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 patch series "name_is_dot* cleanup"

Amir Goldstein <amir73il@gmail.com> says:

Following the syzbot ovl bug report and a fix by Qing Wang,
I decided to follow up with a small vfs cleanup of some
open coded version of checking "." and ".." name in readdir.

The fix patch is applied at the start of this cleanup series to allow
for easy backporting, but it is not an urgent fix so I don't think
there is a need to fast track it.

* patches from https://patch.msgid.link/20260128132406.23768-1-amir73il@gmail.com:
ovl: use name_is_dot* helpers in readdir code
fs: add helpers name_is_dot{,dot,_dotdot}
ovl: Fix uninit-value in ovl_fill_real

Link: https://patch.msgid.link/20260128132406.23768-1-amir73il@gmail.com
Signed-off-by: Christian Brauner <brauner@kernel.org>

+35 -35
+1 -1
fs/crypto/fname.c
··· 76 76 77 77 static inline bool fscrypt_is_dot_dotdot(const struct qstr *str) 78 78 { 79 - return is_dot_dotdot(str->name, str->len); 79 + return name_is_dot_dotdot(str->name, str->len); 80 80 } 81 81 82 82 /**
+1 -1
fs/ecryptfs/crypto.c
··· 1904 1904 1905 1905 if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) && 1906 1906 !(mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)) { 1907 - if (is_dot_dotdot(name, name_size)) { 1907 + if (name_is_dot_dotdot(name, name_size)) { 1908 1908 rc = ecryptfs_copy_filename(plaintext_name, 1909 1909 plaintext_name_size, 1910 1910 name, name_size);
+2 -1
fs/exportfs/expfs.c
··· 253 253 container_of(ctx, struct getdents_callback, ctx); 254 254 255 255 buf->sequence++; 256 - if (buf->ino == ino && len <= NAME_MAX && !is_dot_dotdot(name, len)) { 256 + if (buf->ino == ino && len <= NAME_MAX && 257 + !name_is_dot_dotdot(name, len)) { 257 258 memcpy(buf->name, name, len); 258 259 buf->name[len] = '\0'; 259 260 buf->found = 1;
+1 -1
fs/f2fs/dir.c
··· 67 67 int len; 68 68 69 69 if (IS_CASEFOLDED(dir) && 70 - !is_dot_dotdot(fname->usr_fname->name, fname->usr_fname->len)) { 70 + !name_is_dot_dotdot(fname->usr_fname->name, fname->usr_fname->len)) { 71 71 buf = f2fs_kmem_cache_alloc(f2fs_cf_name_slab, 72 72 GFP_NOFS, false, F2FS_SB(sb)); 73 73 if (!buf)
+1 -1
fs/f2fs/hash.c
··· 100 100 101 101 WARN_ON_ONCE(!name); 102 102 103 - if (is_dot_dotdot(name, len)) { 103 + if (name_is_dot_dotdot(name, len)) { 104 104 fname->hash = 0; 105 105 return; 106 106 }
+1 -1
fs/namei.c
··· 3042 3042 if (!len) 3043 3043 return -EACCES; 3044 3044 3045 - if (is_dot_dotdot(name, len)) 3045 + if (name_is_dot_dotdot(name, len)) 3046 3046 return -EACCES; 3047 3047 3048 3048 while (len--) {
+15 -26
fs/overlayfs/readdir.c
··· 76 76 char *cf_name; 77 77 int cf_len; 78 78 79 - if (!IS_ENABLED(CONFIG_UNICODE) || !rdd->map || is_dot_dotdot(str, len)) 79 + if (!IS_ENABLED(CONFIG_UNICODE) || !rdd->map || 80 + name_is_dot_dotdot(str, len)) 80 81 return 0; 81 82 82 83 cf_name = kmalloc(NAME_MAX, GFP_KERNEL); ··· 154 153 return true; 155 154 156 155 /* Always recalc d_ino for parent */ 157 - if (strcmp(p->name, "..") == 0) 156 + if (name_is_dotdot(p->name, p->len)) 158 157 return true; 159 158 160 159 /* If this is lower, then native d_ino will do */ ··· 165 164 * Recalc d_ino for '.' and for all entries if dir is impure (contains 166 165 * copied up entries) 167 166 */ 168 - if ((p->name[0] == '.' && p->len == 1) || 167 + if (name_is_dot(p->name, p->len) || 169 168 ovl_test_flag(OVL_IMPURE, d_inode(rdd->dentry))) 170 169 return true; 171 170 ··· 561 560 if (!ovl_same_dev(ofs) && !p->check_xwhiteout) 562 561 goto out; 563 562 564 - if (p->name[0] == '.') { 563 + if (name_is_dot_dotdot(p->name, p->len)) { 565 564 if (p->len == 1) { 566 565 this = dget(dir); 567 566 goto get; 568 567 } 569 - if (p->len == 2 && p->name[1] == '.') { 568 + if (p->len == 2) { 570 569 /* we shall not be moved */ 571 570 this = dget(dir->d_parent); 572 571 goto get; ··· 666 665 return err; 667 666 668 667 list_for_each_entry_safe(p, n, list, l_node) { 669 - if (strcmp(p->name, ".") != 0 && 670 - strcmp(p->name, "..") != 0) { 668 + if (!name_is_dot_dotdot(p->name, p->len)) { 671 669 err = ovl_cache_update(path, p, true); 672 670 if (err) 673 671 return err; ··· 755 755 struct dir_context *orig_ctx = rdt->orig_ctx; 756 756 bool res; 757 757 758 - if (rdt->parent_ino && strcmp(name, "..") == 0) { 758 + if (rdt->parent_ino && name_is_dotdot(name, namelen)) { 759 759 ino = rdt->parent_ino; 760 760 } else if (rdt->cache) { 761 761 struct ovl_cache_entry *p; ··· 1096 1096 goto del_entry; 1097 1097 } 1098 1098 1099 - if (p->name[0] == '.') { 1100 - if (p->len == 1) 1101 - goto del_entry; 1102 - if (p->len == 2 && p->name[1] == '.') 1103 - goto del_entry; 1104 - } 1099 + if (name_is_dot_dotdot(p->name, p->len)) 1100 + goto del_entry; 1105 1101 err = -ENOTEMPTY; 1106 1102 break; 1107 1103 ··· 1141 1145 container_of(ctx, struct ovl_readdir_data, ctx); 1142 1146 1143 1147 /* Even if d_type is not supported, DT_DIR is returned for . and .. */ 1144 - if (!strncmp(name, ".", namelen) || !strncmp(name, "..", namelen)) 1148 + if (name_is_dot_dotdot(name, namelen)) 1145 1149 return true; 1146 1150 1147 1151 if (d_type != DT_UNKNOWN) ··· 1204 1208 list_for_each_entry(p, &list, l_node) { 1205 1209 struct dentry *dentry; 1206 1210 1207 - if (p->name[0] == '.') { 1208 - if (p->len == 1) 1209 - continue; 1210 - if (p->len == 2 && p->name[1] == '.') 1211 - continue; 1211 + if (name_is_dot_dotdot(p->name, p->len)) { 1212 + continue; 1212 1213 } else if (incompat) { 1213 1214 pr_err("overlay with incompat feature '%s' cannot be mounted\n", 1214 1215 p->name); ··· 1270 1277 goto out; 1271 1278 1272 1279 list_for_each_entry(p, &list, l_node) { 1273 - if (p->name[0] == '.') { 1274 - if (p->len == 1) 1275 - continue; 1276 - if (p->len == 2 && p->name[1] == '.') 1277 - continue; 1278 - } 1280 + if (name_is_dot_dotdot(p->name, p->len)) 1281 + continue; 1279 1282 index = ovl_lookup_upper_unlocked(ofs, p->name, indexdir, p->len); 1280 1283 if (IS_ERR(index)) { 1281 1284 err = PTR_ERR(index);
+1 -1
fs/smb/server/vfs.c
··· 1052 1052 struct ksmbd_readdir_data *buf; 1053 1053 1054 1054 buf = container_of(ctx, struct ksmbd_readdir_data, ctx); 1055 - if (!is_dot_dotdot(name, namlen)) 1055 + if (!name_is_dot_dotdot(name, namlen)) 1056 1056 buf->dirent_count++; 1057 1057 1058 1058 return !buf->dirent_count;
+12 -2
include/linux/fs.h
··· 2844 2844 2845 2845 extern char *file_path(struct file *, char *, int); 2846 2846 2847 + static inline bool name_is_dot(const char *name, size_t len) 2848 + { 2849 + return unlikely(len == 1 && name[0] == '.'); 2850 + } 2851 + 2852 + static inline bool name_is_dotdot(const char *name, size_t len) 2853 + { 2854 + return unlikely(len == 2 && name[0] == '.' && name[1] == '.'); 2855 + } 2856 + 2847 2857 /** 2848 - * is_dot_dotdot - returns true only if @name is "." or ".." 2858 + * name_is_dot_dotdot - returns true only if @name is "." or ".." 2849 2859 * @name: file name to check 2850 2860 * @len: length of file name, in bytes 2851 2861 */ 2852 - static inline bool is_dot_dotdot(const char *name, size_t len) 2862 + static inline bool name_is_dot_dotdot(const char *name, size_t len) 2853 2863 { 2854 2864 return len && unlikely(name[0] == '.') && 2855 2865 (len == 1 || (len == 2 && name[1] == '.'));