~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/proc/namespaces.c

Version: ~ [ linux-5.8 ] ~ [ linux-5.7.14 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.57 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.138 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.193 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.232 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.232 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #include <linux/proc_fs.h>
  2 #include <linux/nsproxy.h>
  3 #include <linux/ptrace.h>
  4 #include <linux/namei.h>
  5 #include <linux/file.h>
  6 #include <linux/utsname.h>
  7 #include <net/net_namespace.h>
  8 #include <linux/ipc_namespace.h>
  9 #include <linux/pid_namespace.h>
 10 #include <linux/user_namespace.h>
 11 #include "internal.h"
 12 
 13 
 14 static const struct proc_ns_operations *ns_entries[] = {
 15 #ifdef CONFIG_NET_NS
 16         &netns_operations,
 17 #endif
 18 #ifdef CONFIG_UTS_NS
 19         &utsns_operations,
 20 #endif
 21 #ifdef CONFIG_IPC_NS
 22         &ipcns_operations,
 23 #endif
 24 #ifdef CONFIG_PID_NS
 25         &pidns_operations,
 26 #endif
 27 #ifdef CONFIG_USER_NS
 28         &userns_operations,
 29 #endif
 30         &mntns_operations,
 31 };
 32 
 33 static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
 34 {
 35         struct inode *inode = dentry->d_inode;
 36         const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
 37         struct task_struct *task;
 38         struct path ns_path;
 39         void *error = ERR_PTR(-EACCES);
 40 
 41         task = get_proc_task(inode);
 42         if (!task)
 43                 return error;
 44 
 45         if (ptrace_may_access(task, PTRACE_MODE_READ)) {
 46                 error = ns_get_path(&ns_path, task, ns_ops);
 47                 if (!error)
 48                         nd_jump_link(nd, &ns_path);
 49         }
 50         put_task_struct(task);
 51         return error;
 52 }
 53 
 54 static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 55 {
 56         struct inode *inode = dentry->d_inode;
 57         const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
 58         struct task_struct *task;
 59         char name[50];
 60         int res = -EACCES;
 61 
 62         task = get_proc_task(inode);
 63         if (!task)
 64                 return res;
 65 
 66         if (ptrace_may_access(task, PTRACE_MODE_READ)) {
 67                 res = ns_get_name(name, sizeof(name), task, ns_ops);
 68                 if (res >= 0)
 69                         res = readlink_copy(buffer, buflen, name);
 70         }
 71         put_task_struct(task);
 72         return res;
 73 }
 74 
 75 static const struct inode_operations proc_ns_link_inode_operations = {
 76         .readlink       = proc_ns_readlink,
 77         .follow_link    = proc_ns_follow_link,
 78         .setattr        = proc_setattr,
 79 };
 80 
 81 static int proc_ns_instantiate(struct inode *dir,
 82         struct dentry *dentry, struct task_struct *task, const void *ptr)
 83 {
 84         const struct proc_ns_operations *ns_ops = ptr;
 85         struct inode *inode;
 86         struct proc_inode *ei;
 87 
 88         inode = proc_pid_make_inode(dir->i_sb, task);
 89         if (!inode)
 90                 goto out;
 91 
 92         ei = PROC_I(inode);
 93         inode->i_mode = S_IFLNK|S_IRWXUGO;
 94         inode->i_op = &proc_ns_link_inode_operations;
 95         ei->ns_ops = ns_ops;
 96 
 97         d_set_d_op(dentry, &pid_dentry_operations);
 98         d_add(dentry, inode);
 99         /* Close the race of the process dying before we return the dentry */
100         if (pid_revalidate(dentry, 0))
101                 return 0;
102 out:
103         return -ENOENT;
104 }
105 
106 static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx)
107 {
108         struct task_struct *task = get_proc_task(file_inode(file));
109         const struct proc_ns_operations **entry, **last;
110 
111         if (!task)
112                 return -ENOENT;
113 
114         if (!dir_emit_dots(file, ctx))
115                 goto out;
116         if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries))
117                 goto out;
118         entry = ns_entries + (ctx->pos - 2);
119         last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
120         while (entry <= last) {
121                 const struct proc_ns_operations *ops = *entry;
122                 if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name),
123                                      proc_ns_instantiate, task, ops))
124                         break;
125                 ctx->pos++;
126                 entry++;
127         }
128 out:
129         put_task_struct(task);
130         return 0;
131 }
132 
133 const struct file_operations proc_ns_dir_operations = {
134         .read           = generic_read_dir,
135         .iterate        = proc_ns_dir_readdir,
136 };
137 
138 static struct dentry *proc_ns_dir_lookup(struct inode *dir,
139                                 struct dentry *dentry, unsigned int flags)
140 {
141         int error;
142         struct task_struct *task = get_proc_task(dir);
143         const struct proc_ns_operations **entry, **last;
144         unsigned int len = dentry->d_name.len;
145 
146         error = -ENOENT;
147 
148         if (!task)
149                 goto out_no_task;
150 
151         last = &ns_entries[ARRAY_SIZE(ns_entries)];
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 ERR_PTR(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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp