Messages in this thread Patch in this message | | | Subject | [PATCH 6/9] Allow fs syscall dfd arguments to take a container fd | From | David Howells <> | Date | Mon, 22 May 2017 17:23:17 +0100 |
| |
Some filesystem system calls, such as mkdirat(), take a 'directory fd' to specify the pathwalk origin. This takes either AT_FDCWD or a file descriptor that refers to an open directory.
Make it possible to supply a container fd, as obtained from container_create(), instead thereby specifying the container's root as the origin. This performs the filesystem operation into the container's mount namespace. For example:
int cfd = container_create("fred", CONTAINER_NEW_MNT_NS, 0); mkdirat(cfd, "/fred", 0755);
A better way to do this might be to temporarily override current->fs and current->nsproxy, but this requires splitting those fields so that procfs doesn't see the override.
A sequence number and lock are available to protect the root pointer in case container_chroot() and/or container_pivot_root() are implemented.
Signed-off-by: David Howells <dhowells@redhat.com> ---
fs/namei.c | 52 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 14 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c index 0d35760fee00..2f0310a39e60 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2208,23 +2208,47 @@ static const char *path_init(struct nameidata *nd, unsigned flags) if (!f.file) return ERR_PTR(-EBADF); - dentry = f.file->f_path.dentry; + if (is_container_file(f.file)) { + struct container *c = f.file->private_data; + unsigned seq; - if (*s) { - if (!d_can_lookup(dentry)) { - fdput(f); - return ERR_PTR(-ENOTDIR); + if (!*s) + return ERR_PTR(-EINVAL); + + if (flags & LOOKUP_RCU) { + rcu_read_lock(); + do { + seq = read_seqcount_begin(&c->seq); + nd->path = c->root; + nd->inode = nd->path.dentry->d_inode; + nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); + } while (read_seqcount_retry(&c->seq, seq)); + } else { + spin_lock(&c->lock); + nd->path = c->root; + path_get(&nd->path); + spin_unlock(&c->lock); + nd->inode = nd->path.dentry->d_inode; } - } - - nd->path = f.file->f_path; - if (flags & LOOKUP_RCU) { - rcu_read_lock(); - nd->inode = nd->path.dentry->d_inode; - nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); } else { - path_get(&nd->path); - nd->inode = nd->path.dentry->d_inode; + dentry = f.file->f_path.dentry; + + if (*s) { + if (!d_can_lookup(dentry)) { + fdput(f); + return ERR_PTR(-ENOTDIR); + } + } + + nd->path = f.file->f_path; + if (flags & LOOKUP_RCU) { + rcu_read_lock(); + nd->inode = nd->path.dentry->d_inode; + nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); + } else { + path_get(&nd->path); + nd->inode = nd->path.dentry->d_inode; + } } fdput(f); return s;
| |