Commit 7fe2bc1b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'ucount-rlimit-fixes-for-v5.16' of...

Merge branch 'ucount-rlimit-fixes-for-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace

Pull ucount fix from Eric Biederman:
 "This fixes a silly logic bug in the ucount rlimits code, where it was
  comparing against the wrong limit"

* 'ucount-rlimit-fixes-for-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace:
  ucounts: Fix rlimit max values check
parents 76657eae 59ec7157
...@@ -264,15 +264,16 @@ void dec_ucount(struct ucounts *ucounts, enum ucount_type type) ...@@ -264,15 +264,16 @@ void dec_ucount(struct ucounts *ucounts, enum ucount_type type)
long inc_rlimit_ucounts(struct ucounts *ucounts, enum ucount_type type, long v) long inc_rlimit_ucounts(struct ucounts *ucounts, enum ucount_type type, long v)
{ {
struct ucounts *iter; struct ucounts *iter;
long max = LONG_MAX;
long ret = 0; long ret = 0;
for (iter = ucounts; iter; iter = iter->ns->ucounts) { for (iter = ucounts; iter; iter = iter->ns->ucounts) {
long max = READ_ONCE(iter->ns->ucount_max[type]);
long new = atomic_long_add_return(v, &iter->ucount[type]); long new = atomic_long_add_return(v, &iter->ucount[type]);
if (new < 0 || new > max) if (new < 0 || new > max)
ret = LONG_MAX; ret = LONG_MAX;
else if (iter == ucounts) else if (iter == ucounts)
ret = new; ret = new;
max = READ_ONCE(iter->ns->ucount_max[type]);
} }
return ret; return ret;
} }
...@@ -312,15 +313,16 @@ long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type) ...@@ -312,15 +313,16 @@ long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type)
{ {
/* Caller must hold a reference to ucounts */ /* Caller must hold a reference to ucounts */
struct ucounts *iter; struct ucounts *iter;
long max = LONG_MAX;
long dec, ret = 0; long dec, ret = 0;
for (iter = ucounts; iter; iter = iter->ns->ucounts) { for (iter = ucounts; iter; iter = iter->ns->ucounts) {
long max = READ_ONCE(iter->ns->ucount_max[type]);
long new = atomic_long_add_return(1, &iter->ucount[type]); long new = atomic_long_add_return(1, &iter->ucount[type]);
if (new < 0 || new > max) if (new < 0 || new > max)
goto unwind; goto unwind;
if (iter == ucounts) if (iter == ucounts)
ret = new; ret = new;
max = READ_ONCE(iter->ns->ucount_max[type]);
/* /*
* Grab an extra ucount reference for the caller when * Grab an extra ucount reference for the caller when
* the rlimit count was previously 0. * the rlimit count was previously 0.
...@@ -339,15 +341,16 @@ long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type) ...@@ -339,15 +341,16 @@ long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type)
return 0; return 0;
} }
bool is_ucounts_overlimit(struct ucounts *ucounts, enum ucount_type type, unsigned long max) bool is_ucounts_overlimit(struct ucounts *ucounts, enum ucount_type type, unsigned long rlimit)
{ {
struct ucounts *iter; struct ucounts *iter;
if (get_ucounts_value(ucounts, type) > max) long max = rlimit;
return true; if (rlimit > LONG_MAX)
max = LONG_MAX;
for (iter = ucounts; iter; iter = iter->ns->ucounts) { for (iter = ucounts; iter; iter = iter->ns->ucounts) {
max = READ_ONCE(iter->ns->ucount_max[type]);
if (get_ucounts_value(iter, type) > max) if (get_ucounts_value(iter, type) > max)
return true; return true;
max = READ_ONCE(iter->ns->ucount_max[type]);
} }
return false; return false;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment