From: Alexey Gladkov <legion@kernel.org> To: LKML <linux-kernel@vger.kernel.org>, Linux Containers <containers@lists.linux.dev> Cc: 0day robot <lkp@intel.com>, "Eric W . Biederman" <ebiederm@xmission.com>, lkp@lists.01.org, kernel test robot <oliver.sang@intel.com> Subject: [PATCH v2 2/2] ucounts: Move rlimit max values from ucounts max Date: Mon, 29 Nov 2021 21:37:26 +0100 [thread overview] Message-ID: <24c87e225c7950bf2ea1ff4b4a8f237348808241.1638218242.git.legion@kernel.org> (raw) In-Reply-To: <cover.1638218242.git.legion@kernel.org> Since the semantics of maximum rlimit values are different, they need to be separated from ucount_max. This will prevent the error of using inc_count/dec_ucount for rlimit parameters. This patch also renames the functions to emphasize the lack of connection between rlimit_max and ucount_max. v2: - Fix the array-index-out-of-bounds that was found by the lkp project. Reported-by: kernel test robot <oliver.sang@intel.com> Signed-off-by: Alexey Gladkov <legion@kernel.org> --- include/linux/user_namespace.h | 17 ++++++++++++----- kernel/fork.c | 10 +++++----- kernel/ucount.c | 10 +++------- kernel/user_namespace.c | 10 +++++----- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 33a4240e6a6f..812b6935f4a3 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -58,10 +58,11 @@ enum ucount_type { UCOUNT_RLIMIT_MSGQUEUE, UCOUNT_RLIMIT_SIGPENDING, UCOUNT_RLIMIT_MEMLOCK, - UCOUNT_COUNTS, + UCOUNT_ALL_COUNTS, }; -#define MAX_PER_NAMESPACE_UCOUNTS UCOUNT_RLIMIT_NPROC +#define UCOUNT_COUNTS UCOUNT_RLIMIT_NPROC +#define RLIMIT_COUNTS UCOUNT_ALL_COUNTS - UCOUNT_COUNTS + 1 struct user_namespace { struct uid_gid_map uid_map; @@ -99,6 +100,7 @@ struct user_namespace { #endif struct ucounts *ucounts; long ucount_max[UCOUNT_COUNTS]; + long rlimit_max[RLIMIT_COUNTS]; } __randomize_layout; struct ucounts { @@ -106,7 +108,7 @@ struct ucounts { struct user_namespace *ns; kuid_t uid; atomic_t count; - atomic_long_t ucount[UCOUNT_COUNTS]; + atomic_long_t ucount[UCOUNT_ALL_COUNTS]; }; extern struct user_namespace init_user_ns; @@ -131,10 +133,15 @@ long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type); void dec_rlimit_put_ucounts(struct ucounts *ucounts, enum ucount_type type); bool is_ucounts_overlimit(struct ucounts *ucounts, enum ucount_type type, unsigned long max); -static inline void set_rlimit_ucount_max(struct user_namespace *ns, +static inline long get_userns_rlimit_max(struct user_namespace *ns, enum ucount_type type) +{ + return READ_ONCE(ns->rlimit_max[type - UCOUNT_COUNTS]); +} + +static inline void set_userns_rlimit_max(struct user_namespace *ns, enum ucount_type type, unsigned long max) { - ns->ucount_max[type] = max <= LONG_MAX ? max : LONG_MAX; + ns->rlimit_max[type - UCOUNT_COUNTS] = max <= LONG_MAX ? max : LONG_MAX; } #ifdef CONFIG_USER_NS diff --git a/kernel/fork.c b/kernel/fork.c index 3244cc56b697..365819458030 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -836,13 +836,13 @@ void __init fork_init(void) init_task.signal->rlim[RLIMIT_SIGPENDING] = init_task.signal->rlim[RLIMIT_NPROC]; - for (i = 0; i < MAX_PER_NAMESPACE_UCOUNTS; i++) + for (i = 0; i < UCOUNT_COUNTS; i++) init_user_ns.ucount_max[i] = max_threads/2; - set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_NPROC, RLIM_INFINITY); - set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_MSGQUEUE, RLIM_INFINITY); - set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_SIGPENDING, RLIM_INFINITY); - set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_MEMLOCK, RLIM_INFINITY); + set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_NPROC, RLIM_INFINITY); + set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_MSGQUEUE, RLIM_INFINITY); + set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_SIGPENDING, RLIM_INFINITY); + set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_MEMLOCK, RLIM_INFINITY); #ifdef CONFIG_VMAP_STACK cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "fork:vm_stack_cache", diff --git a/kernel/ucount.c b/kernel/ucount.c index 7b32c356ebc5..ffffcfae8474 100644 --- a/kernel/ucount.c +++ b/kernel/ucount.c @@ -87,10 +87,6 @@ static struct ctl_table user_table[] = { UCOUNT_ENTRY("max_fanotify_groups"), UCOUNT_ENTRY("max_fanotify_marks"), #endif - { }, - { }, - { }, - { }, { } }; #endif /* CONFIG_SYSCTL */ @@ -273,7 +269,7 @@ long inc_rlimit_ucounts(struct ucounts *ucounts, enum ucount_type type, long v) ret = LONG_MAX; else if (iter == ucounts) ret = new; - max = READ_ONCE(iter->ns->ucount_max[type]); + max = get_userns_rlimit_max(iter->ns, type); } return ret; } @@ -322,7 +318,7 @@ long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type) goto unwind; if (iter == ucounts) ret = new; - max = READ_ONCE(iter->ns->ucount_max[type]); + max = get_userns_rlimit_max(iter->ns, type); /* * Grab an extra ucount reference for the caller when * the rlimit count was previously 0. @@ -350,7 +346,7 @@ bool is_ucounts_overlimit(struct ucounts *ucounts, enum ucount_type type, unsign for (iter = ucounts; iter; iter = iter->ns->ucounts) { if (get_ucounts_value(iter, type) > max) return true; - max = READ_ONCE(iter->ns->ucount_max[type]); + max = get_userns_rlimit_max(iter->ns, type); } return false; } diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 6b2e3ca7ee99..b9f6729b4e5f 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -119,13 +119,13 @@ int create_user_ns(struct cred *new) ns->owner = owner; ns->group = group; INIT_WORK(&ns->work, free_user_ns); - for (i = 0; i < MAX_PER_NAMESPACE_UCOUNTS; i++) { + for (i = 0; i < UCOUNT_COUNTS; i++) { ns->ucount_max[i] = INT_MAX; } - set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC)); - set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_MSGQUEUE, rlimit(RLIMIT_MSGQUEUE)); - set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_SIGPENDING, rlimit(RLIMIT_SIGPENDING)); - set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_MEMLOCK, rlimit(RLIMIT_MEMLOCK)); + set_userns_rlimit_max(ns, UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC)); + set_userns_rlimit_max(ns, UCOUNT_RLIMIT_MSGQUEUE, rlimit(RLIMIT_MSGQUEUE)); + set_userns_rlimit_max(ns, UCOUNT_RLIMIT_SIGPENDING, rlimit(RLIMIT_SIGPENDING)); + set_userns_rlimit_max(ns, UCOUNT_RLIMIT_MEMLOCK, rlimit(RLIMIT_MEMLOCK)); ns->ucounts = ucounts; /* Inherit USERNS_SETGROUPS_ALLOWED from our parent */ -- 2.33.0
WARNING: multiple messages have this Message-ID (diff)
From: Alexey Gladkov <legion@kernel.org> To: lkp@lists.01.org Subject: [PATCH v2 2/2] ucounts: Move rlimit max values from ucounts max Date: Mon, 29 Nov 2021 21:37:26 +0100 [thread overview] Message-ID: <24c87e225c7950bf2ea1ff4b4a8f237348808241.1638218242.git.legion@kernel.org> (raw) In-Reply-To: <cover.1638218242.git.legion@kernel.org> [-- Attachment #1: Type: text/plain, Size: 6257 bytes --] Since the semantics of maximum rlimit values are different, they need to be separated from ucount_max. This will prevent the error of using inc_count/dec_ucount for rlimit parameters. This patch also renames the functions to emphasize the lack of connection between rlimit_max and ucount_max. v2: - Fix the array-index-out-of-bounds that was found by the lkp project. Reported-by: kernel test robot <oliver.sang@intel.com> Signed-off-by: Alexey Gladkov <legion@kernel.org> --- include/linux/user_namespace.h | 17 ++++++++++++----- kernel/fork.c | 10 +++++----- kernel/ucount.c | 10 +++------- kernel/user_namespace.c | 10 +++++----- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 33a4240e6a6f..812b6935f4a3 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -58,10 +58,11 @@ enum ucount_type { UCOUNT_RLIMIT_MSGQUEUE, UCOUNT_RLIMIT_SIGPENDING, UCOUNT_RLIMIT_MEMLOCK, - UCOUNT_COUNTS, + UCOUNT_ALL_COUNTS, }; -#define MAX_PER_NAMESPACE_UCOUNTS UCOUNT_RLIMIT_NPROC +#define UCOUNT_COUNTS UCOUNT_RLIMIT_NPROC +#define RLIMIT_COUNTS UCOUNT_ALL_COUNTS - UCOUNT_COUNTS + 1 struct user_namespace { struct uid_gid_map uid_map; @@ -99,6 +100,7 @@ struct user_namespace { #endif struct ucounts *ucounts; long ucount_max[UCOUNT_COUNTS]; + long rlimit_max[RLIMIT_COUNTS]; } __randomize_layout; struct ucounts { @@ -106,7 +108,7 @@ struct ucounts { struct user_namespace *ns; kuid_t uid; atomic_t count; - atomic_long_t ucount[UCOUNT_COUNTS]; + atomic_long_t ucount[UCOUNT_ALL_COUNTS]; }; extern struct user_namespace init_user_ns; @@ -131,10 +133,15 @@ long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type); void dec_rlimit_put_ucounts(struct ucounts *ucounts, enum ucount_type type); bool is_ucounts_overlimit(struct ucounts *ucounts, enum ucount_type type, unsigned long max); -static inline void set_rlimit_ucount_max(struct user_namespace *ns, +static inline long get_userns_rlimit_max(struct user_namespace *ns, enum ucount_type type) +{ + return READ_ONCE(ns->rlimit_max[type - UCOUNT_COUNTS]); +} + +static inline void set_userns_rlimit_max(struct user_namespace *ns, enum ucount_type type, unsigned long max) { - ns->ucount_max[type] = max <= LONG_MAX ? max : LONG_MAX; + ns->rlimit_max[type - UCOUNT_COUNTS] = max <= LONG_MAX ? max : LONG_MAX; } #ifdef CONFIG_USER_NS diff --git a/kernel/fork.c b/kernel/fork.c index 3244cc56b697..365819458030 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -836,13 +836,13 @@ void __init fork_init(void) init_task.signal->rlim[RLIMIT_SIGPENDING] = init_task.signal->rlim[RLIMIT_NPROC]; - for (i = 0; i < MAX_PER_NAMESPACE_UCOUNTS; i++) + for (i = 0; i < UCOUNT_COUNTS; i++) init_user_ns.ucount_max[i] = max_threads/2; - set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_NPROC, RLIM_INFINITY); - set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_MSGQUEUE, RLIM_INFINITY); - set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_SIGPENDING, RLIM_INFINITY); - set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_MEMLOCK, RLIM_INFINITY); + set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_NPROC, RLIM_INFINITY); + set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_MSGQUEUE, RLIM_INFINITY); + set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_SIGPENDING, RLIM_INFINITY); + set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_MEMLOCK, RLIM_INFINITY); #ifdef CONFIG_VMAP_STACK cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "fork:vm_stack_cache", diff --git a/kernel/ucount.c b/kernel/ucount.c index 7b32c356ebc5..ffffcfae8474 100644 --- a/kernel/ucount.c +++ b/kernel/ucount.c @@ -87,10 +87,6 @@ static struct ctl_table user_table[] = { UCOUNT_ENTRY("max_fanotify_groups"), UCOUNT_ENTRY("max_fanotify_marks"), #endif - { }, - { }, - { }, - { }, { } }; #endif /* CONFIG_SYSCTL */ @@ -273,7 +269,7 @@ long inc_rlimit_ucounts(struct ucounts *ucounts, enum ucount_type type, long v) ret = LONG_MAX; else if (iter == ucounts) ret = new; - max = READ_ONCE(iter->ns->ucount_max[type]); + max = get_userns_rlimit_max(iter->ns, type); } return ret; } @@ -322,7 +318,7 @@ long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type) goto unwind; if (iter == ucounts) ret = new; - max = READ_ONCE(iter->ns->ucount_max[type]); + max = get_userns_rlimit_max(iter->ns, type); /* * Grab an extra ucount reference for the caller when * the rlimit count was previously 0. @@ -350,7 +346,7 @@ bool is_ucounts_overlimit(struct ucounts *ucounts, enum ucount_type type, unsign for (iter = ucounts; iter; iter = iter->ns->ucounts) { if (get_ucounts_value(iter, type) > max) return true; - max = READ_ONCE(iter->ns->ucount_max[type]); + max = get_userns_rlimit_max(iter->ns, type); } return false; } diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 6b2e3ca7ee99..b9f6729b4e5f 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -119,13 +119,13 @@ int create_user_ns(struct cred *new) ns->owner = owner; ns->group = group; INIT_WORK(&ns->work, free_user_ns); - for (i = 0; i < MAX_PER_NAMESPACE_UCOUNTS; i++) { + for (i = 0; i < UCOUNT_COUNTS; i++) { ns->ucount_max[i] = INT_MAX; } - set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC)); - set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_MSGQUEUE, rlimit(RLIMIT_MSGQUEUE)); - set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_SIGPENDING, rlimit(RLIMIT_SIGPENDING)); - set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_MEMLOCK, rlimit(RLIMIT_MEMLOCK)); + set_userns_rlimit_max(ns, UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC)); + set_userns_rlimit_max(ns, UCOUNT_RLIMIT_MSGQUEUE, rlimit(RLIMIT_MSGQUEUE)); + set_userns_rlimit_max(ns, UCOUNT_RLIMIT_SIGPENDING, rlimit(RLIMIT_SIGPENDING)); + set_userns_rlimit_max(ns, UCOUNT_RLIMIT_MEMLOCK, rlimit(RLIMIT_MEMLOCK)); ns->ucounts = ucounts; /* Inherit USERNS_SETGROUPS_ALLOWED from our parent */ -- 2.33.0
next prev parent reply other threads:[~2021-11-29 20:38 UTC|newest] Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-11-26 14:37 [PATCH v1 0/2] ucounts: Fix rlimit max values check Alexey Gladkov 2021-11-26 14:37 ` [PATCH v1 1/2] " Alexey Gladkov 2021-11-26 14:37 ` [PATCH v1 2/2] ucounts: Move rlimit max values from ucounts max Alexey Gladkov 2021-11-27 16:42 ` kernel test robot 2021-12-03 13:33 ` Dan Carpenter 2021-12-03 13:33 ` Dan Carpenter 2021-12-03 13:54 ` Alexey Gladkov 2021-12-03 13:54 ` Alexey Gladkov 2021-12-03 14:19 ` David Laight 2021-12-03 14:19 ` David Laight 2021-12-03 13:57 ` Alexey Gladkov 2021-12-03 13:57 ` Alexey Gladkov 2021-11-29 7:47 ` [ucounts] dc7e5f9d41: UBSAN:array-index-out-of-bounds_in_kernel/ucount.c kernel test robot 2021-11-29 7:47 ` kernel test robot 2021-11-29 20:37 ` [PATCH v2 0/2] ucounts: Fix rlimit max values check Alexey Gladkov 2021-11-29 20:37 ` Alexey Gladkov 2021-11-29 20:37 ` [PATCH v2 1/2] " Alexey Gladkov 2021-11-29 20:37 ` Alexey Gladkov 2021-11-29 20:37 ` Alexey Gladkov [this message] 2021-11-29 20:37 ` [PATCH v2 2/2] ucounts: Move rlimit max values from ucounts max Alexey Gladkov 2021-12-13 15:50 ` Eric W. Biederman 2021-12-13 15:50 ` Eric W. Biederman 2021-12-17 14:48 ` [PATCH v3] ucounts: Split rlimit and ucount values and max values Alexey Gladkov 2021-12-17 14:48 ` Alexey Gladkov 2021-12-19 19:54 ` Eric W. Biederman 2021-12-19 19:54 ` Eric W. Biederman
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=24c87e225c7950bf2ea1ff4b4a8f237348808241.1638218242.git.legion@kernel.org \ --to=legion@kernel.org \ --cc=containers@lists.linux.dev \ --cc=ebiederm@xmission.com \ --cc=linux-kernel@vger.kernel.org \ --cc=lkp@intel.com \ --cc=lkp@lists.01.org \ --cc=oliver.sang@intel.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.