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 : struct task_struct *task;
48 : 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 : goto out;
60 :
61 0 : error = ns_get_path(&ns_path, task, ns_ops);
62 0 : if (error)
63 : goto out;
64 :
65 0 : error = nd_jump_link(&ns_path);
66 : 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 : struct task_struct *task;
76 : 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 : struct inode *inode;
103 : 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 : 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 : goto out;
128 0 : if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries))
129 : 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 : 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 : 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 : 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 : goto out;
171 :
172 0 : res = proc_ns_instantiate(dentry, task, *entry);
173 : out:
174 0 : put_task_struct(task);
175 : 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 : };
|