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