Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs

Pull overlayfs fixes from Miklos Szeredi:

- fix incomplete syncing of filesystem

- fix regression in readdir on ovl over 9p

- only follow redirects when needed

- misc fixes and cleanups

* 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
ovl: fix overlay: warning prefix
ovl: Use PTR_ERR_OR_ZERO()
ovl: Sync upper dirty data when syncing overlayfs
ovl: update ctx->pos on impure dir iteration
ovl: Pass ovl_get_nlink() parameters in right order
ovl: don't follow redirects if redirect_dir=off

+137 -26
+34
Documentation/filesystems/overlayfs.txt
··· 156 156 root of the overlay. Finally the directory is moved to the new 157 157 location. 158 158 159 + There are several ways to tune the "redirect_dir" feature. 160 + 161 + Kernel config options: 162 + 163 + - OVERLAY_FS_REDIRECT_DIR: 164 + If this is enabled, then redirect_dir is turned on by default. 165 + - OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW: 166 + If this is enabled, then redirects are always followed by default. Enabling 167 + this results in a less secure configuration. Enable this option only when 168 + worried about backward compatibility with kernels that have the redirect_dir 169 + feature and follow redirects even if turned off. 170 + 171 + Module options (can also be changed through /sys/module/overlay/parameters/*): 172 + 173 + - "redirect_dir=BOOL": 174 + See OVERLAY_FS_REDIRECT_DIR kernel config option above. 175 + - "redirect_always_follow=BOOL": 176 + See OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW kernel config option above. 177 + - "redirect_max=NUM": 178 + The maximum number of bytes in an absolute redirect (default is 256). 179 + 180 + Mount options: 181 + 182 + - "redirect_dir=on": 183 + Redirects are enabled. 184 + - "redirect_dir=follow": 185 + Redirects are not created, but followed. 186 + - "redirect_dir=off": 187 + Redirects are not created and only followed if "redirect_always_follow" 188 + feature is enabled in the kernel/module config. 189 + - "redirect_dir=nofollow": 190 + Redirects are not created and not followed (equivalent to "redirect_dir=off" 191 + if "redirect_always_follow" feature is not enabled). 192 + 159 193 Non-directories 160 194 --------------- 161 195
+10
fs/overlayfs/Kconfig
··· 24 24 an overlay which has redirects on a kernel that doesn't support this 25 25 feature will have unexpected results. 26 26 27 + config OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW 28 + bool "Overlayfs: follow redirects even if redirects are turned off" 29 + default y 30 + depends on OVERLAY_FS 31 + help 32 + Disable this to get a possibly more secure configuration, but that 33 + might not be backward compatible with previous kernels. 34 + 35 + For more information, see Documentation/filesystems/overlayfs.txt 36 + 27 37 config OVERLAY_FS_INDEX 28 38 bool "Overlayfs: turn on inodes index feature by default" 29 39 depends on OVERLAY_FS
+2 -1
fs/overlayfs/dir.c
··· 887 887 spin_unlock(&dentry->d_lock); 888 888 } else { 889 889 kfree(redirect); 890 - pr_warn_ratelimited("overlay: failed to set redirect (%i)\n", err); 890 + pr_warn_ratelimited("overlayfs: failed to set redirect (%i)\n", 891 + err); 891 892 /* Fall back to userspace copy-up */ 892 893 err = -EXDEV; 893 894 }
+17 -1
fs/overlayfs/namei.c
··· 435 435 436 436 /* Check if index is orphan and don't warn before cleaning it */ 437 437 if (d_inode(index)->i_nlink == 1 && 438 - ovl_get_nlink(index, origin.dentry, 0) == 0) 438 + ovl_get_nlink(origin.dentry, index, 0) == 0) 439 439 err = -ENOENT; 440 440 441 441 dput(origin.dentry); ··· 680 680 681 681 if (d.stop) 682 682 break; 683 + 684 + /* 685 + * Following redirects can have security consequences: it's like 686 + * a symlink into the lower layer without the permission checks. 687 + * This is only a problem if the upper layer is untrusted (e.g 688 + * comes from an USB drive). This can allow a non-readable file 689 + * or directory to become readable. 690 + * 691 + * Only following redirects when redirects are enabled disables 692 + * this attack vector when not necessary. 693 + */ 694 + err = -EPERM; 695 + if (d.redirect && !ofs->config.redirect_follow) { 696 + pr_warn_ratelimited("overlay: refusing to follow redirect for (%pd2)\n", dentry); 697 + goto out_put; 698 + } 683 699 684 700 if (d.redirect && d.redirect[0] == '/' && poe != roe) { 685 701 poe = roe;
+1 -1
fs/overlayfs/overlayfs.h
··· 180 180 static inline struct dentry *ovl_do_tmpfile(struct dentry *dentry, umode_t mode) 181 181 { 182 182 struct dentry *ret = vfs_tmpfile(dentry, mode, 0); 183 - int err = IS_ERR(ret) ? PTR_ERR(ret) : 0; 183 + int err = PTR_ERR_OR_ZERO(ret); 184 184 185 185 pr_debug("tmpfile(%pd2, 0%o) = %i\n", dentry, mode, err); 186 186 return ret;
+2
fs/overlayfs/ovl_entry.h
··· 14 14 char *workdir; 15 15 bool default_permissions; 16 16 bool redirect_dir; 17 + bool redirect_follow; 18 + const char *redirect_mode; 17 19 bool index; 18 20 }; 19 21
+5 -2
fs/overlayfs/readdir.c
··· 499 499 return err; 500 500 501 501 fail: 502 - pr_warn_ratelimited("overlay: failed to look up (%s) for ino (%i)\n", 502 + pr_warn_ratelimited("overlayfs: failed to look up (%s) for ino (%i)\n", 503 503 p->name, err); 504 504 goto out; 505 505 } ··· 663 663 return PTR_ERR(rdt.cache); 664 664 } 665 665 666 - return iterate_dir(od->realfile, &rdt.ctx); 666 + err = iterate_dir(od->realfile, &rdt.ctx); 667 + ctx->pos = rdt.ctx.pos; 668 + 669 + return err; 667 670 } 668 671 669 672
+66 -21
fs/overlayfs/super.c
··· 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, ··· 239 232 kfree(ofs->config.lowerdir); 240 233 kfree(ofs->config.upperdir); 241 234 kfree(ofs->config.workdir); 235 + kfree(ofs->config.redirect_mode); 242 236 if (ofs->creator_cred) 243 237 put_cred(ofs->creator_cred); 244 238 kfree(ofs); ··· 252 244 ovl_free_fs(ofs); 253 245 } 254 246 247 + /* Sync real dirty inodes in upper filesystem (if it exists) */ 255 248 static int ovl_sync_fs(struct super_block *sb, int wait) 256 249 { 257 250 struct ovl_fs *ofs = sb->s_fs_info; ··· 261 252 262 253 if (!ofs->upper_mnt) 263 254 return 0; 264 - upper_sb = ofs->upper_mnt->mnt_sb; 265 - if (!upper_sb->s_op->sync_fs) 255 + 256 + /* 257 + * If this is a sync(2) call or an emergency sync, all the super blocks 258 + * will be iterated, including upper_sb, so no need to do anything. 259 + * 260 + * If this is a syncfs(2) call, then we do need to call 261 + * sync_filesystem() on upper_sb, but enough if we do it when being 262 + * called with wait == 1. 263 + */ 264 + if (!wait) 266 265 return 0; 267 266 268 - /* real inodes have already been synced by sync_filesystem(ovl_sb) */ 267 + upper_sb = ofs->upper_mnt->mnt_sb; 268 + 269 269 down_read(&upper_sb->s_umount); 270 - ret = upper_sb->s_op->sync_fs(upper_sb, wait); 270 + ret = sync_filesystem(upper_sb); 271 271 up_read(&upper_sb->s_umount); 272 + 272 273 return ret; 273 274 } 274 275 ··· 314 295 return (!ofs->upper_mnt || !ofs->workdir); 315 296 } 316 297 298 + static const char *ovl_redirect_mode_def(void) 299 + { 300 + return ovl_redirect_dir_def ? "on" : "off"; 301 + } 302 + 317 303 /** 318 304 * ovl_show_options 319 305 * ··· 337 313 } 338 314 if (ofs->config.default_permissions) 339 315 seq_puts(m, ",default_permissions"); 340 - if (ofs->config.redirect_dir != ovl_redirect_dir_def) 341 - seq_printf(m, ",redirect_dir=%s", 342 - ofs->config.redirect_dir ? "on" : "off"); 316 + if (strcmp(ofs->config.redirect_mode, ovl_redirect_mode_def()) != 0) 317 + seq_printf(m, ",redirect_dir=%s", ofs->config.redirect_mode); 343 318 if (ofs->config.index != ovl_index_def) 344 - seq_printf(m, ",index=%s", 345 - ofs->config.index ? "on" : "off"); 319 + seq_printf(m, ",index=%s", ofs->config.index ? "on" : "off"); 346 320 return 0; 347 321 } 348 322 ··· 370 348 OPT_UPPERDIR, 371 349 OPT_WORKDIR, 372 350 OPT_DEFAULT_PERMISSIONS, 373 - OPT_REDIRECT_DIR_ON, 374 - OPT_REDIRECT_DIR_OFF, 351 + OPT_REDIRECT_DIR, 375 352 OPT_INDEX_ON, 376 353 OPT_INDEX_OFF, 377 354 OPT_ERR, ··· 381 360 {OPT_UPPERDIR, "upperdir=%s"}, 382 361 {OPT_WORKDIR, "workdir=%s"}, 383 362 {OPT_DEFAULT_PERMISSIONS, "default_permissions"}, 384 - {OPT_REDIRECT_DIR_ON, "redirect_dir=on"}, 385 - {OPT_REDIRECT_DIR_OFF, "redirect_dir=off"}, 363 + {OPT_REDIRECT_DIR, "redirect_dir=%s"}, 386 364 {OPT_INDEX_ON, "index=on"}, 387 365 {OPT_INDEX_OFF, "index=off"}, 388 366 {OPT_ERR, NULL} ··· 410 390 return sbegin; 411 391 } 412 392 393 + static int ovl_parse_redirect_mode(struct ovl_config *config, const char *mode) 394 + { 395 + if (strcmp(mode, "on") == 0) { 396 + config->redirect_dir = true; 397 + /* 398 + * Does not make sense to have redirect creation without 399 + * redirect following. 400 + */ 401 + config->redirect_follow = true; 402 + } else if (strcmp(mode, "follow") == 0) { 403 + config->redirect_follow = true; 404 + } else if (strcmp(mode, "off") == 0) { 405 + if (ovl_redirect_always_follow) 406 + config->redirect_follow = true; 407 + } else if (strcmp(mode, "nofollow") != 0) { 408 + pr_err("overlayfs: bad mount option \"redirect_dir=%s\"\n", 409 + mode); 410 + return -EINVAL; 411 + } 412 + 413 + return 0; 414 + } 415 + 413 416 static int ovl_parse_opt(char *opt, struct ovl_config *config) 414 417 { 415 418 char *p; 419 + 420 + config->redirect_mode = kstrdup(ovl_redirect_mode_def(), GFP_KERNEL); 421 + if (!config->redirect_mode) 422 + return -ENOMEM; 416 423 417 424 while ((p = ovl_next_opt(&opt)) != NULL) { 418 425 int token; ··· 475 428 config->default_permissions = true; 476 429 break; 477 430 478 - case OPT_REDIRECT_DIR_ON: 479 - config->redirect_dir = true; 480 - break; 481 - 482 - case OPT_REDIRECT_DIR_OFF: 483 - config->redirect_dir = false; 431 + case OPT_REDIRECT_DIR: 432 + kfree(config->redirect_mode); 433 + config->redirect_mode = match_strdup(&args[0]); 434 + if (!config->redirect_mode) 435 + return -ENOMEM; 484 436 break; 485 437 486 438 case OPT_INDEX_ON: ··· 504 458 config->workdir = NULL; 505 459 } 506 460 507 - return 0; 461 + return ovl_parse_redirect_mode(config, config->redirect_mode); 508 462 } 509 463 510 464 #define OVL_WORKDIR_NAME "work" ··· 1206 1160 if (!cred) 1207 1161 goto out_err; 1208 1162 1209 - ofs->config.redirect_dir = ovl_redirect_dir_def; 1210 1163 ofs->config.index = ovl_index_def; 1211 1164 err = ovl_parse_opt((char *) data, &ofs->config); 1212 1165 if (err)