From nobody Wed Jul 1 10:35:43 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23F83C433F5 for ; Fri, 21 Jan 2022 13:09:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1380549AbiAUNJS convert rfc822-to-8bit (ORCPT ); Fri, 21 Jan 2022 08:09:18 -0500 Received: from us-smtp-delivery-44.mimecast.com ([205.139.111.44]:60373 "EHLO us-smtp-delivery-44.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350519AbiAUNJR (ORCPT ); Fri, 21 Jan 2022 08:09:17 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-88-ecJTHvhXOYaHSMHmN8LB-g-1; Fri, 21 Jan 2022 08:09:13 -0500 X-MC-Unique: ecJTHvhXOYaHSMHmN8LB-g-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5059193920; Fri, 21 Jan 2022 13:09:11 +0000 (UTC) Received: from comp-core-i7-2640m-0182e6.redhat.com (unknown [10.36.110.3]) by smtp.corp.redhat.com (Postfix) with ESMTP id EC85178AA0; Fri, 21 Jan 2022 13:09:07 +0000 (UTC) From: Alexey Gladkov To: LKML , Linux Containers Cc: Alexander Mikhalitsyn , Andrew Morton , Christian Brauner , Daniel Walsh , Davidlohr Bueso , "Eric W . Biederman" , Kirill Tkhai , Manfred Spraul , Serge Hallyn , Varad Gautam , Vasily Averin , kernel test robot Subject: [RFC PATCH v3 1/4] ipc: Store mqueue sysctls in the ipc namespace Date: Fri, 21 Jan 2022 14:08:38 +0100 Message-Id: <861ff67f82a0d82321e843282c3c2f6ed2dc041e.1642769810.git.legion@kernel.org> In-Reply-To: References: <87tuebwo99.fsf@email.froward.int.ebiederm.org> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=legion@kernel.org X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: kernel.org Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Right now, the mqueue sysctls take ipc namespaces into account in a rather hacky way. This works in most cases, but does not respect the user namespace. Within the user namespace, the user cannot change the /proc/sys/fs/mqueue/* parametres. This poses a problem in the rootless containers. To solve this I changed the implementation of the mqueue sysctls just like some other sysctls. So far, the changes do not provide additional access to files. This will be done in a future patch. v3: * Don't implemenet set_permissions to keep the current behavior. v2: * Fixed compilation problem if CONFIG_POSIX_MQUEUE_SYSCTL is not specified. Reported-by: kernel test robot Signed-off-by: Alexey Gladkov --- include/linux/ipc_namespace.h | 16 +++-- ipc/mq_sysctl.c | 121 ++++++++++++++++++---------------- ipc/mqueue.c | 10 ++- ipc/namespace.c | 6 ++ 4 files changed, 88 insertions(+), 65 deletions(-) diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h index b75395ec8d52..fa787d97d60a 100644 --- a/include/linux/ipc_namespace.h +++ b/include/linux/ipc_namespace.h @@ -10,6 +10,7 @@ #include #include #include +#include =20 struct user_namespace; =20 @@ -63,6 +64,9 @@ struct ipc_namespace { unsigned int mq_msg_default; unsigned int mq_msgsize_default; =20 + struct ctl_table_set mq_set; + struct ctl_table_header *mq_sysctls; + /* user_ns which owns the ipc ns */ struct user_namespace *user_ns; struct ucounts *ucounts; @@ -169,14 +173,18 @@ static inline void put_ipc_ns(struct ipc_namespace *n= s) =20 #ifdef CONFIG_POSIX_MQUEUE_SYSCTL =20 -struct ctl_table_header; -extern struct ctl_table_header *mq_register_sysctl_table(void); +void retire_mq_sysctls(struct ipc_namespace *ns); +bool setup_mq_sysctls(struct ipc_namespace *ns); =20 #else /* CONFIG_POSIX_MQUEUE_SYSCTL */ =20 -static inline struct ctl_table_header *mq_register_sysctl_table(void) +static inline void retire_mq_sysctls(struct ipc_namespace *ns) { - return NULL; +} + +static inline bool setup_mq_sysctls(struct ipc_namespace *ns) +{ + return true; } =20 #endif /* CONFIG_POSIX_MQUEUE_SYSCTL */ diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c index 72a92a08c848..fbf6a8b93a26 100644 --- a/ipc/mq_sysctl.c +++ b/ipc/mq_sysctl.c @@ -9,39 +9,9 @@ #include #include =20 -#ifdef CONFIG_PROC_SYSCTL -static void *get_mq(struct ctl_table *table) -{ - char *which =3D table->data; - struct ipc_namespace *ipc_ns =3D current->nsproxy->ipc_ns; - which =3D (which - (char *)&init_ipc_ns) + (char *)ipc_ns; - return which; -} - -static int proc_mq_dointvec(struct ctl_table *table, int write, - void *buffer, size_t *lenp, loff_t *ppos) -{ - struct ctl_table mq_table; - memcpy(&mq_table, table, sizeof(mq_table)); - mq_table.data =3D get_mq(table); - - return proc_dointvec(&mq_table, write, buffer, lenp, ppos); -} - -static int proc_mq_dointvec_minmax(struct ctl_table *table, int write, - void *buffer, size_t *lenp, loff_t *ppos) -{ - struct ctl_table mq_table; - memcpy(&mq_table, table, sizeof(mq_table)); - mq_table.data =3D get_mq(table); - - return proc_dointvec_minmax(&mq_table, write, buffer, - lenp, ppos); -} -#else -#define proc_mq_dointvec NULL -#define proc_mq_dointvec_minmax NULL -#endif +#include +#include +#include =20 static int msg_max_limit_min =3D MIN_MSGMAX; static int msg_max_limit_max =3D HARD_MSGMAX; @@ -55,14 +25,14 @@ static struct ctl_table mq_sysctls[] =3D { .data =3D &init_ipc_ns.mq_queues_max, .maxlen =3D sizeof(int), .mode =3D 0644, - .proc_handler =3D proc_mq_dointvec, + .proc_handler =3D proc_dointvec, }, { .procname =3D "msg_max", .data =3D &init_ipc_ns.mq_msg_max, .maxlen =3D sizeof(int), .mode =3D 0644, - .proc_handler =3D proc_mq_dointvec_minmax, + .proc_handler =3D proc_dointvec_minmax, .extra1 =3D &msg_max_limit_min, .extra2 =3D &msg_max_limit_max, }, @@ -71,7 +41,7 @@ static struct ctl_table mq_sysctls[] =3D { .data =3D &init_ipc_ns.mq_msgsize_max, .maxlen =3D sizeof(int), .mode =3D 0644, - .proc_handler =3D proc_mq_dointvec_minmax, + .proc_handler =3D proc_dointvec_minmax, .extra1 =3D &msg_maxsize_limit_min, .extra2 =3D &msg_maxsize_limit_max, }, @@ -80,7 +50,7 @@ static struct ctl_table mq_sysctls[] =3D { .data =3D &init_ipc_ns.mq_msg_default, .maxlen =3D sizeof(int), .mode =3D 0644, - .proc_handler =3D proc_mq_dointvec_minmax, + .proc_handler =3D proc_dointvec_minmax, .extra1 =3D &msg_max_limit_min, .extra2 =3D &msg_max_limit_max, }, @@ -89,32 +59,73 @@ static struct ctl_table mq_sysctls[] =3D { .data =3D &init_ipc_ns.mq_msgsize_default, .maxlen =3D sizeof(int), .mode =3D 0644, - .proc_handler =3D proc_mq_dointvec_minmax, + .proc_handler =3D proc_dointvec_minmax, .extra1 =3D &msg_maxsize_limit_min, .extra2 =3D &msg_maxsize_limit_max, }, {} }; =20 -static struct ctl_table mq_sysctl_dir[] =3D { - { - .procname =3D "mqueue", - .mode =3D 0555, - .child =3D mq_sysctls, - }, - {} -}; +static struct ctl_table_set *set_lookup(struct ctl_table_root *root) +{ + return ¤t->nsproxy->ipc_ns->mq_set; +} =20 -static struct ctl_table mq_sysctl_root[] =3D { - { - .procname =3D "fs", - .mode =3D 0555, - .child =3D mq_sysctl_dir, - }, - {} +static int set_is_seen(struct ctl_table_set *set) +{ + return ¤t->nsproxy->ipc_ns->mq_set =3D=3D set; +} + +static struct ctl_table_root set_root =3D { + .lookup =3D set_lookup, }; =20 -struct ctl_table_header *mq_register_sysctl_table(void) +bool setup_mq_sysctls(struct ipc_namespace *ns) { - return register_sysctl_table(mq_sysctl_root); + struct ctl_table *tbl; + + setup_sysctl_set(&ns->mq_set, &set_root, set_is_seen); + + tbl =3D kmemdup(mq_sysctls, sizeof(mq_sysctls), GFP_KERNEL); + if (tbl) { + int i; + + for (i =3D 0; i < ARRAY_SIZE(mq_sysctls); i++) { + if (tbl[i].data =3D=3D &init_ipc_ns.mq_queues_max) + tbl[i].data =3D &ns->mq_queues_max; + + else if (tbl[i].data =3D=3D &init_ipc_ns.mq_msg_max) + tbl[i].data =3D &ns->mq_msg_max; + + else if (tbl[i].data =3D=3D &init_ipc_ns.mq_msgsize_max) + tbl[i].data =3D &ns->mq_msgsize_max; + + else if (tbl[i].data =3D=3D &init_ipc_ns.mq_msg_default) + tbl[i].data =3D &ns->mq_msg_default; + + else if (tbl[i].data =3D=3D &init_ipc_ns.mq_msgsize_default) + tbl[i].data =3D &ns->mq_msgsize_default; + else + tbl[i].data =3D NULL; + } + + ns->mq_sysctls =3D __register_sysctl_table(&ns->mq_set, "fs/mqueue", tbl= ); + } + if (!ns->mq_sysctls) { + kfree(tbl); + retire_sysctl_set(&ns->mq_set); + return false; + } + + return true; +} + +void retire_mq_sysctls(struct ipc_namespace *ns) +{ + struct ctl_table *tbl; + + tbl =3D ns->mq_sysctls->ctl_table_arg; + unregister_sysctl_table(ns->mq_sysctls); + retire_sysctl_set(&ns->mq_set); + kfree(tbl); } diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 5becca9be867..1b4a3be71636 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -163,8 +163,6 @@ static void remove_notification(struct mqueue_inode_inf= o *info); =20 static struct kmem_cache *mqueue_inode_cachep; =20 -static struct ctl_table_header *mq_sysctl_table; - static inline struct mqueue_inode_info *MQUEUE_I(struct inode *inode) { return container_of(inode, struct mqueue_inode_info, vfs_inode); @@ -1713,8 +1711,10 @@ static int __init init_mqueue_fs(void) if (mqueue_inode_cachep =3D=3D NULL) return -ENOMEM; =20 - /* ignore failures - they are not fatal */ - mq_sysctl_table =3D mq_register_sysctl_table(); + if (!setup_mq_sysctls(&init_ipc_ns)) { + pr_warn("sysctl registration failed\n"); + return -ENOMEM; + } =20 error =3D register_filesystem(&mqueue_fs_type); if (error) @@ -1731,8 +1731,6 @@ static int __init init_mqueue_fs(void) out_filesystem: unregister_filesystem(&mqueue_fs_type); out_sysctl: - if (mq_sysctl_table) - unregister_sysctl_table(mq_sysctl_table); kmem_cache_destroy(mqueue_inode_cachep); return error; } diff --git a/ipc/namespace.c b/ipc/namespace.c index ae83f0f2651b..f760243ca685 100644 --- a/ipc/namespace.c +++ b/ipc/namespace.c @@ -59,6 +59,10 @@ static struct ipc_namespace *create_ipc_ns(struct user_n= amespace *user_ns, if (err) goto fail_put; =20 + err =3D -ENOMEM; + if (!setup_mq_sysctls(ns)) + goto fail_put; + sem_init_ns(ns); msg_init_ns(ns); shm_init_ns(ns); @@ -125,6 +129,8 @@ static void free_ipc_ns(struct ipc_namespace *ns) msg_exit_ns(ns); shm_exit_ns(ns); =20 + retire_mq_sysctls(ns); + dec_ipc_namespaces(ns->ucounts); put_user_ns(ns->user_ns); ns_free_inum(&ns->ns); --=20 2.33.0 From nobody Wed Jul 1 10:35:43 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EAB45C433F5 for ; Fri, 21 Jan 2022 13:10:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1380550AbiAUNKS convert rfc822-to-8bit (ORCPT ); Fri, 21 Jan 2022 08:10:18 -0500 Received: from us-smtp-delivery-44.mimecast.com ([207.211.30.44]:23857 "EHLO us-smtp-delivery-44.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245103AbiAUNKQ (ORCPT ); Fri, 21 Jan 2022 08:10:16 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-355-2fp-tSzhPpi_DP4pLkh_6Q-1; Fri, 21 Jan 2022 08:10:12 -0500 X-MC-Unique: 2fp-tSzhPpi_DP4pLkh_6Q-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id EDBD983DEE1; Fri, 21 Jan 2022 13:10:10 +0000 (UTC) Received: from comp-core-i7-2640m-0182e6.redhat.com (unknown [10.36.110.3]) by smtp.corp.redhat.com (Postfix) with ESMTP id A985078AA0; Fri, 21 Jan 2022 13:09:11 +0000 (UTC) From: Alexey Gladkov To: LKML , Linux Containers Cc: Alexander Mikhalitsyn , Andrew Morton , Christian Brauner , Daniel Walsh , Davidlohr Bueso , "Eric W . Biederman" , Kirill Tkhai , Manfred Spraul , Serge Hallyn , Varad Gautam , Vasily Averin Subject: [RFC PATCH v3 2/4] ipc: Store ipc sysctls in the ipc namespace Date: Fri, 21 Jan 2022 14:08:39 +0100 Message-Id: <5cee8775a57c18d56701b39d28dfbe9ad8a7cc38.1642769810.git.legion@kernel.org> In-Reply-To: References: <87tuebwo99.fsf@email.froward.int.ebiederm.org> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=legion@kernel.org X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: kernel.org Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The ipc sysctls are not available for modification inside the user namespace. Following the mqueue sysctls, we changed the implementation to be more userns friendly. So far, the changes do not provide additional access to files. This will be done in a future patch. Signed-off-by: Alexey Gladkov --- include/linux/ipc_namespace.h | 21 ++++ ipc/ipc_sysctl.c | 189 ++++++++++++++++++++++------------ ipc/namespace.c | 4 + 3 files changed, 147 insertions(+), 67 deletions(-) diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h index fa787d97d60a..94af746704fa 100644 --- a/include/linux/ipc_namespace.h +++ b/include/linux/ipc_namespace.h @@ -67,6 +67,9 @@ struct ipc_namespace { struct ctl_table_set mq_set; struct ctl_table_header *mq_sysctls; =20 + struct ctl_table_set set; + struct ctl_table_header *ipc_sysctls; + /* user_ns which owns the ipc ns */ struct user_namespace *user_ns; struct ucounts *ucounts; @@ -188,4 +191,22 @@ static inline bool setup_mq_sysctls(struct ipc_namespa= ce *ns) } =20 #endif /* CONFIG_POSIX_MQUEUE_SYSCTL */ + +#ifdef CONFIG_SYSVIPC_SYSCTL + +bool setup_ipc_sysctls(struct ipc_namespace *ns); +void retire_ipc_sysctls(struct ipc_namespace *ns); + +#else /* CONFIG_SYSVIPC_SYSCTL */ + +static inline void retire_ipc_sysctls(struct ipc_namespace *ns) +{ +} + +static inline bool setup_ipc_sysctls(struct ipc_namespace *ns) +{ + return true; +} + +#endif /* CONFIG_SYSVIPC_SYSCTL */ #endif diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index f101c171753f..dd87ba12f5e3 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c @@ -13,43 +13,22 @@ #include #include #include +#include #include "util.h" =20 -static void *get_ipc(struct ctl_table *table) -{ - char *which =3D table->data; - struct ipc_namespace *ipc_ns =3D current->nsproxy->ipc_ns; - which =3D (which - (char *)&init_ipc_ns) + (char *)ipc_ns; - return which; -} - -static int proc_ipc_dointvec(struct ctl_table *table, int write, - void *buffer, size_t *lenp, loff_t *ppos) -{ - struct ctl_table ipc_table; - - memcpy(&ipc_table, table, sizeof(ipc_table)); - ipc_table.data =3D get_ipc(table); - - return proc_dointvec(&ipc_table, write, buffer, lenp, ppos); -} - -static int proc_ipc_dointvec_minmax(struct ctl_table *table, int write, +static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int w= rite, void *buffer, size_t *lenp, loff_t *ppos) { + struct ipc_namespace *ns =3D table->extra1; struct ctl_table ipc_table; + int err; =20 memcpy(&ipc_table, table, sizeof(ipc_table)); - ipc_table.data =3D get_ipc(table); =20 - return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); -} + ipc_table.extra1 =3D SYSCTL_ZERO; + ipc_table.extra2 =3D SYSCTL_ONE; =20 -static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int w= rite, - void *buffer, size_t *lenp, loff_t *ppos) -{ - struct ipc_namespace *ns =3D current->nsproxy->ipc_ns; - int err =3D proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos); + err =3D proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); =20 if (err < 0) return err; @@ -58,17 +37,6 @@ static int proc_ipc_dointvec_minmax_orphans(struct ctl_t= able *table, int write, return err; } =20 -static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write, - void *buffer, size_t *lenp, loff_t *ppos) -{ - struct ctl_table ipc_table; - memcpy(&ipc_table, table, sizeof(ipc_table)); - ipc_table.data =3D get_ipc(table); - - return proc_doulongvec_minmax(&ipc_table, write, buffer, - lenp, ppos); -} - static int proc_ipc_auto_msgmni(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { @@ -87,11 +55,17 @@ static int proc_ipc_auto_msgmni(struct ctl_table *table= , int write, static int proc_ipc_sem_dointvec(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { + struct ipc_namespace *ns =3D table->extra1; + struct ctl_table ipc_table; int ret, semmni; - struct ipc_namespace *ns =3D current->nsproxy->ipc_ns; + + memcpy(&ipc_table, table, sizeof(ipc_table)); + + ipc_table.extra1 =3D NULL; + ipc_table.extra2 =3D NULL; =20 semmni =3D ns->sem_ctls[3]; - ret =3D proc_ipc_dointvec(table, write, buffer, lenp, ppos); + ret =3D proc_dointvec(table, write, buffer, lenp, ppos); =20 if (!ret) ret =3D sem_check_semmni(current->nsproxy->ipc_ns); @@ -108,12 +82,18 @@ static int proc_ipc_sem_dointvec(struct ctl_table *tab= le, int write, static int proc_ipc_dointvec_minmax_checkpoint_restore(struct ctl_table *t= able, int write, void *buffer, size_t *lenp, loff_t *ppos) { - struct user_namespace *user_ns =3D current->nsproxy->ipc_ns->user_ns; + struct ipc_namespace *ns =3D table->extra1; + struct ctl_table ipc_table; =20 - if (write && !checkpoint_restore_ns_capable(user_ns)) + if (write && !checkpoint_restore_ns_capable(ns->user_ns)) return -EPERM; =20 - return proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos); + memcpy(&ipc_table, table, sizeof(ipc_table)); + + ipc_table.extra1 =3D SYSCTL_ZERO; + ipc_table.extra2 =3D SYSCTL_INT_MAX; + + return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); } #endif =20 @@ -121,27 +101,27 @@ int ipc_mni =3D IPCMNI; int ipc_mni_shift =3D IPCMNI_SHIFT; int ipc_min_cycle =3D RADIX_TREE_MAP_SIZE; =20 -static struct ctl_table ipc_kern_table[] =3D { +static struct ctl_table ipc_sysctls[] =3D { { .procname =3D "shmmax", .data =3D &init_ipc_ns.shm_ctlmax, .maxlen =3D sizeof(init_ipc_ns.shm_ctlmax), .mode =3D 0644, - .proc_handler =3D proc_ipc_doulongvec_minmax, + .proc_handler =3D proc_doulongvec_minmax, }, { .procname =3D "shmall", .data =3D &init_ipc_ns.shm_ctlall, .maxlen =3D sizeof(init_ipc_ns.shm_ctlall), .mode =3D 0644, - .proc_handler =3D proc_ipc_doulongvec_minmax, + .proc_handler =3D proc_doulongvec_minmax, }, { .procname =3D "shmmni", .data =3D &init_ipc_ns.shm_ctlmni, .maxlen =3D sizeof(init_ipc_ns.shm_ctlmni), .mode =3D 0644, - .proc_handler =3D proc_ipc_dointvec_minmax, + .proc_handler =3D proc_dointvec_minmax, .extra1 =3D SYSCTL_ZERO, .extra2 =3D &ipc_mni, }, @@ -151,15 +131,13 @@ static struct ctl_table ipc_kern_table[] =3D { .maxlen =3D sizeof(init_ipc_ns.shm_rmid_forced), .mode =3D 0644, .proc_handler =3D proc_ipc_dointvec_minmax_orphans, - .extra1 =3D SYSCTL_ZERO, - .extra2 =3D SYSCTL_ONE, }, { .procname =3D "msgmax", .data =3D &init_ipc_ns.msg_ctlmax, .maxlen =3D sizeof(init_ipc_ns.msg_ctlmax), .mode =3D 0644, - .proc_handler =3D proc_ipc_dointvec_minmax, + .proc_handler =3D proc_dointvec_minmax, .extra1 =3D SYSCTL_ZERO, .extra2 =3D SYSCTL_INT_MAX, }, @@ -168,7 +146,7 @@ static struct ctl_table ipc_kern_table[] =3D { .data =3D &init_ipc_ns.msg_ctlmni, .maxlen =3D sizeof(init_ipc_ns.msg_ctlmni), .mode =3D 0644, - .proc_handler =3D proc_ipc_dointvec_minmax, + .proc_handler =3D proc_dointvec_minmax, .extra1 =3D SYSCTL_ZERO, .extra2 =3D &ipc_mni, }, @@ -186,7 +164,7 @@ static struct ctl_table ipc_kern_table[] =3D { .data =3D &init_ipc_ns.msg_ctlmnb, .maxlen =3D sizeof(init_ipc_ns.msg_ctlmnb), .mode =3D 0644, - .proc_handler =3D proc_ipc_dointvec_minmax, + .proc_handler =3D proc_dointvec_minmax, .extra1 =3D SYSCTL_ZERO, .extra2 =3D SYSCTL_INT_MAX, }, @@ -204,8 +182,6 @@ static struct ctl_table ipc_kern_table[] =3D { .maxlen =3D sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id), .mode =3D 0666, .proc_handler =3D proc_ipc_dointvec_minmax_checkpoint_restore, - .extra1 =3D SYSCTL_ZERO, - .extra2 =3D SYSCTL_INT_MAX, }, { .procname =3D "msg_next_id", @@ -213,8 +189,6 @@ static struct ctl_table ipc_kern_table[] =3D { .maxlen =3D sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id), .mode =3D 0666, .proc_handler =3D proc_ipc_dointvec_minmax_checkpoint_restore, - .extra1 =3D SYSCTL_ZERO, - .extra2 =3D SYSCTL_INT_MAX, }, { .procname =3D "shm_next_id", @@ -222,25 +196,106 @@ static struct ctl_table ipc_kern_table[] =3D { .maxlen =3D sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id), .mode =3D 0666, .proc_handler =3D proc_ipc_dointvec_minmax_checkpoint_restore, - .extra1 =3D SYSCTL_ZERO, - .extra2 =3D SYSCTL_INT_MAX, }, #endif {} }; =20 -static struct ctl_table ipc_root_table[] =3D { - { - .procname =3D "kernel", - .mode =3D 0555, - .child =3D ipc_kern_table, - }, - {} +static struct ctl_table_set *set_lookup(struct ctl_table_root *root) +{ + return ¤t->nsproxy->ipc_ns->set; +} + +static int set_is_seen(struct ctl_table_set *set) +{ + return ¤t->nsproxy->ipc_ns->set =3D=3D set; +} + +static struct ctl_table_root set_root =3D { + .lookup =3D set_lookup, }; =20 +bool setup_ipc_sysctls(struct ipc_namespace *ns) +{ + struct ctl_table *tbl; + + setup_sysctl_set(&ns->set, &set_root, set_is_seen); + + tbl =3D kmemdup(ipc_sysctls, sizeof(ipc_sysctls), GFP_KERNEL); + if (tbl) { + int i; + + for (i =3D 0; i < ARRAY_SIZE(ipc_sysctls); i++) { + if (tbl[i].data =3D=3D &init_ipc_ns.shm_ctlmax) { + tbl[i].data =3D &ns->shm_ctlmax; + + } else if (tbl[i].data =3D=3D &init_ipc_ns.shm_ctlall) { + tbl[i].data =3D &ns->shm_ctlall; + + } else if (tbl[i].data =3D=3D &init_ipc_ns.shm_ctlmni) { + tbl[i].data =3D &ns->shm_ctlmni; + + } else if (tbl[i].data =3D=3D &init_ipc_ns.shm_rmid_forced) { + tbl[i].data =3D &ns->shm_rmid_forced; + tbl[i].extra1 =3D ns; + + } else if (tbl[i].data =3D=3D &init_ipc_ns.msg_ctlmax) { + tbl[i].data =3D &ns->msg_ctlmax; + + } else if (tbl[i].data =3D=3D &init_ipc_ns.msg_ctlmni) { + tbl[i].data =3D &ns->msg_ctlmni; + + } else if (tbl[i].data =3D=3D &init_ipc_ns.msg_ctlmnb) { + tbl[i].data =3D &ns->msg_ctlmnb; + + } else if (tbl[i].data =3D=3D &init_ipc_ns.sem_ctls) { + tbl[i].data =3D &ns->sem_ctls; + tbl[i].extra1 =3D ns; +#ifdef CONFIG_CHECKPOINT_RESTORE + } else if (tbl[i].data =3D=3D &init_ipc_ns.ids[IPC_SEM_IDS].next_id) { + tbl[i].data =3D &ns->ids[IPC_SEM_IDS].next_id; + tbl[i].extra1 =3D ns; + + } else if (tbl[i].data =3D=3D &init_ipc_ns.ids[IPC_MSG_IDS].next_id) { + tbl[i].data =3D &ns->ids[IPC_MSG_IDS].next_id; + tbl[i].extra1 =3D ns; + + } else if (tbl[i].data =3D=3D &init_ipc_ns.ids[IPC_SHM_IDS].next_id) { + tbl[i].data =3D &ns->ids[IPC_SHM_IDS].next_id; + tbl[i].extra1 =3D ns; +#endif + } else { + tbl[i].data =3D NULL; + } + } + + ns->ipc_sysctls =3D __register_sysctl_table(&ns->set, "kernel", tbl); + } + if (!ns->ipc_sysctls) { + kfree(tbl); + retire_sysctl_set(&ns->set); + return false; + } + + return true; +} + +void retire_ipc_sysctls(struct ipc_namespace *ns) +{ + struct ctl_table *tbl; + + tbl =3D ns->ipc_sysctls->ctl_table_arg; + unregister_sysctl_table(ns->ipc_sysctls); + retire_sysctl_set(&ns->set); + kfree(tbl); +} + static int __init ipc_sysctl_init(void) { - register_sysctl_table(ipc_root_table); + if (!setup_ipc_sysctls(&init_ipc_ns)) { + pr_warn("ipc sysctl registration failed\n"); + return -ENOMEM; + } return 0; } =20 diff --git a/ipc/namespace.c b/ipc/namespace.c index f760243ca685..754f3237194a 100644 --- a/ipc/namespace.c +++ b/ipc/namespace.c @@ -63,6 +63,9 @@ static struct ipc_namespace *create_ipc_ns(struct user_na= mespace *user_ns, if (!setup_mq_sysctls(ns)) goto fail_put; =20 + if (!setup_ipc_sysctls(ns)) + goto fail_put; + sem_init_ns(ns); msg_init_ns(ns); shm_init_ns(ns); @@ -130,6 +133,7 @@ static void free_ipc_ns(struct ipc_namespace *ns) shm_exit_ns(ns); =20 retire_mq_sysctls(ns); + retire_ipc_sysctls(ns); =20 dec_ipc_namespaces(ns->ucounts); put_user_ns(ns->user_ns); --=20 2.33.0 From nobody Wed Jul 1 10:35:43 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1CBE0C433F5 for ; Fri, 21 Jan 2022 13:10:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1380559AbiAUNKZ convert rfc822-to-8bit (ORCPT ); Fri, 21 Jan 2022 08:10:25 -0500 Received: from us-smtp-delivery-44.mimecast.com ([205.139.111.44]:58576 "EHLO us-smtp-delivery-44.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245103AbiAUNKW (ORCPT ); Fri, 21 Jan 2022 08:10:22 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-642-ArJwf6q4PCK3KbstVWpcDA-1; Fri, 21 Jan 2022 08:10:16 -0500 X-MC-Unique: ArJwf6q4PCK3KbstVWpcDA-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A0242101F7A5; Fri, 21 Jan 2022 13:10:14 +0000 (UTC) Received: from comp-core-i7-2640m-0182e6.redhat.com (unknown [10.36.110.3]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5F36078AA0; Fri, 21 Jan 2022 13:10:11 +0000 (UTC) From: Alexey Gladkov To: LKML , Linux Containers Cc: Alexander Mikhalitsyn , Andrew Morton , Christian Brauner , Daniel Walsh , Davidlohr Bueso , "Eric W . Biederman" , Kirill Tkhai , Manfred Spraul , Serge Hallyn , Varad Gautam , Vasily Averin Subject: [RFC PATCH v3 3/4] ipc: Merge ipc_sysctl and mq_sysctl Date: Fri, 21 Jan 2022 14:08:40 +0100 Message-Id: <1dba01b2f206a097fb2fc614338e1a7aebac5567.1642769810.git.legion@kernel.org> In-Reply-To: References: <87tuebwo99.fsf@email.froward.int.ebiederm.org> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=legion@kernel.org X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: kernel.org Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Both mq_sysctl and ipc_sysctl are in the ipc namespace and both use identical helpers so they can be merged into a single source file. Signed-off-by: Alexey Gladkov --- include/linux/ipc_namespace.h | 41 ++--------- ipc/Makefile | 7 +- ipc/ipc_sysctl.c | 131 ++++++++++++++++++++++++++++++++-- ipc/mq_sysctl.c | 131 ---------------------------------- ipc/mqueue.c | 5 -- ipc/namespace.c | 4 -- ipc/util.h | 4 +- 7 files changed, 132 insertions(+), 191 deletions(-) delete mode 100644 ipc/mq_sysctl.c diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h index 94af746704fa..461540d1cac4 100644 --- a/include/linux/ipc_namespace.h +++ b/include/linux/ipc_namespace.h @@ -64,10 +64,8 @@ struct ipc_namespace { unsigned int mq_msg_default; unsigned int mq_msgsize_default; =20 - struct ctl_table_set mq_set; - struct ctl_table_header *mq_sysctls; - struct ctl_table_set set; + struct ctl_table_header *mq_sysctls; struct ctl_table_header *ipc_sysctls; =20 /* user_ns which owns the ipc ns */ @@ -88,8 +86,6 @@ extern void shm_destroy_orphaned(struct ipc_namespace *ns= ); static inline void shm_destroy_orphaned(struct ipc_namespace *ns) {} #endif /* CONFIG_SYSVIPC */ =20 -#ifdef CONFIG_POSIX_MQUEUE -extern int mq_init_ns(struct ipc_namespace *ns); /* * POSIX Message Queue default values: * @@ -123,6 +119,9 @@ extern int mq_init_ns(struct ipc_namespace *ns); #define DFLT_MSGSIZE 8192U #define DFLT_MSGSIZEMAX 8192 #define HARD_MSGSIZEMAX (16*1024*1024) + +#ifdef CONFIG_POSIX_MQUEUE +extern int mq_init_ns(struct ipc_namespace *ns); #else static inline int mq_init_ns(struct ipc_namespace *ns) { return 0; } #endif @@ -174,39 +173,7 @@ static inline void put_ipc_ns(struct ipc_namespace *ns) } #endif =20 -#ifdef CONFIG_POSIX_MQUEUE_SYSCTL - -void retire_mq_sysctls(struct ipc_namespace *ns); -bool setup_mq_sysctls(struct ipc_namespace *ns); - -#else /* CONFIG_POSIX_MQUEUE_SYSCTL */ - -static inline void retire_mq_sysctls(struct ipc_namespace *ns) -{ -} - -static inline bool setup_mq_sysctls(struct ipc_namespace *ns) -{ - return true; -} - -#endif /* CONFIG_POSIX_MQUEUE_SYSCTL */ - -#ifdef CONFIG_SYSVIPC_SYSCTL - bool setup_ipc_sysctls(struct ipc_namespace *ns); void retire_ipc_sysctls(struct ipc_namespace *ns); =20 -#else /* CONFIG_SYSVIPC_SYSCTL */ - -static inline void retire_ipc_sysctls(struct ipc_namespace *ns) -{ -} - -static inline bool setup_ipc_sysctls(struct ipc_namespace *ns) -{ - return true; -} - -#endif /* CONFIG_SYSVIPC_SYSCTL */ #endif diff --git a/ipc/Makefile b/ipc/Makefile index c2558c430f51..f79eab42a4dc 100644 --- a/ipc/Makefile +++ b/ipc/Makefile @@ -4,9 +4,6 @@ # =20 obj-$(CONFIG_SYSVIPC_COMPAT) +=3D compat.o -obj-$(CONFIG_SYSVIPC) +=3D util.o msgutil.o msg.o sem.o shm.o syscall.o -obj-$(CONFIG_SYSVIPC_SYSCTL) +=3D ipc_sysctl.o -obj-$(CONFIG_POSIX_MQUEUE) +=3D mqueue.o msgutil.o +obj-$(CONFIG_SYSVIPC) +=3D util.o msgutil.o msg.o sem.o shm.o syscall.o ip= c_sysctl.o +obj-$(CONFIG_POSIX_MQUEUE) +=3D mqueue.o msgutil.o ipc_sysctl.o obj-$(CONFIG_IPC_NS) +=3D namespace.o -obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) +=3D mq_sysctl.o - diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index dd87ba12f5e3..9fc8e3e75be7 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c @@ -201,6 +201,59 @@ static struct ctl_table ipc_sysctls[] =3D { {} }; =20 +static int msg_max_limit_min =3D MIN_MSGMAX; +static int msg_max_limit_max =3D HARD_MSGMAX; + +static int msg_maxsize_limit_min =3D MIN_MSGSIZEMAX; +static int msg_maxsize_limit_max =3D HARD_MSGSIZEMAX; + +static struct ctl_table mq_sysctls[] =3D { + { + .procname =3D "queues_max", + .data =3D &init_ipc_ns.mq_queues_max, + .maxlen =3D sizeof(int), + .mode =3D 0644, + .proc_handler =3D proc_dointvec, + }, + { + .procname =3D "msg_max", + .data =3D &init_ipc_ns.mq_msg_max, + .maxlen =3D sizeof(int), + .mode =3D 0644, + .proc_handler =3D proc_dointvec_minmax, + .extra1 =3D &msg_max_limit_min, + .extra2 =3D &msg_max_limit_max, + }, + { + .procname =3D "msgsize_max", + .data =3D &init_ipc_ns.mq_msgsize_max, + .maxlen =3D sizeof(int), + .mode =3D 0644, + .proc_handler =3D proc_dointvec_minmax, + .extra1 =3D &msg_maxsize_limit_min, + .extra2 =3D &msg_maxsize_limit_max, + }, + { + .procname =3D "msg_default", + .data =3D &init_ipc_ns.mq_msg_default, + .maxlen =3D sizeof(int), + .mode =3D 0644, + .proc_handler =3D proc_dointvec_minmax, + .extra1 =3D &msg_max_limit_min, + .extra2 =3D &msg_max_limit_max, + }, + { + .procname =3D "msgsize_default", + .data =3D &init_ipc_ns.mq_msgsize_default, + .maxlen =3D sizeof(int), + .mode =3D 0644, + .proc_handler =3D proc_dointvec_minmax, + .extra1 =3D &msg_maxsize_limit_min, + .extra2 =3D &msg_maxsize_limit_max, + }, + {} +}; + static struct ctl_table_set *set_lookup(struct ctl_table_root *root) { return ¤t->nsproxy->ipc_ns->set; @@ -215,12 +268,10 @@ static struct ctl_table_root set_root =3D { .lookup =3D set_lookup, }; =20 -bool setup_ipc_sysctls(struct ipc_namespace *ns) +static bool register_ipc_sysctl_table(struct ipc_namespace *ns) { struct ctl_table *tbl; =20 - setup_sysctl_set(&ns->set, &set_root, set_is_seen); - tbl =3D kmemdup(ipc_sysctls, sizeof(ipc_sysctls), GFP_KERNEL); if (tbl) { int i; @@ -273,23 +324,91 @@ bool setup_ipc_sysctls(struct ipc_namespace *ns) } if (!ns->ipc_sysctls) { kfree(tbl); - retire_sysctl_set(&ns->set); return false; } =20 return true; } =20 -void retire_ipc_sysctls(struct ipc_namespace *ns) +static void unregister_ipc_sysctl_table(struct ipc_namespace *ns) { struct ctl_table *tbl; =20 tbl =3D ns->ipc_sysctls->ctl_table_arg; unregister_sysctl_table(ns->ipc_sysctls); - retire_sysctl_set(&ns->set); kfree(tbl); } =20 +static bool register_mqueue_sysctl_table(struct ipc_namespace *ns) +{ + struct ctl_table *tbl; + + tbl =3D kmemdup(mq_sysctls, sizeof(mq_sysctls), GFP_KERNEL); + if (tbl) { + int i; + + for (i =3D 0; i < ARRAY_SIZE(mq_sysctls); i++) { + if (tbl[i].data =3D=3D &init_ipc_ns.mq_queues_max) + tbl[i].data =3D &ns->mq_queues_max; + + else if (tbl[i].data =3D=3D &init_ipc_ns.mq_msg_max) + tbl[i].data =3D &ns->mq_msg_max; + + else if (tbl[i].data =3D=3D &init_ipc_ns.mq_msgsize_max) + tbl[i].data =3D &ns->mq_msgsize_max; + + else if (tbl[i].data =3D=3D &init_ipc_ns.mq_msg_default) + tbl[i].data =3D &ns->mq_msg_default; + + else if (tbl[i].data =3D=3D &init_ipc_ns.mq_msgsize_default) + tbl[i].data =3D &ns->mq_msgsize_default; + else + tbl[i].data =3D NULL; + } + + ns->mq_sysctls =3D __register_sysctl_table(&ns->set, "fs/mqueue", tbl); + } + if (!ns->mq_sysctls) { + kfree(tbl); + return false; + } + + return true; +} + +static void unregister_mqueue_sysctl_table(struct ipc_namespace *ns) +{ + struct ctl_table *tbl; + + tbl =3D ns->mq_sysctls->ctl_table_arg; + unregister_sysctl_table(ns->mq_sysctls); + kfree(tbl); +} + +bool setup_ipc_sysctls(struct ipc_namespace *ns) +{ + setup_sysctl_set(&ns->set, &set_root, set_is_seen); + + if (IS_ENABLED(CONFIG_SYSVIPC_SYSCTL)) + register_ipc_sysctl_table(ns); + + if (IS_ENABLED(CONFIG_POSIX_MQUEUE_SYSCTL)) + register_mqueue_sysctl_table(ns); + + return true; +} + +void retire_ipc_sysctls(struct ipc_namespace *ns) +{ + if (IS_ENABLED(CONFIG_SYSVIPC_SYSCTL)) + unregister_ipc_sysctl_table(ns); + + if (IS_ENABLED(CONFIG_POSIX_MQUEUE_SYSCTL)) + unregister_mqueue_sysctl_table(ns); + + retire_sysctl_set(&ns->set); +} + static int __init ipc_sysctl_init(void) { if (!setup_ipc_sysctls(&init_ipc_ns)) { diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c deleted file mode 100644 index fbf6a8b93a26..000000000000 --- a/ipc/mq_sysctl.c +++ /dev/null @@ -1,131 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2007 IBM Corporation - * - * Author: Cedric Le Goater - */ - -#include -#include -#include - -#include -#include -#include - -static int msg_max_limit_min =3D MIN_MSGMAX; -static int msg_max_limit_max =3D HARD_MSGMAX; - -static int msg_maxsize_limit_min =3D MIN_MSGSIZEMAX; -static int msg_maxsize_limit_max =3D HARD_MSGSIZEMAX; - -static struct ctl_table mq_sysctls[] =3D { - { - .procname =3D "queues_max", - .data =3D &init_ipc_ns.mq_queues_max, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec, - }, - { - .procname =3D "msg_max", - .data =3D &init_ipc_ns.mq_msg_max, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec_minmax, - .extra1 =3D &msg_max_limit_min, - .extra2 =3D &msg_max_limit_max, - }, - { - .procname =3D "msgsize_max", - .data =3D &init_ipc_ns.mq_msgsize_max, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec_minmax, - .extra1 =3D &msg_maxsize_limit_min, - .extra2 =3D &msg_maxsize_limit_max, - }, - { - .procname =3D "msg_default", - .data =3D &init_ipc_ns.mq_msg_default, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec_minmax, - .extra1 =3D &msg_max_limit_min, - .extra2 =3D &msg_max_limit_max, - }, - { - .procname =3D "msgsize_default", - .data =3D &init_ipc_ns.mq_msgsize_default, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec_minmax, - .extra1 =3D &msg_maxsize_limit_min, - .extra2 =3D &msg_maxsize_limit_max, - }, - {} -}; - -static struct ctl_table_set *set_lookup(struct ctl_table_root *root) -{ - return ¤t->nsproxy->ipc_ns->mq_set; -} - -static int set_is_seen(struct ctl_table_set *set) -{ - return ¤t->nsproxy->ipc_ns->mq_set =3D=3D set; -} - -static struct ctl_table_root set_root =3D { - .lookup =3D set_lookup, -}; - -bool setup_mq_sysctls(struct ipc_namespace *ns) -{ - struct ctl_table *tbl; - - setup_sysctl_set(&ns->mq_set, &set_root, set_is_seen); - - tbl =3D kmemdup(mq_sysctls, sizeof(mq_sysctls), GFP_KERNEL); - if (tbl) { - int i; - - for (i =3D 0; i < ARRAY_SIZE(mq_sysctls); i++) { - if (tbl[i].data =3D=3D &init_ipc_ns.mq_queues_max) - tbl[i].data =3D &ns->mq_queues_max; - - else if (tbl[i].data =3D=3D &init_ipc_ns.mq_msg_max) - tbl[i].data =3D &ns->mq_msg_max; - - else if (tbl[i].data =3D=3D &init_ipc_ns.mq_msgsize_max) - tbl[i].data =3D &ns->mq_msgsize_max; - - else if (tbl[i].data =3D=3D &init_ipc_ns.mq_msg_default) - tbl[i].data =3D &ns->mq_msg_default; - - else if (tbl[i].data =3D=3D &init_ipc_ns.mq_msgsize_default) - tbl[i].data =3D &ns->mq_msgsize_default; - else - tbl[i].data =3D NULL; - } - - ns->mq_sysctls =3D __register_sysctl_table(&ns->mq_set, "fs/mqueue", tbl= ); - } - if (!ns->mq_sysctls) { - kfree(tbl); - retire_sysctl_set(&ns->mq_set); - return false; - } - - return true; -} - -void retire_mq_sysctls(struct ipc_namespace *ns) -{ - struct ctl_table *tbl; - - tbl =3D ns->mq_sysctls->ctl_table_arg; - unregister_sysctl_table(ns->mq_sysctls); - retire_sysctl_set(&ns->mq_set); - kfree(tbl); -} diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 1b4a3be71636..f08e9f8db195 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -1711,11 +1711,6 @@ static int __init init_mqueue_fs(void) if (mqueue_inode_cachep =3D=3D NULL) return -ENOMEM; =20 - if (!setup_mq_sysctls(&init_ipc_ns)) { - pr_warn("sysctl registration failed\n"); - return -ENOMEM; - } - error =3D register_filesystem(&mqueue_fs_type); if (error) goto out_sysctl; diff --git a/ipc/namespace.c b/ipc/namespace.c index 754f3237194a..e18b6b5c2a46 100644 --- a/ipc/namespace.c +++ b/ipc/namespace.c @@ -60,9 +60,6 @@ static struct ipc_namespace *create_ipc_ns(struct user_na= mespace *user_ns, goto fail_put; =20 err =3D -ENOMEM; - if (!setup_mq_sysctls(ns)) - goto fail_put; - if (!setup_ipc_sysctls(ns)) goto fail_put; =20 @@ -132,7 +129,6 @@ static void free_ipc_ns(struct ipc_namespace *ns) msg_exit_ns(ns); shm_exit_ns(ns); =20 - retire_mq_sysctls(ns); retire_ipc_sysctls(ns); =20 dec_ipc_namespaces(ns->ucounts); diff --git a/ipc/util.h b/ipc/util.h index 2dd7ce0416d8..e88e486e9048 100644 --- a/ipc/util.h +++ b/ipc/util.h @@ -31,18 +31,16 @@ #define IPCMNI (1 << IPCMNI_SHIFT) #define IPCMNI_EXTEND (1 << IPCMNI_EXTEND_SHIFT) =20 -#ifdef CONFIG_SYSVIPC_SYSCTL extern int ipc_mni; extern int ipc_mni_shift; extern int ipc_min_cycle; =20 +#ifdef CONFIG_SYSVIPC_SYSCTL #define ipcmni_seq_shift() ipc_mni_shift #define IPCMNI_IDX_MASK ((1 << ipc_mni_shift) - 1) =20 #else /* CONFIG_SYSVIPC_SYSCTL */ =20 -#define ipc_mni IPCMNI -#define ipc_min_cycle ((int)RADIX_TREE_MAP_SIZE) #define ipcmni_seq_shift() IPCMNI_SHIFT #define IPCMNI_IDX_MASK ((1 << IPCMNI_SHIFT) - 1) #endif /* CONFIG_SYSVIPC_SYSCTL */ --=20 2.33.0 From nobody Wed Jul 1 10:35:43 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3A469C433EF for ; Fri, 21 Jan 2022 13:10:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1380573AbiAUNK1 convert rfc822-to-8bit (ORCPT ); Fri, 21 Jan 2022 08:10:27 -0500 Received: from us-smtp-delivery-44.mimecast.com ([205.139.111.44]:30977 "EHLO us-smtp-delivery-44.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1380557AbiAUNKY (ORCPT ); Fri, 21 Jan 2022 08:10:24 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-286-qgc-g0hKP0O-lYa8qA8vPA-1; Fri, 21 Jan 2022 08:10:20 -0500 X-MC-Unique: qgc-g0hKP0O-lYa8qA8vPA-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 8ED5C83DEE1; Fri, 21 Jan 2022 13:10:18 +0000 (UTC) Received: from comp-core-i7-2640m-0182e6.redhat.com (unknown [10.36.110.3]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1AC8178AA0; Fri, 21 Jan 2022 13:10:14 +0000 (UTC) From: Alexey Gladkov To: LKML , Linux Containers Cc: Alexander Mikhalitsyn , Andrew Morton , Christian Brauner , Daniel Walsh , Davidlohr Bueso , "Eric W . Biederman" , Kirill Tkhai , Manfred Spraul , Serge Hallyn , Varad Gautam , Vasily Averin Subject: [RFC PATCH v3 4/4] ipc: Allow to modify ipc/mq sysctls if CAP_SYS_RESOURCE is present Date: Fri, 21 Jan 2022 14:08:41 +0100 Message-Id: <9351533c4114f160d7b7d2db32d9636747bdede9.1642769810.git.legion@kernel.org> In-Reply-To: References: <87tuebwo99.fsf@email.froward.int.ebiederm.org> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=legion@kernel.org X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: kernel.org Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The mq_overview(7) says that mq sysctls are available for modification to a privileged process (CAP_SYS_RESOURCE). Right now, within userns, a privileged process cannot modify these files. Once the mq and ipc sysctls have been moved to the ipc namespace we can grant access to these files. mqueue sysctls -------------- The mq sysctls are protected by an upper limit that cannot be exceeded on the system: For /proc/sys/fs/mqueue/msg_max the upper limit is HARD_MSGMAX. For /proc/sys/fs/mqueue/msgsize_max the upper limit is HARD_MSGSIZEMAX. Also RLIMIT_MSGQUEUE limits all queues used by the process. This limit is also tied to userns. ipc sysctls ----------- The implementation has no specific limits for the per-process maximum number of shared memory segments. Only SHM_LOCK and SHM_HUGETLB limited by RLIMIT_MEMLOCK which is also tied to userns. This patch is RPC only and should not be applied without a security discussion. Signed-off-by: Alexey Gladkov --- ipc/ipc_sysctl.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index 9fc8e3e75be7..f1d1c83656f9 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c @@ -254,6 +254,21 @@ static struct ctl_table mq_sysctls[] =3D { {} }; =20 +static int set_permissions(struct ctl_table_header *head, struct ctl_table= *table) +{ + struct ipc_namespace *ns =3D container_of(head->set, struct ipc_namespace= , set); + int mode; + + /* Allow users with CAP_SYS_RESOURCE unrestrained access */ + if (ns_capable(ns->user_ns, CAP_SYS_RESOURCE)) + mode =3D (table->mode & S_IRWXU) >> 6; + else + /* Allow all others at most read-only access */ + mode =3D table->mode & S_IROTH; + + return (mode << 6) | (mode << 3) | mode; +} + static struct ctl_table_set *set_lookup(struct ctl_table_root *root) { return ¤t->nsproxy->ipc_ns->set; @@ -266,6 +281,7 @@ static int set_is_seen(struct ctl_table_set *set) =20 static struct ctl_table_root set_root =3D { .lookup =3D set_lookup, + .permissions =3D set_permissions, }; =20 static bool register_ipc_sysctl_table(struct ipc_namespace *ns) --=20 2.33.0