summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-09-03 16:06:50 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-09-08 08:49:00 +0200
commitae16b7c668378ea00eb60ab9d29e0d46b0e7aa15 (patch)
treee5cb3c783e9fe2f38001514423f5a082836ecb7a /kernel
parent1aa3f27e592dea3b6cbc5ef5ec979ba5f511d410 (diff)
Revert "Add a reference to ucounts for each cred"
This reverts commit b2c4d9a33cc2dec7466f97eba2c4dd571ad798a5 which is commit 905ae01c4ae2ae3df05bb141801b1db4b7d83c61 upstream. This commit should not have been applied to the 5.10.y stable tree, so revert it. Reported-by: "Eric W. Biederman" <ebiederm@xmission.com> Link: https://lore.kernel.org/r/87v93k4bl6.fsf@disp2133 Cc: Alexey Gladkov <legion@kernel.org> Cc: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cred.c40
-rw-r--r--kernel/fork.c6
-rw-r--r--kernel/sys.c12
-rw-r--r--kernel/ucount.c40
-rw-r--r--kernel/user_namespace.c3
5 files changed, 3 insertions, 98 deletions
diff --git a/kernel/cred.c b/kernel/cred.c
index 58a8a9e24347..421b1149c651 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -60,7 +60,6 @@ struct cred init_cred = {
.user = INIT_USER,
.user_ns = &init_user_ns,
.group_info = &init_groups,
- .ucounts = &init_ucounts,
};
static inline void set_cred_subscribers(struct cred *cred, int n)
@@ -120,8 +119,6 @@ static void put_cred_rcu(struct rcu_head *rcu)
if (cred->group_info)
put_group_info(cred->group_info);
free_uid(cred->user);
- if (cred->ucounts)
- put_ucounts(cred->ucounts);
put_user_ns(cred->user_ns);
kmem_cache_free(cred_jar, cred);
}
@@ -225,7 +222,6 @@ struct cred *cred_alloc_blank(void)
#ifdef CONFIG_DEBUG_CREDENTIALS
new->magic = CRED_MAGIC;
#endif
- new->ucounts = get_ucounts(&init_ucounts);
if (security_cred_alloc_blank(new, GFP_KERNEL_ACCOUNT) < 0)
goto error;
@@ -288,11 +284,6 @@ struct cred *prepare_creds(void)
if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0)
goto error;
-
- new->ucounts = get_ucounts(new->ucounts);
- if (!new->ucounts)
- goto error;
-
validate_creds(new);
return new;
@@ -372,8 +363,6 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
ret = create_user_ns(new);
if (ret < 0)
goto error_put;
- if (set_cred_ucounts(new) < 0)
- goto error_put;
}
#ifdef CONFIG_KEYS
@@ -664,31 +653,6 @@ int cred_fscmp(const struct cred *a, const struct cred *b)
}
EXPORT_SYMBOL(cred_fscmp);
-int set_cred_ucounts(struct cred *new)
-{
- struct task_struct *task = current;
- const struct cred *old = task->real_cred;
- struct ucounts *old_ucounts = new->ucounts;
-
- if (new->user == old->user && new->user_ns == old->user_ns)
- return 0;
-
- /*
- * This optimization is needed because alloc_ucounts() uses locks
- * for table lookups.
- */
- if (old_ucounts && old_ucounts->ns == new->user_ns && uid_eq(old_ucounts->uid, new->euid))
- return 0;
-
- if (!(new->ucounts = alloc_ucounts(new->user_ns, new->euid)))
- return -EAGAIN;
-
- if (old_ucounts)
- put_ucounts(old_ucounts);
-
- return 0;
-}
-
/*
* initialise the credentials stuff
*/
@@ -755,10 +719,6 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0)
goto error;
- new->ucounts = get_ucounts(new->ucounts);
- if (!new->ucounts)
- goto error;
-
put_cred(old);
validate_creds(new);
return new;
diff --git a/kernel/fork.c b/kernel/fork.c
index 096945ef49ad..9705439439fe 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -2960,12 +2960,6 @@ int ksys_unshare(unsigned long unshare_flags)
if (err)
goto bad_unshare_cleanup_cred;
- if (new_cred) {
- err = set_cred_ucounts(new_cred);
- if (err)
- goto bad_unshare_cleanup_cred;
- }
-
if (new_fs || new_fd || do_sysvsem || new_cred || new_nsproxy) {
if (do_sysvsem) {
/*
diff --git a/kernel/sys.c b/kernel/sys.c
index 0670e824e019..a730c03ee607 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -552,10 +552,6 @@ long __sys_setreuid(uid_t ruid, uid_t euid)
if (retval < 0)
goto error;
- retval = set_cred_ucounts(new);
- if (retval < 0)
- goto error;
-
return commit_creds(new);
error:
@@ -614,10 +610,6 @@ long __sys_setuid(uid_t uid)
if (retval < 0)
goto error;
- retval = set_cred_ucounts(new);
- if (retval < 0)
- goto error;
-
return commit_creds(new);
error:
@@ -693,10 +685,6 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
if (retval < 0)
goto error;
- retval = set_cred_ucounts(new);
- if (retval < 0)
- goto error;
-
return commit_creds(new);
error:
diff --git a/kernel/ucount.c b/kernel/ucount.c
index 9894795043c4..11b1596e2542 100644
--- a/kernel/ucount.c
+++ b/kernel/ucount.c
@@ -8,12 +8,6 @@
#include <linux/kmemleak.h>
#include <linux/user_namespace.h>
-struct ucounts init_ucounts = {
- .ns = &init_user_ns,
- .uid = GLOBAL_ROOT_UID,
- .count = 1,
-};
-
#define UCOUNTS_HASHTABLE_BITS 10
static struct hlist_head ucounts_hashtable[(1 << UCOUNTS_HASHTABLE_BITS)];
static DEFINE_SPINLOCK(ucounts_lock);
@@ -131,15 +125,7 @@ static struct ucounts *find_ucounts(struct user_namespace *ns, kuid_t uid, struc
return NULL;
}
-static void hlist_add_ucounts(struct ucounts *ucounts)
-{
- struct hlist_head *hashent = ucounts_hashentry(ucounts->ns, ucounts->uid);
- spin_lock_irq(&ucounts_lock);
- hlist_add_head(&ucounts->node, hashent);
- spin_unlock_irq(&ucounts_lock);
-}
-
-struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid)
+static struct ucounts *get_ucounts(struct user_namespace *ns, kuid_t uid)
{
struct hlist_head *hashent = ucounts_hashentry(ns, uid);
struct ucounts *ucounts, *new;
@@ -174,26 +160,7 @@ struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid)
return ucounts;
}
-struct ucounts *get_ucounts(struct ucounts *ucounts)
-{
- unsigned long flags;
-
- if (!ucounts)
- return NULL;
-
- spin_lock_irqsave(&ucounts_lock, flags);
- if (ucounts->count == INT_MAX) {
- WARN_ONCE(1, "ucounts: counter has reached its maximum value");
- ucounts = NULL;
- } else {
- ucounts->count += 1;
- }
- spin_unlock_irqrestore(&ucounts_lock, flags);
-
- return ucounts;
-}
-
-void put_ucounts(struct ucounts *ucounts)
+static void put_ucounts(struct ucounts *ucounts)
{
unsigned long flags;
@@ -227,7 +194,7 @@ struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid,
{
struct ucounts *ucounts, *iter, *bad;
struct user_namespace *tns;
- ucounts = alloc_ucounts(ns, uid);
+ ucounts = get_ucounts(ns, uid);
for (iter = ucounts; iter; iter = tns->ucounts) {
int max;
tns = iter->ns;
@@ -270,7 +237,6 @@ static __init int user_namespace_sysctl_init(void)
BUG_ON(!user_header);
BUG_ON(!setup_userns_sysctls(&init_user_ns));
#endif
- hlist_add_ucounts(&init_ucounts);
return 0;
}
subsys_initcall(user_namespace_sysctl_init);
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 8206a13c81eb..ce396ea4de60 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -1340,9 +1340,6 @@ static int userns_install(struct nsset *nsset, struct ns_common *ns)
put_user_ns(cred->user_ns);
set_cred_user_ns(cred, get_user_ns(user_ns));
- if (set_cred_ucounts(cred) < 0)
- return -EINVAL;
-
return 0;
}