linux/fs/proc/namespaces.c
<<
>>
Prefs
   1#include <linux/proc_fs.h>
   2#include <linux/nsproxy.h>
   3#include <linux/ptrace.h>
   4#include <linux/namei.h>
   5#include <linux/file.h>
   6#include <linux/utsname.h>
   7#include <net/net_namespace.h>
   8#include <linux/ipc_namespace.h>
   9#include <linux/pid_namespace.h>
  10#include <linux/user_namespace.h>
  11#include "internal.h"
  12
  13
  14static const struct proc_ns_operations *ns_entries[] = {
  15#ifdef CONFIG_NET_NS
  16        &netns_operations,
  17#endif
  18#ifdef CONFIG_UTS_NS
  19        &utsns_operations,
  20#endif
  21#ifdef CONFIG_IPC_NS
  22        &ipcns_operations,
  23#endif
  24#ifdef CONFIG_PID_NS
  25        &pidns_operations,
  26#endif
  27#ifdef CONFIG_USER_NS
  28        &userns_operations,
  29#endif
  30        &mntns_operations,
  31#ifdef CONFIG_CGROUPS
  32        &cgroupns_operations,
  33#endif
  34};
  35
  36static const char *proc_ns_get_link(struct dentry *dentry,
  37                                    struct inode *inode,
  38                                    struct delayed_call *done)
  39{
  40        const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
  41        struct task_struct *task;
  42        struct path ns_path;
  43        void *error = ERR_PTR(-EACCES);
  44
  45        if (!dentry)
  46                return ERR_PTR(-ECHILD);
  47
  48        task = get_proc_task(inode);
  49        if (!task)
  50                return error;
  51
  52        if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
  53                error = ns_get_path(&ns_path, task, ns_ops);
  54                if (!error)
  55                        nd_jump_link(&ns_path);
  56        }
  57        put_task_struct(task);
  58        return error;
  59}
  60
  61static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen)
  62{
  63        struct inode *inode = d_inode(dentry);
  64        const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
  65        struct task_struct *task;
  66        char name[50];
  67        int res = -EACCES;
  68
  69        task = get_proc_task(inode);
  70        if (!task)
  71                return res;
  72
  73        if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
  74                res = ns_get_name(name, sizeof(name), task, ns_ops);
  75                if (res >= 0)
  76                        res = readlink_copy(buffer, buflen, name);
  77        }
  78        put_task_struct(task);
  79        return res;
  80}
  81
  82static const struct inode_operations proc_ns_link_inode_operations = {
  83        .readlink       = proc_ns_readlink,
  84        .get_link       = proc_ns_get_link,
  85        .setattr        = proc_setattr,
  86};
  87
  88static int proc_ns_instantiate(struct inode *dir,
  89        struct dentry *dentry, struct task_struct *task, const void *ptr)
  90{
  91        const struct proc_ns_operations *ns_ops = ptr;
  92        struct inode *inode;
  93        struct proc_inode *ei;
  94
  95        inode = proc_pid_make_inode(dir->i_sb, task);
  96        if (!inode)
  97                goto out;
  98
  99        ei = PROC_I(inode);
 100        inode->i_mode = S_IFLNK|S_IRWXUGO;
 101        inode->i_op = &proc_ns_link_inode_operations;
 102        ei->ns_ops = ns_ops;
 103
 104        d_set_d_op(dentry, &pid_dentry_operations);
 105        d_add(dentry, inode);
 106        /* Close the race of the process dying before we return the dentry */
 107        if (pid_revalidate(dentry, 0))
 108                return 0;
 109out:
 110        return -ENOENT;
 111}
 112
 113static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx)
 114{
 115        struct task_struct *task = get_proc_task(file_inode(file));
 116        const struct proc_ns_operations **entry, **last;
 117
 118        if (!task)
 119                return -ENOENT;
 120
 121        if (!dir_emit_dots(file, ctx))
 122                goto out;
 123        if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries))
 124                goto out;
 125        entry = ns_entries + (ctx->pos - 2);
 126        last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
 127        while (entry <= last) {
 128                const struct proc_ns_operations *ops = *entry;
 129                if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name),
 130                                     proc_ns_instantiate, task, ops))
 131                        break;
 132                ctx->pos++;
 133                entry++;
 134        }
 135out:
 136        put_task_struct(task);
 137        return 0;
 138}
 139
 140const struct file_operations proc_ns_dir_operations = {
 141        .read           = generic_read_dir,
 142        .iterate        = proc_ns_dir_readdir,
 143};
 144
 145static struct dentry *proc_ns_dir_lookup(struct inode *dir,
 146                                struct dentry *dentry, unsigned int flags)
 147{
 148        int error;
 149        struct task_struct *task = get_proc_task(dir);
 150        const struct proc_ns_operations **entry, **last;
 151        unsigned int len = dentry->d_name.len;
 152
 153        error = -ENOENT;
 154
 155        if (!task)
 156                goto out_no_task;
 157
 158        last = &ns_entries[ARRAY_SIZE(ns_entries)];
 159        for (entry = ns_entries; entry < last; entry++) {
 160                if (strlen((*entry)->name) != len)
 161                        continue;
 162                if (!memcmp(dentry->d_name.name, (*entry)->name, len))
 163                        break;
 164        }
 165        if (entry == last)
 166                goto out;
 167
 168        error = proc_ns_instantiate(dir, dentry, task, *entry);
 169out:
 170        put_task_struct(task);
 171out_no_task:
 172        return ERR_PTR(error);
 173}
 174
 175const struct inode_operations proc_ns_dir_inode_operations = {
 176        .lookup         = proc_ns_dir_lookup,
 177        .getattr        = pid_getattr,
 178        .setattr        = proc_setattr,
 179};
 180