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 31 static inline struct net *PDE_NET(struct proc_dir_entry *pde) 32 { 33 return pde->parent->data; 34 } 35 36 static struct net *get_proc_net(const struct inode *inode) 37 { 38 return maybe_get_net(PDE_NET(PDE(inode))); 39 } 40 41 int seq_open_net(struct inode *ino, struct file *f, 42 const struct seq_operations *ops, int size) 43 { 44 struct net *net; 45 struct seq_net_private *p; 46 47 BUG_ON(size < sizeof(*p)); 48 49 net = get_proc_net(ino); 50 if (net == NULL) 51 return -ENXIO; 52 53 p = __seq_open_private(f, ops, size); 54 if (p == NULL) { 55 put_net(net); 56 return -ENOMEM; 57 } 58 #ifdef CONFIG_NET_NS 59 p->net = net; 60 #endif 61 return 0; 62 } 63 EXPORT_SYMBOL_GPL(seq_open_net); 64 65 int single_open_net(struct inode *inode, struct file *file, 66 int (*show)(struct seq_file *, void *)) 67 { 68 int err; 69 struct net *net; 70 71 err = -ENXIO; 72 net = get_proc_net(inode); 73 if (net == NULL) 74 goto err_net; 75 76 err = single_open(file, show, net); 77 if (err < 0) 78 goto err_open; 79 80 return 0; 81 82 err_open: 83 put_net(net); 84 err_net: 85 return err; 86 } 87 EXPORT_SYMBOL_GPL(single_open_net); 88 89 int seq_release_net(struct inode *ino, struct file *f) 90 { 91 struct seq_file *seq; 92 93 seq = f->private_data; 94 95 put_net(seq_file_net(seq)); 96 seq_release_private(ino, f); 97 return 0; 98 } 99 EXPORT_SYMBOL_GPL(seq_release_net); 100 101 int single_release_net(struct inode *ino, struct file *f) 102 { 103 struct seq_file *seq = f->private_data; 104 put_net(seq->private); 105 return single_release(ino, f); 106 } 107 EXPORT_SYMBOL_GPL(single_release_net); 108 109 static struct net *get_proc_task_net(struct inode *dir) 110 { 111 struct task_struct *task; 112 struct nsproxy *ns; 113 struct net *net = NULL; 114 115 rcu_read_lock(); 116 task = pid_task(proc_pid(dir), PIDTYPE_PID); 117 if (task != NULL) { 118 task_lock(task); 119 ns = task->nsproxy; 120 if (ns != NULL) 121 net = get_net(ns->net_ns); 122 task_unlock(task); 123 } 124 rcu_read_unlock(); 125 126 return net; 127 } 128 129 static struct dentry *proc_tgid_net_lookup(struct inode *dir, 130 struct dentry *dentry, unsigned int flags) 131 { 132 struct dentry *de; 133 struct net *net; 134 135 de = ERR_PTR(-ENOENT); 136 net = get_proc_task_net(dir); 137 if (net != NULL) { 138 de = proc_lookup_de(dir, dentry, net->proc_net); 139 put_net(net); 140 } 141 return de; 142 } 143 144 static int proc_tgid_net_getattr(const struct path *path, struct kstat *stat, 145 u32 request_mask, unsigned int query_flags) 146 { 147 struct inode *inode = d_inode(path->dentry); 148 struct net *net; 149 150 net = get_proc_task_net(inode); 151 152 generic_fillattr(inode, stat); 153 154 if (net != NULL) { 155 stat->nlink = net->proc_net->nlink; 156 put_net(net); 157 } 158 159 return 0; 160 } 161 162 const struct inode_operations proc_net_inode_operations = { 163 .lookup = proc_tgid_net_lookup, 164 .getattr = proc_tgid_net_getattr, 165 }; 166 167 static int proc_tgid_net_readdir(struct file *file, struct dir_context *ctx) 168 { 169 int ret; 170 struct net *net; 171 172 ret = -EINVAL; 173 net = get_proc_task_net(file_inode(file)); 174 if (net != NULL) { 175 ret = proc_readdir_de(file, ctx, net->proc_net); 176 put_net(net); 177 } 178 return ret; 179 } 180 181 const struct file_operations proc_net_operations = { 182 .llseek = generic_file_llseek, 183 .read = generic_read_dir, 184 .iterate_shared = proc_tgid_net_readdir, 185 }; 186 187 static __net_init int proc_net_ns_init(struct net *net) 188 { 189 struct proc_dir_entry *netd, *net_statd; 190 kuid_t uid; 191 kgid_t gid; 192 int err; 193 194 err = -ENOMEM; 195 netd = kmem_cache_zalloc(proc_dir_entry_cache, GFP_KERNEL); 196 if (!netd) 197 goto out; 198 199 netd->subdir = RB_ROOT; 200 netd->data = net; 201 netd->nlink = 2; 202 netd->namelen = 3; 203 netd->parent = &proc_root; 204 netd->name = netd->inline_name; 205 memcpy(netd->name, "net", 4); 206 207 uid = make_kuid(net->user_ns, 0); 208 if (!uid_valid(uid)) 209 uid = netd->uid; 210 211 gid = make_kgid(net->user_ns, 0); 212 if (!gid_valid(gid)) 213 gid = netd->gid; 214 215 proc_set_user(netd, uid, gid); 216 217 err = -EEXIST; 218 net_statd = proc_net_mkdir(net, "stat", netd); 219 if (!net_statd) 220 goto free_net; 221 222 net->proc_net = netd; 223 net->proc_net_stat = net_statd; 224 return 0; 225 226 free_net: 227 pde_free(netd); 228 out: 229 return err; 230 } 231 232 static __net_exit void proc_net_ns_exit(struct net *net) 233 { 234 remove_proc_entry("stat", net->proc_net); 235 pde_free(net->proc_net); 236 } 237 238 static struct pernet_operations __net_initdata proc_net_ns_ops = { 239 .init = proc_net_ns_init, 240 .exit = proc_net_ns_exit, 241 }; 242 243 int __init proc_net_init(void) 244 { 245 proc_symlink("net", NULL, "self/net"); 246 247 return register_pernet_subsys(&proc_net_ns_ops); 248 } 249