From: Nadia Derbey <Nadia.Derbey@bull.net>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Alexey Dobriyan <adobriyan@sw.ru>, linux-kernel@vger.kernel.org
Subject: Re: 2.6.23-rc6-mm1: IPC: sleeping function called ...
Date: Fri, 21 Sep 2007 11:18:53 +0200 [thread overview]
Message-ID: <46F38C7D.9050500@bull.net> (raw)
In-Reply-To: <20070918100115.b9da8ad5.akpm@linux-foundation.org>
[-- Attachment #1: Type: text/plain, Size: 438 bytes --]
Andrew Morton wrote:
> On Tue, 18 Sep 2007 16:55:19 +0200 Nadia Derbey <Nadia.Derbey@bull.net> wrote:
>
>
>>This patch fixes the missing rcu_read_(un)lock in the ipc code
>
>
> Thanks. Could you please check the code comments in ipc/util.c for
> accuracy and completeness sometime?
>
Done - see attachment.
Hope I didn't forget / add some wrong stuff ;-)
BTW this patch also fixes a missing lock in shm_get_stat().
Regards,
Nadia
[-- Attachment #2: ipc_fix_wrong_comments.patch --]
[-- Type: text/x-patch, Size: 14401 bytes --]
This patch fixes the wrong / obsolete comments in the ipc code.
Also adds a missing lock around ipc_get_maxid() in shm_get_stat().
Signed-off-by: Nadia Derbey <Nadia.Derbey@bull.net>
---
This patch applies on top of 2.6.23-rc6-mm1 + the previous IPC patches.
ipc/msg.c | 14 +++++++++-
ipc/sem.c | 14 ++++++++++
ipc/shm.c | 39 ++++++++++++++++++++----------
ipc/util.c | 78 +++++++++++++++++++++++++++++++++++++++----------------------
ipc/util.h | 18 ++++++++++++--
5 files changed, 118 insertions(+), 45 deletions(-)
Index: linux-2.6.23-rc6-mm1/ipc/util.c
===================================================================
--- linux-2.6.23-rc6-mm1.orig/ipc/util.c 2007-09-21 08:00:41.000000000 +0200
+++ linux-2.6.23-rc6-mm1/ipc/util.c 2007-09-21 10:32:03.000000000 +0200
@@ -194,7 +194,7 @@ void __init ipc_init_proc_interface(cons
* Requires ipc_ids.mutex locked.
* Returns the LOCKED pointer to the ipc structure if found or NULL
* if not.
- * If key is found ipc contains its ipc structure
+ * If key is found ipc points to the owning ipc structure
*/
static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
@@ -258,10 +258,10 @@ int ipc_get_maxid(struct ipc_ids *ids)
* @new: new IPC permission set
* @size: limit for the number of used ids
*
- * Add an entry 'new' to the IPC idr. The permissions object is
+ * Add an entry 'new' to the IPC ids idr. The permissions object is
* initialised and the first free entry is set up and the id assigned
- * is returned. The list is returned in a locked state on success.
- * On failure the list is not locked and -1 is returned.
+ * is returned. The 'new' entry is returned in a locked state on success.
+ * On failure the entry is not locked and -1 is returned.
*
* Called with ipc_ids.mutex held.
*/
@@ -270,10 +270,6 @@ int ipc_addid(struct ipc_ids* ids, struc
{
int id, err;
- /*
- * rcu_dereference()() is not needed here since
- * ipc_ids.mutex is held
- */
if (size > IPCMNI)
size = IPCMNI;
@@ -303,12 +299,12 @@ int ipc_addid(struct ipc_ids* ids, struc
/**
* ipcget_new - create a new ipc object
* @ns: namespace
- * @ids: identifer set
+ * @ids: IPC identifer set
* @ops: the actual creation routine to call
* @params: its parameters
*
- * This routine is called sys_msgget, sys_semget() and sys_shmget() when
- * the key is IPC_PRIVATE
+ * This routine is called by sys_msgget, sys_semget() and sys_shmget()
+ * when the key is IPC_PRIVATE.
*/
int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
struct ipc_ops *ops, struct ipc_params *params)
@@ -330,9 +326,16 @@ int ipcget_new(struct ipc_namespace *ns,
/**
* ipc_check_perms - check security and permissions for an IPC
* @ipcp: ipc permission set
- * @ids: identifer set
* @ops: the actual security routine to call
* @params: its parameters
+ *
+ * This routine is called by sys_msgget(), sys_semget() and sys_shmget()
+ * when the key is not IPC_PRIVATE and that key already exists in the
+ * ids IDR.
+ *
+ * On success, the IPC id is returned.
+ *
+ * It is called with ipc_ids.mutex and ipcp->lock held.
*/
static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops,
struct ipc_params *params)
@@ -353,12 +356,16 @@ static int ipc_check_perms(struct kern_i
/**
* ipcget_public - get an ipc object or create a new one
* @ns: namespace
- * @ids: identifer set
+ * @ids: IPC identifer set
* @ops: the actual creation routine to call
* @params: its parameters
*
- * This routine is called sys_msgget, sys_semget() and sys_shmget() when
- * the key is not IPC_PRIVATE
+ * This routine is called by sys_msgget, sys_semget() and sys_shmget()
+ * when the key is not IPC_PRIVATE.
+ * It adds a new entry if the key is not found and does some permission
+ * / security checkings if the key is found.
+ *
+ * On success, the ipc id is returned.
*/
int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
struct ipc_ops *ops, struct ipc_params *params)
@@ -389,6 +396,10 @@ int ipcget_public(struct ipc_namespace *
if (ops->more_checks)
err = ops->more_checks(ipcp, params);
if (!err)
+ /*
+ * ipc_check_perms returns the IPC id on
+ * success
+ */
err = ipc_check_perms(ipcp, ops, params);
}
ipc_unlock(ipcp);
@@ -401,12 +412,9 @@ int ipcget_public(struct ipc_namespace *
/**
* ipc_rmid - remove an IPC identifier
- * @ids: identifier set
- * @id: ipc perm structure containing the identifier to remove
+ * @ids: IPC identifier set
+ * @ipcp: ipc perm structure containing the identifier to remove
*
- * The identifier must be valid, and in use. The kernel will panic if
- * fed an invalid identifier. The entry is removed and internal
- * variables recomputed.
* ipc_ids.mutex and the spinlock for this ID are held before this
* function is called, and remain locked on the exit.
*/
@@ -558,10 +566,12 @@ static void ipc_do_vfree(struct work_str
*/
static void ipc_schedule_free(struct rcu_head *head)
{
- struct ipc_rcu_grace *grace =
- container_of(head, struct ipc_rcu_grace, rcu);
- struct ipc_rcu_sched *sched =
- container_of(&(grace->data[0]), struct ipc_rcu_sched, data[0]);
+ struct ipc_rcu_grace *grace;
+ struct ipc_rcu_sched *sched;
+
+ grace = container_of(head, struct ipc_rcu_grace, rcu);
+ sched = container_of(&(grace->data[0]), struct ipc_rcu_sched,
+ data[0]);
INIT_WORK(&sched->work, ipc_do_vfree);
schedule_work(&sched->work);
@@ -650,7 +660,7 @@ void kernel_to_ipc64_perm (struct kern_i
}
/**
- * ipc64_perm_to_ipc_perm - convert old ipc permissions to new
+ * ipc64_perm_to_ipc_perm - convert new ipc permissions to old
* @in: new style IPC permissions
* @out: old style IPC permissions
*
@@ -669,6 +679,18 @@ void ipc64_perm_to_ipc_perm (struct ipc6
out->seq = in->seq;
}
+/**
+ * ipc_lock - Lock an ipc structure
+ * @ids: IPC identifier set
+ * @id: ipc id to look for
+ *
+ * Look for an id in the ipc ids idr and lock the associated ipc object.
+ *
+ * ipc_ids.mutex is not necessarily held before this function is called,
+ * that's why we enter a RCU read section.
+ * The ipc object is locked on exit.
+ */
+
struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
{
struct kern_ipc_perm *out;
@@ -771,8 +793,8 @@ static void *sysvipc_proc_next(struct se
}
/*
- * File positions: pos 0 -> header, pos n -> ipc id + 1.
- * SeqFile iterator: iterator value locked shp or SEQ_TOKEN_START.
+ * File positions: pos 0 -> header, pos n -> ipc id = n - 1.
+ * SeqFile iterator: iterator value locked ipc pointer or SEQ_TOKEN_START.
*/
static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
{
@@ -807,7 +829,7 @@ static void sysvipc_proc_stop(struct seq
struct ipc_proc_iface *iface = iter->iface;
struct ipc_ids *ids;
- /* If we had a locked segment, release it */
+ /* If we had a locked structure, release it */
if (ipc && ipc != SEQ_START_TOKEN)
ipc_unlock(ipc);
Index: linux-2.6.23-rc6-mm1/ipc/util.h
===================================================================
--- linux-2.6.23-rc6-mm1.orig/ipc/util.h 2007-09-21 08:00:41.000000000 +0200
+++ linux-2.6.23-rc6-mm1/ipc/util.h 2007-09-21 10:30:27.000000000 +0200
@@ -54,7 +54,7 @@ struct ipc_params {
* the calls to sys_msgget(), sys_semget(), sys_shmget()
* . routine to call to create a new ipc object. Can be one of newque,
* newary, newseg
- * . routine to call to call to check permissions for a new ipc object.
+ * . routine to call to check permissions for a new ipc object.
* Can be one of security_msg_associate, security_sem_associate,
* security_shm_associate
* . routine to call for an extra check if needed
@@ -88,7 +88,8 @@ int ipc_get_maxid(struct ipc_ids *);
/* must be called with both locks acquired. */
void ipc_rmid(struct ipc_ids *, struct kern_ipc_perm *);
-int ipcperms (struct kern_ipc_perm *ipcp, short flg);
+/* must be called with ipcp locked */
+int ipcperms(struct kern_ipc_perm *ipcp, short flg);
/* for rare, potentially huge allocations.
* both function can sleep
@@ -131,6 +132,9 @@ static inline int ipc_buildid(struct ipc
return SEQ_MULTIPLIER * seq + id;
}
+/*
+ * Must be called with ipcp locked
+ */
static inline int ipc_checkid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp,
int uid)
{
@@ -168,6 +172,16 @@ static inline struct kern_ipc_perm *ipc_
return out;
}
+/**
+ * ipcget - Common sys_*get() code
+ * @ns : namsepace
+ * @ids : IPC identifier set
+ * @ops : operations to be called on ipc object creation, permission checks
+ * and further checks
+ * @params : the parameters needed by the previous operations.
+ *
+ * Common routine called by sys_msgget(), sys_semget() and sys_shmget().
+ */
static inline int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
struct ipc_ops *ops, struct ipc_params *params)
{
Index: linux-2.6.23-rc6-mm1/ipc/msg.c
===================================================================
--- linux-2.6.23-rc6-mm1.orig/ipc/msg.c 2007-09-21 08:00:41.000000000 +0200
+++ linux-2.6.23-rc6-mm1/ipc/msg.c 2007-09-21 10:33:08.000000000 +0200
@@ -156,6 +156,13 @@ static inline void msg_rmid(struct ipc_n
ipc_rmid(&msg_ids(ns), &s->q_perm);
}
+/**
+ * newque - Create a new msg queue
+ * @ns: namespace
+ * @params: ptr to the structure that contains the key and msgflg
+ *
+ * Called with msg_ids.mutex held
+ */
static int newque(struct ipc_namespace *ns, struct ipc_params *params)
{
struct msg_queue *msq;
@@ -250,8 +257,8 @@ static void expunge_all(struct msg_queue
/*
* freeque() wakes up waiters on the sender and receiver waiting queue,
- * removes the message queue from message queue ID
- * IDR, and cleans up all the messages associated with this queue.
+ * removes the message queue from message queue ID IDR, and cleans up all the
+ * messages associated with this queue.
*
* msg_ids.mutex and the spinlock for this message queue are held
* before freeque() is called. msg_ids.mutex remains locked on exit.
@@ -278,6 +285,9 @@ static void freeque(struct ipc_namespace
ipc_rcu_putref(msq);
}
+/*
+ * Called with msg_ids.mutex and ipcp locked.
+ */
static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg)
{
struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm);
Index: linux-2.6.23-rc6-mm1/ipc/sem.c
===================================================================
--- linux-2.6.23-rc6-mm1.orig/ipc/sem.c 2007-09-21 08:00:41.000000000 +0200
+++ linux-2.6.23-rc6-mm1/ipc/sem.c 2007-09-21 10:33:50.000000000 +0200
@@ -228,6 +228,14 @@ static inline void sem_rmid(struct ipc_n
*/
#define IN_WAKEUP 1
+/**
+ * newary - Create a new semaphore set
+ * @ns: namespace
+ * @params: ptr to the structure that contains key, semflg and nsems
+ *
+ * Called with sem_ids.mutex held
+ */
+
static int newary(struct ipc_namespace *ns, struct ipc_params *params)
{
int id;
@@ -281,6 +289,9 @@ static int newary(struct ipc_namespace *
}
+/*
+ * Called with sem_ids.mutex and ipcp locked.
+ */
static inline int sem_security(struct kern_ipc_perm *ipcp, int semflg)
{
struct sem_array *sma;
@@ -289,6 +300,9 @@ static inline int sem_security(struct ke
return security_sem_associate(sma, semflg);
}
+/*
+ * Called with sem_ids.mutex and ipcp locked.
+ */
static inline int sem_more_checks(struct kern_ipc_perm *ipcp,
struct ipc_params *params)
{
Index: linux-2.6.23-rc6-mm1/ipc/shm.c
===================================================================
--- linux-2.6.23-rc6-mm1.orig/ipc/shm.c 2007-09-21 08:00:41.000000000 +0200
+++ linux-2.6.23-rc6-mm1/ipc/shm.c 2007-09-21 10:34:25.000000000 +0200
@@ -82,6 +82,10 @@ static void __shm_init_ns(struct ipc_nam
ipc_init_ids(ids);
}
+/*
+ * Called with shm_ids.mutex and the shp structure locked.
+ * Only shm_ids.mutex remains locked on exit.
+ */
static void do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp)
{
if (shp->shm_nattch){
@@ -182,6 +186,7 @@ static void shm_open(struct vm_area_stru
/*
* shm_destroy - free the struct shmid_kernel
*
+ * @ns: namespace
* @shp: struct to free
*
* It has to be called with shp and shm_ids.mutex locked,
@@ -343,6 +348,14 @@ static struct vm_operations_struct shm_v
#endif
};
+/**
+ * newseg - Create a new shared memory segment
+ * @ns: namespace
+ * @params: ptr to the structure that contains key, size and shmflg
+ *
+ * Called with shm_ids.mutex held
+ */
+
static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
{
key_t key = params->key;
@@ -428,6 +441,9 @@ no_file:
return error;
}
+/*
+ * Called with shm_ids.mutex and ipcp locked.
+ */
static inline int shm_security(struct kern_ipc_perm *ipcp, int shmflg)
{
struct shmid_kernel *shp;
@@ -436,6 +452,9 @@ static inline int shm_security(struct ke
return security_shm_associate(shp, shmflg);
}
+/*
+ * Called with shm_ids.mutex and ipcp locked.
+ */
static inline int shm_more_checks(struct kern_ipc_perm *ipcp,
struct ipc_params *params)
{
@@ -558,6 +577,9 @@ static inline unsigned long copy_shminfo
}
}
+/*
+ * Called with shm_ids.mutex held
+ */
static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
unsigned long *swp)
{
@@ -573,18 +595,6 @@ static void shm_get_stat(struct ipc_name
struct shmid_kernel *shp;
struct inode *inode;
- /*
- * idr_find() is called via shm_get(), so with shm_ids.mutex
- * locked. Since ipc_addid() is also called with
- * shm_ids.mutex down, there is no need to add read barriers
- * here to gurantee the writes in ipc_addid() are seen in
- * order here (for Alpha).
- * However idr_find() itself does not necessary require
- * ipc_ids.mutex down. So if idr_find() is used by other
- * places without ipc_ids.mutex down, then it needs read
- * read memory barriers as ipc_lock() does.
- */
-
shp = idr_find(&shm_ids(ns).ipcs_idr, next_id);
if (shp == NULL)
continue;
@@ -638,8 +648,11 @@ asmlinkage long sys_shmctl (int shmid, i
shminfo.shmmin = SHMMIN;
if(copy_shminfo_to_user (buf, &shminfo, version))
return -EFAULT;
- /* reading a integer is always atomic */
+
+ mutex_lock(&shm_ids(ns).mutex);
err = ipc_get_maxid(&shm_ids(ns));
+ mutex_unlock(&shm_ids(ns).mutex);
+
if(err<0)
err = 0;
goto out;
next prev parent reply other threads:[~2007-09-21 9:13 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-18 9:17 2.6.23-rc6-mm1: IPC: sleeping function called Alexey Dobriyan
2007-09-18 9:42 ` Andrew Morton
2007-09-18 10:17 ` Andrew Morton
2007-09-18 10:30 ` Nadia Derbey
2007-09-18 10:34 ` Andrew Morton
[not found] ` <20070918142451.418b3b51@twins>
2007-09-18 16:13 ` Paul E. McKenney
2007-09-18 16:57 ` Andrew Morton
2007-09-18 18:29 ` Paul E. McKenney
2007-09-18 19:41 ` Peter Zijlstra
2007-09-18 20:26 ` [PATCH 1/2] lockdep: annotate rcu_read_lock() Peter Zijlstra
2007-09-18 20:27 ` [RFC][PATCH 2/2] lockdep: rcu_dereference() vs rcu_read_lock() Peter Zijlstra
2007-09-18 21:21 ` Paul E. McKenney
2007-09-18 10:27 ` 2.6.23-rc6-mm1: IPC: sleeping function called Andrew Morton
2007-09-18 10:32 ` Alexey Dobriyan
2007-09-18 14:55 ` Nadia Derbey
2007-09-18 17:01 ` Andrew Morton
2007-09-21 9:18 ` Nadia Derbey [this message]
2007-09-19 14:07 ` Jarek Poplawski
2007-09-20 6:24 ` Nadia Derbey
2007-09-20 7:28 ` Jarek Poplawski
2007-09-20 8:21 ` Jarek Poplawski
2007-09-20 8:52 ` Nadia Derbey
2007-09-20 13:08 ` Nadia Derbey
2007-09-20 13:26 ` Jarek Poplawski
2007-09-21 8:44 ` Jarek Poplawski
2007-09-21 10:11 ` Nadia Derbey
2007-09-21 11:03 ` Jarek Poplawski
2007-09-21 11:15 ` Jarek Poplawski
2007-09-24 6:54 ` Jarek Poplawski
2007-09-24 7:43 ` Jarek Poplawski
2007-09-24 8:18 ` Nadia Derbey
2007-09-24 9:50 ` Nadia Derbey
2007-09-25 11:47 ` Jarek Poplawski
2007-09-26 6:13 ` Jarek Poplawski
2007-09-20 13:19 ` Jarek Poplawski
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=46F38C7D.9050500@bull.net \
--to=nadia.derbey@bull.net \
--cc=adobriyan@sw.ru \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.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 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.