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 }; 26 27 static const struct file_operations ns_file_operations = { 28 .llseek = no_llseek, 29 }; 30 31 static struct dentry *proc_ns_instantiate(struct inode *dir, 32 struct dentry *dentry, struct task_struct *task, const void *ptr) 33 { 34 const struct proc_ns_operations *ns_ops = ptr; 35 struct inode *inode; 36 struct proc_inode *ei; 37 struct dentry *error = ERR_PTR(-ENOENT); 38 39 inode = proc_pid_make_inode(dir->i_sb, task); 40 if (!inode) 41 goto out; 42 43 ei = PROC_I(inode); 44 inode->i_mode = S_IFREG|S_IRUSR; 45 inode->i_fop = &ns_file_operations; 46 ei->ns_ops = ns_ops; 47 ei->ns = ns_ops->get(task); 48 if (!ei->ns) 49 goto out_iput; 50 51 dentry->d_op = &pid_dentry_operations; 52 d_add(dentry, inode); 53 /* Close the race of the process dying before we return the dentry */ 54 if (pid_revalidate(dentry, NULL)) 55 error = NULL; 56 out: 57 return error; 58 out_iput: 59 iput(inode); 60 goto out; 61 } 62 63 static int proc_ns_fill_cache(struct file *filp, void *dirent, 64 filldir_t filldir, struct task_struct *task, 65 const struct proc_ns_operations *ops) 66 { 67 return proc_fill_cache(filp, dirent, filldir, 68 ops->name, strlen(ops->name), 69 proc_ns_instantiate, task, ops); 70 } 71 72 static int proc_ns_dir_readdir(struct file *filp, void *dirent, 73 filldir_t filldir) 74 { 75 int i; 76 struct dentry *dentry = filp->f_path.dentry; 77 struct inode *inode = dentry->d_inode; 78 struct task_struct *task = get_proc_task(inode); 79 const struct proc_ns_operations **entry, **last; 80 ino_t ino; 81 int ret; 82 83 ret = -ENOENT; 84 if (!task) 85 goto out_no_task; 86 87 ret = -EPERM; 88 if (!ptrace_may_access(task, PTRACE_MODE_READ)) 89 goto out; 90 91 ret = 0; 92 i = filp->f_pos; 93 switch (i) { 94 case 0: 95 ino = inode->i_ino; 96 if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) 97 goto out; 98 i++; 99 filp->f_pos++; 100 /* fall through */ 101 case 1: 102 ino = parent_ino(dentry); 103 if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) 104 goto out; 105 i++; 106 filp->f_pos++; 107 /* fall through */ 108 default: 109 i -= 2; 110 if (i >= ARRAY_SIZE(ns_entries)) { 111 ret = 1; 112 goto out; 113 } 114 entry = ns_entries + i; 115 last = &ns_entries[ARRAY_SIZE(ns_entries) - 1]; 116 while (entry <= last) { 117 if (proc_ns_fill_cache(filp, dirent, filldir, 118 task, *entry) < 0) 119 goto out; 120 filp->f_pos++; 121 entry++; 122 } 123 } 124 125 ret = 1; 126 out: 127 put_task_struct(task); 128 out_no_task: 129 return ret; 130 } 131 132 const struct file_operations proc_ns_dir_operations = { 133 .read = generic_read_dir, 134 .readdir = proc_ns_dir_readdir, 135 }; 136 137 static struct dentry *proc_ns_dir_lookup(struct inode *dir, 138 struct dentry *dentry, struct nameidata *nd) 139 { 140 struct dentry *error; 141 struct task_struct *task = get_proc_task(dir); 142 const struct proc_ns_operations **entry, **last; 143 unsigned int len = dentry->d_name.len; 144 145 error = ERR_PTR(-ENOENT); 146 147 if (!task) 148 goto out_no_task; 149 150 error = ERR_PTR(-EPERM); 151 if (!ptrace_may_access(task, PTRACE_MODE_READ)) 152 goto out; 153 154 last = &ns_entries[ARRAY_SIZE(ns_entries) - 1]; 155 for (entry = ns_entries; entry <= last; entry++) { 156 if (strlen((*entry)->name) != len) 157 continue; 158 if (!memcmp(dentry->d_name.name, (*entry)->name, len)) 159 break; 160 } 161 if (entry > last) 162 goto out; 163 164 error = proc_ns_instantiate(dir, dentry, task, *entry); 165 out: 166 put_task_struct(task); 167 out_no_task: 168 return error; 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 }; 176 177 struct file *proc_ns_fget(int fd) 178 { 179 struct file *file; 180 181 file = fget(fd); 182 if (!file) 183 return ERR_PTR(-EBADF); 184 185 if (file->f_op != &ns_file_operations) 186 goto out_invalid; 187 188 return file; 189 190 out_invalid: 191 fput(file); 192 return ERR_PTR(-EINVAL); 193 } 194 195