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 static const char *proc_ns_get_link(struct dentry *dentry, 39 struct inode *inode, 40 struct delayed_call *done) 41 { 42 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 if (!dentry) 48 return ERR_PTR(-ECHILD); 49 50 task = get_proc_task(inode); 51 if (!task) 52 return error; 53 54 if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) { 55 error = ns_get_path(&ns_path, task, ns_ops); 56 if (!error) 57 nd_jump_link(&ns_path); 58 } 59 put_task_struct(task); 60 return error; 61 } 62 63 static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen) 64 { 65 struct inode *inode = d_inode(dentry); 66 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 if (!task) 73 return res; 74 75 if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) { 76 res = ns_get_name(name, sizeof(name), task, ns_ops); 77 if (res >= 0) 78 res = readlink_copy(buffer, buflen, name); 79 } 80 put_task_struct(task); 81 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 static int proc_ns_instantiate(struct inode *dir, 91 struct dentry *dentry, 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 inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK | S_IRWXUGO); 98 if (!inode) 99 goto out; 100 101 ei = PROC_I(inode); 102 inode->i_op = &proc_ns_link_inode_operations; 103 ei->ns_ops = ns_ops; 104 105 d_set_d_op(dentry, &pid_dentry_operations); 106 d_add(dentry, inode); 107 /* Close the race of the process dying before we return the dentry */ 108 if (pid_revalidate(dentry, 0)) 109 return 0; 110 out: 111 return -ENOENT; 112 } 113 114 static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx) 115 { 116 struct task_struct *task = get_proc_task(file_inode(file)); 117 const struct proc_ns_operations **entry, **last; 118 119 if (!task) 120 return -ENOENT; 121 122 if (!dir_emit_dots(file, ctx)) 123 goto out; 124 if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries)) 125 goto out; 126 entry = ns_entries + (ctx->pos - 2); 127 last = &ns_entries[ARRAY_SIZE(ns_entries) - 1]; 128 while (entry <= last) { 129 const struct proc_ns_operations *ops = *entry; 130 if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name), 131 proc_ns_instantiate, task, ops)) 132 break; 133 ctx->pos++; 134 entry++; 135 } 136 out: 137 put_task_struct(task); 138 return 0; 139 } 140 141 const struct file_operations proc_ns_dir_operations = { 142 .read = generic_read_dir, 143 .iterate_shared = proc_ns_dir_readdir, 144 .llseek = generic_file_llseek, 145 }; 146 147 static struct dentry *proc_ns_dir_lookup(struct inode *dir, 148 struct dentry *dentry, unsigned int flags) 149 { 150 int error; 151 struct task_struct *task = get_proc_task(dir); 152 const struct proc_ns_operations **entry, **last; 153 unsigned int len = dentry->d_name.len; 154 155 error = -ENOENT; 156 157 if (!task) 158 goto out_no_task; 159 160 last = &ns_entries[ARRAY_SIZE(ns_entries)]; 161 for (entry = ns_entries; entry < last; entry++) { 162 if (strlen((*entry)->name) != len) 163 continue; 164 if (!memcmp(dentry->d_name.name, (*entry)->name, len)) 165 break; 166 } 167 if (entry == last) 168 goto out; 169 170 error = proc_ns_instantiate(dir, dentry, task, *entry); 171 out: 172 put_task_struct(task); 173 out_no_task: 174 return ERR_PTR(error); 175 } 176 177 const struct inode_operations proc_ns_dir_inode_operations = { 178 .lookup = proc_ns_dir_lookup, 179 .getattr = pid_getattr, 180 .setattr = proc_setattr, 181 }; 182