Commit f9c82a4e authored by Alexey Gladkov's avatar Alexey Gladkov Committed by Eric W. Biederman
Browse files

Increase size of ucounts to atomic_long_t



RLIMIT_MSGQUEUE and RLIMIT_MEMLOCK use unsigned long to store their
counters. As a preparation for moving rlimits based on ucounts, we need
to increase the size of the variable to long.

Signed-off-by: default avatarAlexey Gladkov <legion@kernel.org>
Link: https://lkml.kernel.org/r/257aa5fb1a7d81cf0f4c34f39ada2320c4284771.1619094428.git.legion@kernel.org


Signed-off-by: default avatarEric W. Biederman <ebiederm@xmission.com>
parent 9f4ad9e4
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -88,7 +88,7 @@ struct user_namespace {
	struct ctl_table_header *sysctls;
#endif
	struct ucounts		*ucounts;
	int ucount_max[UCOUNT_COUNTS];
	long ucount_max[UCOUNT_COUNTS];
} __randomize_layout;

struct ucounts {
@@ -96,7 +96,7 @@ struct ucounts {
	struct user_namespace *ns;
	kuid_t uid;
	int count;
	atomic_t ucount[UCOUNT_COUNTS];
	atomic_long_t ucount[UCOUNT_COUNTS];
};

extern struct user_namespace init_user_ns;
+8 −8
Original line number Diff line number Diff line
@@ -175,14 +175,14 @@ static void put_ucounts(struct ucounts *ucounts)
	kfree(ucounts);
}

static inline bool atomic_inc_below(atomic_t *v, int u)
static inline bool atomic_long_inc_below(atomic_long_t *v, int u)
{
	int c, old;
	c = atomic_read(v);
	long c, old;
	c = atomic_long_read(v);
	for (;;) {
		if (unlikely(c >= u))
			return false;
		old = atomic_cmpxchg(v, c, c+1);
		old = atomic_long_cmpxchg(v, c, c+1);
		if (likely(old == c))
			return true;
		c = old;
@@ -196,17 +196,17 @@ struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid,
	struct user_namespace *tns;
	ucounts = get_ucounts(ns, uid);
	for (iter = ucounts; iter; iter = tns->ucounts) {
		int max;
		long max;
		tns = iter->ns;
		max = READ_ONCE(tns->ucount_max[type]);
		if (!atomic_inc_below(&iter->ucount[type], max))
		if (!atomic_long_inc_below(&iter->ucount[type], max))
			goto fail;
	}
	return ucounts;
fail:
	bad = iter;
	for (iter = ucounts; iter != bad; iter = iter->ns->ucounts)
		atomic_dec(&iter->ucount[type]);
		atomic_long_dec(&iter->ucount[type]);

	put_ucounts(ucounts);
	return NULL;
@@ -216,7 +216,7 @@ void dec_ucount(struct ucounts *ucounts, enum ucount_type type)
{
	struct ucounts *iter;
	for (iter = ucounts; iter; iter = iter->ns->ucounts) {
		int dec = atomic_dec_if_positive(&iter->ucount[type]);
		long dec = atomic_long_dec_if_positive(&iter->ucount[type]);
		WARN_ON_ONCE(dec < 0);
	}
	put_ucounts(ucounts);