Commit 1db49495 authored by Amir Goldstein's avatar Amir Goldstein Committed by Ma Wupeng
Browse files

ovl: fix memory leak in ovl_parse_param()

stable inclusion
from stable-v6.6.30
commit be9857a4d280bc5d6f9fdfc134918a7f13dda9ae
bugzilla: https://gitee.com/openeuler/kernel/issues/I9MPZ8

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=be9857a4d280bc5d6f9fdfc134918a7f13dda9ae



--------------------------------

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: default avatar <syzbot+26eedf3631650972f17c@syzkaller.appspotmail.com>
Fixes: c835110b588a ("ovl: remove unused code in lowerdir param parsing")
Co-authored-by: default avatarEdward Adam Davis <eadavis@qq.com>
Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarJingbo Xu <jefflexu@linux.alibaba.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarZhangPeng <zhangpeng362@huawei.com>
parent 47ea0c81
Loading
Loading
Loading
Loading
+5 −6
Original line number Diff line number Diff line
@@ -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;