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