Thank you for the review, Eric, I'll address your comments in v2. On Mon, 13 Jul 2020 at 18:10, Eric Biggers <ebiggers@xxxxxxxxxx> wrote: > > Just some bike-shedding: > > On Mon, Jul 13, 2020 at 05:48:57PM +0100, Elena Petrova wrote: > > Extending the userspace RNG interface: > > 1. adding ALG_SET_DRBG_ENTROPY setsockopt option for entropy input; > > 2. using sendmsg syscall for specifying the additional data. > > > > Signed-off-by: Elena Petrova <lenaptr@xxxxxxxxxx> > > A cover letter shouldn't really be used for a single patch. > Just put the details here in the commit message. Ack > > diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c > > index 087c0ad09d38..c3d1667db367 100644 > > --- a/crypto/algif_rng.c > > +++ b/crypto/algif_rng.c > > @@ -53,8 +53,24 @@ struct rng_ctx { > > #define MAXSIZE 128 > > unsigned int len; > > struct crypto_rng *drng; > > + u8 *addtl; > > + size_t addtl_len; > > }; > > > > +struct rng_parent_ctx { > > + struct crypto_rng *drng; > > + u8 *entropy; > > +}; > > + > > +static void reset_addtl(struct rng_ctx *ctx) > > +{ > > + if (ctx->addtl) { > > + kzfree(ctx->addtl); > > + ctx->addtl = NULL; > > + } > > + ctx->addtl_len = 0; > > +} > > It's recommended to prefix function names. So, reset_addtl => rng_reset_addtl. Ack > > +static int rng_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) > > +{ > > + int err; > > + struct alg_sock *ask = alg_sk(sock->sk); > > + struct rng_ctx *ctx = ask->private; > > + > > + reset_addtl(ctx); > > + ctx->addtl = kzalloc(len, GFP_KERNEL); > > + if (!ctx->addtl) > > + return -ENOMEM; > > Shouldn't the length be limited here? > > Also, kmalloc would be sufficient since the memcpy_from_msg() immediately below > initializes the memory. Good point, I'll use the same limit as for the recv(). Ack kzalloc/kmalloc. > > + > > + err = memcpy_from_msg(ctx->addtl, msg, len); > > + if (err) { > > + reset_addtl(ctx); > > + return err; > > + } > > + ctx->addtl_len = len; > > + > > + return 0; > > +} > > > static void *rng_bind(const char *name, u32 type, u32 mask) > > { > > - return crypto_alloc_rng(name, type, mask); > > + struct rng_parent_ctx *pctx; > > + void *err_ptr; > > + > > + pctx = kzalloc(sizeof(*pctx), GFP_KERNEL); > > + if (!pctx) > > + return ERR_PTR(-ENOMEM); > > + > > + pctx->drng = crypto_alloc_rng(name, type, mask); > > + if (!IS_ERR(pctx->drng)) > > + return pctx; > > + > > + err_ptr = pctx->drng; > > + kfree(pctx); > > + return err_ptr; > > } > > The error handling here is weird. It would be more conventional to do something > like: > > static void *rng_bind(const char *name, u32 type, u32 mask) > { > struct rng_parent_ctx *pctx; > struct crypto_rng *rng; > > pctx = kzalloc(sizeof(*pctx), GFP_KERNEL); > if (!pctx) > return ERR_PTR(-ENOMEM); > > rng = crypto_alloc_rng(name, type, mask); > if (IS_ERR(rng)) { > kfree(pctx); > return ERR_CAST(rng); > } > > pctx->drng = rng; > return pctx; > } Thanks, I will use your variant. > > static void rng_release(void *private) > > { > > - crypto_free_rng(private); > > + struct rng_parent_ctx *pctx = private; > > + if (unlikely(!pctx)) > > + return; > > There should be a blank line between declarations and statements. Ack > > + crypto_free_rng(pctx->drng); > > + if (pctx->entropy) > > + kzfree(pctx->entropy); > > No need to check for NULL before calling kzfree(). Ack > > +static int rng_setentropy(void *private, const u8 *entropy, unsigned int len) > > +{ > > + struct rng_parent_ctx *pctx = private; > > + u8 *kentropy = NULL; > > + > > + if (pctx->entropy) > > + return -EINVAL; > > + > > + if (entropy && len) { > > Best to check just 'len', so that users get an error as expected if they > accidentally pass entry=NULL len=nonzero. Ack > > + kentropy = kzalloc(len, GFP_KERNEL); > > + if (!kentropy) > > + return -ENOMEM; > > + if (copy_from_user(kentropy, entropy, len)) { > > + kzfree(kentropy); > > + return -EFAULT; > > + } > > This can use memdup_user(). Also, should there be a length limit? Alright, changed to memdup_user() and added the same limit as in send and recv. > > + } > > + > > + crypto_rng_alg(pctx->drng)->set_ent(pctx->drng, kentropy, len); > > + pctx->entropy = kentropy; > > pctx->entropy could just be a bool 'has_entropy', right? The actual value > doesn't need to be saved. I need to keep the pointer to free it after use. DRBG saves the pointer in one of its internal structures, but doesn't do any memory management. So I had to either change drbg code to deal with the memory, or save the pointer somewhere inside the socket. I opted for the latter. > > +static int rng_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) > > +{ > > + int err; > > + struct alg_sock *ask = alg_sk(sock->sk); > > + struct rng_ctx *ctx = ask->private; > > + > > + reset_addtl(ctx); > > + ctx->addtl = kzalloc(len, GFP_KERNEL); > > + if (!ctx->addtl) > > + return -ENOMEM; > > + > > + err = memcpy_from_msg(ctx->addtl, msg, len); > > + if (err) { > > + reset_addtl(ctx); > > + return err; > > + } > > + ctx->addtl_len = len; > > + > > + return 0; > > +} > > This is also missing any sort of locking, both between concurrent calls to > rng_sendmsg(), and between rng_sendmsg() and rng_recvmsg(). > > lock_sock() would solve the former. I'm not sure what should be done about > rng_recvmsg(). It apparently relies on the crypto_rng doing its own locking, > but maybe it should just use lock_sock() too. Thanks, I've added lock_sock() to both. > - Eric