Skip to content

Commit 76a53de

Browse files
neilbrownbrauner
authored andcommitted
VFS/audit: introduce kern_path_parent() for audit
audit_alloc_mark() and audit_get_nd() both need to perform a path lookup getting the parent dentry (which must exist) and the final target (following a LAST_NORM name) which sometimes doesn't need to exist. They don't need the parent to be locked, but use kern_path_locked() or kern_path_locked_negative() anyway. This is somewhat misleading to the casual reader. This patch introduces a more targeted function, kern_path_parent(), which returns not holding locks. On success the "path" will be set to the parent, which must be found, and the return value is the dentry of the target, which might be negative. This will clear the way to rename kern_path_locked() which is otherwise only used to prepare for removing something. It also allows us to remove kern_path_locked_negative(), which is transformed into the new kern_path_parent(). Signed-off-by: NeilBrown <neil@brown.name> Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent d7fb2c4 commit 76a53de

4 files changed

Lines changed: 25 additions & 14 deletions

File tree

fs/namei.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2781,7 +2781,20 @@ static struct dentry *__kern_path_locked(int dfd, struct filename *name, struct
27812781
return d;
27822782
}
27832783

2784-
struct dentry *kern_path_locked_negative(const char *name, struct path *path)
2784+
/**
2785+
* kern_path_parent: lookup path returning parent and target
2786+
* @name: path name
2787+
* @path: path to store parent in
2788+
*
2789+
* The path @name should end with a normal component, not "." or ".." or "/".
2790+
* A lookup is performed and if successful the parent information
2791+
* is store in @parent and the dentry is returned.
2792+
*
2793+
* The dentry maybe negative, the parent will be positive.
2794+
*
2795+
* Returns: dentry or error.
2796+
*/
2797+
struct dentry *kern_path_parent(const char *name, struct path *path)
27852798
{
27862799
struct path parent_path __free(path_put) = {};
27872800
struct filename *filename __free(putname) = getname_kernel(name);
@@ -2794,12 +2807,10 @@ struct dentry *kern_path_locked_negative(const char *name, struct path *path)
27942807
return ERR_PTR(error);
27952808
if (unlikely(type != LAST_NORM))
27962809
return ERR_PTR(-EINVAL);
2797-
inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
2798-
d = lookup_one_qstr_excl(&last, parent_path.dentry, LOOKUP_CREATE);
2799-
if (IS_ERR(d)) {
2800-
inode_unlock(parent_path.dentry->d_inode);
2810+
2811+
d = lookup_noperm_unlocked(&last, parent_path.dentry);
2812+
if (IS_ERR(d))
28012813
return d;
2802-
}
28032814
path->dentry = no_free_ptr(parent_path.dentry);
28042815
path->mnt = no_free_ptr(parent_path.mnt);
28052816
return d;

include/linux/namei.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ struct dentry *lookup_one_qstr_excl(const struct qstr *name,
5757
struct dentry *base,
5858
unsigned int flags);
5959
extern int kern_path(const char *, unsigned, struct path *);
60+
struct dentry *kern_path_parent(const char *name, struct path *parent);
6061

6162
extern struct dentry *kern_path_create(int, const char *, struct path *, unsigned int);
6263
extern struct dentry *user_path_create(int, const char __user *, struct path *, unsigned int);
6364
extern void done_path_create(struct path *, struct dentry *);
6465
extern struct dentry *kern_path_locked(const char *, struct path *);
65-
extern struct dentry *kern_path_locked_negative(const char *, struct path *);
6666
extern struct dentry *user_path_locked_at(int , const char __user *, struct path *);
6767
int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
6868
struct path *parent, struct qstr *last, int *type,

kernel/audit_fsnotify.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,18 @@ struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pa
7676
struct audit_fsnotify_mark *audit_mark;
7777
struct path path;
7878
struct dentry *dentry;
79-
struct inode *inode;
8079
int ret;
8180

8281
if (pathname[0] != '/' || pathname[len-1] == '/')
8382
return ERR_PTR(-EINVAL);
8483

85-
dentry = kern_path_locked(pathname, &path);
84+
dentry = kern_path_parent(pathname, &path);
8685
if (IS_ERR(dentry))
8786
return ERR_CAST(dentry); /* returning an error */
88-
inode = path.dentry->d_inode;
89-
inode_unlock(inode);
87+
if (d_really_is_negative(dentry)) {
88+
audit_mark = ERR_PTR(-ENOENT);
89+
goto out;
90+
}
9091

9192
audit_mark = kzalloc(sizeof(*audit_mark), GFP_KERNEL);
9293
if (unlikely(!audit_mark)) {
@@ -100,7 +101,7 @@ struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pa
100101
audit_update_mark(audit_mark, dentry->d_inode);
101102
audit_mark->rule = krule;
102103

103-
ret = fsnotify_add_inode_mark(&audit_mark->mark, inode, 0);
104+
ret = fsnotify_add_inode_mark(&audit_mark->mark, path.dentry->d_inode, 0);
104105
if (ret < 0) {
105106
audit_mark->path = NULL;
106107
fsnotify_put_mark(&audit_mark->mark);

kernel/audit_watch.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ static int audit_get_nd(struct audit_watch *watch, struct path *parent)
349349
{
350350
struct dentry *d;
351351

352-
d = kern_path_locked_negative(watch->path, parent);
352+
d = kern_path_parent(watch->path, parent);
353353
if (IS_ERR(d))
354354
return PTR_ERR(d);
355355

@@ -359,7 +359,6 @@ static int audit_get_nd(struct audit_watch *watch, struct path *parent)
359359
watch->ino = d_backing_inode(d)->i_ino;
360360
}
361361

362-
inode_unlock(d_backing_inode(parent->dentry));
363362
dput(d);
364363
return 0;
365364
}

0 commit comments

Comments
 (0)