Skip to content

Commit 180a9cc

Browse files
author
Al Viro
committed
make it easier to catch those who try to modify ->d_name
Turn d_name into an anon union of const struct qstr d_name with struct qstr __d_name. Very few places need to modify it (all in fs/dcache.c); those are switched to use of ->__d_name. Note that ->d_name can actually change under you unless you have the right locking environment; this const just prohibits accidentally doing stores without being easily spotted. Reviewed-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent ca97d6c commit 180a9cc

2 files changed

Lines changed: 17 additions & 14 deletions

File tree

fs/dcache.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,13 +1717,13 @@ static struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
17171717
dname = dentry->d_shortname.string;
17181718
}
17191719

1720-
dentry->d_name.len = name->len;
1721-
dentry->d_name.hash = name->hash;
1720+
dentry->__d_name.len = name->len;
1721+
dentry->__d_name.hash = name->hash;
17221722
memcpy(dname, name->name, name->len);
17231723
dname[name->len] = 0;
17241724

17251725
/* Make sure we always see the terminating NUL character */
1726-
smp_store_release(&dentry->d_name.name, dname); /* ^^^ */
1726+
smp_store_release(&dentry->__d_name.name, dname); /* ^^^ */
17271727

17281728
dentry->d_flags = 0;
17291729
lockref_init(&dentry->d_lockref);
@@ -2743,25 +2743,25 @@ static void swap_names(struct dentry *dentry, struct dentry *target)
27432743
/*
27442744
* Both external: swap the pointers
27452745
*/
2746-
swap(target->d_name.name, dentry->d_name.name);
2746+
swap(target->__d_name.name, dentry->__d_name.name);
27472747
} else {
27482748
/*
27492749
* dentry:internal, target:external. Steal target's
27502750
* storage and make target internal.
27512751
*/
2752-
dentry->d_name.name = target->d_name.name;
2752+
dentry->__d_name.name = target->__d_name.name;
27532753
target->d_shortname = dentry->d_shortname;
2754-
target->d_name.name = target->d_shortname.string;
2754+
target->__d_name.name = target->d_shortname.string;
27552755
}
27562756
} else {
27572757
if (unlikely(dname_external(dentry))) {
27582758
/*
27592759
* dentry:external, target:internal. Give dentry's
27602760
* storage to target and make dentry internal
27612761
*/
2762-
target->d_name.name = dentry->d_name.name;
2762+
target->__d_name.name = dentry->__d_name.name;
27632763
dentry->d_shortname = target->d_shortname;
2764-
dentry->d_name.name = dentry->d_shortname.string;
2764+
dentry->__d_name.name = dentry->d_shortname.string;
27652765
} else {
27662766
/*
27672767
* Both are internal.
@@ -2771,7 +2771,7 @@ static void swap_names(struct dentry *dentry, struct dentry *target)
27712771
target->d_shortname.words[i]);
27722772
}
27732773
}
2774-
swap(dentry->d_name.hash_len, target->d_name.hash_len);
2774+
swap(dentry->__d_name.hash_len, target->__d_name.hash_len);
27752775
}
27762776

27772777
static void copy_name(struct dentry *dentry, struct dentry *target)
@@ -2781,11 +2781,11 @@ static void copy_name(struct dentry *dentry, struct dentry *target)
27812781
old_name = external_name(dentry);
27822782
if (unlikely(dname_external(target))) {
27832783
atomic_inc(&external_name(target)->count);
2784-
dentry->d_name = target->d_name;
2784+
dentry->__d_name = target->__d_name;
27852785
} else {
27862786
dentry->d_shortname = target->d_shortname;
2787-
dentry->d_name.name = dentry->d_shortname.string;
2788-
dentry->d_name.hash_len = target->d_name.hash_len;
2787+
dentry->__d_name.name = dentry->d_shortname.string;
2788+
dentry->__d_name.hash_len = target->__d_name.hash_len;
27892789
}
27902790
if (old_name && likely(atomic_dec_and_test(&old_name->count)))
27912791
kfree_rcu(old_name, head);
@@ -3133,7 +3133,7 @@ void d_mark_tmpfile(struct file *file, struct inode *inode)
31333133
!d_unlinked(dentry));
31343134
spin_lock(&dentry->d_parent->d_lock);
31353135
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
3136-
dentry->d_name.len = sprintf(dentry->d_shortname.string, "#%llu",
3136+
dentry->__d_name.len = sprintf(dentry->d_shortname.string, "#%llu",
31373137
(unsigned long long)inode->i_ino);
31383138
spin_unlock(&dentry->d_lock);
31393139
spin_unlock(&dentry->d_parent->d_lock);

include/linux/dcache.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,10 @@ struct dentry {
9595
seqcount_spinlock_t d_seq; /* per dentry seqlock */
9696
struct hlist_bl_node d_hash; /* lookup hash list */
9797
struct dentry *d_parent; /* parent directory */
98-
struct qstr d_name;
98+
union {
99+
struct qstr __d_name; /* for use ONLY in fs/dcache.c */
100+
const struct qstr d_name;
101+
};
99102
struct inode *d_inode; /* Where the name belongs to - NULL is
100103
* negative */
101104
union shortname_store d_shortname;

0 commit comments

Comments
 (0)