Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs pile #2 from Al Viro:
"Next pile (and there'll be one or two more).

The large piece in this one is getting rid of /proc/*/ns/* weirdness;
among other things, it allows to (finally) make nameidata completely
opaque outside of fs/namei.c, making for easier further cleanups in
there"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
coda_venus_readdir(): use file_inode()
fs/namei.c: fold link_path_walk() call into path_init()
path_init(): don't bother with LOOKUP_PARENT in argument
fs/namei.c: new helper (path_cleanup())
path_init(): store the "base" pointer to file in nameidata itself
make default ->i_fop have ->open() fail with ENXIO
make nameidata completely opaque outside of fs/namei.c
kill proc_ns completely
take the targets of /proc/*/ns/* symlinks to separate fs
bury struct proc_ns in fs/proc
copy address of proc_ns_ops into ns_common
new helpers: ns_alloc_inum/ns_free_inum
make proc_ns_operations work with struct ns_common * instead of void *
switch the rest of proc_ns_operations to working with &...->ns
netns: switch ->get()/->put()/->install()/->inum() to working with &net->ns
make mntns ->get()/->put()/->install()/->inum() work with &mnt_ns->ns
common object embedded into various struct ....ns

+416 -430
-10
arch/ia64/kernel/perfmon.c
··· 2145 2145 return 0; 2146 2146 } 2147 2147 2148 - static int 2149 - pfm_no_open(struct inode *irrelevant, struct file *dontcare) 2150 - { 2151 - DPRINT(("pfm_no_open called\n")); 2152 - return -ENXIO; 2153 - } 2154 - 2155 - 2156 - 2157 2148 static const struct file_operations pfm_file_ops = { 2158 2149 .llseek = no_llseek, 2159 2150 .read = pfm_read, 2160 2151 .write = pfm_write, 2161 2152 .poll = pfm_poll, 2162 2153 .unlocked_ioctl = pfm_ioctl, 2163 - .open = pfm_no_open, /* special open code to disallow open via /proc */ 2164 2154 .fasync = pfm_fasync, 2165 2155 .release = pfm_close, 2166 2156 .flush = pfm_flush
+1 -1
fs/Makefile
··· 11 11 attr.o bad_inode.o file.o filesystems.o namespace.o \ 12 12 seq_file.o xattr.o libfs.o fs-writeback.o \ 13 13 pnode.o splice.o sync.o utimes.o \ 14 - stack.o fs_struct.o statfs.o fs_pin.o 14 + stack.o fs_struct.o statfs.o fs_pin.o nsfs.o 15 15 16 16 ifeq ($(CONFIG_BLOCK),y) 17 17 obj-y += buffer.o block_dev.o direct-io.o mpage.o
+1 -3
fs/coda/dir.c
··· 426 426 struct coda_file_info *cfi; 427 427 struct coda_inode_info *cii; 428 428 struct file *host_file; 429 - struct dentry *de; 430 429 struct venus_dirent *vdir; 431 430 unsigned long vdir_size = offsetof(struct venus_dirent, d_name); 432 431 unsigned int type; ··· 437 438 BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); 438 439 host_file = cfi->cfi_container; 439 440 440 - de = coda_file->f_path.dentry; 441 - cii = ITOC(de->d_inode); 441 + cii = ITOC(file_inode(coda_file)); 442 442 443 443 vdir = kmalloc(sizeof(*vdir), GFP_KERNEL); 444 444 if (!vdir) return -ENOMEM;
+8 -3
fs/inode.c
··· 114 114 } 115 115 #endif 116 116 117 + static int no_open(struct inode *inode, struct file *file) 118 + { 119 + return -ENXIO; 120 + } 121 + 117 122 /** 118 123 * inode_init_always - perform inode structure intialisation 119 124 * @sb: superblock inode belongs to ··· 130 125 int inode_init_always(struct super_block *sb, struct inode *inode) 131 126 { 132 127 static const struct inode_operations empty_iops; 133 - static const struct file_operations empty_fops; 128 + static const struct file_operations no_open_fops = {.open = no_open}; 134 129 struct address_space *const mapping = &inode->i_data; 135 130 136 131 inode->i_sb = sb; ··· 138 133 inode->i_flags = 0; 139 134 atomic_set(&inode->i_count, 1); 140 135 inode->i_op = &empty_iops; 141 - inode->i_fop = &empty_fops; 136 + inode->i_fop = &no_open_fops; 142 137 inode->__i_nlink = 1; 143 138 inode->i_opflags = 0; 144 139 i_uid_write(inode, 0); ··· 1803 1798 } else if (S_ISFIFO(mode)) 1804 1799 inode->i_fop = &pipefifo_fops; 1805 1800 else if (S_ISSOCK(mode)) 1806 - inode->i_fop = &bad_sock_fops; 1801 + ; /* leave it no_open_fops */ 1807 1802 else 1808 1803 printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for" 1809 1804 " inode %s:%lu\n", mode, inode->i_sb->s_id,
+5
fs/internal.h
··· 147 147 */ 148 148 extern void sb_pin_kill(struct super_block *sb); 149 149 extern void mnt_pin_kill(struct mount *m); 150 + 151 + /* 152 + * fs/nsfs.c 153 + */ 154 + extern struct dentry_operations ns_dentry_operations;
+2 -1
fs/mount.h
··· 1 1 #include <linux/mount.h> 2 2 #include <linux/seq_file.h> 3 3 #include <linux/poll.h> 4 + #include <linux/ns_common.h> 4 5 5 6 struct mnt_namespace { 6 7 atomic_t count; 7 - unsigned int proc_inum; 8 + struct ns_common ns; 8 9 struct mount * root; 9 10 struct list_head list; 10 11 struct user_namespace *user_ns;
+51 -47
fs/namei.c
··· 487 487 } 488 488 EXPORT_SYMBOL(path_put); 489 489 490 + struct nameidata { 491 + struct path path; 492 + struct qstr last; 493 + struct path root; 494 + struct inode *inode; /* path.dentry.d_inode */ 495 + unsigned int flags; 496 + unsigned seq, m_seq; 497 + int last_type; 498 + unsigned depth; 499 + struct file *base; 500 + char *saved_names[MAX_NESTED_LINKS + 1]; 501 + }; 502 + 490 503 /* 491 504 * Path walking has 2 modes, rcu-walk and ref-walk (see 492 505 * Documentation/filesystems/path-lookup.txt). In situations when we can't ··· 707 694 nd->inode = nd->path.dentry->d_inode; 708 695 nd->flags |= LOOKUP_JUMPED; 709 696 } 697 + 698 + void nd_set_link(struct nameidata *nd, char *path) 699 + { 700 + nd->saved_names[nd->depth] = path; 701 + } 702 + EXPORT_SYMBOL(nd_set_link); 703 + 704 + char *nd_get_link(struct nameidata *nd) 705 + { 706 + return nd->saved_names[nd->depth]; 707 + } 708 + EXPORT_SYMBOL(nd_get_link); 710 709 711 710 static inline void put_link(struct nameidata *nd, struct path *link, void *cookie) 712 711 { ··· 1846 1821 } 1847 1822 1848 1823 static int path_init(int dfd, const char *name, unsigned int flags, 1849 - struct nameidata *nd, struct file **fp) 1824 + struct nameidata *nd) 1850 1825 { 1851 1826 int retval = 0; 1852 1827 1853 1828 nd->last_type = LAST_ROOT; /* if there are only slashes... */ 1854 - nd->flags = flags | LOOKUP_JUMPED; 1829 + nd->flags = flags | LOOKUP_JUMPED | LOOKUP_PARENT; 1855 1830 nd->depth = 0; 1831 + nd->base = NULL; 1856 1832 if (flags & LOOKUP_ROOT) { 1857 1833 struct dentry *root = nd->root.dentry; 1858 1834 struct inode *inode = root->d_inode; ··· 1873 1847 } else { 1874 1848 path_get(&nd->path); 1875 1849 } 1876 - return 0; 1850 + goto done; 1877 1851 } 1878 1852 1879 1853 nd->root.mnt = NULL; ··· 1923 1897 nd->path = f.file->f_path; 1924 1898 if (flags & LOOKUP_RCU) { 1925 1899 if (f.flags & FDPUT_FPUT) 1926 - *fp = f.file; 1900 + nd->base = f.file; 1927 1901 nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); 1928 1902 rcu_read_lock(); 1929 1903 } else { ··· 1934 1908 1935 1909 nd->inode = nd->path.dentry->d_inode; 1936 1910 if (!(flags & LOOKUP_RCU)) 1937 - return 0; 1911 + goto done; 1938 1912 if (likely(!read_seqcount_retry(&nd->path.dentry->d_seq, nd->seq))) 1939 - return 0; 1913 + goto done; 1940 1914 if (!(nd->flags & LOOKUP_ROOT)) 1941 1915 nd->root.mnt = NULL; 1942 1916 rcu_read_unlock(); 1943 1917 return -ECHILD; 1918 + done: 1919 + current->total_link_count = 0; 1920 + return link_path_walk(name, nd); 1921 + } 1922 + 1923 + static void path_cleanup(struct nameidata *nd) 1924 + { 1925 + if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) { 1926 + path_put(&nd->root); 1927 + nd->root.mnt = NULL; 1928 + } 1929 + if (unlikely(nd->base)) 1930 + fput(nd->base); 1944 1931 } 1945 1932 1946 1933 static inline int lookup_last(struct nameidata *nd, struct path *path) ··· 1969 1930 static int path_lookupat(int dfd, const char *name, 1970 1931 unsigned int flags, struct nameidata *nd) 1971 1932 { 1972 - struct file *base = NULL; 1973 1933 struct path path; 1974 1934 int err; 1975 1935 ··· 1986 1948 * be handled by restarting a traditional ref-walk (which will always 1987 1949 * be able to complete). 1988 1950 */ 1989 - err = path_init(dfd, name, flags | LOOKUP_PARENT, nd, &base); 1990 - 1991 - if (unlikely(err)) 1992 - goto out; 1993 - 1994 - current->total_link_count = 0; 1995 - err = link_path_walk(name, nd); 1996 - 1951 + err = path_init(dfd, name, flags, nd); 1997 1952 if (!err && !(flags & LOOKUP_PARENT)) { 1998 1953 err = lookup_last(nd, &path); 1999 1954 while (err > 0) { ··· 2014 1983 } 2015 1984 } 2016 1985 2017 - out: 2018 - if (base) 2019 - fput(base); 2020 - 2021 - if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) { 2022 - path_put(&nd->root); 2023 - nd->root.mnt = NULL; 2024 - } 1986 + path_cleanup(nd); 2025 1987 return err; 2026 1988 } 2027 1989 ··· 2321 2297 static int 2322 2298 path_mountpoint(int dfd, const char *name, struct path *path, unsigned int flags) 2323 2299 { 2324 - struct file *base = NULL; 2325 2300 struct nameidata nd; 2326 2301 int err; 2327 2302 2328 - err = path_init(dfd, name, flags | LOOKUP_PARENT, &nd, &base); 2303 + err = path_init(dfd, name, flags, &nd); 2329 2304 if (unlikely(err)) 2330 - goto out; 2331 - 2332 - current->total_link_count = 0; 2333 - err = link_path_walk(name, &nd); 2334 - if (err) 2335 2305 goto out; 2336 2306 2337 2307 err = mountpoint_last(&nd, path); ··· 2343 2325 put_link(&nd, &link, cookie); 2344 2326 } 2345 2327 out: 2346 - if (base) 2347 - fput(base); 2348 - 2349 - if (nd.root.mnt && !(nd.flags & LOOKUP_ROOT)) 2350 - path_put(&nd.root); 2351 - 2328 + path_cleanup(&nd); 2352 2329 return err; 2353 2330 } 2354 2331 ··· 3194 3181 static struct file *path_openat(int dfd, struct filename *pathname, 3195 3182 struct nameidata *nd, const struct open_flags *op, int flags) 3196 3183 { 3197 - struct file *base = NULL; 3198 3184 struct file *file; 3199 3185 struct path path; 3200 3186 int opened = 0; ··· 3210 3198 goto out; 3211 3199 } 3212 3200 3213 - error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base); 3214 - if (unlikely(error)) 3215 - goto out; 3216 - 3217 - current->total_link_count = 0; 3218 - error = link_path_walk(pathname->name, nd); 3201 + error = path_init(dfd, pathname->name, flags, nd); 3219 3202 if (unlikely(error)) 3220 3203 goto out; 3221 3204 ··· 3236 3229 put_link(nd, &link, cookie); 3237 3230 } 3238 3231 out: 3239 - if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) 3240 - path_put(&nd->root); 3241 - if (base) 3242 - fput(base); 3232 + path_cleanup(nd); 3243 3233 if (!(opened & FILE_OPENED)) { 3244 3234 BUG_ON(!error); 3245 3235 put_filp(file);
+22 -29
fs/namespace.c
··· 1569 1569 static bool is_mnt_ns_file(struct dentry *dentry) 1570 1570 { 1571 1571 /* Is this a proxy for a mount namespace? */ 1572 - struct inode *inode = dentry->d_inode; 1573 - struct proc_ns *ei; 1572 + return dentry->d_op == &ns_dentry_operations && 1573 + dentry->d_fsdata == &mntns_operations; 1574 + } 1574 1575 1575 - if (!proc_ns_inode(inode)) 1576 - return false; 1577 - 1578 - ei = get_proc_ns(inode); 1579 - if (ei->ns_ops != &mntns_operations) 1580 - return false; 1581 - 1582 - return true; 1576 + struct mnt_namespace *to_mnt_ns(struct ns_common *ns) 1577 + { 1578 + return container_of(ns, struct mnt_namespace, ns); 1583 1579 } 1584 1580 1585 1581 static bool mnt_ns_loop(struct dentry *dentry) ··· 1587 1591 if (!is_mnt_ns_file(dentry)) 1588 1592 return false; 1589 1593 1590 - mnt_ns = get_proc_ns(dentry->d_inode)->ns; 1594 + mnt_ns = to_mnt_ns(get_proc_ns(dentry->d_inode)); 1591 1595 return current->nsproxy->mnt_ns->seq >= mnt_ns->seq; 1592 1596 } 1593 1597 ··· 2016 2020 if (IS_MNT_UNBINDABLE(old)) 2017 2021 goto out2; 2018 2022 2019 - if (!check_mnt(parent) || !check_mnt(old)) 2023 + if (!check_mnt(parent)) 2024 + goto out2; 2025 + 2026 + if (!check_mnt(old) && old_path.dentry->d_op != &ns_dentry_operations) 2020 2027 goto out2; 2021 2028 2022 2029 if (!recurse && has_locked_children(old, old_path.dentry)) ··· 2639 2640 2640 2641 static void free_mnt_ns(struct mnt_namespace *ns) 2641 2642 { 2642 - proc_free_inum(ns->proc_inum); 2643 + ns_free_inum(&ns->ns); 2643 2644 put_user_ns(ns->user_ns); 2644 2645 kfree(ns); 2645 2646 } ··· 2661 2662 new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL); 2662 2663 if (!new_ns) 2663 2664 return ERR_PTR(-ENOMEM); 2664 - ret = proc_alloc_inum(&new_ns->proc_inum); 2665 + ret = ns_alloc_inum(&new_ns->ns); 2665 2666 if (ret) { 2666 2667 kfree(new_ns); 2667 2668 return ERR_PTR(ret); 2668 2669 } 2670 + new_ns->ns.ops = &mntns_operations; 2669 2671 new_ns->seq = atomic64_add_return(1, &mnt_ns_seq); 2670 2672 atomic_set(&new_ns->count, 1); 2671 2673 new_ns->root = NULL; ··· 3144 3144 return visible; 3145 3145 } 3146 3146 3147 - static void *mntns_get(struct task_struct *task) 3147 + static struct ns_common *mntns_get(struct task_struct *task) 3148 3148 { 3149 - struct mnt_namespace *ns = NULL; 3149 + struct ns_common *ns = NULL; 3150 3150 struct nsproxy *nsproxy; 3151 3151 3152 3152 task_lock(task); 3153 3153 nsproxy = task->nsproxy; 3154 3154 if (nsproxy) { 3155 - ns = nsproxy->mnt_ns; 3156 - get_mnt_ns(ns); 3155 + ns = &nsproxy->mnt_ns->ns; 3156 + get_mnt_ns(to_mnt_ns(ns)); 3157 3157 } 3158 3158 task_unlock(task); 3159 3159 3160 3160 return ns; 3161 3161 } 3162 3162 3163 - static void mntns_put(void *ns) 3163 + static void mntns_put(struct ns_common *ns) 3164 3164 { 3165 - put_mnt_ns(ns); 3165 + put_mnt_ns(to_mnt_ns(ns)); 3166 3166 } 3167 3167 3168 - static int mntns_install(struct nsproxy *nsproxy, void *ns) 3168 + static int mntns_install(struct nsproxy *nsproxy, struct ns_common *ns) 3169 3169 { 3170 3170 struct fs_struct *fs = current->fs; 3171 - struct mnt_namespace *mnt_ns = ns; 3171 + struct mnt_namespace *mnt_ns = to_mnt_ns(ns); 3172 3172 struct path root; 3173 3173 3174 3174 if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) || ··· 3198 3198 return 0; 3199 3199 } 3200 3200 3201 - static unsigned int mntns_inum(void *ns) 3202 - { 3203 - struct mnt_namespace *mnt_ns = ns; 3204 - return mnt_ns->proc_inum; 3205 - } 3206 - 3207 3201 const struct proc_ns_operations mntns_operations = { 3208 3202 .name = "mnt", 3209 3203 .type = CLONE_NEWNS, 3210 3204 .get = mntns_get, 3211 3205 .put = mntns_put, 3212 3206 .install = mntns_install, 3213 - .inum = mntns_inum, 3214 3207 };
+161
fs/nsfs.c
··· 1 + #include <linux/mount.h> 2 + #include <linux/file.h> 3 + #include <linux/fs.h> 4 + #include <linux/proc_ns.h> 5 + #include <linux/magic.h> 6 + #include <linux/ktime.h> 7 + 8 + static struct vfsmount *nsfs_mnt; 9 + 10 + static const struct file_operations ns_file_operations = { 11 + .llseek = no_llseek, 12 + }; 13 + 14 + static char *ns_dname(struct dentry *dentry, char *buffer, int buflen) 15 + { 16 + struct inode *inode = dentry->d_inode; 17 + const struct proc_ns_operations *ns_ops = dentry->d_fsdata; 18 + 19 + return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]", 20 + ns_ops->name, inode->i_ino); 21 + } 22 + 23 + static void ns_prune_dentry(struct dentry *dentry) 24 + { 25 + struct inode *inode = dentry->d_inode; 26 + if (inode) { 27 + struct ns_common *ns = inode->i_private; 28 + atomic_long_set(&ns->stashed, 0); 29 + } 30 + } 31 + 32 + const struct dentry_operations ns_dentry_operations = 33 + { 34 + .d_prune = ns_prune_dentry, 35 + .d_delete = always_delete_dentry, 36 + .d_dname = ns_dname, 37 + }; 38 + 39 + static void nsfs_evict(struct inode *inode) 40 + { 41 + struct ns_common *ns = inode->i_private; 42 + clear_inode(inode); 43 + ns->ops->put(ns); 44 + } 45 + 46 + void *ns_get_path(struct path *path, struct task_struct *task, 47 + const struct proc_ns_operations *ns_ops) 48 + { 49 + struct vfsmount *mnt = mntget(nsfs_mnt); 50 + struct qstr qname = { .name = "", }; 51 + struct dentry *dentry; 52 + struct inode *inode; 53 + struct ns_common *ns; 54 + unsigned long d; 55 + 56 + again: 57 + ns = ns_ops->get(task); 58 + if (!ns) { 59 + mntput(mnt); 60 + return ERR_PTR(-ENOENT); 61 + } 62 + rcu_read_lock(); 63 + d = atomic_long_read(&ns->stashed); 64 + if (!d) 65 + goto slow; 66 + dentry = (struct dentry *)d; 67 + if (!lockref_get_not_dead(&dentry->d_lockref)) 68 + goto slow; 69 + rcu_read_unlock(); 70 + ns_ops->put(ns); 71 + got_it: 72 + path->mnt = mnt; 73 + path->dentry = dentry; 74 + return NULL; 75 + slow: 76 + rcu_read_unlock(); 77 + inode = new_inode_pseudo(mnt->mnt_sb); 78 + if (!inode) { 79 + ns_ops->put(ns); 80 + mntput(mnt); 81 + return ERR_PTR(-ENOMEM); 82 + } 83 + inode->i_ino = ns->inum; 84 + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; 85 + inode->i_flags |= S_IMMUTABLE; 86 + inode->i_mode = S_IFREG | S_IRUGO; 87 + inode->i_fop = &ns_file_operations; 88 + inode->i_private = ns; 89 + 90 + dentry = d_alloc_pseudo(mnt->mnt_sb, &qname); 91 + if (!dentry) { 92 + iput(inode); 93 + mntput(mnt); 94 + return ERR_PTR(-ENOMEM); 95 + } 96 + d_instantiate(dentry, inode); 97 + dentry->d_fsdata = (void *)ns_ops; 98 + d = atomic_long_cmpxchg(&ns->stashed, 0, (unsigned long)dentry); 99 + if (d) { 100 + d_delete(dentry); /* make sure ->d_prune() does nothing */ 101 + dput(dentry); 102 + cpu_relax(); 103 + goto again; 104 + } 105 + goto got_it; 106 + } 107 + 108 + int ns_get_name(char *buf, size_t size, struct task_struct *task, 109 + const struct proc_ns_operations *ns_ops) 110 + { 111 + struct ns_common *ns; 112 + int res = -ENOENT; 113 + ns = ns_ops->get(task); 114 + if (ns) { 115 + res = snprintf(buf, size, "%s:[%u]", ns_ops->name, ns->inum); 116 + ns_ops->put(ns); 117 + } 118 + return res; 119 + } 120 + 121 + struct file *proc_ns_fget(int fd) 122 + { 123 + struct file *file; 124 + 125 + file = fget(fd); 126 + if (!file) 127 + return ERR_PTR(-EBADF); 128 + 129 + if (file->f_op != &ns_file_operations) 130 + goto out_invalid; 131 + 132 + return file; 133 + 134 + out_invalid: 135 + fput(file); 136 + return ERR_PTR(-EINVAL); 137 + } 138 + 139 + static const struct super_operations nsfs_ops = { 140 + .statfs = simple_statfs, 141 + .evict_inode = nsfs_evict, 142 + }; 143 + static struct dentry *nsfs_mount(struct file_system_type *fs_type, 144 + int flags, const char *dev_name, void *data) 145 + { 146 + return mount_pseudo(fs_type, "nsfs:", &nsfs_ops, 147 + &ns_dentry_operations, NSFS_MAGIC); 148 + } 149 + static struct file_system_type nsfs = { 150 + .name = "nsfs", 151 + .mount = nsfs_mount, 152 + .kill_sb = kill_anon_super, 153 + }; 154 + 155 + void __init nsfs_init(void) 156 + { 157 + nsfs_mnt = kern_mount(&nsfs); 158 + if (IS_ERR(nsfs_mnt)) 159 + panic("can't set nsfs up\n"); 160 + nsfs_mnt->mnt_sb->s_flags &= ~MS_NOUSER; 161 + }
+1 -9
fs/proc/inode.c
··· 32 32 { 33 33 struct proc_dir_entry *de; 34 34 struct ctl_table_header *head; 35 - const struct proc_ns_operations *ns_ops; 36 - void *ns; 37 35 38 36 truncate_inode_pages_final(&inode->i_data); 39 37 clear_inode(inode); ··· 48 50 RCU_INIT_POINTER(PROC_I(inode)->sysctl, NULL); 49 51 sysctl_head_put(head); 50 52 } 51 - /* Release any associated namespace */ 52 - ns_ops = PROC_I(inode)->ns.ns_ops; 53 - ns = PROC_I(inode)->ns.ns; 54 - if (ns_ops && ns) 55 - ns_ops->put(ns); 56 53 } 57 54 58 55 static struct kmem_cache * proc_inode_cachep; ··· 66 73 ei->pde = NULL; 67 74 ei->sysctl = NULL; 68 75 ei->sysctl_entry = NULL; 69 - ei->ns.ns = NULL; 70 - ei->ns.ns_ops = NULL; 76 + ei->ns_ops = NULL; 71 77 inode = &ei->vfs_inode; 72 78 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; 73 79 return inode;
+1 -1
fs/proc/internal.h
··· 65 65 struct proc_dir_entry *pde; 66 66 struct ctl_table_header *sysctl; 67 67 struct ctl_table *sysctl_entry; 68 - struct proc_ns ns; 68 + const struct proc_ns_operations *ns_ops; 69 69 struct inode vfs_inode; 70 70 }; 71 71
+14 -139
fs/proc/namespaces.c
··· 1 1 #include <linux/proc_fs.h> 2 2 #include <linux/nsproxy.h> 3 - #include <linux/sched.h> 4 3 #include <linux/ptrace.h> 5 - #include <linux/fs_struct.h> 6 - #include <linux/mount.h> 7 - #include <linux/path.h> 8 4 #include <linux/namei.h> 9 5 #include <linux/file.h> 10 6 #include <linux/utsname.h> ··· 30 34 &mntns_operations, 31 35 }; 32 36 33 - static const struct file_operations ns_file_operations = { 34 - .llseek = no_llseek, 35 - }; 36 - 37 - static const struct inode_operations ns_inode_operations = { 38 - .setattr = proc_setattr, 39 - }; 40 - 41 - static char *ns_dname(struct dentry *dentry, char *buffer, int buflen) 42 - { 43 - struct inode *inode = dentry->d_inode; 44 - const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns.ns_ops; 45 - 46 - return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]", 47 - ns_ops->name, inode->i_ino); 48 - } 49 - 50 - const struct dentry_operations ns_dentry_operations = 51 - { 52 - .d_delete = always_delete_dentry, 53 - .d_dname = ns_dname, 54 - }; 55 - 56 - static struct dentry *proc_ns_get_dentry(struct super_block *sb, 57 - struct task_struct *task, const struct proc_ns_operations *ns_ops) 58 - { 59 - struct dentry *dentry, *result; 60 - struct inode *inode; 61 - struct proc_inode *ei; 62 - struct qstr qname = { .name = "", }; 63 - void *ns; 64 - 65 - ns = ns_ops->get(task); 66 - if (!ns) 67 - return ERR_PTR(-ENOENT); 68 - 69 - dentry = d_alloc_pseudo(sb, &qname); 70 - if (!dentry) { 71 - ns_ops->put(ns); 72 - return ERR_PTR(-ENOMEM); 73 - } 74 - 75 - inode = iget_locked(sb, ns_ops->inum(ns)); 76 - if (!inode) { 77 - dput(dentry); 78 - ns_ops->put(ns); 79 - return ERR_PTR(-ENOMEM); 80 - } 81 - 82 - ei = PROC_I(inode); 83 - if (inode->i_state & I_NEW) { 84 - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; 85 - inode->i_op = &ns_inode_operations; 86 - inode->i_mode = S_IFREG | S_IRUGO; 87 - inode->i_fop = &ns_file_operations; 88 - ei->ns.ns_ops = ns_ops; 89 - ei->ns.ns = ns; 90 - unlock_new_inode(inode); 91 - } else { 92 - ns_ops->put(ns); 93 - } 94 - 95 - d_set_d_op(dentry, &ns_dentry_operations); 96 - result = d_instantiate_unique(dentry, inode); 97 - if (result) { 98 - dput(dentry); 99 - dentry = result; 100 - } 101 - 102 - return dentry; 103 - } 104 - 105 37 static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd) 106 38 { 107 39 struct inode *inode = dentry->d_inode; 108 - struct super_block *sb = inode->i_sb; 109 - struct proc_inode *ei = PROC_I(inode); 40 + const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops; 110 41 struct task_struct *task; 111 42 struct path ns_path; 112 43 void *error = ERR_PTR(-EACCES); 113 44 114 45 task = get_proc_task(inode); 115 46 if (!task) 116 - goto out; 47 + return error; 117 48 118 - if (!ptrace_may_access(task, PTRACE_MODE_READ)) 119 - goto out_put_task; 120 - 121 - ns_path.dentry = proc_ns_get_dentry(sb, task, ei->ns.ns_ops); 122 - if (IS_ERR(ns_path.dentry)) { 123 - error = ERR_CAST(ns_path.dentry); 124 - goto out_put_task; 49 + if (ptrace_may_access(task, PTRACE_MODE_READ)) { 50 + error = ns_get_path(&ns_path, task, ns_ops); 51 + if (!error) 52 + nd_jump_link(nd, &ns_path); 125 53 } 126 - 127 - ns_path.mnt = mntget(nd->path.mnt); 128 - nd_jump_link(nd, &ns_path); 129 - error = NULL; 130 - 131 - out_put_task: 132 54 put_task_struct(task); 133 - out: 134 55 return error; 135 56 } 136 57 137 58 static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen) 138 59 { 139 60 struct inode *inode = dentry->d_inode; 140 - struct proc_inode *ei = PROC_I(inode); 141 - const struct proc_ns_operations *ns_ops = ei->ns.ns_ops; 61 + const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops; 142 62 struct task_struct *task; 143 - void *ns; 144 63 char name[50]; 145 64 int res = -EACCES; 146 65 147 66 task = get_proc_task(inode); 148 67 if (!task) 149 - goto out; 68 + return res; 150 69 151 - if (!ptrace_may_access(task, PTRACE_MODE_READ)) 152 - goto out_put_task; 153 - 154 - res = -ENOENT; 155 - ns = ns_ops->get(task); 156 - if (!ns) 157 - goto out_put_task; 158 - 159 - snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns)); 160 - res = readlink_copy(buffer, buflen, name); 161 - ns_ops->put(ns); 162 - out_put_task: 70 + if (ptrace_may_access(task, PTRACE_MODE_READ)) { 71 + res = ns_get_name(name, sizeof(name), task, ns_ops); 72 + if (res >= 0) 73 + res = readlink_copy(buffer, buflen, name); 74 + } 163 75 put_task_struct(task); 164 - out: 165 76 return res; 166 77 } 167 78 ··· 92 189 ei = PROC_I(inode); 93 190 inode->i_mode = S_IFLNK|S_IRWXUGO; 94 191 inode->i_op = &proc_ns_link_inode_operations; 95 - ei->ns.ns_ops = ns_ops; 192 + ei->ns_ops = ns_ops; 96 193 97 194 d_set_d_op(dentry, &pid_dentry_operations); 98 195 d_add(dentry, inode); ··· 170 267 .getattr = pid_getattr, 171 268 .setattr = proc_setattr, 172 269 }; 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 - struct proc_ns *get_proc_ns(struct inode *inode) 193 - { 194 - return &PROC_I(inode)->ns; 195 - } 196 - 197 - bool proc_ns_inode(struct inode *inode) 198 - { 199 - return inode->i_fop == &ns_file_operations; 200 - }
-1
include/linux/fs.h
··· 2176 2176 extern int sync_filesystem(struct super_block *); 2177 2177 extern const struct file_operations def_blk_fops; 2178 2178 extern const struct file_operations def_chr_fops; 2179 - extern const struct file_operations bad_sock_fops; 2180 2179 #ifdef CONFIG_BLOCK 2181 2180 extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long); 2182 2181 extern int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long);
+2 -1
include/linux/ipc_namespace.h
··· 6 6 #include <linux/rwsem.h> 7 7 #include <linux/notifier.h> 8 8 #include <linux/nsproxy.h> 9 + #include <linux/ns_common.h> 9 10 10 11 struct user_namespace; 11 12 ··· 59 58 /* user_ns which owns the ipc ns */ 60 59 struct user_namespace *user_ns; 61 60 62 - unsigned int proc_inum; 61 + struct ns_common ns; 63 62 }; 64 63 65 64 extern struct ipc_namespace init_ipc_ns;
+3 -22
include/linux/namei.h
··· 7 7 #include <linux/path.h> 8 8 9 9 struct vfsmount; 10 + struct nameidata; 10 11 11 12 enum { MAX_NESTED_LINKS = 8 }; 12 - 13 - struct nameidata { 14 - struct path path; 15 - struct qstr last; 16 - struct path root; 17 - struct inode *inode; /* path.dentry.d_inode */ 18 - unsigned int flags; 19 - unsigned seq, m_seq; 20 - int last_type; 21 - unsigned depth; 22 - char *saved_names[MAX_NESTED_LINKS + 1]; 23 - }; 24 13 25 14 /* 26 15 * Type of the last component on LOOKUP_PARENT ··· 71 82 extern void unlock_rename(struct dentry *, struct dentry *); 72 83 73 84 extern void nd_jump_link(struct nameidata *nd, struct path *path); 74 - 75 - static inline void nd_set_link(struct nameidata *nd, char *path) 76 - { 77 - nd->saved_names[nd->depth] = path; 78 - } 79 - 80 - static inline char *nd_get_link(struct nameidata *nd) 81 - { 82 - return nd->saved_names[nd->depth]; 83 - } 85 + extern void nd_set_link(struct nameidata *nd, char *path); 86 + extern char *nd_get_link(struct nameidata *nd); 84 87 85 88 static inline void nd_terminate_link(void *name, size_t len, size_t maxlen) 86 89 {
+12
include/linux/ns_common.h
··· 1 + #ifndef _LINUX_NS_COMMON_H 2 + #define _LINUX_NS_COMMON_H 3 + 4 + struct proc_ns_operations; 5 + 6 + struct ns_common { 7 + atomic_long_t stashed; 8 + const struct proc_ns_operations *ops; 9 + unsigned int inum; 10 + }; 11 + 12 + #endif
+2 -1
include/linux/pid_namespace.h
··· 8 8 #include <linux/threads.h> 9 9 #include <linux/nsproxy.h> 10 10 #include <linux/kref.h> 11 + #include <linux/ns_common.h> 11 12 12 13 struct pidmap { 13 14 atomic_t nr_free; ··· 44 43 kgid_t pid_gid; 45 44 int hide_pid; 46 45 int reboot; /* group exit code if this pidns was rebooted */ 47 - unsigned int proc_inum; 46 + struct ns_common ns; 48 47 }; 49 48 50 49 extern struct pid_namespace init_pid_ns;
+23 -20
include/linux/proc_ns.h
··· 4 4 #ifndef _LINUX_PROC_NS_H 5 5 #define _LINUX_PROC_NS_H 6 6 7 + #include <linux/ns_common.h> 8 + 7 9 struct pid_namespace; 8 10 struct nsproxy; 11 + struct path; 9 12 10 13 struct proc_ns_operations { 11 14 const char *name; 12 15 int type; 13 - void *(*get)(struct task_struct *task); 14 - void (*put)(void *ns); 15 - int (*install)(struct nsproxy *nsproxy, void *ns); 16 - unsigned int (*inum)(void *ns); 17 - }; 18 - 19 - struct proc_ns { 20 - void *ns; 21 - const struct proc_ns_operations *ns_ops; 16 + struct ns_common *(*get)(struct task_struct *task); 17 + void (*put)(struct ns_common *ns); 18 + int (*install)(struct nsproxy *nsproxy, struct ns_common *ns); 22 19 }; 23 20 24 21 extern const struct proc_ns_operations netns_operations; ··· 40 43 41 44 extern int pid_ns_prepare_proc(struct pid_namespace *ns); 42 45 extern void pid_ns_release_proc(struct pid_namespace *ns); 43 - extern struct file *proc_ns_fget(int fd); 44 - extern struct proc_ns *get_proc_ns(struct inode *); 45 46 extern int proc_alloc_inum(unsigned int *pino); 46 47 extern void proc_free_inum(unsigned int inum); 47 - extern bool proc_ns_inode(struct inode *inode); 48 48 49 49 #else /* CONFIG_PROC_FS */ 50 50 51 51 static inline int pid_ns_prepare_proc(struct pid_namespace *ns) { return 0; } 52 52 static inline void pid_ns_release_proc(struct pid_namespace *ns) {} 53 - 54 - static inline struct file *proc_ns_fget(int fd) 55 - { 56 - return ERR_PTR(-EINVAL); 57 - } 58 - 59 - static inline struct proc_ns *get_proc_ns(struct inode *inode) { return NULL; } 60 53 61 54 static inline int proc_alloc_inum(unsigned int *inum) 62 55 { ··· 54 67 return 0; 55 68 } 56 69 static inline void proc_free_inum(unsigned int inum) {} 57 - static inline bool proc_ns_inode(struct inode *inode) { return false; } 58 70 59 71 #endif /* CONFIG_PROC_FS */ 72 + 73 + static inline int ns_alloc_inum(struct ns_common *ns) 74 + { 75 + atomic_long_set(&ns->stashed, 0); 76 + return proc_alloc_inum(&ns->inum); 77 + } 78 + 79 + #define ns_free_inum(ns) proc_free_inum((ns)->inum) 80 + 81 + extern struct file *proc_ns_fget(int fd); 82 + #define get_proc_ns(inode) ((struct ns_common *)(inode)->i_private) 83 + extern void *ns_get_path(struct path *path, struct task_struct *task, 84 + const struct proc_ns_operations *ns_ops); 85 + 86 + extern int ns_get_name(char *buf, size_t size, struct task_struct *task, 87 + const struct proc_ns_operations *ns_ops); 88 + extern void nsfs_init(void); 60 89 61 90 #endif /* _LINUX_PROC_NS_H */
+2 -1
include/linux/user_namespace.h
··· 3 3 4 4 #include <linux/kref.h> 5 5 #include <linux/nsproxy.h> 6 + #include <linux/ns_common.h> 6 7 #include <linux/sched.h> 7 8 #include <linux/err.h> 8 9 ··· 27 26 int level; 28 27 kuid_t owner; 29 28 kgid_t group; 30 - unsigned int proc_inum; 29 + struct ns_common ns; 31 30 32 31 /* Register of per-UID persistent keyrings for this namespace */ 33 32 #ifdef CONFIG_PERSISTENT_KEYRINGS
+2 -1
include/linux/utsname.h
··· 5 5 #include <linux/sched.h> 6 6 #include <linux/kref.h> 7 7 #include <linux/nsproxy.h> 8 + #include <linux/ns_common.h> 8 9 #include <linux/err.h> 9 10 #include <uapi/linux/utsname.h> 10 11 ··· 24 23 struct kref kref; 25 24 struct new_utsname name; 26 25 struct user_namespace *user_ns; 27 - unsigned int proc_inum; 26 + struct ns_common ns; 28 27 }; 29 28 extern struct uts_namespace init_uts_ns; 30 29
+2 -1
include/net/net_namespace.h
··· 26 26 #endif 27 27 #include <net/netns/nftables.h> 28 28 #include <net/netns/xfrm.h> 29 + #include <linux/ns_common.h> 29 30 30 31 struct user_namespace; 31 32 struct proc_dir_entry; ··· 61 60 62 61 struct user_namespace *user_ns; /* Owning user namespace */ 63 62 64 - unsigned int proc_inum; 63 + struct ns_common ns; 65 64 66 65 struct proc_dir_entry *proc_net; 67 66 struct proc_dir_entry *proc_net_stat;
+1
include/uapi/linux/magic.h
··· 72 72 #define MTD_INODE_FS_MAGIC 0x11307854 73 73 #define ANON_INODE_FS_MAGIC 0x09041934 74 74 #define BTRFS_TEST_MAGIC 0x73727279 75 + #define NSFS_MAGIC 0x6e736673 75 76 76 77 #endif /* __LINUX_MAGIC_H__ */
+2
init/main.c
··· 79 79 #include <linux/random.h> 80 80 #include <linux/list.h> 81 81 #include <linux/integrity.h> 82 + #include <linux/proc_ns.h> 82 83 83 84 #include <asm/io.h> 84 85 #include <asm/bugs.h> ··· 666 665 /* rootfs populating might need page-writeback */ 667 666 page_writeback_init(); 668 667 proc_root_init(); 668 + nsfs_init(); 669 669 cgroup_init(); 670 670 cpuset_init(); 671 671 taskstats_init_early();
+4 -1
init/version.c
··· 35 35 .domainname = UTS_DOMAINNAME, 36 36 }, 37 37 .user_ns = &init_user_ns, 38 - .proc_inum = PROC_UTS_INIT_INO, 38 + .ns.inum = PROC_UTS_INIT_INO, 39 + #ifdef CONFIG_UTS_NS 40 + .ns.ops = &utsns_operations, 41 + #endif 39 42 }; 40 43 EXPORT_SYMBOL_GPL(init_uts_ns); 41 44
+4 -1
ipc/msgutil.c
··· 31 31 struct ipc_namespace init_ipc_ns = { 32 32 .count = ATOMIC_INIT(1), 33 33 .user_ns = &init_user_ns, 34 - .proc_inum = PROC_IPC_INIT_INO, 34 + .ns.inum = PROC_IPC_INIT_INO, 35 + #ifdef CONFIG_IPC_NS 36 + .ns.ops = &ipcns_operations, 37 + #endif 35 38 }; 36 39 37 40 atomic_t nr_ipc_ns = ATOMIC_INIT(1);
+15 -17
ipc/namespace.c
··· 26 26 if (ns == NULL) 27 27 return ERR_PTR(-ENOMEM); 28 28 29 - err = proc_alloc_inum(&ns->proc_inum); 29 + err = ns_alloc_inum(&ns->ns); 30 30 if (err) { 31 31 kfree(ns); 32 32 return ERR_PTR(err); 33 33 } 34 + ns->ns.ops = &ipcns_operations; 34 35 35 36 atomic_set(&ns->count, 1); 36 37 err = mq_init_ns(ns); 37 38 if (err) { 38 - proc_free_inum(ns->proc_inum); 39 + ns_free_inum(&ns->ns); 39 40 kfree(ns); 40 41 return ERR_PTR(err); 41 42 } ··· 98 97 atomic_dec(&nr_ipc_ns); 99 98 100 99 put_user_ns(ns->user_ns); 101 - proc_free_inum(ns->proc_inum); 100 + ns_free_inum(&ns->ns); 102 101 kfree(ns); 103 102 } 104 103 ··· 128 127 } 129 128 } 130 129 131 - static void *ipcns_get(struct task_struct *task) 130 + static inline struct ipc_namespace *to_ipc_ns(struct ns_common *ns) 131 + { 132 + return container_of(ns, struct ipc_namespace, ns); 133 + } 134 + 135 + static struct ns_common *ipcns_get(struct task_struct *task) 132 136 { 133 137 struct ipc_namespace *ns = NULL; 134 138 struct nsproxy *nsproxy; ··· 144 138 ns = get_ipc_ns(nsproxy->ipc_ns); 145 139 task_unlock(task); 146 140 147 - return ns; 141 + return ns ? &ns->ns : NULL; 148 142 } 149 143 150 - static void ipcns_put(void *ns) 144 + static void ipcns_put(struct ns_common *ns) 151 145 { 152 - return put_ipc_ns(ns); 146 + return put_ipc_ns(to_ipc_ns(ns)); 153 147 } 154 148 155 - static int ipcns_install(struct nsproxy *nsproxy, void *new) 149 + static int ipcns_install(struct nsproxy *nsproxy, struct ns_common *new) 156 150 { 157 - struct ipc_namespace *ns = new; 151 + struct ipc_namespace *ns = to_ipc_ns(new); 158 152 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) || 159 153 !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) 160 154 return -EPERM; ··· 166 160 return 0; 167 161 } 168 162 169 - static unsigned int ipcns_inum(void *vp) 170 - { 171 - struct ipc_namespace *ns = vp; 172 - 173 - return ns->proc_inum; 174 - } 175 - 176 163 const struct proc_ns_operations ipcns_operations = { 177 164 .name = "ipc", 178 165 .type = CLONE_NEWIPC, 179 166 .get = ipcns_get, 180 167 .put = ipcns_put, 181 168 .install = ipcns_install, 182 - .inum = ipcns_inum, 183 169 };
+4 -6
kernel/nsproxy.c
··· 220 220 221 221 SYSCALL_DEFINE2(setns, int, fd, int, nstype) 222 222 { 223 - const struct proc_ns_operations *ops; 224 223 struct task_struct *tsk = current; 225 224 struct nsproxy *new_nsproxy; 226 - struct proc_ns *ei; 227 225 struct file *file; 226 + struct ns_common *ns; 228 227 int err; 229 228 230 229 file = proc_ns_fget(fd); ··· 231 232 return PTR_ERR(file); 232 233 233 234 err = -EINVAL; 234 - ei = get_proc_ns(file_inode(file)); 235 - ops = ei->ns_ops; 236 - if (nstype && (ops->type != nstype)) 235 + ns = get_proc_ns(file_inode(file)); 236 + if (nstype && (ns->ops->type != nstype)) 237 237 goto out; 238 238 239 239 new_nsproxy = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs); ··· 241 243 goto out; 242 244 } 243 245 244 - err = ops->install(new_nsproxy, ei->ns); 246 + err = ns->ops->install(new_nsproxy, ns); 245 247 if (err) { 246 248 free_nsproxy(new_nsproxy); 247 249 goto out;
+4 -1
kernel/pid.c
··· 79 79 .level = 0, 80 80 .child_reaper = &init_task, 81 81 .user_ns = &init_user_ns, 82 - .proc_inum = PROC_PID_INIT_INO, 82 + .ns.inum = PROC_PID_INIT_INO, 83 + #ifdef CONFIG_PID_NS 84 + .ns.ops = &pidns_operations, 85 + #endif 83 86 }; 84 87 EXPORT_SYMBOL_GPL(init_pid_ns); 85 88
+14 -15
kernel/pid_namespace.c
··· 105 105 if (ns->pid_cachep == NULL) 106 106 goto out_free_map; 107 107 108 - err = proc_alloc_inum(&ns->proc_inum); 108 + err = ns_alloc_inum(&ns->ns); 109 109 if (err) 110 110 goto out_free_map; 111 + ns->ns.ops = &pidns_operations; 111 112 112 113 kref_init(&ns->kref); 113 114 ns->level = level; ··· 143 142 { 144 143 int i; 145 144 146 - proc_free_inum(ns->proc_inum); 145 + ns_free_inum(&ns->ns); 147 146 for (i = 0; i < PIDMAP_ENTRIES; i++) 148 147 kfree(ns->pidmap[i].page); 149 148 put_user_ns(ns->user_ns); ··· 334 333 return 0; 335 334 } 336 335 337 - static void *pidns_get(struct task_struct *task) 336 + static inline struct pid_namespace *to_pid_ns(struct ns_common *ns) 337 + { 338 + return container_of(ns, struct pid_namespace, ns); 339 + } 340 + 341 + static struct ns_common *pidns_get(struct task_struct *task) 338 342 { 339 343 struct pid_namespace *ns; 340 344 ··· 349 343 get_pid_ns(ns); 350 344 rcu_read_unlock(); 351 345 352 - return ns; 346 + return ns ? &ns->ns : NULL; 353 347 } 354 348 355 - static void pidns_put(void *ns) 349 + static void pidns_put(struct ns_common *ns) 356 350 { 357 - put_pid_ns(ns); 351 + put_pid_ns(to_pid_ns(ns)); 358 352 } 359 353 360 - static int pidns_install(struct nsproxy *nsproxy, void *ns) 354 + static int pidns_install(struct nsproxy *nsproxy, struct ns_common *ns) 361 355 { 362 356 struct pid_namespace *active = task_active_pid_ns(current); 363 - struct pid_namespace *ancestor, *new = ns; 357 + struct pid_namespace *ancestor, *new = to_pid_ns(ns); 364 358 365 359 if (!ns_capable(new->user_ns, CAP_SYS_ADMIN) || 366 360 !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) ··· 388 382 return 0; 389 383 } 390 384 391 - static unsigned int pidns_inum(void *ns) 392 - { 393 - struct pid_namespace *pid_ns = ns; 394 - return pid_ns->proc_inum; 395 - } 396 - 397 385 const struct proc_ns_operations pidns_operations = { 398 386 .name = "pid", 399 387 .type = CLONE_NEWPID, 400 388 .get = pidns_get, 401 389 .put = pidns_put, 402 390 .install = pidns_install, 403 - .inum = pidns_inum, 404 391 }; 405 392 406 393 static __init int pid_namespaces_init(void)
+4 -1
kernel/user.c
··· 50 50 .count = ATOMIC_INIT(3), 51 51 .owner = GLOBAL_ROOT_UID, 52 52 .group = GLOBAL_ROOT_GID, 53 - .proc_inum = PROC_USER_INIT_INO, 53 + .ns.inum = PROC_USER_INIT_INO, 54 + #ifdef CONFIG_USER_NS 55 + .ns.ops = &userns_operations, 56 + #endif 54 57 #ifdef CONFIG_PERSISTENT_KEYRINGS 55 58 .persistent_keyring_register_sem = 56 59 __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
+14 -15
kernel/user_namespace.c
··· 86 86 if (!ns) 87 87 return -ENOMEM; 88 88 89 - ret = proc_alloc_inum(&ns->proc_inum); 89 + ret = ns_alloc_inum(&ns->ns); 90 90 if (ret) { 91 91 kmem_cache_free(user_ns_cachep, ns); 92 92 return ret; 93 93 } 94 + ns->ns.ops = &userns_operations; 94 95 95 96 atomic_set(&ns->count, 1); 96 97 /* Leave the new->user_ns reference with the new user namespace. */ ··· 137 136 #ifdef CONFIG_PERSISTENT_KEYRINGS 138 137 key_put(ns->persistent_keyring_register); 139 138 #endif 140 - proc_free_inum(ns->proc_inum); 139 + ns_free_inum(&ns->ns); 141 140 kmem_cache_free(user_ns_cachep, ns); 142 141 ns = parent; 143 142 } while (atomic_dec_and_test(&parent->count)); ··· 842 841 return false; 843 842 } 844 843 845 - static void *userns_get(struct task_struct *task) 844 + static inline struct user_namespace *to_user_ns(struct ns_common *ns) 845 + { 846 + return container_of(ns, struct user_namespace, ns); 847 + } 848 + 849 + static struct ns_common *userns_get(struct task_struct *task) 846 850 { 847 851 struct user_namespace *user_ns; 848 852 ··· 855 849 user_ns = get_user_ns(__task_cred(task)->user_ns); 856 850 rcu_read_unlock(); 857 851 858 - return user_ns; 852 + return user_ns ? &user_ns->ns : NULL; 859 853 } 860 854 861 - static void userns_put(void *ns) 855 + static void userns_put(struct ns_common *ns) 862 856 { 863 - put_user_ns(ns); 857 + put_user_ns(to_user_ns(ns)); 864 858 } 865 859 866 - static int userns_install(struct nsproxy *nsproxy, void *ns) 860 + static int userns_install(struct nsproxy *nsproxy, struct ns_common *ns) 867 861 { 868 - struct user_namespace *user_ns = ns; 862 + struct user_namespace *user_ns = to_user_ns(ns); 869 863 struct cred *cred; 870 864 871 865 /* Don't allow gaining capabilities by reentering ··· 894 888 return commit_creds(cred); 895 889 } 896 890 897 - static unsigned int userns_inum(void *ns) 898 - { 899 - struct user_namespace *user_ns = ns; 900 - return user_ns->proc_inum; 901 - } 902 - 903 891 const struct proc_ns_operations userns_operations = { 904 892 .name = "user", 905 893 .type = CLONE_NEWUSER, 906 894 .get = userns_get, 907 895 .put = userns_put, 908 896 .install = userns_install, 909 - .inum = userns_inum, 910 897 }; 911 898 912 899 static __init int user_namespaces_init(void)
+15 -16
kernel/utsname.c
··· 42 42 if (!ns) 43 43 return ERR_PTR(-ENOMEM); 44 44 45 - err = proc_alloc_inum(&ns->proc_inum); 45 + err = ns_alloc_inum(&ns->ns); 46 46 if (err) { 47 47 kfree(ns); 48 48 return ERR_PTR(err); 49 49 } 50 + 51 + ns->ns.ops = &utsns_operations; 50 52 51 53 down_read(&uts_sem); 52 54 memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); ··· 86 84 87 85 ns = container_of(kref, struct uts_namespace, kref); 88 86 put_user_ns(ns->user_ns); 89 - proc_free_inum(ns->proc_inum); 87 + ns_free_inum(&ns->ns); 90 88 kfree(ns); 91 89 } 92 90 93 - static void *utsns_get(struct task_struct *task) 91 + static inline struct uts_namespace *to_uts_ns(struct ns_common *ns) 92 + { 93 + return container_of(ns, struct uts_namespace, ns); 94 + } 95 + 96 + static struct ns_common *utsns_get(struct task_struct *task) 94 97 { 95 98 struct uts_namespace *ns = NULL; 96 99 struct nsproxy *nsproxy; ··· 108 101 } 109 102 task_unlock(task); 110 103 111 - return ns; 104 + return ns ? &ns->ns : NULL; 112 105 } 113 106 114 - static void utsns_put(void *ns) 107 + static void utsns_put(struct ns_common *ns) 115 108 { 116 - put_uts_ns(ns); 109 + put_uts_ns(to_uts_ns(ns)); 117 110 } 118 111 119 - static int utsns_install(struct nsproxy *nsproxy, void *new) 112 + static int utsns_install(struct nsproxy *nsproxy, struct ns_common *new) 120 113 { 121 - struct uts_namespace *ns = new; 114 + struct uts_namespace *ns = to_uts_ns(new); 122 115 123 116 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) || 124 117 !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) ··· 130 123 return 0; 131 124 } 132 125 133 - static unsigned int utsns_inum(void *vp) 134 - { 135 - struct uts_namespace *ns = vp; 136 - 137 - return ns->proc_inum; 138 - } 139 - 140 126 const struct proc_ns_operations utsns_operations = { 141 127 .name = "uts", 142 128 .type = CLONE_NEWUTS, 143 129 .get = utsns_get, 144 130 .put = utsns_put, 145 131 .install = utsns_install, 146 - .inum = utsns_inum, 147 132 };
-2
net/Makefile
··· 5 5 # Rewritten to use lists instead of if-statements. 6 6 # 7 7 8 - obj-y := nonet.o 9 - 10 8 obj-$(CONFIG_NET) := socket.o core/ 11 9 12 10 tmp-$(CONFIG_COMPAT) := compat.o
+20 -19
net/core/net_namespace.c
··· 337 337 338 338 struct net *get_net_ns_by_fd(int fd) 339 339 { 340 - struct proc_ns *ei; 341 340 struct file *file; 341 + struct ns_common *ns; 342 342 struct net *net; 343 343 344 344 file = proc_ns_fget(fd); 345 345 if (IS_ERR(file)) 346 346 return ERR_CAST(file); 347 347 348 - ei = get_proc_ns(file_inode(file)); 349 - if (ei->ns_ops == &netns_operations) 350 - net = get_net(ei->ns); 348 + ns = get_proc_ns(file_inode(file)); 349 + if (ns->ops == &netns_operations) 350 + net = get_net(container_of(ns, struct net, ns)); 351 351 else 352 352 net = ERR_PTR(-EINVAL); 353 353 ··· 386 386 387 387 static __net_init int net_ns_net_init(struct net *net) 388 388 { 389 - return proc_alloc_inum(&net->proc_inum); 389 + #ifdef CONFIG_NET_NS 390 + net->ns.ops = &netns_operations; 391 + #endif 392 + return ns_alloc_inum(&net->ns); 390 393 } 391 394 392 395 static __net_exit void net_ns_net_exit(struct net *net) 393 396 { 394 - proc_free_inum(net->proc_inum); 397 + ns_free_inum(&net->ns); 395 398 } 396 399 397 400 static struct pernet_operations __net_initdata net_ns_ops = { ··· 632 629 EXPORT_SYMBOL_GPL(unregister_pernet_device); 633 630 634 631 #ifdef CONFIG_NET_NS 635 - static void *netns_get(struct task_struct *task) 632 + static struct ns_common *netns_get(struct task_struct *task) 636 633 { 637 634 struct net *net = NULL; 638 635 struct nsproxy *nsproxy; ··· 643 640 net = get_net(nsproxy->net_ns); 644 641 task_unlock(task); 645 642 646 - return net; 643 + return net ? &net->ns : NULL; 647 644 } 648 645 649 - static void netns_put(void *ns) 646 + static inline struct net *to_net_ns(struct ns_common *ns) 650 647 { 651 - put_net(ns); 648 + return container_of(ns, struct net, ns); 652 649 } 653 650 654 - static int netns_install(struct nsproxy *nsproxy, void *ns) 651 + static void netns_put(struct ns_common *ns) 655 652 { 656 - struct net *net = ns; 653 + put_net(to_net_ns(ns)); 654 + } 655 + 656 + static int netns_install(struct nsproxy *nsproxy, struct ns_common *ns) 657 + { 658 + struct net *net = to_net_ns(ns); 657 659 658 660 if (!ns_capable(net->user_ns, CAP_SYS_ADMIN) || 659 661 !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) ··· 669 661 return 0; 670 662 } 671 663 672 - static unsigned int netns_inum(void *ns) 673 - { 674 - struct net *net = ns; 675 - return net->proc_inum; 676 - } 677 - 678 664 const struct proc_ns_operations netns_operations = { 679 665 .name = "net", 680 666 .type = CLONE_NEWNET, 681 667 .get = netns_get, 682 668 .put = netns_put, 683 669 .install = netns_install, 684 - .inum = netns_inum, 685 670 }; 686 671 #endif
-26
net/nonet.c
··· 1 - /* 2 - * net/nonet.c 3 - * 4 - * Dummy functions to allow us to configure network support entirely 5 - * out of the kernel. 6 - * 7 - * Distributed under the terms of the GNU GPL version 2. 8 - * Copyright (c) Matthew Wilcox 2003 9 - */ 10 - 11 - #include <linux/module.h> 12 - #include <linux/errno.h> 13 - #include <linux/fs.h> 14 - #include <linux/init.h> 15 - #include <linux/kernel.h> 16 - 17 - static int sock_no_open(struct inode *irrelevant, struct file *dontcare) 18 - { 19 - return -ENXIO; 20 - } 21 - 22 - const struct file_operations bad_sock_fops = { 23 - .owner = THIS_MODULE, 24 - .open = sock_no_open, 25 - .llseek = noop_llseek, 26 - };
-19
net/socket.c
··· 113 113 unsigned int sysctl_net_busy_poll __read_mostly; 114 114 #endif 115 115 116 - static int sock_no_open(struct inode *irrelevant, struct file *dontcare); 117 116 static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, 118 117 unsigned long nr_segs, loff_t pos); 119 118 static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, ··· 150 151 .compat_ioctl = compat_sock_ioctl, 151 152 #endif 152 153 .mmap = sock_mmap, 153 - .open = sock_no_open, /* special open code to disallow open via /proc */ 154 154 .release = sock_close, 155 155 .fasync = sock_fasync, 156 156 .sendpage = sock_sendpage, ··· 556 558 this_cpu_add(sockets_in_use, 1); 557 559 return sock; 558 560 } 559 - 560 - /* 561 - * In theory you can't get an open on this inode, but /proc provides 562 - * a back door. Remember to keep it shut otherwise you'll let the 563 - * creepy crawlies in. 564 - */ 565 - 566 - static int sock_no_open(struct inode *irrelevant, struct file *dontcare) 567 - { 568 - return -ENXIO; 569 - } 570 - 571 - const struct file_operations bad_sock_fops = { 572 - .owner = THIS_MODULE, 573 - .open = sock_no_open, 574 - .llseek = noop_llseek, 575 - }; 576 561 577 562 /** 578 563 * sock_release - close a socket