From: Linus Torvalds Date: Tue, 29 Jun 2021 03:39:26 +0000 (-0700) Subject: Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm... X-Git-Tag: v5.15~877 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c54b245d011855ea91c5beff07f1db74143ce614;p=platform%2Fkernel%2Flinux-starfive.git Merge branch 'for-linus' of git://git./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 --- c54b245d011855ea91c5beff07f1db74143ce614 diff --cc include/linux/sched/user.h index 3632c5d,82bd253..2462f7d --- a/include/linux/sched/user.h +++ b/include/linux/sched/user.h @@@ -12,8 -12,9 +12,6 @@@ */ struct user_struct { refcount_t __count; /* reference count */ - atomic_t processes; /* How many processes does this user have? */ - atomic_t sigpending; /* How many pending signals does this user have? */ -#ifdef CONFIG_FANOTIFY - atomic_t fanotify_listeners; -#endif #ifdef CONFIG_EPOLL atomic_long_t epoll_watches; /* The number of file descriptors currently watched */ #endif diff --cc include/linux/user_namespace.h index 1d08dbb,61794ae..eb70cab --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@@ -50,10 -50,10 +50,14 @@@ enum ucount_type UCOUNT_INOTIFY_INSTANCES, UCOUNT_INOTIFY_WATCHES, #endif +#ifdef CONFIG_FANOTIFY + UCOUNT_FANOTIFY_GROUPS, + UCOUNT_FANOTIFY_MARKS, +#endif + UCOUNT_RLIMIT_NPROC, + UCOUNT_RLIMIT_MSGQUEUE, + UCOUNT_RLIMIT_SIGPENDING, + UCOUNT_RLIMIT_MEMLOCK, UCOUNT_COUNTS, }; diff --cc kernel/fork.c index 4820c2a,c418204..b4386ff --- a/kernel/fork.c +++ b/kernel/fork.c @@@ -2388,10 -2386,10 +2392,10 @@@ bad_fork_cleanup_threadgroup_lock #endif delayacct_tsk_free(p); bad_fork_cleanup_count: - atomic_dec(&p->cred->user->processes); + dec_rlimit_ucounts(task_ucounts(p), UCOUNT_RLIMIT_NPROC, 1); exit_creds(p); bad_fork_free: - p->state = TASK_DEAD; + WRITE_ONCE(p->__state, TASK_DEAD); put_task_stack(p); delayed_free_task(p); fork_out: diff --cc kernel/signal.c index 20d1d89,9a6dab7..de09203 --- a/kernel/signal.c +++ b/kernel/signal.c @@@ -408,12 -410,11 +408,12 @@@ void task_join_group_stop(struct task_s * appropriate lock must be held to stop the target task from exiting */ static struct sigqueue * -__sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimit) +__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 -425,26 +424,26 @@@ * 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, flags); + 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 = 0; + q->flags = sigqueue_flags; - q->user = user; + q->ucounts = ucounts; } - return q; } diff --cc kernel/ucount.c index 8d8874f,df84a2a..87799e2 --- a/kernel/ucount.c +++ b/kernel/ucount.c @@@ -74,10 -80,10 +80,14 @@@ static struct ctl_table user_table[] = UCOUNT_ENTRY("max_inotify_instances"), UCOUNT_ENTRY("max_inotify_watches"), #endif +#ifdef CONFIG_FANOTIFY + UCOUNT_ENTRY("max_fanotify_groups"), + UCOUNT_ENTRY("max_fanotify_marks"), +#endif + { }, + { }, + { }, + { }, { } }; #endif /* CONFIG_SYSCTL */