Author: brooks
Date: Mon Feb 12 18:40:19 2018
New Revision: 329177
URL: https://svnweb.freebsd.org/changeset/base/329177

Log:
  MFC r328799:
  
  Add kern.ipc.{msqids,semsegs,sema} sysctls for FreeBSD32.
  
  Stop leaking kernel pointers though theses sysctls and make sure that the
  padding in the structures is zeroed on allocation to avoid other leaks.
  
  Reviewed by:  gordon, kib
  Obtained from:        CheriBSD
  Sponsored by: DARPA, AFRL
  Differential Revision:        https://reviews.freebsd.org/D13459

Modified:
  stable/11/sys/compat/freebsd32/freebsd32_ipc.h
  stable/11/sys/kern/sysv_msg.c
  stable/11/sys/kern/sysv_sem.c
  stable/11/sys/kern/sysv_shm.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/compat/freebsd32/freebsd32_ipc.h
==============================================================================
--- stable/11/sys/compat/freebsd32/freebsd32_ipc.h      Mon Feb 12 18:30:20 
2018        (r329176)
+++ stable/11/sys/compat/freebsd32/freebsd32_ipc.h      Mon Feb 12 18:40:19 
2018        (r329177)
@@ -47,6 +47,18 @@ struct semid_ds32 {
        int32_t         sem_ctime;
 };
 
+#ifdef _KERNEL
+struct semid_kernel32 {
+       /* Data structure exposed to user space. */
+       struct semid_ds32       u;
+
+       /* Kernel-private components of the semaphore. */
+       int32_t                 label;
+       int32_t                 cred;
+};
+#endif /* _KERNEL */
+
+
 union semun32 {
        int             val;
        uint32_t        buf;
@@ -67,6 +79,17 @@ struct msqid_ds32 {
        int32_t         msg_ctime;
 };
 
+#ifdef _KERNEL
+struct msqid_kernel32 {
+       /* Data structure exposed to user space. */
+       struct msqid_ds32       u;
+
+       /* Kernel-private components of the message queue. */
+       uint32_t                label;
+       uint32_t                cred;
+};
+#endif
+
 struct shmid_ds32 {
        struct ipc_perm32 shm_perm;
        int32_t         shm_segsz;
@@ -77,6 +100,15 @@ struct shmid_ds32 {
        int32_t         shm_dtime;
        int32_t         shm_ctime;
 };
+
+#ifdef _KERNEL
+struct shmid_kernel32 {
+       struct shmid_ds32        u;
+       int32_t                 *object;
+       int32_t                 *label;
+       int32_t                 *cred;
+};
+#endif
 
 struct shm_info32 {
        int32_t         used_ids;

Modified: stable/11/sys/kern/sysv_msg.c
==============================================================================
--- stable/11/sys/kern/sysv_msg.c       Mon Feb 12 18:30:20 2018        
(r329176)
+++ stable/11/sys/kern/sysv_msg.c       Mon Feb 12 18:40:19 2018        
(r329177)
@@ -220,7 +220,7 @@ msginit()
        msgmaps = malloc(sizeof(struct msgmap) * msginfo.msgseg, M_MSG, 
M_WAITOK);
        msghdrs = malloc(sizeof(struct msg) * msginfo.msgtql, M_MSG, M_WAITOK);
        msqids = malloc(sizeof(struct msqid_kernel) * msginfo.msgmni, M_MSG,
-           M_WAITOK);
+           M_WAITOK | M_ZERO);
 
        /*
         * msginfo.msgssz should be a power of two for efficiency reasons.
@@ -1417,7 +1417,12 @@ static int
 sysctl_msqids(SYSCTL_HANDLER_ARGS)
 {
        struct msqid_kernel tmsqk;
+#ifdef COMPAT_FREEBSD32
+       struct msqid_kernel32 tmsqk32;
+#endif
        struct prison *pr, *rpr;
+       void *outaddr;
+       size_t outsize;
        int error, i;
 
        pr = req->td->td_ucred->cr_prison;
@@ -1434,7 +1439,40 @@ sysctl_msqids(SYSCTL_HANDLER_ARGS)
                                tmsqk.u.msg_perm.key = IPC_PRIVATE;
                }
                mtx_unlock(&msq_mtx);
-               error = SYSCTL_OUT(req, &tmsqk, sizeof(tmsqk));
+#ifdef COMPAT_FREEBSD32
+               if (SV_CURPROC_FLAG(SV_ILP32)) {
+                       bzero(&tmsqk32, sizeof(tmsqk32));
+                       freebsd32_ipcperm_out(&tmsqk.u.msg_perm,
+                           &tmsqk32.u.msg_perm);
+                       /* Don't copy u.msg_first or u.msg_last */
+                       CP(tmsqk, tmsqk32, u.msg_cbytes);
+                       CP(tmsqk, tmsqk32, u.msg_qnum);
+                       CP(tmsqk, tmsqk32, u.msg_qbytes);
+                       CP(tmsqk, tmsqk32, u.msg_lspid);
+                       CP(tmsqk, tmsqk32, u.msg_lrpid);
+                       CP(tmsqk, tmsqk32, u.msg_stime);
+                       CP(tmsqk, tmsqk32, u.msg_rtime);
+                       CP(tmsqk, tmsqk32, u.msg_ctime);
+                       /* Don't copy label or cred */
+                       outaddr = &tmsqk32;
+                       outsize = sizeof(tmsqk32);
+               } else
+#endif
+               {
+                       /* Don't leak kernel pointers */
+                       tmsqk.u.msg_first = NULL;
+                       tmsqk.u.msg_last = NULL;
+                       tmsqk.label = NULL;
+                       tmsqk.cred = NULL;
+                       /*
+                        * XXX: some padding also exists, but we take care to
+                        * allocate our pool of msqid_kernel structs with
+                        * zeroed memory so this should be OK.
+                        */
+                       outaddr = &tmsqk;
+                       outsize = sizeof(tmsqk);
+               }
+               error = SYSCTL_OUT(req, outaddr, outsize);
                if (error != 0)
                        break;
        }

Modified: stable/11/sys/kern/sysv_sem.c
==============================================================================
--- stable/11/sys/kern/sysv_sem.c       Mon Feb 12 18:30:20 2018        
(r329176)
+++ stable/11/sys/kern/sysv_sem.c       Mon Feb 12 18:40:19 2018        
(r329177)
@@ -271,7 +271,7 @@ seminit(void)
 
        sem = malloc(sizeof(struct sem) * seminfo.semmns, M_SEM, M_WAITOK);
        sema = malloc(sizeof(struct semid_kernel) * seminfo.semmni, M_SEM,
-           M_WAITOK);
+           M_WAITOK | M_ZERO);
        sema_mtx = malloc(sizeof(struct mtx) * seminfo.semmni, M_SEM,
            M_WAITOK | M_ZERO);
        semu = malloc(seminfo.semmnu * seminfo.semusz, M_SEM, M_WAITOK);
@@ -1467,6 +1467,11 @@ sysctl_sema(SYSCTL_HANDLER_ARGS)
 {
        struct prison *pr, *rpr;
        struct semid_kernel tsemak;
+#ifdef COMPAT_FREEBSD32
+       struct semid_kernel32 tsemak32;
+#endif
+       void *outaddr;
+       size_t outsize;
        int error, i;
 
        pr = req->td->td_ucred->cr_prison;
@@ -1483,7 +1488,28 @@ sysctl_sema(SYSCTL_HANDLER_ARGS)
                                tsemak.u.sem_perm.key = IPC_PRIVATE;
                }
                mtx_unlock(&sema_mtx[i]);
-               error = SYSCTL_OUT(req, &tsemak, sizeof(tsemak));
+#ifdef COMPAT_FREEBSD32
+               if (SV_CURPROC_FLAG(SV_ILP32)) {
+                       bzero(&tsemak32, sizeof(tsemak32));
+                       freebsd32_ipcperm_out(&tsemak.u.sem_perm,
+                           &tsemak32.u.sem_perm);
+                       /* Don't copy u.sem_base */
+                       CP(tsemak, tsemak32, u.sem_nsems);
+                       CP(tsemak, tsemak32, u.sem_otime);
+                       CP(tsemak, tsemak32, u.sem_ctime);
+                       /* Don't copy label or cred */
+                       outaddr = &tsemak32;
+                       outsize = sizeof(tsemak32);
+               } else
+#endif
+               {
+                       tsemak.u.sem_base = NULL;
+                       tsemak.label = NULL;
+                       tsemak.cred = NULL;
+                       outaddr = &tsemak;
+                       outsize = sizeof(tsemak);
+               }
+               error = SYSCTL_OUT(req, outaddr, outsize);
                if (error != 0)
                        break;
        }

Modified: stable/11/sys/kern/sysv_shm.c
==============================================================================
--- stable/11/sys/kern/sysv_shm.c       Mon Feb 12 18:30:20 2018        
(r329176)
+++ stable/11/sys/kern/sysv_shm.c       Mon Feb 12 18:40:19 2018        
(r329177)
@@ -844,7 +844,8 @@ shmrealloc(void)
        if (shmalloced >= shminfo.shmmni)
                return;
 
-       newsegs = malloc(shminfo.shmmni * sizeof(*newsegs), M_SHM, M_WAITOK);
+       newsegs = malloc(shminfo.shmmni * sizeof(*newsegs), M_SHM,
+           M_WAITOK | M_ZERO);
        for (i = 0; i < shmalloced; i++)
                bcopy(&shmsegs[i], &newsegs[i], sizeof(newsegs[0]));
        for (; i < shminfo.shmmni; i++) {
@@ -922,7 +923,8 @@ shminit(void)
                }
        }
        shmalloced = shminfo.shmmni;
-       shmsegs = malloc(shmalloced * sizeof(shmsegs[0]), M_SHM, M_WAITOK);
+       shmsegs = malloc(shmalloced * sizeof(shmsegs[0]), M_SHM,
+           M_WAITOK|M_ZERO);
        for (i = 0; i < shmalloced; i++) {
                shmsegs[i].u.shm_perm.mode = SHMSEG_FREE;
                shmsegs[i].u.shm_perm.seq = 0;
@@ -1009,7 +1011,12 @@ static int
 sysctl_shmsegs(SYSCTL_HANDLER_ARGS)
 {
        struct shmid_kernel tshmseg;
+#ifdef COMPAT_FREEBSD32
+       struct shmid_kernel32 tshmseg32;
+#endif
        struct prison *pr, *rpr;
+       void *outaddr;
+       size_t outsize;
        int error, i;
 
        SYSVSHM_LOCK();
@@ -1026,7 +1033,31 @@ sysctl_shmsegs(SYSCTL_HANDLER_ARGS)
                        if (tshmseg.cred->cr_prison != pr)
                                tshmseg.u.shm_perm.key = IPC_PRIVATE;
                }
-               error = SYSCTL_OUT(req, &tshmseg, sizeof(tshmseg));
+#ifdef COMPAT_FREEBSD32
+               if (SV_CURPROC_FLAG(SV_ILP32)) {
+                       bzero(&tshmseg32, sizeof(tshmseg32));
+                       freebsd32_ipcperm_out(&tshmseg.u.shm_perm,
+                           &tshmseg32.u.shm_perm);
+                       CP(tshmseg, tshmseg32, u.shm_segsz);
+                       CP(tshmseg, tshmseg32, u.shm_lpid);
+                       CP(tshmseg, tshmseg32, u.shm_cpid);
+                       CP(tshmseg, tshmseg32, u.shm_nattch);
+                       CP(tshmseg, tshmseg32, u.shm_atime);
+                       CP(tshmseg, tshmseg32, u.shm_dtime);
+                       CP(tshmseg, tshmseg32, u.shm_ctime);
+                       /* Don't copy object, label, or cred */
+                       outaddr = &tshmseg32;
+                       outsize = sizeof(tshmseg32);
+               } else
+#endif
+               {
+                       tshmseg.object = NULL;
+                       tshmseg.label = NULL;
+                       tshmseg.cred = NULL;
+                       outaddr = &tshmseg;
+                       outsize = sizeof(tshmseg);
+               }
+               error = SYSCTL_OUT(req, outaddr, outsize);
                if (error != 0)
                        break;
        }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to