Unverified Commit 06c56740 authored by NeilBrown's avatar NeilBrown Committed by Christian Brauner
Browse files

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: default avatarNeilBrown <neilb@suse.de>
Link: https://lore.kernel.org/r/20250319031545.2999807-6-neil@brown.name


Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent fa6fe07d
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -1232,3 +1232,14 @@ checked that the caller has 'X' permission on the parent. They must
ONLY be used internally by a filesystem on itself when it knows that
permissions are irrelevant or in a context where permission checks have
already been performed such as after vfs_path_parent_lookup()

---

** mandatory**

d_hash_and_lookup() is no longer exported or available outside the VFS.
Use try_lookup_noperm() instead.  This adds name validation and takes
arguments in the opposite order but is otherwise identical.

Using try_lookup_noperm() will require linux/namei.h to be included.
+0 −1
Original line number Diff line number Diff line
@@ -2412,7 +2412,6 @@ struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name)
	}
	return d_lookup(dir, name);
}
EXPORT_SYMBOL(d_hash_and_lookup);

/*
 * When a file is deleted, we have two options:
+5 −10
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/statfs.h>
#include <linux/notifier.h>
#include <linux/printk.h>
#include <linux/namei.h>

#include "internal.h"

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

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

	qstr.name = name;
	qstr.len = strlen(name);
	dentry = d_hash_and_lookup(sb->s_root, &qstr);
	dentry = try_lookup_noperm(&QSTR(name), sb->s_root);
	kfree(name);
	if (!IS_ERR_OR_NULL(dentry))
		dput(dentry);
@@ -404,8 +402,8 @@ static bool efivarfs_actor(struct dir_context *ctx, const char *name, int len,
{
	unsigned long size;
	struct efivarfs_ctx *ectx = container_of(ctx, struct efivarfs_ctx, ctx);
	struct qstr qstr = { .name = name, .len = len };
	struct dentry *dentry = d_hash_and_lookup(ectx->sb->s_root, &qstr);
	struct dentry *dentry = try_lookup_noperm(&QSTR_LEN(name, len),
						  ectx->sb->s_root);
	struct inode *inode;
	struct efivar_entry *entry;
	int err;
@@ -441,7 +439,6 @@ static int efivarfs_check_missing(efi_char16_t *name16, efi_guid_t vendor,
	char *name;
	struct super_block *sb = data;
	struct dentry *dentry;
	struct qstr qstr;
	int err;

	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,
	if (!name)
		return -ENOMEM;

	qstr.name = name;
	qstr.len = strlen(name);
	dentry = d_hash_and_lookup(sb->s_root, &qstr);
	dentry = try_lookup_noperm(&QSTR(name), sb->s_root);
	if (IS_ERR(dentry)) {
		err = PTR_ERR(dentry);
		goto out;
+1 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ int do_linkat(int olddfd, struct filename *old, int newdfd,
int vfs_tmpfile(struct mnt_idmap *idmap,
		const struct path *parentpath,
		struct file *file, umode_t mode);
struct dentry *d_hash_and_lookup(struct dentry *, struct qstr *);

/*
 * namespace.c
+1 −1
Original line number Diff line number Diff line
@@ -2121,7 +2121,7 @@ bool proc_fill_cache(struct file *file, struct dir_context *ctx,
	unsigned type = DT_UNKNOWN;
	ino_t ino = 1;

	child = d_hash_and_lookup(dir, &qname);
	child = try_lookup_noperm(&qname, dir);
	if (!child) {
		DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
		child = d_alloc_parallel(dir, &qname, &wq);
Loading