cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

namespace.c (3465B)


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