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