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