ovl: fix memory leak in ovl_parse_param()
commit37f32f5264
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:c835110b58
("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>
This commit is contained in:
parent
3caf7f49f1
commit
be9857a4d2
|
@ -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 *ctx = fc->fs_private;
|
||||||
struct ovl_fs_context_layer *l;
|
struct ovl_fs_context_layer *l;
|
||||||
char *dup = NULL, *iter;
|
char *dup = NULL, *iter;
|
||||||
ssize_t nr_lower = 0, nr = 0, nr_data = 0;
|
ssize_t nr_lower, nr;
|
||||||
bool data_layer = false;
|
bool data_layer = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -490,6 +490,7 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
|
||||||
iter = dup;
|
iter = dup;
|
||||||
l = ctx->lower;
|
l = ctx->lower;
|
||||||
for (nr = 0; nr < nr_lower; nr++, l++) {
|
for (nr = 0; nr < nr_lower; nr++, l++) {
|
||||||
|
ctx->nr++;
|
||||||
memset(l, 0, sizeof(*l));
|
memset(l, 0, sizeof(*l));
|
||||||
|
|
||||||
err = ovl_mount_dir(iter, &l->path);
|
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;
|
goto out_put;
|
||||||
|
|
||||||
if (data_layer)
|
if (data_layer)
|
||||||
nr_data++;
|
ctx->nr_data++;
|
||||||
|
|
||||||
/* Calling strchr() again would overrun. */
|
/* Calling strchr() again would overrun. */
|
||||||
if ((nr + 1) == nr_lower)
|
if (ctx->nr == nr_lower)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
err = -EINVAL;
|
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
|
* This is a regular layer so we require that
|
||||||
* there are no data layers.
|
* 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");
|
pr_err("regular lower layers cannot follow data lower layers");
|
||||||
goto out_put;
|
goto out_put;
|
||||||
}
|
}
|
||||||
|
@ -532,8 +533,6 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
|
||||||
data_layer = true;
|
data_layer = true;
|
||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
ctx->nr = nr_lower;
|
|
||||||
ctx->nr_data += nr_data;
|
|
||||||
kfree(dup);
|
kfree(dup);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue