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; 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)