Re: [PATCH v3] selinux: lsm: fix a missing-check bug in selinux_sb_eat_lsm_opts()

From: Paul Moore
Date: Mon Jun 03 2019 - 18:03:38 EST


On Mon, Jun 3, 2019 at 3:27 AM Ondrej Mosnacek <omosnace@xxxxxxxxxx> wrote:
> On Sat, Jun 1, 2019 at 4:15 AM Gen Zhang <blackgod016574@xxxxxxxxx> wrote:
> > In selinux_sb_eat_lsm_opts(), 'arg' is allocated by kmemdup_nul(). It
> > returns NULL when fails. So 'arg' should be checked. And 'mnt_opts'
> > should be freed when error.
> >
> > Signed-off-by: Gen Zhang <blackgod016574@xxxxxxxxx>
> > Reviewed-by: Ondrej Mosnacek <omosnace@xxxxxxxxxx>
> > Fixes: 99dbbb593fe6 ("selinux: rewrite selinux_sb_eat_lsm_opts()")
> > ---
> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > index 3ec702c..f329fc0 100644
> > --- a/security/selinux/hooks.c
> > +++ b/security/selinux/hooks.c
> > @@ -2616,6 +2616,7 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
> > char *from = options;
> > char *to = options;
> > bool first = true;
> > + int ret;
>
> I'd suggest just moving the declaration of 'rc' here and simply reuse
> that variable. Otherwise the patch looks good to me.

Agreed. Creating "ret" only makes the patch larger and doesn't add any value.

I try to avoid making broad statements, but if you are unsure about
which approach to take when fixing a problem, start with the smallest
patch you can write. Even if it turns out not to be the "best"
solution upstream, it will be easier to review, discuss, and
potentially port to other/older kernels.

> >
> > while (1) {
> > int len = opt_len(from);
> > @@ -2635,15 +2636,16 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
> > *q++ = c;
> > }
> > arg = kmemdup_nul(arg, q - arg, GFP_KERNEL);
> > + if (!arg) {
> > + ret = -ENOMEM;
> > + goto free_opt;
> > + }
> > }
> > rc = selinux_add_opt(token, arg, mnt_opts);
> > if (unlikely(rc)) {
> > + ret = rc;
> > kfree(arg);
> > - if (*mnt_opts) {
> > - selinux_free_mnt_opts(*mnt_opts);
> > - *mnt_opts = NULL;
> > - }
> > - return rc;
> > + goto free_opt;
> > }
> > } else {
> > if (!first) { // copy with preceding comma
> > @@ -2661,6 +2663,12 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
> > }
> > *to = '\0';
> > return 0;
> > +free_opt:
> > + if (*mnt_opts) {
> > + selinux_free_mnt_opts(*mnt_opts);
> > + *mnt_opts = NULL;
> > + }
> > + return ret;
> > }
> >
> > static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
>
> --
> Ondrej Mosnacek <omosnace at redhat dot com>
> Software Engineer, Security Technologies
> Red Hat, Inc.

--
paul moore
www.paul-moore.com