summaryrefslogtreecommitdiff
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
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>
-rw-r--r--fs/exec.c4
-rw-r--r--include/linux/cred.h2
-rw-r--r--include/linux/user_namespace.h4
-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
8 files changed, 3 insertions, 108 deletions
diff --git a/fs/exec.c b/fs/exec.c
index c7a4ef8df305..ca89e0e3ef10 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1347,10 +1347,6 @@ int begin_new_exec(struct linux_binprm * bprm)
WRITE_ONCE(me->self_exec_id, me->self_exec_id + 1);
flush_signal_handlers(me, 0);
- retval = set_cred_ucounts(bprm->cred);
- if (retval < 0)
- goto out_unlock;
-
/*
* install the new credentials for this executable
*/
diff --git a/include/linux/cred.h b/include/linux/cred.h
index ad160e5fe5c6..18639c069263 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -144,7 +144,6 @@ struct cred {
#endif
struct user_struct *user; /* real user ID subscription */
struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
- struct ucounts *ucounts;
struct group_info *group_info; /* supplementary groups for euid/fsgid */
/* RCU deletion */
union {
@@ -171,7 +170,6 @@ extern int set_security_override_from_ctx(struct cred *, const char *);
extern int set_create_files_as(struct cred *, struct inode *);
extern int cred_fscmp(const struct cred *, const struct cred *);
extern void __init cred_init(void);
-extern int set_cred_ucounts(struct cred *);
/*
* check for validity of credentials
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index e1bd560da1cd..7616c7bf4b24 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -101,15 +101,11 @@ struct ucounts {
};
extern struct user_namespace init_user_ns;
-extern struct ucounts init_ucounts;
bool setup_userns_sysctls(struct user_namespace *ns);
void retire_userns_sysctls(struct user_namespace *ns);
struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid, enum ucount_type type);
void dec_ucount(struct ucounts *ucounts, enum ucount_type type);
-struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid);
-struct ucounts *get_ucounts(struct ucounts *ucounts);
-void put_ucounts(struct ucounts *ucounts);
#ifdef CONFIG_USER_NS
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;
}