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