Merge branch 'userns-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 4 Apr 2018 02:15:32 +0000 (19:15 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 4 Apr 2018 02:15:32 +0000 (19:15 -0700)
Pull namespace updates from Eric Biederman:
 "There was a lot of work this cycle fixing bugs that were discovered
  after the merge window and getting everything ready where we can
  reasonably support fully unprivileged fuse. The bug fixes you already
  have and much of the unprivileged fuse work is coming in via other
  trees.

  Still left for fully unprivileged fuse is figuring out how to cleanly
  handle .set_acl and .get_acl in the legacy case, and properly handling
  of evm xattrs on unprivileged mounts.

  Included in the tree is a cleanup from Alexely that replaced a linked
  list with a statically allocated fix sized array for the pid caches,
  which simplifies and speeds things up.

  Then there is are some cleanups and fixes for the ipc namespace. The
  motivation was that in reviewing other code it was discovered that
  access ipc objects from different pid namespaces recorded pids in such
  a way that when asked the wrong pids were returned. In the worst case
  there has been a measured 30% performance impact for sysvipc
  semaphores. Other test cases showed no measurable performance impact.
  Manfred Spraul and Davidlohr Bueso who tend to work on sysvipc
  performance both gave the nod that this is good enough.

  Casey Schaufler and James Morris have given their approval to the LSM
  side of the changes.

  I simplified the types and the code dealing with sysvipc to pass just
  kern_ipc_perm for all three types of ipc. Which reduced the header
  dependencies throughout the kernel and simplified the lsm code.

  Which let me work on the pid fixes without having to worry about
  trivial changes causing complete kernel recompiles"

* 'userns-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace:
  ipc/shm: Fix pid freeing.
  ipc/shm: fix up for struct file no longer being available in shm.h
  ipc/smack: Tidy up from the change in type of the ipc security hooks
  ipc: Directly call the security hook in ipc_ops.associate
  ipc/sem: Fix semctl(..., GETPID, ...) between pid namespaces
  ipc/msg: Fix msgctl(..., IPC_STAT, ...) between pid namespaces
  ipc/shm: Fix shmctl(..., IPC_STAT, ...) between pid namespaces.
  ipc/util: Helpers for making the sysvipc operations pid namespace aware
  ipc: Move IPCMNI from include/ipc.h into ipc/util.h
  msg: Move struct msg_queue into ipc/msg.c
  shm: Move struct shmid_kernel into ipc/shm.c
  sem: Move struct sem and struct sem_array into ipc/sem.c
  msg/security: Pass kern_ipc_perm not msg_queue into the msg_queue security hooks
  shm/security: Pass kern_ipc_perm not shmid_kernel into the shm security hooks
  sem/security: Pass kern_ipc_perm not sem_array into the sem security hooks
  pidns: simpler allocation of pid_* caches

15 files changed:
include/linux/ipc.h
include/linux/lsm_hooks.h
include/linux/msg.h
include/linux/security.h
include/linux/sem.h
include/linux/shm.h
ipc/msg.c
ipc/sem.c
ipc/shm.c
ipc/util.c
ipc/util.h
kernel/pid_namespace.c
security/security.c
security/selinux/hooks.c
security/smack/smack_lsm.c

index 821b2f2609926636a6b88c5e25cb23ecc8f92806..6cc2df7f7ac949e72a59821ae9d25ce529371213 100644 (file)
@@ -8,8 +8,6 @@
 #include <uapi/linux/ipc.h>
 #include <linux/refcount.h>
 
-#define IPCMNI 32768  /* <= MAX_INT limit for ipc arrays (including sysctl changes) */
-
 /* used by in-kernel data structures */
 struct kern_ipc_perm {
        spinlock_t      lock;
index 7161d8e7ee79246ffca220805826f883f26d7ddd..bde167fa2c51260b095d5f869e033d9c4d89e357 100644 (file)
@@ -1575,28 +1575,28 @@ union security_list_options {
        int (*msg_msg_alloc_security)(struct msg_msg *msg);
        void (*msg_msg_free_security)(struct msg_msg *msg);
 
-       int (*msg_queue_alloc_security)(struct msg_queue *msq);
-       void (*msg_queue_free_security)(struct msg_queue *msq);
-       int (*msg_queue_associate)(struct msg_queue *msq, int msqflg);
-       int (*msg_queue_msgctl)(struct msg_queue *msq, int cmd);
-       int (*msg_queue_msgsnd)(struct msg_queue *msq, struct msg_msg *msg,
+       int (*msg_queue_alloc_security)(struct kern_ipc_perm *msq);
+       void (*msg_queue_free_security)(struct kern_ipc_perm *msq);
+       int (*msg_queue_associate)(struct kern_ipc_perm *msq, int msqflg);
+       int (*msg_queue_msgctl)(struct kern_ipc_perm *msq, int cmd);
+       int (*msg_queue_msgsnd)(struct kern_ipc_perm *msq, struct msg_msg *msg,
                                int msqflg);
-       int (*msg_queue_msgrcv)(struct msg_queue *msq, struct msg_msg *msg,
+       int (*msg_queue_msgrcv)(struct kern_ipc_perm *msq, struct msg_msg *msg,
                                struct task_struct *target, long type,
                                int mode);
 
-       int (*shm_alloc_security)(struct shmid_kernel *shp);
-       void (*shm_free_security)(struct shmid_kernel *shp);
-       int (*shm_associate)(struct shmid_kernel *shp, int shmflg);
-       int (*shm_shmctl)(struct shmid_kernel *shp, int cmd);
-       int (*shm_shmat)(struct shmid_kernel *shp, char __user *shmaddr,
+       int (*shm_alloc_security)(struct kern_ipc_perm *shp);
+       void (*shm_free_security)(struct kern_ipc_perm *shp);
+       int (*shm_associate)(struct kern_ipc_perm *shp, int shmflg);
+       int (*shm_shmctl)(struct kern_ipc_perm *shp, int cmd);
+       int (*shm_shmat)(struct kern_ipc_perm *shp, char __user *shmaddr,
                                int shmflg);
 
-       int (*sem_alloc_security)(struct sem_array *sma);
-       void (*sem_free_security)(struct sem_array *sma);
-       int (*sem_associate)(struct sem_array *sma, int semflg);
-       int (*sem_semctl)(struct sem_array *sma, int cmd);
-       int (*sem_semop)(struct sem_array *sma, struct sembuf *sops,
+       int (*sem_alloc_security)(struct kern_ipc_perm *sma);
+       void (*sem_free_security)(struct kern_ipc_perm *sma);
+       int (*sem_associate)(struct kern_ipc_perm *sma, int semflg);
+       int (*sem_semctl)(struct kern_ipc_perm *sma, int cmd);
+       int (*sem_semop)(struct kern_ipc_perm *sma, struct sembuf *sops,
                                unsigned nsops, int alter);
 
        int (*netlink_send)(struct sock *sk, struct sk_buff *skb);
index 0a7eefeee0d11862d7e2932a1ee56750b562b24f..9a972a296b9539e5c83565c09d196e7e1c06f354 100644 (file)
@@ -3,7 +3,6 @@
 #define _LINUX_MSG_H
 
 #include <linux/list.h>
-#include <linux/time64.h>
 #include <uapi/linux/msg.h>
 
 /* one msg_msg structure for each message */
@@ -16,21 +15,4 @@ struct msg_msg {
        /* the actual message follows immediately */
 };
 
-/* one msq_queue structure for each present queue on the system */
-struct msg_queue {
-       struct kern_ipc_perm q_perm;
-       time64_t q_stime;               /* last msgsnd time */
-       time64_t q_rtime;               /* last msgrcv time */
-       time64_t q_ctime;               /* last change time */
-       unsigned long q_cbytes;         /* current number of bytes on queue */
-       unsigned long q_qnum;           /* number of messages in queue */
-       unsigned long q_qbytes;         /* max number of bytes on queue */
-       pid_t q_lspid;                  /* pid of last msgsnd */
-       pid_t q_lrpid;                  /* last receive pid */
-
-       struct list_head q_messages;
-       struct list_head q_receivers;
-       struct list_head q_senders;
-} __randomize_layout;
-
 #endif /* _LINUX_MSG_H */
index 73f1ef625d40c900430778fab29f8bad6cd2e029..128e1e4a53460bbc1068e0f6d4ba0677f02899f5 100644 (file)
@@ -36,7 +36,6 @@ struct linux_binprm;
 struct cred;
 struct rlimit;
 struct siginfo;
-struct sem_array;
 struct sembuf;
 struct kern_ipc_perm;
 struct audit_context;
@@ -50,9 +49,7 @@ struct qstr;
 struct iattr;
 struct fown_struct;
 struct file_operations;
-struct shmid_kernel;
 struct msg_msg;
-struct msg_queue;
 struct xattr;
 struct xfrm_sec_ctx;
 struct mm_struct;
@@ -355,24 +352,24 @@ int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag);
 void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid);
 int security_msg_msg_alloc(struct msg_msg *msg);
 void security_msg_msg_free(struct msg_msg *msg);
-int security_msg_queue_alloc(struct msg_queue *msq);
-void security_msg_queue_free(struct msg_queue *msq);
-int security_msg_queue_associate(struct msg_queue *msq, int msqflg);
-int security_msg_queue_msgctl(struct msg_queue *msq, int cmd);
-int security_msg_queue_msgsnd(struct msg_queue *msq,
+int security_msg_queue_alloc(struct kern_ipc_perm *msq);
+void security_msg_queue_free(struct kern_ipc_perm *msq);
+int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg);
+int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd);
+int security_msg_queue_msgsnd(struct kern_ipc_perm *msq,
                              struct msg_msg *msg, int msqflg);
-int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
+int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
                              struct task_struct *target, long type, int mode);
-int security_shm_alloc(struct shmid_kernel *shp);
-void security_shm_free(struct shmid_kernel *shp);
-int security_shm_associate(struct shmid_kernel *shp, int shmflg);
-int security_shm_shmctl(struct shmid_kernel *shp, int cmd);
-int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg);
-int security_sem_alloc(struct sem_array *sma);
-void security_sem_free(struct sem_array *sma);
-int security_sem_associate(struct sem_array *sma, int semflg);
-int security_sem_semctl(struct sem_array *sma, int cmd);
-int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
+int security_shm_alloc(struct kern_ipc_perm *shp);
+void security_shm_free(struct kern_ipc_perm *shp);
+int security_shm_associate(struct kern_ipc_perm *shp, int shmflg);
+int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd);
+int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg);
+int security_sem_alloc(struct kern_ipc_perm *sma);
+void security_sem_free(struct kern_ipc_perm *sma);
+int security_sem_associate(struct kern_ipc_perm *sma, int semflg);
+int security_sem_semctl(struct kern_ipc_perm *sma, int cmd);
+int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
                        unsigned nsops, int alter);
 void security_d_instantiate(struct dentry *dentry, struct inode *inode);
 int security_getprocattr(struct task_struct *p, char *name, char **value);
@@ -1045,32 +1042,32 @@ static inline int security_msg_msg_alloc(struct msg_msg *msg)
 static inline void security_msg_msg_free(struct msg_msg *msg)
 { }
 
-static inline int security_msg_queue_alloc(struct msg_queue *msq)
+static inline int security_msg_queue_alloc(struct kern_ipc_perm *msq)
 {
        return 0;
 }
 
-static inline void security_msg_queue_free(struct msg_queue *msq)
+static inline void security_msg_queue_free(struct kern_ipc_perm *msq)
 { }
 
-static inline int security_msg_queue_associate(struct msg_queue *msq,
+static inline int security_msg_queue_associate(struct kern_ipc_perm *msq,
                                               int msqflg)
 {
        return 0;
 }
 
-static inline int security_msg_queue_msgctl(struct msg_queue *msq, int cmd)
+static inline int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
 {
        return 0;
 }
 
-static inline int security_msg_queue_msgsnd(struct msg_queue *msq,
+static inline int security_msg_queue_msgsnd(struct kern_ipc_perm *msq,
                                            struct msg_msg *msg, int msqflg)
 {
        return 0;
 }
 
-static inline int security_msg_queue_msgrcv(struct msg_queue *msq,
+static inline int security_msg_queue_msgrcv(struct kern_ipc_perm *msq,
                                            struct msg_msg *msg,
                                            struct task_struct *target,
                                            long type, int mode)
@@ -1078,50 +1075,50 @@ static inline int security_msg_queue_msgrcv(struct msg_queue *msq,
        return 0;
 }
 
-static inline int security_shm_alloc(struct shmid_kernel *shp)
+static inline int security_shm_alloc(struct kern_ipc_perm *shp)
 {
        return 0;
 }
 
-static inline void security_shm_free(struct shmid_kernel *shp)
+static inline void security_shm_free(struct kern_ipc_perm *shp)
 { }
 
-static inline int security_shm_associate(struct shmid_kernel *shp,
+static inline int security_shm_associate(struct kern_ipc_perm *shp,
                                         int shmflg)
 {
        return 0;
 }
 
-static inline int security_shm_shmctl(struct shmid_kernel *shp, int cmd)
+static inline int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
 {
        return 0;
 }
 
-static inline int security_shm_shmat(struct shmid_kernel *shp,
+static inline int security_shm_shmat(struct kern_ipc_perm *shp,
                                     char __user *shmaddr, int shmflg)
 {
        return 0;
 }
 
-static inline int security_sem_alloc(struct sem_array *sma)
+static inline int security_sem_alloc(struct kern_ipc_perm *sma)
 {
        return 0;
 }
 
-static inline void security_sem_free(struct sem_array *sma)
+static inline void security_sem_free(struct kern_ipc_perm *sma)
 { }
 
-static inline int security_sem_associate(struct sem_array *sma, int semflg)
+static inline int security_sem_associate(struct kern_ipc_perm *sma, int semflg)
 {
        return 0;
 }
 
-static inline int security_sem_semctl(struct sem_array *sma, int cmd)
+static inline int security_sem_semctl(struct kern_ipc_perm *sma, int cmd)
 {
        return 0;
 }
 
-static inline int security_sem_semop(struct sem_array *sma,
+static inline int security_sem_semop(struct kern_ipc_perm *sma,
                                     struct sembuf *sops, unsigned nsops,
                                     int alter)
 {
index 9badd322dcee809bcd398977ad511868be96cc6a..5608a500c43ea9090835d0bee34b1dbb548444f3 100644 (file)
@@ -2,48 +2,10 @@
 #ifndef _LINUX_SEM_H
 #define _LINUX_SEM_H
 
-#include <linux/atomic.h>
-#include <linux/rcupdate.h>
-#include <linux/cache.h>
-#include <linux/time64.h>
 #include <uapi/linux/sem.h>
 
 struct task_struct;
-
-/* One semaphore structure for each semaphore in the system. */
-struct sem {
-       int     semval;         /* current value */
-       /*
-        * PID of the process that last modified the semaphore. For
-        * Linux, specifically these are:
-        *  - semop
-        *  - semctl, via SETVAL and SETALL.
-        *  - at task exit when performing undo adjustments (see exit_sem).
-        */
-       int     sempid;
-       spinlock_t      lock;   /* spinlock for fine-grained semtimedop */
-       struct list_head pending_alter; /* pending single-sop operations */
-                                       /* that alter the semaphore */
-       struct list_head pending_const; /* pending single-sop operations */
-                                       /* that do not alter the semaphore*/
-       time_t  sem_otime;      /* candidate for sem_otime */
-} ____cacheline_aligned_in_smp;
-
-/* One sem_array data structure for each set of semaphores in the system. */
-struct sem_array {
-       struct kern_ipc_perm    sem_perm;       /* permissions .. see ipc.h */
-       time64_t                sem_ctime;      /* create/last semctl() time */
-       struct list_head        pending_alter;  /* pending operations */
-                                               /* that alter the array */
-       struct list_head        pending_const;  /* pending complex operations */
-                                               /* that do not alter semvals */
-       struct list_head        list_id;        /* undo requests on this array */
-       int                     sem_nsems;      /* no. of semaphores in array */
-       int                     complex_count;  /* pending complex operations */
-       unsigned int            use_global_lock;/* >0: global lock required */
-
-       struct sem              sems[];
-} __randomize_layout;
+struct sem_undo_list;
 
 #ifdef CONFIG_SYSVIPC
 
index 2bbafacfbfc9fc87bb03d207b79915e237a2eb1a..d8e69aed3d322d2b5a1ad05c4e6032fa25e68daf 100644 (file)
@@ -7,27 +7,7 @@
 #include <uapi/linux/shm.h>
 #include <asm/shmparam.h>
 
-struct shmid_kernel /* private to the kernel */
-{      
-       struct kern_ipc_perm    shm_perm;
-       struct file             *shm_file;
-       unsigned long           shm_nattch;
-       unsigned long           shm_segsz;
-       time64_t                shm_atim;
-       time64_t                shm_dtim;
-       time64_t                shm_ctim;
-       pid_t                   shm_cprid;
-       pid_t                   shm_lprid;
-       struct user_struct      *mlock_user;
-
-       /* The task created the shm object.  NULL if the task is dead. */
-       struct task_struct      *shm_creator;
-       struct list_head        shm_clist;      /* list by creator */
-} __randomize_layout;
-
-/* shm_mode upper byte flags */
-#define        SHM_DEST        01000   /* segment will be destroyed on last detach */
-#define SHM_LOCKED      02000   /* segment will not be swapped */
+struct file;
 
 #ifdef CONFIG_SYSVIPC
 struct sysv_shm {
index 9de48065c1ac03e5b592a2d0a9a0a38c1cd0c3d5..114a211896131c65b389f851b6bf33a7bef99ba1 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
 #include <linux/uaccess.h>
 #include "util.h"
 
+/* one msq_queue structure for each present queue on the system */
+struct msg_queue {
+       struct kern_ipc_perm q_perm;
+       time64_t q_stime;               /* last msgsnd time */
+       time64_t q_rtime;               /* last msgrcv time */
+       time64_t q_ctime;               /* last change time */
+       unsigned long q_cbytes;         /* current number of bytes on queue */
+       unsigned long q_qnum;           /* number of messages in queue */
+       unsigned long q_qbytes;         /* max number of bytes on queue */
+       struct pid *q_lspid;            /* pid of last msgsnd */
+       struct pid *q_lrpid;            /* last receive pid */
+
+       struct list_head q_messages;
+       struct list_head q_receivers;
+       struct list_head q_senders;
+} __randomize_layout;
+
 /* one msg_receiver structure for each sleeping receiver */
 struct msg_receiver {
        struct list_head        r_list;
@@ -101,7 +118,7 @@ static void msg_rcu_free(struct rcu_head *head)
        struct kern_ipc_perm *p = container_of(head, struct kern_ipc_perm, rcu);
        struct msg_queue *msq = container_of(p, struct msg_queue, q_perm);
 
-       security_msg_queue_free(msq);
+       security_msg_queue_free(&msq->q_perm);
        kvfree(msq);
 }
 
@@ -127,7 +144,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
        msq->q_perm.key = key;
 
        msq->q_perm.security = NULL;
-       retval = security_msg_queue_alloc(msq);
+       retval = security_msg_queue_alloc(&msq->q_perm);
        if (retval) {
                kvfree(msq);
                return retval;
@@ -137,7 +154,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
        msq->q_ctime = ktime_get_real_seconds();
        msq->q_cbytes = msq->q_qnum = 0;
        msq->q_qbytes = ns->msg_ctlmnb;
-       msq->q_lspid = msq->q_lrpid = 0;
+       msq->q_lspid = msq->q_lrpid = NULL;
        INIT_LIST_HEAD(&msq->q_messages);
        INIT_LIST_HEAD(&msq->q_receivers);
        INIT_LIST_HEAD(&msq->q_senders);
@@ -250,25 +267,17 @@ static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
                free_msg(msg);
        }
        atomic_sub(msq->q_cbytes, &ns->msg_bytes);
+       ipc_update_pid(&msq->q_lspid, NULL);
+       ipc_update_pid(&msq->q_lrpid, NULL);
        ipc_rcu_putref(&msq->q_perm, msg_rcu_free);
 }
 
-/*
- * Called with msg_ids.rwsem 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);
-
-       return security_msg_queue_associate(msq, msgflg);
-}
-
 long ksys_msgget(key_t key, int msgflg)
 {
        struct ipc_namespace *ns;
        static const struct ipc_ops msg_ops = {
                .getnew = newque,
-               .associate = msg_security,
+               .associate = security_msg_queue_associate,
        };
        struct ipc_params msg_params;
 
@@ -385,7 +394,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
 
        msq = container_of(ipcp, struct msg_queue, q_perm);
 
-       err = security_msg_queue_msgctl(msq, cmd);
+       err = security_msg_queue_msgctl(&msq->q_perm, cmd);
        if (err)
                goto out_unlock1;
 
@@ -507,7 +516,7 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid,
        if (ipcperms(ns, &msq->q_perm, S_IRUGO))
                goto out_unlock;
 
-       err = security_msg_queue_msgctl(msq, cmd);
+       err = security_msg_queue_msgctl(&msq->q_perm, cmd);
        if (err)
                goto out_unlock;
 
@@ -526,8 +535,8 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid,
        p->msg_cbytes = msq->q_cbytes;
        p->msg_qnum   = msq->q_qnum;
        p->msg_qbytes = msq->q_qbytes;
-       p->msg_lspid  = msq->q_lspid;
-       p->msg_lrpid  = msq->q_lrpid;
+       p->msg_lspid  = pid_vnr(msq->q_lspid);
+       p->msg_lrpid  = pid_vnr(msq->q_lrpid);
 
        ipc_unlock_object(&msq->q_perm);
        rcu_read_unlock();
@@ -733,7 +742,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg,
 
        list_for_each_entry_safe(msr, t, &msq->q_receivers, r_list) {
                if (testmsg(msg, msr->r_msgtype, msr->r_mode) &&
-                   !security_msg_queue_msgrcv(msq, msg, msr->r_tsk,
+                   !security_msg_queue_msgrcv(&msq->q_perm, msg, msr->r_tsk,
                                               msr->r_msgtype, msr->r_mode)) {
 
                        list_del(&msr->r_list);
@@ -741,7 +750,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg,
                                wake_q_add(wake_q, msr->r_tsk);
                                WRITE_ONCE(msr->r_msg, ERR_PTR(-E2BIG));
                        } else {
-                               msq->q_lrpid = task_pid_vnr(msr->r_tsk);
+                               ipc_update_pid(&msq->q_lrpid, task_pid(msr->r_tsk));
                                msq->q_rtime = get_seconds();
 
                                wake_q_add(wake_q, msr->r_tsk);
@@ -799,7 +808,7 @@ static long do_msgsnd(int msqid, long mtype, void __user *mtext,
                        goto out_unlock0;
                }
 
-               err = security_msg_queue_msgsnd(msq, msg, msgflg);
+               err = security_msg_queue_msgsnd(&msq->q_perm, msg, msgflg);
                if (err)
                        goto out_unlock0;
 
@@ -842,7 +851,7 @@ static long do_msgsnd(int msqid, long mtype, void __user *mtext,
 
        }
 
-       msq->q_lspid = task_tgid_vnr(current);
+       ipc_update_pid(&msq->q_lspid, task_tgid(current));
        msq->q_stime = get_seconds();
 
        if (!pipelined_send(msq, msg, &wake_q)) {
@@ -987,7 +996,7 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode)
 
        list_for_each_entry(msg, &msq->q_messages, m_list) {
                if (testmsg(msg, *msgtyp, mode) &&
-                   !security_msg_queue_msgrcv(msq, msg, current,
+                   !security_msg_queue_msgrcv(&msq->q_perm, msg, current,
                                               *msgtyp, mode)) {
                        if (mode == SEARCH_LESSEQUAL && msg->m_type != 1) {
                                *msgtyp = msg->m_type - 1;
@@ -1072,7 +1081,7 @@ static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, in
                        list_del(&msg->m_list);
                        msq->q_qnum--;
                        msq->q_rtime = get_seconds();
-                       msq->q_lrpid = task_tgid_vnr(current);
+                       ipc_update_pid(&msq->q_lrpid, task_tgid(current));
                        msq->q_cbytes -= msg->m_ts;
                        atomic_sub(msg->m_ts, &ns->msg_bytes);
                        atomic_dec(&ns->msg_hdrs);
@@ -1227,6 +1236,7 @@ void msg_exit_ns(struct ipc_namespace *ns)
 #ifdef CONFIG_PROC_FS
 static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
 {
+       struct pid_namespace *pid_ns = ipc_seq_pid_ns(s);
        struct user_namespace *user_ns = seq_user_ns(s);
        struct kern_ipc_perm *ipcp = it;
        struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm);
@@ -1238,8 +1248,8 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
                   msq->q_perm.mode,
                   msq->q_cbytes,
                   msq->q_qnum,
-                  msq->q_lspid,
-                  msq->q_lrpid,
+                  pid_nr_ns(msq->q_lspid, pid_ns),
+                  pid_nr_ns(msq->q_lrpid, pid_ns),
                   from_kuid_munged(user_ns, msq->q_perm.uid),
                   from_kgid_munged(user_ns, msq->q_perm.gid),
                   from_kuid_munged(user_ns, msq->q_perm.cuid),
index 1cf56279a84c7f79cec2be8f11b9600f41249d34..2994da8ccc7f6d77b72451e96d6c7f4dcc0764c0 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
 #include <linux/uaccess.h>
 #include "util.h"
 
+/* One semaphore structure for each semaphore in the system. */
+struct sem {
+       int     semval;         /* current value */
+       /*
+        * PID of the process that last modified the semaphore. For
+        * Linux, specifically these are:
+        *  - semop
+        *  - semctl, via SETVAL and SETALL.
+        *  - at task exit when performing undo adjustments (see exit_sem).
+        */
+       struct pid *sempid;
+       spinlock_t      lock;   /* spinlock for fine-grained semtimedop */
+       struct list_head pending_alter; /* pending single-sop operations */
+                                       /* that alter the semaphore */
+       struct list_head pending_const; /* pending single-sop operations */
+                                       /* that do not alter the semaphore*/
+       time_t  sem_otime;      /* candidate for sem_otime */
+} ____cacheline_aligned_in_smp;
+
+/* One sem_array data structure for each set of semaphores in the system. */
+struct sem_array {
+       struct kern_ipc_perm    sem_perm;       /* permissions .. see ipc.h */
+       time64_t                sem_ctime;      /* create/last semctl() time */
+       struct list_head        pending_alter;  /* pending operations */
+                                               /* that alter the array */
+       struct list_head        pending_const;  /* pending complex operations */
+                                               /* that do not alter semvals */
+       struct list_head        list_id;        /* undo requests on this array */
+       int                     sem_nsems;      /* no. of semaphores in array */
+       int                     complex_count;  /* pending complex operations */
+       unsigned int            use_global_lock;/* >0: global lock required */
+
+       struct sem              sems[];
+} __randomize_layout;
 
 /* One queue for each sleeping process in the system. */
 struct sem_queue {
        struct list_head        list;    /* queue of pending operations */
        struct task_struct      *sleeper; /* this process */
        struct sem_undo         *undo;   /* undo structure */
-       int                     pid;     /* process id of requesting process */
+       struct pid              *pid;    /* process id of requesting process */
        int                     status;  /* completion status of operation */
        struct sembuf           *sops;   /* array of pending operations */
        struct sembuf           *blocking; /* the operation that blocked */
@@ -265,7 +299,7 @@ static void sem_rcu_free(struct rcu_head *head)
        struct kern_ipc_perm *p = container_of(head, struct kern_ipc_perm, rcu);
        struct sem_array *sma = container_of(p, struct sem_array, sem_perm);
 
-       security_sem_free(sma);
+       security_sem_free(&sma->sem_perm);
        kvfree(sma);
 }
 
@@ -495,7 +529,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
        sma->sem_perm.key = key;
 
        sma->sem_perm.security = NULL;
-       retval = security_sem_alloc(sma);
+       retval = security_sem_alloc(&sma->sem_perm);
        if (retval) {
                kvfree(sma);
                return retval;
@@ -530,17 +564,6 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
 }
 
 
-/*
- * Called with sem_ids.rwsem and ipcp locked.
- */
-static inline int sem_security(struct kern_ipc_perm *ipcp, int semflg)
-{
-       struct sem_array *sma;
-
-       sma = container_of(ipcp, struct sem_array, sem_perm);
-       return security_sem_associate(sma, semflg);
-}
-
 /*
  * Called with sem_ids.rwsem and ipcp locked.
  */
@@ -561,7 +584,7 @@ long ksys_semget(key_t key, int nsems, int semflg)
        struct ipc_namespace *ns;
        static const struct ipc_ops sem_ops = {
                .getnew = newary,
-               .associate = sem_security,
+               .associate = security_sem_associate,
                .more_checks = sem_more_checks,
        };
        struct ipc_params sem_params;
@@ -602,7 +625,8 @@ SYSCALL_DEFINE3(semget, key_t, key, int, nsems, int, semflg)
  */
 static int perform_atomic_semop_slow(struct sem_array *sma, struct sem_queue *q)
 {
-       int result, sem_op, nsops, pid;
+       int result, sem_op, nsops;
+       struct pid *pid;
        struct sembuf *sop;
        struct sem *curr;
        struct sembuf *sops;
@@ -640,7 +664,7 @@ static int perform_atomic_semop_slow(struct sem_array *sma, struct sem_queue *q)
        sop--;
        pid = q->pid;
        while (sop >= sops) {
-               sma->sems[sop->sem_num].sempid = pid;
+               ipc_update_pid(&sma->sems[sop->sem_num].sempid, pid);
                sop--;
        }
 
@@ -727,7 +751,7 @@ static int perform_atomic_semop(struct sem_array *sma, struct sem_queue *q)
                        un->semadj[sop->sem_num] = undo;
                }
                curr->semval += sem_op;
-               curr->sempid = q->pid;
+               ipc_update_pid(&curr->sempid, q->pid);
        }
 
        return 0;
@@ -1134,6 +1158,7 @@ static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
                        unlink_queue(sma, q);
                        wake_up_sem_queue_prepare(q, -EIDRM, &wake_q);
                }
+               ipc_update_pid(&sem->sempid, NULL);
        }
 
        /* Remove the semaphore set from the IDR */
@@ -1214,7 +1239,7 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
        if (ipcperms(ns, &sma->sem_perm, S_IRUGO))
                goto out_unlock;
 
-       err = security_sem_semctl(sma, cmd);
+       err = security_sem_semctl(&sma->sem_perm, cmd);
        if (err)
                goto out_unlock;
 
@@ -1305,7 +1330,7 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
                return -EACCES;
        }
 
-       err = security_sem_semctl(sma, SETVAL);
+       err = security_sem_semctl(&sma->sem_perm, SETVAL);
        if (err) {
                rcu_read_unlock();
                return -EACCES;
@@ -1326,7 +1351,7 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
                un->semadj[semnum] = 0;
 
        curr->semval = val;
-       curr->sempid = task_tgid_vnr(current);
+       ipc_update_pid(&curr->sempid, task_tgid(current));
        sma->sem_ctime = ktime_get_real_seconds();
        /* maybe some queued-up processes were waiting for this */
        do_smart_update(sma, NULL, 0, 0, &wake_q);
@@ -1359,7 +1384,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
        if (ipcperms(ns, &sma->sem_perm, cmd == SETALL ? S_IWUGO : S_IRUGO))
                goto out_rcu_wakeup;
 
-       err = security_sem_semctl(sma, cmd);
+       err = security_sem_semctl(&sma->sem_perm, cmd);
        if (err)
                goto out_rcu_wakeup;
 
@@ -1447,7 +1472,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
 
                for (i = 0; i < nsems; i++) {
                        sma->sems[i].semval = sem_io[i];
-                       sma->sems[i].sempid = task_tgid_vnr(current);
+                       ipc_update_pid(&sma->sems[i].sempid, task_tgid(current));
                }
 
                ipc_assert_locked_object(&sma->sem_perm);
@@ -1479,7 +1504,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                err = curr->semval;
                goto out_unlock;
        case GETPID:
-               err = curr->sempid;
+               err = pid_vnr(curr->sempid);
                goto out_unlock;
        case GETNCNT:
                err = count_semcnt(sma, semnum, 0);
@@ -1550,7 +1575,7 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
 
        sma = container_of(ipcp, struct sem_array, sem_perm);
 
-       err = security_sem_semctl(sma, cmd);
+       err = security_sem_semctl(&sma->sem_perm, cmd);
        if (err)
                goto out_unlock1;
 
@@ -1977,7 +2002,7 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
                goto out_free;
        }
 
-       error = security_sem_semop(sma, sops, nsops, alter);
+       error = security_sem_semop(&sma->sem_perm, sops, nsops, alter);
        if (error) {
                rcu_read_unlock();
                goto out_free;
@@ -2008,7 +2033,7 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
        queue.sops = sops;
        queue.nsops = nsops;
        queue.undo = un;
-       queue.pid = task_tgid_vnr(current);
+       queue.pid = task_tgid(current);
        queue.alter = alter;
        queue.dupsop = dupsop;
 
@@ -2315,7 +2340,7 @@ void exit_sem(struct task_struct *tsk)
                                        semaphore->semval = 0;
                                if (semaphore->semval > SEMVMX)
                                        semaphore->semval = SEMVMX;
-                               semaphore->sempid = task_tgid_vnr(current);
+                               ipc_update_pid(&semaphore->sempid, task_tgid(current));
                        }
                }
                /* maybe some queued-up processes were waiting for this */
index c38c8425a89eef2afcfabadaade095e8f19ffbf1..acefe44fefefa187c838c3830d944b5d3a4c047d 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
 
 #include "util.h"
 
+struct shmid_kernel /* private to the kernel */
+{
+       struct kern_ipc_perm    shm_perm;
+       struct file             *shm_file;
+       unsigned long           shm_nattch;
+       unsigned long           shm_segsz;
+       time64_t                shm_atim;
+       time64_t                shm_dtim;
+       time64_t                shm_ctim;
+       struct pid              *shm_cprid;
+       struct pid              *shm_lprid;
+       struct user_struct      *mlock_user;
+
+       /* The task created the shm object.  NULL if the task is dead. */
+       struct task_struct      *shm_creator;
+       struct list_head        shm_clist;      /* list by creator */
+} __randomize_layout;
+
+/* shm_mode upper byte flags */
+#define SHM_DEST       01000   /* segment will be destroyed on last detach */
+#define SHM_LOCKED     02000   /* segment will not be swapped */
+
 struct shm_file_data {
        int id;
        struct ipc_namespace *ns;
@@ -181,7 +203,7 @@ static void shm_rcu_free(struct rcu_head *head)
                                                        rcu);
        struct shmid_kernel *shp = container_of(ptr, struct shmid_kernel,
                                                        shm_perm);
-       security_shm_free(shp);
+       security_shm_free(&shp->shm_perm);
        kvfree(shp);
 }
 
@@ -204,7 +226,7 @@ static int __shm_open(struct vm_area_struct *vma)
                return PTR_ERR(shp);
 
        shp->shm_atim = ktime_get_real_seconds();
-       shp->shm_lprid = task_tgid_vnr(current);
+       ipc_update_pid(&shp->shm_lprid, task_tgid(current));
        shp->shm_nattch++;
        shm_unlock(shp);
        return 0;
@@ -245,6 +267,8 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
                user_shm_unlock(i_size_read(file_inode(shm_file)),
                                shp->mlock_user);
        fput(shm_file);
+       ipc_update_pid(&shp->shm_cprid, NULL);
+       ipc_update_pid(&shp->shm_lprid, NULL);
        ipc_rcu_putref(&shp->shm_perm, shm_rcu_free);
 }
 
@@ -289,7 +313,7 @@ static void shm_close(struct vm_area_struct *vma)
        if (WARN_ON_ONCE(IS_ERR(shp)))
                goto done; /* no-op */
 
-       shp->shm_lprid = task_tgid_vnr(current);
+       ipc_update_pid(&shp->shm_lprid, task_tgid(current));
        shp->shm_dtim = ktime_get_real_seconds();
        shp->shm_nattch--;
        if (shm_may_destroy(ns, shp))
@@ -566,7 +590,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        shp->mlock_user = NULL;
 
        shp->shm_perm.security = NULL;
-       error = security_shm_alloc(shp);
+       error = security_shm_alloc(&shp->shm_perm);
        if (error) {
                kvfree(shp);
                return error;
@@ -604,8 +628,8 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        if (IS_ERR(file))
                goto no_file;
 
-       shp->shm_cprid = task_tgid_vnr(current);
-       shp->shm_lprid = 0;
+       shp->shm_cprid = get_pid(task_tgid(current));
+       shp->shm_lprid = NULL;
        shp->shm_atim = shp->shm_dtim = 0;
        shp->shm_ctim = ktime_get_real_seconds();
        shp->shm_segsz = size;
@@ -634,6 +658,8 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        return error;
 
 no_id:
+       ipc_update_pid(&shp->shm_cprid, NULL);
+       ipc_update_pid(&shp->shm_lprid, NULL);
        if (is_file_hugepages(file) && shp->mlock_user)
                user_shm_unlock(size, shp->mlock_user);
        fput(file);
@@ -642,17 +668,6 @@ no_file:
        return error;
 }
 
-/*
- * Called with shm_ids.rwsem and ipcp locked.
- */
-static inline int shm_security(struct kern_ipc_perm *ipcp, int shmflg)
-{
-       struct shmid_kernel *shp;
-
-       shp = container_of(ipcp, struct shmid_kernel, shm_perm);
-       return security_shm_associate(shp, shmflg);
-}
-
 /*
  * Called with shm_ids.rwsem and ipcp locked.
  */
@@ -673,7 +688,7 @@ long ksys_shmget(key_t key, size_t size, int shmflg)
        struct ipc_namespace *ns;
        static const struct ipc_ops shm_ops = {
                .getnew = newseg,
-               .associate = shm_security,
+               .associate = security_shm_associate,
                .more_checks = shm_more_checks,
        };
        struct ipc_params shm_params;
@@ -852,7 +867,7 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
 
        shp = container_of(ipcp, struct shmid_kernel, shm_perm);
 
-       err = security_shm_shmctl(shp, cmd);
+       err = security_shm_shmctl(&shp->shm_perm, cmd);
        if (err)
                goto out_unlock1;
 
@@ -951,7 +966,7 @@ static int shmctl_stat(struct ipc_namespace *ns, int shmid,
        if (ipcperms(ns, &shp->shm_perm, S_IRUGO))
                goto out_unlock;
 
-       err = security_shm_shmctl(shp, cmd);
+       err = security_shm_shmctl(&shp->shm_perm, cmd);
        if (err)
                goto out_unlock;
 
@@ -968,8 +983,8 @@ static int shmctl_stat(struct ipc_namespace *ns, int shmid,
        tbuf->shm_atime = shp->shm_atim;
        tbuf->shm_dtime = shp->shm_dtim;
        tbuf->shm_ctime = shp->shm_ctim;
-       tbuf->shm_cpid  = shp->shm_cprid;
-       tbuf->shm_lpid  = shp->shm_lprid;
+       tbuf->shm_cpid  = pid_vnr(shp->shm_cprid);
+       tbuf->shm_lpid  = pid_vnr(shp->shm_lprid);
        tbuf->shm_nattch = shp->shm_nattch;
 
        ipc_unlock_object(&shp->shm_perm);
@@ -995,7 +1010,7 @@ static int shmctl_do_lock(struct ipc_namespace *ns, int shmid, int cmd)
        }
 
        audit_ipc_obj(&(shp->shm_perm));
-       err = security_shm_shmctl(shp, cmd);
+       err = security_shm_shmctl(&shp->shm_perm, cmd);
        if (err)
                goto out_unlock1;
 
@@ -1375,7 +1390,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
        if (ipcperms(ns, &shp->shm_perm, acc_mode))
                goto out_unlock;
 
-       err = security_shm_shmat(shp, shmaddr, shmflg);
+       err = security_shm_shmat(&shp->shm_perm, shmaddr, shmflg);
        if (err)
                goto out_unlock;
 
@@ -1618,6 +1633,7 @@ SYSCALL_DEFINE1(shmdt, char __user *, shmaddr)
 #ifdef CONFIG_PROC_FS
 static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
 {
+       struct pid_namespace *pid_ns = ipc_seq_pid_ns(s);
        struct user_namespace *user_ns = seq_user_ns(s);
        struct kern_ipc_perm *ipcp = it;
        struct shmid_kernel *shp;
@@ -1640,8 +1656,8 @@ static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
                   shp->shm_perm.id,
                   shp->shm_perm.mode,
                   shp->shm_segsz,
-                  shp->shm_cprid,
-                  shp->shm_lprid,
+                  pid_nr_ns(shp->shm_cprid, pid_ns),
+                  pid_nr_ns(shp->shm_lprid, pid_ns),
                   shp->shm_nattch,
                   from_kuid_munged(user_ns, shp->shm_perm.uid),
                   from_kgid_munged(user_ns, shp->shm_perm.gid),
index 4ed5a17dd06fea5416baedbdcda205f5c3a3b3ff..3783b7991cc7e2b10745d36d933f66f5fd68bcda 100644 (file)
@@ -747,9 +747,16 @@ int ipc_parse_version(int *cmd)
 #ifdef CONFIG_PROC_FS
 struct ipc_proc_iter {
        struct ipc_namespace *ns;
+       struct pid_namespace *pid_ns;
        struct ipc_proc_iface *iface;
 };
 
+struct pid_namespace *ipc_seq_pid_ns(struct seq_file *s)
+{
+       struct ipc_proc_iter *iter = s->private;
+       return iter->pid_ns;
+}
+
 /*
  * This routine locks the ipc structure found at least at position pos.
  */
@@ -872,6 +879,7 @@ static int sysvipc_proc_open(struct inode *inode, struct file *file)
 
        iter->iface = PDE_DATA(inode);
        iter->ns    = get_ipc_ns(current->nsproxy->ipc_ns);
+       iter->pid_ns = get_pid_ns(task_active_pid_ns(current));
 
        return 0;
 }
@@ -881,6 +889,7 @@ static int sysvipc_proc_release(struct inode *inode, struct file *file)
        struct seq_file *seq = file->private_data;
        struct ipc_proc_iter *iter = seq->private;
        put_ipc_ns(iter->ns);
+       put_pid_ns(iter->pid_ns);
        return seq_release_private(inode, file);
 }
 
index 51853dc2f340b9364ff5b79f52bdad1137dcefab..acc5159e96d058cb8caa12fc5066ebd0676bc376 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/err.h>
 #include <linux/ipc_namespace.h>
 
+#define IPCMNI 32768  /* <= MAX_INT limit for ipc arrays (including sysctl changes) */
 #define SEQ_MULTIPLIER (IPCMNI)
 
 int sem_init(void);
@@ -22,6 +23,7 @@ int msg_init(void);
 void shm_init(void);
 
 struct ipc_namespace;
+struct pid_namespace;
 
 #ifdef CONFIG_POSIX_MQUEUE
 extern void mq_clear_sbinfo(struct ipc_namespace *ns);
@@ -85,6 +87,7 @@ int ipc_init_ids(struct ipc_ids *);
 #ifdef CONFIG_PROC_FS
 void __init ipc_init_proc_interface(const char *path, const char *header,
                int ids, int (*show)(struct seq_file *, void *));
+struct pid_namespace *ipc_seq_pid_ns(struct seq_file *);
 #else
 #define ipc_init_proc_interface(path, header, ids, show) do {} while (0)
 #endif
@@ -149,6 +152,15 @@ struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
                                             struct ipc_ids *ids, int id, int cmd,
                                             struct ipc64_perm *perm, int extra_perm);
 
+static inline void ipc_update_pid(struct pid **pos, struct pid *pid)
+{
+       struct pid *old = *pos;
+       if (old != pid) {
+               *pos = get_pid(pid);
+               put_pid(old);
+       }
+}
+
 #ifndef CONFIG_ARCH_WANT_IPC_PARSE_VERSION
 /* On IA-64, we always use the "64-bit version" of the IPC structures.  */
 # define ipc_parse_version(cmd)        IPC_64
index 93b57f02668862a1c22f54074065e4aa1ad9ce9e..2a2ac53d8b8bb845f25581b549a1ea4136564692 100644 (file)
 #include <linux/sched/signal.h>
 #include <linux/idr.h>
 
-struct pid_cache {
-       int nr_ids;
-       char name[16];
-       struct kmem_cache *cachep;
-       struct list_head list;
-};
-
-static LIST_HEAD(pid_caches_lh);
 static DEFINE_MUTEX(pid_caches_mutex);
 static struct kmem_cache *pid_ns_cachep;
+/* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */
+#define MAX_PID_NS_LEVEL 32
+/* Write once array, filled from the beginning. */
+static struct kmem_cache *pid_cache[MAX_PID_NS_LEVEL];
 
 /*
  * creates the kmem cache to allocate pids from.
- * @nr_ids: the number of numerical ids this pid will have to carry
+ * @level: pid namespace level
  */
 
-static struct kmem_cache *create_pid_cachep(int nr_ids)
+static struct kmem_cache *create_pid_cachep(unsigned int level)
 {
-       struct pid_cache *pcache;
-       struct kmem_cache *cachep;
-
+       /* Level 0 is init_pid_ns.pid_cachep */
+       struct kmem_cache **pkc = &pid_cache[level - 1];
+       struct kmem_cache *kc;
+       char name[4 + 10 + 1];
+       unsigned int len;
+
+       kc = READ_ONCE(*pkc);
+       if (kc)
+               return kc;
+
+       snprintf(name, sizeof(name), "pid_%u", level + 1);
+       len = sizeof(struct pid) + level * sizeof(struct upid);
        mutex_lock(&pid_caches_mutex);
-       list_for_each_entry(pcache, &pid_caches_lh, list)
-               if (pcache->nr_ids == nr_ids)
-                       goto out;
-
-       pcache = kmalloc(sizeof(struct pid_cache), GFP_KERNEL);
-       if (pcache == NULL)
-               goto err_alloc;
-
-       snprintf(pcache->name, sizeof(pcache->name), "pid_%d", nr_ids);
-       cachep = kmem_cache_create(pcache->name,
-                       sizeof(struct pid) + (nr_ids - 1) * sizeof(struct upid),
-                       0, SLAB_HWCACHE_ALIGN, NULL);
-       if (cachep == NULL)
-               goto err_cachep;
-
-       pcache->nr_ids = nr_ids;
-       pcache->cachep = cachep;
-       list_add(&pcache->list, &pid_caches_lh);
-out:
+       /* Name collision forces to do allocation under mutex. */
+       if (!*pkc)
+               *pkc = kmem_cache_create(name, len, 0, SLAB_HWCACHE_ALIGN, 0);
        mutex_unlock(&pid_caches_mutex);
-       return pcache->cachep;
-
-err_cachep:
-       kfree(pcache);
-err_alloc:
-       mutex_unlock(&pid_caches_mutex);
-       return NULL;
+       /* current can fail, but someone else can succeed. */
+       return READ_ONCE(*pkc);
 }
 
 static void proc_cleanup_work(struct work_struct *work)
@@ -80,9 +64,6 @@ static void proc_cleanup_work(struct work_struct *work)
        pid_ns_release_proc(ns);
 }
 
-/* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */
-#define MAX_PID_NS_LEVEL 32
-
 static struct ucounts *inc_pid_namespaces(struct user_namespace *ns)
 {
        return inc_ucount(ns, current_euid(), UCOUNT_PID_NAMESPACES);
@@ -119,7 +100,7 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns
 
        idr_init(&ns->idr);
 
-       ns->pid_cachep = create_pid_cachep(level + 1);
+       ns->pid_cachep = create_pid_cachep(level);
        if (ns->pid_cachep == NULL)
                goto out_free_idr;
 
index 1cd8526cb0b775647fe567a6910cc7b811cff21a..02d734e6995595606dd9e9fefbf8a27165506bef 100644 (file)
@@ -1163,84 +1163,84 @@ void security_msg_msg_free(struct msg_msg *msg)
        call_void_hook(msg_msg_free_security, msg);
 }
 
-int security_msg_queue_alloc(struct msg_queue *msq)
+int security_msg_queue_alloc(struct kern_ipc_perm *msq)
 {
        return call_int_hook(msg_queue_alloc_security, 0, msq);
 }
 
-void security_msg_queue_free(struct msg_queue *msq)
+void security_msg_queue_free(struct kern_ipc_perm *msq)
 {
        call_void_hook(msg_queue_free_security, msq);
 }
 
-int security_msg_queue_associate(struct msg_queue *msq, int msqflg)
+int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
 {
        return call_int_hook(msg_queue_associate, 0, msq, msqflg);
 }
 
-int security_msg_queue_msgctl(struct msg_queue *msq, int cmd)
+int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
 {
        return call_int_hook(msg_queue_msgctl, 0, msq, cmd);
 }
 
-int security_msg_queue_msgsnd(struct msg_queue *msq,
+int security_msg_queue_msgsnd(struct kern_ipc_perm *msq,
                               struct msg_msg *msg, int msqflg)
 {
        return call_int_hook(msg_queue_msgsnd, 0, msq, msg, msqflg);
 }
 
-int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
+int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
                               struct task_struct *target, long type, int mode)
 {
        return call_int_hook(msg_queue_msgrcv, 0, msq, msg, target, type, mode);
 }
 
-int security_shm_alloc(struct shmid_kernel *shp)
+int security_shm_alloc(struct kern_ipc_perm *shp)
 {
        return call_int_hook(shm_alloc_security, 0, shp);
 }
 
-void security_shm_free(struct shmid_kernel *shp)
+void security_shm_free(struct kern_ipc_perm *shp)
 {
        call_void_hook(shm_free_security, shp);
 }
 
-int security_shm_associate(struct shmid_kernel *shp, int shmflg)
+int security_shm_associate(struct kern_ipc_perm *shp, int shmflg)
 {
        return call_int_hook(shm_associate, 0, shp, shmflg);
 }
 
-int security_shm_shmctl(struct shmid_kernel *shp, int cmd)
+int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
 {
        return call_int_hook(shm_shmctl, 0, shp, cmd);
 }
 
-int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg)
+int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg)
 {
        return call_int_hook(shm_shmat, 0, shp, shmaddr, shmflg);
 }
 
-int security_sem_alloc(struct sem_array *sma)
+int security_sem_alloc(struct kern_ipc_perm *sma)
 {
        return call_int_hook(sem_alloc_security, 0, sma);
 }
 
-void security_sem_free(struct sem_array *sma)
+void security_sem_free(struct kern_ipc_perm *sma)
 {
        call_void_hook(sem_free_security, sma);
 }
 
-int security_sem_associate(struct sem_array *sma, int semflg)
+int security_sem_associate(struct kern_ipc_perm *sma, int semflg)
 {
        return call_int_hook(sem_associate, 0, sma, semflg);
 }
 
-int security_sem_semctl(struct sem_array *sma, int cmd)
+int security_sem_semctl(struct kern_ipc_perm *sma, int cmd)
 {
        return call_int_hook(sem_semctl, 0, sma, cmd);
 }
 
-int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
+int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
                        unsigned nsops, int alter)
 {
        return call_int_hook(sem_semop, 0, sma, sops, nsops, alter);
index 8644d864e3c196ca3dc8a10cb84c2daa97e3a596..925e546b5a873941fa5f5180cecdb47060c4c1cb 100644 (file)
@@ -5532,52 +5532,52 @@ static void selinux_msg_msg_free_security(struct msg_msg *msg)
 }
 
 /* message queue security operations */
-static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
+static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
        u32 sid = current_sid();
        int rc;
 
-       rc = ipc_alloc_security(&msq->q_perm, SECCLASS_MSGQ);
+       rc = ipc_alloc_security(msq, SECCLASS_MSGQ);
        if (rc)
                return rc;
 
-       isec = msq->q_perm.security;
+       isec = msq->security;
 
        ad.type = LSM_AUDIT_DATA_IPC;
-       ad.u.ipc_id = msq->q_perm.key;
+       ad.u.ipc_id = msq->key;
 
        rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
                          MSGQ__CREATE, &ad);
        if (rc) {
-               ipc_free_security(&msq->q_perm);
+               ipc_free_security(msq);
                return rc;
        }
        return 0;
 }
 
-static void selinux_msg_queue_free_security(struct msg_queue *msq)
+static void selinux_msg_queue_free_security(struct kern_ipc_perm *msq)
 {
-       ipc_free_security(&msq->q_perm);
+       ipc_free_security(msq);
 }
 
-static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
+static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
        u32 sid = current_sid();
 
-       isec = msq->q_perm.security;
+       isec = msq->security;
 
        ad.type = LSM_AUDIT_DATA_IPC;
-       ad.u.ipc_id = msq->q_perm.key;
+       ad.u.ipc_id = msq->key;
 
        return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
                            MSGQ__ASSOCIATE, &ad);
 }
 
-static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
+static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
 {
        int err;
        int perms;
@@ -5602,11 +5602,11 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
                return 0;
        }
 
-       err = ipc_has_perm(&msq->q_perm, perms);
+       err = ipc_has_perm(msq, perms);
        return err;
 }
 
-static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
+static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg)
 {
        struct ipc_security_struct *isec;
        struct msg_security_struct *msec;
@@ -5614,7 +5614,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
        u32 sid = current_sid();
        int rc;
 
-       isec = msq->q_perm.security;
+       isec = msq->security;
        msec = msg->security;
 
        /*
@@ -5632,7 +5632,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
        }
 
        ad.type = LSM_AUDIT_DATA_IPC;
-       ad.u.ipc_id = msq->q_perm.key;
+       ad.u.ipc_id = msq->key;
 
        /* Can this process write to the queue? */
        rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
@@ -5649,7 +5649,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
        return rc;
 }
 
-static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
+static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
                                    struct task_struct *target,
                                    long type, int mode)
 {
@@ -5659,11 +5659,11 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
        u32 sid = task_sid(target);
        int rc;
 
-       isec = msq->q_perm.security;
+       isec = msq->security;
        msec = msg->security;
 
        ad.type = LSM_AUDIT_DATA_IPC;
-       ad.u.ipc_id = msq->q_perm.key;
+       ad.u.ipc_id = msq->key;
 
        rc = avc_has_perm(sid, isec->sid,
                          SECCLASS_MSGQ, MSGQ__READ, &ad);
@@ -5674,53 +5674,53 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
 }
 
 /* Shared Memory security operations */
-static int selinux_shm_alloc_security(struct shmid_kernel *shp)
+static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
        u32 sid = current_sid();
        int rc;
 
-       rc = ipc_alloc_security(&shp->shm_perm, SECCLASS_SHM);
+       rc = ipc_alloc_security(shp, SECCLASS_SHM);
        if (rc)
                return rc;
 
-       isec = shp->shm_perm.security;
+       isec = shp->security;
 
        ad.type = LSM_AUDIT_DATA_IPC;
-       ad.u.ipc_id = shp->shm_perm.key;
+       ad.u.ipc_id = shp->key;
 
        rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
                          SHM__CREATE, &ad);
        if (rc) {
-               ipc_free_security(&shp->shm_perm);
+               ipc_free_security(shp);
                return rc;
        }
        return 0;
 }
 
-static void selinux_shm_free_security(struct shmid_kernel *shp)
+static void selinux_shm_free_security(struct kern_ipc_perm *shp)
 {
-       ipc_free_security(&shp->shm_perm);
+       ipc_free_security(shp);
 }
 
-static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
+static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
        u32 sid = current_sid();
 
-       isec = shp->shm_perm.security;
+       isec = shp->security;
 
        ad.type = LSM_AUDIT_DATA_IPC;
-       ad.u.ipc_id = shp->shm_perm.key;
+       ad.u.ipc_id = shp->key;
 
        return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
                            SHM__ASSOCIATE, &ad);
 }
 
 /* Note, at this point, shp is locked down */
-static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
+static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
 {
        int perms;
        int err;
@@ -5749,11 +5749,11 @@ static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
                return 0;
        }
 
-       err = ipc_has_perm(&shp->shm_perm, perms);
+       err = ipc_has_perm(shp, perms);
        return err;
 }
 
-static int selinux_shm_shmat(struct shmid_kernel *shp,
+static int selinux_shm_shmat(struct kern_ipc_perm *shp,
                             char __user *shmaddr, int shmflg)
 {
        u32 perms;
@@ -5763,57 +5763,57 @@ static int selinux_shm_shmat(struct shmid_kernel *shp,
        else
                perms = SHM__READ | SHM__WRITE;
 
-       return ipc_has_perm(&shp->shm_perm, perms);
+       return ipc_has_perm(shp, perms);
 }
 
 /* Semaphore security operations */
-static int selinux_sem_alloc_security(struct sem_array *sma)
+static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
        u32 sid = current_sid();
        int rc;
 
-       rc = ipc_alloc_security(&sma->sem_perm, SECCLASS_SEM);
+       rc = ipc_alloc_security(sma, SECCLASS_SEM);
        if (rc)
                return rc;
 
-       isec = sma->sem_perm.security;
+       isec = sma->security;
 
        ad.type = LSM_AUDIT_DATA_IPC;
-       ad.u.ipc_id = sma->sem_perm.key;
+       ad.u.ipc_id = sma->key;
 
        rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
                          SEM__CREATE, &ad);
        if (rc) {
-               ipc_free_security(&sma->sem_perm);
+               ipc_free_security(sma);
                return rc;
        }
        return 0;
 }
 
-static void selinux_sem_free_security(struct sem_array *sma)
+static void selinux_sem_free_security(struct kern_ipc_perm *sma)
 {
-       ipc_free_security(&sma->sem_perm);
+       ipc_free_security(sma);
 }
 
-static int selinux_sem_associate(struct sem_array *sma, int semflg)
+static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
        u32 sid = current_sid();
 
-       isec = sma->sem_perm.security;
+       isec = sma->security;
 
        ad.type = LSM_AUDIT_DATA_IPC;
-       ad.u.ipc_id = sma->sem_perm.key;
+       ad.u.ipc_id = sma->key;
 
        return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
                            SEM__ASSOCIATE, &ad);
 }
 
 /* Note, at this point, sma is locked down */
-static int selinux_sem_semctl(struct sem_array *sma, int cmd)
+static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd)
 {
        int err;
        u32 perms;
@@ -5851,11 +5851,11 @@ static int selinux_sem_semctl(struct sem_array *sma, int cmd)
                return 0;
        }
 
-       err = ipc_has_perm(&sma->sem_perm, perms);
+       err = ipc_has_perm(sma, perms);
        return err;
 }
 
-static int selinux_sem_semop(struct sem_array *sma,
+static int selinux_sem_semop(struct kern_ipc_perm *sma,
                             struct sembuf *sops, unsigned nsops, int alter)
 {
        u32 perms;
@@ -5865,7 +5865,7 @@ static int selinux_sem_semop(struct sem_array *sma,
        else
                perms = SEM__READ;
 
-       return ipc_has_perm(&sma->sem_perm, perms);
+       return ipc_has_perm(sma, perms);
 }
 
 static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
index 03fdecba93bb2b238d91e0e29efa0783c7e84b72..0735b8db158b7ba0fd3d4b61fcd81df63a639f68 100644 (file)
@@ -2945,25 +2945,24 @@ static void smack_msg_msg_free_security(struct msg_msg *msg)
 }
 
 /**
- * smack_of_shm - the smack pointer for the shm
- * @shp: the object
+ * smack_of_ipc - the smack pointer for the ipc
+ * @isp: the object
  *
  * Returns a pointer to the smack value
  */
-static struct smack_known *smack_of_shm(struct shmid_kernel *shp)
+static struct smack_known *smack_of_ipc(struct kern_ipc_perm *isp)
 {
-       return (struct smack_known *)shp->shm_perm.security;
+       return (struct smack_known *)isp->security;
 }
 
 /**
- * smack_shm_alloc_security - Set the security blob for shm
- * @shp: the object
+ * smack_ipc_alloc_security - Set the security blob for ipc
+ * @isp: the object
  *
  * Returns 0
  */
-static int smack_shm_alloc_security(struct shmid_kernel *shp)
+static int smack_ipc_alloc_security(struct kern_ipc_perm *isp)
 {
-       struct kern_ipc_perm *isp = &shp->shm_perm;
        struct smack_known *skp = smk_of_current();
 
        isp->security = skp;
@@ -2971,34 +2970,32 @@ static int smack_shm_alloc_security(struct shmid_kernel *shp)
 }
 
 /**
- * smack_shm_free_security - Clear the security blob for shm
- * @shp: the object
+ * smack_ipc_free_security - Clear the security blob for ipc
+ * @isp: the object
  *
  * Clears the blob pointer
  */
-static void smack_shm_free_security(struct shmid_kernel *shp)
+static void smack_ipc_free_security(struct kern_ipc_perm *isp)
 {
-       struct kern_ipc_perm *isp = &shp->shm_perm;
-
        isp->security = NULL;
 }
 
 /**
  * smk_curacc_shm : check if current has access on shm
- * @shp : the object
+ * @isp : the object
  * @access : access requested
  *
  * Returns 0 if current has the requested access, error code otherwise
  */
-static int smk_curacc_shm(struct shmid_kernel *shp, int access)
+static int smk_curacc_shm(struct kern_ipc_perm *isp, int access)
 {
-       struct smack_known *ssp = smack_of_shm(shp);
+       struct smack_known *ssp = smack_of_ipc(isp);
        struct smk_audit_info ad;
        int rc;
 
 #ifdef CONFIG_AUDIT
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
-       ad.a.u.ipc_id = shp->shm_perm.id;
+       ad.a.u.ipc_id = isp->id;
 #endif
        rc = smk_curacc(ssp, access, &ad);
        rc = smk_bu_current("shm", ssp, access, rc);
@@ -3007,27 +3004,27 @@ static int smk_curacc_shm(struct shmid_kernel *shp, int access)
 
 /**
  * smack_shm_associate - Smack access check for shm
- * @shp: the object
+ * @isp: the object
  * @shmflg: access requested
  *
  * Returns 0 if current has the requested access, error code otherwise
  */
-static int smack_shm_associate(struct shmid_kernel *shp, int shmflg)
+static int smack_shm_associate(struct kern_ipc_perm *isp, int shmflg)
 {
        int may;
 
        may = smack_flags_to_may(shmflg);
-       return smk_curacc_shm(shp, may);
+       return smk_curacc_shm(isp, may);
 }
 
 /**
  * smack_shm_shmctl - Smack access check for shm
- * @shp: the object
+ * @isp: the object
  * @cmd: what it wants to do
  *
  * Returns 0 if current has the requested access, error code otherwise
  */
-static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)
+static int smack_shm_shmctl(struct kern_ipc_perm *isp, int cmd)
 {
        int may;
 
@@ -3051,81 +3048,42 @@ static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)
        default:
                return -EINVAL;
        }
-       return smk_curacc_shm(shp, may);
+       return smk_curacc_shm(isp, may);
 }
 
 /**
  * smack_shm_shmat - Smack access for shmat
- * @shp: the object
+ * @isp: the object
  * @shmaddr: unused
  * @shmflg: access requested
  *
  * Returns 0 if current has the requested access, error code otherwise
  */
-static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
+static int smack_shm_shmat(struct kern_ipc_perm *ipc, char __user *shmaddr,
                           int shmflg)
 {
        int may;
 
        may = smack_flags_to_may(shmflg);
-       return smk_curacc_shm(shp, may);
-}
-
-/**
- * smack_of_sem - the smack pointer for the sem
- * @sma: the object
- *
- * Returns a pointer to the smack value
- */
-static struct smack_known *smack_of_sem(struct sem_array *sma)
-{
-       return (struct smack_known *)sma->sem_perm.security;
-}
-
-/**
- * smack_sem_alloc_security - Set the security blob for sem
- * @sma: the object
- *
- * Returns 0
- */
-static int smack_sem_alloc_security(struct sem_array *sma)
-{
-       struct kern_ipc_perm *isp = &sma->sem_perm;
-       struct smack_known *skp = smk_of_current();
-
-       isp->security = skp;
-       return 0;
-}
-
-/**
- * smack_sem_free_security - Clear the security blob for sem
- * @sma: the object
- *
- * Clears the blob pointer
- */
-static void smack_sem_free_security(struct sem_array *sma)
-{
-       struct kern_ipc_perm *isp = &sma->sem_perm;
-
-       isp->security = NULL;
+       return smk_curacc_shm(ipc, may);
 }
 
 /**
  * smk_curacc_sem : check if current has access on sem
- * @sma : the object
+ * @isp : the object
  * @access : access requested
  *
  * Returns 0 if current has the requested access, error code otherwise
  */
-static int smk_curacc_sem(struct sem_array *sma, int access)
+static int smk_curacc_sem(struct kern_ipc_perm *isp, int access)
 {
-       struct smack_known *ssp = smack_of_sem(sma);
+       struct smack_known *ssp = smack_of_ipc(isp);
        struct smk_audit_info ad;
        int rc;
 
 #ifdef CONFIG_AUDIT
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
-       ad.a.u.ipc_id = sma->sem_perm.id;
+       ad.a.u.ipc_id = isp->id;
 #endif
        rc = smk_curacc(ssp, access, &ad);
        rc = smk_bu_current("sem", ssp, access, rc);
@@ -3134,27 +3092,27 @@ static int smk_curacc_sem(struct sem_array *sma, int access)
 
 /**
  * smack_sem_associate - Smack access check for sem
- * @sma: the object
+ * @isp: the object
  * @semflg: access requested
  *
  * Returns 0 if current has the requested access, error code otherwise
  */
-static int smack_sem_associate(struct sem_array *sma, int semflg)
+static int smack_sem_associate(struct kern_ipc_perm *isp, int semflg)
 {
        int may;
 
        may = smack_flags_to_may(semflg);
-       return smk_curacc_sem(sma, may);
+       return smk_curacc_sem(isp, may);
 }
 
 /**
  * smack_sem_shmctl - Smack access check for sem
- * @sma: the object
+ * @isp: the object
  * @cmd: what it wants to do
  *
  * Returns 0 if current has the requested access, error code otherwise
  */
-static int smack_sem_semctl(struct sem_array *sma, int cmd)
+static int smack_sem_semctl(struct kern_ipc_perm *isp, int cmd)
 {
        int may;
 
@@ -3184,12 +3142,12 @@ static int smack_sem_semctl(struct sem_array *sma, int cmd)
                return -EINVAL;
        }
 
-       return smk_curacc_sem(sma, may);
+       return smk_curacc_sem(isp, may);
 }
 
 /**
  * smack_sem_semop - Smack checks of semaphore operations
- * @sma: the object
+ * @isp: the object
  * @sops: unused
  * @nsops: unused
  * @alter: unused
@@ -3198,67 +3156,28 @@ static int smack_sem_semctl(struct sem_array *sma, int cmd)
  *
  * Returns 0 if access is allowed, error code otherwise
  */
-static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops,
+static int smack_sem_semop(struct kern_ipc_perm *isp, struct sembuf *sops,
                           unsigned nsops, int alter)
 {
-       return smk_curacc_sem(sma, MAY_READWRITE);
-}
-
-/**
- * smack_msg_alloc_security - Set the security blob for msg
- * @msq: the object
- *
- * Returns 0
- */
-static int smack_msg_queue_alloc_security(struct msg_queue *msq)
-{
-       struct kern_ipc_perm *kisp = &msq->q_perm;
-       struct smack_known *skp = smk_of_current();
-
-       kisp->security = skp;
-       return 0;
-}
-
-/**
- * smack_msg_free_security - Clear the security blob for msg
- * @msq: the object
- *
- * Clears the blob pointer
- */
-static void smack_msg_queue_free_security(struct msg_queue *msq)
-{
-       struct kern_ipc_perm *kisp = &msq->q_perm;
-
-       kisp->security = NULL;
-}
-
-/**
- * smack_of_msq - the smack pointer for the msq
- * @msq: the object
- *
- * Returns a pointer to the smack label entry
- */
-static struct smack_known *smack_of_msq(struct msg_queue *msq)
-{
-       return (struct smack_known *)msq->q_perm.security;
+       return smk_curacc_sem(isp, MAY_READWRITE);
 }
 
 /**
  * smk_curacc_msq : helper to check if current has access on msq
- * @msq : the msq
+ * @isp : the msq
  * @access : access requested
  *
  * return 0 if current has access, error otherwise
  */
-static int smk_curacc_msq(struct msg_queue *msq, int access)
+static int smk_curacc_msq(struct kern_ipc_perm *isp, int access)
 {
-       struct smack_known *msp = smack_of_msq(msq);
+       struct smack_known *msp = smack_of_ipc(isp);
        struct smk_audit_info ad;
        int rc;
 
 #ifdef CONFIG_AUDIT
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
-       ad.a.u.ipc_id = msq->q_perm.id;
+       ad.a.u.ipc_id = isp->id;
 #endif
        rc = smk_curacc(msp, access, &ad);
        rc = smk_bu_current("msq", msp, access, rc);
@@ -3267,27 +3186,27 @@ static int smk_curacc_msq(struct msg_queue *msq, int access)
 
 /**
  * smack_msg_queue_associate - Smack access check for msg_queue
- * @msq: the object
+ * @isp: the object
  * @msqflg: access requested
  *
  * Returns 0 if current has the requested access, error code otherwise
  */
-static int smack_msg_queue_associate(struct msg_queue *msq, int msqflg)
+static int smack_msg_queue_associate(struct kern_ipc_perm *isp, int msqflg)
 {
        int may;
 
        may = smack_flags_to_may(msqflg);
-       return smk_curacc_msq(msq, may);
+       return smk_curacc_msq(isp, may);
 }
 
 /**
  * smack_msg_queue_msgctl - Smack access check for msg_queue
- * @msq: the object
+ * @isp: the object
  * @cmd: what it wants to do
  *
  * Returns 0 if current has the requested access, error code otherwise
  */
-static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)
+static int smack_msg_queue_msgctl(struct kern_ipc_perm *isp, int cmd)
 {
        int may;
 
@@ -3310,29 +3229,29 @@ static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)
                return -EINVAL;
        }
 
-       return smk_curacc_msq(msq, may);
+       return smk_curacc_msq(isp, may);
 }
 
 /**
  * smack_msg_queue_msgsnd - Smack access check for msg_queue
- * @msq: the object
+ * @isp: the object
  * @msg: unused
  * @msqflg: access requested
  *
  * Returns 0 if current has the requested access, error code otherwise
  */
-static int smack_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
+static int smack_msg_queue_msgsnd(struct kern_ipc_perm *isp, struct msg_msg *msg,
                                  int msqflg)
 {
        int may;
 
        may = smack_flags_to_may(msqflg);
-       return smk_curacc_msq(msq, may);
+       return smk_curacc_msq(isp, may);
 }
 
 /**
  * smack_msg_queue_msgsnd - Smack access check for msg_queue
- * @msq: the object
+ * @isp: the object
  * @msg: unused
  * @target: unused
  * @type: unused
@@ -3340,10 +3259,10 @@ static int smack_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
  *
  * Returns 0 if current has read and write access, error code otherwise
  */
-static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
+static int smack_msg_queue_msgrcv(struct kern_ipc_perm *isp, struct msg_msg *msg,
                        struct task_struct *target, long type, int mode)
 {
-       return smk_curacc_msq(msq, MAY_READWRITE);
+       return smk_curacc_msq(isp, MAY_READWRITE);
 }
 
 /**
@@ -4756,21 +4675,21 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(msg_msg_alloc_security, smack_msg_msg_alloc_security),
        LSM_HOOK_INIT(msg_msg_free_security, smack_msg_msg_free_security),
 
-       LSM_HOOK_INIT(msg_queue_alloc_security, smack_msg_queue_alloc_security),
-       LSM_HOOK_INIT(msg_queue_free_security, smack_msg_queue_free_security),
+       LSM_HOOK_INIT(msg_queue_alloc_security, smack_ipc_alloc_security),
+       LSM_HOOK_INIT(msg_queue_free_security, smack_ipc_free_security),
        LSM_HOOK_INIT(msg_queue_associate, smack_msg_queue_associate),
        LSM_HOOK_INIT(msg_queue_msgctl, smack_msg_queue_msgctl),
        LSM_HOOK_INIT(msg_queue_msgsnd, smack_msg_queue_msgsnd),
        LSM_HOOK_INIT(msg_queue_msgrcv, smack_msg_queue_msgrcv),
 
-       LSM_HOOK_INIT(shm_alloc_security, smack_shm_alloc_security),
-       LSM_HOOK_INIT(shm_free_security, smack_shm_free_security),
+       LSM_HOOK_INIT(shm_alloc_security, smack_ipc_alloc_security),
+       LSM_HOOK_INIT(shm_free_security, smack_ipc_free_security),
        LSM_HOOK_INIT(shm_associate, smack_shm_associate),
        LSM_HOOK_INIT(shm_shmctl, smack_shm_shmctl),
        LSM_HOOK_INIT(shm_shmat, smack_shm_shmat),
 
-       LSM_HOOK_INIT(sem_alloc_security, smack_sem_alloc_security),
-       LSM_HOOK_INIT(sem_free_security, smack_sem_free_security),
+       LSM_HOOK_INIT(sem_alloc_security, smack_ipc_alloc_security),
+       LSM_HOOK_INIT(sem_free_security, smack_ipc_free_security),
        LSM_HOOK_INIT(sem_associate, smack_sem_associate),
        LSM_HOOK_INIT(sem_semctl, smack_sem_semctl),
        LSM_HOOK_INIT(sem_semop, smack_sem_semop),