linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Waiman Long <longman@redhat.com>
To: "Luis R. Rodriguez" <mcgrof@kernel.org>,
	Kees Cook <keescook@chromium.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Jonathan Corbet <corbet@lwn.net>
Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	linux-doc@vger.kernel.org, Al Viro <viro@zeniv.linux.org.uk>,
	Matthew Wilcox <willy@infradead.org>,
	"Eric W. Biederman" <ebiederm@xmission.com>,
	Takashi Iwai <tiwai@suse.de>, Davidlohr Bueso <dbueso@suse.de>,
	Manfred Spraul <manfred@colorfullife.com>,
	Waiman Long <longman@redhat.com>
Subject: [PATCH v10 3/4] ipc: Make the new sequence number generation mode available to all
Date: Mon,  5 Nov 2018 10:43:45 -0500	[thread overview]
Message-ID: <1541432626-27780-4-git-send-email-longman@redhat.com> (raw)
In-Reply-To: <1541432626-27780-1-git-send-email-longman@redhat.com>

It happens that the new IPC id sequence number inrement mode can be
useful to reduce the chance of IPC id reuse even if the ipcmni_extend
boot command line parameter isn't specified. So a new ipcid_mode sysctl
parameter is added to control the sequence number generation mode -
legacy and delete modes.

In the legacy mode, the sequence number is incremented every time a new
ID is generated. In the delete mode, the number is incremented only if
one or more IDs have been previously deleted. The default is legacy for
non-ipcmni_extend and delete for ipcmni_extend. This new ipcid_mode
parameter is specific to each of the IPC namespaces.

Signed-off-by: Waiman Long <longman@redhat.com>
---
 Documentation/sysctl/kernel.txt | 17 +++++++++++++++++
 include/linux/ipc_namespace.h   | 12 ++++++++++++
 ipc/ipc_sysctl.c                | 10 ++++++++++
 ipc/msg.c                       |  3 ++-
 ipc/namespace.c                 |  2 ++
 ipc/sem.c                       |  3 ++-
 ipc/shm.c                       |  3 ++-
 ipc/util.c                      | 10 ++++++----
 ipc/util.h                      |  3 ++-
 9 files changed, 55 insertions(+), 8 deletions(-)

diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 37a6795..91bada1 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -41,6 +41,7 @@ show up in /proc/sys/kernel:
 - hung_task_check_interval_secs
 - hung_task_warnings
 - hyperv_record_panic_msg
+- ipcid_mode
 - kexec_load_disabled
 - kptr_restrict
 - l2cr                        [ PPC only ]
@@ -398,6 +399,22 @@ Controls whether the panic kmsg data should be reported to Hyper-V.
 
 ==============================================================
 
+ipcid_mode:
+
+Controls how the IPC ids returned by msgget(), semget() and shmget()
+are being generated.
+
+0: legacy mode
+1: delete mode
+
+There are two components in an IPC id - an integer identifier and a
+sequence number. In the legacy mode, the sequence number is incremented
+every time a new id is generated. In the delete mode, the sequence number
+is only incremented if one or more ids have been previously deleted. The
+delete mode reduces the chance that a given id will be reused again.
+
+==============================================================
+
 kexec_load_disabled:
 
 A toggle indicating if the kexec_load syscall has been disabled. This
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index 7d5f553..79d9d50 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -26,6 +26,15 @@ struct ipc_ids {
 	struct rhashtable key_ht;
 };
 
+/*
+ * IPC id generation mode for controlling how the IPC id returned by
+ * {msg,sem,shm}get() is being generated.
+ */
+enum ipc_id_mode {
+	ipc_id_legacy,	/* Sequence # incremented on every allocation */
+	ipc_id_delete,	/* Sequence # incremented only if an ID was deleted */
+};
+
 struct ipc_namespace {
 	refcount_t	count;
 	struct ipc_ids	ids[3];
@@ -39,6 +48,9 @@ struct ipc_namespace {
 	atomic_t	msg_bytes;
 	atomic_t	msg_hdrs;
 
+	/* IPC id generation mode */
+	unsigned int	ipcid_mode;
+
 	size_t		shm_ctlmax;
 	size_t		shm_ctlall;
 	unsigned long	shm_tot;
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index d9ac6ca..4c30e62 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -200,6 +200,15 @@ static int proc_ipc_sem_dointvec(struct ctl_table *table, int write,
 		.mode		= 0644,
 		.proc_handler	= proc_ipc_sem_dointvec,
 	},
+	{
+		.procname	= "ipcid_mode",
+		.data		= &init_ipc_ns.ipcid_mode,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_ipc_dointvec_minmax,
+		.extra1		= &zero,
+		.extra2		= &one,
+	},
 #ifdef CONFIG_CHECKPOINT_RESTORE
 	{
 		.procname	= "sem_next_id",
@@ -254,6 +263,7 @@ static int __init ipc_mni_extend(char *str)
 	ipc_mni = IPCMNI_EXTEND;
 	ipc_mni_shift = IPCMNI_EXTEND_SHIFT;
 	ipc_mni_extended = true;
+	init_ipc_ns.ipcid_mode = ipc_id_delete;
 	pr_info("IPCMNI extended to %d.\n", ipc_mni);
 	return 0;
 }
diff --git a/ipc/msg.c b/ipc/msg.c
index 0833c64..b401ba2 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -161,7 +161,8 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
 	INIT_LIST_HEAD(&msq->q_senders);
 
 	/* ipc_addid() locks msq upon success. */
-	retval = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni);
+	retval = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni,
+			   ns->ipcid_mode);
 	if (retval < 0) {
 		ipc_rcu_putref(&msq->q_perm, msg_rcu_free);
 		return retval;
diff --git a/ipc/namespace.c b/ipc/namespace.c
index 2160779..8b62cbd0 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -55,6 +55,8 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
 	ns->user_ns = get_user_ns(user_ns);
 	ns->ucounts = ucounts;
 
+	ns->ipcid_mode = ipc_mni_extended ? ipc_id_delete : ipc_id_legacy;
+
 	err = mq_init_ns(ns);
 	if (err)
 		goto fail_put;
diff --git a/ipc/sem.c b/ipc/sem.c
index 745dc61..51af634 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -553,7 +553,8 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
 	sma->sem_ctime = ktime_get_real_seconds();
 
 	/* ipc_addid() locks sma upon success. */
-	retval = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
+	retval = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni,
+			   ns->ipcid_mode);
 	if (retval < 0) {
 		ipc_rcu_putref(&sma->sem_perm, sem_rcu_free);
 		return retval;
diff --git a/ipc/shm.c b/ipc/shm.c
index 0842411..182ae4c 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -676,7 +676,8 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
 	shp->shm_creator = current;
 
 	/* ipc_addid() locks shp upon success. */
-	error = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
+	error = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni,
+			  ns->ipcid_mode);
 	if (error < 0)
 		goto no_id;
 
diff --git a/ipc/util.c b/ipc/util.c
index 6ae0007..04c8e31 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -195,7 +195,8 @@ static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
  * The caller must own kern_ipc_perm.lock.of the new object.
  * On error, the function returns a (negative) error code.
  */
-static inline int ipc_idr_alloc(struct ipc_ids *ids, struct kern_ipc_perm *new)
+static inline int ipc_idr_alloc(struct ipc_ids *ids, struct kern_ipc_perm *new,
+				int idmode)
 {
 	int idx, next_id = -1;
 
@@ -222,7 +223,7 @@ static inline int ipc_idr_alloc(struct ipc_ids *ids, struct kern_ipc_perm *new)
 	 */
 
 	if (next_id < 0) { /* !CHECKPOINT_RESTORE or next_id is unset */
-		if (!ipc_mni_extended || ids->deleted) {
+		if (idmode == ipc_id_legacy || ids->deleted) {
 			ids->seq++;
 			if (ids->seq > IPCID_SEQ_MAX)
 				ids->seq = 0;
@@ -255,7 +256,8 @@ static inline int ipc_idr_alloc(struct ipc_ids *ids, struct kern_ipc_perm *new)
  *
  * Called with writer ipc_ids.rwsem held.
  */
-int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int limit)
+int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int limit,
+	      int idmode)
 {
 	kuid_t euid;
 	kgid_t egid;
@@ -282,7 +284,7 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int limit)
 
 	new->deleted = false;
 
-	idx = ipc_idr_alloc(ids, new);
+	idx = ipc_idr_alloc(ids, new, idmode);
 	idr_preload_end();
 
 	if (idx >= 0 && new->key != IPC_PRIVATE) {
diff --git a/ipc/util.h b/ipc/util.h
index 1f19729..c8f2d0ed 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -129,7 +129,8 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
 #define IPCID_SEQ_MAX	  (INT_MAX >> IPCMNI_SEQ_SHIFT)
 
 /* must be called with ids->rwsem acquired for writing */
-int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
+int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int limit,
+	      int idmode);
 
 /* must be called with both locks acquired. */
 void ipc_rmid(struct ipc_ids *, struct kern_ipc_perm *);
-- 
1.8.3.1

  parent reply	other threads:[~2018-11-06  1:06 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-05 15:43 [PATCH v10 0/4] ipc: Increase IPCMNI limit & IPC id generation modes Waiman Long
2018-11-05 15:43 ` [PATCH v10 1/4] ipc: Allow boot time extension of IPCMNI from 32k to 8M Waiman Long
2018-11-06 13:20   ` Matthew Wilcox
2018-11-08 21:29     ` Waiman Long
2018-11-05 15:43 ` [PATCH v10 2/4] ipc: Conserve sequence numbers in extended IPCMNI mode Waiman Long
2018-11-05 15:43 ` Waiman Long [this message]
2018-11-06  4:53   ` [PATCH v10 3/4] ipc: Make the new sequence number generation mode available to all kbuild test robot
2018-11-05 15:43 ` [PATCH v10 4/4] ipc: Add a cyclic mode for id generation Waiman Long
2018-11-06 13:02   ` Matthew Wilcox
2018-11-08 21:38     ` Waiman Long

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=1541432626-27780-4-git-send-email-longman@redhat.com \
    --to=longman@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=corbet@lwn.net \
    --cc=dbueso@suse.de \
    --cc=ebiederm@xmission.com \
    --cc=keescook@chromium.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=manfred@colorfullife.com \
    --cc=mcgrof@kernel.org \
    --cc=tiwai@suse.de \
    --cc=viro@zeniv.linux.org.uk \
    --cc=willy@infradead.org \
    /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;
as well as URLs for NNTP newsgroup(s).