linux/fs/proc/proc_net.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/proc/net.c
   3 *
   4 *  Copyright (C) 2007
   5 *
   6 *  Author: Eric Biederman <ebiederm@xmission.com>
   7 *
   8 *  proc net directory handling functions
   9 */
  10
  11#include <linux/uaccess.h>
  12
  13#include <linux/errno.h>
  14#include <linux/time.h>
  15#include <linux/proc_fs.h>
  16#include <linux/stat.h>
  17#include <linux/slab.h>
  18#include <linux/init.h>
  19#include <linux/sched.h>
  20#include <linux/sched/task.h>
  21#include <linux/module.h>
  22#include <linux/bitops.h>
  23#include <linux/mount.h>
  24#include <linux/nsproxy.h>
  25#include <linux/uidgid.h>
  26#include <net/net_namespace.h>
  27#include <linux/seq_file.h>
  28
  29#include "internal.h"
  30
  31static inline struct net *PDE_NET(struct proc_dir_entry *pde)
  32{
  33        return pde->parent->data;
  34}
  35
  36static struct net *get_proc_net(const struct inode *inode)
  37{
  38        return maybe_get_net(PDE_NET(PDE(inode)));
  39}
  40
  41static int seq_open_net(struct inode *inode, struct file *file)
  42{
  43        unsigned int state_size = PDE(inode)->state_size;
  44        struct seq_net_private *p;
  45        struct net *net;
  46
  47        WARN_ON_ONCE(state_size < sizeof(*p));
  48
  49        if (file->f_mode & FMODE_WRITE && !PDE(inode)->write)
  50                return -EACCES;
  51
  52        net = get_proc_net(inode);
  53        if (!net)
  54                return -ENXIO;
  55
  56        p = __seq_open_private(file, PDE(inode)->seq_ops, state_size);
  57        if (!p) {
  58                put_net(net);
  59                return -ENOMEM;
  60        }
  61#ifdef CONFIG_NET_NS
  62        p->net = net;
  63#endif
  64        return 0;
  65}
  66
  67static int seq_release_net(struct inode *ino, struct file *f)
  68{
  69        struct seq_file *seq = f->private_data;
  70
  71        put_net(seq_file_net(seq));
  72        seq_release_private(ino, f);
  73        return 0;
  74}
  75
  76static const struct file_operations proc_net_seq_fops = {
  77        .open           = seq_open_net,
  78        .read           = seq_read,
  79        .write          = proc_simple_write,
  80        .llseek         = seq_lseek,
  81        .release        = seq_release_net,
  82};
  83
  84struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
  85                struct proc_dir_entry *parent, const struct seq_operations *ops,
  86                unsigned int state_size, void *data)
  87{
  88        struct proc_dir_entry *p;
  89
  90        p = proc_create_reg(name, mode, &parent, data);
  91        if (!p)
  92                return NULL;
  93        p->proc_fops = &proc_net_seq_fops;
  94        p->seq_ops = ops;
  95        p->state_size = state_size;
  96        return proc_register(parent, p);
  97}
  98EXPORT_SYMBOL_GPL(proc_create_net_data);
  99
 100/**
 101 * proc_create_net_data_write - Create a writable net_ns-specific proc file
 102 * @name: The name of the file.
 103 * @mode: The file's access mode.
 104 * @parent: The parent directory in which to create.
 105 * @ops: The seq_file ops with which to read the file.
 106 * @write: The write method which which to 'modify' the file.
 107 * @data: Data for retrieval by PDE_DATA().
 108 *
 109 * Create a network namespaced proc file in the @parent directory with the
 110 * specified @name and @mode that allows reading of a file that displays a
 111 * series of elements and also provides for the file accepting writes that have
 112 * some arbitrary effect.
 113 *
 114 * The functions in the @ops table are used to iterate over items to be
 115 * presented and extract the readable content using the seq_file interface.
 116 *
 117 * The @write function is called with the data copied into a kernel space
 118 * scratch buffer and has a NUL appended for convenience.  The buffer may be
 119 * modified by the @write function.  @write should return 0 on success.
 120 *
 121 * The @data value is accessible from the @show and @write functions by calling
 122 * PDE_DATA() on the file inode.  The network namespace must be accessed by
 123 * calling seq_file_net() on the seq_file struct.
 124 */
 125struct proc_dir_entry *proc_create_net_data_write(const char *name, umode_t mode,
 126                                                  struct proc_dir_entry *parent,
 127                                                  const struct seq_operations *ops,
 128                                                  proc_write_t write,
 129                                                  unsigned int state_size, void *data)
 130{
 131        struct proc_dir_entry *p;
 132
 133        p = proc_create_reg(name, mode, &parent, data);
 134        if (!p)
 135                return NULL;
 136        p->proc_fops = &proc_net_seq_fops;
 137        p->seq_ops = ops;
 138        p->state_size = state_size;
 139        p->write = write;
 140        return proc_register(parent, p);
 141}
 142EXPORT_SYMBOL_GPL(proc_create_net_data_write);
 143
 144static int single_open_net(struct inode *inode, struct file *file)
 145{
 146        struct proc_dir_entry *de = PDE(inode);
 147        struct net *net;
 148        int err;
 149
 150        net = get_proc_net(inode);
 151        if (!net)
 152                return -ENXIO;
 153
 154        err = single_open(file, de->single_show, net);
 155        if (err)
 156                put_net(net);
 157        return err;
 158}
 159
 160static int single_release_net(struct inode *ino, struct file *f)
 161{
 162        struct seq_file *seq = f->private_data;
 163        put_net(seq->private);
 164        return single_release(ino, f);
 165}
 166
 167static const struct file_operations proc_net_single_fops = {
 168        .open           = single_open_net,
 169        .read           = seq_read,
 170        .write          = proc_simple_write,
 171        .llseek         = seq_lseek,
 172        .release        = single_release_net,
 173};
 174
 175struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
 176                struct proc_dir_entry *parent,
 177                int (*show)(struct seq_file *, void *), void *data)
 178{
 179        struct proc_dir_entry *p;
 180
 181        p = proc_create_reg(name, mode, &parent, data);
 182        if (!p)
 183                return NULL;
 184        p->proc_fops = &proc_net_single_fops;
 185        p->single_show = show;
 186        return proc_register(parent, p);
 187}
 188EXPORT_SYMBOL_GPL(proc_create_net_single);
 189
 190/**
 191 * proc_create_net_single_write - Create a writable net_ns-specific proc file
 192 * @name: The name of the file.
 193 * @mode: The file's access mode.
 194 * @parent: The parent directory in which to create.
 195 * @show: The seqfile show method with which to read the file.
 196 * @write: The write method which which to 'modify' the file.
 197 * @data: Data for retrieval by PDE_DATA().
 198 *
 199 * Create a network-namespaced proc file in the @parent directory with the
 200 * specified @name and @mode that allows reading of a file that displays a
 201 * single element rather than a series and also provides for the file accepting
 202 * writes that have some arbitrary effect.
 203 *
 204 * The @show function is called to extract the readable content via the
 205 * seq_file interface.
 206 *
 207 * The @write function is called with the data copied into a kernel space
 208 * scratch buffer and has a NUL appended for convenience.  The buffer may be
 209 * modified by the @write function.  @write should return 0 on success.
 210 *
 211 * The @data value is accessible from the @show and @write functions by calling
 212 * PDE_DATA() on the file inode.  The network namespace must be accessed by
 213 * calling seq_file_single_net() on the seq_file struct.
 214 */
 215struct proc_dir_entry *proc_create_net_single_write(const char *name, umode_t mode,
 216                                                    struct proc_dir_entry *parent,
 217                                                    int (*show)(struct seq_file *, void *),
 218                                                    proc_write_t write,
 219                                                    void *data)
 220{
 221        struct proc_dir_entry *p;
 222
 223        p = proc_create_reg(name, mode, &parent, data);
 224        if (!p)
 225                return NULL;
 226        p->proc_fops = &proc_net_single_fops;
 227        p->single_show = show;
 228        p->write = write;
 229        return proc_register(parent, p);
 230}
 231EXPORT_SYMBOL_GPL(proc_create_net_single_write);
 232
 233static struct net *get_proc_task_net(struct inode *dir)
 234{
 235        struct task_struct *task;
 236        struct nsproxy *ns;
 237        struct net *net = NULL;
 238
 239        rcu_read_lock();
 240        task = pid_task(proc_pid(dir), PIDTYPE_PID);
 241        if (task != NULL) {
 242                task_lock(task);
 243                ns = task->nsproxy;
 244                if (ns != NULL)
 245                        net = get_net(ns->net_ns);
 246                task_unlock(task);
 247        }
 248        rcu_read_unlock();
 249
 250        return net;
 251}
 252
 253static struct dentry *proc_tgid_net_lookup(struct inode *dir,
 254                struct dentry *dentry, unsigned int flags)
 255{
 256        struct dentry *de;
 257        struct net *net;
 258
 259        de = ERR_PTR(-ENOENT);
 260        net = get_proc_task_net(dir);
 261        if (net != NULL) {
 262                de = proc_lookup_de(dir, dentry, net->proc_net);
 263                put_net(net);
 264        }
 265        return de;
 266}
 267
 268static int proc_tgid_net_getattr(const struct path *path, struct kstat *stat,
 269                                 u32 request_mask, unsigned int query_flags)
 270{
 271        struct inode *inode = d_inode(path->dentry);
 272        struct net *net;
 273
 274        net = get_proc_task_net(inode);
 275
 276        generic_fillattr(inode, stat);
 277
 278        if (net != NULL) {
 279                stat->nlink = net->proc_net->nlink;
 280                put_net(net);
 281        }
 282
 283        return 0;
 284}
 285
 286const struct inode_operations proc_net_inode_operations = {
 287        .lookup         = proc_tgid_net_lookup,
 288        .getattr        = proc_tgid_net_getattr,
 289};
 290
 291static int proc_tgid_net_readdir(struct file *file, struct dir_context *ctx)
 292{
 293        int ret;
 294        struct net *net;
 295
 296        ret = -EINVAL;
 297        net = get_proc_task_net(file_inode(file));
 298        if (net != NULL) {
 299                ret = proc_readdir_de(file, ctx, net->proc_net);
 300                put_net(net);
 301        }
 302        return ret;
 303}
 304
 305const struct file_operations proc_net_operations = {
 306        .llseek         = generic_file_llseek,
 307        .read           = generic_read_dir,
 308        .iterate_shared = proc_tgid_net_readdir,
 309};
 310
 311static __net_init int proc_net_ns_init(struct net *net)
 312{
 313        struct proc_dir_entry *netd, *net_statd;
 314        kuid_t uid;
 315        kgid_t gid;
 316        int err;
 317
 318        err = -ENOMEM;
 319        netd = kmem_cache_zalloc(proc_dir_entry_cache, GFP_KERNEL);
 320        if (!netd)
 321                goto out;
 322
 323        netd->subdir = RB_ROOT;
 324        netd->data = net;
 325        netd->nlink = 2;
 326        netd->namelen = 3;
 327        netd->parent = &proc_root;
 328        netd->name = netd->inline_name;
 329        memcpy(netd->name, "net", 4);
 330
 331        uid = make_kuid(net->user_ns, 0);
 332        if (!uid_valid(uid))
 333                uid = netd->uid;
 334
 335        gid = make_kgid(net->user_ns, 0);
 336        if (!gid_valid(gid))
 337                gid = netd->gid;
 338
 339        proc_set_user(netd, uid, gid);
 340
 341        err = -EEXIST;
 342        net_statd = proc_net_mkdir(net, "stat", netd);
 343        if (!net_statd)
 344                goto free_net;
 345
 346        net->proc_net = netd;
 347        net->proc_net_stat = net_statd;
 348        return 0;
 349
 350free_net:
 351        pde_free(netd);
 352out:
 353        return err;
 354}
 355
 356static __net_exit void proc_net_ns_exit(struct net *net)
 357{
 358        remove_proc_entry("stat", net->proc_net);
 359        pde_free(net->proc_net);
 360}
 361
 362static struct pernet_operations __net_initdata proc_net_ns_ops = {
 363        .init = proc_net_ns_init,
 364        .exit = proc_net_ns_exit,
 365};
 366
 367int __init proc_net_init(void)
 368{
 369        proc_symlink("net", NULL, "self/net");
 370
 371        return register_pernet_subsys(&proc_net_ns_ops);
 372}
 373