diff options
| author | 2021-06-28 20:39:26 -0700 | |
|---|---|---|
| committer | 2021-06-28 20:39:26 -0700 | |
| commit | c54b245d011855ea91c5beff07f1db74143ce614 (patch) | |
| tree | 7982f28c76f578997f342c7255e222dabeffde63 /kernel/signal.c | |
| parent | Merge tag 'array-bounds-fixes-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gustavoars/linux (diff) | |
| parent | cred: add missing return error code when set_cred_ucounts() failed (diff) | |
| download | linux-dev-c54b245d011855ea91c5beff07f1db74143ce614.tar.xz linux-dev-c54b245d011855ea91c5beff07f1db74143ce614.zip  | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull user namespace rlimit handling update from Eric Biederman:
 "This is the work mainly by Alexey Gladkov to limit rlimits to the
  rlimits of the user that created a user namespace, and to allow users
  to have stricter limits on the resources created within a user
  namespace."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace:
  cred: add missing return error code when set_cred_ucounts() failed
  ucounts: Silence warning in dec_rlimit_ucounts
  ucounts: Set ucount_max to the largest positive value the type can hold
  kselftests: Add test to check for rlimit changes in different user namespaces
  Reimplement RLIMIT_MEMLOCK on top of ucounts
  Reimplement RLIMIT_SIGPENDING on top of ucounts
  Reimplement RLIMIT_MSGQUEUE on top of ucounts
  Reimplement RLIMIT_NPROC on top of ucounts
  Use atomic_t for ucounts reference counting
  Add a reference to ucounts for each cred
  Increase size of ucounts to atomic_long_t
Diffstat (limited to 'kernel/signal.c')
| -rw-r--r-- | kernel/signal.c | 25 | 
1 files changed, 13 insertions, 12 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 20d1d896d5b0..de0920353d30 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -412,8 +412,8 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t gfp_flags,  		 int override_rlimit, const unsigned int sigqueue_flags)  {  	struct sigqueue *q = NULL; -	struct user_struct *user; -	int sigpending; +	struct ucounts *ucounts = NULL; +	long sigpending;  	/*  	 * Protect access to @t credentials. This can go away when all @@ -424,27 +424,26 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t gfp_flags,  	 * changes from/to zero.  	 */  	rcu_read_lock(); -	user = __task_cred(t)->user; -	sigpending = atomic_inc_return(&user->sigpending); +	ucounts = task_ucounts(t); +	sigpending = inc_rlimit_ucounts(ucounts, UCOUNT_RLIMIT_SIGPENDING, 1);  	if (sigpending == 1) -		get_uid(user); +		ucounts = get_ucounts(ucounts);  	rcu_read_unlock(); -	if (override_rlimit || likely(sigpending <= task_rlimit(t, RLIMIT_SIGPENDING))) { +	if (override_rlimit || (sigpending < LONG_MAX && sigpending <= task_rlimit(t, RLIMIT_SIGPENDING))) {  		q = kmem_cache_alloc(sigqueue_cachep, gfp_flags);  	} else {  		print_dropped_signal(sig);  	}  	if (unlikely(q == NULL)) { -		if (atomic_dec_and_test(&user->sigpending)) -			free_uid(user); +		if (ucounts && dec_rlimit_ucounts(ucounts, UCOUNT_RLIMIT_SIGPENDING, 1)) +			put_ucounts(ucounts);  	} else {  		INIT_LIST_HEAD(&q->list);  		q->flags = sigqueue_flags; -		q->user = user; +		q->ucounts = ucounts;  	} -  	return q;  } @@ -452,8 +451,10 @@ static void __sigqueue_free(struct sigqueue *q)  {  	if (q->flags & SIGQUEUE_PREALLOC)  		return; -	if (atomic_dec_and_test(&q->user->sigpending)) -		free_uid(q->user); +	if (q->ucounts && dec_rlimit_ucounts(q->ucounts, UCOUNT_RLIMIT_SIGPENDING, 1)) { +		put_ucounts(q->ucounts); +		q->ucounts = NULL; +	}  	kmem_cache_free(sigqueue_cachep, q);  }  | 
