vfs-6.16-rc1.async.dir

-----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCaDBN6wAKCRCRxhvAZXjc
 ok32AQD9DTiSCAoVg+7s+gSBuLTi8drPTN++mCaxdTqRh5WpRAD9GVyrGQT0s6LH
 eo9bm8d1TAYjilEWM0c0K0TxyQ7KcAA=
 =IW7H
 -----END PGP SIGNATURE-----

Merge tag 'vfs-6.16-rc1.async.dir' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs directory lookup updates from Christian Brauner:
 "This contains cleanups for the lookup_one*() family of helpers.

  We expose a set of functions with names containing "lookup_one_len"
  and others without the "_len". This difference has nothing to do with
  "len". It's rater a historical accident that can be confusing.

  The functions without "_len" take a "mnt_idmap" pointer. This is found
  in the "vfsmount" and that is an important question when choosing
  which to use: do you have a vfsmount, or are you "inside" the
  filesystem. A related question is "is permission checking relevant
  here?".

  nfsd and cachefiles *do* have a vfsmount but *don't* use the non-_len
  functions. They pass nop_mnt_idmap and refuse to work on filesystems
  which have any other idmap.

  This work changes nfsd and cachefile to use the lookup_one family of
  functions and to explictily pass &nop_mnt_idmap which is consistent
  with all other vfs interfaces used where &nop_mnt_idmap is explicitly
  passed.

  The remaining uses of the "_one" functions do not require permission
  checks so these are renamed to be "_noperm" and the permission
  checking is removed.

  This series also changes these lookup function to take a qstr instead
  of separate name and len. In many cases this simplifies the call"

* tag 'vfs-6.16-rc1.async.dir' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  VFS: change lookup_one_common and lookup_noperm_common to take a qstr
  Use try_lookup_noperm() instead of d_hash_and_lookup() outside of VFS
  VFS: rename lookup_one_len family to lookup_noperm and remove permission check
  cachefiles: Use lookup_one() rather than lookup_one_len()
  nfsd: Use lookup_one() rather than lookup_one_len()
  VFS: improve interface for lookup_one functions
This commit is contained in:
Linus Torvalds 2025-05-26 08:02:43 -07:00
commit 6d5b940e1e
48 changed files with 254 additions and 210 deletions

View File

@ -1203,3 +1203,43 @@ should use d_drop();d_splice_alias() and return the result of the latter.
If a positive dentry cannot be returned for some reason, in-kernel If a positive dentry cannot be returned for some reason, in-kernel
clients such as cachefiles, nfsd, smb/server may not perform ideally but clients such as cachefiles, nfsd, smb/server may not perform ideally but
will fail-safe. will fail-safe.
---
** mandatory**
lookup_one(), lookup_one_unlocked(), lookup_one_positive_unlocked() now
take a qstr instead of a name and len. These, not the "one_len"
versions, should be used whenever accessing a filesystem from outside
that filesysmtem, through a mount point - which will have a mnt_idmap.
---
** mandatory**
Functions try_lookup_one_len(), lookup_one_len(),
lookup_one_len_unlocked() and lookup_positive_unlocked() have been
renamed to try_lookup_noperm(), lookup_noperm(),
lookup_noperm_unlocked(), lookup_noperm_positive_unlocked(). They now
take a qstr instead of separate name and length. QSTR() can be used
when strlen() is needed for the length.
For try_lookup_noperm() a reference to the qstr is passed in case the
hash might subsequently be needed.
These function no longer do any permission checking - they previously
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.

View File

@ -342,7 +342,7 @@ static struct dentry *hypfs_create_file(struct dentry *parent, const char *name,
struct inode *inode; struct inode *inode;
inode_lock(d_inode(parent)); inode_lock(d_inode(parent));
dentry = lookup_one_len(name, parent, strlen(name)); dentry = lookup_noperm(&QSTR(name), parent);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
dentry = ERR_PTR(-ENOMEM); dentry = ERR_PTR(-ENOMEM);
goto fail; goto fail;

View File

@ -187,7 +187,7 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
inode_lock(d_inode(root)); inode_lock(d_inode(root));
/* look it up */ /* look it up */
dentry = lookup_one_len(name, root, name_len); dentry = lookup_noperm(&QSTR(name), root);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
inode_unlock(d_inode(root)); inode_unlock(d_inode(root));
ret = PTR_ERR(dentry); ret = PTR_ERR(dentry);
@ -487,7 +487,7 @@ static struct dentry *binderfs_create_dentry(struct dentry *parent,
{ {
struct dentry *dentry; struct dentry *dentry;
dentry = lookup_one_len(name, parent, strlen(name)); dentry = lookup_noperm(&QSTR(name), parent);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
return dentry; return dentry;

View File

@ -90,7 +90,7 @@ static int create_file(const char *name, umode_t mode,
int error; int error;
inode_lock(d_inode(parent)); inode_lock(d_inode(parent));
*dentry = lookup_one_len(name, parent, strlen(name)); *dentry = lookup_noperm(&QSTR(name), parent);
if (!IS_ERR(*dentry)) if (!IS_ERR(*dentry))
error = qibfs_mknod(d_inode(parent), *dentry, error = qibfs_mknod(d_inode(parent), *dentry,
mode, fops, data); mode, fops, data);
@ -433,7 +433,7 @@ static int remove_device_files(struct super_block *sb,
char unit[10]; char unit[10];
snprintf(unit, sizeof(unit), "%u", dd->unit); snprintf(unit, sizeof(unit), "%u", dd->unit);
dir = lookup_one_len_unlocked(unit, sb->s_root, strlen(unit)); dir = lookup_noperm_unlocked(&QSTR(unit), sb->s_root);
if (IS_ERR(dir)) { if (IS_ERR(dir)) {
pr_err("Lookup of %s failed\n", unit); pr_err("Lookup of %s failed\n", unit);

View File

@ -943,7 +943,7 @@ static struct dentry *afs_lookup_atsys(struct inode *dir, struct dentry *dentry)
} }
strcpy(p, name); strcpy(p, name);
ret = lookup_one_len(buf, dentry->d_parent, len); ret = lookup_noperm(&QSTR(buf), dentry->d_parent);
if (IS_ERR(ret) || d_is_positive(ret)) if (IS_ERR(ret) || d_is_positive(ret))
goto out_s; goto out_s;
dput(ret); dput(ret);

View File

@ -113,16 +113,14 @@ int afs_sillyrename(struct afs_vnode *dvnode, struct afs_vnode *vnode,
sdentry = NULL; sdentry = NULL;
do { do {
int slen;
dput(sdentry); dput(sdentry);
sillycounter++; sillycounter++;
/* Create a silly name. Note that the ".__afs" prefix is /* Create a silly name. Note that the ".__afs" prefix is
* understood by the salvager and must not be changed. * understood by the salvager and must not be changed.
*/ */
slen = scnprintf(silly, sizeof(silly), ".__afs%04X", sillycounter); scnprintf(silly, sizeof(silly), ".__afs%04X", sillycounter);
sdentry = lookup_one_len(silly, dentry->d_parent, slen); sdentry = lookup_noperm(&QSTR(silly), dentry->d_parent);
/* N.B. Better to return EBUSY here ... it could be dangerous /* N.B. Better to return EBUSY here ... it could be dangerous
* to delete the file while it's in use. * to delete the file while it's in use.

View File

@ -459,7 +459,8 @@ static int autofs_dev_ioctl_timeout(struct file *fp,
"the parent autofs mount timeout which could " "the parent autofs mount timeout which could "
"prevent shutdown\n"); "prevent shutdown\n");
dentry = try_lookup_one_len(param->path, base, path_len); dentry = try_lookup_noperm(&QSTR_LEN(param->path, path_len),
base);
if (IS_ERR_OR_NULL(dentry)) if (IS_ERR_OR_NULL(dentry))
return dentry ? PTR_ERR(dentry) : -ENOENT; return dentry ? PTR_ERR(dentry) : -ENOENT;
ino = autofs_dentry_ino(dentry); ino = autofs_dentry_ino(dentry);

View File

@ -842,7 +842,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
} }
inode_lock(d_inode(root)); inode_lock(d_inode(root));
dentry = lookup_one_len(e->name, root, strlen(e->name)); dentry = lookup_noperm(&QSTR(e->name), root);
err = PTR_ERR(dentry); err = PTR_ERR(dentry);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
goto out; goto out;

View File

@ -909,7 +909,7 @@ static noinline int btrfs_mksubvol(const struct path *parent,
if (error == -EINTR) if (error == -EINTR)
return error; return error;
dentry = lookup_one(idmap, name, parent->dentry, namelen); dentry = lookup_one(idmap, &QSTR_LEN(name, namelen), parent->dentry);
error = PTR_ERR(dentry); error = PTR_ERR(dentry);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
goto out_unlock; goto out_unlock;
@ -2288,7 +2288,6 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
struct btrfs_ioctl_vol_args_v2 *vol_args2 = NULL; struct btrfs_ioctl_vol_args_v2 *vol_args2 = NULL;
struct mnt_idmap *idmap = file_mnt_idmap(file); struct mnt_idmap *idmap = file_mnt_idmap(file);
char *subvol_name, *subvol_name_ptr = NULL; char *subvol_name, *subvol_name_ptr = NULL;
int subvol_namelen;
int ret = 0; int ret = 0;
bool destroy_parent = false; bool destroy_parent = false;
@ -2411,10 +2410,8 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
goto out; goto out;
} }
subvol_namelen = strlen(subvol_name);
if (strchr(subvol_name, '/') || if (strchr(subvol_name, '/') ||
strncmp(subvol_name, "..", subvol_namelen) == 0) { strcmp(subvol_name, "..") == 0) {
ret = -EINVAL; ret = -EINVAL;
goto free_subvol_name; goto free_subvol_name;
} }
@ -2427,7 +2424,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
ret = down_write_killable_nested(&dir->i_rwsem, I_MUTEX_PARENT); ret = down_write_killable_nested(&dir->i_rwsem, I_MUTEX_PARENT);
if (ret == -EINTR) if (ret == -EINTR)
goto free_subvol_name; goto free_subvol_name;
dentry = lookup_one(idmap, subvol_name, parent, subvol_namelen); dentry = lookup_one(idmap, &QSTR(subvol_name), parent);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry); ret = PTR_ERR(dentry);
goto out_unlock_dir; goto out_unlock_dir;

View File

@ -71,7 +71,6 @@ struct cachefiles_object {
int debug_id; int debug_id;
spinlock_t lock; spinlock_t lock;
refcount_t ref; refcount_t ref;
u8 d_name_len; /* Length of filename */
enum cachefiles_content content_info:8; /* Info about content presence */ enum cachefiles_content content_info:8; /* Info about content presence */
unsigned long flags; unsigned long flags;
#define CACHEFILES_OBJECT_USING_TMPFILE 0 /* Have an unlinked tmpfile */ #define CACHEFILES_OBJECT_USING_TMPFILE 0 /* Have an unlinked tmpfile */

View File

@ -132,7 +132,6 @@ bool cachefiles_cook_key(struct cachefiles_object *object)
success: success:
name[len] = 0; name[len] = 0;
object->d_name = name; object->d_name = name;
object->d_name_len = len;
_leave(" = %s", object->d_name); _leave(" = %s", object->d_name);
return true; return true;
} }

View File

@ -98,7 +98,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
retry: retry:
ret = cachefiles_inject_read_error(); ret = cachefiles_inject_read_error();
if (ret == 0) if (ret == 0)
subdir = lookup_one_len(dirname, dir, strlen(dirname)); subdir = lookup_one(&nop_mnt_idmap, &QSTR(dirname), dir);
else else
subdir = ERR_PTR(ret); subdir = ERR_PTR(ret);
trace_cachefiles_lookup(NULL, dir, subdir); trace_cachefiles_lookup(NULL, dir, subdir);
@ -338,7 +338,7 @@ try_again:
return -EIO; return -EIO;
} }
grave = lookup_one_len(nbuffer, cache->graveyard, strlen(nbuffer)); grave = lookup_one(&nop_mnt_idmap, &QSTR(nbuffer), cache->graveyard);
if (IS_ERR(grave)) { if (IS_ERR(grave)) {
unlock_rename(cache->graveyard, dir); unlock_rename(cache->graveyard, dir);
trace_cachefiles_vfs_error(object, d_inode(cache->graveyard), trace_cachefiles_vfs_error(object, d_inode(cache->graveyard),
@ -630,8 +630,8 @@ bool cachefiles_look_up_object(struct cachefiles_object *object)
/* Look up path "cache/vol/fanout/file". */ /* Look up path "cache/vol/fanout/file". */
ret = cachefiles_inject_read_error(); ret = cachefiles_inject_read_error();
if (ret == 0) if (ret == 0)
dentry = lookup_positive_unlocked(object->d_name, fan, dentry = lookup_one_positive_unlocked(&nop_mnt_idmap,
object->d_name_len); &QSTR(object->d_name), fan);
else else
dentry = ERR_PTR(ret); dentry = ERR_PTR(ret);
trace_cachefiles_lookup(object, fan, dentry); trace_cachefiles_lookup(object, fan, dentry);
@ -683,7 +683,7 @@ bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache,
inode_lock_nested(d_inode(fan), I_MUTEX_PARENT); inode_lock_nested(d_inode(fan), I_MUTEX_PARENT);
ret = cachefiles_inject_read_error(); ret = cachefiles_inject_read_error();
if (ret == 0) if (ret == 0)
dentry = lookup_one_len(object->d_name, fan, object->d_name_len); dentry = lookup_one(&nop_mnt_idmap, &QSTR(object->d_name), fan);
else else
dentry = ERR_PTR(ret); dentry = ERR_PTR(ret);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
@ -702,7 +702,7 @@ bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache,
dput(dentry); dput(dentry);
ret = cachefiles_inject_read_error(); ret = cachefiles_inject_read_error();
if (ret == 0) if (ret == 0)
dentry = lookup_one_len(object->d_name, fan, object->d_name_len); dentry = lookup_one(&nop_mnt_idmap, &QSTR(object->d_name), fan);
else else
dentry = ERR_PTR(ret); dentry = ERR_PTR(ret);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
@ -751,7 +751,7 @@ static struct dentry *cachefiles_lookup_for_cull(struct cachefiles_cache *cache,
inode_lock_nested(d_inode(dir), I_MUTEX_PARENT); inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
victim = lookup_one_len(filename, dir, strlen(filename)); victim = lookup_one(&nop_mnt_idmap, &QSTR(filename), dir);
if (IS_ERR(victim)) if (IS_ERR(victim))
goto lookup_error; goto lookup_error;
if (d_is_negative(victim)) if (d_is_negative(victim))

View File

@ -2412,7 +2412,6 @@ struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name)
} }
return d_lookup(dir, name); return d_lookup(dir, name);
} }
EXPORT_SYMBOL(d_hash_and_lookup);
/* /*
* When a file is deleted, we have two options: * When a file is deleted, we have two options:

View File

@ -346,7 +346,7 @@ struct dentry *debugfs_lookup(const char *name, struct dentry *parent)
if (!parent) if (!parent)
parent = debugfs_mount->mnt_root; parent = debugfs_mount->mnt_root;
dentry = lookup_positive_unlocked(name, parent, strlen(name)); dentry = lookup_noperm_positive_unlocked(&QSTR(name), parent);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
return NULL; return NULL;
return dentry; return dentry;
@ -388,7 +388,7 @@ static struct dentry *start_creating(const char *name, struct dentry *parent)
if (unlikely(IS_DEADDIR(d_inode(parent)))) if (unlikely(IS_DEADDIR(d_inode(parent))))
dentry = ERR_PTR(-ENOENT); dentry = ERR_PTR(-ENOENT);
else else
dentry = lookup_one_len(name, parent, strlen(name)); dentry = lookup_noperm(&QSTR(name), parent);
if (!IS_ERR(dentry) && d_really_is_positive(dentry)) { if (!IS_ERR(dentry) && d_really_is_positive(dentry)) {
if (d_is_dir(dentry)) if (d_is_dir(dentry))
pr_err("Directory '%s' with parent '%s' already present!\n", pr_err("Directory '%s' with parent '%s' already present!\n",
@ -872,7 +872,7 @@ int __printf(2, 3) debugfs_change_name(struct dentry *dentry, const char *fmt, .
} }
if (strcmp(old_name.name.name, new_name) == 0) if (strcmp(old_name.name.name, new_name) == 0)
goto out; goto out;
target = lookup_one_len(new_name, parent, strlen(new_name)); target = lookup_noperm(&QSTR(new_name), parent);
if (IS_ERR(target)) { if (IS_ERR(target)) {
error = PTR_ERR(target); error = PTR_ERR(target);
goto out; goto out;

View File

@ -394,8 +394,8 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
char *encrypted_and_encoded_name = NULL; char *encrypted_and_encoded_name = NULL;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat; struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
struct dentry *lower_dir_dentry, *lower_dentry; struct dentry *lower_dir_dentry, *lower_dentry;
const char *name = ecryptfs_dentry->d_name.name; struct qstr qname = QSTR_INIT(ecryptfs_dentry->d_name.name,
size_t len = ecryptfs_dentry->d_name.len; ecryptfs_dentry->d_name.len);
struct dentry *res; struct dentry *res;
int rc = 0; int rc = 0;
@ -404,23 +404,25 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
mount_crypt_stat = &ecryptfs_superblock_to_private( mount_crypt_stat = &ecryptfs_superblock_to_private(
ecryptfs_dentry->d_sb)->mount_crypt_stat; ecryptfs_dentry->d_sb)->mount_crypt_stat;
if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) { if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) {
size_t len = qname.len;
rc = ecryptfs_encrypt_and_encode_filename( rc = ecryptfs_encrypt_and_encode_filename(
&encrypted_and_encoded_name, &len, &encrypted_and_encoded_name, &len,
mount_crypt_stat, name, len); mount_crypt_stat, qname.name, len);
if (rc) { if (rc) {
printk(KERN_ERR "%s: Error attempting to encrypt and encode " printk(KERN_ERR "%s: Error attempting to encrypt and encode "
"filename; rc = [%d]\n", __func__, rc); "filename; rc = [%d]\n", __func__, rc);
return ERR_PTR(rc); return ERR_PTR(rc);
} }
name = encrypted_and_encoded_name; qname.name = encrypted_and_encoded_name;
qname.len = len;
} }
lower_dentry = lookup_one_len_unlocked(name, lower_dir_dentry, len); lower_dentry = lookup_noperm_unlocked(&qname, lower_dir_dentry);
if (IS_ERR(lower_dentry)) { if (IS_ERR(lower_dentry)) {
ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " ecryptfs_printk(KERN_DEBUG, "%s: lookup_noperm() returned "
"[%ld] on lower_dentry = [%s]\n", __func__, "[%ld] on lower_dentry = [%s]\n", __func__,
PTR_ERR(lower_dentry), PTR_ERR(lower_dentry),
name); qname.name);
res = ERR_CAST(lower_dentry); res = ERR_CAST(lower_dentry);
} else { } else {
res = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry); res = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry);

View File

@ -18,6 +18,7 @@
#include <linux/statfs.h> #include <linux/statfs.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/printk.h> #include <linux/printk.h>
#include <linux/namei.h>
#include "internal.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); char *name = efivar_get_utf8name(variable_name, vendor);
struct super_block *sb = data; struct super_block *sb = data;
struct dentry *dentry; struct dentry *dentry;
struct qstr qstr;
if (!name) if (!name)
/* /*
@ -217,9 +217,7 @@ bool efivarfs_variable_is_present(efi_char16_t *variable_name,
*/ */
return true; return true;
qstr.name = name; dentry = try_lookup_noperm(&QSTR(name), sb->s_root);
qstr.len = strlen(name);
dentry = d_hash_and_lookup(sb->s_root, &qstr);
kfree(name); kfree(name);
if (!IS_ERR_OR_NULL(dentry)) if (!IS_ERR_OR_NULL(dentry))
dput(dentry); dput(dentry);
@ -404,8 +402,8 @@ static bool efivarfs_actor(struct dir_context *ctx, const char *name, int len,
{ {
unsigned long size; unsigned long size;
struct efivarfs_ctx *ectx = container_of(ctx, struct efivarfs_ctx, ctx); struct efivarfs_ctx *ectx = container_of(ctx, struct efivarfs_ctx, ctx);
struct qstr qstr = { .name = name, .len = len }; struct dentry *dentry = try_lookup_noperm(&QSTR_LEN(name, len),
struct dentry *dentry = d_hash_and_lookup(ectx->sb->s_root, &qstr); ectx->sb->s_root);
struct inode *inode; struct inode *inode;
struct efivar_entry *entry; struct efivar_entry *entry;
int err; int err;
@ -441,7 +439,6 @@ static int efivarfs_check_missing(efi_char16_t *name16, efi_guid_t vendor,
char *name; char *name;
struct super_block *sb = data; struct super_block *sb = data;
struct dentry *dentry; struct dentry *dentry;
struct qstr qstr;
int err; int err;
if (guid_equal(&vendor, &LINUX_EFI_RANDOM_SEED_TABLE_GUID)) 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) if (!name)
return -ENOMEM; return -ENOMEM;
qstr.name = name; dentry = try_lookup_noperm(&QSTR(name), sb->s_root);
qstr.len = strlen(name);
dentry = d_hash_and_lookup(sb->s_root, &qstr);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
err = PTR_ERR(dentry); err = PTR_ERR(dentry);
goto out; goto out;

View File

@ -143,7 +143,7 @@ static struct dentry *reconnect_one(struct vfsmount *mnt,
if (err) if (err)
goto out_err; goto out_err;
dprintk("%s: found name: %s\n", __func__, nbuf); dprintk("%s: found name: %s\n", __func__, nbuf);
tmp = lookup_one_unlocked(mnt_idmap(mnt), nbuf, parent, strlen(nbuf)); tmp = lookup_one_unlocked(mnt_idmap(mnt), &QSTR(nbuf), parent);
if (IS_ERR(tmp)) { if (IS_ERR(tmp)) {
dprintk("lookup failed: %ld\n", PTR_ERR(tmp)); dprintk("lookup failed: %ld\n", PTR_ERR(tmp));
err = PTR_ERR(tmp); err = PTR_ERR(tmp);
@ -549,8 +549,7 @@ exportfs_decode_fh_raw(struct vfsmount *mnt, struct fid *fid, int fh_len,
} }
inode_lock(target_dir->d_inode); inode_lock(target_dir->d_inode);
nresult = lookup_one(mnt_idmap(mnt), nbuf, nresult = lookup_one(mnt_idmap(mnt), &QSTR(nbuf), target_dir);
target_dir, strlen(nbuf));
if (!IS_ERR(nresult)) { if (!IS_ERR(nresult)) {
if (unlikely(nresult->d_inode != result->d_inode)) { if (unlikely(nresult->d_inode != result->d_inode)) {
dput(nresult); dput(nresult);

View File

@ -66,6 +66,7 @@ int do_linkat(int olddfd, struct filename *old, int newdfd,
int vfs_tmpfile(struct mnt_idmap *idmap, int vfs_tmpfile(struct mnt_idmap *idmap,
const struct path *parentpath, const struct path *parentpath,
struct file *file, umode_t mode); struct file *file, umode_t mode);
struct dentry *d_hash_and_lookup(struct dentry *, struct qstr *);
/* /*
* namespace.c * namespace.c

View File

@ -255,7 +255,7 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn,
dput(dentry); dput(dentry);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
dtmp = lookup_positive_unlocked(name, dentry, strlen(name)); dtmp = lookup_noperm_positive_unlocked(&QSTR(name), dentry);
dput(dentry); dput(dentry);
kfree(name); kfree(name);
if (IS_ERR(dtmp)) if (IS_ERR(dtmp))

View File

@ -2869,13 +2869,12 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
} }
EXPORT_SYMBOL(vfs_path_lookup); EXPORT_SYMBOL(vfs_path_lookup);
static int lookup_one_common(struct mnt_idmap *idmap, static int lookup_noperm_common(struct qstr *qname, struct dentry *base)
const char *name, struct dentry *base, int len,
struct qstr *this)
{ {
this->name = name; const char *name = qname->name;
this->len = len; u32 len = qname->len;
this->hash = full_name_hash(base, name, len);
qname->hash = full_name_hash(base, name, len);
if (!len) if (!len)
return -EACCES; return -EACCES;
@ -2892,139 +2891,135 @@ static int lookup_one_common(struct mnt_idmap *idmap,
* to use its own hash.. * to use its own hash..
*/ */
if (base->d_flags & DCACHE_OP_HASH) { if (base->d_flags & DCACHE_OP_HASH) {
int err = base->d_op->d_hash(base, this); int err = base->d_op->d_hash(base, qname);
if (err < 0) if (err < 0)
return err; return err;
} }
return 0;
}
static int lookup_one_common(struct mnt_idmap *idmap,
struct qstr *qname, struct dentry *base)
{
int err;
err = lookup_noperm_common(qname, base);
if (err < 0)
return err;
return inode_permission(idmap, base->d_inode, MAY_EXEC); return inode_permission(idmap, base->d_inode, MAY_EXEC);
} }
/** /**
* try_lookup_one_len - filesystem helper to lookup single pathname component * try_lookup_noperm - filesystem helper to lookup single pathname component
* @name: pathname component to lookup * @name: qstr storing pathname component to lookup
* @base: base directory to lookup from * @base: base directory to lookup from
* @len: maximum length @len should be interpreted to
* *
* Look up a dentry by name in the dcache, returning NULL if it does not * Look up a dentry by name in the dcache, returning NULL if it does not
* currently exist. The function does not try to create a dentry. * currently exist. The function does not try to create a dentry.
* *
* Note that this routine is purely a helper for filesystem usage and should * Note that this routine is purely a helper for filesystem usage and should
* not be called by generic code. * not be called by generic code. It does no permission checking.
* *
* No locks need be held - only a counted reference to @base is needed. * No locks need be held - only a counted reference to @base is needed.
* *
*/ */
struct dentry *try_lookup_one_len(const char *name, struct dentry *base, int len) struct dentry *try_lookup_noperm(struct qstr *name, struct dentry *base)
{ {
struct qstr this;
int err; int err;
err = lookup_one_common(&nop_mnt_idmap, name, base, len, &this); err = lookup_noperm_common(name, base);
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
return lookup_dcache(&this, base, 0); return lookup_dcache(name, base, 0);
} }
EXPORT_SYMBOL(try_lookup_one_len); EXPORT_SYMBOL(try_lookup_noperm);
/** /**
* lookup_one_len - filesystem helper to lookup single pathname component * lookup_noperm - filesystem helper to lookup single pathname component
* @name: pathname component to lookup * @name: qstr storing pathname component to lookup
* @base: base directory to lookup from * @base: base directory to lookup from
* @len: maximum length @len should be interpreted to
* *
* Note that this routine is purely a helper for filesystem usage and should * Note that this routine is purely a helper for filesystem usage and should
* not be called by generic code. * not be called by generic code. It does no permission checking.
* *
* The caller must hold base->i_mutex. * The caller must hold base->i_mutex.
*/ */
struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) struct dentry *lookup_noperm(struct qstr *name, struct dentry *base)
{ {
struct dentry *dentry; struct dentry *dentry;
struct qstr this;
int err; int err;
WARN_ON_ONCE(!inode_is_locked(base->d_inode)); WARN_ON_ONCE(!inode_is_locked(base->d_inode));
err = lookup_one_common(&nop_mnt_idmap, name, base, len, &this); err = lookup_noperm_common(name, base);
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
dentry = lookup_dcache(&this, base, 0); dentry = lookup_dcache(name, base, 0);
return dentry ? dentry : __lookup_slow(&this, base, 0); return dentry ? dentry : __lookup_slow(name, base, 0);
} }
EXPORT_SYMBOL(lookup_one_len); EXPORT_SYMBOL(lookup_noperm);
/** /**
* lookup_one - filesystem helper to lookup single pathname component * lookup_one - lookup single pathname component
* @idmap: idmap of the mount the lookup is performed from * @idmap: idmap of the mount the lookup is performed from
* @name: pathname component to lookup * @name: qstr holding pathname component to lookup
* @base: base directory to lookup from * @base: base directory to lookup from
* @len: maximum length @len should be interpreted to
* *
* Note that this routine is purely a helper for filesystem usage and should * This can be used for in-kernel filesystem clients such as file servers.
* not be called by generic code.
* *
* The caller must hold base->i_mutex. * The caller must hold base->i_mutex.
*/ */
struct dentry *lookup_one(struct mnt_idmap *idmap, const char *name, struct dentry *lookup_one(struct mnt_idmap *idmap, struct qstr *name,
struct dentry *base, int len) struct dentry *base)
{ {
struct dentry *dentry; struct dentry *dentry;
struct qstr this;
int err; int err;
WARN_ON_ONCE(!inode_is_locked(base->d_inode)); WARN_ON_ONCE(!inode_is_locked(base->d_inode));
err = lookup_one_common(idmap, name, base, len, &this); err = lookup_one_common(idmap, name, base);
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
dentry = lookup_dcache(&this, base, 0); dentry = lookup_dcache(name, base, 0);
return dentry ? dentry : __lookup_slow(&this, base, 0); return dentry ? dentry : __lookup_slow(name, base, 0);
} }
EXPORT_SYMBOL(lookup_one); EXPORT_SYMBOL(lookup_one);
/** /**
* lookup_one_unlocked - filesystem helper to lookup single pathname component * lookup_one_unlocked - lookup single pathname component
* @idmap: idmap of the mount the lookup is performed from * @idmap: idmap of the mount the lookup is performed from
* @name: pathname component to lookup * @name: qstr olding pathname component to lookup
* @base: base directory to lookup from * @base: base directory to lookup from
* @len: maximum length @len should be interpreted to
* *
* Note that this routine is purely a helper for filesystem usage and should * This can be used for in-kernel filesystem clients such as file servers.
* not be called by generic code.
* *
* Unlike lookup_one_len, it should be called without the parent * Unlike lookup_one, it should be called without the parent
* i_mutex held, and will take the i_mutex itself if necessary. * i_rwsem held, and will take the i_rwsem itself if necessary.
*/ */
struct dentry *lookup_one_unlocked(struct mnt_idmap *idmap, struct dentry *lookup_one_unlocked(struct mnt_idmap *idmap, struct qstr *name,
const char *name, struct dentry *base, struct dentry *base)
int len)
{ {
struct qstr this;
int err; int err;
struct dentry *ret; struct dentry *ret;
err = lookup_one_common(idmap, name, base, len, &this); err = lookup_one_common(idmap, name, base);
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
ret = lookup_dcache(&this, base, 0); ret = lookup_dcache(name, base, 0);
if (!ret) if (!ret)
ret = lookup_slow(&this, base, 0); ret = lookup_slow(name, base, 0);
return ret; return ret;
} }
EXPORT_SYMBOL(lookup_one_unlocked); EXPORT_SYMBOL(lookup_one_unlocked);
/** /**
* lookup_one_positive_unlocked - filesystem helper to lookup single * lookup_one_positive_unlocked - lookup single pathname component
* pathname component
* @idmap: idmap of the mount the lookup is performed from * @idmap: idmap of the mount the lookup is performed from
* @name: pathname component to lookup * @name: qstr holding pathname component to lookup
* @base: base directory to lookup from * @base: base directory to lookup from
* @len: maximum length @len should be interpreted to
* *
* This helper will yield ERR_PTR(-ENOENT) on negatives. The helper returns * This helper will yield ERR_PTR(-ENOENT) on negatives. The helper returns
* known positive or ERR_PTR(). This is what most of the users want. * known positive or ERR_PTR(). This is what most of the users want.
@ -3033,16 +3028,15 @@ EXPORT_SYMBOL(lookup_one_unlocked);
* time, so callers of lookup_one_unlocked() need to be very careful; pinned * time, so callers of lookup_one_unlocked() need to be very careful; pinned
* positives have >d_inode stable, so this one avoids such problems. * positives have >d_inode stable, so this one avoids such problems.
* *
* Note that this routine is purely a helper for filesystem usage and should * This can be used for in-kernel filesystem clients such as file servers.
* not be called by generic code.
* *
* The helper should be called without i_mutex held. * The helper should be called without i_rwsem held.
*/ */
struct dentry *lookup_one_positive_unlocked(struct mnt_idmap *idmap, struct dentry *lookup_one_positive_unlocked(struct mnt_idmap *idmap,
const char *name, struct qstr *name,
struct dentry *base, int len) struct dentry *base)
{ {
struct dentry *ret = lookup_one_unlocked(idmap, name, base, len); struct dentry *ret = lookup_one_unlocked(idmap, name, base);
if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) { if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) {
dput(ret); dput(ret);
@ -3053,38 +3047,48 @@ struct dentry *lookup_one_positive_unlocked(struct mnt_idmap *idmap,
EXPORT_SYMBOL(lookup_one_positive_unlocked); EXPORT_SYMBOL(lookup_one_positive_unlocked);
/** /**
* lookup_one_len_unlocked - filesystem helper to lookup single pathname component * lookup_noperm_unlocked - filesystem helper to lookup single pathname component
* @name: pathname component to lookup * @name: pathname component to lookup
* @base: base directory to lookup from * @base: base directory to lookup from
* @len: maximum length @len should be interpreted to
* *
* Note that this routine is purely a helper for filesystem usage and should * Note that this routine is purely a helper for filesystem usage and should
* not be called by generic code. * not be called by generic code. It does no permission checking.
* *
* Unlike lookup_one_len, it should be called without the parent * Unlike lookup_noperm, it should be called without the parent
* i_mutex held, and will take the i_mutex itself if necessary. * i_rwsem held, and will take the i_rwsem itself if necessary.
*/ */
struct dentry *lookup_one_len_unlocked(const char *name, struct dentry *lookup_noperm_unlocked(struct qstr *name, struct dentry *base)
struct dentry *base, int len)
{ {
return lookup_one_unlocked(&nop_mnt_idmap, name, base, len); struct dentry *ret;
ret = try_lookup_noperm(name, base);
if (!ret)
ret = lookup_slow(name, base, 0);
return ret;
} }
EXPORT_SYMBOL(lookup_one_len_unlocked); EXPORT_SYMBOL(lookup_noperm_unlocked);
/* /*
* Like lookup_one_len_unlocked(), except that it yields ERR_PTR(-ENOENT) * Like lookup_noperm_unlocked(), except that it yields ERR_PTR(-ENOENT)
* on negatives. Returns known positive or ERR_PTR(); that's what * on negatives. Returns known positive or ERR_PTR(); that's what
* most of the users want. Note that pinned negative with unlocked parent * most of the users want. Note that pinned negative with unlocked parent
* _can_ become positive at any time, so callers of lookup_one_len_unlocked() * _can_ become positive at any time, so callers of lookup_noperm_unlocked()
* need to be very careful; pinned positives have ->d_inode stable, so * need to be very careful; pinned positives have ->d_inode stable, so
* this one avoids such problems. * this one avoids such problems.
*/ */
struct dentry *lookup_positive_unlocked(const char *name, struct dentry *lookup_noperm_positive_unlocked(struct qstr *name,
struct dentry *base, int len) struct dentry *base)
{ {
return lookup_one_positive_unlocked(&nop_mnt_idmap, name, base, len); struct dentry *ret;
ret = lookup_noperm_unlocked(name, base);
if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) {
dput(ret);
ret = ERR_PTR(-ENOENT);
} }
EXPORT_SYMBOL(lookup_positive_unlocked); return ret;
}
EXPORT_SYMBOL(lookup_noperm_positive_unlocked);
#ifdef CONFIG_UNIX98_PTYS #ifdef CONFIG_UNIX98_PTYS
int path_pts(struct path *path) int path_pts(struct path *path)

View File

@ -464,10 +464,9 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
sdentry = NULL; sdentry = NULL;
do { do {
int slen;
dput(sdentry); dput(sdentry);
sillycounter++; sillycounter++;
slen = scnprintf(silly, sizeof(silly), scnprintf(silly, sizeof(silly),
SILLYNAME_PREFIX "%0*llx%0*x", SILLYNAME_PREFIX "%0*llx%0*x",
SILLYNAME_FILEID_LEN, fileid, SILLYNAME_FILEID_LEN, fileid,
SILLYNAME_COUNTER_LEN, sillycounter); SILLYNAME_COUNTER_LEN, sillycounter);
@ -475,7 +474,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
dfprintk(VFS, "NFS: trying to rename %pd to %s\n", dfprintk(VFS, "NFS: trying to rename %pd to %s\n",
dentry, silly); dentry, silly);
sdentry = lookup_one_len(silly, dentry->d_parent, slen); sdentry = lookup_noperm(&QSTR(silly), dentry->d_parent);
/* /*
* N.B. Better to return EBUSY here ... it could be * N.B. Better to return EBUSY here ... it could be
* dangerous to delete the file while it's in use. * dangerous to delete the file while it's in use.

View File

@ -284,7 +284,9 @@ nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
inode_lock_nested(inode, I_MUTEX_PARENT); inode_lock_nested(inode, I_MUTEX_PARENT);
child = lookup_one_len(argp->name, parent, argp->len); child = lookup_one(&nop_mnt_idmap,
&QSTR_LEN(argp->name, argp->len),
parent);
if (IS_ERR(child)) { if (IS_ERR(child)) {
status = nfserrno(PTR_ERR(child)); status = nfserrno(PTR_ERR(child));
goto out; goto out;

View File

@ -1001,7 +1001,9 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
} else } else
dchild = dget(dparent); dchild = dget(dparent);
} else } else
dchild = lookup_positive_unlocked(name, dparent, namlen); dchild = lookup_one_positive_unlocked(&nop_mnt_idmap,
&QSTR_LEN(name, namlen),
dparent);
if (IS_ERR(dchild)) if (IS_ERR(dchild))
return rv; return rv;
if (d_mountpoint(dchild)) if (d_mountpoint(dchild))

View File

@ -266,7 +266,9 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
inode_lock_nested(inode, I_MUTEX_PARENT); inode_lock_nested(inode, I_MUTEX_PARENT);
child = lookup_one_len(open->op_fname, parent, open->op_fnamelen); child = lookup_one(&nop_mnt_idmap,
&QSTR_LEN(open->op_fname, open->op_fnamelen),
parent);
if (IS_ERR(child)) { if (IS_ERR(child)) {
status = nfserrno(PTR_ERR(child)); status = nfserrno(PTR_ERR(child));
goto out; goto out;

View File

@ -218,7 +218,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
/* lock the parent */ /* lock the parent */
inode_lock(d_inode(dir)); inode_lock(d_inode(dir));
dentry = lookup_one_len(dname, dir, HEXDIR_LEN-1); dentry = lookup_one(&nop_mnt_idmap, &QSTR(dname), dir);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
status = PTR_ERR(dentry); status = PTR_ERR(dentry);
goto out_unlock; goto out_unlock;
@ -316,7 +316,8 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
list_for_each_entry_safe(entry, tmp, &ctx.names, list) { list_for_each_entry_safe(entry, tmp, &ctx.names, list) {
if (!status) { if (!status) {
struct dentry *dentry; struct dentry *dentry;
dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1); dentry = lookup_one(&nop_mnt_idmap,
&QSTR(entry->name), dir);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
status = PTR_ERR(dentry); status = PTR_ERR(dentry);
break; break;
@ -339,16 +340,16 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
} }
static int static int
nfsd4_unlink_clid_dir(char *name, int namlen, struct nfsd_net *nn) nfsd4_unlink_clid_dir(char *name, struct nfsd_net *nn)
{ {
struct dentry *dir, *dentry; struct dentry *dir, *dentry;
int status; int status;
dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); dprintk("NFSD: nfsd4_unlink_clid_dir. name %s\n", name);
dir = nn->rec_file->f_path.dentry; dir = nn->rec_file->f_path.dentry;
inode_lock_nested(d_inode(dir), I_MUTEX_PARENT); inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
dentry = lookup_one_len(name, dir, namlen); dentry = lookup_one(&nop_mnt_idmap, &QSTR(name), dir);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
status = PTR_ERR(dentry); status = PTR_ERR(dentry);
goto out_unlock; goto out_unlock;
@ -408,7 +409,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
if (status < 0) if (status < 0)
goto out_drop_write; goto out_drop_write;
status = nfsd4_unlink_clid_dir(dname, HEXDIR_LEN-1, nn); status = nfsd4_unlink_clid_dir(dname, nn);
nfs4_reset_creds(original_cred); nfs4_reset_creds(original_cred);
if (status == 0) { if (status == 0) {
vfs_fsync(nn->rec_file, 0); vfs_fsync(nn->rec_file, 0);

View File

@ -3812,7 +3812,9 @@ nfsd4_encode_entry4_fattr(struct nfsd4_readdir *cd, const char *name,
__be32 nfserr; __be32 nfserr;
int ignore_crossmnt = 0; int ignore_crossmnt = 0;
dentry = lookup_positive_unlocked(name, cd->rd_fhp->fh_dentry, namlen); dentry = lookup_one_positive_unlocked(&nop_mnt_idmap,
&QSTR_LEN(name, namlen),
cd->rd_fhp->fh_dentry);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
return nfserrno(PTR_ERR(dentry)); return nfserrno(PTR_ERR(dentry));

View File

@ -312,7 +312,8 @@ nfsd_proc_create(struct svc_rqst *rqstp)
} }
inode_lock_nested(dirfhp->fh_dentry->d_inode, I_MUTEX_PARENT); inode_lock_nested(dirfhp->fh_dentry->d_inode, I_MUTEX_PARENT);
dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len); dchild = lookup_one(&nop_mnt_idmap, &QSTR_LEN(argp->name, argp->len),
dirfhp->fh_dentry);
if (IS_ERR(dchild)) { if (IS_ERR(dchild)) {
resp->status = nfserrno(PTR_ERR(dchild)); resp->status = nfserrno(PTR_ERR(dchild));
goto out_unlock; goto out_unlock;

View File

@ -264,7 +264,8 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
goto out_nfserr; goto out_nfserr;
} }
} else { } else {
dentry = lookup_one_len_unlocked(name, dparent, len); dentry = lookup_one_unlocked(&nop_mnt_idmap,
&QSTR_LEN(name, len), dparent);
host_err = PTR_ERR(dentry); host_err = PTR_ERR(dentry);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
goto out_nfserr; goto out_nfserr;
@ -922,7 +923,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
* directories, but we never have and it doesn't seem to have * directories, but we never have and it doesn't seem to have
* caused anyone a problem. If we were to change this, note * caused anyone a problem. If we were to change this, note
* also that our filldir callbacks would need a variant of * also that our filldir callbacks would need a variant of
* lookup_one_len that doesn't check permissions. * lookup_one_positive_unlocked() that doesn't check permissions.
*/ */
if (type == S_IFREG) if (type == S_IFREG)
may_flags |= NFSD_MAY_OWNER_OVERRIDE; may_flags |= NFSD_MAY_OWNER_OVERRIDE;
@ -1554,7 +1555,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
return nfserrno(host_err); return nfserrno(host_err);
inode_lock_nested(dentry->d_inode, I_MUTEX_PARENT); inode_lock_nested(dentry->d_inode, I_MUTEX_PARENT);
dchild = lookup_one_len(fname, dentry, flen); dchild = lookup_one(&nop_mnt_idmap, &QSTR_LEN(fname, flen), dentry);
host_err = PTR_ERR(dchild); host_err = PTR_ERR(dchild);
if (IS_ERR(dchild)) { if (IS_ERR(dchild)) {
err = nfserrno(host_err); err = nfserrno(host_err);
@ -1659,7 +1660,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
dentry = fhp->fh_dentry; dentry = fhp->fh_dentry;
inode_lock_nested(dentry->d_inode, I_MUTEX_PARENT); inode_lock_nested(dentry->d_inode, I_MUTEX_PARENT);
dnew = lookup_one_len(fname, dentry, flen); dnew = lookup_one(&nop_mnt_idmap, &QSTR_LEN(fname, flen), dentry);
if (IS_ERR(dnew)) { if (IS_ERR(dnew)) {
err = nfserrno(PTR_ERR(dnew)); err = nfserrno(PTR_ERR(dnew));
inode_unlock(dentry->d_inode); inode_unlock(dentry->d_inode);
@ -1734,7 +1735,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
dirp = d_inode(ddir); dirp = d_inode(ddir);
inode_lock_nested(dirp, I_MUTEX_PARENT); inode_lock_nested(dirp, I_MUTEX_PARENT);
dnew = lookup_one_len(name, ddir, len); dnew = lookup_one(&nop_mnt_idmap, &QSTR_LEN(name, len), ddir);
if (IS_ERR(dnew)) { if (IS_ERR(dnew)) {
host_err = PTR_ERR(dnew); host_err = PTR_ERR(dnew);
goto out_unlock; goto out_unlock;
@ -1867,7 +1868,7 @@ retry:
if (err != nfs_ok) if (err != nfs_ok)
goto out_unlock; goto out_unlock;
odentry = lookup_one_len(fname, fdentry, flen); odentry = lookup_one(&nop_mnt_idmap, &QSTR_LEN(fname, flen), fdentry);
host_err = PTR_ERR(odentry); host_err = PTR_ERR(odentry);
if (IS_ERR(odentry)) if (IS_ERR(odentry))
goto out_nfserr; goto out_nfserr;
@ -1880,7 +1881,7 @@ retry:
goto out_dput_old; goto out_dput_old;
type = d_inode(odentry)->i_mode & S_IFMT; type = d_inode(odentry)->i_mode & S_IFMT;
ndentry = lookup_one_len(tname, tdentry, tlen); ndentry = lookup_one(&nop_mnt_idmap, &QSTR_LEN(tname, tlen), tdentry);
host_err = PTR_ERR(ndentry); host_err = PTR_ERR(ndentry);
if (IS_ERR(ndentry)) if (IS_ERR(ndentry))
goto out_dput_old; goto out_dput_old;
@ -1998,7 +1999,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
dirp = d_inode(dentry); dirp = d_inode(dentry);
inode_lock_nested(dirp, I_MUTEX_PARENT); inode_lock_nested(dirp, I_MUTEX_PARENT);
rdentry = lookup_one_len(fname, dentry, flen); rdentry = lookup_one(&nop_mnt_idmap, &QSTR_LEN(fname, flen), dentry);
host_err = PTR_ERR(rdentry); host_err = PTR_ERR(rdentry);
if (IS_ERR(rdentry)) if (IS_ERR(rdentry))
goto out_unlock; goto out_unlock;

View File

@ -385,11 +385,9 @@ static struct dentry *ovl_lookup_real_one(struct dentry *connected,
*/ */
take_dentry_name_snapshot(&name, real); take_dentry_name_snapshot(&name, real);
/* /*
* No idmap handling here: it's an internal lookup. Could skip * No idmap handling here: it's an internal lookup.
* permission checking altogether, but for now just use non-idmap
* transformed ids.
*/ */
this = lookup_one_len(name.name.name, connected, name.name.len); this = lookup_noperm(&name.name, connected);
release_dentry_name_snapshot(&name); release_dentry_name_snapshot(&name);
err = PTR_ERR(this); err = PTR_ERR(this);
if (IS_ERR(this)) { if (IS_ERR(this)) {

View File

@ -205,8 +205,8 @@ static struct dentry *ovl_lookup_positive_unlocked(struct ovl_lookup_data *d,
struct dentry *base, int len, struct dentry *base, int len,
bool drop_negative) bool drop_negative)
{ {
struct dentry *ret = lookup_one_unlocked(mnt_idmap(d->layer->mnt), name, struct dentry *ret = lookup_one_unlocked(mnt_idmap(d->layer->mnt),
base, len); &QSTR_LEN(name, len), base);
if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) { if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) {
if (drop_negative && ret->d_lockref.count == 1) { if (drop_negative && ret->d_lockref.count == 1) {
@ -757,7 +757,7 @@ struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh)
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
index = lookup_positive_unlocked(name.name, ofs->workdir, name.len); index = lookup_noperm_positive_unlocked(&name, ofs->workdir);
kfree(name.name); kfree(name.name);
if (IS_ERR(index)) { if (IS_ERR(index)) {
if (PTR_ERR(index) == -ENOENT) if (PTR_ERR(index) == -ENOENT)
@ -789,8 +789,8 @@ struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper,
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
index = lookup_one_positive_unlocked(ovl_upper_mnt_idmap(ofs), name.name, index = lookup_one_positive_unlocked(ovl_upper_mnt_idmap(ofs), &name,
ofs->workdir, name.len); ofs->workdir);
if (IS_ERR(index)) { if (IS_ERR(index)) {
err = PTR_ERR(index); err = PTR_ERR(index);
if (err == -ENOENT) { if (err == -ENOENT) {
@ -1371,7 +1371,7 @@ out:
bool ovl_lower_positive(struct dentry *dentry) bool ovl_lower_positive(struct dentry *dentry)
{ {
struct ovl_entry *poe = OVL_E(dentry->d_parent); struct ovl_entry *poe = OVL_E(dentry->d_parent);
const struct qstr *name = &dentry->d_name; struct qstr *name = &dentry->d_name;
const struct cred *old_cred; const struct cred *old_cred;
unsigned int i; unsigned int i;
bool positive = false; bool positive = false;
@ -1396,7 +1396,7 @@ bool ovl_lower_positive(struct dentry *dentry)
this = lookup_one_positive_unlocked( this = lookup_one_positive_unlocked(
mnt_idmap(parentpath->layer->mnt), mnt_idmap(parentpath->layer->mnt),
name->name, parentpath->dentry, name->len); name, parentpath->dentry);
if (IS_ERR(this)) { if (IS_ERR(this)) {
switch (PTR_ERR(this)) { switch (PTR_ERR(this)) {
case -ENOENT: case -ENOENT:

View File

@ -402,7 +402,7 @@ static inline struct dentry *ovl_lookup_upper(struct ovl_fs *ofs,
const char *name, const char *name,
struct dentry *base, int len) struct dentry *base, int len)
{ {
return lookup_one(ovl_upper_mnt_idmap(ofs), name, base, len); return lookup_one(ovl_upper_mnt_idmap(ofs), &QSTR_LEN(name, len), base);
} }
static inline bool ovl_open_flags_need_copy_up(int flags) static inline bool ovl_open_flags_need_copy_up(int flags)

View File

@ -271,7 +271,6 @@ static bool ovl_fill_merge(struct dir_context *ctx, const char *name,
static int ovl_check_whiteouts(const struct path *path, struct ovl_readdir_data *rdd) static int ovl_check_whiteouts(const struct path *path, struct ovl_readdir_data *rdd)
{ {
int err; int err;
struct ovl_cache_entry *p;
struct dentry *dentry, *dir = path->dentry; struct dentry *dentry, *dir = path->dentry;
const struct cred *old_cred; const struct cred *old_cred;
@ -280,9 +279,11 @@ static int ovl_check_whiteouts(const struct path *path, struct ovl_readdir_data
err = down_write_killable(&dir->d_inode->i_rwsem); err = down_write_killable(&dir->d_inode->i_rwsem);
if (!err) { if (!err) {
while (rdd->first_maybe_whiteout) { while (rdd->first_maybe_whiteout) {
p = rdd->first_maybe_whiteout; struct ovl_cache_entry *p =
rdd->first_maybe_whiteout;
rdd->first_maybe_whiteout = p->next_maybe_whiteout; rdd->first_maybe_whiteout = p->next_maybe_whiteout;
dentry = lookup_one(mnt_idmap(path->mnt), p->name, dir, p->len); dentry = lookup_one(mnt_idmap(path->mnt),
&QSTR_LEN(p->name, p->len), dir);
if (!IS_ERR(dentry)) { if (!IS_ERR(dentry)) {
p->is_whiteout = ovl_is_whiteout(dentry); p->is_whiteout = ovl_is_whiteout(dentry);
dput(dentry); dput(dentry);
@ -492,7 +493,7 @@ static int ovl_cache_update(const struct path *path, struct ovl_cache_entry *p,
} }
} }
/* This checks also for xwhiteouts */ /* This checks also for xwhiteouts */
this = lookup_one(mnt_idmap(path->mnt), p->name, dir, p->len); this = lookup_one(mnt_idmap(path->mnt), &QSTR_LEN(p->name, p->len), dir);
if (IS_ERR_OR_NULL(this) || !this->d_inode) { if (IS_ERR_OR_NULL(this) || !this->d_inode) {
/* Mark a stale entry */ /* Mark a stale entry */
p->is_whiteout = true; p->is_whiteout = true;

View File

@ -2121,7 +2121,7 @@ bool proc_fill_cache(struct file *file, struct dir_context *ctx,
unsigned type = DT_UNKNOWN; unsigned type = DT_UNKNOWN;
ino_t ino = 1; ino_t ino = 1;
child = d_hash_and_lookup(dir, &qname); child = try_lookup_noperm(&qname, dir);
if (!child) { if (!child) {
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
child = d_alloc_parallel(dir, &qname, &wq); child = d_alloc_parallel(dir, &qname, &wq);

View File

@ -2560,7 +2560,7 @@ int dquot_quota_on_mount(struct super_block *sb, char *qf_name,
struct dentry *dentry; struct dentry *dentry;
int error; int error;
dentry = lookup_positive_unlocked(qf_name, sb->s_root, strlen(qf_name)); dentry = lookup_noperm_positive_unlocked(&QSTR(qf_name), sb->s_root);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
return PTR_ERR(dentry); return PTR_ERR(dentry);

View File

@ -102,7 +102,8 @@ path_to_dentry(struct cifs_sb_info *cifs_sb, const char *path)
while (*s && *s != sep) while (*s && *s != sep)
s++; s++;
child = lookup_positive_unlocked(p, dentry, s - p); child = lookup_noperm_positive_unlocked(&QSTR_LEN(p, s - p),
dentry);
dput(dentry); dput(dentry);
dentry = child; dentry = child;
} while (!IS_ERR(dentry)); } while (!IS_ERR(dentry));
@ -201,7 +202,7 @@ replay_again:
spin_unlock(&cfids->cfid_list_lock); spin_unlock(&cfids->cfid_list_lock);
/* /*
* Skip any prefix paths in @path as lookup_positive_unlocked() ends up * Skip any prefix paths in @path as lookup_noperm_positive_unlocked() ends up
* calling ->lookup() which already adds those through * calling ->lookup() which already adds those through
* build_path_from_dentry(). Also, do it earlier as we might reconnect * build_path_from_dentry(). Also, do it earlier as we might reconnect
* below when trying to send compounded request and then potentially * below when trying to send compounded request and then potentially

View File

@ -929,7 +929,8 @@ cifs_get_root(struct smb3_fs_context *ctx, struct super_block *sb)
while (*s && *s != sep) while (*s && *s != sep)
s++; s++;
child = lookup_positive_unlocked(p, dentry, s - p); child = lookup_noperm_positive_unlocked(&QSTR_LEN(p, s - p),
dentry);
dput(dentry); dput(dentry);
dentry = child; dentry = child;
} while (!IS_ERR(dentry)); } while (!IS_ERR(dentry));

View File

@ -9,6 +9,7 @@
* *
*/ */
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/namei.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/stat.h> #include <linux/stat.h>
@ -78,7 +79,7 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
cifs_dbg(FYI, "%s: for %s\n", __func__, name->name); cifs_dbg(FYI, "%s: for %s\n", __func__, name->name);
dentry = d_hash_and_lookup(parent, name); dentry = try_lookup_noperm(name, parent);
if (!dentry) { if (!dentry) {
/* /*
* If we know that the inode will need to be revalidated * If we know that the inode will need to be revalidated

View File

@ -4120,9 +4120,10 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv)
return -EINVAL; return -EINVAL;
lock_dir(priv->dir_fp); lock_dir(priv->dir_fp);
dent = lookup_one(idmap, priv->d_info->name, dent = lookup_one(idmap,
priv->dir_fp->filp->f_path.dentry, &QSTR_LEN(priv->d_info->name,
priv->d_info->name_len); priv->d_info->name_len),
priv->dir_fp->filp->f_path.dentry);
unlock_dir(priv->dir_fp); unlock_dir(priv->dir_fp);
if (IS_ERR(dent)) { if (IS_ERR(dent)) {

View File

@ -555,7 +555,7 @@ struct dentry *tracefs_start_creating(const char *name, struct dentry *parent)
if (unlikely(IS_DEADDIR(d_inode(parent)))) if (unlikely(IS_DEADDIR(d_inode(parent))))
dentry = ERR_PTR(-ENOENT); dentry = ERR_PTR(-ENOENT);
else else
dentry = lookup_one_len(name, parent, strlen(name)); dentry = lookup_noperm(&QSTR(name), parent);
if (!IS_ERR(dentry) && d_inode(dentry)) { if (!IS_ERR(dentry) && d_inode(dentry)) {
dput(dentry); dput(dentry);
dentry = ERR_PTR(-EEXIST); dentry = ERR_PTR(-EEXIST);

View File

@ -153,8 +153,7 @@ xrep_orphanage_create(
/* Try to find the orphanage directory. */ /* Try to find the orphanage directory. */
inode_lock_nested(root_inode, I_MUTEX_PARENT); inode_lock_nested(root_inode, I_MUTEX_PARENT);
orphanage_dentry = lookup_one_len(ORPHANAGE, root_dentry, orphanage_dentry = lookup_noperm(&QSTR(ORPHANAGE), root_dentry);
strlen(ORPHANAGE));
if (IS_ERR(orphanage_dentry)) { if (IS_ERR(orphanage_dentry)) {
error = PTR_ERR(orphanage_dentry); error = PTR_ERR(orphanage_dentry);
goto out_unlock_root; goto out_unlock_root;
@ -445,7 +444,7 @@ xrep_adoption_check_dcache(
if (!d_orphanage) if (!d_orphanage)
return 0; return 0;
d_child = d_hash_and_lookup(d_orphanage, &qname); d_child = try_lookup_noperm(&qname, d_orphanage);
if (d_child) { if (d_child) {
trace_xrep_adoption_check_child(sc->mp, d_child); trace_xrep_adoption_check_child(sc->mp, d_child);
@ -482,7 +481,7 @@ xrep_adoption_zap_dcache(
if (!d_orphanage) if (!d_orphanage)
return; return;
d_child = d_hash_and_lookup(d_orphanage, &qname); d_child = try_lookup_noperm(&qname, d_orphanage);
while (d_child != NULL) { while (d_child != NULL) {
trace_xrep_adoption_invalidate_child(sc->mp, d_child); trace_xrep_adoption_invalidate_child(sc->mp, d_child);

View File

@ -57,7 +57,8 @@ struct qstr {
}; };
#define QSTR_INIT(n,l) { { { .len = l } }, .name = n } #define QSTR_INIT(n,l) { { { .len = l } }, .name = n }
#define QSTR(n) (struct qstr)QSTR_INIT(n, strlen(n)) #define QSTR_LEN(n,l) (struct qstr)QSTR_INIT(n,l)
#define QSTR(n) QSTR_LEN(n, strlen(n))
extern const struct qstr empty_name; extern const struct qstr empty_name;
extern const struct qstr slash_name; extern const struct qstr slash_name;
@ -281,7 +282,6 @@ extern void d_exchange(struct dentry *, struct dentry *);
extern struct dentry *d_ancestor(struct dentry *, struct dentry *); extern struct dentry *d_ancestor(struct dentry *, struct dentry *);
extern struct dentry *d_lookup(const struct dentry *, const struct qstr *); extern struct dentry *d_lookup(const struct dentry *, const struct qstr *);
extern struct dentry *d_hash_and_lookup(struct dentry *, struct qstr *);
static inline unsigned d_count(const struct dentry *dentry) static inline unsigned d_count(const struct dentry *dentry)
{ {

View File

@ -70,17 +70,16 @@ int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
int vfs_path_lookup(struct dentry *, struct vfsmount *, const char *, int vfs_path_lookup(struct dentry *, struct vfsmount *, const char *,
unsigned int, struct path *); unsigned int, struct path *);
extern struct dentry *try_lookup_one_len(const char *, struct dentry *, int); extern struct dentry *try_lookup_noperm(struct qstr *, struct dentry *);
extern struct dentry *lookup_one_len(const char *, struct dentry *, int); extern struct dentry *lookup_noperm(struct qstr *, struct dentry *);
extern struct dentry *lookup_one_len_unlocked(const char *, struct dentry *, int); extern struct dentry *lookup_noperm_unlocked(struct qstr *, struct dentry *);
extern struct dentry *lookup_positive_unlocked(const char *, struct dentry *, int); extern struct dentry *lookup_noperm_positive_unlocked(struct qstr *, struct dentry *);
struct dentry *lookup_one(struct mnt_idmap *, const char *, struct dentry *, int); struct dentry *lookup_one(struct mnt_idmap *, struct qstr *, struct dentry *);
struct dentry *lookup_one_unlocked(struct mnt_idmap *idmap, struct dentry *lookup_one_unlocked(struct mnt_idmap *idmap,
const char *name, struct dentry *base, struct qstr *name, struct dentry *base);
int len);
struct dentry *lookup_one_positive_unlocked(struct mnt_idmap *idmap, struct dentry *lookup_one_positive_unlocked(struct mnt_idmap *idmap,
const char *name, struct qstr *name,
struct dentry *base, int len); struct dentry *base);
extern int follow_down_one(struct path *); extern int follow_down_one(struct path *);
extern int follow_down(struct path *path, unsigned int flags); extern int follow_down(struct path *path, unsigned int flags);

View File

@ -913,7 +913,7 @@ static int do_mq_open(const char __user *u_name, int oflag, umode_t mode,
ro = mnt_want_write(mnt); /* we'll drop it in any case */ ro = mnt_want_write(mnt); /* we'll drop it in any case */
inode_lock(d_inode(root)); inode_lock(d_inode(root));
path.dentry = lookup_one_len(name->name, root, strlen(name->name)); path.dentry = lookup_noperm(&QSTR(name->name), root);
if (IS_ERR(path.dentry)) { if (IS_ERR(path.dentry)) {
error = PTR_ERR(path.dentry); error = PTR_ERR(path.dentry);
goto out_putfd; goto out_putfd;
@ -969,8 +969,7 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
if (err) if (err)
goto out_name; goto out_name;
inode_lock_nested(d_inode(mnt->mnt_root), I_MUTEX_PARENT); inode_lock_nested(d_inode(mnt->mnt_root), I_MUTEX_PARENT);
dentry = lookup_one_len(name->name, mnt->mnt_root, dentry = lookup_noperm(&QSTR(name->name), mnt->mnt_root);
strlen(name->name));
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
err = PTR_ERR(dentry); err = PTR_ERR(dentry);
goto out_unlock; goto out_unlock;

View File

@ -421,7 +421,7 @@ static int bpf_iter_link_pin_kernel(struct dentry *parent,
int ret; int ret;
inode_lock(parent->d_inode); inode_lock(parent->d_inode);
dentry = lookup_one_len(name, parent, strlen(name)); dentry = lookup_noperm(&QSTR(name), parent);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
inode_unlock(parent->d_inode); inode_unlock(parent->d_inode);
return PTR_ERR(dentry); return PTR_ERR(dentry);

View File

@ -631,7 +631,7 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent,
const char *name) const char *name)
{ {
struct qstr q = QSTR(name); struct qstr q = QSTR(name);
struct dentry *dentry = d_hash_and_lookup(parent, &q); struct dentry *dentry = try_lookup_noperm(&q, parent);
if (!dentry) { if (!dentry) {
dentry = d_alloc(parent, &q); dentry = d_alloc(parent, &q);
if (!dentry) if (!dentry)
@ -658,7 +658,7 @@ static void __rpc_depopulate(struct dentry *parent,
for (i = start; i < eof; i++) { for (i = start; i < eof; i++) {
name.name = files[i].name; name.name = files[i].name;
name.len = strlen(files[i].name); name.len = strlen(files[i].name);
dentry = d_hash_and_lookup(parent, &name); dentry = try_lookup_noperm(&name, parent);
if (dentry == NULL) if (dentry == NULL)
continue; continue;
@ -1190,7 +1190,7 @@ static const struct rpc_filelist files[] = {
struct dentry *rpc_d_lookup_sb(const struct super_block *sb, struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
const unsigned char *dir_name) const unsigned char *dir_name)
{ {
return d_hash_and_lookup(sb->s_root, &QSTR(dir_name)); return try_lookup_noperm(&QSTR(dir_name), sb->s_root);
} }
EXPORT_SYMBOL_GPL(rpc_d_lookup_sb); EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
@ -1301,7 +1301,7 @@ rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data)
struct dentry *pipe_dentry = NULL; struct dentry *pipe_dentry = NULL;
/* We should never get this far if "gssd" doesn't exist */ /* We should never get this far if "gssd" doesn't exist */
gssd_dentry = d_hash_and_lookup(root, &QSTR(files[RPCAUTH_gssd].name)); gssd_dentry = try_lookup_noperm(&QSTR(files[RPCAUTH_gssd].name), root);
if (!gssd_dentry) if (!gssd_dentry)
return ERR_PTR(-ENOENT); return ERR_PTR(-ENOENT);
@ -1311,8 +1311,8 @@ rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data)
goto out; goto out;
} }
clnt_dentry = d_hash_and_lookup(gssd_dentry, clnt_dentry = try_lookup_noperm(&QSTR(gssd_dummy_clnt_dir[0].name),
&QSTR(gssd_dummy_clnt_dir[0].name)); gssd_dentry);
if (!clnt_dentry) { if (!clnt_dentry) {
__rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1); __rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1);
pipe_dentry = ERR_PTR(-ENOENT); pipe_dentry = ERR_PTR(-ENOENT);

View File

@ -283,7 +283,7 @@ static struct dentry *aafs_create(const char *name, umode_t mode,
dir = d_inode(parent); dir = d_inode(parent);
inode_lock(dir); inode_lock(dir);
dentry = lookup_one_len(name, parent, strlen(name)); dentry = lookup_noperm(&QSTR(name), parent);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
error = PTR_ERR(dentry); error = PTR_ERR(dentry);
goto fail_lock; goto fail_lock;
@ -2551,7 +2551,7 @@ static int aa_mk_null_file(struct dentry *parent)
return error; return error;
inode_lock(d_inode(parent)); inode_lock(d_inode(parent));
dentry = lookup_one_len(NULL_FILE_NAME, parent, strlen(NULL_FILE_NAME)); dentry = lookup_noperm(&QSTR(NULL_FILE_NAME), parent);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
error = PTR_ERR(dentry); error = PTR_ERR(dentry);
goto out; goto out;

View File

@ -128,7 +128,7 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode,
dir = d_inode(parent); dir = d_inode(parent);
inode_lock(dir); inode_lock(dir);
dentry = lookup_one_len(name, parent, strlen(name)); dentry = lookup_noperm(&QSTR(name), parent);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
goto out; goto out;

View File

@ -2158,8 +2158,8 @@ static int __init init_sel_fs(void)
return err; return err;
} }
selinux_null.dentry = d_hash_and_lookup(selinux_null.mnt->mnt_root, selinux_null.dentry = try_lookup_noperm(&null_name,
&null_name); selinux_null.mnt->mnt_root);
if (IS_ERR(selinux_null.dentry)) { if (IS_ERR(selinux_null.dentry)) {
pr_err("selinuxfs: could not lookup null!\n"); pr_err("selinuxfs: could not lookup null!\n");
err = PTR_ERR(selinux_null.dentry); err = PTR_ERR(selinux_null.dentry);