Blame view

fs/proc/namespaces.c 4.19 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
6b4e306aa   Eric W. Biederman   ns: proc files fo...
2
3
  #include <linux/proc_fs.h>
  #include <linux/nsproxy.h>
6b4e306aa   Eric W. Biederman   ns: proc files fo...
4
  #include <linux/ptrace.h>
6b4e306aa   Eric W. Biederman   ns: proc files fo...
5
6
7
8
  #include <linux/namei.h>
  #include <linux/file.h>
  #include <linux/utsname.h>
  #include <net/net_namespace.h>
6b4e306aa   Eric W. Biederman   ns: proc files fo...
9
10
  #include <linux/ipc_namespace.h>
  #include <linux/pid_namespace.h>
cde1975bc   Eric W. Biederman   userns: Implent p...
11
  #include <linux/user_namespace.h>
6b4e306aa   Eric W. Biederman   ns: proc files fo...
12
13
14
15
  #include "internal.h"
  
  
  static const struct proc_ns_operations *ns_entries[] = {
13b6f5762   Eric W. Biederman   ns proc: Add supp...
16
17
18
  #ifdef CONFIG_NET_NS
  	&netns_operations,
  #endif
34482e89a   Eric W. Biederman   ns proc: Add supp...
19
20
21
  #ifdef CONFIG_UTS_NS
  	&utsns_operations,
  #endif
a00eaf11a   Eric W. Biederman   ns proc: Add supp...
22
23
24
  #ifdef CONFIG_IPC_NS
  	&ipcns_operations,
  #endif
57e8391d3   Eric W. Biederman   pidns: Add setns ...
25
26
  #ifdef CONFIG_PID_NS
  	&pidns_operations,
eaa0d190b   Kirill Tkhai   pidns: expose tas...
27
  	&pidns_for_children_operations,
57e8391d3   Eric W. Biederman   pidns: Add setns ...
28
  #endif
cde1975bc   Eric W. Biederman   userns: Implent p...
29
30
31
  #ifdef CONFIG_USER_NS
  	&userns_operations,
  #endif
8823c079b   Eric W. Biederman   vfs: Add setns su...
32
  	&mntns_operations,
a79a908fd   Aditya Kali   cgroup: introduce...
33
34
35
  #ifdef CONFIG_CGROUPS
  	&cgroupns_operations,
  #endif
6b4e306aa   Eric W. Biederman   ns: proc files fo...
36
  };
6b2553918   Al Viro   replace ->follow_...
37
  static const char *proc_ns_get_link(struct dentry *dentry,
fceef393a   Al Viro   switch ->get_link...
38
39
  				    struct inode *inode,
  				    struct delayed_call *done)
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
40
  {
3d3d35b1e   Al Viro   kill proc_ns comp...
41
  	const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
42
  	struct task_struct *task;
db04dc679   Eric W. Biederman   proc: Use nd_jump...
43
  	struct path ns_path;
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
44
  	void *error = ERR_PTR(-EACCES);
6b2553918   Al Viro   replace ->follow_...
45
46
  	if (!dentry)
  		return ERR_PTR(-ECHILD);
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
47
48
  	task = get_proc_task(inode);
  	if (!task)
e149ed2b8   Al Viro   take the targets ...
49
  		return error;
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
50

caaee6234   Jann Horn   ptrace: use fsuid...
51
  	if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
e149ed2b8   Al Viro   take the targets ...
52
53
  		error = ns_get_path(&ns_path, task, ns_ops);
  		if (!error)
6e77137b3   Al Viro   don't pass nameid...
54
  			nd_jump_link(&ns_path);
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
55
  	}
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
56
  	put_task_struct(task);
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
57
58
59
60
61
  	return error;
  }
  
  static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen)
  {
2b0143b5c   David Howells   VFS: normal files...
62
  	struct inode *inode = d_inode(dentry);
3d3d35b1e   Al Viro   kill proc_ns comp...
63
  	const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
64
  	struct task_struct *task;
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
65
  	char name[50];
5d826c847   Al Viro   new helper: readl...
66
  	int res = -EACCES;
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
67
68
69
  
  	task = get_proc_task(inode);
  	if (!task)
e149ed2b8   Al Viro   take the targets ...
70
  		return res;
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
71

caaee6234   Jann Horn   ptrace: use fsuid...
72
  	if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
e149ed2b8   Al Viro   take the targets ...
73
74
75
76
  		res = ns_get_name(name, sizeof(name), task, ns_ops);
  		if (res >= 0)
  			res = readlink_copy(buffer, buflen, name);
  	}
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
77
  	put_task_struct(task);
5d826c847   Al Viro   new helper: readl...
78
  	return res;
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
79
80
81
82
  }
  
  static const struct inode_operations proc_ns_link_inode_operations = {
  	.readlink	= proc_ns_readlink,
6b2553918   Al Viro   replace ->follow_...
83
  	.get_link	= proc_ns_get_link,
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
84
85
  	.setattr	= proc_setattr,
  };
c52a47ace   Al Viro   proc_fill_cache()...
86
  static int proc_ns_instantiate(struct inode *dir,
6b4e306aa   Eric W. Biederman   ns: proc files fo...
87
88
89
90
91
  	struct dentry *dentry, struct task_struct *task, const void *ptr)
  {
  	const struct proc_ns_operations *ns_ops = ptr;
  	struct inode *inode;
  	struct proc_inode *ei;
6b4e306aa   Eric W. Biederman   ns: proc files fo...
92

db978da8f   Andreas Gruenbacher   proc: Pass file m...
93
  	inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK | S_IRWXUGO);
6b4e306aa   Eric W. Biederman   ns: proc files fo...
94
95
96
97
  	if (!inode)
  		goto out;
  
  	ei = PROC_I(inode);
bf056bfa8   Eric W. Biederman   proc: Fix the nam...
98
  	inode->i_op = &proc_ns_link_inode_operations;
3d3d35b1e   Al Viro   kill proc_ns comp...
99
  	ei->ns_ops = ns_ops;
6b4e306aa   Eric W. Biederman   ns: proc files fo...
100

1b26c9b33   Pravin B Shelar   proc-ns: use d_se...
101
  	d_set_d_op(dentry, &pid_dentry_operations);
6b4e306aa   Eric W. Biederman   ns: proc files fo...
102
103
  	d_add(dentry, inode);
  	/* Close the race of the process dying before we return the dentry */
0b728e191   Al Viro   stop passing name...
104
  	if (pid_revalidate(dentry, 0))
c52a47ace   Al Viro   proc_fill_cache()...
105
  		return 0;
6b4e306aa   Eric W. Biederman   ns: proc files fo...
106
  out:
c52a47ace   Al Viro   proc_fill_cache()...
107
  	return -ENOENT;
6b4e306aa   Eric W. Biederman   ns: proc files fo...
108
  }
f0c3b5093   Al Viro   [readdir] convert...
109
  static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx)
6b4e306aa   Eric W. Biederman   ns: proc files fo...
110
  {
f0c3b5093   Al Viro   [readdir] convert...
111
  	struct task_struct *task = get_proc_task(file_inode(file));
6b4e306aa   Eric W. Biederman   ns: proc files fo...
112
  	const struct proc_ns_operations **entry, **last;
6b4e306aa   Eric W. Biederman   ns: proc files fo...
113

6b4e306aa   Eric W. Biederman   ns: proc files fo...
114
  	if (!task)
f0c3b5093   Al Viro   [readdir] convert...
115
  		return -ENOENT;
6b4e306aa   Eric W. Biederman   ns: proc files fo...
116

f0c3b5093   Al Viro   [readdir] convert...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
  	if (!dir_emit_dots(file, ctx))
  		goto out;
  	if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries))
  		goto out;
  	entry = ns_entries + (ctx->pos - 2);
  	last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
  	while (entry <= last) {
  		const struct proc_ns_operations *ops = *entry;
  		if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name),
  				     proc_ns_instantiate, task, ops))
  			break;
  		ctx->pos++;
  		entry++;
  	}
6b4e306aa   Eric W. Biederman   ns: proc files fo...
131
132
  out:
  	put_task_struct(task);
f0c3b5093   Al Viro   [readdir] convert...
133
  	return 0;
6b4e306aa   Eric W. Biederman   ns: proc files fo...
134
135
136
137
  }
  
  const struct file_operations proc_ns_dir_operations = {
  	.read		= generic_read_dir,
f50752eaa   Al Viro   switch all procfs...
138
139
  	.iterate_shared	= proc_ns_dir_readdir,
  	.llseek		= generic_file_llseek,
6b4e306aa   Eric W. Biederman   ns: proc files fo...
140
141
142
  };
  
  static struct dentry *proc_ns_dir_lookup(struct inode *dir,
00cd8dd3b   Al Viro   stop passing name...
143
  				struct dentry *dentry, unsigned int flags)
6b4e306aa   Eric W. Biederman   ns: proc files fo...
144
  {
c52a47ace   Al Viro   proc_fill_cache()...
145
  	int error;
6b4e306aa   Eric W. Biederman   ns: proc files fo...
146
147
148
  	struct task_struct *task = get_proc_task(dir);
  	const struct proc_ns_operations **entry, **last;
  	unsigned int len = dentry->d_name.len;
c52a47ace   Al Viro   proc_fill_cache()...
149
  	error = -ENOENT;
6b4e306aa   Eric W. Biederman   ns: proc files fo...
150
151
152
  
  	if (!task)
  		goto out_no_task;
4c619aa0b   Andrew Morton   fs/proc/namespace...
153
154
  	last = &ns_entries[ARRAY_SIZE(ns_entries)];
  	for (entry = ns_entries; entry < last; entry++) {
6b4e306aa   Eric W. Biederman   ns: proc files fo...
155
156
157
158
159
  		if (strlen((*entry)->name) != len)
  			continue;
  		if (!memcmp(dentry->d_name.name, (*entry)->name, len))
  			break;
  	}
4c619aa0b   Andrew Morton   fs/proc/namespace...
160
  	if (entry == last)
6b4e306aa   Eric W. Biederman   ns: proc files fo...
161
162
163
164
165
166
  		goto out;
  
  	error = proc_ns_instantiate(dir, dentry, task, *entry);
  out:
  	put_task_struct(task);
  out_no_task:
c52a47ace   Al Viro   proc_fill_cache()...
167
  	return ERR_PTR(error);
6b4e306aa   Eric W. Biederman   ns: proc files fo...
168
169
170
171
172
173
174
  }
  
  const struct inode_operations proc_ns_dir_inode_operations = {
  	.lookup		= proc_ns_dir_lookup,
  	.getattr	= pid_getattr,
  	.setattr	= proc_setattr,
  };