Blame view
fs/proc/namespaces.c
4.19 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
6b4e306aa ns: proc files fo... |
2 3 |
#include <linux/proc_fs.h> #include <linux/nsproxy.h> |
6b4e306aa ns: proc files fo... |
4 |
#include <linux/ptrace.h> |
6b4e306aa 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 ns: proc files fo... |
9 10 |
#include <linux/ipc_namespace.h> #include <linux/pid_namespace.h> |
cde1975bc userns: Implent p... |
11 |
#include <linux/user_namespace.h> |
6b4e306aa ns: proc files fo... |
12 13 14 15 |
#include "internal.h" static const struct proc_ns_operations *ns_entries[] = { |
13b6f5762 ns proc: Add supp... |
16 17 18 |
#ifdef CONFIG_NET_NS &netns_operations, #endif |
34482e89a ns proc: Add supp... |
19 20 21 |
#ifdef CONFIG_UTS_NS &utsns_operations, #endif |
a00eaf11a ns proc: Add supp... |
22 23 24 |
#ifdef CONFIG_IPC_NS &ipcns_operations, #endif |
57e8391d3 pidns: Add setns ... |
25 26 |
#ifdef CONFIG_PID_NS &pidns_operations, |
eaa0d190b pidns: expose tas... |
27 |
&pidns_for_children_operations, |
57e8391d3 pidns: Add setns ... |
28 |
#endif |
cde1975bc userns: Implent p... |
29 30 31 |
#ifdef CONFIG_USER_NS &userns_operations, #endif |
8823c079b vfs: Add setns su... |
32 |
&mntns_operations, |
a79a908fd cgroup: introduce... |
33 34 35 |
#ifdef CONFIG_CGROUPS &cgroupns_operations, #endif |
6b4e306aa ns: proc files fo... |
36 |
}; |
6b2553918 replace ->follow_... |
37 |
static const char *proc_ns_get_link(struct dentry *dentry, |
fceef393a switch ->get_link... |
38 39 |
struct inode *inode, struct delayed_call *done) |
bf056bfa8 proc: Fix the nam... |
40 |
{ |
3d3d35b1e kill proc_ns comp... |
41 |
const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops; |
bf056bfa8 proc: Fix the nam... |
42 |
struct task_struct *task; |
db04dc679 proc: Use nd_jump... |
43 |
struct path ns_path; |
bf056bfa8 proc: Fix the nam... |
44 |
void *error = ERR_PTR(-EACCES); |
6b2553918 replace ->follow_... |
45 46 |
if (!dentry) return ERR_PTR(-ECHILD); |
bf056bfa8 proc: Fix the nam... |
47 48 |
task = get_proc_task(inode); if (!task) |
e149ed2b8 take the targets ... |
49 |
return error; |
bf056bfa8 proc: Fix the nam... |
50 |
|
caaee6234 ptrace: use fsuid... |
51 |
if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) { |
e149ed2b8 take the targets ... |
52 53 |
error = ns_get_path(&ns_path, task, ns_ops); if (!error) |
6e77137b3 don't pass nameid... |
54 |
nd_jump_link(&ns_path); |
bf056bfa8 proc: Fix the nam... |
55 |
} |
bf056bfa8 proc: Fix the nam... |
56 |
put_task_struct(task); |
bf056bfa8 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 VFS: normal files... |
62 |
struct inode *inode = d_inode(dentry); |
3d3d35b1e kill proc_ns comp... |
63 |
const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops; |
bf056bfa8 proc: Fix the nam... |
64 |
struct task_struct *task; |
bf056bfa8 proc: Fix the nam... |
65 |
char name[50]; |
5d826c847 new helper: readl... |
66 |
int res = -EACCES; |
bf056bfa8 proc: Fix the nam... |
67 68 69 |
task = get_proc_task(inode); if (!task) |
e149ed2b8 take the targets ... |
70 |
return res; |
bf056bfa8 proc: Fix the nam... |
71 |
|
caaee6234 ptrace: use fsuid... |
72 |
if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) { |
e149ed2b8 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 proc: Fix the nam... |
77 |
put_task_struct(task); |
5d826c847 new helper: readl... |
78 |
return res; |
bf056bfa8 proc: Fix the nam... |
79 80 81 82 |
} static const struct inode_operations proc_ns_link_inode_operations = { .readlink = proc_ns_readlink, |
6b2553918 replace ->follow_... |
83 |
.get_link = proc_ns_get_link, |
bf056bfa8 proc: Fix the nam... |
84 85 |
.setattr = proc_setattr, }; |
c52a47ace proc_fill_cache()... |
86 |
static int proc_ns_instantiate(struct inode *dir, |
6b4e306aa 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 ns: proc files fo... |
92 |
|
db978da8f proc: Pass file m... |
93 |
inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK | S_IRWXUGO); |
6b4e306aa ns: proc files fo... |
94 95 96 97 |
if (!inode) goto out; ei = PROC_I(inode); |
bf056bfa8 proc: Fix the nam... |
98 |
inode->i_op = &proc_ns_link_inode_operations; |
3d3d35b1e kill proc_ns comp... |
99 |
ei->ns_ops = ns_ops; |
6b4e306aa ns: proc files fo... |
100 |
|
1b26c9b33 proc-ns: use d_se... |
101 |
d_set_d_op(dentry, &pid_dentry_operations); |
6b4e306aa ns: proc files fo... |
102 103 |
d_add(dentry, inode); /* Close the race of the process dying before we return the dentry */ |
0b728e191 stop passing name... |
104 |
if (pid_revalidate(dentry, 0)) |
c52a47ace proc_fill_cache()... |
105 |
return 0; |
6b4e306aa ns: proc files fo... |
106 |
out: |
c52a47ace proc_fill_cache()... |
107 |
return -ENOENT; |
6b4e306aa ns: proc files fo... |
108 |
} |
f0c3b5093 [readdir] convert... |
109 |
static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx) |
6b4e306aa ns: proc files fo... |
110 |
{ |
f0c3b5093 [readdir] convert... |
111 |
struct task_struct *task = get_proc_task(file_inode(file)); |
6b4e306aa ns: proc files fo... |
112 |
const struct proc_ns_operations **entry, **last; |
6b4e306aa ns: proc files fo... |
113 |
|
6b4e306aa ns: proc files fo... |
114 |
if (!task) |
f0c3b5093 [readdir] convert... |
115 |
return -ENOENT; |
6b4e306aa ns: proc files fo... |
116 |
|
f0c3b5093 [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 ns: proc files fo... |
131 132 |
out: put_task_struct(task); |
f0c3b5093 [readdir] convert... |
133 |
return 0; |
6b4e306aa ns: proc files fo... |
134 135 136 137 |
} const struct file_operations proc_ns_dir_operations = { .read = generic_read_dir, |
f50752eaa switch all procfs... |
138 139 |
.iterate_shared = proc_ns_dir_readdir, .llseek = generic_file_llseek, |
6b4e306aa ns: proc files fo... |
140 141 142 |
}; static struct dentry *proc_ns_dir_lookup(struct inode *dir, |
00cd8dd3b stop passing name... |
143 |
struct dentry *dentry, unsigned int flags) |
6b4e306aa ns: proc files fo... |
144 |
{ |
c52a47ace proc_fill_cache()... |
145 |
int error; |
6b4e306aa 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 proc_fill_cache()... |
149 |
error = -ENOENT; |
6b4e306aa ns: proc files fo... |
150 151 152 |
if (!task) goto out_no_task; |
4c619aa0b fs/proc/namespace... |
153 154 |
last = &ns_entries[ARRAY_SIZE(ns_entries)]; for (entry = ns_entries; entry < last; entry++) { |
6b4e306aa 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 fs/proc/namespace... |
160 |
if (entry == last) |
6b4e306aa 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 proc_fill_cache()... |
167 |
return ERR_PTR(error); |
6b4e306aa 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, }; |