Add a new LOOKUP_IN_INIT flag that causes the lookup to be performed relative to userspace init's root or working directory. This will be used to force kthreads to be isolated in nullfs and explicitly opt-in to lookup stuff in init's filesystem state. Signed-off-by: Christian Brauner --- fs/namei.c | 17 ++++++++++++++--- include/linux/namei.h | 3 ++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 58f715f7657e..dd2710d5f5df 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1099,7 +1099,12 @@ static int complete_walk(struct nameidata *nd) static int set_root(struct nameidata *nd) { - struct fs_struct *fs = current->fs; + struct fs_struct *fs; + + if (nd->flags & LOOKUP_IN_INIT) + fs = &init_fs; + else + fs = current->fs; /* * Jumping to the real root in a scoped-lookup is a BUG in namei, but we @@ -2716,8 +2721,14 @@ static const char *path_init(struct nameidata *nd, unsigned flags) /* Relative pathname -- get the starting-point it is relative to. */ if (nd->dfd == AT_FDCWD) { + struct fs_struct *fs; + + if (nd->flags & LOOKUP_IN_INIT) + fs = &init_fs; + else + fs = current->fs; + if (flags & LOOKUP_RCU) { - struct fs_struct *fs = current->fs; unsigned seq; do { @@ -2727,7 +2738,7 @@ static const char *path_init(struct nameidata *nd, unsigned flags) nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); } while (read_seqretry(&fs->seq, seq)); } else { - get_fs_pwd(current->fs, &nd->path); + get_fs_pwd(fs, &nd->path); nd->inode = nd->path.dentry->d_inode; } } else { diff --git a/include/linux/namei.h b/include/linux/namei.h index 58600cf234bc..072533ec367b 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -46,9 +46,10 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT}; #define LOOKUP_NO_XDEV BIT(26) /* No mountpoint crossing. */ #define LOOKUP_BENEATH BIT(27) /* No escaping from starting point. */ #define LOOKUP_IN_ROOT BIT(28) /* Treat dirfd as fs root. */ +#define LOOKUP_IN_INIT BIT(29) /* Lookup in init's namespace. */ /* LOOKUP_* flags which do scope-related checks based on the dirfd. */ #define LOOKUP_IS_SCOPED (LOOKUP_BENEATH | LOOKUP_IN_ROOT) -/* 3 spare bits for scoping */ +/* 2 spare bits for scoping */ extern int path_pts(struct path *path); -- 2.47.3