1 #include <linux/proc_fs.h> 2 #include <linux/nsproxy.h> 3 #include <linux/sched.h> 4 #include <linux/ptrace.h> 5 #include <linux/fs_struct.h> 6 #include <linux/mount.h> 7 #include <linux/path.h> 8 #include <linux/namei.h> 9 #include <linux/file.h> 10 #include <linux/utsname.h> 11 #include <net/net_namespace.h> 12 #include <linux/mnt_namespace.h> 13 #include <linux/ipc_namespace.h> 14 #include <linux/pid_namespace.h> 15 #include "internal.h" 16 17 18 static const struct proc_ns_operations *ns_entries[] = { 19 #ifdef CONFIG_NET_NS 20 &netns_operations, 21 #endif 22 #ifdef CONFIG_UTS_NS 23 &utsns_operations, 24 #endif 25 #ifdef CONFIG_IPC_NS 26 &ipcns_operations, 27 #endif 28 }; 29 30 static const struct file_operations ns_file_operations = { 31 .llseek = no_llseek, 32 }; 33 34 static struct dentry *proc_ns_instantiate(struct inode *dir, 35 struct dentry *dentry, struct task_struct *task, const void *ptr) 36 { 37 const struct proc_ns_operations *ns_ops = ptr; 38 struct inode *inode; 39 struct proc_inode *ei; 40 struct dentry *error = ERR_PTR(-ENOENT); 41 void *ns; 42 43 inode = proc_pid_make_inode(dir->i_sb, task); 44 if (!inode) 45 goto out; 46 47 ns = ns_ops->get(task); 48 if (!ns) 49 goto out_iput; 50 51 ei = PROC_I(inode); 52 inode->i_mode = S_IFREG|S_IRUSR; 53 inode->i_fop = &ns_file_operations; 54 ei->ns_ops = ns_ops; 55 ei->ns = ns; 56 57 dentry->d_op = &pid_dentry_operations; 58 d_add(dentry, inode); 59 /* Close the race of the process dying before we return the dentry */ 60 if (pid_revalidate(dentry, NULL)) 61 error = NULL; 62 out: 63 return error; 64 out_iput: 65 iput(inode); 66 goto out; 67 } 68 69 static int proc_ns_fill_cache(struct file *filp, void *dirent, 70 filldir_t filldir, struct task_struct *task, 71 const struct proc_ns_operations *ops) 72 { 73 return proc_fill_cache(filp, dirent, filldir, 74 ops->name, strlen(ops->name), 75 proc_ns_instantiate, task, ops); 76 } 77 78 static int proc_ns_dir_readdir(struct file *filp, void *dirent, 79 filldir_t filldir) 80 { 81 int i; 82 struct dentry *dentry = filp->f_path.dentry; 83 struct inode *inode = dentry->d_inode; 84 struct task_struct *task = get_proc_task(inode); 85 const struct proc_ns_operations **entry, **last; 86 ino_t ino; 87 int ret; 88 89 ret = -ENOENT; 90 if (!task) 91 goto out_no_task; 92 93 ret = -EPERM; 94 if (!ptrace_may_access(task, PTRACE_MODE_READ)) 95 goto out; 96 97 ret = 0; 98 i = filp->f_pos; 99 switch (i) { 100 case 0: 101 ino = inode->i_ino; 102 if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) 103 goto out; 104 i++; 105 filp->f_pos++; 106 /* fall through */ 107 case 1: 108 ino = parent_ino(dentry); 109 if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) 110 goto out; 111 i++; 112 filp->f_pos++; 113 /* fall through */ 114 default: 115 i -= 2; 116 if (i >= ARRAY_SIZE(ns_entries)) { 117 ret = 1; 118 goto out; 119 } 120 entry = ns_entries + i; 121 last = &ns_entries[ARRAY_SIZE(ns_entries) - 1]; 122 while (entry <= last) { 123 if (proc_ns_fill_cache(filp, dirent, filldir, 124 task, *entry) < 0) 125 goto out; 126 filp->f_pos++; 127 entry++; 128 } 129 } 130 131 ret = 1; 132 out: 133 put_task_struct(task); 134 out_no_task: 135 return ret; 136 } 137 138 const struct file_operations proc_ns_dir_operations = { 139 .read = generic_read_dir, 140 .readdir = proc_ns_dir_readdir, 141 }; 142 143 static struct dentry *proc_ns_dir_lookup(struct inode *dir, 144 struct dentry *dentry, struct nameidata *nd) 145 { 146 struct dentry *error; 147 struct task_struct *task = get_proc_task(dir); 148 const struct proc_ns_operations **entry, **last; 149 unsigned int len = dentry->d_name.len; 150 151 error = ERR_PTR(-ENOENT); 152 153 if (!task) 154 goto out_no_task; 155 156 error = ERR_PTR(-EPERM); 157 if (!ptrace_may_access(task, PTRACE_MODE_READ)) 158 goto out; 159 160 last = &ns_entries[ARRAY_SIZE(ns_entries) - 1]; 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 error = ERR_PTR(-ENOENT); 168 if (entry > last) 169 goto out; 170 171 error = proc_ns_instantiate(dir, dentry, task, *entry); 172 out: 173 put_task_struct(task); 174 out_no_task: 175 return error; 176 } 177 178 const struct inode_operations proc_ns_dir_inode_operations = { 179 .lookup = proc_ns_dir_lookup, 180 .getattr = pid_getattr, 181 .setattr = proc_setattr, 182 }; 183 184 struct file *proc_ns_fget(int fd) 185 { 186 struct file *file; 187 188 file = fget(fd); 189 if (!file) 190 return ERR_PTR(-EBADF); 191 192 if (file->f_op != &ns_file_operations) 193 goto out_invalid; 194 195 return file; 196 197 out_invalid: 198 fput(file); 199 return ERR_PTR(-EINVAL); 200 } 201 202