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 <asm/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/init.h> 18 #include <linux/sched.h> 19 #include <linux/module.h> 20 #include <linux/bitops.h> 21 #include <linux/smp_lock.h> 22 #include <linux/mount.h> 23 #include <linux/nsproxy.h> 24 #include <net/net_namespace.h> 25 26 #include "internal.h" 27 28 29 struct proc_dir_entry *proc_net_create(struct net *net, 30 const char *name, mode_t mode, get_info_t *get_info) 31 { 32 return create_proc_info_entry(name,mode, net->proc_net, get_info); 33 } 34 EXPORT_SYMBOL_GPL(proc_net_create); 35 36 struct proc_dir_entry *proc_net_fops_create(struct net *net, 37 const char *name, mode_t mode, const struct file_operations *fops) 38 { 39 struct proc_dir_entry *res; 40 41 res = create_proc_entry(name, mode, net->proc_net); 42 if (res) 43 res->proc_fops = fops; 44 return res; 45 } 46 EXPORT_SYMBOL_GPL(proc_net_fops_create); 47 48 void proc_net_remove(struct net *net, const char *name) 49 { 50 remove_proc_entry(name, net->proc_net); 51 } 52 EXPORT_SYMBOL_GPL(proc_net_remove); 53 54 struct net *get_proc_net(const struct inode *inode) 55 { 56 return maybe_get_net(PDE_NET(PDE(inode))); 57 } 58 EXPORT_SYMBOL_GPL(get_proc_net); 59 60 static struct proc_dir_entry *proc_net_shadow; 61 62 static struct dentry *proc_net_shadow_dentry(struct dentry *parent, 63 struct proc_dir_entry *de) 64 { 65 struct dentry *shadow = NULL; 66 struct inode *inode; 67 if (!de) 68 goto out; 69 de_get(de); 70 inode = proc_get_inode(parent->d_inode->i_sb, de->low_ino, de); 71 if (!inode) 72 goto out_de_put; 73 shadow = d_alloc_name(parent, de->name); 74 if (!shadow) 75 goto out_iput; 76 shadow->d_op = parent->d_op; /* proc_dentry_operations */ 77 d_instantiate(shadow, inode); 78 out: 79 return shadow; 80 out_iput: 81 iput(inode); 82 out_de_put: 83 de_put(de); 84 goto out; 85 } 86 87 static void *proc_net_follow_link(struct dentry *parent, struct nameidata *nd) 88 { 89 struct net *net = current->nsproxy->net_ns; 90 struct dentry *shadow; 91 shadow = proc_net_shadow_dentry(parent, net->proc_net); 92 if (!shadow) 93 return ERR_PTR(-ENOENT); 94 95 dput(nd->dentry); 96 /* My dentry count is 1 and that should be enough as the 97 * shadow dentry is thrown away immediately. 98 */ 99 nd->dentry = shadow; 100 return NULL; 101 } 102 103 static struct dentry *proc_net_lookup(struct inode *dir, struct dentry *dentry, 104 struct nameidata *nd) 105 { 106 struct net *net = current->nsproxy->net_ns; 107 struct dentry *shadow; 108 109 shadow = proc_net_shadow_dentry(nd->dentry, net->proc_net); 110 if (!shadow) 111 return ERR_PTR(-ENOENT); 112 113 dput(nd->dentry); 114 nd->dentry = shadow; 115 116 return shadow->d_inode->i_op->lookup(shadow->d_inode, dentry, nd); 117 } 118 119 static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr) 120 { 121 struct net *net = current->nsproxy->net_ns; 122 struct dentry *shadow; 123 int ret; 124 125 shadow = proc_net_shadow_dentry(dentry->d_parent, net->proc_net); 126 if (!shadow) 127 return -ENOENT; 128 ret = shadow->d_inode->i_op->setattr(shadow, iattr); 129 dput(shadow); 130 return ret; 131 } 132 133 static const struct file_operations proc_net_dir_operations = { 134 .read = generic_read_dir, 135 }; 136 137 static struct inode_operations proc_net_dir_inode_operations = { 138 .follow_link = proc_net_follow_link, 139 .lookup = proc_net_lookup, 140 .setattr = proc_net_setattr, 141 }; 142 143 static __net_init int proc_net_ns_init(struct net *net) 144 { 145 struct proc_dir_entry *root, *netd, *net_statd; 146 int err; 147 148 err = -ENOMEM; 149 root = kzalloc(sizeof(*root), GFP_KERNEL); 150 if (!root) 151 goto out; 152 153 err = -EEXIST; 154 netd = proc_mkdir("net", root); 155 if (!netd) 156 goto free_root; 157 158 err = -EEXIST; 159 net_statd = proc_mkdir("stat", netd); 160 if (!net_statd) 161 goto free_net; 162 163 root->data = net; 164 netd->data = net; 165 net_statd->data = net; 166 167 net->proc_net_root = root; 168 net->proc_net = netd; 169 net->proc_net_stat = net_statd; 170 err = 0; 171 172 out: 173 return err; 174 free_net: 175 remove_proc_entry("net", root); 176 free_root: 177 kfree(root); 178 goto out; 179 } 180 181 static __net_exit void proc_net_ns_exit(struct net *net) 182 { 183 remove_proc_entry("stat", net->proc_net); 184 remove_proc_entry("net", net->proc_net_root); 185 kfree(net->proc_net_root); 186 } 187 188 struct pernet_operations __net_initdata proc_net_ns_ops = { 189 .init = proc_net_ns_init, 190 .exit = proc_net_ns_exit, 191 }; 192 193 int __init proc_net_init(void) 194 { 195 proc_net_shadow = proc_mkdir("net", NULL); 196 proc_net_shadow->proc_iops = &proc_net_dir_inode_operations; 197 proc_net_shadow->proc_fops = &proc_net_dir_operations; 198 199 return register_pernet_subsys(&proc_net_ns_ops); 200 } 201