mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Alejandro Colomar <alx@kernel.org>
To: Yingjie Wang <x-professor@outlook.com>
Cc: "akpm@linux-foundation.org" <akpm@linux-foundation.org>,
	"Manfred Spraul" <manfred@colorfullife.com>,
	"Alexey Gladkov" <legion@kernel.org>,
	"Eric W . Biederman" <ebiederm@xmission.com>,
	"Vasily Averin" <vasily.averin@linux.dev>,
	"Johannes Weiner" <hannes@cmpxchg.org>,
	"Shakeel Butt" <shakeel.butt@linux.dev>,
	"Michal Koutný" <mkoutny@suse.com>,
	"Michal Hocko" <mhocko@suse.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>,
	"cgroups@vger.kernel.org" <cgroups@vger.kernel.org>,
	"linux-api@vger.kernel.org" <linux-api@vger.kernel.org>,
	"linux-man@vger.kernel.org" <linux-man@vger.kernel.org>,
	"stable@vger.kernel.org" <stable@vger.kernel.org>,
	linux-hardening@vger.kernel.org
Subject: Re: [PATCH v3 2/3] ipc/sem: reject negative SEMOPM values
Date: Sat, 24 Oct 2026 15:23:11 +0200	[thread overview]
Message-ID: <atyvbQ5xxtxcxBZE@debian> (raw)
In-Reply-To: <c2c9cb6d741fd9290c835679f9c209b147f74f64.1792808260.git.x-professor@outlook.com>

[-- Attachment #1: Type: text/plain, Size: 6187 bytes --]

Hi Yingjie,

> Date: 2026-10-24 12:21:42+0000
> From: Yingjie Wang <x-professor@outlook.com>
>
> The SEMOPM field has been stored as an int while semop() receives an
> unsigned operation count since the beginning of Git history. A negative
> SEMOPM accepted by proc_dointvec() is converted to a large unsigned value
> in the comparison, defeating the intended operation-count limit.
> 
> Commit 50ec499b9a43 ("sysctl: allow change system v ipc sysctls inside ipc
> namespace") made kernel.sem writable by IPC namespace owners without
> capabilities in the initial user namespace.
> 
> Parse writes against a temporary copy and validate SEMOPM and SEMMNI
> before changing the live settings. Hold a per-namespace mutex from the
> snapshot through publication so concurrent sysctl writers cannot publish
> stale values for fields they did not supply. Access the live fields with
> READ_ONCE() and WRITE_ONCE(), preserving the per-field access semantics of
> proc_dointvec(). Read requests continue to use proc_dointvec() directly.
> 
> Failed writes leave the live settings unchanged. Successful partial writes
> change only the supplied fields relative to the latest locked snapshot.
> The writer mutex retains the existing per-field visibility for readers.
> 
> Keep zero and positive SEMOPM values valid. Zero continues to reject every
> non-empty semop() request.
> 
> Suggested-by: Andrew Morton <akpm@linux-foundation.org>
> Link: https://lore.kernel.org/r/20261016155905.2a659b7bb7d61f33467a3263@linux-foundation.org
> Link: https://lore.kernel.org/r/51c93c19-f1dd-455f-8698-6b1ee30eb630@colorfullife.com
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Cc: stable@vger.kernel.org
> Signed-off-by: Yingjie Wang <x-professor@outlook.com>
> Reviewed-by: Manfred Spraul <manfred@colorfullife.com>
> ---
>  include/linux/ipc_namespace.h |  3 +++
>  ipc/ipc_sysctl.c              | 35 ++++++++++++++++++++++++++---------
>  ipc/sem.c                     |  1 +
>  ipc/util.h                    |  9 ---------
>  4 files changed, 30 insertions(+), 18 deletions(-)
> 
> diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
> index 12faca29bbb9c..c06568ccfca88 100644
> --- a/include/linux/ipc_namespace.h
> +++ b/include/linux/ipc_namespace.h
> @@ -4,6 +4,7 @@
>  
>  #include <linux/err.h>
>  #include <linux/idr.h>
> +#include <linux/mutex.h>
>  #include <linux/rwsem.h>
>  #include <linux/notifier.h>
>  #include <linux/nsproxy.h>
> @@ -31,6 +32,8 @@ struct ipc_ids {
>  struct ipc_namespace {
>  	struct ipc_ids	ids[3];
>  
> +	/* Serialize kernel.sem writers. */
> +	struct mutex	sem_ctls_mutex;
>  	int		sem_ctls[4];
>  	int		used_sems;
>  
> diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
> index d038d944257f6..a05e28e67c305 100644
> --- a/ipc/ipc_sysctl.c
> +++ b/ipc/ipc_sysctl.c
> @@ -51,21 +51,38 @@ static int proc_ipc_auto_msgmni(const struct ctl_table *table, int write,
>  static int proc_ipc_sem_dointvec(const struct ctl_table *table, int write,
>  	void *buffer, size_t *lenp, loff_t *ppos)
>  {
> +	struct ctl_table ipc_table;
>  	struct ipc_namespace *ns =
>  		container_of(table->data, struct ipc_namespace, sem_ctls);
> -	int ret, semmni;
> +	int sem_ctls[ARRAY_SIZE(ns->sem_ctls)];
> +	size_t i;
> +	int ret;
> +
> +	if (!write)
> +		return proc_dointvec(table, write, buffer, lenp, ppos);
>  
> -	semmni = ns->sem_ctls[3];
> -	ret = proc_dointvec(table, write, buffer, lenp, ppos);
> +	mutex_lock(&ns->sem_ctls_mutex);
> +	for (i = 0; i < ARRAY_SIZE(sem_ctls); i++)
> +		sem_ctls[i] = READ_ONCE(ns->sem_ctls[i]);
>  
> -	if (!ret)
> -		ret = sem_check_semmni(ns);
> +	memcpy(&ipc_table, table, sizeof(ipc_table));

Why memcpy(3)?  Being a structure, we could use simple assignment, which
is type safe.

	ipc_table = *table;

memcpy(3) is way too powerful for this, and that can be dangerous.
A few ways where it is easy to screw a call to memcpy(3) are:

-  Size of destination doesn't match size of input.
-  Size argument doesn't match size of destination.
-  Type of input doesn't match type of destination.
-  You may forget to copy a flexible array member.

In some cases, you really want to defeat those, and then memcpy(3) is
useful (or you're copying an array, and then you have no choice), but if
not, memccpy(3) is not the best tool.

[CC += linux-hardening]


Have a lovely day!
Alex

> +	ipc_table.data = sem_ctls;
>  
> -	/*
> -	 * Reset the semmni value if an error happens.
> -	 */
> +	ret = proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
>  	if (ret)
> -		ns->sem_ctls[3] = semmni;
> +		goto out_unlock;
> +
> +	if (sem_ctls[2] < 0 ||
> +	    sem_ctls[3] < 0 || sem_ctls[3] > ipc_mni) {
> +		ret = -ERANGE;
> +		goto out_unlock;
> +	}
> +
> +	for (i = 0; i < ARRAY_SIZE(sem_ctls); i++)
> +		WRITE_ONCE(ns->sem_ctls[i], sem_ctls[i]);
> +
> +out_unlock:
> +	mutex_unlock(&ns->sem_ctls_mutex);
>  	return ret;
>  }
>  
> diff --git a/ipc/sem.c b/ipc/sem.c
> index a8c9807175520..0f7d32c12993f 100644
> --- a/ipc/sem.c
> +++ b/ipc/sem.c
> @@ -249,6 +249,7 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it);
>  
>  void sem_init_ns(struct ipc_namespace *ns)
>  {
> +	mutex_init(&ns->sem_ctls_mutex);
>  	ns->sc_semmsl = SEMMSL;
>  	ns->sc_semmns = SEMMNS;
>  	ns->sc_semopm = SEMOPM;
> diff --git a/ipc/util.h b/ipc/util.h
> index a55d6cebe6d3b..51b4efa3d6db0 100644
> --- a/ipc/util.h
> +++ b/ipc/util.h
> @@ -245,15 +245,6 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
>  void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
>  		void (*free)(struct ipc_namespace *, struct kern_ipc_perm *));
>  
> -static inline int sem_check_semmni(struct ipc_namespace *ns) {
> -	/*
> -	 * Check semmni range [0, ipc_mni]
> -	 * semmni is the last element of sem_ctls[4] array
> -	 */
> -	return ((ns->sem_ctls[3] < 0) || (ns->sem_ctls[3] > ipc_mni))
> -		? -ERANGE : 0;
> -}
> -
>  #ifdef CONFIG_COMPAT
>  #include <linux/compat.h>
>  struct compat_ipc_perm {
> -- 
> 2.43.0
> 

-- 
<https://www.alejandro-colomar.es>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2026-10-24 13:23 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-24 12:21 [PATCH v3 0/3] ipc/sem: account enlarged sops arrays and validate SEMOPM Yingjie Wang
2026-10-24 12:21 ` [PATCH v3 1/3] ipc/sem: account enlarged sops arrays to memcg Yingjie Wang
2026-10-24 12:21 ` [PATCH v3 2/3] ipc/sem: reject negative SEMOPM values Yingjie Wang
2026-10-24 13:23   ` Alejandro Colomar [this message]
2026-10-24 12:21 ` [PATCH v3 3/3] ipc/sem: remove obsolete SEMOPM fragmentation warning Yingjie Wang

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=atyvbQ5xxtxcxBZE@debian \
    --to=alx@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=cgroups@vger.kernel.org \
    --cc=ebiederm@xmission.com \
    --cc=hannes@cmpxchg.org \
    --cc=legion@kernel.org \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-man@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=manfred@colorfullife.com \
    --cc=mhocko@suse.com \
    --cc=mkoutny@suse.com \
    --cc=shakeel.butt@linux.dev \
    --cc=stable@vger.kernel.org \
    --cc=vasily.averin@linux.dev \
    --cc=x-professor@outlook.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: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®