From: Stephan Mueller <smueller-T9tCv8IpfcWELgA04lAiVw@public.gmane.org>
To: Daniel Borkmann <dborkman-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Cc: Herbert Xu
<herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org>,
ABI/API <linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
linux-crypto-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
LKML <linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Subject: Re: [PATCH 7/8] crypto: AF_ALG: add random number generator support
Date: Wed, 12 Nov 2014 17:54:23 +0100 [thread overview]
Message-ID: <9137675.ZTbqvCU5Bi@tachyon.chronox.de> (raw)
In-Reply-To: <546387B8.9050601-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Am Mittwoch, 12. November 2014, 17:15:52 schrieb Daniel Borkmann:
Hi Daniel,
thanks for the comments.
> On 11/12/2014 08:05 AM, Stephan Mueller wrote:
> > This patch adds the random number generator support for AF_ALG.
> >
> > A random number generator's purpose is to generate data without
> > requiring the caller to provide any data. Therefore, the AF_ALG
> > interface handler for RNGs only implements a callback handler for
> > recvmsg.
>
> ...
>
> > +static int rng_recvmsg(struct kiocb *unused, struct socket *sock,
> > + struct msghdr *msg, size_t len, int flags)
> > +{
> > + struct sock *sk = sock->sk;
> > + struct alg_sock *ask = alg_sk(sk);
> > + struct rng_ctx *ctx = ask->private;
> > + int err = -EFAULT;
> > +
> > + if (0 == len)
>
> if (len == 0)
> ...
>
> [And also other places.]
>
> We don't use Yoda condition style in the kernel.
Well, there is a very good reason for using the approach I have: we all have
done the error of forgetting the second = sign.
In my case, the compiler will complain and we fix the error right away.
In your case, nobody is complaining but we introduced a nasty, potentially
hard to debug error. Thus, I very much like to keep my version just to be on
the safe side.
Note, there was even a backdoor I have seen where the missing 2nd equal sign
introduced a privilege escalation.
Therefore, my standard coding practice is to have a fixed value on the left
side and the variable on the right side of any comparison.
>
> > + return 0;
> > + if (MAXSIZE < len)
> > + len = MAXSIZE;
> > +
> > + lock_sock(sk);
> > + len = crypto_rng_get_bytes(ctx->drng, ctx->result, len);
> > + if (0 > len)
> > + goto unlock;
> > +
> > + err = memcpy_toiovec(msg->msg_iov, ctx->result, len);
> > + memset(ctx->result, 0, err);
> > +
>
> This looks buggy.
>
> If copy_to_user() fails from within memcpy_toiovec(), we call memset()
> with a negative return value which is interpreted as size_t and thus
> causes a buffer overflow writing beyond ctx->result, no?
>
> If it succeeds, we call memset(ctx->result, 0, 0) .....
Right, good catch, I have to add a catch for negative error here.
>
> > +unlock:
> > + release_sock(sk);
> > +
> > + return err ? err : len;
> > +}
> > +
> > +static struct proto_ops algif_rng_ops = {
> > + .family = PF_ALG,
> > +
> > + .connect = sock_no_connect,
> > + .socketpair = sock_no_socketpair,
> > + .getname = sock_no_getname,
> > + .ioctl = sock_no_ioctl,
> > + .listen = sock_no_listen,
> > + .shutdown = sock_no_shutdown,
> > + .getsockopt = sock_no_getsockopt,
> > + .mmap = sock_no_mmap,
> > + .bind = sock_no_bind,
> > + .accept = sock_no_accept,
> > + .setsockopt = sock_no_setsockopt,
> > + .poll = sock_no_poll,
> > + .sendmsg = sock_no_sendmsg,
> > + .sendpage = sock_no_sendpage,
> > +
> > + .release = af_alg_release,
> > + .recvmsg = rng_recvmsg,
> > +};
> > +
> > +static void *rng_bind(const char *name, u32 type, u32 mask)
> > +{
> > + return crypto_alloc_rng(name, type, mask);
> > +}
> > +
> > +static void rng_release(void *private)
> > +{
> > + crypto_free_rng(private);
> > +}
> > +
> > +static void rng_sock_destruct(struct sock *sk)
> > +{
> > + struct alg_sock *ask = alg_sk(sk);
> > + struct rng_ctx *ctx = ask->private;
> > +
> > + memset(ctx->result, 0, MAXSIZE);
>
> memset(ctx->result, 0, sizeof(ctx->result));
Ok, if this is desired, fine with me.
>
> > + sock_kfree_s(sk, ctx, ctx->len);
> > + af_alg_release_parent(sk);
> > +}
> > +
> > +static int rng_accept_parent(void *private, struct sock *sk)
> > +{
> > + struct rng_ctx *ctx;
> > + struct alg_sock *ask = alg_sk(sk);
> > + unsigned int len = sizeof(*ctx);
> > + int seedsize = crypto_rng_seedsize(private);
> > + int ret = -ENOMEM;
> > +
> > + ctx = sock_kmalloc(sk, len, GFP_KERNEL);
> > + if (!ctx)
> > + return -ENOMEM;
> > + memset(ctx->result, 0, MAXSIZE);
>
> Ditto...
Will do.
>
> > + ctx->len = len;
> > +
> > + if (seedsize) {
> > + u8 *buf = kmalloc(seedsize, GFP_KERNEL);
> > + if (!buf)
> > + goto err;
> > + get_random_bytes(buf, seedsize);
> > + ret = crypto_rng_reset(private, buf, len);
> > + kzfree(buf);
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
Ciao
Stephan
WARNING: multiple messages have this Message-ID (diff)
From: Stephan Mueller <smueller@chronox.de>
To: Daniel Borkmann <dborkman@redhat.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>,
ABI/API <linux-api@vger.kernel.org>,
linux-crypto@vger.kernel.org, LKML <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH 7/8] crypto: AF_ALG: add random number generator support
Date: Wed, 12 Nov 2014 17:54:23 +0100 [thread overview]
Message-ID: <9137675.ZTbqvCU5Bi@tachyon.chronox.de> (raw)
In-Reply-To: <546387B8.9050601@redhat.com>
Am Mittwoch, 12. November 2014, 17:15:52 schrieb Daniel Borkmann:
Hi Daniel,
thanks for the comments.
> On 11/12/2014 08:05 AM, Stephan Mueller wrote:
> > This patch adds the random number generator support for AF_ALG.
> >
> > A random number generator's purpose is to generate data without
> > requiring the caller to provide any data. Therefore, the AF_ALG
> > interface handler for RNGs only implements a callback handler for
> > recvmsg.
>
> ...
>
> > +static int rng_recvmsg(struct kiocb *unused, struct socket *sock,
> > + struct msghdr *msg, size_t len, int flags)
> > +{
> > + struct sock *sk = sock->sk;
> > + struct alg_sock *ask = alg_sk(sk);
> > + struct rng_ctx *ctx = ask->private;
> > + int err = -EFAULT;
> > +
> > + if (0 == len)
>
> if (len == 0)
> ...
>
> [And also other places.]
>
> We don't use Yoda condition style in the kernel.
Well, there is a very good reason for using the approach I have: we all have
done the error of forgetting the second = sign.
In my case, the compiler will complain and we fix the error right away.
In your case, nobody is complaining but we introduced a nasty, potentially
hard to debug error. Thus, I very much like to keep my version just to be on
the safe side.
Note, there was even a backdoor I have seen where the missing 2nd equal sign
introduced a privilege escalation.
Therefore, my standard coding practice is to have a fixed value on the left
side and the variable on the right side of any comparison.
>
> > + return 0;
> > + if (MAXSIZE < len)
> > + len = MAXSIZE;
> > +
> > + lock_sock(sk);
> > + len = crypto_rng_get_bytes(ctx->drng, ctx->result, len);
> > + if (0 > len)
> > + goto unlock;
> > +
> > + err = memcpy_toiovec(msg->msg_iov, ctx->result, len);
> > + memset(ctx->result, 0, err);
> > +
>
> This looks buggy.
>
> If copy_to_user() fails from within memcpy_toiovec(), we call memset()
> with a negative return value which is interpreted as size_t and thus
> causes a buffer overflow writing beyond ctx->result, no?
>
> If it succeeds, we call memset(ctx->result, 0, 0) .....
Right, good catch, I have to add a catch for negative error here.
>
> > +unlock:
> > + release_sock(sk);
> > +
> > + return err ? err : len;
> > +}
> > +
> > +static struct proto_ops algif_rng_ops = {
> > + .family = PF_ALG,
> > +
> > + .connect = sock_no_connect,
> > + .socketpair = sock_no_socketpair,
> > + .getname = sock_no_getname,
> > + .ioctl = sock_no_ioctl,
> > + .listen = sock_no_listen,
> > + .shutdown = sock_no_shutdown,
> > + .getsockopt = sock_no_getsockopt,
> > + .mmap = sock_no_mmap,
> > + .bind = sock_no_bind,
> > + .accept = sock_no_accept,
> > + .setsockopt = sock_no_setsockopt,
> > + .poll = sock_no_poll,
> > + .sendmsg = sock_no_sendmsg,
> > + .sendpage = sock_no_sendpage,
> > +
> > + .release = af_alg_release,
> > + .recvmsg = rng_recvmsg,
> > +};
> > +
> > +static void *rng_bind(const char *name, u32 type, u32 mask)
> > +{
> > + return crypto_alloc_rng(name, type, mask);
> > +}
> > +
> > +static void rng_release(void *private)
> > +{
> > + crypto_free_rng(private);
> > +}
> > +
> > +static void rng_sock_destruct(struct sock *sk)
> > +{
> > + struct alg_sock *ask = alg_sk(sk);
> > + struct rng_ctx *ctx = ask->private;
> > +
> > + memset(ctx->result, 0, MAXSIZE);
>
> memset(ctx->result, 0, sizeof(ctx->result));
Ok, if this is desired, fine with me.
>
> > + sock_kfree_s(sk, ctx, ctx->len);
> > + af_alg_release_parent(sk);
> > +}
> > +
> > +static int rng_accept_parent(void *private, struct sock *sk)
> > +{
> > + struct rng_ctx *ctx;
> > + struct alg_sock *ask = alg_sk(sk);
> > + unsigned int len = sizeof(*ctx);
> > + int seedsize = crypto_rng_seedsize(private);
> > + int ret = -ENOMEM;
> > +
> > + ctx = sock_kmalloc(sk, len, GFP_KERNEL);
> > + if (!ctx)
> > + return -ENOMEM;
> > + memset(ctx->result, 0, MAXSIZE);
>
> Ditto...
Will do.
>
> > + ctx->len = len;
> > +
> > + if (seedsize) {
> > + u8 *buf = kmalloc(seedsize, GFP_KERNEL);
> > + if (!buf)
> > + goto err;
> > + get_random_bytes(buf, seedsize);
> > + ret = crypto_rng_reset(private, buf, len);
> > + kzfree(buf);
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
Ciao
Stephan
next prev parent reply other threads:[~2014-11-12 16:54 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-12 6:59 [PATCH 0/8] crypto: AF_ALG: add AEAD and RNG support Stephan Mueller
2014-11-12 7:00 ` [PATCH 1/8] crypto: AF_ALG: add user space interface for AEAD Stephan Mueller
2014-11-12 7:01 ` [PATCH 2/8] crypto: AF_ALG: user space interface for cipher info Stephan Mueller
2014-11-12 7:01 ` [PATCH 3/8] crypto: AF_ALG: extend data structuers for AEAD Stephan Mueller
2014-11-12 7:03 ` [PATCH 4/8] crypto: AF_ALG: crypto API calls to inline functions Stephan Mueller
2014-11-12 7:04 ` [PATCH 5/8] crypto: AF_ALG: add AEAD support Stephan Mueller
2014-11-12 7:05 ` [PATCH 6/8] crypto: AF_ALG: make setkey optional Stephan Mueller
2014-11-12 7:05 ` [PATCH 7/8] crypto: AF_ALG: add random number generator support Stephan Mueller
2014-11-12 16:15 ` Daniel Borkmann
[not found] ` <546387B8.9050601-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2014-11-12 16:54 ` Stephan Mueller [this message]
2014-11-12 16:54 ` Stephan Mueller
2014-11-12 17:23 ` Daniel Borkmann
2014-11-12 17:46 ` Stephan Mueller
2014-11-12 17:51 ` Daniel Borkmann
2014-11-12 17:51 ` Daniel Borkmann
2014-11-12 7:06 ` [PATCH 8/8] crypto: AF_ALG: enable RNG interface compilation Stephan Mueller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9137675.ZTbqvCU5Bi@tachyon.chronox.de \
--to=smueller-t9tcv8ipfcwelga04laivw@public.gmane.org \
--cc=dborkman-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
--cc=herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org \
--cc=linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-crypto-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.