namespace.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #include "cgroup-internal.h"
  2. #include <linux/sched/task.h>
  3. #include <linux/slab.h>
  4. #include <linux/nsproxy.h>
  5. #include <linux/proc_ns.h>
  6. /* cgroup namespaces */
  7. static struct ucounts *inc_cgroup_namespaces(struct user_namespace *ns)
  8. {
  9. return inc_ucount(ns, current_euid(), UCOUNT_CGROUP_NAMESPACES);
  10. }
  11. static void dec_cgroup_namespaces(struct ucounts *ucounts)
  12. {
  13. dec_ucount(ucounts, UCOUNT_CGROUP_NAMESPACES);
  14. }
  15. static struct cgroup_namespace *alloc_cgroup_ns(void)
  16. {
  17. struct cgroup_namespace *new_ns;
  18. int ret;
  19. new_ns = kzalloc(sizeof(struct cgroup_namespace), GFP_KERNEL);
  20. if (!new_ns)
  21. return ERR_PTR(-ENOMEM);
  22. ret = ns_alloc_inum(&new_ns->ns);
  23. if (ret) {
  24. kfree(new_ns);
  25. return ERR_PTR(ret);
  26. }
  27. atomic_set(&new_ns->count, 1);
  28. new_ns->ns.ops = &cgroupns_operations;
  29. return new_ns;
  30. }
  31. void free_cgroup_ns(struct cgroup_namespace *ns)
  32. {
  33. put_css_set(ns->root_cset);
  34. dec_cgroup_namespaces(ns->ucounts);
  35. put_user_ns(ns->user_ns);
  36. ns_free_inum(&ns->ns);
  37. kfree(ns);
  38. }
  39. EXPORT_SYMBOL(free_cgroup_ns);
  40. struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
  41. struct user_namespace *user_ns,
  42. struct cgroup_namespace *old_ns)
  43. {
  44. struct cgroup_namespace *new_ns;
  45. struct ucounts *ucounts;
  46. struct css_set *cset;
  47. BUG_ON(!old_ns);
  48. if (!(flags & CLONE_NEWCGROUP)) {
  49. get_cgroup_ns(old_ns);
  50. return old_ns;
  51. }
  52. /* Allow only sysadmin to create cgroup namespace. */
  53. if (!ns_capable(user_ns, CAP_SYS_ADMIN))
  54. return ERR_PTR(-EPERM);
  55. ucounts = inc_cgroup_namespaces(user_ns);
  56. if (!ucounts)
  57. return ERR_PTR(-ENOSPC);
  58. /* It is not safe to take cgroup_mutex here */
  59. spin_lock_irq(&css_set_lock);
  60. cset = task_css_set(current);
  61. get_css_set(cset);
  62. spin_unlock_irq(&css_set_lock);
  63. new_ns = alloc_cgroup_ns();
  64. if (IS_ERR(new_ns)) {
  65. put_css_set(cset);
  66. dec_cgroup_namespaces(ucounts);
  67. return new_ns;
  68. }
  69. new_ns->user_ns = get_user_ns(user_ns);
  70. new_ns->ucounts = ucounts;
  71. new_ns->root_cset = cset;
  72. return new_ns;
  73. }
  74. static inline struct cgroup_namespace *to_cg_ns(struct ns_common *ns)
  75. {
  76. return container_of(ns, struct cgroup_namespace, ns);
  77. }
  78. static int cgroupns_install(struct nsproxy *nsproxy, struct ns_common *ns)
  79. {
  80. struct cgroup_namespace *cgroup_ns = to_cg_ns(ns);
  81. if (!ns_capable(current_user_ns(), CAP_SYS_ADMIN) ||
  82. !ns_capable(cgroup_ns->user_ns, CAP_SYS_ADMIN))
  83. return -EPERM;
  84. /* Don't need to do anything if we are attaching to our own cgroupns. */
  85. if (cgroup_ns == nsproxy->cgroup_ns)
  86. return 0;
  87. get_cgroup_ns(cgroup_ns);
  88. put_cgroup_ns(nsproxy->cgroup_ns);
  89. nsproxy->cgroup_ns = cgroup_ns;
  90. return 0;
  91. }
  92. static struct ns_common *cgroupns_get(struct task_struct *task)
  93. {
  94. struct cgroup_namespace *ns = NULL;
  95. struct nsproxy *nsproxy;
  96. task_lock(task);
  97. nsproxy = task->nsproxy;
  98. if (nsproxy) {
  99. ns = nsproxy->cgroup_ns;
  100. get_cgroup_ns(ns);
  101. }
  102. task_unlock(task);
  103. return ns ? &ns->ns : NULL;
  104. }
  105. static void cgroupns_put(struct ns_common *ns)
  106. {
  107. put_cgroup_ns(to_cg_ns(ns));
  108. }
  109. static struct user_namespace *cgroupns_owner(struct ns_common *ns)
  110. {
  111. return to_cg_ns(ns)->user_ns;
  112. }
  113. const struct proc_ns_operations cgroupns_operations = {
  114. .name = "cgroup",
  115. .type = CLONE_NEWCGROUP,
  116. .get = cgroupns_get,
  117. .put = cgroupns_put,
  118. .install = cgroupns_install,
  119. .owner = cgroupns_owner,
  120. };
  121. static __init int cgroup_namespaces_init(void)
  122. {
  123. return 0;
  124. }
  125. subsys_initcall(cgroup_namespaces_init);