@@ -33,6 +33,13 @@ module_param_named(redirect_dir, ovl_redirect_dir_def, bool, 0644);
33
33
MODULE_PARM_DESC (ovl_redirect_dir_def ,
34
34
"Default to on or off for the redirect_dir feature" );
35
35
36
+ static bool ovl_redirect_always_follow =
37
+ IS_ENABLED (CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW );
38
+ module_param_named (redirect_always_follow , ovl_redirect_always_follow ,
39
+ bool , 0644 );
40
+ MODULE_PARM_DESC (ovl_redirect_always_follow ,
41
+ "Follow redirects even if redirect_dir feature is turned off" );
42
+
36
43
static bool ovl_index_def = IS_ENABLED (CONFIG_OVERLAY_FS_INDEX );
37
44
module_param_named (index , ovl_index_def , bool , 0644 );
38
45
MODULE_PARM_DESC (ovl_index_def ,
@@ -232,6 +239,7 @@ static void ovl_free_fs(struct ovl_fs *ofs)
232
239
kfree (ofs -> config .lowerdir );
233
240
kfree (ofs -> config .upperdir );
234
241
kfree (ofs -> config .workdir );
242
+ kfree (ofs -> config .redirect_mode );
235
243
if (ofs -> creator_cred )
236
244
put_cred (ofs -> creator_cred );
237
245
kfree (ofs );
@@ -295,6 +303,11 @@ static bool ovl_force_readonly(struct ovl_fs *ofs)
295
303
return (!ofs -> upper_mnt || !ofs -> workdir );
296
304
}
297
305
306
+ static const char * ovl_redirect_mode_def (void )
307
+ {
308
+ return ovl_redirect_dir_def ? "on" : "off" ;
309
+ }
310
+
298
311
/**
299
312
* ovl_show_options
300
313
*
@@ -313,12 +326,10 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
313
326
}
314
327
if (ofs -> config .default_permissions )
315
328
seq_puts (m , ",default_permissions" );
316
- if (ofs -> config .redirect_dir != ovl_redirect_dir_def )
317
- seq_printf (m , ",redirect_dir=%s" ,
318
- ofs -> config .redirect_dir ? "on" : "off" );
329
+ if (strcmp (ofs -> config .redirect_mode , ovl_redirect_mode_def ()) != 0 )
330
+ seq_printf (m , ",redirect_dir=%s" , ofs -> config .redirect_mode );
319
331
if (ofs -> config .index != ovl_index_def )
320
- seq_printf (m , ",index=%s" ,
321
- ofs -> config .index ? "on" : "off" );
332
+ seq_printf (m , ",index=%s" , ofs -> config .index ? "on" : "off" );
322
333
return 0 ;
323
334
}
324
335
@@ -348,8 +359,7 @@ enum {
348
359
OPT_UPPERDIR ,
349
360
OPT_WORKDIR ,
350
361
OPT_DEFAULT_PERMISSIONS ,
351
- OPT_REDIRECT_DIR_ON ,
352
- OPT_REDIRECT_DIR_OFF ,
362
+ OPT_REDIRECT_DIR ,
353
363
OPT_INDEX_ON ,
354
364
OPT_INDEX_OFF ,
355
365
OPT_ERR ,
@@ -360,8 +370,7 @@ static const match_table_t ovl_tokens = {
360
370
{OPT_UPPERDIR , "upperdir=%s" },
361
371
{OPT_WORKDIR , "workdir=%s" },
362
372
{OPT_DEFAULT_PERMISSIONS , "default_permissions" },
363
- {OPT_REDIRECT_DIR_ON , "redirect_dir=on" },
364
- {OPT_REDIRECT_DIR_OFF , "redirect_dir=off" },
373
+ {OPT_REDIRECT_DIR , "redirect_dir=%s" },
365
374
{OPT_INDEX_ON , "index=on" },
366
375
{OPT_INDEX_OFF , "index=off" },
367
376
{OPT_ERR , NULL }
@@ -390,10 +399,37 @@ static char *ovl_next_opt(char **s)
390
399
return sbegin ;
391
400
}
392
401
402
+ static int ovl_parse_redirect_mode (struct ovl_config * config , const char * mode )
403
+ {
404
+ if (strcmp (mode , "on" ) == 0 ) {
405
+ config -> redirect_dir = true;
406
+ /*
407
+ * Does not make sense to have redirect creation without
408
+ * redirect following.
409
+ */
410
+ config -> redirect_follow = true;
411
+ } else if (strcmp (mode , "follow" ) == 0 ) {
412
+ config -> redirect_follow = true;
413
+ } else if (strcmp (mode , "off" ) == 0 ) {
414
+ if (ovl_redirect_always_follow )
415
+ config -> redirect_follow = true;
416
+ } else if (strcmp (mode , "nofollow" ) != 0 ) {
417
+ pr_err ("overlayfs: bad mount option \"redirect_dir=%s\"\n" ,
418
+ mode );
419
+ return - EINVAL ;
420
+ }
421
+
422
+ return 0 ;
423
+ }
424
+
393
425
static int ovl_parse_opt (char * opt , struct ovl_config * config )
394
426
{
395
427
char * p ;
396
428
429
+ config -> redirect_mode = kstrdup (ovl_redirect_mode_def (), GFP_KERNEL );
430
+ if (!config -> redirect_mode )
431
+ return - ENOMEM ;
432
+
397
433
while ((p = ovl_next_opt (& opt )) != NULL ) {
398
434
int token ;
399
435
substring_t args [MAX_OPT_ARGS ];
@@ -428,12 +464,11 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
428
464
config -> default_permissions = true;
429
465
break ;
430
466
431
- case OPT_REDIRECT_DIR_ON :
432
- config -> redirect_dir = true;
433
- break ;
434
-
435
- case OPT_REDIRECT_DIR_OFF :
436
- config -> redirect_dir = false;
467
+ case OPT_REDIRECT_DIR :
468
+ kfree (config -> redirect_mode );
469
+ config -> redirect_mode = match_strdup (& args [0 ]);
470
+ if (!config -> redirect_mode )
471
+ return - ENOMEM ;
437
472
break ;
438
473
439
474
case OPT_INDEX_ON :
@@ -458,7 +493,7 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
458
493
config -> workdir = NULL ;
459
494
}
460
495
461
- return 0 ;
496
+ return ovl_parse_redirect_mode ( config , config -> redirect_mode ) ;
462
497
}
463
498
464
499
#define OVL_WORKDIR_NAME "work"
@@ -1160,7 +1195,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
1160
1195
if (!cred )
1161
1196
goto out_err ;
1162
1197
1163
- ofs -> config .redirect_dir = ovl_redirect_dir_def ;
1164
1198
ofs -> config .index = ovl_index_def ;
1165
1199
err = ovl_parse_opt ((char * ) data , & ofs -> config );
1166
1200
if (err )
0 commit comments