Branch data Line data Source code
1 : : #include <linux/proc_fs.h>
2 : : #include <linux/nsproxy.h>
3 : : #include <linux/sched.h>
4 : : #include <linux/ptrace.h>
5 : : #include <linux/fs_struct.h>
6 : : #include <linux/mount.h>
7 : : #include <linux/path.h>
8 : : #include <linux/namei.h>
9 : : #include <linux/file.h>
10 : : #include <linux/utsname.h>
11 : : #include <net/net_namespace.h>
12 : : #include <linux/ipc_namespace.h>
13 : : #include <linux/pid_namespace.h>
14 : : #include <linux/user_namespace.h>
15 : : #include "internal.h"
16 : :
17 : :
18 : : static const struct proc_ns_operations *ns_entries[] = {
19 : : #ifdef CONFIG_NET_NS
20 : : &netns_operations,
21 : : #endif
22 : : #ifdef CONFIG_UTS_NS
23 : : &utsns_operations,
24 : : #endif
25 : : #ifdef CONFIG_IPC_NS
26 : : &ipcns_operations,
27 : : #endif
28 : : #ifdef CONFIG_PID_NS
29 : : &pidns_operations,
30 : : #endif
31 : : #ifdef CONFIG_USER_NS
32 : : &userns_operations,
33 : : #endif
34 : : &mntns_operations,
35 : : };
36 : :
37 : : static const struct file_operations ns_file_operations = {
38 : : .llseek = no_llseek,
39 : : };
40 : :
41 : : static const struct inode_operations ns_inode_operations = {
42 : : .setattr = proc_setattr,
43 : : };
44 : :
45 : 0 : static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
46 : : {
47 : 0 : struct inode *inode = dentry->d_inode;
48 : 0 : const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns.ns_ops;
49 : :
50 : 0 : return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
51 : : ns_ops->name, inode->i_ino);
52 : : }
53 : :
54 : : const struct dentry_operations ns_dentry_operations =
55 : : {
56 : : .d_delete = always_delete_dentry,
57 : : .d_dname = ns_dname,
58 : : };
59 : :
60 : 0 : static struct dentry *proc_ns_get_dentry(struct super_block *sb,
61 : : struct task_struct *task, const struct proc_ns_operations *ns_ops)
62 : : {
63 : : struct dentry *dentry, *result;
64 : : struct inode *inode;
65 : : struct proc_inode *ei;
66 : 2 : struct qstr qname = { .name = "", };
67 : : void *ns;
68 : :
69 : 2 : ns = ns_ops->get(task);
70 [ + - ]: 2 : if (!ns)
71 : : return ERR_PTR(-ENOENT);
72 : :
73 : 2 : dentry = d_alloc_pseudo(sb, &qname);
74 [ - + ]: 2 : if (!dentry) {
75 : 0 : ns_ops->put(ns);
76 : 0 : return ERR_PTR(-ENOMEM);
77 : : }
78 : :
79 : 2 : inode = iget_locked(sb, ns_ops->inum(ns));
80 [ - + ]: 4 : if (!inode) {
81 : 0 : dput(dentry);
82 : 0 : ns_ops->put(ns);
83 : 0 : return ERR_PTR(-ENOMEM);
84 : : }
85 : :
86 : : ei = PROC_I(inode);
87 [ + - ]: 2 : if (inode->i_state & I_NEW) {
88 : 2 : inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
89 : 2 : inode->i_op = &ns_inode_operations;
90 : 2 : inode->i_mode = S_IFREG | S_IRUGO;
91 : 2 : inode->i_fop = &ns_file_operations;
92 : 2 : ei->ns.ns_ops = ns_ops;
93 : 2 : ei->ns.ns = ns;
94 : 2 : unlock_new_inode(inode);
95 : : } else {
96 : 0 : ns_ops->put(ns);
97 : : }
98 : :
99 : 2 : d_set_d_op(dentry, &ns_dentry_operations);
100 : 2 : result = d_instantiate_unique(dentry, inode);
101 [ - + ]: 2 : if (result) {
102 : 0 : dput(dentry);
103 : : dentry = result;
104 : : }
105 : :
106 : 2 : return dentry;
107 : : }
108 : :
109 : 0 : static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
110 : : {
111 : 2 : struct inode *inode = dentry->d_inode;
112 : 2 : struct super_block *sb = inode->i_sb;
113 : : struct proc_inode *ei = PROC_I(inode);
114 : : struct task_struct *task;
115 : : struct path ns_path;
116 : : void *error = ERR_PTR(-EACCES);
117 : :
118 : : task = get_proc_task(inode);
119 [ + - ]: 2 : if (!task)
120 : : goto out;
121 : :
122 [ + - ]: 2 : if (!ptrace_may_access(task, PTRACE_MODE_READ))
123 : : goto out_put_task;
124 : :
125 : 2 : ns_path.dentry = proc_ns_get_dentry(sb, task, ei->ns.ns_ops);
126 [ + - ]: 2 : if (IS_ERR(ns_path.dentry)) {
127 : : error = ERR_CAST(ns_path.dentry);
128 : : goto out_put_task;
129 : : }
130 : :
131 : 2 : ns_path.mnt = mntget(nd->path.mnt);
132 : 2 : nd_jump_link(nd, &ns_path);
133 : : error = NULL;
134 : :
135 : : out_put_task:
136 : : put_task_struct(task);
137 : : out:
138 : 2 : return error;
139 : : }
140 : :
141 : 0 : static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen)
142 : : {
143 : 0 : struct inode *inode = dentry->d_inode;
144 : : struct proc_inode *ei = PROC_I(inode);
145 : 0 : const struct proc_ns_operations *ns_ops = ei->ns.ns_ops;
146 : : struct task_struct *task;
147 : : void *ns;
148 : : char name[50];
149 : : int len = -EACCES;
150 : :
151 : : task = get_proc_task(inode);
152 [ # # ]: 0 : if (!task)
153 : : goto out;
154 : :
155 [ # # ]: 0 : if (!ptrace_may_access(task, PTRACE_MODE_READ))
156 : : goto out_put_task;
157 : :
158 : : len = -ENOENT;
159 : 0 : ns = ns_ops->get(task);
160 [ # # ]: 0 : if (!ns)
161 : : goto out_put_task;
162 : :
163 : 0 : snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns));
164 : 0 : len = strlen(name);
165 : :
166 [ # # ]: 0 : if (len > buflen)
167 : : len = buflen;
168 [ # # ]: 0 : if (copy_to_user(buffer, name, len))
169 : : len = -EFAULT;
170 : :
171 : 0 : ns_ops->put(ns);
172 : : out_put_task:
173 : : put_task_struct(task);
174 : : out:
175 : 0 : return len;
176 : : }
177 : :
178 : : static const struct inode_operations proc_ns_link_inode_operations = {
179 : : .readlink = proc_ns_readlink,
180 : : .follow_link = proc_ns_follow_link,
181 : : .setattr = proc_setattr,
182 : : };
183 : :
184 : 0 : static int proc_ns_instantiate(struct inode *dir,
185 : : struct dentry *dentry, struct task_struct *task, const void *ptr)
186 : : {
187 : : const struct proc_ns_operations *ns_ops = ptr;
188 : : struct inode *inode;
189 : : struct proc_inode *ei;
190 : :
191 : 3 : inode = proc_pid_make_inode(dir->i_sb, task);
192 [ + - ]: 3 : if (!inode)
193 : : goto out;
194 : :
195 : : ei = PROC_I(inode);
196 : 3 : inode->i_mode = S_IFLNK|S_IRWXUGO;
197 : 3 : inode->i_op = &proc_ns_link_inode_operations;
198 : 3 : ei->ns.ns_ops = ns_ops;
199 : :
200 : 3 : d_set_d_op(dentry, &pid_dentry_operations);
201 : : d_add(dentry, inode);
202 : : /* Close the race of the process dying before we return the dentry */
203 [ - + ]: 3 : if (pid_revalidate(dentry, 0))
204 : : return 0;
205 : : out:
206 : : return -ENOENT;
207 : : }
208 : :
209 : 0 : static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx)
210 : : {
211 : : struct task_struct *task = get_proc_task(file_inode(file));
212 : : const struct proc_ns_operations **entry, **last;
213 : :
214 [ + - ]: 4 : if (!task)
215 : : return -ENOENT;
216 : :
217 [ + - ]: 4 : if (!dir_emit_dots(file, ctx))
218 : : goto out;
219 [ + + ]: 4 : if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries))
220 : : goto out;
221 : 2 : entry = ns_entries + (ctx->pos - 2);
222 : : last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
223 [ + + ]: 4 : while (entry <= last) {
224 : 2 : const struct proc_ns_operations *ops = *entry;
225 [ + - ]: 2 : if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name),
226 : : proc_ns_instantiate, task, ops))
227 : : break;
228 : 2 : ctx->pos++;
229 : 2 : entry++;
230 : : }
231 : : out:
232 : : put_task_struct(task);
233 : : return 0;
234 : : }
235 : :
236 : : const struct file_operations proc_ns_dir_operations = {
237 : : .read = generic_read_dir,
238 : : .iterate = proc_ns_dir_readdir,
239 : : };
240 : :
241 : 0 : static struct dentry *proc_ns_dir_lookup(struct inode *dir,
242 : : struct dentry *dentry, unsigned int flags)
243 : : {
244 : : int error;
245 : : struct task_struct *task = get_proc_task(dir);
246 : : const struct proc_ns_operations **entry, **last;
247 : 7 : unsigned int len = dentry->d_name.len;
248 : :
249 : : error = -ENOENT;
250 : :
251 [ + - ]: 7 : if (!task)
252 : : goto out_no_task;
253 : :
254 : : last = &ns_entries[ARRAY_SIZE(ns_entries)];
255 [ + + ]: 13 : for (entry = ns_entries; entry < last; entry++) {
256 [ - + ]: 7 : if (strlen((*entry)->name) != len)
257 : 0 : continue;
258 [ + + ]: 7 : if (!memcmp(dentry->d_name.name, (*entry)->name, len))
259 : : break;
260 : : }
261 [ + + ]: 7 : if (entry == last)
262 : : goto out;
263 : :
264 : 1 : error = proc_ns_instantiate(dir, dentry, task, *entry);
265 : : out:
266 : : put_task_struct(task);
267 : : out_no_task:
268 : 7 : return ERR_PTR(error);
269 : : }
270 : :
271 : : const struct inode_operations proc_ns_dir_inode_operations = {
272 : : .lookup = proc_ns_dir_lookup,
273 : : .getattr = pid_getattr,
274 : : .setattr = proc_setattr,
275 : : };
276 : :
277 : 0 : struct file *proc_ns_fget(int fd)
278 : : {
279 : : struct file *file;
280 : :
281 : 6 : file = fget(fd);
282 [ + + ]: 6 : if (!file)
283 : : return ERR_PTR(-EBADF);
284 : :
285 [ + + ]: 3 : if (file->f_op != &ns_file_operations)
286 : : goto out_invalid;
287 : :
288 : : return file;
289 : :
290 : : out_invalid:
291 : 1 : fput(file);
292 : 1 : return ERR_PTR(-EINVAL);
293 : : }
294 : :
295 : 0 : struct proc_ns *get_proc_ns(struct inode *inode)
296 : : {
297 : 2 : return &PROC_I(inode)->ns;
298 : : }
299 : :
300 : 0 : bool proc_ns_inode(struct inode *inode)
301 : : {
302 : 1245 : return inode->i_fop == &ns_file_operations;
303 : : }
|