Skip to content

Commit

Permalink
Revert "Add a reference to ucounts for each cred"
Browse files Browse the repository at this point in the history
This reverts commit b2c4d9a which is
commit 905ae01 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>
  • Loading branch information
gregkh committed Sep 8, 2021
1 parent 1aa3f27 commit ae16b7c
Show file tree
Hide file tree
Showing 8 changed files with 3 additions and 108 deletions.
4 changes: 0 additions & 4 deletions fs/exec.c
Expand Up @@ -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
*/
Expand Down
2 changes: 0 additions & 2 deletions include/linux/cred.h
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
4 changes: 0 additions & 4 deletions include/linux/user_namespace.h
Expand Up @@ -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

Expand Down
40 changes: 0 additions & 40 deletions kernel/cred.c
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
*/
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 0 additions & 6 deletions kernel/fork.c
Expand Up @@ -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) {
/*
Expand Down
12 changes: 0 additions & 12 deletions kernel/sys.c
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
40 changes: 3 additions & 37 deletions kernel/ucount.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
3 changes: 0 additions & 3 deletions kernel/user_namespace.c
Expand Up @@ -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;
}

Expand Down

0 comments on commit ae16b7c

Please sign in to comment.