]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.11-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 16 Oct 2013 00:01:32 +0000 (17:01 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 16 Oct 2013 00:01:32 +0000 (17:01 -0700)
added patches:
ipc-document-general-ipc-locking-scheme.patch
ipc-drop-ipc_lock_by_ptr.patch
ipc-drop-ipc_lock_check.patch
ipc-msg-drop-msg_unlock.patch
ipc-rename-ids-rw_mutex.patch
ipc-shm-drop-shm_lock_check.patch
ipc-shm-guard-against-non-existant-vma-in-shmdt-2.patch

queue-3.11/ipc-document-general-ipc-locking-scheme.patch [new file with mode: 0644]
queue-3.11/ipc-drop-ipc_lock_by_ptr.patch [new file with mode: 0644]
queue-3.11/ipc-drop-ipc_lock_check.patch [new file with mode: 0644]
queue-3.11/ipc-msg-drop-msg_unlock.patch [new file with mode: 0644]
queue-3.11/ipc-rename-ids-rw_mutex.patch [new file with mode: 0644]
queue-3.11/ipc-shm-drop-shm_lock_check.patch [new file with mode: 0644]
queue-3.11/ipc-shm-guard-against-non-existant-vma-in-shmdt-2.patch [new file with mode: 0644]
queue-3.11/series

diff --git a/queue-3.11/ipc-document-general-ipc-locking-scheme.patch b/queue-3.11/ipc-document-general-ipc-locking-scheme.patch
new file mode 100644 (file)
index 0000000..50a9a45
--- /dev/null
@@ -0,0 +1,46 @@
+From 05603c44a7627793219b0bd9a7b236099dc9cd9d Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:26 -0700
+Subject: ipc: document general ipc locking scheme
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit 05603c44a7627793219b0bd9a7b236099dc9cd9d upstream.
+
+As suggested by Andrew, add a generic initial locking scheme used
+throughout all sysv ipc mechanisms.  Documenting the ids rwsem, how rcu
+can be enough to do the initial checks and when to actually acquire the
+kern_ipc_perm.lock spinlock.
+
+I found that adding it to util.c was generic enough.
+
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/util.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/ipc/util.c
++++ b/ipc/util.c
+@@ -15,6 +15,14 @@
+  * Jun 2006 - namespaces ssupport
+  *            OpenVZ, SWsoft Inc.
+  *            Pavel Emelianov <xemul@openvz.org>
++ *
++ * General sysv ipc locking scheme:
++ *  when doing ipc id lookups, take the ids->rwsem
++ *      rcu_read_lock()
++ *          obtain the ipc object (kern_ipc_perm)
++ *          perform security, capabilities, auditing and permission checks, etc.
++ *          acquire the ipc lock (kern_ipc_perm.lock) throught ipc_lock_object()
++ *             perform data updates (ie: SET, RMID, LOCK/UNLOCK commands)
+  */
+ #include <linux/mm.h>
diff --git a/queue-3.11/ipc-drop-ipc_lock_by_ptr.patch b/queue-3.11/ipc-drop-ipc_lock_by_ptr.patch
new file mode 100644 (file)
index 0000000..6cdd9e3
--- /dev/null
@@ -0,0 +1,77 @@
+From 32a2750010981216fb788c5190fb0e646abfab30 Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:29 -0700
+Subject: ipc: drop ipc_lock_by_ptr
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit 32a2750010981216fb788c5190fb0e646abfab30 upstream.
+
+After previous cleanups and optimizations, this function is no longer
+heavily used and we don't have a good reason to keep it.  Update the few
+remaining callers and get rid of it.
+
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Cc: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/namespace.c |    3 ++-
+ ipc/util.c      |    6 ++++--
+ ipc/util.h      |    6 ------
+ 3 files changed, 6 insertions(+), 9 deletions(-)
+
+--- a/ipc/namespace.c
++++ b/ipc/namespace.c
+@@ -89,7 +89,8 @@ void free_ipcs(struct ipc_namespace *ns,
+               perm = idr_find(&ids->ipcs_idr, next_id);
+               if (perm == NULL)
+                       continue;
+-              ipc_lock_by_ptr(perm);
++              rcu_read_lock();
++              ipc_lock_object(perm);
+               free(ns, perm);
+               total++;
+       }
+--- a/ipc/util.c
++++ b/ipc/util.c
+@@ -205,7 +205,8 @@ static struct kern_ipc_perm *ipc_findkey
+                       continue;
+               }
+-              ipc_lock_by_ptr(ipc);
++              rcu_read_lock();
++              ipc_lock_object(ipc);
+               return ipc;
+       }
+@@ -830,7 +831,8 @@ static struct kern_ipc_perm *sysvipc_fin
+               ipc = idr_find(&ids->ipcs_idr, pos);
+               if (ipc != NULL) {
+                       *new_pos = pos + 1;
+-                      ipc_lock_by_ptr(ipc);
++                      rcu_read_lock();
++                      ipc_lock_object(ipc);
+                       return ipc;
+               }
+       }
+--- a/ipc/util.h
++++ b/ipc/util.h
+@@ -179,12 +179,6 @@ static inline void ipc_assert_locked_obj
+       assert_spin_locked(&perm->lock);
+ }
+-static inline void ipc_lock_by_ptr(struct kern_ipc_perm *perm)
+-{
+-      rcu_read_lock();
+-      ipc_lock_object(perm);
+-}
+-
+ static inline void ipc_unlock(struct kern_ipc_perm *perm)
+ {
+       ipc_unlock_object(perm);
diff --git a/queue-3.11/ipc-drop-ipc_lock_check.patch b/queue-3.11/ipc-drop-ipc_lock_check.patch
new file mode 100644 (file)
index 0000000..27ac1bb
--- /dev/null
@@ -0,0 +1,60 @@
+From 20b8875abcf2daa1dda5cf70bd6369df5e85d4c1 Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:31 -0700
+Subject: ipc: drop ipc_lock_check
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit 20b8875abcf2daa1dda5cf70bd6369df5e85d4c1 upstream.
+
+No remaining users, we now use ipc_obtain_object_check().
+
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Cc: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/util.c |   16 ----------------
+ ipc/util.h |    1 -
+ 2 files changed, 17 deletions(-)
+
+--- a/ipc/util.c
++++ b/ipc/util.c
+@@ -678,22 +678,6 @@ out:
+       return out;
+ }
+-struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id)
+-{
+-      struct kern_ipc_perm *out;
+-
+-      out = ipc_lock(ids, id);
+-      if (IS_ERR(out))
+-              return out;
+-
+-      if (ipc_checkid(out, id)) {
+-              ipc_unlock(out);
+-              return ERR_PTR(-EIDRM);
+-      }
+-
+-      return out;
+-}
+-
+ /**
+  * ipcget - Common sys_*get() code
+  * @ns : namsepace
+--- a/ipc/util.h
++++ b/ipc/util.h
+@@ -185,7 +185,6 @@ static inline void ipc_unlock(struct ker
+       rcu_read_unlock();
+ }
+-struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id);
+ struct kern_ipc_perm *ipc_obtain_object_check(struct ipc_ids *ids, int id);
+ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
+                       struct ipc_ops *ops, struct ipc_params *params);
diff --git a/queue-3.11/ipc-msg-drop-msg_unlock.patch b/queue-3.11/ipc-msg-drop-msg_unlock.patch
new file mode 100644 (file)
index 0000000..f144ef6
--- /dev/null
@@ -0,0 +1,46 @@
+From 4718787d1f626f45ddb239912bc07266b9880044 Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:25 -0700
+Subject: ipc,msg: drop msg_unlock
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit 4718787d1f626f45ddb239912bc07266b9880044 upstream.
+
+There is only one user left, drop this function and just call
+ipc_unlock_object() and rcu_read_unlock().
+
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/msg.c |    5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/ipc/msg.c
++++ b/ipc/msg.c
+@@ -70,8 +70,6 @@ struct msg_sender {
+ #define msg_ids(ns)   ((ns)->ids[IPC_MSG_IDS])
+-#define msg_unlock(msq)               ipc_unlock(&(msq)->q_perm)
+-
+ static void freeque(struct ipc_namespace *, struct kern_ipc_perm *);
+ static int newque(struct ipc_namespace *, struct ipc_params *);
+ #ifdef CONFIG_PROC_FS
+@@ -278,7 +276,8 @@ static void freeque(struct ipc_namespace
+       expunge_all(msq, -EIDRM);
+       ss_wakeup(&msq->q_senders, 1);
+       msg_rmid(ns, msq);
+-      msg_unlock(msq);
++      ipc_unlock_object(&msq->q_perm);
++      rcu_read_unlock();
+       list_for_each_entry_safe(msg, t, &msq->q_messages, m_list) {
+               atomic_dec(&ns->msg_hdrs);
diff --git a/queue-3.11/ipc-rename-ids-rw_mutex.patch b/queue-3.11/ipc-rename-ids-rw_mutex.patch
new file mode 100644 (file)
index 0000000..8d3602e
--- /dev/null
@@ -0,0 +1,594 @@
+From d9a605e40b1376eb02b067d7690580255a0df68f Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:24 -0700
+Subject: ipc: rename ids->rw_mutex
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit d9a605e40b1376eb02b067d7690580255a0df68f upstream.
+
+Since in some situations the lock can be shared for readers, we shouldn't
+be calling it a mutex, rename it to rwsem.
+
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/ipc_namespace.h |    2 -
+ ipc/msg.c                     |   20 +++++++--------
+ ipc/namespace.c               |    4 +--
+ ipc/sem.c                     |   24 +++++++++---------
+ ipc/shm.c                     |   56 +++++++++++++++++++++---------------------
+ ipc/util.c                    |   28 ++++++++++-----------
+ ipc/util.h                    |    4 +--
+ 7 files changed, 69 insertions(+), 69 deletions(-)
+
+--- a/include/linux/ipc_namespace.h
++++ b/include/linux/ipc_namespace.h
+@@ -22,7 +22,7 @@ struct ipc_ids {
+       int in_use;
+       unsigned short seq;
+       unsigned short seq_max;
+-      struct rw_semaphore rw_mutex;
++      struct rw_semaphore rwsem;
+       struct idr ipcs_idr;
+       int next_id;
+ };
+--- a/ipc/msg.c
++++ b/ipc/msg.c
+@@ -181,7 +181,7 @@ static void msg_rcu_free(struct rcu_head
+  * @ns: namespace
+  * @params: ptr to the structure that contains the key and msgflg
+  *
+- * Called with msg_ids.rw_mutex held (writer)
++ * Called with msg_ids.rwsem held (writer)
+  */
+ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
+ {
+@@ -267,8 +267,8 @@ static void expunge_all(struct msg_queue
+  * removes the message queue from message queue ID IDR, and cleans up all the
+  * messages associated with this queue.
+  *
+- * msg_ids.rw_mutex (writer) and the spinlock for this message queue are held
+- * before freeque() is called. msg_ids.rw_mutex remains locked on exit.
++ * msg_ids.rwsem (writer) and the spinlock for this message queue are held
++ * before freeque() is called. msg_ids.rwsem remains locked on exit.
+  */
+ static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
+ {
+@@ -289,7 +289,7 @@ static void freeque(struct ipc_namespace
+ }
+ /*
+- * Called with msg_ids.rw_mutex and ipcp locked.
++ * Called with msg_ids.rwsem and ipcp locked.
+  */
+ static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg)
+ {
+@@ -393,9 +393,9 @@ copy_msqid_from_user(struct msqid64_ds *
+ }
+ /*
+- * This function handles some msgctl commands which require the rw_mutex
++ * This function handles some msgctl commands which require the rwsem
+  * to be held in write mode.
+- * NOTE: no locks must be held, the rw_mutex is taken inside this function.
++ * NOTE: no locks must be held, the rwsem is taken inside this function.
+  */
+ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
+                      struct msqid_ds __user *buf, int version)
+@@ -410,7 +410,7 @@ static int msgctl_down(struct ipc_namesp
+                       return -EFAULT;
+       }
+-      down_write(&msg_ids(ns).rw_mutex);
++      down_write(&msg_ids(ns).rwsem);
+       rcu_read_lock();
+       ipcp = ipcctl_pre_down_nolock(ns, &msg_ids(ns), msqid, cmd,
+@@ -466,7 +466,7 @@ out_unlock0:
+ out_unlock1:
+       rcu_read_unlock();
+ out_up:
+-      up_write(&msg_ids(ns).rw_mutex);
++      up_write(&msg_ids(ns).rwsem);
+       return err;
+ }
+@@ -501,7 +501,7 @@ static int msgctl_nolock(struct ipc_name
+               msginfo.msgmnb = ns->msg_ctlmnb;
+               msginfo.msgssz = MSGSSZ;
+               msginfo.msgseg = MSGSEG;
+-              down_read(&msg_ids(ns).rw_mutex);
++              down_read(&msg_ids(ns).rwsem);
+               if (cmd == MSG_INFO) {
+                       msginfo.msgpool = msg_ids(ns).in_use;
+                       msginfo.msgmap = atomic_read(&ns->msg_hdrs);
+@@ -512,7 +512,7 @@ static int msgctl_nolock(struct ipc_name
+                       msginfo.msgtql = MSGTQL;
+               }
+               max_id = ipc_get_maxid(&msg_ids(ns));
+-              up_read(&msg_ids(ns).rw_mutex);
++              up_read(&msg_ids(ns).rwsem);
+               if (copy_to_user(buf, &msginfo, sizeof(struct msginfo)))
+                       return -EFAULT;
+               return (max_id < 0) ? 0 : max_id;
+--- a/ipc/namespace.c
++++ b/ipc/namespace.c
+@@ -81,7 +81,7 @@ void free_ipcs(struct ipc_namespace *ns,
+       int next_id;
+       int total, in_use;
+-      down_write(&ids->rw_mutex);
++      down_write(&ids->rwsem);
+       in_use = ids->in_use;
+@@ -93,7 +93,7 @@ void free_ipcs(struct ipc_namespace *ns,
+               free(ns, perm);
+               total++;
+       }
+-      up_write(&ids->rw_mutex);
++      up_write(&ids->rwsem);
+ }
+ static void free_ipc_ns(struct ipc_namespace *ns)
+--- a/ipc/sem.c
++++ b/ipc/sem.c
+@@ -365,7 +365,7 @@ static inline void sem_unlock(struct sem
+ }
+ /*
+- * sem_lock_(check_) routines are called in the paths where the rw_mutex
++ * sem_lock_(check_) routines are called in the paths where the rwsem
+  * is not held.
+  *
+  * The caller holds the RCU read lock.
+@@ -464,7 +464,7 @@ static inline void sem_rmid(struct ipc_n
+  * @ns: namespace
+  * @params: ptr to the structure that contains key, semflg and nsems
+  *
+- * Called with sem_ids.rw_mutex held (as a writer)
++ * Called with sem_ids.rwsem held (as a writer)
+  */
+ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
+@@ -529,7 +529,7 @@ static int newary(struct ipc_namespace *
+ /*
+- * Called with sem_ids.rw_mutex and ipcp locked.
++ * Called with sem_ids.rwsem and ipcp locked.
+  */
+ static inline int sem_security(struct kern_ipc_perm *ipcp, int semflg)
+ {
+@@ -540,7 +540,7 @@ static inline int sem_security(struct ke
+ }
+ /*
+- * Called with sem_ids.rw_mutex and ipcp locked.
++ * Called with sem_ids.rwsem and ipcp locked.
+  */
+ static inline int sem_more_checks(struct kern_ipc_perm *ipcp,
+                               struct ipc_params *params)
+@@ -1031,8 +1031,8 @@ static int count_semzcnt (struct sem_arr
+       return semzcnt;
+ }
+-/* Free a semaphore set. freeary() is called with sem_ids.rw_mutex locked
+- * as a writer and the spinlock for this semaphore set hold. sem_ids.rw_mutex
++/* Free a semaphore set. freeary() is called with sem_ids.rwsem locked
++ * as a writer and the spinlock for this semaphore set hold. sem_ids.rwsem
+  * remains locked on exit.
+  */
+ static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
+@@ -1152,7 +1152,7 @@ static int semctl_nolock(struct ipc_name
+               seminfo.semmnu = SEMMNU;
+               seminfo.semmap = SEMMAP;
+               seminfo.semume = SEMUME;
+-              down_read(&sem_ids(ns).rw_mutex);
++              down_read(&sem_ids(ns).rwsem);
+               if (cmd == SEM_INFO) {
+                       seminfo.semusz = sem_ids(ns).in_use;
+                       seminfo.semaem = ns->used_sems;
+@@ -1161,7 +1161,7 @@ static int semctl_nolock(struct ipc_name
+                       seminfo.semaem = SEMAEM;
+               }
+               max_id = ipc_get_maxid(&sem_ids(ns));
+-              up_read(&sem_ids(ns).rw_mutex);
++              up_read(&sem_ids(ns).rwsem);
+               if (copy_to_user(p, &seminfo, sizeof(struct seminfo))) 
+                       return -EFAULT;
+               return (max_id < 0) ? 0: max_id;
+@@ -1467,9 +1467,9 @@ copy_semid_from_user(struct semid64_ds *
+ }
+ /*
+- * This function handles some semctl commands which require the rw_mutex
++ * This function handles some semctl commands which require the rwsem
+  * to be held in write mode.
+- * NOTE: no locks must be held, the rw_mutex is taken inside this function.
++ * NOTE: no locks must be held, the rwsem is taken inside this function.
+  */
+ static int semctl_down(struct ipc_namespace *ns, int semid,
+                      int cmd, int version, void __user *p)
+@@ -1484,7 +1484,7 @@ static int semctl_down(struct ipc_namesp
+                       return -EFAULT;
+       }
+-      down_write(&sem_ids(ns).rw_mutex);
++      down_write(&sem_ids(ns).rwsem);
+       rcu_read_lock();
+       ipcp = ipcctl_pre_down_nolock(ns, &sem_ids(ns), semid, cmd,
+@@ -1523,7 +1523,7 @@ out_unlock0:
+ out_unlock1:
+       rcu_read_unlock();
+ out_up:
+-      up_write(&sem_ids(ns).rw_mutex);
++      up_write(&sem_ids(ns).rwsem);
+       return err;
+ }
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -83,8 +83,8 @@ void shm_init_ns(struct ipc_namespace *n
+ }
+ /*
+- * Called with shm_ids.rw_mutex (writer) and the shp structure locked.
+- * Only shm_ids.rw_mutex remains locked on exit.
++ * Called with shm_ids.rwsem (writer) and the shp structure locked.
++ * Only shm_ids.rwsem remains locked on exit.
+  */
+ static void do_shm_rmid(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
+ {
+@@ -148,7 +148,7 @@ static inline struct shmid_kernel *shm_o
+ }
+ /*
+- * shm_lock_(check_) routines are called in the paths where the rw_mutex
++ * shm_lock_(check_) routines are called in the paths where the rwsem
+  * is not necessarily held.
+  */
+ static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id)
+@@ -214,7 +214,7 @@ static void shm_open(struct vm_area_stru
+  * @ns: namespace
+  * @shp: struct to free
+  *
+- * It has to be called with shp and shm_ids.rw_mutex (writer) locked,
++ * It has to be called with shp and shm_ids.rwsem (writer) locked,
+  * but returns with shp unlocked and freed.
+  */
+ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
+@@ -261,7 +261,7 @@ static void shm_close(struct vm_area_str
+       struct shmid_kernel *shp;
+       struct ipc_namespace *ns = sfd->ns;
+-      down_write(&shm_ids(ns).rw_mutex);
++      down_write(&shm_ids(ns).rwsem);
+       /* remove from the list of attaches of the shm segment */
+       shp = shm_lock(ns, sfd->id);
+       BUG_ON(IS_ERR(shp));
+@@ -272,10 +272,10 @@ static void shm_close(struct vm_area_str
+               shm_destroy(ns, shp);
+       else
+               shm_unlock(shp);
+-      up_write(&shm_ids(ns).rw_mutex);
++      up_write(&shm_ids(ns).rwsem);
+ }
+-/* Called with ns->shm_ids(ns).rw_mutex locked */
++/* Called with ns->shm_ids(ns).rwsem locked */
+ static int shm_try_destroy_current(int id, void *p, void *data)
+ {
+       struct ipc_namespace *ns = data;
+@@ -306,7 +306,7 @@ static int shm_try_destroy_current(int i
+       return 0;
+ }
+-/* Called with ns->shm_ids(ns).rw_mutex locked */
++/* Called with ns->shm_ids(ns).rwsem locked */
+ static int shm_try_destroy_orphaned(int id, void *p, void *data)
+ {
+       struct ipc_namespace *ns = data;
+@@ -317,7 +317,7 @@ static int shm_try_destroy_orphaned(int
+        * We want to destroy segments without users and with already
+        * exit'ed originating process.
+        *
+-       * As shp->* are changed under rw_mutex, it's safe to skip shp locking.
++       * As shp->* are changed under rwsem, it's safe to skip shp locking.
+        */
+       if (shp->shm_creator != NULL)
+               return 0;
+@@ -331,10 +331,10 @@ static int shm_try_destroy_orphaned(int
+ void shm_destroy_orphaned(struct ipc_namespace *ns)
+ {
+-      down_write(&shm_ids(ns).rw_mutex);
++      down_write(&shm_ids(ns).rwsem);
+       if (shm_ids(ns).in_use)
+               idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_orphaned, ns);
+-      up_write(&shm_ids(ns).rw_mutex);
++      up_write(&shm_ids(ns).rwsem);
+ }
+@@ -346,10 +346,10 @@ void exit_shm(struct task_struct *task)
+               return;
+       /* Destroy all already created segments, but not mapped yet */
+-      down_write(&shm_ids(ns).rw_mutex);
++      down_write(&shm_ids(ns).rwsem);
+       if (shm_ids(ns).in_use)
+               idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_current, ns);
+-      up_write(&shm_ids(ns).rw_mutex);
++      up_write(&shm_ids(ns).rwsem);
+ }
+ static int shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+@@ -483,7 +483,7 @@ static const struct vm_operations_struct
+  * @ns: namespace
+  * @params: ptr to the structure that contains key, size and shmflg
+  *
+- * Called with shm_ids.rw_mutex held as a writer.
++ * Called with shm_ids.rwsem held as a writer.
+  */
+ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
+@@ -590,7 +590,7 @@ no_file:
+ }
+ /*
+- * Called with shm_ids.rw_mutex and ipcp locked.
++ * Called with shm_ids.rwsem and ipcp locked.
+  */
+ static inline int shm_security(struct kern_ipc_perm *ipcp, int shmflg)
+ {
+@@ -601,7 +601,7 @@ static inline int shm_security(struct ke
+ }
+ /*
+- * Called with shm_ids.rw_mutex and ipcp locked.
++ * Called with shm_ids.rwsem and ipcp locked.
+  */
+ static inline int shm_more_checks(struct kern_ipc_perm *ipcp,
+                               struct ipc_params *params)
+@@ -714,7 +714,7 @@ static inline unsigned long copy_shminfo
+ /*
+  * Calculate and add used RSS and swap pages of a shm.
+- * Called with shm_ids.rw_mutex held as a reader
++ * Called with shm_ids.rwsem held as a reader
+  */
+ static void shm_add_rss_swap(struct shmid_kernel *shp,
+       unsigned long *rss_add, unsigned long *swp_add)
+@@ -741,7 +741,7 @@ static void shm_add_rss_swap(struct shmi
+ }
+ /*
+- * Called with shm_ids.rw_mutex held as a reader
++ * Called with shm_ids.rwsem held as a reader
+  */
+ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
+               unsigned long *swp)
+@@ -770,9 +770,9 @@ static void shm_get_stat(struct ipc_name
+ }
+ /*
+- * This function handles some shmctl commands which require the rw_mutex
++ * This function handles some shmctl commands which require the rwsem
+  * to be held in write mode.
+- * NOTE: no locks must be held, the rw_mutex is taken inside this function.
++ * NOTE: no locks must be held, the rwsem is taken inside this function.
+  */
+ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
+                      struct shmid_ds __user *buf, int version)
+@@ -787,7 +787,7 @@ static int shmctl_down(struct ipc_namesp
+                       return -EFAULT;
+       }
+-      down_write(&shm_ids(ns).rw_mutex);
++      down_write(&shm_ids(ns).rwsem);
+       rcu_read_lock();
+       ipcp = ipcctl_pre_down_nolock(ns, &shm_ids(ns), shmid, cmd,
+@@ -826,7 +826,7 @@ out_unlock0:
+ out_unlock1:
+       rcu_read_unlock();
+ out_up:
+-      up_write(&shm_ids(ns).rw_mutex);
++      up_write(&shm_ids(ns).rwsem);
+       return err;
+ }
+@@ -857,9 +857,9 @@ static int shmctl_nolock(struct ipc_name
+               if(copy_shminfo_to_user (buf, &shminfo, version))
+                       return -EFAULT;
+-              down_read(&shm_ids(ns).rw_mutex);
++              down_read(&shm_ids(ns).rwsem);
+               err = ipc_get_maxid(&shm_ids(ns));
+-              up_read(&shm_ids(ns).rw_mutex);
++              up_read(&shm_ids(ns).rwsem);
+               if(err<0)
+                       err = 0;
+@@ -870,14 +870,14 @@ static int shmctl_nolock(struct ipc_name
+               struct shm_info shm_info;
+               memset(&shm_info, 0, sizeof(shm_info));
+-              down_read(&shm_ids(ns).rw_mutex);
++              down_read(&shm_ids(ns).rwsem);
+               shm_info.used_ids = shm_ids(ns).in_use;
+               shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp);
+               shm_info.shm_tot = ns->shm_tot;
+               shm_info.swap_attempts = 0;
+               shm_info.swap_successes = 0;
+               err = ipc_get_maxid(&shm_ids(ns));
+-              up_read(&shm_ids(ns).rw_mutex);
++              up_read(&shm_ids(ns).rwsem);
+               if (copy_to_user(buf, &shm_info, sizeof(shm_info))) {
+                       err = -EFAULT;
+                       goto out;
+@@ -1176,7 +1176,7 @@ out_fput:
+       fput(file);
+ out_nattch:
+-      down_write(&shm_ids(ns).rw_mutex);
++      down_write(&shm_ids(ns).rwsem);
+       shp = shm_lock(ns, shmid);
+       BUG_ON(IS_ERR(shp));
+       shp->shm_nattch--;
+@@ -1184,7 +1184,7 @@ out_nattch:
+               shm_destroy(ns, shp);
+       else
+               shm_unlock(shp);
+-      up_write(&shm_ids(ns).rw_mutex);
++      up_write(&shm_ids(ns).rwsem);
+       return err;
+ out_unlock:
+--- a/ipc/util.c
++++ b/ipc/util.c
+@@ -119,7 +119,7 @@ __initcall(ipc_init);
+  
+ void ipc_init_ids(struct ipc_ids *ids)
+ {
+-      init_rwsem(&ids->rw_mutex);
++      init_rwsem(&ids->rwsem);
+       ids->in_use = 0;
+       ids->seq = 0;
+@@ -174,7 +174,7 @@ void __init ipc_init_proc_interface(cons
+  *    @ids: Identifier set
+  *    @key: The key to find
+  *    
+- *    Requires ipc_ids.rw_mutex locked.
++ *    Requires ipc_ids.rwsem locked.
+  *    Returns the LOCKED pointer to the ipc structure if found or NULL
+  *    if not.
+  *    If key is found ipc points to the owning ipc structure
+@@ -208,7 +208,7 @@ static struct kern_ipc_perm *ipc_findkey
+  *    ipc_get_maxid   -       get the last assigned id
+  *    @ids: IPC identifier set
+  *
+- *    Called with ipc_ids.rw_mutex held.
++ *    Called with ipc_ids.rwsem held.
+  */
+ int ipc_get_maxid(struct ipc_ids *ids)
+@@ -246,7 +246,7 @@ int ipc_get_maxid(struct ipc_ids *ids)
+  *    is returned. The 'new' entry is returned in a locked state on success.
+  *    On failure the entry is not locked and a negative err-code is returned.
+  *
+- *    Called with writer ipc_ids.rw_mutex held.
++ *    Called with writer ipc_ids.rwsem held.
+  */
+ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
+ {
+@@ -312,9 +312,9 @@ static int ipcget_new(struct ipc_namespa
+ {
+       int err;
+-      down_write(&ids->rw_mutex);
++      down_write(&ids->rwsem);
+       err = ops->getnew(ns, params);
+-      up_write(&ids->rw_mutex);
++      up_write(&ids->rwsem);
+       return err;
+ }
+@@ -331,7 +331,7 @@ static int ipcget_new(struct ipc_namespa
+  *
+  *    On success, the IPC id is returned.
+  *
+- *    It is called with ipc_ids.rw_mutex and ipcp->lock held.
++ *    It is called with ipc_ids.rwsem and ipcp->lock held.
+  */
+ static int ipc_check_perms(struct ipc_namespace *ns,
+                          struct kern_ipc_perm *ipcp,
+@@ -376,7 +376,7 @@ static int ipcget_public(struct ipc_name
+        * Take the lock as a writer since we are potentially going to add
+        * a new entry + read locks are not "upgradable"
+        */
+-      down_write(&ids->rw_mutex);
++      down_write(&ids->rwsem);
+       ipcp = ipc_findkey(ids, params->key);
+       if (ipcp == NULL) {
+               /* key not used */
+@@ -402,7 +402,7 @@ static int ipcget_public(struct ipc_name
+               }
+               ipc_unlock(ipcp);
+       }
+-      up_write(&ids->rw_mutex);
++      up_write(&ids->rwsem);
+       return err;
+ }
+@@ -413,7 +413,7 @@ static int ipcget_public(struct ipc_name
+  *    @ids: IPC identifier set
+  *    @ipcp: ipc perm structure containing the identifier to remove
+  *
+- *    ipc_ids.rw_mutex (as a writer) and the spinlock for this ID are held
++ *    ipc_ids.rwsem (as a writer) and the spinlock for this ID are held
+  *    before this function is called, and remain locked on the exit.
+  */
+  
+@@ -613,7 +613,7 @@ struct kern_ipc_perm *ipc_obtain_object(
+ }
+ /**
+- * ipc_lock - Lock an ipc structure without rw_mutex held
++ * ipc_lock - Lock an ipc structure without rwsem held
+  * @ids: IPC identifier set
+  * @id: ipc id to look for
+  *
+@@ -740,7 +740,7 @@ int ipc_update_perm(struct ipc64_perm *i
+  *  - performs some audit and permission check, depending on the given cmd
+  *  - returns a pointer to the ipc object or otherwise, the corresponding error.
+  *
+- * Call holding the both the rw_mutex and the rcu read lock.
++ * Call holding the both the rwsem and the rcu read lock.
+  */
+ struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
+                                       struct ipc_ids *ids, int id, int cmd,
+@@ -860,7 +860,7 @@ static void *sysvipc_proc_start(struct s
+        * Take the lock - this will be released by the corresponding
+        * call to stop().
+        */
+-      down_read(&ids->rw_mutex);
++      down_read(&ids->rwsem);
+       /* pos < 0 is invalid */
+       if (*pos < 0)
+@@ -887,7 +887,7 @@ static void sysvipc_proc_stop(struct seq
+       ids = &iter->ns->ids[iface->ids];
+       /* Release the lock we took in start() */
+-      up_read(&ids->rw_mutex);
++      up_read(&ids->rwsem);
+ }
+ static int sysvipc_proc_show(struct seq_file *s, void *it)
+--- a/ipc/util.h
++++ b/ipc/util.h
+@@ -101,10 +101,10 @@ void __init ipc_init_proc_interface(cons
+ #define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)
+ #define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER)
+-/* must be called with ids->rw_mutex acquired for writing */
++/* must be called with ids->rwsem acquired for writing */
+ int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
+-/* must be called with ids->rw_mutex acquired for reading */
++/* must be called with ids->rwsem acquired for reading */
+ int ipc_get_maxid(struct ipc_ids *);
+ /* must be called with both locks acquired. */
diff --git a/queue-3.11/ipc-shm-drop-shm_lock_check.patch b/queue-3.11/ipc-shm-drop-shm_lock_check.patch
new file mode 100644 (file)
index 0000000..7031353
--- /dev/null
@@ -0,0 +1,45 @@
+From 7a25dd9e042b2b94202a67e5551112f4ac87285a Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:30 -0700
+Subject: ipc, shm: drop shm_lock_check
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit 7a25dd9e042b2b94202a67e5551112f4ac87285a upstream.
+
+This function was replaced by a the lockless shm_obtain_object_check(),
+and no longer has any users.
+
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Cc: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/shm.c |   11 -----------
+ 1 file changed, 11 deletions(-)
+
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -167,17 +167,6 @@ static inline void shm_lock_by_ptr(struc
+       ipc_lock_object(&ipcp->shm_perm);
+ }
+-static inline struct shmid_kernel *shm_lock_check(struct ipc_namespace *ns,
+-                                              int id)
+-{
+-      struct kern_ipc_perm *ipcp = ipc_lock_check(&shm_ids(ns), id);
+-
+-      if (IS_ERR(ipcp))
+-              return (struct shmid_kernel *)ipcp;
+-
+-      return container_of(ipcp, struct shmid_kernel, shm_perm);
+-}
+-
+ static void shm_rcu_free(struct rcu_head *head)
+ {
+       struct ipc_rcu *p = container_of(head, struct ipc_rcu, rcu);
diff --git a/queue-3.11/ipc-shm-guard-against-non-existant-vma-in-shmdt-2.patch b/queue-3.11/ipc-shm-guard-against-non-existant-vma-in-shmdt-2.patch
new file mode 100644 (file)
index 0000000..5441759
--- /dev/null
@@ -0,0 +1,40 @@
+From 530fcd16d87cd2417c472a581ba5a1e501556c86 Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:28 -0700
+Subject: ipc, shm: guard against non-existant vma in shmdt(2)
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit 530fcd16d87cd2417c472a581ba5a1e501556c86 upstream.
+
+When !CONFIG_MMU there's a chance we can derefence a NULL pointer when the
+VM area isn't found - check the return value of find_vma().
+
+Also, remove the redundant -EINVAL return: retval is set to the proper
+return code and *only* changed to 0, when we actually unmap the segments.
+
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Cc: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/shm.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -1295,8 +1295,7 @@ SYSCALL_DEFINE1(shmdt, char __user *, sh
+ #else /* CONFIG_MMU */
+       /* under NOMMU conditions, the exact address to be destroyed must be
+        * given */
+-      retval = -EINVAL;
+-      if (vma->vm_start == addr && vma->vm_ops == &shm_vm_ops) {
++      if (vma && vma->vm_start == addr && vma->vm_ops == &shm_vm_ops) {
+               do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
+               retval = 0;
+       }
index 4b1e035ee5b6a66e8f76aa12c28ebbd844aedca0..df3ee059fb0fe80e2d249e51eb3061a7c0b60de9 100644 (file)
@@ -37,3 +37,10 @@ ipc-shm-make-shmctl_nolock-lockless.patch
 ipc-shm-shorten-critical-region-for-shmctl.patch
 ipc-shm-cleanup-do_shmat-pasta.patch
 ipc-shm-shorten-critical-region-for-shmat.patch
+ipc-rename-ids-rw_mutex.patch
+ipc-msg-drop-msg_unlock.patch
+ipc-document-general-ipc-locking-scheme.patch
+ipc-shm-guard-against-non-existant-vma-in-shmdt-2.patch
+ipc-drop-ipc_lock_by_ptr.patch
+ipc-shm-drop-shm_lock_check.patch
+ipc-drop-ipc_lock_check.patch