linux/fs/proc/namespaces.c
<<
>>
Prefs
   1#include <linux/proc_fs.h>
   2#include <linux/nsproxy.h>
   3#include <linux/sched.h>
   4#include <linux/ptrace.h>
   5#include <linux/fs_struct.h>
   6#include <linux/mount.h>
   7#include <linux/path.h>
   8#include <linux/namei.h>
   9#include <linux/file.h>
  10#include <linux/utsname.h>
  11#include <net/net_namespace.h>
  12#include <linux/ipc_namespace.h>
  13#include <linux/pid_namespace.h>
  14#include <linux/user_namespace.h>
  15#include "internal.h"
  16
  17
  18static const struct proc_ns_operations *ns_entries[] = {
  19#ifdef CONFIG_NET_NS
  20        &netns_operations,
  21#endif
  22#ifdef CONFIG_UTS_NS
  23        &utsns_operations,
  24#endif
  25#ifdef CONFIG_IPC_NS
  26        &ipcns_operations,
  27#endif
  28#ifdef CONFIG_PID_NS
  29        &pidns_operations,
  30#endif
  31#ifdef CONFIG_USER_NS
  32        &userns_operations,
  33#endif
  34        &mntns_operations,
  35};
  36
  37static const struct file_operations ns_file_operations = {
  38        .llseek         = no_llseek,
  39};
  40
  41static const struct inode_operations ns_inode_operations = {
  42        .setattr        = proc_setattr,
  43};
  44
  45static int ns_delete_dentry(const struct dentry *dentry)
  46{
  47        /* Don't cache namespace inodes when not in use */
  48        return 1;
  49}
  50
  51static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
  52{
  53        struct inode *inode = dentry->d_inode;
  54        const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns.ns_ops;
  55
  56        return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
  57                ns_ops->name, inode->i_ino);
  58}
  59
  60const struct dentry_operations ns_dentry_operations =
  61{
  62        .d_delete       = ns_delete_dentry,
  63        .d_dname        = ns_dname,
  64};
  65
  66static struct dentry *proc_ns_get_dentry(struct super_block *sb,
  67        struct task_struct *task, const struct proc_ns_operations *ns_ops)
  68{
  69        struct dentry *dentry, *result;
  70        struct inode *inode;
  71        struct proc_inode *ei;
  72        struct qstr qname = { .name = "", };
  73        void *ns;
  74
  75        ns = ns_ops->get(task);
  76        if (!ns)
  77                return ERR_PTR(-ENOENT);
  78
  79        dentry = d_alloc_pseudo(sb, &qname);
  80        if (!dentry) {
  81                ns_ops->put(ns);
  82                return ERR_PTR(-ENOMEM);
  83        }
  84
  85        inode = iget_locked(sb, ns_ops->inum(ns));
  86        if (!inode) {
  87                dput(dentry);
  88                ns_ops->put(ns);
  89                return ERR_PTR(-ENOMEM);
  90        }
  91
  92        ei = PROC_I(inode);
  93        if (inode->i_state & I_NEW) {
  94                inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
  95                inode->i_op = &ns_inode_operations;
  96                inode->i_mode = S_IFREG | S_IRUGO;
  97                inode->i_fop = &ns_file_operations;
  98                ei->ns.ns_ops = ns_ops;
  99                ei->ns.ns = ns;
 100                unlock_new_inode(inode);
 101        } else {
 102                ns_ops->put(ns);
 103        }
 104
 105        d_set_d_op(dentry, &ns_dentry_operations);
 106        result = d_instantiate_unique(dentry, inode);
 107        if (result) {
 108                dput(dentry);
 109                dentry = result;
 110        }
 111
 112        return dentry;
 113}
 114
 115static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
 116{
 117        struct inode *inode = dentry->d_inode;
 118        struct super_block *sb = inode->i_sb;
 119        struct proc_inode *ei = PROC_I(inode);
 120        struct task_struct *task;
 121        struct path ns_path;
 122        void *error = ERR_PTR(-EACCES);
 123
 124        task = get_proc_task(inode);
 125        if (!task)
 126                goto out;
 127
 128        if (!ptrace_may_access(task, PTRACE_MODE_READ))
 129                goto out_put_task;
 130
 131        ns_path.dentry = proc_ns_get_dentry(sb, task, ei->ns.ns_ops);
 132        if (IS_ERR(ns_path.dentry)) {
 133                error = ERR_CAST(ns_path.dentry);
 134                goto out_put_task;
 135        }
 136
 137        ns_path.mnt = mntget(nd->path.mnt);
 138        nd_jump_link(nd, &ns_path);
 139        error = NULL;
 140
 141out_put_task:
 142        put_task_struct(task);
 143out:
 144        return error;
 145}
 146
 147static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 148{
 149        struct inode *inode = dentry->d_inode;
 150        struct proc_inode *ei = PROC_I(inode);
 151        const struct proc_ns_operations *ns_ops = ei->ns.ns_ops;
 152        struct task_struct *task;
 153        void *ns;
 154        char name[50];
 155        int len = -EACCES;
 156
 157        task = get_proc_task(inode);
 158        if (!task)
 159                goto out;
 160
 161        if (!ptrace_may_access(task, PTRACE_MODE_READ))
 162                goto out_put_task;
 163
 164        len = -ENOENT;
 165        ns = ns_ops->get(task);
 166        if (!ns)
 167                goto out_put_task;
 168
 169        snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns));
 170        len = strlen(name);
 171
 172        if (len > buflen)
 173                len = buflen;
 174        if (copy_to_user(buffer, name, len))
 175                len = -EFAULT;
 176
 177        ns_ops->put(ns);
 178out_put_task:
 179        put_task_struct(task);
 180out:
 181        return len;
 182}
 183
 184static const struct inode_operations proc_ns_link_inode_operations = {
 185        .readlink       = proc_ns_readlink,
 186        .follow_link    = proc_ns_follow_link,
 187        .setattr        = proc_setattr,
 188};
 189
 190static struct dentry *proc_ns_instantiate(struct inode *dir,
 191        struct dentry *dentry, struct task_struct *task, const void *ptr)
 192{
 193        const struct proc_ns_operations *ns_ops = ptr;
 194        struct inode *inode;
 195        struct proc_inode *ei;
 196        struct dentry *error = ERR_PTR(-ENOENT);
 197
 198        inode = proc_pid_make_inode(dir->i_sb, task);
 199        if (!inode)
 200                goto out;
 201
 202        ei = PROC_I(inode);
 203        inode->i_mode = S_IFLNK|S_IRWXUGO;
 204        inode->i_op = &proc_ns_link_inode_operations;
 205        ei->ns.ns_ops = ns_ops;
 206
 207        d_set_d_op(dentry, &pid_dentry_operations);
 208        d_add(dentry, inode);
 209        /* Close the race of the process dying before we return the dentry */
 210        if (pid_revalidate(dentry, 0))
 211                error = NULL;
 212out:
 213        return error;
 214}
 215
 216static int proc_ns_fill_cache(struct file *filp, void *dirent,
 217        filldir_t filldir, struct task_struct *task,
 218        const struct proc_ns_operations *ops)
 219{
 220        return proc_fill_cache(filp, dirent, filldir,
 221                                ops->name, strlen(ops->name),
 222                                proc_ns_instantiate, task, ops);
 223}
 224
 225static int proc_ns_dir_readdir(struct file *filp, void *dirent,
 226                                filldir_t filldir)
 227{
 228        int i;
 229        struct dentry *dentry = filp->f_path.dentry;
 230        struct inode *inode = dentry->d_inode;
 231        struct task_struct *task = get_proc_task(inode);
 232        const struct proc_ns_operations **entry, **last;
 233        ino_t ino;
 234        int ret;
 235
 236        ret = -ENOENT;
 237        if (!task)
 238                goto out_no_task;
 239
 240        ret = 0;
 241        i = filp->f_pos;
 242        switch (i) {
 243        case 0:
 244                ino = inode->i_ino;
 245                if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
 246                        goto out;
 247                i++;
 248                filp->f_pos++;
 249                /* fall through */
 250        case 1:
 251                ino = parent_ino(dentry);
 252                if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
 253                        goto out;
 254                i++;
 255                filp->f_pos++;
 256                /* fall through */
 257        default:
 258                i -= 2;
 259                if (i >= ARRAY_SIZE(ns_entries)) {
 260                        ret = 1;
 261                        goto out;
 262                }
 263                entry = ns_entries + i;
 264                last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
 265                while (entry <= last) {
 266                        if (proc_ns_fill_cache(filp, dirent, filldir,
 267                                                task, *entry) < 0)
 268                                goto out;
 269                        filp->f_pos++;
 270                        entry++;
 271                }
 272        }
 273
 274        ret = 1;
 275out:
 276        put_task_struct(task);
 277out_no_task:
 278        return ret;
 279}
 280
 281const struct file_operations proc_ns_dir_operations = {
 282        .read           = generic_read_dir,
 283        .readdir        = proc_ns_dir_readdir,
 284};
 285
 286static struct dentry *proc_ns_dir_lookup(struct inode *dir,
 287                                struct dentry *dentry, unsigned int flags)
 288{
 289        struct dentry *error;
 290        struct task_struct *task = get_proc_task(dir);
 291        const struct proc_ns_operations **entry, **last;
 292        unsigned int len = dentry->d_name.len;
 293
 294        error = ERR_PTR(-ENOENT);
 295
 296        if (!task)
 297                goto out_no_task;
 298
 299        last = &ns_entries[ARRAY_SIZE(ns_entries)];
 300        for (entry = ns_entries; entry < last; entry++) {
 301                if (strlen((*entry)->name) != len)
 302                        continue;
 303                if (!memcmp(dentry->d_name.name, (*entry)->name, len))
 304                        break;
 305        }
 306        if (entry == last)
 307                goto out;
 308
 309        error = proc_ns_instantiate(dir, dentry, task, *entry);
 310out:
 311        put_task_struct(task);
 312out_no_task:
 313        return error;
 314}
 315
 316const struct inode_operations proc_ns_dir_inode_operations = {
 317        .lookup         = proc_ns_dir_lookup,
 318        .getattr        = pid_getattr,
 319        .setattr        = proc_setattr,
 320};
 321
 322struct file *proc_ns_fget(int fd)
 323{
 324        struct file *file;
 325
 326        file = fget(fd);
 327        if (!file)
 328                return ERR_PTR(-EBADF);
 329
 330        if (file->f_op != &ns_file_operations)
 331                goto out_invalid;
 332
 333        return file;
 334
 335out_invalid:
 336        fput(file);
 337        return ERR_PTR(-EINVAL);
 338}
 339
 340struct proc_ns *get_proc_ns(struct inode *inode)
 341{
 342        return &PROC_I(inode)->ns;
 343}
 344
 345bool proc_ns_inode(struct inode *inode)
 346{
 347        return inode->i_fop == &ns_file_operations;
 348}
 349