Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Mar 2018 03:07:03 +0000 (UTC)
From:      Mateusz Guzik <mjg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r331657 - head/sys/kern
Message-ID:  <201803280307.w2S373EP055055@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mjg
Date: Wed Mar 28 03:07:02 2018
New Revision: 331657
URL: https://svnweb.freebsd.org/changeset/base/331657

Log:
  fd: tighten seq protected areas to not contain malloc/free

Modified:
  head/sys/kern/kern_descrip.c

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c	Tue Mar 27 22:49:06 2018	(r331656)
+++ head/sys/kern/kern_descrip.c	Wed Mar 28 03:07:02 2018	(r331657)
@@ -111,6 +111,11 @@ static void	fdgrowtable_exp(struct filedesc *fdp, int 
 static void	fdunused(struct filedesc *fdp, int fd);
 static void	fdused(struct filedesc *fdp, int fd);
 static int	getmaxfd(struct thread *td);
+static u_long	*filecaps_copy_prep(const struct filecaps *src);
+static void	filecaps_copy_finish(const struct filecaps *src,
+		    struct filecaps *dst, u_long *ioctls);
+static u_long 	*filecaps_free_prep(struct filecaps *fcaps);
+static void	filecaps_free_finish(u_long *ioctls);
 
 /*
  * Each process has:
@@ -302,12 +307,12 @@ fdfree(struct filedesc *fdp, int fd)
 #ifdef CAPABILITIES
 	seq_write_begin(&fde->fde_seq);
 #endif
-	fdefree_last(fde);
 	fde->fde_file = NULL;
-	fdunused(fdp, fd);
 #ifdef CAPABILITIES
 	seq_write_end(&fde->fde_seq);
 #endif
+	fdefree_last(fde);
+	fdunused(fdp, fd);
 }
 
 void
@@ -813,6 +818,7 @@ kern_dup(struct thread *td, u_int mode, int flags, int
 	struct filedescent *oldfde, *newfde;
 	struct proc *p;
 	struct file *delfp;
+	u_long *oioctls, *nioctls;
 	int error, maxfd;
 
 	p = td->td_proc;
@@ -902,15 +908,18 @@ kern_dup(struct thread *td, u_int mode, int flags, int
 	newfde = &fdp->fd_ofiles[new];
 	delfp = newfde->fde_file;
 
+	oioctls = filecaps_free_prep(&newfde->fde_caps);
+	nioctls = filecaps_copy_prep(&oldfde->fde_caps);
+
 	/*
 	 * Duplicate the source descriptor.
 	 */
 #ifdef CAPABILITIES
 	seq_write_begin(&newfde->fde_seq);
 #endif
-	filecaps_free(&newfde->fde_caps);
 	memcpy(newfde, oldfde, fde_change_size);
-	filecaps_copy(&oldfde->fde_caps, &newfde->fde_caps, true);
+	filecaps_copy_finish(&oldfde->fde_caps, &newfde->fde_caps,
+	    nioctls);
 	if ((flags & FDDUP_FLAG_CLOEXEC) != 0)
 		newfde->fde_flags = oldfde->fde_flags | UF_EXCLOSE;
 	else
@@ -918,6 +927,7 @@ kern_dup(struct thread *td, u_int mode, int flags, int
 #ifdef CAPABILITIES
 	seq_write_end(&newfde->fde_seq);
 #endif
+	filecaps_free_finish(oioctls);
 	td->td_retval[0] = new;
 
 	error = 0;
@@ -1503,6 +1513,40 @@ filecaps_copy(const struct filecaps *src, struct filec
 	return (0);
 }
 
+static u_long *
+filecaps_copy_prep(const struct filecaps *src)
+{
+	u_long *ioctls;
+	size_t size;
+
+	if (src->fc_ioctls == NULL)
+		return (NULL);
+
+	KASSERT(src->fc_nioctls > 0,
+	    ("fc_ioctls != NULL, but fc_nioctls=%hd", src->fc_nioctls));
+
+	size = sizeof(src->fc_ioctls[0]) * src->fc_nioctls;
+	ioctls = malloc(size, M_FILECAPS, M_WAITOK);
+	return (ioctls);
+}
+
+static void
+filecaps_copy_finish(const struct filecaps *src, struct filecaps *dst,
+    u_long *ioctls)
+{
+	size_t size;
+
+	*dst = *src;
+	if (src->fc_ioctls == NULL) {
+		MPASS(ioctls == NULL);
+		return;
+	}
+
+	size = sizeof(src->fc_ioctls[0]) * src->fc_nioctls;
+	dst->fc_ioctls = ioctls;
+	bcopy(src->fc_ioctls, dst->fc_ioctls, size);
+}
+
 /*
  * Move filecaps structure to the new place and clear the old place.
  */
@@ -1538,6 +1582,23 @@ filecaps_free(struct filecaps *fcaps)
 	bzero(fcaps, sizeof(*fcaps));
 }
 
+static u_long *
+filecaps_free_prep(struct filecaps *fcaps)
+{
+	u_long *ioctls;
+
+	ioctls = fcaps->fc_ioctls;
+	bzero(fcaps, sizeof(*fcaps));
+	return (ioctls);
+}
+
+static void
+filecaps_free_finish(u_long *ioctls)
+{
+
+	free(ioctls, M_FILECAPS);
+}
+
 /*
  * Validate the given filecaps structure.
  */
@@ -2963,6 +3024,7 @@ dupfdopen(struct thread *td, struct filedesc *fdp, int
 {
 	struct filedescent *newfde, *oldfde;
 	struct file *fp;
+	u_long *ioctls;
 	int error, indx;
 
 	KASSERT(openerror == ENODEV || openerror == ENXIO,
@@ -3007,11 +3069,13 @@ dupfdopen(struct thread *td, struct filedesc *fdp, int
 		fhold(fp);
 		newfde = &fdp->fd_ofiles[indx];
 		oldfde = &fdp->fd_ofiles[dfd];
+		ioctls = filecaps_copy_prep(&oldfde->fde_caps);
 #ifdef CAPABILITIES
 		seq_write_begin(&newfde->fde_seq);
 #endif
 		memcpy(newfde, oldfde, fde_change_size);
-		filecaps_copy(&oldfde->fde_caps, &newfde->fde_caps, true);
+		filecaps_copy_finish(&oldfde->fde_caps, &newfde->fde_caps,
+		    ioctls);
 #ifdef CAPABILITIES
 		seq_write_end(&newfde->fde_seq);
 #endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803280307.w2S373EP055055>