Skip to content

Commit 53e8441

Browse files
committed
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>
2 parents 9396bfd + 9cf8ddb commit 53e8441

File tree

9 files changed

+35
-35
lines changed

9 files changed

+35
-35
lines changed

fs/crypto/fname.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ struct fscrypt_nokey_name {
7676

7777
static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
7878
{
79-
return is_dot_dotdot(str->name, str->len);
79+
return name_is_dot_dotdot(str->name, str->len);
8080
}
8181

8282
/**

fs/ecryptfs/crypto.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1904,7 +1904,7 @@ int ecryptfs_decode_and_decrypt_filename(char **plaintext_name,
19041904

19051905
if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) &&
19061906
!(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)) {
19081908
rc = ecryptfs_copy_filename(plaintext_name,
19091909
plaintext_name_size,
19101910
name, name_size);

fs/exportfs/expfs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,8 @@ static bool filldir_one(struct dir_context *ctx, const char *name, int len,
253253
container_of(ctx, struct getdents_callback, ctx);
254254

255255
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)) {
257258
memcpy(buf->name, name, len);
258259
buf->name[len] = '\0';
259260
buf->found = 1;

fs/f2fs/dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ int f2fs_init_casefolded_name(const struct inode *dir,
6767
int len;
6868

6969
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)) {
7171
buf = f2fs_kmem_cache_alloc(f2fs_cf_name_slab,
7272
GFP_NOFS, false, F2FS_SB(sb));
7373
if (!buf)

fs/f2fs/hash.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ void f2fs_hash_filename(const struct inode *dir, struct f2fs_filename *fname)
100100

101101
WARN_ON_ONCE(!name);
102102

103-
if (is_dot_dotdot(name, len)) {
103+
if (name_is_dot_dotdot(name, len)) {
104104
fname->hash = 0;
105105
return;
106106
}

fs/namei.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3042,7 +3042,7 @@ int lookup_noperm_common(struct qstr *qname, struct dentry *base)
30423042
if (!len)
30433043
return -EACCES;
30443044

3045-
if (is_dot_dotdot(name, len))
3045+
if (name_is_dot_dotdot(name, len))
30463046
return -EACCES;
30473047

30483048
while (len--) {

fs/overlayfs/readdir.c

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ static int ovl_casefold(struct ovl_readdir_data *rdd, const char *str, int len,
7676
char *cf_name;
7777
int cf_len;
7878

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))
8081
return 0;
8182

8283
cf_name = kmalloc(NAME_MAX, GFP_KERNEL);
@@ -153,7 +154,7 @@ static bool ovl_calc_d_ino(struct ovl_readdir_data *rdd,
153154
return true;
154155

155156
/* Always recalc d_ino for parent */
156-
if (strcmp(p->name, "..") == 0)
157+
if (name_is_dotdot(p->name, p->len))
157158
return true;
158159

159160
/* If this is lower, then native d_ino will do */
@@ -164,7 +165,7 @@ static bool ovl_calc_d_ino(struct ovl_readdir_data *rdd,
164165
* Recalc d_ino for '.' and for all entries if dir is impure (contains
165166
* copied up entries)
166167
*/
167-
if ((p->name[0] == '.' && p->len == 1) ||
168+
if (name_is_dot(p->name, p->len) ||
168169
ovl_test_flag(OVL_IMPURE, d_inode(rdd->dentry)))
169170
return true;
170171

@@ -560,12 +561,12 @@ static int ovl_cache_update(const struct path *path, struct ovl_cache_entry *p,
560561
if (!ovl_same_dev(ofs) && !p->check_xwhiteout)
561562
goto out;
562563

563-
if (p->name[0] == '.') {
564+
if (name_is_dot_dotdot(p->name, p->len)) {
564565
if (p->len == 1) {
565566
this = dget(dir);
566567
goto get;
567568
}
568-
if (p->len == 2 && p->name[1] == '.') {
569+
if (p->len == 2) {
569570
/* we shall not be moved */
570571
this = dget(dir->d_parent);
571572
goto get;
@@ -665,8 +666,7 @@ static int ovl_dir_read_impure(const struct path *path, struct list_head *list,
665666
return err;
666667

667668
list_for_each_entry_safe(p, n, list, l_node) {
668-
if (strcmp(p->name, ".") != 0 &&
669-
strcmp(p->name, "..") != 0) {
669+
if (!name_is_dot_dotdot(p->name, p->len)) {
670670
err = ovl_cache_update(path, p, true);
671671
if (err)
672672
return err;
@@ -755,7 +755,7 @@ static bool ovl_fill_real(struct dir_context *ctx, const char *name,
755755
struct dir_context *orig_ctx = rdt->orig_ctx;
756756
bool res;
757757

758-
if (rdt->parent_ino && strcmp(name, "..") == 0) {
758+
if (rdt->parent_ino && name_is_dotdot(name, namelen)) {
759759
ino = rdt->parent_ino;
760760
} else if (rdt->cache) {
761761
struct ovl_cache_entry *p;
@@ -1096,12 +1096,8 @@ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list)
10961096
goto del_entry;
10971097
}
10981098

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;
11051101
err = -ENOTEMPTY;
11061102
break;
11071103

@@ -1145,7 +1141,7 @@ static bool ovl_check_d_type(struct dir_context *ctx, const char *name,
11451141
container_of(ctx, struct ovl_readdir_data, ctx);
11461142

11471143
/* Even if d_type is not supported, DT_DIR is returned for . and .. */
1148-
if (!strncmp(name, ".", namelen) || !strncmp(name, "..", namelen))
1144+
if (name_is_dot_dotdot(name, namelen))
11491145
return true;
11501146

11511147
if (d_type != DT_UNKNOWN)
@@ -1208,11 +1204,8 @@ static int ovl_workdir_cleanup_recurse(struct ovl_fs *ofs, const struct path *pa
12081204
list_for_each_entry(p, &list, l_node) {
12091205
struct dentry *dentry;
12101206

1211-
if (p->name[0] == '.') {
1212-
if (p->len == 1)
1213-
continue;
1214-
if (p->len == 2 && p->name[1] == '.')
1215-
continue;
1207+
if (name_is_dot_dotdot(p->name, p->len)) {
1208+
continue;
12161209
} else if (incompat) {
12171210
pr_err("overlay with incompat feature '%s' cannot be mounted\n",
12181211
p->name);
@@ -1277,12 +1270,8 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs)
12771270
goto out;
12781271

12791272
list_for_each_entry(p, &list, l_node) {
1280-
if (p->name[0] == '.') {
1281-
if (p->len == 1)
1282-
continue;
1283-
if (p->len == 2 && p->name[1] == '.')
1284-
continue;
1285-
}
1273+
if (name_is_dot_dotdot(p->name, p->len))
1274+
continue;
12861275
index = ovl_lookup_upper_unlocked(ofs, p->name, indexdir, p->len);
12871276
if (IS_ERR(index)) {
12881277
err = PTR_ERR(index);

fs/smb/server/vfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1052,7 +1052,7 @@ static bool __dir_empty(struct dir_context *ctx, const char *name, int namlen,
10521052
struct ksmbd_readdir_data *buf;
10531053

10541054
buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
1055-
if (!is_dot_dotdot(name, namlen))
1055+
if (!name_is_dot_dotdot(name, namlen))
10561056
buf->dirent_count++;
10571057

10581058
return !buf->dirent_count;

include/linux/fs.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2844,12 +2844,22 @@ u64 vfsmount_to_propagation_flags(struct vfsmount *mnt);
28442844

28452845
extern char *file_path(struct file *, char *, int);
28462846

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+
28472857
/**
2848-
* is_dot_dotdot - returns true only if @name is "." or ".."
2858+
* name_is_dot_dotdot - returns true only if @name is "." or ".."
28492859
* @name: file name to check
28502860
* @len: length of file name, in bytes
28512861
*/
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)
28532863
{
28542864
return len && unlikely(name[0] == '.') &&
28552865
(len == 1 || (len == 2 && name[1] == '.'));

0 commit comments

Comments
 (0)