1410 lines · 35.7 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only #include <linux/export.h>#include <linux/nsproxy.h>#include <linux/slab.h>#include <linux/sched/signal.h>#include <linux/user_namespace.h>#include <linux/proc_ns.h>#include <linux/highuid.h>#include <linux/cred.h>#include <linux/securebits.h>#include <linux/security.h>#include <linux/keyctl.h>#include <linux/key-type.h>#include <keys/user-type.h>#include <linux/seq_file.h>#include <linux/fs.h>#include <linux/uaccess.h>#include <linux/ctype.h>#include <linux/projid.h>#include <linux/fs_struct.h>#include <linux/bsearch.h>#include <linux/sort.h> static struct kmem_cache *user_ns_cachep __ro_after_init;static DEFINE_MUTEX(userns_state_mutex); static bool new_idmap_permitted(const struct file *file,				struct user_namespace *ns, int cap_setid,				struct uid_gid_map *map);static void free_user_ns(struct work_struct *work); static struct ucounts *inc_user_namespaces(struct user_namespace *ns, kuid_t uid){	return inc_ucount(ns, uid, UCOUNT_USER_NAMESPACES);} static void dec_user_namespaces(struct ucounts *ucounts){	return dec_ucount(ucounts, UCOUNT_USER_NAMESPACES);} static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns){	/* Start with the same capabilities as init but useless for doing	 * anything as the capabilities are bound to the new user namespace.	 */	cred->securebits = SECUREBITS_DEFAULT;	cred->cap_inheritable = CAP_EMPTY_SET;	cred->cap_permitted = CAP_FULL_SET;	cred->cap_effective = CAP_FULL_SET;	cred->cap_ambient = CAP_EMPTY_SET;	cred->cap_bset = CAP_FULL_SET;#ifdef CONFIG_KEYS	key_put(cred->request_key_auth);	cred->request_key_auth = NULL;#endif	/* tgcred will be cleared in our caller bc CLONE_THREAD won't be set */	cred->user_ns = user_ns;} static unsigned long enforced_nproc_rlimit(void){	unsigned long limit = RLIM_INFINITY; 	/* Is RLIMIT_NPROC currently enforced? */	if (!uid_eq(current_uid(), GLOBAL_ROOT_UID) ||	    (current_user_ns() != &init_user_ns))		limit = rlimit(RLIMIT_NPROC); 	return limit;} /* * Create a new user namespace, deriving the creator from the user in the * passed credentials, and replacing that user with the new root user for the * new namespace. * * This is called by copy_creds(), which will finish setting the target task's * credentials. */int create_user_ns(struct cred *new){	struct user_namespace *ns, *parent_ns = new->user_ns;	kuid_t owner = new->euid;	kgid_t group = new->egid;	struct ucounts *ucounts;	int ret, i; 	ret = -ENOSPC;	if (parent_ns->level > 32)		goto fail; 	ucounts = inc_user_namespaces(parent_ns, owner);	if (!ucounts)		goto fail; 	/*	 * Verify that we can not violate the policy of which files	 * may be accessed that is specified by the root directory,	 * by verifying that the root directory is at the root of the	 * mount namespace which allows all files to be accessed.	 */	ret = -EPERM;	if (current_chrooted())		goto fail_dec; 	/* The creator needs a mapping in the parent user namespace	 * or else we won't be able to reasonably tell userspace who	 * created a user_namespace.	 */	ret = -EPERM;	if (!kuid_has_mapping(parent_ns, owner) ||	    !kgid_has_mapping(parent_ns, group))		goto fail_dec; 	ret = security_create_user_ns(new);	if (ret < 0)		goto fail_dec; 	ret = -ENOMEM;	ns = kmem_cache_zalloc(user_ns_cachep, GFP_KERNEL);	if (!ns)		goto fail_dec; 	ns->parent_could_setfcap = cap_raised(new->cap_effective, CAP_SETFCAP);	ret = ns_alloc_inum(&ns->ns);	if (ret)		goto fail_free;	ns->ns.ops = &userns_operations; 	refcount_set(&ns->ns.count, 1);	/* Leave the new->user_ns reference with the new user namespace. */	ns->parent = parent_ns;	ns->level = parent_ns->level + 1;	ns->owner = owner;	ns->group = group;	INIT_WORK(&ns->work, free_user_ns);	for (i = 0; i < UCOUNT_COUNTS; i++) {		ns->ucount_max[i] = INT_MAX;	}	set_userns_rlimit_max(ns, UCOUNT_RLIMIT_NPROC, enforced_nproc_rlimit());	set_userns_rlimit_max(ns, UCOUNT_RLIMIT_MSGQUEUE, rlimit(RLIMIT_MSGQUEUE));	set_userns_rlimit_max(ns, UCOUNT_RLIMIT_SIGPENDING, rlimit(RLIMIT_SIGPENDING));	set_userns_rlimit_max(ns, UCOUNT_RLIMIT_MEMLOCK, rlimit(RLIMIT_MEMLOCK));	ns->ucounts = ucounts; 	/* Inherit USERNS_SETGROUPS_ALLOWED from our parent */	mutex_lock(&userns_state_mutex);	ns->flags = parent_ns->flags;	mutex_unlock(&userns_state_mutex); #ifdef CONFIG_KEYS	INIT_LIST_HEAD(&ns->keyring_name_list);	init_rwsem(&ns->keyring_sem);#endif	ret = -ENOMEM;	if (!setup_userns_sysctls(ns))		goto fail_keyring; 	set_cred_user_ns(new, ns);	return 0;fail_keyring:#ifdef CONFIG_PERSISTENT_KEYRINGS	key_put(ns->persistent_keyring_register);#endif	ns_free_inum(&ns->ns);fail_free:	kmem_cache_free(user_ns_cachep, ns);fail_dec:	dec_user_namespaces(ucounts);fail:	return ret;} int unshare_userns(unsigned long unshare_flags, struct cred **new_cred){	struct cred *cred;	int err = -ENOMEM; 	if (!(unshare_flags & CLONE_NEWUSER))		return 0; 	cred = prepare_creds();	if (cred) {		err = create_user_ns(cred);		if (err)			put_cred(cred);		else			*new_cred = cred;	} 	return err;} static void free_user_ns(struct work_struct *work){	struct user_namespace *parent, *ns =		container_of(work, struct user_namespace, work); 	do {		struct ucounts *ucounts = ns->ucounts;		parent = ns->parent;		if (ns->gid_map.nr_extents > UID_GID_MAP_MAX_BASE_EXTENTS) {			kfree(ns->gid_map.forward);			kfree(ns->gid_map.reverse);		}		if (ns->uid_map.nr_extents > UID_GID_MAP_MAX_BASE_EXTENTS) {			kfree(ns->uid_map.forward);			kfree(ns->uid_map.reverse);		}		if (ns->projid_map.nr_extents > UID_GID_MAP_MAX_BASE_EXTENTS) {			kfree(ns->projid_map.forward);			kfree(ns->projid_map.reverse);		}#if IS_ENABLED(CONFIG_BINFMT_MISC)		kfree(ns->binfmt_misc);#endif		retire_userns_sysctls(ns);		key_free_user_ns(ns);		ns_free_inum(&ns->ns);		kmem_cache_free(user_ns_cachep, ns);		dec_user_namespaces(ucounts);		ns = parent;	} while (refcount_dec_and_test(&parent->ns.count));} void __put_user_ns(struct user_namespace *ns){	schedule_work(&ns->work);}EXPORT_SYMBOL(__put_user_ns); /* * struct idmap_key - holds the information necessary to find an idmapping in a * sorted idmap array. It is passed to cmp_map_id() as first argument. */struct idmap_key {	bool map_up; /* true  -> id from kid; false -> kid from id */	u32 id; /* id to find */	u32 count; /* == 0 unless used with map_id_range_down() */}; /* * cmp_map_id - Function to be passed to bsearch() to find the requested * idmapping. Expects struct idmap_key to be passed via @k. */static int cmp_map_id(const void *k, const void *e){	u32 first, last, id2;	const struct idmap_key *key = k;	const struct uid_gid_extent *el = e; 	id2 = key->id + key->count - 1; 	/* handle map_id_{down,up}() */	if (key->map_up)		first = el->lower_first;	else		first = el->first; 	last = first + el->count - 1; 	if (key->id >= first && key->id <= last &&	    (id2 >= first && id2 <= last))		return 0; 	if (key->id < first || id2 < first)		return -1; 	return 1;} /* * map_id_range_down_max - Find idmap via binary search in ordered idmap array. * Can only be called if number of mappings exceeds UID_GID_MAP_MAX_BASE_EXTENTS. */static struct uid_gid_extent *map_id_range_down_max(unsigned extents, struct uid_gid_map *map, u32 id, u32 count){	struct idmap_key key; 	key.map_up = false;	key.count = count;	key.id = id; 	return bsearch(&key, map->forward, extents,		       sizeof(struct uid_gid_extent), cmp_map_id);} /* * map_id_range_down_base - Find idmap via binary search in static extent array. * Can only be called if number of mappings is equal or less than * UID_GID_MAP_MAX_BASE_EXTENTS. */static struct uid_gid_extent *map_id_range_down_base(unsigned extents, struct uid_gid_map *map, u32 id, u32 count){	unsigned idx;	u32 first, last, id2; 	id2 = id + count - 1; 	/* Find the matching extent */	for (idx = 0; idx < extents; idx++) {		first = map->extent[idx].first;		last = first + map->extent[idx].count - 1;		if (id >= first && id <= last &&		    (id2 >= first && id2 <= last))			return &map->extent[idx];	}	return NULL;} static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count){	struct uid_gid_extent *extent;	unsigned extents = map->nr_extents;	smp_rmb(); 	if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)		extent = map_id_range_down_base(extents, map, id, count);	else		extent = map_id_range_down_max(extents, map, id, count); 	/* Map the id or note failure */	if (extent)		id = (id - extent->first) + extent->lower_first;	else		id = (u32) -1; 	return id;} u32 map_id_down(struct uid_gid_map *map, u32 id){	return map_id_range_down(map, id, 1);} /* * map_id_up_base - Find idmap via binary search in static extent array. * Can only be called if number of mappings is equal or less than * UID_GID_MAP_MAX_BASE_EXTENTS. */static struct uid_gid_extent *map_id_up_base(unsigned extents, struct uid_gid_map *map, u32 id){	unsigned idx;	u32 first, last; 	/* Find the matching extent */	for (idx = 0; idx < extents; idx++) {		first = map->extent[idx].lower_first;		last = first + map->extent[idx].count - 1;		if (id >= first && id <= last)			return &map->extent[idx];	}	return NULL;} /* * map_id_up_max - Find idmap via binary search in ordered idmap array. * Can only be called if number of mappings exceeds UID_GID_MAP_MAX_BASE_EXTENTS. */static struct uid_gid_extent *map_id_up_max(unsigned extents, struct uid_gid_map *map, u32 id){	struct idmap_key key; 	key.map_up = true;	key.count = 1;	key.id = id; 	return bsearch(&key, map->reverse, extents,		       sizeof(struct uid_gid_extent), cmp_map_id);} u32 map_id_up(struct uid_gid_map *map, u32 id){	struct uid_gid_extent *extent;	unsigned extents = map->nr_extents;	smp_rmb(); 	if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)		extent = map_id_up_base(extents, map, id);	else		extent = map_id_up_max(extents, map, id); 	/* Map the id or note failure */	if (extent)		id = (id - extent->lower_first) + extent->first;	else		id = (u32) -1; 	return id;} /** *	make_kuid - Map a user-namespace uid pair into a kuid. *	@ns:  User namespace that the uid is in *	@uid: User identifier * *	Maps a user-namespace uid pair into a kernel internal kuid, *	and returns that kuid. * *	When there is no mapping defined for the user-namespace uid *	pair INVALID_UID is returned.  Callers are expected to test *	for and handle INVALID_UID being returned.  INVALID_UID *	may be tested for using uid_valid(). */kuid_t make_kuid(struct user_namespace *ns, uid_t uid){	/* Map the uid to a global kernel uid */	return KUIDT_INIT(map_id_down(&ns->uid_map, uid));}EXPORT_SYMBOL(make_kuid); /** *	from_kuid - Create a uid from a kuid user-namespace pair. *	@targ: The user namespace we want a uid in. *	@kuid: The kernel internal uid to start with. * *	Map @kuid into the user-namespace specified by @targ and *	return the resulting uid. * *	There is always a mapping into the initial user_namespace. * *	If @kuid has no mapping in @targ (uid_t)-1 is returned. */uid_t from_kuid(struct user_namespace *targ, kuid_t kuid){	/* Map the uid from a global kernel uid */	return map_id_up(&targ->uid_map, __kuid_val(kuid));}EXPORT_SYMBOL(from_kuid); /** *	from_kuid_munged - Create a uid from a kuid user-namespace pair. *	@targ: The user namespace we want a uid in. *	@kuid: The kernel internal uid to start with. * *	Map @kuid into the user-namespace specified by @targ and *	return the resulting uid. * *	There is always a mapping into the initial user_namespace. * *	Unlike from_kuid from_kuid_munged never fails and always *	returns a valid uid.  This makes from_kuid_munged appropriate *	for use in syscalls like stat and getuid where failing the *	system call and failing to provide a valid uid are not an *	options. * *	If @kuid has no mapping in @targ overflowuid is returned. */uid_t from_kuid_munged(struct user_namespace *targ, kuid_t kuid){	uid_t uid;	uid = from_kuid(targ, kuid); 	if (uid == (uid_t) -1)		uid = overflowuid;	return uid;}EXPORT_SYMBOL(from_kuid_munged); /** *	make_kgid - Map a user-namespace gid pair into a kgid. *	@ns:  User namespace that the gid is in *	@gid: group identifier * *	Maps a user-namespace gid pair into a kernel internal kgid, *	and returns that kgid. * *	When there is no mapping defined for the user-namespace gid *	pair INVALID_GID is returned.  Callers are expected to test *	for and handle INVALID_GID being returned.  INVALID_GID may be *	tested for using gid_valid(). */kgid_t make_kgid(struct user_namespace *ns, gid_t gid){	/* Map the gid to a global kernel gid */	return KGIDT_INIT(map_id_down(&ns->gid_map, gid));}EXPORT_SYMBOL(make_kgid); /** *	from_kgid - Create a gid from a kgid user-namespace pair. *	@targ: The user namespace we want a gid in. *	@kgid: The kernel internal gid to start with. * *	Map @kgid into the user-namespace specified by @targ and *	return the resulting gid. * *	There is always a mapping into the initial user_namespace. * *	If @kgid has no mapping in @targ (gid_t)-1 is returned. */gid_t from_kgid(struct user_namespace *targ, kgid_t kgid){	/* Map the gid from a global kernel gid */

Lines 1–500 of 1410.