Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : #include <linux/proc_fs.h>
3 : : #include <linux/nsproxy.h>
4 : : #include <linux/ptrace.h>
5 : : #include <linux/namei.h>
6 : : #include <linux/file.h>
7 : : #include <linux/utsname.h>
8 : : #include <net/net_namespace.h>
9 : : #include <linux/ipc_namespace.h>
10 : : #include <linux/pid_namespace.h>
11 : : #include <linux/user_namespace.h>
12 : : #include "internal.h"
13 : :
14 : :
15 : : static const struct proc_ns_operations *ns_entries[] = {
16 : : #ifdef CONFIG_NET_NS
17 : : &netns_operations,
18 : : #endif
19 : : #ifdef CONFIG_UTS_NS
20 : : &utsns_operations,
21 : : #endif
22 : : #ifdef CONFIG_IPC_NS
23 : : &ipcns_operations,
24 : : #endif
25 : : #ifdef CONFIG_PID_NS
26 : : &pidns_operations,
27 : : &pidns_for_children_operations,
28 : : #endif
29 : : #ifdef CONFIG_USER_NS
30 : : &userns_operations,
31 : : #endif
32 : : &mntns_operations,
33 : : #ifdef CONFIG_CGROUPS
34 : : &cgroupns_operations,
35 : : #endif
36 : : #ifdef CONFIG_TIME_NS
37 : : &timens_operations,
38 : : &timens_for_children_operations,
39 : : #endif
40 : : };
41 : :
42 : 0 : static const char *proc_ns_get_link(struct dentry *dentry,
43 : : struct inode *inode,
44 : : struct delayed_call *done)
45 : : {
46 [ # # ]: 0 : const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
47 : 0 : struct task_struct *task;
48 : 0 : struct path ns_path;
49 : 0 : int error = -EACCES;
50 : :
51 [ # # ]: 0 : if (!dentry)
52 : : return ERR_PTR(-ECHILD);
53 : :
54 : 0 : task = get_proc_task(inode);
55 [ # # ]: 0 : if (!task)
56 : : return ERR_PTR(-EACCES);
57 : :
58 [ # # ]: 0 : if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
59 : 0 : goto out;
60 : :
61 : 0 : error = ns_get_path(&ns_path, task, ns_ops);
62 [ # # ]: 0 : if (error)
63 : 0 : goto out;
64 : :
65 : 0 : error = nd_jump_link(&ns_path);
66 : 0 : out:
67 : 0 : put_task_struct(task);
68 : 0 : return ERR_PTR(error);
69 : : }
70 : :
71 : 0 : static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen)
72 : : {
73 : 0 : struct inode *inode = d_inode(dentry);
74 : 0 : const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
75 : 0 : struct task_struct *task;
76 : 0 : char name[50];
77 : 0 : int res = -EACCES;
78 : :
79 : 0 : task = get_proc_task(inode);
80 [ # # ]: 0 : if (!task)
81 : : return res;
82 : :
83 [ # # ]: 0 : if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
84 : 0 : res = ns_get_name(name, sizeof(name), task, ns_ops);
85 [ # # ]: 0 : if (res >= 0)
86 : 0 : res = readlink_copy(buffer, buflen, name);
87 : : }
88 : 0 : put_task_struct(task);
89 : 0 : return res;
90 : : }
91 : :
92 : : static const struct inode_operations proc_ns_link_inode_operations = {
93 : : .readlink = proc_ns_readlink,
94 : : .get_link = proc_ns_get_link,
95 : : .setattr = proc_setattr,
96 : : };
97 : :
98 : 0 : static struct dentry *proc_ns_instantiate(struct dentry *dentry,
99 : : struct task_struct *task, const void *ptr)
100 : : {
101 : 0 : const struct proc_ns_operations *ns_ops = ptr;
102 : 0 : struct inode *inode;
103 : 0 : struct proc_inode *ei;
104 : :
105 : 0 : inode = proc_pid_make_inode(dentry->d_sb, task, S_IFLNK | S_IRWXUGO);
106 [ # # ]: 0 : if (!inode)
107 : : return ERR_PTR(-ENOENT);
108 : :
109 : 0 : ei = PROC_I(inode);
110 : 0 : inode->i_op = &proc_ns_link_inode_operations;
111 : 0 : ei->ns_ops = ns_ops;
112 : 0 : pid_update_inode(task, inode);
113 : :
114 : 0 : d_set_d_op(dentry, &pid_dentry_operations);
115 : 0 : return d_splice_alias(inode, dentry);
116 : : }
117 : :
118 : 0 : static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx)
119 : : {
120 : 0 : struct task_struct *task = get_proc_task(file_inode(file));
121 : 0 : const struct proc_ns_operations **entry, **last;
122 : :
123 [ # # ]: 0 : if (!task)
124 : : return -ENOENT;
125 : :
126 [ # # ]: 0 : if (!dir_emit_dots(file, ctx))
127 : 0 : goto out;
128 [ # # ]: 0 : if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries))
129 : 0 : goto out;
130 : 0 : entry = ns_entries + (ctx->pos - 2);
131 : 0 : last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
132 [ # # ]: 0 : while (entry <= last) {
133 : 0 : const struct proc_ns_operations *ops = *entry;
134 [ # # ]: 0 : if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name),
135 : : proc_ns_instantiate, task, ops))
136 : : break;
137 : 0 : ctx->pos++;
138 : 0 : entry++;
139 : : }
140 : 0 : out:
141 : 0 : put_task_struct(task);
142 : 0 : return 0;
143 : : }
144 : :
145 : : const struct file_operations proc_ns_dir_operations = {
146 : : .read = generic_read_dir,
147 : : .iterate_shared = proc_ns_dir_readdir,
148 : : .llseek = generic_file_llseek,
149 : : };
150 : :
151 : 0 : static struct dentry *proc_ns_dir_lookup(struct inode *dir,
152 : : struct dentry *dentry, unsigned int flags)
153 : : {
154 : 0 : struct task_struct *task = get_proc_task(dir);
155 : 0 : const struct proc_ns_operations **entry, **last;
156 : 0 : unsigned int len = dentry->d_name.len;
157 [ # # ]: 0 : struct dentry *res = ERR_PTR(-ENOENT);
158 : :
159 [ # # ]: 0 : if (!task)
160 : 0 : goto out_no_task;
161 : :
162 : : last = &ns_entries[ARRAY_SIZE(ns_entries)];
163 [ # # ]: 0 : for (entry = ns_entries; entry < last; entry++) {
164 [ # # ]: 0 : if (strlen((*entry)->name) != len)
165 : 0 : continue;
166 [ # # ]: 0 : if (!memcmp(dentry->d_name.name, (*entry)->name, len))
167 : : break;
168 : : }
169 [ # # ]: 0 : if (entry == last)
170 : 0 : goto out;
171 : :
172 : 0 : res = proc_ns_instantiate(dentry, task, *entry);
173 : 0 : out:
174 : 0 : put_task_struct(task);
175 : 0 : out_no_task:
176 : 0 : return res;
177 : : }
178 : :
179 : : const struct inode_operations proc_ns_dir_inode_operations = {
180 : : .lookup = proc_ns_dir_lookup,
181 : : .getattr = pid_getattr,
182 : : .setattr = proc_setattr,
183 : : };
|