Skip to content

Commit 06c5674

Browse files
neilbrownbrauner
authored andcommitted
Use try_lookup_noperm() instead of d_hash_and_lookup() outside of VFS
try_lookup_noperm() and d_hash_and_lookup() are nearly identical. The former does some validation of the name where the latter doesn't. Outside of the VFS that validation is likely valuable, and having only one exported function for this task is certainly a good idea. So make d_hash_and_lookup() local to VFS files and change all other callers to try_lookup_noperm(). Note that the arguments are swapped. Signed-off-by: NeilBrown <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Christian Brauner <[email protected]>
1 parent fa6fe07 commit 06c5674

File tree

10 files changed

+30
-24
lines changed

10 files changed

+30
-24
lines changed

Documentation/filesystems/porting.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,3 +1232,14 @@ checked that the caller has 'X' permission on the parent. They must
12321232
ONLY be used internally by a filesystem on itself when it knows that
12331233
permissions are irrelevant or in a context where permission checks have
12341234
already been performed such as after vfs_path_parent_lookup()
1235+
1236+
---
1237+
1238+
** mandatory**
1239+
1240+
d_hash_and_lookup() is no longer exported or available outside the VFS.
1241+
Use try_lookup_noperm() instead. This adds name validation and takes
1242+
arguments in the opposite order but is otherwise identical.
1243+
1244+
Using try_lookup_noperm() will require linux/namei.h to be included.
1245+

fs/dcache.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2412,7 +2412,6 @@ struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name)
24122412
}
24132413
return d_lookup(dir, name);
24142414
}
2415-
EXPORT_SYMBOL(d_hash_and_lookup);
24162415

24172416
/*
24182417
* When a file is deleted, we have two options:

fs/efivarfs/super.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/statfs.h>
1919
#include <linux/notifier.h>
2020
#include <linux/printk.h>
21+
#include <linux/namei.h>
2122

2223
#include "internal.h"
2324

@@ -204,7 +205,6 @@ bool efivarfs_variable_is_present(efi_char16_t *variable_name,
204205
char *name = efivar_get_utf8name(variable_name, vendor);
205206
struct super_block *sb = data;
206207
struct dentry *dentry;
207-
struct qstr qstr;
208208

209209
if (!name)
210210
/*
@@ -217,9 +217,7 @@ bool efivarfs_variable_is_present(efi_char16_t *variable_name,
217217
*/
218218
return true;
219219

220-
qstr.name = name;
221-
qstr.len = strlen(name);
222-
dentry = d_hash_and_lookup(sb->s_root, &qstr);
220+
dentry = try_lookup_noperm(&QSTR(name), sb->s_root);
223221
kfree(name);
224222
if (!IS_ERR_OR_NULL(dentry))
225223
dput(dentry);
@@ -404,8 +402,8 @@ static bool efivarfs_actor(struct dir_context *ctx, const char *name, int len,
404402
{
405403
unsigned long size;
406404
struct efivarfs_ctx *ectx = container_of(ctx, struct efivarfs_ctx, ctx);
407-
struct qstr qstr = { .name = name, .len = len };
408-
struct dentry *dentry = d_hash_and_lookup(ectx->sb->s_root, &qstr);
405+
struct dentry *dentry = try_lookup_noperm(&QSTR_LEN(name, len),
406+
ectx->sb->s_root);
409407
struct inode *inode;
410408
struct efivar_entry *entry;
411409
int err;
@@ -441,7 +439,6 @@ static int efivarfs_check_missing(efi_char16_t *name16, efi_guid_t vendor,
441439
char *name;
442440
struct super_block *sb = data;
443441
struct dentry *dentry;
444-
struct qstr qstr;
445442
int err;
446443

447444
if (guid_equal(&vendor, &LINUX_EFI_RANDOM_SEED_TABLE_GUID))
@@ -451,9 +448,7 @@ static int efivarfs_check_missing(efi_char16_t *name16, efi_guid_t vendor,
451448
if (!name)
452449
return -ENOMEM;
453450

454-
qstr.name = name;
455-
qstr.len = strlen(name);
456-
dentry = d_hash_and_lookup(sb->s_root, &qstr);
451+
dentry = try_lookup_noperm(&QSTR(name), sb->s_root);
457452
if (IS_ERR(dentry)) {
458453
err = PTR_ERR(dentry);
459454
goto out;

fs/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ int do_linkat(int olddfd, struct filename *old, int newdfd,
6666
int vfs_tmpfile(struct mnt_idmap *idmap,
6767
const struct path *parentpath,
6868
struct file *file, umode_t mode);
69+
struct dentry *d_hash_and_lookup(struct dentry *, struct qstr *);
6970

7071
/*
7172
* namespace.c

fs/proc/base.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2121,7 +2121,7 @@ bool proc_fill_cache(struct file *file, struct dir_context *ctx,
21212121
unsigned type = DT_UNKNOWN;
21222122
ino_t ino = 1;
21232123

2124-
child = d_hash_and_lookup(dir, &qname);
2124+
child = try_lookup_noperm(&qname, dir);
21252125
if (!child) {
21262126
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
21272127
child = d_alloc_parallel(dir, &qname, &wq);

fs/smb/client/readdir.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*
1010
*/
1111
#include <linux/fs.h>
12+
#include <linux/namei.h>
1213
#include <linux/pagemap.h>
1314
#include <linux/slab.h>
1415
#include <linux/stat.h>
@@ -78,7 +79,7 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
7879

7980
cifs_dbg(FYI, "%s: for %s\n", __func__, name->name);
8081

81-
dentry = d_hash_and_lookup(parent, name);
82+
dentry = try_lookup_noperm(name, parent);
8283
if (!dentry) {
8384
/*
8485
* If we know that the inode will need to be revalidated

fs/xfs/scrub/orphanage.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ xrep_adoption_check_dcache(
444444
if (!d_orphanage)
445445
return 0;
446446

447-
d_child = d_hash_and_lookup(d_orphanage, &qname);
447+
d_child = try_lookup_noperm(&qname, d_orphanage);
448448
if (d_child) {
449449
trace_xrep_adoption_check_child(sc->mp, d_child);
450450

@@ -481,7 +481,7 @@ xrep_adoption_zap_dcache(
481481
if (!d_orphanage)
482482
return;
483483

484-
d_child = d_hash_and_lookup(d_orphanage, &qname);
484+
d_child = try_lookup_noperm(&qname, d_orphanage);
485485
while (d_child != NULL) {
486486
trace_xrep_adoption_invalidate_child(sc->mp, d_child);
487487

include/linux/dcache.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,6 @@ extern void d_exchange(struct dentry *, struct dentry *);
288288
extern struct dentry *d_ancestor(struct dentry *, struct dentry *);
289289

290290
extern struct dentry *d_lookup(const struct dentry *, const struct qstr *);
291-
extern struct dentry *d_hash_and_lookup(struct dentry *, struct qstr *);
292291

293292
static inline unsigned d_count(const struct dentry *dentry)
294293
{

net/sunrpc/rpc_pipe.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent,
631631
const char *name)
632632
{
633633
struct qstr q = QSTR(name);
634-
struct dentry *dentry = d_hash_and_lookup(parent, &q);
634+
struct dentry *dentry = try_lookup_noperm(&q, parent);
635635
if (!dentry) {
636636
dentry = d_alloc(parent, &q);
637637
if (!dentry)
@@ -658,7 +658,7 @@ static void __rpc_depopulate(struct dentry *parent,
658658
for (i = start; i < eof; i++) {
659659
name.name = files[i].name;
660660
name.len = strlen(files[i].name);
661-
dentry = d_hash_and_lookup(parent, &name);
661+
dentry = try_lookup_noperm(&name, parent);
662662

663663
if (dentry == NULL)
664664
continue;
@@ -1190,7 +1190,7 @@ static const struct rpc_filelist files[] = {
11901190
struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
11911191
const unsigned char *dir_name)
11921192
{
1193-
return d_hash_and_lookup(sb->s_root, &QSTR(dir_name));
1193+
return try_lookup_noperm(&QSTR(dir_name), sb->s_root);
11941194
}
11951195
EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
11961196

@@ -1301,7 +1301,7 @@ rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data)
13011301
struct dentry *pipe_dentry = NULL;
13021302

13031303
/* We should never get this far if "gssd" doesn't exist */
1304-
gssd_dentry = d_hash_and_lookup(root, &QSTR(files[RPCAUTH_gssd].name));
1304+
gssd_dentry = try_lookup_noperm(&QSTR(files[RPCAUTH_gssd].name), root);
13051305
if (!gssd_dentry)
13061306
return ERR_PTR(-ENOENT);
13071307

@@ -1311,8 +1311,8 @@ rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data)
13111311
goto out;
13121312
}
13131313

1314-
clnt_dentry = d_hash_and_lookup(gssd_dentry,
1315-
&QSTR(gssd_dummy_clnt_dir[0].name));
1314+
clnt_dentry = try_lookup_noperm(&QSTR(gssd_dummy_clnt_dir[0].name),
1315+
gssd_dentry);
13161316
if (!clnt_dentry) {
13171317
__rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1);
13181318
pipe_dentry = ERR_PTR(-ENOENT);

security/selinux/selinuxfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,8 +2158,8 @@ static int __init init_sel_fs(void)
21582158
return err;
21592159
}
21602160

2161-
selinux_null.dentry = d_hash_and_lookup(selinux_null.mnt->mnt_root,
2162-
&null_name);
2161+
selinux_null.dentry = try_lookup_noperm(&null_name,
2162+
selinux_null.mnt->mnt_root);
21632163
if (IS_ERR(selinux_null.dentry)) {
21642164
pr_err("selinuxfs: could not lookup null!\n");
21652165
err = PTR_ERR(selinux_null.dentry);

0 commit comments

Comments
 (0)