Skip to content

Commit

Permalink
Merge branch 'ucount-rlimit-fixes-for-v5.16' of git://git.kernel.org/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Linus Torvalds committed Dec 23, 2021
2 parents 76657ea + 59ec715 commit 7fe2bc1
Showing 1 changed file with 9 additions and 6 deletions.
15 changes: 9 additions & 6 deletions kernel/ucount.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
struct ucounts *iter;
long max = LONG_MAX;
long ret = 0;

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]);
if (new < 0 || new > max)
ret = LONG_MAX;
else if (iter == ucounts)
ret = new;
max = READ_ONCE(iter->ns->ucount_max[type]);
}
return ret;
}
Expand Down Expand Up @@ -312,15 +313,16 @@ long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type)
{
/* Caller must hold a reference to ucounts */
struct ucounts *iter;
long max = LONG_MAX;
long dec, ret = 0;

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]);
if (new < 0 || new > max)
goto unwind;
if (iter == ucounts)
ret = new;
max = READ_ONCE(iter->ns->ucount_max[type]);
/*
* Grab an extra ucount reference for the caller when
* the rlimit count was previously 0.
Expand All @@ -339,15 +341,16 @@ long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type)
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;
if (get_ucounts_value(ucounts, type) > max)
return true;
long max = rlimit;
if (rlimit > LONG_MAX)
max = LONG_MAX;
for (iter = ucounts; iter; iter = iter->ns->ucounts) {
max = READ_ONCE(iter->ns->ucount_max[type]);
if (get_ucounts_value(iter, type) > max)
return true;
max = READ_ONCE(iter->ns->ucount_max[type]);
}
return false;
}
Expand Down

0 comments on commit 7fe2bc1

Please sign in to comment.