]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ovl: fix memory leak in ovl_parse_param()
authorAmir Goldstein <amir73il@gmail.com>
Sun, 12 Nov 2023 08:11:25 +0000 (10:11 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 2 May 2024 14:32:49 +0000 (16:32 +0200)
commit 37f32f52643869131ec01bb69bdf9f404f6109fb upstream.

On failure to parse parameters in ovl_parse_param_lowerdir(), it is
necessary to update ctx->nr with the correct nr before using
ovl_reset_lowerdirs() to release l->name.

Reported-and-tested-by: syzbot+26eedf3631650972f17c@syzkaller.appspotmail.com
Fixes: c835110b588a ("ovl: remove unused code in lowerdir param parsing")
Co-authored-by: Edward Adam Davis <eadavis@qq.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/overlayfs/params.c

index ad3593a41fb5f6d41688a3c261b0ce523e09cd70..488f920f79d283283d764cdbae61308bad5f54d7 100644 (file)
@@ -438,7 +438,7 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
        struct ovl_fs_context *ctx = fc->fs_private;
        struct ovl_fs_context_layer *l;
        char *dup = NULL, *iter;
-       ssize_t nr_lower = 0, nr = 0, nr_data = 0;
+       ssize_t nr_lower, nr;
        bool data_layer = false;
 
        /*
@@ -490,6 +490,7 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
        iter = dup;
        l = ctx->lower;
        for (nr = 0; nr < nr_lower; nr++, l++) {
+               ctx->nr++;
                memset(l, 0, sizeof(*l));
 
                err = ovl_mount_dir(iter, &l->path);
@@ -506,10 +507,10 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
                        goto out_put;
 
                if (data_layer)
-                       nr_data++;
+                       ctx->nr_data++;
 
                /* Calling strchr() again would overrun. */
-               if ((nr + 1) == nr_lower)
+               if (ctx->nr == nr_lower)
                        break;
 
                err = -EINVAL;
@@ -519,7 +520,7 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
                         * This is a regular layer so we require that
                         * there are no data layers.
                         */
-                       if ((ctx->nr_data + nr_data) > 0) {
+                       if (ctx->nr_data > 0) {
                                pr_err("regular lower layers cannot follow data lower layers");
                                goto out_put;
                        }
@@ -532,8 +533,6 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
                data_layer = true;
                iter++;
        }
-       ctx->nr = nr_lower;
-       ctx->nr_data += nr_data;
        kfree(dup);
        return 0;