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 tag 'ovl-update-v2-6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs

Pull overlayfs update from Miklos Szeredi:

- Fix a regression in getting the path of an open file (e.g. in
/proc/PID/maps) for a nested overlayfs setup (André Almeida)

- Support data-only layers and verity in a user namespace (unprivileged
composefs use case)

- Fix a gcc warning (Kees)

- Cleanups

* tag 'ovl-update-v2-6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs:
ovl: Annotate struct ovl_entry with __counted_by()
ovl: Replace offsetof() with struct_size() in ovl_stack_free()
ovl: Replace offsetof() with struct_size() in ovl_cache_entry_new()
ovl: Check for NULL d_inode() in ovl_dentry_upper()
ovl: Use str_on_off() helper in ovl_show_options()
ovl: don't require "metacopy=on" for "verity"
ovl: relax redirect/metacopy requirements for lower -> data redirect
ovl: make redirect/metacopy rejection consistent
ovl: Fix nested backing file paths

+84 -80
+7
Documentation/filesystems/overlayfs.rst
··· 443 443 when a "metacopy" file in one of the lower layers above it, has a "redirect" 444 444 to the absolute path of the "lower data" file in the "data-only" lower layer. 445 445 446 + Instead of explicitly enabling "metacopy=on" it is sufficient to specify at 447 + least one data-only layer to enable redirection of data to a data-only layer. 448 + In this case other forms of metacopy are rejected. Note: this way data-only 449 + layers may be used toghether with "userxattr", in which case careful attention 450 + must be given to privileges needed to change the "user.overlay.redirect" xattr 451 + to prevent misuse. 452 + 446 453 Since kernel version v6.8, "data-only" lower layers can also be added using 447 454 the "datadir+" mount options and the fsconfig syscall from new mount api. 448 455 For example::
+2 -2
fs/overlayfs/file.c
··· 48 48 if (!inode_owner_or_capable(real_idmap, realinode)) 49 49 flags &= ~O_NOATIME; 50 50 51 - realfile = backing_file_open(&file->f_path, flags, realpath, 52 - current_cred()); 51 + realfile = backing_file_open(file_user_path((struct file *) file), 52 + flags, realpath, current_cred()); 53 53 } 54 54 ovl_revert_creds(old_cred); 55 55
+60 -38
fs/overlayfs/namei.c
··· 16 16 17 17 struct ovl_lookup_data { 18 18 struct super_block *sb; 19 + struct dentry *dentry; 19 20 const struct ovl_layer *layer; 20 21 struct qstr name; 21 22 bool is_dir; ··· 25 24 bool stop; 26 25 bool last; 27 26 char *redirect; 27 + char *upperredirect; 28 28 int metacopy; 29 29 /* Referring to last redirect xattr */ 30 30 bool absolute_redirect; ··· 1026 1024 return ovl_maybe_validate_verity(dentry); 1027 1025 } 1028 1026 1027 + /* 1028 + * Following redirects/metacopy can have security consequences: it's like a 1029 + * symlink into the lower layer without the permission checks. 1030 + * 1031 + * This is only a problem if the upper layer is untrusted (e.g comes from an USB 1032 + * drive). This can allow a non-readable file or directory to become readable. 1033 + * 1034 + * Only following redirects when redirects are enabled disables this attack 1035 + * vector when not necessary. 1036 + */ 1037 + static bool ovl_check_follow_redirect(struct ovl_lookup_data *d) 1038 + { 1039 + struct ovl_fs *ofs = OVL_FS(d->sb); 1040 + 1041 + if (d->metacopy && !ofs->config.metacopy) { 1042 + pr_warn_ratelimited("refusing to follow metacopy origin for (%pd2)\n", d->dentry); 1043 + return false; 1044 + } 1045 + if ((d->redirect || d->upperredirect) && !ovl_redirect_follow(ofs)) { 1046 + pr_warn_ratelimited("refusing to follow redirect for (%pd2)\n", d->dentry); 1047 + return false; 1048 + } 1049 + return true; 1050 + } 1051 + 1029 1052 struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, 1030 1053 unsigned int flags) 1031 1054 { ··· 1066 1039 unsigned int ctr = 0; 1067 1040 struct inode *inode = NULL; 1068 1041 bool upperopaque = false; 1069 - char *upperredirect = NULL; 1042 + bool check_redirect = (ovl_redirect_follow(ofs) || ofs->numdatalayer); 1070 1043 struct dentry *this; 1071 1044 unsigned int i; 1072 1045 int err; ··· 1074 1047 int metacopy_size = 0; 1075 1048 struct ovl_lookup_data d = { 1076 1049 .sb = dentry->d_sb, 1050 + .dentry = dentry, 1077 1051 .name = dentry->d_name, 1078 1052 .is_dir = false, 1079 1053 .opaque = false, 1080 1054 .stop = false, 1081 - .last = ovl_redirect_follow(ofs) ? false : !ovl_numlower(poe), 1055 + .last = check_redirect ? false : !ovl_numlower(poe), 1082 1056 .redirect = NULL, 1057 + .upperredirect = NULL, 1083 1058 .metacopy = 0, 1084 1059 }; 1085 1060 ··· 1123 1094 1124 1095 if (d.redirect) { 1125 1096 err = -ENOMEM; 1126 - upperredirect = kstrdup(d.redirect, GFP_KERNEL); 1127 - if (!upperredirect) 1097 + d.upperredirect = kstrdup(d.redirect, GFP_KERNEL); 1098 + if (!d.upperredirect) 1128 1099 goto out_put_upper; 1129 1100 if (d.redirect[0] == '/') 1130 1101 poe = roe; ··· 1142 1113 for (i = 0; !d.stop && i < ovl_numlower(poe); i++) { 1143 1114 struct ovl_path lower = ovl_lowerstack(poe)[i]; 1144 1115 1145 - if (!ovl_redirect_follow(ofs)) 1116 + if (!ovl_check_follow_redirect(&d)) { 1117 + err = -EPERM; 1118 + goto out_put; 1119 + } 1120 + 1121 + if (!check_redirect) 1146 1122 d.last = i == ovl_numlower(poe) - 1; 1147 1123 else if (d.is_dir || !ofs->numdatalayer) 1148 1124 d.last = lower.layer->idx == ovl_numlower(roe); ··· 1159 1125 1160 1126 if (!this) 1161 1127 continue; 1162 - 1163 - if ((uppermetacopy || d.metacopy) && !ofs->config.metacopy) { 1164 - dput(this); 1165 - err = -EPERM; 1166 - pr_warn_ratelimited("refusing to follow metacopy origin for (%pd2)\n", dentry); 1167 - goto out_put; 1168 - } 1169 1128 1170 1129 /* 1171 1130 * If no origin fh is stored in upper of a merge dir, store fh ··· 1212 1185 ctr++; 1213 1186 } 1214 1187 1215 - /* 1216 - * Following redirects can have security consequences: it's like 1217 - * a symlink into the lower layer without the permission checks. 1218 - * This is only a problem if the upper layer is untrusted (e.g 1219 - * comes from an USB drive). This can allow a non-readable file 1220 - * or directory to become readable. 1221 - * 1222 - * Only following redirects when redirects are enabled disables 1223 - * this attack vector when not necessary. 1224 - */ 1225 - err = -EPERM; 1226 - if (d.redirect && !ovl_redirect_follow(ofs)) { 1227 - pr_warn_ratelimited("refusing to follow redirect for (%pd2)\n", 1228 - dentry); 1229 - goto out_put; 1230 - } 1231 - 1232 1188 if (d.stop) 1233 1189 break; 1234 1190 ··· 1222 1212 } 1223 1213 } 1224 1214 1225 - /* Defer lookup of lowerdata in data-only layers to first access */ 1215 + /* 1216 + * Defer lookup of lowerdata in data-only layers to first access. 1217 + * Don't require redirect=follow and metacopy=on in this case. 1218 + */ 1226 1219 if (d.metacopy && ctr && ofs->numdatalayer && d.absolute_redirect) { 1227 1220 d.metacopy = 0; 1228 1221 ctr++; 1222 + } else if (!ovl_check_follow_redirect(&d)) { 1223 + err = -EPERM; 1224 + goto out_put; 1229 1225 } 1230 1226 1231 1227 /* ··· 1314 1298 1315 1299 /* 1316 1300 * It's safe to assign upperredirect here: the previous 1317 - * assignment of happens only if upperdentry is non-NULL, and 1301 + * assignment happens only if upperdentry is non-NULL, and 1318 1302 * this one only if upperdentry is NULL. 1319 1303 */ 1320 - upperredirect = ovl_get_redirect_xattr(ofs, &upperpath, 0); 1321 - if (IS_ERR(upperredirect)) { 1322 - err = PTR_ERR(upperredirect); 1323 - upperredirect = NULL; 1304 + d.upperredirect = ovl_get_redirect_xattr(ofs, &upperpath, 0); 1305 + if (IS_ERR(d.upperredirect)) { 1306 + err = PTR_ERR(d.upperredirect); 1307 + d.upperredirect = NULL; 1324 1308 goto out_free_oe; 1325 1309 } 1310 + 1326 1311 err = ovl_check_metacopy_xattr(ofs, &upperpath, NULL); 1327 1312 if (err < 0) 1328 1313 goto out_free_oe; 1329 - uppermetacopy = err; 1314 + d.metacopy = uppermetacopy = err; 1330 1315 metacopy_size = err; 1316 + 1317 + if (!ovl_check_follow_redirect(&d)) { 1318 + err = -EPERM; 1319 + goto out_free_oe; 1320 + } 1331 1321 } 1332 1322 1333 1323 if (upperdentry || ctr) { ··· 1341 1319 .upperdentry = upperdentry, 1342 1320 .oe = oe, 1343 1321 .index = index, 1344 - .redirect = upperredirect, 1322 + .redirect = d.upperredirect, 1345 1323 }; 1346 1324 1347 1325 /* Store lowerdata redirect for lazy lookup */ ··· 1383 1361 kfree(origin_path); 1384 1362 } 1385 1363 dput(upperdentry); 1386 - kfree(upperredirect); 1364 + kfree(d.upperredirect); 1387 1365 out: 1388 1366 kfree(d.redirect); 1389 1367 ovl_revert_creds(old_cred);
+1 -1
fs/overlayfs/ovl_entry.h
··· 51 51 52 52 struct ovl_entry { 53 53 unsigned int __numlower; 54 - struct ovl_path __lowerstack[]; 54 + struct ovl_path __lowerstack[] __counted_by(__numlower); 55 55 }; 56 56 57 57 /* private information held for overlayfs's superblock */
+6 -34
fs/overlayfs/params.c
··· 871 871 config->uuid = OVL_UUID_NULL; 872 872 } 873 873 874 - /* Resolve verity -> metacopy dependency */ 875 - if (config->verity_mode && !config->metacopy) { 876 - /* Don't allow explicit specified conflicting combinations */ 877 - if (set.metacopy) { 878 - pr_err("conflicting options: metacopy=off,verity=%s\n", 879 - ovl_verity_mode(config)); 880 - return -EINVAL; 881 - } 882 - /* Otherwise automatically enable metacopy. */ 883 - config->metacopy = true; 884 - } 885 - 886 874 /* 887 875 * This is to make the logic below simpler. It doesn't make any other 888 876 * difference, since redirect_dir=on is only used for upper. ··· 878 890 if (!config->upperdir && config->redirect_mode == OVL_REDIRECT_FOLLOW) 879 891 config->redirect_mode = OVL_REDIRECT_ON; 880 892 881 - /* Resolve verity -> metacopy -> redirect_dir dependency */ 893 + /* metacopy -> redirect_dir dependency */ 882 894 if (config->metacopy && config->redirect_mode != OVL_REDIRECT_ON) { 883 895 if (set.metacopy && set.redirect) { 884 896 pr_err("conflicting options: metacopy=on,redirect_dir=%s\n", 885 897 ovl_redirect_mode(config)); 886 - return -EINVAL; 887 - } 888 - if (config->verity_mode && set.redirect) { 889 - pr_err("conflicting options: verity=%s,redirect_dir=%s\n", 890 - ovl_verity_mode(config), ovl_redirect_mode(config)); 891 898 return -EINVAL; 892 899 } 893 900 if (set.redirect) { ··· 953 970 } 954 971 955 972 956 - /* Resolve userxattr -> !redirect && !metacopy && !verity dependency */ 973 + /* Resolve userxattr -> !redirect && !metacopy dependency */ 957 974 if (config->userxattr) { 958 975 if (set.redirect && 959 976 config->redirect_mode != OVL_REDIRECT_NOFOLLOW) { ··· 963 980 } 964 981 if (config->metacopy && set.metacopy) { 965 982 pr_err("conflicting options: userxattr,metacopy=on\n"); 966 - return -EINVAL; 967 - } 968 - if (config->verity_mode) { 969 - pr_err("conflicting options: userxattr,verity=%s\n", 970 - ovl_verity_mode(config)); 971 983 return -EINVAL; 972 984 } 973 985 /* ··· 1001 1023 * Other xattr-dependent features should be disabled without 1002 1024 * great disturbance to the user in ovl_make_workdir(). 1003 1025 */ 1004 - } 1005 - 1006 - if (ctx->nr_data > 0 && !config->metacopy) { 1007 - pr_err("lower data-only dirs require metacopy support.\n"); 1008 - return -EINVAL; 1009 1026 } 1010 1027 1011 1028 return 0; ··· 1051 1078 seq_printf(m, ",redirect_dir=%s", 1052 1079 ovl_redirect_mode(&ofs->config)); 1053 1080 if (ofs->config.index != ovl_index_def) 1054 - seq_printf(m, ",index=%s", ofs->config.index ? "on" : "off"); 1081 + seq_printf(m, ",index=%s", str_on_off(ofs->config.index)); 1055 1082 if (ofs->config.uuid != ovl_uuid_def()) 1056 1083 seq_printf(m, ",uuid=%s", ovl_uuid_mode(&ofs->config)); 1057 1084 if (ofs->config.nfs_export != ovl_nfs_export_def) 1058 - seq_printf(m, ",nfs_export=%s", ofs->config.nfs_export ? 1059 - "on" : "off"); 1085 + seq_printf(m, ",nfs_export=%s", 1086 + str_on_off(ofs->config.nfs_export)); 1060 1087 if (ofs->config.xino != ovl_xino_def() && !ovl_same_fs(ofs)) 1061 1088 seq_printf(m, ",xino=%s", ovl_xino_mode(&ofs->config)); 1062 1089 if (ofs->config.metacopy != ovl_metacopy_def) 1063 - seq_printf(m, ",metacopy=%s", 1064 - ofs->config.metacopy ? "on" : "off"); 1090 + seq_printf(m, ",metacopy=%s", str_on_off(ofs->config.metacopy)); 1065 1091 if (ofs->config.ovl_volatile) 1066 1092 seq_puts(m, ",volatile"); 1067 1093 if (ofs->config.userxattr)
+2 -2
fs/overlayfs/readdir.c
··· 13 13 #include <linux/security.h> 14 14 #include <linux/cred.h> 15 15 #include <linux/ratelimit.h> 16 + #include <linux/overflow.h> 16 17 #include "overlayfs.h" 17 18 18 19 struct ovl_cache_entry { ··· 148 147 u64 ino, unsigned int d_type) 149 148 { 150 149 struct ovl_cache_entry *p; 151 - size_t size = offsetof(struct ovl_cache_entry, name[len + 1]); 152 150 153 - p = kmalloc(size, GFP_KERNEL); 151 + p = kmalloc(struct_size(p, name, len + 1), GFP_KERNEL); 154 152 if (!p) 155 153 return NULL; 156 154
+6 -3
fs/overlayfs/util.c
··· 15 15 #include <linux/uuid.h> 16 16 #include <linux/namei.h> 17 17 #include <linux/ratelimit.h> 18 + #include <linux/overflow.h> 18 19 #include "overlayfs.h" 19 20 20 21 /* Get write access to upper mnt - may fail if upper sb was remounted ro */ ··· 146 145 147 146 struct ovl_entry *ovl_alloc_entry(unsigned int numlower) 148 147 { 149 - size_t size = offsetof(struct ovl_entry, __lowerstack[numlower]); 150 - struct ovl_entry *oe = kzalloc(size, GFP_KERNEL); 148 + struct ovl_entry *oe; 151 149 150 + oe = kzalloc(struct_size(oe, __lowerstack, numlower), GFP_KERNEL); 152 151 if (oe) 153 152 oe->__numlower = numlower; 154 153 ··· 306 305 307 306 struct dentry *ovl_dentry_upper(struct dentry *dentry) 308 307 { 309 - return ovl_upperdentry_dereference(OVL_I(d_inode(dentry))); 308 + struct inode *inode = d_inode(dentry); 309 + 310 + return inode ? ovl_upperdentry_dereference(OVL_I(inode)) : NULL; 310 311 } 311 312 312 313 struct dentry *ovl_dentry_lower(struct dentry *dentry)