Skip to content

Commit ca76ac3

Browse files
Zhihao Chengbrauner
authored andcommitted
ovl: fix wrong lowerdir number check for parameter Opt_lowerdir
The max count of lowerdir is OVL_MAX_STACK[500], which is broken by commit 37f32f5("ovl: fix memory leak in ovl_parse_param()") for parameter Opt_lowerdir. Since commit 819829f("ovl: refactor layer parsing helpers") and commit 24e16e3("ovl: add support for appending lowerdirs one by one") added check ovl_mount_dir_check() in function ovl_parse_param_lowerdir(), the 'ctx->nr' should be smaller than OVL_MAX_STACK, after commit 37f32f5("ovl: fix memory leak in ovl_parse_param()") is applied, the 'ctx->nr' is updated before the check ovl_mount_dir_check(), which leads the max count of lowerdir to become 499 for parameter Opt_lowerdir. Fix it by replacing lower layers parsing code with the existing helper function ovl_parse_layer(). Fixes: 37f32f5 ("ovl: fix memory leak in ovl_parse_param()") Signed-off-by: Zhihao Cheng <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Amir Goldstein <[email protected]> Signed-off-by: Christian Brauner <[email protected]>
1 parent 7eff345 commit ca76ac3

File tree

1 file changed

+7
-33
lines changed

1 file changed

+7
-33
lines changed

fs/overlayfs/params.c

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,8 @@ static void ovl_add_layer(struct fs_context *fc, enum ovl_opt layer,
353353
case Opt_datadir_add:
354354
ctx->nr_data++;
355355
fallthrough;
356+
case Opt_lowerdir:
357+
fallthrough;
356358
case Opt_lowerdir_add:
357359
WARN_ON(ctx->nr >= ctx->capacity);
358360
l = &ctx->lower[ctx->nr++];
@@ -375,7 +377,7 @@ static int ovl_parse_layer(struct fs_context *fc, const char *layer_name, enum o
375377
if (!name)
376378
return -ENOMEM;
377379

378-
if (upper)
380+
if (upper || layer == Opt_lowerdir)
379381
err = ovl_mount_dir(name, &path);
380382
else
381383
err = ovl_mount_dir_noesc(name, &path);
@@ -431,7 +433,6 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
431433
{
432434
int err;
433435
struct ovl_fs_context *ctx = fc->fs_private;
434-
struct ovl_fs_context_layer *l;
435436
char *dup = NULL, *iter;
436437
ssize_t nr_lower, nr;
437438
bool data_layer = false;
@@ -471,35 +472,11 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
471472
goto out_err;
472473
}
473474

474-
if (nr_lower > ctx->capacity) {
475-
err = -ENOMEM;
476-
l = krealloc_array(ctx->lower, nr_lower, sizeof(*ctx->lower),
477-
GFP_KERNEL_ACCOUNT);
478-
if (!l)
479-
goto out_err;
480-
481-
ctx->lower = l;
482-
ctx->capacity = nr_lower;
483-
}
484-
485475
iter = dup;
486-
l = ctx->lower;
487-
for (nr = 0; nr < nr_lower; nr++, l++) {
488-
ctx->nr++;
489-
memset(l, 0, sizeof(*l));
490-
491-
err = ovl_mount_dir(iter, &l->path);
476+
for (nr = 0; nr < nr_lower; nr++) {
477+
err = ovl_parse_layer(fc, iter, Opt_lowerdir);
492478
if (err)
493-
goto out_put;
494-
495-
err = ovl_mount_dir_check(fc, &l->path, Opt_lowerdir, iter, false);
496-
if (err)
497-
goto out_put;
498-
499-
err = -ENOMEM;
500-
l->name = kstrdup(iter, GFP_KERNEL_ACCOUNT);
501-
if (!l->name)
502-
goto out_put;
479+
goto out_err;
503480

504481
if (data_layer)
505482
ctx->nr_data++;
@@ -517,7 +494,7 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
517494
*/
518495
if (ctx->nr_data > 0) {
519496
pr_err("regular lower layers cannot follow data lower layers");
520-
goto out_put;
497+
goto out_err;
521498
}
522499

523500
data_layer = false;
@@ -531,9 +508,6 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
531508
kfree(dup);
532509
return 0;
533510

534-
out_put:
535-
ovl_reset_lowerdirs(ctx);
536-
537511
out_err:
538512
kfree(dup);
539513

0 commit comments

Comments
 (0)