diff options
Diffstat (limited to 'fs/proc')
| -rw-r--r-- | fs/proc/generic.c | 12 | ||||
| -rw-r--r-- | fs/proc/proc_net.c | 86 |
2 files changed, 16 insertions, 82 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 39f3d6519035..5fccfe222a63 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
| @@ -374,9 +374,16 @@ static int proc_delete_dentry(struct dentry * dentry) | |||
| 374 | return 1; | 374 | return 1; |
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | static int proc_revalidate_dentry(struct dentry *dentry, struct nameidata *nd) | ||
| 378 | { | ||
| 379 | d_drop(dentry); | ||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | |||
| 377 | static struct dentry_operations proc_dentry_operations = | 383 | static struct dentry_operations proc_dentry_operations = |
| 378 | { | 384 | { |
| 379 | .d_delete = proc_delete_dentry, | 385 | .d_delete = proc_delete_dentry, |
| 386 | .d_revalidate = proc_revalidate_dentry, | ||
| 380 | }; | 387 | }; |
| 381 | 388 | ||
| 382 | /* | 389 | /* |
| @@ -397,8 +404,11 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam | |||
| 397 | if (de->namelen != dentry->d_name.len) | 404 | if (de->namelen != dentry->d_name.len) |
| 398 | continue; | 405 | continue; |
| 399 | if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { | 406 | if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { |
| 400 | unsigned int ino = de->low_ino; | 407 | unsigned int ino; |
| 401 | 408 | ||
| 409 | if (de->shadow_proc) | ||
| 410 | de = de->shadow_proc(current, de); | ||
| 411 | ino = de->low_ino; | ||
| 402 | de_get(de); | 412 | de_get(de); |
| 403 | spin_unlock(&proc_subdir_lock); | 413 | spin_unlock(&proc_subdir_lock); |
| 404 | error = -EINVAL; | 414 | error = -EINVAL; |
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index 131f9c68be5f..0afe21ee0607 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c | |||
| @@ -50,89 +50,14 @@ struct net *get_proc_net(const struct inode *inode) | |||
| 50 | } | 50 | } |
| 51 | EXPORT_SYMBOL_GPL(get_proc_net); | 51 | EXPORT_SYMBOL_GPL(get_proc_net); |
| 52 | 52 | ||
| 53 | static struct proc_dir_entry *proc_net_shadow; | 53 | static struct proc_dir_entry *shadow_pde; |
| 54 | 54 | ||
| 55 | static struct dentry *proc_net_shadow_dentry(struct dentry *parent, | 55 | static struct proc_dir_entry *proc_net_shadow(struct task_struct *task, |
| 56 | struct proc_dir_entry *de) | 56 | struct proc_dir_entry *de) |
| 57 | { | 57 | { |
| 58 | struct dentry *shadow = NULL; | 58 | return task->nsproxy->net_ns->proc_net; |
| 59 | struct inode *inode; | ||
| 60 | if (!de) | ||
| 61 | goto out; | ||
| 62 | de_get(de); | ||
| 63 | inode = proc_get_inode(parent->d_inode->i_sb, de->low_ino, de); | ||
| 64 | if (!inode) | ||
| 65 | goto out_de_put; | ||
| 66 | shadow = d_alloc_name(parent, de->name); | ||
| 67 | if (!shadow) | ||
| 68 | goto out_iput; | ||
| 69 | shadow->d_op = parent->d_op; /* proc_dentry_operations */ | ||
| 70 | d_instantiate(shadow, inode); | ||
| 71 | out: | ||
| 72 | return shadow; | ||
| 73 | out_iput: | ||
| 74 | iput(inode); | ||
| 75 | out_de_put: | ||
| 76 | de_put(de); | ||
| 77 | goto out; | ||
| 78 | } | ||
| 79 | |||
| 80 | static void *proc_net_follow_link(struct dentry *parent, struct nameidata *nd) | ||
| 81 | { | ||
| 82 | struct net *net = current->nsproxy->net_ns; | ||
| 83 | struct dentry *shadow; | ||
| 84 | shadow = proc_net_shadow_dentry(parent, net->proc_net); | ||
| 85 | if (!shadow) | ||
| 86 | return ERR_PTR(-ENOENT); | ||
| 87 | |||
| 88 | dput(nd->dentry); | ||
| 89 | /* My dentry count is 1 and that should be enough as the | ||
| 90 | * shadow dentry is thrown away immediately. | ||
| 91 | */ | ||
| 92 | nd->dentry = shadow; | ||
| 93 | return NULL; | ||
| 94 | } | 59 | } |
| 95 | 60 | ||
| 96 | static struct dentry *proc_net_lookup(struct inode *dir, struct dentry *dentry, | ||
| 97 | struct nameidata *nd) | ||
| 98 | { | ||
| 99 | struct net *net = current->nsproxy->net_ns; | ||
| 100 | struct dentry *shadow; | ||
| 101 | |||
| 102 | shadow = proc_net_shadow_dentry(nd->dentry, net->proc_net); | ||
| 103 | if (!shadow) | ||
| 104 | return ERR_PTR(-ENOENT); | ||
| 105 | |||
| 106 | dput(nd->dentry); | ||
| 107 | nd->dentry = shadow; | ||
| 108 | |||
| 109 | return shadow->d_inode->i_op->lookup(shadow->d_inode, dentry, nd); | ||
| 110 | } | ||
| 111 | |||
| 112 | static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr) | ||
| 113 | { | ||
| 114 | struct net *net = current->nsproxy->net_ns; | ||
| 115 | struct dentry *shadow; | ||
| 116 | int ret; | ||
| 117 | |||
| 118 | shadow = proc_net_shadow_dentry(dentry->d_parent, net->proc_net); | ||
| 119 | if (!shadow) | ||
| 120 | return -ENOENT; | ||
| 121 | ret = shadow->d_inode->i_op->setattr(shadow, iattr); | ||
| 122 | dput(shadow); | ||
| 123 | return ret; | ||
| 124 | } | ||
| 125 | |||
| 126 | static const struct file_operations proc_net_dir_operations = { | ||
| 127 | .read = generic_read_dir, | ||
| 128 | }; | ||
| 129 | |||
| 130 | static struct inode_operations proc_net_dir_inode_operations = { | ||
| 131 | .follow_link = proc_net_follow_link, | ||
| 132 | .lookup = proc_net_lookup, | ||
| 133 | .setattr = proc_net_setattr, | ||
| 134 | }; | ||
| 135 | |||
| 136 | static __net_init int proc_net_ns_init(struct net *net) | 61 | static __net_init int proc_net_ns_init(struct net *net) |
| 137 | { | 62 | { |
| 138 | struct proc_dir_entry *root, *netd, *net_statd; | 63 | struct proc_dir_entry *root, *netd, *net_statd; |
| @@ -185,9 +110,8 @@ static struct pernet_operations __net_initdata proc_net_ns_ops = { | |||
| 185 | 110 | ||
| 186 | int __init proc_net_init(void) | 111 | int __init proc_net_init(void) |
| 187 | { | 112 | { |
| 188 | proc_net_shadow = proc_mkdir("net", NULL); | 113 | shadow_pde = proc_mkdir("net", NULL); |
| 189 | proc_net_shadow->proc_iops = &proc_net_dir_inode_operations; | 114 | shadow_pde->shadow_proc = proc_net_shadow; |
| 190 | proc_net_shadow->proc_fops = &proc_net_dir_operations; | ||
| 191 | 115 | ||
| 192 | return register_pernet_subsys(&proc_net_ns_ops); | 116 | return register_pernet_subsys(&proc_net_ns_ops); |
| 193 | } | 117 | } |
