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 *const 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 static const char *proc_ns_get_link(struct dentry *dentry, 43 struct inode *inode, 44 struct delayed_call *done) 45 { 46 const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops; 47 struct task_struct *task; 48 struct path ns_path; 49 int error; 50 51 if (!dentry) 52 return ERR_PTR(-ECHILD); 53 54 task = get_proc_task(inode); 55 if (!task) 56 return ERR_PTR(-EACCES); 57 58 error = down_read_killable(&task->signal->exec_update_lock); 59 if (error) 60 goto out_put_task; 61 62 error = -EACCES; 63 if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) 64 goto out; 65 66 error = ns_get_path(&ns_path, task, ns_ops); 67 if (error) 68 goto out; 69 70 error = nd_jump_link(&ns_path); 71 out: 72 up_read(&task->signal->exec_update_lock); 73 out_put_task: 74 put_task_struct(task); 75 return ERR_PTR(error); 76 } 77 78 static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen) 79 { 80 struct inode *inode = d_inode(dentry); 81 const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops; 82 struct task_struct *task; 83 char name[50]; 84 int res = -EACCES; 85 86 task = get_proc_task(inode); 87 if (!task) 88 return res; 89 90 res = down_read_killable(&task->signal->exec_update_lock); 91 if (res) 92 goto out_put_task; 93 94 res = -EACCES; 95 if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) { 96 res = ns_get_name(name, sizeof(name), task, ns_ops); 97 if (res >= 0) 98 res = readlink_copy(buffer, buflen, name, strlen(name)); 99 } 100 up_read(&task->signal->exec_update_lock); 101 out_put_task: 102 put_task_struct(task); 103 return res; 104 } 105 106 static const struct inode_operations proc_ns_link_inode_operations = { 107 .readlink = proc_ns_readlink, 108 .get_link = proc_ns_get_link, 109 .setattr = proc_nochmod_setattr, 110 }; 111 112 static struct dentry *proc_ns_instantiate(struct dentry *dentry, 113 struct task_struct *task, const void *ptr) 114 { 115 const struct proc_ns_operations *ns_ops = ptr; 116 struct inode *inode; 117 struct proc_inode *ei; 118 119 inode = proc_pid_make_inode(dentry->d_sb, task, S_IFLNK | S_IRWXUGO); 120 if (!inode) 121 return ERR_PTR(-ENOENT); 122 123 ei = PROC_I(inode); 124 inode->i_op = &proc_ns_link_inode_operations; 125 ei->ns_ops = ns_ops; 126 pid_update_inode(task, inode); 127 128 return d_splice_alias_ops(inode, dentry, &pid_dentry_operations); 129 } 130 131 static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx) 132 { 133 struct task_struct *task = get_proc_task(file_inode(file)); 134 const struct proc_ns_operations *const *entry, *const *last; 135 136 if (!task) 137 return -ENOENT; 138 139 if (!dir_emit_dots(file, ctx)) 140 goto out; 141 if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries)) 142 goto out; 143 entry = ns_entries + (ctx->pos - 2); 144 last = &ns_entries[ARRAY_SIZE(ns_entries) - 1]; 145 while (entry <= last) { 146 const struct proc_ns_operations *ops = *entry; 147 if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name), 148 proc_ns_instantiate, task, ops)) 149 break; 150 ctx->pos++; 151 entry++; 152 } 153 out: 154 put_task_struct(task); 155 return 0; 156 } 157 158 const struct file_operations proc_ns_dir_operations = { 159 .read = generic_read_dir, 160 .iterate_shared = proc_ns_dir_readdir, 161 .llseek = generic_file_llseek, 162 }; 163 164 static struct dentry *proc_ns_dir_lookup(struct inode *dir, 165 struct dentry *dentry, unsigned int flags) 166 { 167 struct task_struct *task = get_proc_task(dir); 168 const struct proc_ns_operations *const *entry, *const *last; 169 unsigned int len = dentry->d_name.len; 170 struct dentry *res = ERR_PTR(-ENOENT); 171 172 if (!task) 173 goto out_no_task; 174 175 last = &ns_entries[ARRAY_SIZE(ns_entries)]; 176 for (entry = ns_entries; entry < last; entry++) { 177 if (strlen((*entry)->name) != len) 178 continue; 179 if (!memcmp(dentry->d_name.name, (*entry)->name, len)) 180 break; 181 } 182 if (entry == last) 183 goto out; 184 185 res = proc_ns_instantiate(dentry, task, *entry); 186 out: 187 put_task_struct(task); 188 out_no_task: 189 return res; 190 } 191 192 const struct inode_operations proc_ns_dir_inode_operations = { 193 .lookup = proc_ns_dir_lookup, 194 .getattr = pid_getattr, 195 .setattr = proc_nochmod_setattr, 196 }; 197