#ifdef __KERNEL__
 #include <linux/spinlock.h>
+#include <linux/uidgid.h>
 
 #define IPCMNI 32768  /* <= MAX_INT limit for ipc arrays (including sysctl changes) */
 
        int             deleted;
        int             id;
        key_t           key;
-       uid_t           uid;
-       gid_t           gid;
-       uid_t           cuid;
-       gid_t           cgid;
+       kuid_t          uid;
+       kgid_t          gid;
+       kuid_t          cuid;
+       kgid_t          cgid;
        umode_t         mode; 
        unsigned long   seq;
        void            *security;
 
 
        # List of kernel pieces that need user namespace work
        # Features
-       depends on SYSVIPC = n
        depends on IMA = n
        depends on EVM = n
        depends on KEYS = n
 
                        goto out_unlock;
                }
 
+               err = ipc_update_perm(&msqid64.msg_perm, ipcp);
+               if (err)
+                       goto out_unlock;
+
                msq->q_qbytes = msqid64.msg_qbytes;
 
-               ipc_update_perm(&msqid64.msg_perm, ipcp);
                msq->q_ctime = get_seconds();
                /* sleeping receivers might be excluded by
                 * stricter permissions.
 #ifdef CONFIG_PROC_FS
 static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
 {
+       struct user_namespace *user_ns = seq_user_ns(s);
        struct msg_queue *msq = it;
 
        return seq_printf(s,
                        msq->q_qnum,
                        msq->q_lspid,
                        msq->q_lrpid,
-                       msq->q_perm.uid,
-                       msq->q_perm.gid,
-                       msq->q_perm.cuid,
-                       msq->q_perm.cgid,
+                       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),
+                       from_kgid_munged(user_ns, msq->q_perm.cgid),
                        msq->q_stime,
                        msq->q_rtime,
                        msq->q_ctime);
 
                freeary(ns, ipcp);
                goto out_up;
        case IPC_SET:
-               ipc_update_perm(&semid64.sem_perm, ipcp);
+               err = ipc_update_perm(&semid64.sem_perm, ipcp);
+               if (err)
+                       goto out_unlock;
                sma->sem_ctime = get_seconds();
                break;
        default:
 #ifdef CONFIG_PROC_FS
 static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
 {
+       struct user_namespace *user_ns = seq_user_ns(s);
        struct sem_array *sma = it;
 
        return seq_printf(s,
                          sma->sem_perm.id,
                          sma->sem_perm.mode,
                          sma->sem_nsems,
-                         sma->sem_perm.uid,
-                         sma->sem_perm.gid,
-                         sma->sem_perm.cuid,
-                         sma->sem_perm.cgid,
+                         from_kuid_munged(user_ns, sma->sem_perm.uid),
+                         from_kgid_munged(user_ns, sma->sem_perm.gid),
+                         from_kuid_munged(user_ns, sma->sem_perm.cuid),
+                         from_kgid_munged(user_ns, sma->sem_perm.cgid),
                          sma->sem_otime,
                          sma->sem_ctime);
 }
 
                do_shm_rmid(ns, ipcp);
                goto out_up;
        case IPC_SET:
-               ipc_update_perm(&shmid64.shm_perm, ipcp);
+               err = ipc_update_perm(&shmid64.shm_perm, ipcp);
+               if (err)
+                       goto out_unlock;
                shp->shm_ctim = get_seconds();
                break;
        default:
                audit_ipc_obj(&(shp->shm_perm));
 
                if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) {
-                       uid_t euid = current_euid();
+                       kuid_t euid = current_euid();
                        err = -EPERM;
-                       if (euid != shp->shm_perm.uid &&
-                           euid != shp->shm_perm.cuid)
+                       if (!uid_eq(euid, shp->shm_perm.uid) &&
+                           !uid_eq(euid, shp->shm_perm.cuid))
                                goto out_unlock;
                        if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK))
                                goto out_unlock;
 #ifdef CONFIG_PROC_FS
 static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
 {
+       struct user_namespace *user_ns = seq_user_ns(s);
        struct shmid_kernel *shp = it;
        unsigned long rss = 0, swp = 0;
 
                          shp->shm_cprid,
                          shp->shm_lprid,
                          shp->shm_nattch,
-                         shp->shm_perm.uid,
-                         shp->shm_perm.gid,
-                         shp->shm_perm.cuid,
-                         shp->shm_perm.cgid,
+                         from_kuid_munged(user_ns, shp->shm_perm.uid),
+                         from_kgid_munged(user_ns, shp->shm_perm.gid),
+                         from_kuid_munged(user_ns, shp->shm_perm.cuid),
+                         from_kgid_munged(user_ns, shp->shm_perm.cgid),
                          shp->shm_atim,
                          shp->shm_dtim,
                          shp->shm_ctim,
 
  
 int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 {
-       uid_t euid;
-       gid_t egid;
+       kuid_t euid;
+       kgid_t egid;
        int id, err;
 
        if (size > IPCMNI)
  
 int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag)
 {
-       uid_t euid = current_euid();
+       kuid_t euid = current_euid();
        int requested_mode, granted_mode;
 
        audit_ipc_obj(ipcp);
        requested_mode = (flag >> 6) | (flag >> 3) | flag;
        granted_mode = ipcp->mode;
-       if (euid == ipcp->cuid ||
-           euid == ipcp->uid)
+       if (uid_eq(euid, ipcp->cuid) ||
+           uid_eq(euid, ipcp->uid))
                granted_mode >>= 6;
        else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid))
                granted_mode >>= 3;
 void kernel_to_ipc64_perm (struct kern_ipc_perm *in, struct ipc64_perm *out)
 {
        out->key        = in->key;
-       out->uid        = in->uid;
-       out->gid        = in->gid;
-       out->cuid       = in->cuid;
-       out->cgid       = in->cgid;
+       out->uid        = from_kuid_munged(current_user_ns(), in->uid);
+       out->gid        = from_kgid_munged(current_user_ns(), in->gid);
+       out->cuid       = from_kuid_munged(current_user_ns(), in->cuid);
+       out->cgid       = from_kgid_munged(current_user_ns(), in->cgid);
        out->mode       = in->mode;
        out->seq        = in->seq;
 }
  * @in:  the permission given as input.
  * @out: the permission of the ipc to set.
  */
-void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
+int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
 {
-       out->uid = in->uid;
-       out->gid = in->gid;
+       kuid_t uid = make_kuid(current_user_ns(), in->uid);
+       kgid_t gid = make_kgid(current_user_ns(), in->gid);
+       if (!uid_valid(uid) || !gid_valid(gid))
+               return -EINVAL;
+
+       out->uid = uid;
+       out->gid = gid;
        out->mode = (out->mode & ~S_IRWXUGO)
                | (in->mode & S_IRWXUGO);
+
+       return 0;
 }
 
 /**
                                      struct ipc64_perm *perm, int extra_perm)
 {
        struct kern_ipc_perm *ipcp;
-       uid_t euid;
+       kuid_t euid;
        int err;
 
        down_write(&ids->rw_mutex);
                                         perm->gid, perm->mode);
 
        euid = current_euid();
-       if (euid == ipcp->cuid || euid == ipcp->uid  ||
+       if (uid_eq(euid, ipcp->cuid) || uid_eq(euid, ipcp->uid)  ||
            ns_capable(ns->user_ns, CAP_SYS_ADMIN))
                return ipcp;
 
 
 
 void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
 void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);
-void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out);
+int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out);
 struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
                                      struct ipc_ids *ids, int id, int cmd,
                                      struct ipc64_perm *perm, int extra_perm);