svn commit: r328799 - in head/sys: compat/freebsd32 kern

Brooks Davis brooks at FreeBSD.org
Fri Feb 2 18:03:14 UTC 2018


Author: brooks
Date: Fri Feb  2 18:03:12 2018
New Revision: 328799
URL: https://svnweb.freebsd.org/changeset/base/328799

Log:
  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
  MFC after:	1 week
  Sponsored by:	DARPA, AFRL
  Differential Revision:	https://reviews.freebsd.org/D13459

Modified:
  head/sys/compat/freebsd32/freebsd32_ipc.h
  head/sys/kern/sysv_msg.c
  head/sys/kern/sysv_sem.c
  head/sys/kern/sysv_shm.c

Modified: head/sys/compat/freebsd32/freebsd32_ipc.h
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_ipc.h	Fri Feb  2 18:02:06 2018	(r328798)
+++ head/sys/compat/freebsd32/freebsd32_ipc.h	Fri Feb  2 18:03:12 2018	(r328799)
@@ -49,6 +49,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;
@@ -69,6 +81,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;
@@ -79,6 +102,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: head/sys/kern/sysv_msg.c
==============================================================================
--- head/sys/kern/sysv_msg.c	Fri Feb  2 18:02:06 2018	(r328798)
+++ head/sys/kern/sysv_msg.c	Fri Feb  2 18:03:12 2018	(r328799)
@@ -229,7 +229,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.
@@ -1418,7 +1418,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;
@@ -1435,7 +1440,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: head/sys/kern/sysv_sem.c
==============================================================================
--- head/sys/kern/sysv_sem.c	Fri Feb  2 18:02:06 2018	(r328798)
+++ head/sys/kern/sysv_sem.c	Fri Feb  2 18:03:12 2018	(r328799)
@@ -280,7 +280,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);
@@ -1487,6 +1487,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;
@@ -1503,7 +1508,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: head/sys/kern/sysv_shm.c
==============================================================================
--- head/sys/kern/sysv_shm.c	Fri Feb  2 18:02:06 2018	(r328798)
+++ head/sys/kern/sysv_shm.c	Fri Feb  2 18:03:12 2018	(r328799)
@@ -866,7 +866,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++) {
@@ -944,7 +945,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;
@@ -1031,7 +1033,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();
@@ -1048,7 +1055,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;
 	}


More information about the svn-src-all mailing list