Advertisement
Guest User

Untitled

a guest
Oct 11th, 2015
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.03 KB | None | 0 0
  1. From a2672b681c9cc6d7d18dd68f95a0d46006cf1470 Mon Sep 17 00:00:00 2001
  2. From: "Eric W. Biederman" <ebiederm@xmission.com>
  3. Date: Sun, 7 Mar 2010 18:49:36 -0800
  4. Subject: [PATCH 1/5] vfs: Add setns support for the mount namespace
  5.  
  6. setns support for the mount namespace is a little tricky as an
  7. arbitrary decision must be made about what to set fs->root and
  8. fs->pwd to, as there is no expectation of a relationship between
  9. the two mount namespaces. Therefore I arbitrarily find the root
  10. mount point, and follow every mount on top of it to find the top
  11. of the mount stack. Then I set fs->root and fs->pwd to that
  12. location. The topmost root of the mount stack seems like a
  13. reasonable place to be.
  14.  
  15. Bind mount support for the mount namespace inodes has the
  16. possibility of creating circular dependencies between mount
  17. namespaces. Circular dependencies can result in loops that
  18. prevent mount namespaces from every being freed. I avoid
  19. creating those circular dependencies by adding a sequence number
  20. to the mount namespace and require all bind mounts be of a
  21. younger mount namespace into an older mount namespace.
  22.  
  23. Add a helper function proc_ns_inode so it is possible to
  24. detect when we are attempting to bind mound a namespace inode.
  25.  
  26. Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
  27. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
  28. (cherry picked from commit 8823c079ba7136dc1948d6f6dcb5f8022bde438e)
  29. ---
  30. fs/mount.h | 1 +
  31. fs/namespace.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++
  32. fs/proc/namespaces.c | 8 +++++
  33. include/linux/proc_fs.h | 8 +++++
  34. 4 files changed, 112 insertions(+)
  35.  
  36. diff --git a/fs/mount.h b/fs/mount.h
  37. index 4ef36d9..ddf6358 100644
  38. --- a/fs/mount.h
  39. +++ b/fs/mount.h
  40. @@ -6,6 +6,7 @@ struct mnt_namespace {
  41. atomic_t count;
  42. struct mount * root;
  43. struct list_head list;
  44. + u64 seq; /* Sequence number to prevent loops */
  45. wait_queue_head_t poll;
  46. int event;
  47. };
  48. diff --git a/fs/namespace.c b/fs/namespace.c
  49. index 081b977..13b3c623 100644
  50. --- a/fs/namespace.c
  51. +++ b/fs/namespace.c
  52. @@ -20,6 +20,7 @@
  53. #include <linux/fs_struct.h> /* get_fs_root et.al. */
  54. #include <linux/fsnotify.h> /* fsnotify_vfsmount_delete */
  55. #include <linux/uaccess.h>
  56. +#include <linux/proc_fs.h>
  57. #include "pnode.h"
  58. #include "internal.h"
  59.  
  60. @@ -1252,6 +1253,26 @@ static int mount_is_safe(struct path *path)
  61. #endif
  62. }
  63.  
  64. +static bool mnt_ns_loop(struct path *path)
  65. +{
  66. + /* Could bind mounting the mount namespace inode cause a
  67. + * mount namespace loop?
  68. + */
  69. + struct inode *inode = path->dentry->d_inode;
  70. + struct proc_inode *ei;
  71. + struct mnt_namespace *mnt_ns;
  72. +
  73. + if (!proc_ns_inode(inode))
  74. + return false;
  75. +
  76. + ei = PROC_I(inode);
  77. + if (ei->ns_ops != &mntns_operations)
  78. + return false;
  79. +
  80. + mnt_ns = ei->ns;
  81. + return current->nsproxy->mnt_ns->seq >= mnt_ns->seq;
  82. +}
  83. +
  84. struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
  85. int flag)
  86. {
  87. @@ -1612,6 +1633,10 @@ static int do_loopback(struct path *path, char *old_name,
  88. if (err)
  89. return err;
  90.  
  91. + err = -EINVAL;
  92. + if (mnt_ns_loop(&old_path))
  93. + goto out;
  94. +
  95. err = lock_mount(path);
  96. if (err)
  97. goto out;
  98. @@ -2213,6 +2238,15 @@ dput_out:
  99. return retval;
  100. }
  101.  
  102. +/*
  103. + * Assign a sequence number so we can detect when we attempt to bind
  104. + * mount a reference to an older mount namespace into the current
  105. + * mount namespace, preventing reference counting loops. A 64bit
  106. + * number incrementing at 10Ghz will take 12,427 years to wrap which
  107. + * is effectively never, so we can ignore the possibility.
  108. + */
  109. +static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1);
  110. +
  111. static struct mnt_namespace *alloc_mnt_ns(void)
  112. {
  113. struct mnt_namespace *new_ns;
  114. @@ -2220,6 +2254,7 @@ static struct mnt_namespace *alloc_mnt_ns(void)
  115. new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
  116. if (!new_ns)
  117. return ERR_PTR(-ENOMEM);
  118. + new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
  119. atomic_set(&new_ns->count, 1);
  120. new_ns->root = NULL;
  121. INIT_LIST_HEAD(&new_ns->list);
  122. @@ -2657,3 +2692,63 @@ bool our_mnt(struct vfsmount *mnt)
  123. {
  124. return check_mnt(real_mount(mnt));
  125. }
  126. +
  127. +static void *mntns_get(struct task_struct *task)
  128. +{
  129. + struct mnt_namespace *ns = NULL;
  130. + struct nsproxy *nsproxy;
  131. +
  132. + rcu_read_lock();
  133. + nsproxy = task_nsproxy(task);
  134. + if (nsproxy) {
  135. + ns = nsproxy->mnt_ns;
  136. + get_mnt_ns(ns);
  137. + }
  138. + rcu_read_unlock();
  139. +
  140. + return ns;
  141. +}
  142. +
  143. +static void mntns_put(void *ns)
  144. +{
  145. + put_mnt_ns(ns);
  146. +}
  147. +
  148. +static int mntns_install(struct nsproxy *nsproxy, void *ns)
  149. +{
  150. + struct fs_struct *fs = current->fs;
  151. + struct mnt_namespace *mnt_ns = ns;
  152. + struct path root;
  153. +
  154. + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_CHROOT))
  155. + return -EINVAL;
  156. +
  157. + if (fs->users != 1)
  158. + return -EINVAL;
  159. +
  160. + get_mnt_ns(mnt_ns);
  161. + put_mnt_ns(nsproxy->mnt_ns);
  162. + nsproxy->mnt_ns = mnt_ns;
  163. +
  164. + /* Find the root */
  165. + root.mnt = &mnt_ns->root->mnt;
  166. + root.dentry = mnt_ns->root->mnt.mnt_root;
  167. + path_get(&root);
  168. + while(d_mountpoint(root.dentry) && follow_down_one(&root))
  169. + ;
  170. +
  171. + /* Update the pwd and root */
  172. + set_fs_pwd(fs, &root);
  173. + set_fs_root(fs, &root);
  174. +
  175. + path_put(&root);
  176. + return 0;
  177. +}
  178. +
  179. +const struct proc_ns_operations mntns_operations = {
  180. + .name = "mnt",
  181. + .type = CLONE_NEWNS,
  182. + .get = mntns_get,
  183. + .put = mntns_put,
  184. + .install = mntns_install,
  185. +};
  186. diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
  187. index 0d9e23a..a971f8e 100644
  188. --- a/fs/proc/namespaces.c
  189. +++ b/fs/proc/namespaces.c
  190. @@ -24,6 +24,10 @@ static const struct proc_ns_operations *ns_entries[] = {
  191. #ifdef CONFIG_IPC_NS
  192. &ipcns_operations,
  193. #endif
  194. +#ifdef CONFIG_PID_NS
  195. + &pidns_operations,
  196. +#endif
  197. + &mntns_operations,
  198. };
  199.  
  200. static const struct file_operations ns_file_operations = {
  201. @@ -198,3 +202,7 @@ out_invalid:
  202. return ERR_PTR(-EINVAL);
  203. }
  204.  
  205. +bool proc_ns_inode(struct inode *inode)
  206. +{
  207. + return inode->i_fop == &ns_file_operations;
  208. +}
  209. diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
  210. index 85c5073..41913af 100644
  211. --- a/include/linux/proc_fs.h
  212. +++ b/include/linux/proc_fs.h
  213. @@ -174,6 +174,7 @@ extern struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name,
  214. struct proc_dir_entry *parent);
  215.  
  216. extern struct file *proc_ns_fget(int fd);
  217. +extern bool proc_ns_inode(struct inode *inode);
  218.  
  219. #else
  220.  
  221. @@ -229,6 +230,11 @@ static inline struct file *proc_ns_fget(int fd)
  222. return ERR_PTR(-EINVAL);
  223. }
  224.  
  225. +static inline bool proc_ns_inode(struct inode *inode)
  226. +{
  227. + return false;
  228. +}
  229. +
  230. #endif /* CONFIG_PROC_FS */
  231.  
  232. #if !defined(CONFIG_PROC_KCORE)
  233. @@ -251,6 +257,8 @@ struct proc_ns_operations {
  234. extern const struct proc_ns_operations netns_operations;
  235. extern const struct proc_ns_operations utsns_operations;
  236. extern const struct proc_ns_operations ipcns_operations;
  237. +extern const struct proc_ns_operations pidns_operations;
  238. +extern const struct proc_ns_operations mntns_operations;
  239.  
  240. union proc_op {
  241. int (*proc_get_link)(struct dentry *, struct path *);
  242. --
  243. 2.6.1
  244.  
  245.  
  246. From 96dde74002f03e77ead93dabc6036e5e7e2d6b5e Mon Sep 17 00:00:00 2001
  247. From: "Eric W. Biederman" <ebiederm@xmission.com>
  248. Date: Thu, 26 Jul 2012 21:08:32 -0700
  249. Subject: [PATCH 2/5] vfs: Add a user namespace reference from struct
  250. mnt_namespace
  251.  
  252. This will allow for support for unprivileged mounts in a new user namespace.
  253.  
  254. Acked-by: "Serge E. Hallyn" <serge@hallyn.com>
  255. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
  256. (cherry picked from commit 771b1371686e0a63e938ada28de020b9a0040f55)
  257. ---
  258. fs/mount.h | 1 +
  259. fs/namespace.c | 28 ++++++++++++++++++----------
  260. include/linux/mnt_namespace.h | 3 ++-
  261. kernel/nsproxy.c | 2 +-
  262. 4 files changed, 22 insertions(+), 12 deletions(-)
  263.  
  264. diff --git a/fs/mount.h b/fs/mount.h
  265. index ddf6358..06274b6 100644
  266. --- a/fs/mount.h
  267. +++ b/fs/mount.h
  268. @@ -6,6 +6,7 @@ struct mnt_namespace {
  269. atomic_t count;
  270. struct mount * root;
  271. struct list_head list;
  272. + struct user_namespace *user_ns;
  273. u64 seq; /* Sequence number to prevent loops */
  274. wait_queue_head_t poll;
  275. int event;
  276. diff --git a/fs/namespace.c b/fs/namespace.c
  277. index 13b3c623..be6e1c6 100644
  278. --- a/fs/namespace.c
  279. +++ b/fs/namespace.c
  280. @@ -12,6 +12,7 @@
  281. #include <linux/export.h>
  282. #include <linux/capability.h>
  283. #include <linux/mnt_namespace.h>
  284. +#include <linux/user_namespace.h>
  285. #include <linux/namei.h>
  286. #include <linux/security.h>
  287. #include <linux/idr.h>
  288. @@ -2238,6 +2239,12 @@ dput_out:
  289. return retval;
  290. }
  291.  
  292. +static void free_mnt_ns(struct mnt_namespace *ns)
  293. +{
  294. + put_user_ns(ns->user_ns);
  295. + kfree(ns);
  296. +}
  297. +
  298. /*
  299. * Assign a sequence number so we can detect when we attempt to bind
  300. * mount a reference to an older mount namespace into the current
  301. @@ -2247,7 +2254,7 @@ dput_out:
  302. */
  303. static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1);
  304.  
  305. -static struct mnt_namespace *alloc_mnt_ns(void)
  306. +static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
  307. {
  308. struct mnt_namespace *new_ns;
  309.  
  310. @@ -2260,6 +2267,7 @@ static struct mnt_namespace *alloc_mnt_ns(void)
  311. INIT_LIST_HEAD(&new_ns->list);
  312. init_waitqueue_head(&new_ns->poll);
  313. new_ns->event = 0;
  314. + new_ns->user_ns = get_user_ns(user_ns);
  315. return new_ns;
  316. }
  317.  
  318. @@ -2285,7 +2293,7 @@ void mnt_make_shortterm(struct vfsmount *m)
  319. * copied from the namespace of the passed in task structure.
  320. */
  321. static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
  322. - struct fs_struct *fs)
  323. + struct user_namespace *user_ns, struct fs_struct *fs)
  324. {
  325. struct mnt_namespace *new_ns;
  326. struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
  327. @@ -2293,17 +2301,17 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
  328. struct mount *old = mnt_ns->root;
  329. struct mount *new;
  330.  
  331. - new_ns = alloc_mnt_ns();
  332. + new_ns = alloc_mnt_ns(user_ns);
  333. if (IS_ERR(new_ns))
  334. return new_ns;
  335.  
  336. down_write(&namespace_sem);
  337. /* First pass: copy the tree topology */
  338. new = copy_tree(old, old->mnt.mnt_root, CL_COPY_ALL | CL_EXPIRE);
  339. - if (!new) {
  340. + if (IS_ERR(new)) {
  341. up_write(&namespace_sem);
  342. - kfree(new_ns);
  343. - return ERR_PTR(-ENOMEM);
  344. + free_mnt_ns(new_ns);
  345. + return ERR_CAST(new);
  346. }
  347. new_ns->root = new;
  348. br_write_lock(vfsmount_lock);
  349. @@ -2348,7 +2356,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
  350. }
  351.  
  352. struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
  353. - struct fs_struct *new_fs)
  354. + struct user_namespace *user_ns, struct fs_struct *new_fs)
  355. {
  356. struct mnt_namespace *new_ns;
  357.  
  358. @@ -2358,7 +2366,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
  359. if (!(flags & CLONE_NEWNS))
  360. return ns;
  361.  
  362. - new_ns = dup_mnt_ns(ns, new_fs);
  363. + new_ns = dup_mnt_ns(ns, user_ns, new_fs);
  364.  
  365. put_mnt_ns(ns);
  366. return new_ns;
  367. @@ -2370,7 +2378,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
  368. */
  369. static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
  370. {
  371. - struct mnt_namespace *new_ns = alloc_mnt_ns();
  372. + struct mnt_namespace *new_ns = alloc_mnt_ns(&init_user_ns);
  373. if (!IS_ERR(new_ns)) {
  374. struct mount *mnt = real_mount(m);
  375. mnt->mnt_ns = new_ns;
  376. @@ -2660,7 +2668,7 @@ void put_mnt_ns(struct mnt_namespace *ns)
  377. br_write_unlock(vfsmount_lock);
  378. up_write(&namespace_sem);
  379. release_mounts(&umount_list);
  380. - kfree(ns);
  381. + free_mnt_ns(ns);
  382. }
  383.  
  384. struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
  385. diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
  386. index 5a8e390..12b2ab5 100644
  387. --- a/include/linux/mnt_namespace.h
  388. +++ b/include/linux/mnt_namespace.h
  389. @@ -4,9 +4,10 @@
  390.  
  391. struct mnt_namespace;
  392. struct fs_struct;
  393. +struct user_namespace;
  394.  
  395. extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
  396. - struct fs_struct *);
  397. + struct user_namespace *, struct fs_struct *);
  398. extern void put_mnt_ns(struct mnt_namespace *ns);
  399.  
  400. extern const struct file_operations proc_mounts_operations;
  401. diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
  402. index b576f7f..5b6ce19 100644
  403. --- a/kernel/nsproxy.c
  404. +++ b/kernel/nsproxy.c
  405. @@ -66,7 +66,7 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
  406. if (!new_nsp)
  407. return ERR_PTR(-ENOMEM);
  408.  
  409. - new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, new_fs);
  410. + new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, task_cred_xxx(tsk, user_ns), new_fs);
  411. if (IS_ERR(new_nsp->mnt_ns)) {
  412. err = PTR_ERR(new_nsp->mnt_ns);
  413. goto out_ns;
  414. --
  415. 2.6.1
  416.  
  417.  
  418. From f32d344be55b5df0e1b6f01e7defa9f25303de39 Mon Sep 17 00:00:00 2001
  419. From: "Eric W. Biederman" <ebiederm@xmission.com>
  420. Date: Tue, 31 Jul 2012 13:13:04 -0700
  421. Subject: [PATCH 3/5] vfs: Only support slave subtrees across different user
  422. namespaces
  423.  
  424. Sharing mount subtress with mount namespaces created by unprivileged
  425. users allows unprivileged mounts created by unprivileged users to
  426. propagate to mount namespaces controlled by privileged users.
  427.  
  428. Prevent nasty consequences by changing shared subtrees to slave
  429. subtress when an unprivileged users creates a new mount namespace.
  430.  
  431. Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
  432. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
  433. (cherry picked from commit 7a472ef4be8387bc05a42e16309b02c8ca943a40)
  434. ---
  435. fs/namespace.c | 14 +++++++++++---
  436. fs/pnode.h | 1 +
  437. 2 files changed, 12 insertions(+), 3 deletions(-)
  438.  
  439. diff --git a/fs/namespace.c b/fs/namespace.c
  440. index be6e1c6..cc1ba97 100644
  441. --- a/fs/namespace.c
  442. +++ b/fs/namespace.c
  443. @@ -730,7 +730,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
  444. struct mount *mnt = alloc_vfsmnt(old->mnt_devname);
  445.  
  446. if (mnt) {
  447. - if (flag & (CL_SLAVE | CL_PRIVATE))
  448. + if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE))
  449. mnt->mnt_group_id = 0; /* not a peer of original */
  450. else
  451. mnt->mnt_group_id = old->mnt_group_id;
  452. @@ -751,7 +751,8 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
  453. list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
  454. br_write_unlock(vfsmount_lock);
  455.  
  456. - if (flag & CL_SLAVE) {
  457. + if ((flag & CL_SLAVE) ||
  458. + ((flag & CL_SHARED_TO_SLAVE) && IS_MNT_SHARED(old))) {
  459. list_add(&mnt->mnt_slave, &old->mnt_slave_list);
  460. mnt->mnt_master = old;
  461. CLEAR_MNT_SHARED(mnt);
  462. @@ -2300,6 +2301,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
  463. struct mount *p, *q;
  464. struct mount *old = mnt_ns->root;
  465. struct mount *new;
  466. + int copy_flags;
  467.  
  468. new_ns = alloc_mnt_ns(user_ns);
  469. if (IS_ERR(new_ns))
  470. @@ -2307,7 +2309,13 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
  471.  
  472. down_write(&namespace_sem);
  473. /* First pass: copy the tree topology */
  474. - new = copy_tree(old, old->mnt.mnt_root, CL_COPY_ALL | CL_EXPIRE);
  475. + copy_flags = CL_COPY_ALL | CL_EXPIRE;
  476. + if (user_ns != mnt_ns->user_ns)
  477. + copy_flags |= CL_SHARED_TO_SLAVE;
  478. + copy_flags = CL_COPY_ALL | CL_EXPIRE;
  479. + if (user_ns != mnt_ns->user_ns)
  480. + copy_flags |= CL_SHARED_TO_SLAVE;
  481. + new = copy_tree(old, old->mnt.mnt_root, copy_flags);
  482. if (IS_ERR(new)) {
  483. up_write(&namespace_sem);
  484. free_mnt_ns(new_ns);
  485. diff --git a/fs/pnode.h b/fs/pnode.h
  486. index 65c6097..19b853a3 100644
  487. --- a/fs/pnode.h
  488. +++ b/fs/pnode.h
  489. @@ -22,6 +22,7 @@
  490. #define CL_COPY_ALL 0x04
  491. #define CL_MAKE_SHARED 0x08
  492. #define CL_PRIVATE 0x10
  493. +#define CL_SHARED_TO_SLAVE 0x20
  494.  
  495. static inline void set_mnt_shared(struct mount *mnt)
  496. {
  497. --
  498. 2.6.1
  499.  
  500.  
  501. From 576d1e885b8ab7e402e0701cd9ade47ba0c42106 Mon Sep 17 00:00:00 2001
  502. From: "Eric W. Biederman" <ebiederm@xmission.com>
  503. Date: Thu, 26 Jul 2012 21:42:03 -0700
  504. Subject: [PATCH 4/5] vfs: Allow unprivileged manipulation of the mount
  505. namespace.
  506.  
  507. - Add a filesystem flag to mark filesystems that are safe to mount as
  508. an unprivileged user.
  509.  
  510. - Add a filesystem flag to mark filesystems that don't need MNT_NODEV
  511. when mounted by an unprivileged user.
  512.  
  513. - Relax the permission checks to allow unprivileged users that have
  514. CAP_SYS_ADMIN permissions in the user namespace referred to by the
  515. current mount namespace to be allowed to mount, unmount, and move
  516. filesystems.
  517.  
  518. Acked-by: "Serge E. Hallyn" <serge@hallyn.com>
  519. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
  520. (cherry picked from commit 0c55cfc4166d9a0f38de779bd4d75a90afbe7734)
  521. ---
  522. fs/namespace.c | 69 ++++++++++++++++++++++++++++++++++--------------------
  523. include/linux/fs.h | 7 ++++++
  524. 2 files changed, 50 insertions(+), 26 deletions(-)
  525.  
  526. diff --git a/fs/namespace.c b/fs/namespace.c
  527. index cc1ba97..8b64e6b 100644
  528. --- a/fs/namespace.c
  529. +++ b/fs/namespace.c
  530. @@ -1213,7 +1213,7 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
  531. goto dput_and_out;
  532.  
  533. retval = -EPERM;
  534. - if (!capable(CAP_SYS_ADMIN))
  535. + if (!ns_capable(mnt->mnt_ns->user_ns, CAP_SYS_ADMIN))
  536. goto dput_and_out;
  537.  
  538. retval = do_umount(mnt, flags);
  539. @@ -1239,7 +1239,7 @@ SYSCALL_DEFINE1(oldumount, char __user *, name)
  540.  
  541. static int mount_is_safe(struct path *path)
  542. {
  543. - if (capable(CAP_SYS_ADMIN))
  544. + if (ns_capable(real_mount(path->mnt)->mnt_ns->user_ns, CAP_SYS_ADMIN))
  545. return 0;
  546. return -EPERM;
  547. #ifdef notyet
  548. @@ -1590,7 +1590,7 @@ static int do_change_type(struct path *path, int flag)
  549. int type;
  550. int err = 0;
  551.  
  552. - if (!capable(CAP_SYS_ADMIN))
  553. + if (!ns_capable(mnt->mnt_ns->user_ns, CAP_SYS_ADMIN))
  554. return -EPERM;
  555.  
  556. if (path->dentry != path->mnt->mnt_root)
  557. @@ -1753,7 +1753,7 @@ static int do_move_mount(struct path *path, char *old_name)
  558. struct mount *p;
  559. struct mount *old;
  560. int err = 0;
  561. - if (!capable(CAP_SYS_ADMIN))
  562. + if (!ns_capable(real_mount(path->mnt)->mnt_ns->user_ns, CAP_SYS_ADMIN))
  563. return -EPERM;
  564. if (!old_name || !*old_name)
  565. return -EINVAL;
  566. @@ -1840,21 +1840,6 @@ static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
  567. return ERR_PTR(err);
  568. }
  569.  
  570. -static struct vfsmount *
  571. -do_kern_mount(const char *fstype, int flags, const char *name, void *data)
  572. -{
  573. - struct file_system_type *type = get_fs_type(fstype);
  574. - struct vfsmount *mnt;
  575. - if (!type)
  576. - return ERR_PTR(-ENODEV);
  577. - mnt = vfs_kern_mount(type, flags, name, data);
  578. - if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
  579. - !mnt->mnt_sb->s_subtype)
  580. - mnt = fs_set_subtype(mnt, fstype);
  581. - put_filesystem(type);
  582. - return mnt;
  583. -}
  584. -
  585. /*
  586. * add a mount into a namespace's mount tree
  587. */
  588. @@ -1894,20 +1879,46 @@ unlock:
  589. * create a new mount for userspace and request it to be added into the
  590. * namespace's tree
  591. */
  592. -static int do_new_mount(struct path *path, char *type, int flags,
  593. +static int do_new_mount(struct path *path, char *fstype, int flags,
  594. int mnt_flags, char *name, void *data)
  595. {
  596. + struct file_system_type *type;
  597. + struct user_namespace *user_ns;
  598. struct vfsmount *mnt;
  599. int err;
  600.  
  601. - if (!type)
  602. + if (!fstype)
  603. return -EINVAL;
  604.  
  605. /* we need capabilities... */
  606. - if (!capable(CAP_SYS_ADMIN))
  607. + user_ns = real_mount(path->mnt)->mnt_ns->user_ns;
  608. + if (!ns_capable(user_ns, CAP_SYS_ADMIN))
  609. return -EPERM;
  610.  
  611. - mnt = do_kern_mount(type, flags, name, data);
  612. + type = get_fs_type(fstype);
  613. + if (!type)
  614. + return -ENODEV;
  615. +
  616. + if (user_ns != &init_user_ns) {
  617. + if (!(type->fs_flags & FS_USERNS_MOUNT)) {
  618. + put_filesystem(type);
  619. + return -EPERM;
  620. + }
  621. + /* Only in special cases allow devices from mounts
  622. + * created outside the initial user namespace.
  623. + */
  624. + if (!(type->fs_flags & FS_USERNS_DEV_MOUNT)) {
  625. + flags |= MS_NODEV;
  626. + mnt_flags |= MNT_NODEV;
  627. + }
  628. + }
  629. +
  630. + mnt = vfs_kern_mount(type, flags, name, data);
  631. + if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
  632. + !mnt->mnt_sb->s_subtype)
  633. + mnt = fs_set_subtype(mnt, fstype);
  634. +
  635. + put_filesystem(type);
  636. if (IS_ERR(mnt))
  637. return PTR_ERR(mnt);
  638.  
  639. @@ -2527,7 +2538,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
  640. struct mount *new_mnt, *root_mnt;
  641. int error;
  642.  
  643. - if (!capable(CAP_SYS_ADMIN))
  644. + if (!ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN))
  645. return -EPERM;
  646.  
  647. error = user_path_dir(new_root, &new);
  648. @@ -2612,8 +2623,13 @@ static void __init init_mount_tree(void)
  649. struct vfsmount *mnt;
  650. struct mnt_namespace *ns;
  651. struct path root;
  652. + struct file_system_type *type;
  653.  
  654. - mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
  655. + type = get_fs_type("rootfs");
  656. + if (!type)
  657. + panic("Can't find rootfs type");
  658. + mnt = vfs_kern_mount(type, 0, "rootfs", NULL);
  659. + put_filesystem(type);
  660. if (IS_ERR(mnt))
  661. panic("Can't create rootfs");
  662.  
  663. @@ -2736,7 +2752,8 @@ static int mntns_install(struct nsproxy *nsproxy, void *ns)
  664. struct mnt_namespace *mnt_ns = ns;
  665. struct path root;
  666.  
  667. - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_CHROOT))
  668. + if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
  669. + !nsown_capable(CAP_SYS_CHROOT))
  670. return -EINVAL;
  671.  
  672. if (fs->users != 1)
  673. diff --git a/include/linux/fs.h b/include/linux/fs.h
  674. index 3d41a6c..6136819 100644
  675. --- a/include/linux/fs.h
  676. +++ b/include/linux/fs.h
  677. @@ -1849,6 +1849,13 @@ int sync_inode_metadata(struct inode *inode, int wait);
  678. struct file_system_type {
  679. const char *name;
  680. int fs_flags;
  681. +#define FS_REQUIRES_DEV 1
  682. +#define FS_BINARY_MOUNTDATA 2
  683. +#define FS_HAS_SUBTYPE 4
  684. +#define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */
  685. +#define FS_USERNS_DEV_MOUNT 16 /* A userns mount does not imply MNT_NODEV */
  686. +#define FS_REVAL_DOT 16384 /* Check the paths ".", ".." for staleness */
  687. +#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
  688. struct dentry *(*mount) (struct file_system_type *, int,
  689. const char *, void *);
  690. void (*kill_sb) (struct super_block *);
  691. --
  692. 2.6.1
  693.  
  694.  
  695. From 00871a3267f14ae7bd57ba0ff6f91518e4d5088f Mon Sep 17 00:00:00 2001
  696. From: Daniel Rosenberg <drosen@google.com>
  697. Date: Tue, 21 Jul 2015 15:17:26 -0700
  698. Subject: [PATCH 5/5] Fix incorrect conflict resolution in "vfs: Add setns
  699. support for the mount namespace"
  700.  
  701. ---
  702. fs/proc/namespaces.c | 3 ---
  703. include/linux/proc_fs.h | 1 -
  704. 2 files changed, 4 deletions(-)
  705.  
  706. diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
  707. index a971f8e..3221fd7 100644
  708. --- a/fs/proc/namespaces.c
  709. +++ b/fs/proc/namespaces.c
  710. @@ -24,9 +24,6 @@ static const struct proc_ns_operations *ns_entries[] = {
  711. #ifdef CONFIG_IPC_NS
  712. &ipcns_operations,
  713. #endif
  714. -#ifdef CONFIG_PID_NS
  715. - &pidns_operations,
  716. -#endif
  717. &mntns_operations,
  718. };
  719.  
  720. diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
  721. index 41913af..7f3cd78 100644
  722. --- a/include/linux/proc_fs.h
  723. +++ b/include/linux/proc_fs.h
  724. @@ -257,7 +257,6 @@ struct proc_ns_operations {
  725. extern const struct proc_ns_operations netns_operations;
  726. extern const struct proc_ns_operations utsns_operations;
  727. extern const struct proc_ns_operations ipcns_operations;
  728. -extern const struct proc_ns_operations pidns_operations;
  729. extern const struct proc_ns_operations mntns_operations;
  730.  
  731. union proc_op {
  732. --
  733. 2.6.1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement