svn commit: r331623 - in head/sys: compat/freebsd32 dev/md

Brooks Davis brooks at FreeBSD.org
Tue Mar 27 16:07:55 UTC 2018


Author: brooks
Date: Tue Mar 27 16:07:54 2018
New Revision: 331623
URL: https://svnweb.freebsd.org/changeset/base/331623

Log:
  Move 32-bit compat for md(4) ioctls into the md code.
  
  This is more correct in that ioctl commands have no meaning until they
  hit the handler associated with the file descriptor.
  
  Add support for MDIOCRESIZE_32 which was missed when it was added.
  
  Reviewed by:	cem, kib, markj (various versions)
  Obtained from:	CheriBSD
  Sponsored by:	DARPA, AFRL
  Differential Revision:	https://reviews.freebsd.org/D14714

Modified:
  head/sys/compat/freebsd32/freebsd32_ioctl.c
  head/sys/compat/freebsd32/freebsd32_ioctl.h
  head/sys/dev/md/md.c

Modified: head/sys/compat/freebsd32/freebsd32_ioctl.c
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_ioctl.c	Tue Mar 27 15:29:32 2018	(r331622)
+++ head/sys/compat/freebsd32/freebsd32_ioctl.c	Tue Mar 27 16:07:54 2018	(r331623)
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/file.h>
 #include <sys/ioccom.h>
 #include <sys/malloc.h>
-#include <sys/mdioctl.h>
 #include <sys/memrange.h>
 #include <sys/pciio.h>
 #include <sys/proc.h>
@@ -58,90 +57,13 @@ __FBSDID("$FreeBSD$");
 #include <compat/freebsd32/freebsd32_ioctl.h>
 #include <compat/freebsd32/freebsd32_proto.h>
 
-CTASSERT((sizeof(struct md_ioctl32)) == 436);
 CTASSERT(sizeof(struct ioc_read_toc_entry32) == 8);
 CTASSERT(sizeof(struct mem_range_op32) == 12);
 CTASSERT(sizeof(struct pci_conf_io32) == 36);
 CTASSERT(sizeof(struct pci_match_conf32) == 44);
 CTASSERT(sizeof(struct pci_conf32) == 44);
 
-
 static int
-freebsd32_ioctl_md(struct thread *td, struct freebsd32_ioctl_args *uap,
-    struct file *fp)
-{
-	struct md_ioctl mdv;
-	struct md_ioctl32 md32;
-	u_long com = 0;
-	int i, error;
-
-	if (uap->com & IOC_IN) {
-		if ((error = copyin(uap->data, &md32, sizeof(md32)))) {
-			return (error);
-		}
-		CP(md32, mdv, md_version);
-		CP(md32, mdv, md_unit);
-		CP(md32, mdv, md_type);
-		PTRIN_CP(md32, mdv, md_file);
-		CP(md32, mdv, md_mediasize);
-		CP(md32, mdv, md_sectorsize);
-		CP(md32, mdv, md_options);
-		CP(md32, mdv, md_base);
-		CP(md32, mdv, md_fwheads);
-		CP(md32, mdv, md_fwsectors);
-		PTRIN_CP(md32, mdv, md_label);
-	} else if (uap->com & IOC_OUT) {
-		/*
-		 * Zero the buffer so the user always
-		 * gets back something deterministic.
-		 */
-		bzero(&mdv, sizeof mdv);
-	}
-
-	switch (uap->com) {
-	case MDIOCATTACH_32:
-		com = MDIOCATTACH;
-		break;
-	case MDIOCDETACH_32:
-		com = MDIOCDETACH;
-		break;
-	case MDIOCQUERY_32:
-		com = MDIOCQUERY;
-		break;
-	case MDIOCLIST_32:
-		com = MDIOCLIST;
-		break;
-	default:
-		panic("%s: unknown MDIOC %#x", __func__, uap->com);
-	}
-	error = fo_ioctl(fp, com, (caddr_t)&mdv, td->td_ucred, td);
-	if (error == 0 && (com & IOC_OUT)) {
-		CP(mdv, md32, md_version);
-		CP(mdv, md32, md_unit);
-		CP(mdv, md32, md_type);
-		PTROUT_CP(mdv, md32, md_file);
-		CP(mdv, md32, md_mediasize);
-		CP(mdv, md32, md_sectorsize);
-		CP(mdv, md32, md_options);
-		CP(mdv, md32, md_base);
-		CP(mdv, md32, md_fwheads);
-		CP(mdv, md32, md_fwsectors);
-		PTROUT_CP(mdv, md32, md_label);
-		if (com == MDIOCLIST) {
-			/*
-			 * Use MDNPAD, and not MDNPAD32.  Padding is
-			 * allocated and used by compat32 ABI.
-			 */
-			for (i = 0; i < MDNPAD; i++)
-				CP(mdv, md32, md_pad[i]);
-		}
-		error = copyout(&md32, uap->data, sizeof(md32));
-	}
-	return error;
-}
-
-
-static int
 freebsd32_ioctl_ioc_read_toc(struct thread *td,
     struct freebsd32_ioctl_args *uap, struct file *fp)
 {
@@ -414,13 +336,6 @@ freebsd32_ioctl(struct thread *td, struct freebsd32_io
 	}
 
 	switch (uap->com) {
-	case MDIOCATTACH_32:	/* FALLTHROUGH */
-	case MDIOCDETACH_32:	/* FALLTHROUGH */
-	case MDIOCQUERY_32:	/* FALLTHROUGH */
-	case MDIOCLIST_32:
-		error = freebsd32_ioctl_md(td, uap, fp);
-		break;
-
 	case CDIOREADTOCENTRYS_32:
 		error = freebsd32_ioctl_ioc_read_toc(td, uap, fp);
 		break;

Modified: head/sys/compat/freebsd32/freebsd32_ioctl.h
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_ioctl.h	Tue Mar 27 15:29:32 2018	(r331622)
+++ head/sys/compat/freebsd32/freebsd32_ioctl.h	Tue Mar 27 16:07:54 2018	(r331623)
@@ -45,22 +45,6 @@ struct ioc_read_toc_entry32 {
 	uint32_t data;		/* struct cd_toc_entry* */
 };
 
-#define	MDNPAD32	MDNPAD
-struct md_ioctl32 {
-	unsigned	md_version;	/* Structure layout version */
-	unsigned	md_unit;	/* unit number */
-	enum md_types	md_type;	/* type of disk */
-	caddr_t32	md_file;	/* pathname of file to mount */
-	off_t		md_mediasize;	/* size of disk in bytes */
-	unsigned	md_sectorsize;	/* sectorsize */
-	unsigned	md_options;	/* options */
-	u_int64_t	md_base;	/* base address */
-	int		md_fwheads;	/* firmware heads */
-	int		md_fwsectors;	/* firmware sectors */
-	caddr_t32	md_label;	/* label of the device */
-	int		md_pad[MDNPAD32]; /* padding for future ideas */
-} __attribute__((__packed__));
-
 struct fiodgname_arg32 {
 	int		len;
 	caddr_t32	buf;
@@ -112,10 +96,6 @@ struct pci_conf_io32 {
 };
 
 #define	CDIOREADTOCENTRYS_32 _IOWR('c', 5, struct ioc_read_toc_entry32)
-#define	MDIOCATTACH_32	_IOC(IOC_INOUT, 'm', 0, sizeof(struct md_ioctl32))
-#define	MDIOCDETACH_32	_IOC(IOC_INOUT, 'm', 1, sizeof(struct md_ioctl32))
-#define	MDIOCQUERY_32	_IOC(IOC_INOUT, 'm', 2, sizeof(struct md_ioctl32))
-#define	MDIOCLIST_32	_IOC(IOC_INOUT, 'm', 3, sizeof(struct md_ioctl32))
 #define	FIODGNAME_32	_IOW('f', 120, struct fiodgname_arg32)
 #define	MEMRANGE_GET32	_IOWR('m', 50, struct mem_range_op32)
 #define	MEMRANGE_SET32	_IOW('m', 51, struct mem_range_op32)

Modified: head/sys/dev/md/md.c
==============================================================================
--- head/sys/dev/md/md.c	Tue Mar 27 15:29:32 2018	(r331622)
+++ head/sys/dev/md/md.c	Tue Mar 27 16:07:54 2018	(r331623)
@@ -60,6 +60,7 @@
  * From: src/sys/dev/vn/vn.c,v 1.122 2000/12/16 16:06:03
  */
 
+#include "opt_compat.h"
 #include "opt_rootdevname.h"
 #include "opt_geom.h"
 #include "opt_md.h"
@@ -130,6 +131,30 @@ struct md_req {
 	size_t		md_units_nitems; /* items in md_units array */
 };
 
+#ifdef COMPAT_FREEBSD32
+struct md_ioctl32 {
+	unsigned	md_version;
+	unsigned	md_unit;
+	enum md_types	md_type;
+	uint32_t	md_file;
+	off_t		md_mediasize;
+	unsigned	md_sectorsize;
+	unsigned	md_options;
+	uint64_t	md_base;
+	int		md_fwheads;
+	int		md_fwsectors;
+	uint32_t	md_label;
+	int		md_pad[MDNPAD];
+} __attribute__((__packed__));
+CTASSERT((sizeof(struct md_ioctl32)) == 436);
+
+#define	MDIOCATTACH_32	_IOC_NEWTYPE(MDIOCATTACH, struct md_ioctl32)
+#define	MDIOCDETACH_32	_IOC_NEWTYPE(MDIOCDETACH, struct md_ioctl32)
+#define	MDIOCQUERY_32	_IOC_NEWTYPE(MDIOCQUERY, struct md_ioctl32)
+#define	MDIOCLIST_32	_IOC_NEWTYPE(MDIOCLIST, struct md_ioctl32)
+#define	MDIOCRESIZE_32	_IOC_NEWTYPE(MDIOCRESIZE, struct md_ioctl32)
+#endif /* COMPAT_FREEBSD32 */
+
 static MALLOC_DEFINE(M_MD, "md_disk", "Memory Disk");
 static MALLOC_DEFINE(M_MDSECT, "md_sectors", "Memory Disk Sectors");
 
@@ -1396,8 +1421,10 @@ mdcreate_vnode(struct md_s *sc, struct md_req *mdr, st
 		error = copyinstr(fname, sc->file, sizeof(sc->file), NULL);
 		if (error != 0)
 			return (error);
-	} else
+	} else if (mdr->md_file_seg == UIO_SYSSPACE)
 		strlcpy(sc->file, fname, sizeof(sc->file));
+	else
+		return (EDOOFUS);
 
 	/*
 	 * If the user specified that this is a read only device, don't
@@ -1859,61 +1886,111 @@ kern_mdlist(struct md_req *mdr)
 	return (error);
 }
 
+/* Copy members that are not userspace pointers. */
+#define	MD_IOCTL2REQ(mdio, mdr) do {					\
+	(mdr)->md_unit = (mdio)->md_unit;				\
+	(mdr)->md_type = (mdio)->md_type;				\
+	(mdr)->md_mediasize = (mdio)->md_mediasize;			\
+	(mdr)->md_sectorsize = (mdio)->md_sectorsize;			\
+	(mdr)->md_options = (mdio)->md_options;				\
+	(mdr)->md_fwheads = (mdio)->md_fwheads;				\
+	(mdr)->md_fwsectors = (mdio)->md_fwsectors;			\
+	(mdr)->md_units = &(mdio)->md_pad[0];				\
+	(mdr)->md_units_nitems = nitems((mdio)->md_pad);		\
+} while(0)
+
+/* Copy members that might have been updated */
+#define MD_REQ2IOCTL(mdr, mdio) do {					\
+	(mdio)->md_unit = (mdr)->md_unit;				\
+	(mdio)->md_type = (mdr)->md_type;				\
+	(mdio)->md_mediasize = (mdr)->md_mediasize;			\
+	(mdio)->md_sectorsize = (mdr)->md_sectorsize;			\
+	(mdio)->md_options = (mdr)->md_options;				\
+	(mdio)->md_fwheads = (mdr)->md_fwheads;				\
+	(mdio)->md_fwsectors = (mdr)->md_fwsectors;			\
+} while(0)
+
 static int
 mdctlioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
     struct thread *td)
 {
 	struct md_req mdr;
-	struct md_ioctl *mdio;
 	int error;
 
 	if (md_debug)
 		printf("mdctlioctl(%s %lx %p %x %p)\n",
 			devtoname(dev), cmd, addr, flags, td);
 
+	bzero(&mdr, sizeof(mdr));
 	switch (cmd) {
 	case MDIOCATTACH:
 	case MDIOCDETACH:
 	case MDIOCRESIZE:
 	case MDIOCQUERY:
-	case MDIOCLIST:
-		mdio = (struct md_ioctl *)addr;
+	case MDIOCLIST: {
+		struct md_ioctl *mdio = (struct md_ioctl *)addr;
 		if (mdio->md_version != MDIOVERSION)
 			return (EINVAL);
-		mdr.md_unit = mdio->md_unit;
-		mdr.md_type = mdio->md_type;
-		mdr.md_mediasize = mdio->md_mediasize;
-		mdr.md_sectorsize = mdio->md_sectorsize;
-		mdr.md_options = mdio->md_options;
-		mdr.md_fwheads = mdio->md_fwheads;
-		mdr.md_fwsectors = mdio->md_fwsectors;
+		MD_IOCTL2REQ(mdio, &mdr);
 		mdr.md_file = mdio->md_file;
+		mdr.md_file_seg = UIO_USERSPACE;
 		/* If the file is adjacent to the md_ioctl it's in kernel. */
 		if ((void *)mdio->md_file == (void *)(mdio + 1))
 			mdr.md_file_seg = UIO_SYSSPACE;
-		else
-			mdr.md_file_seg = UIO_USERSPACE;
 		mdr.md_label = mdio->md_label;
-		mdr.md_units = &mdio->md_pad[0];
-		mdr.md_units_nitems = nitems(mdio->md_pad);
 		break;
 	}
+#ifdef COMPAT_FREEBSD32
+	case MDIOCATTACH_32:
+	case MDIOCDETACH_32:
+	case MDIOCRESIZE_32:
+	case MDIOCQUERY_32:
+	case MDIOCLIST_32: {
+		struct md_ioctl32 *mdio = (struct md_ioctl32 *)addr;
+		if (mdio->md_version != MDIOVERSION)
+			return (EINVAL);
+		MD_IOCTL2REQ(mdio, &mdr);
+		mdr.md_file = (void *)(uintptr_t)mdio->md_file;
+		mdr.md_file_seg = UIO_USERSPACE;
+		mdr.md_label = (void *)(uintptr_t)mdio->md_label;
+		break;
+	}
+#endif
+	default:
+		/* Fall through to handler switch. */
+		break;
+	}
 
 	error = 0;
 	switch (cmd) {
 	case MDIOCATTACH:
+#ifdef COMPAT_FREEBSD32
+	case MDIOCATTACH_32:
+#endif
 		error = kern_mdattach(td, &mdr);
 		break;
 	case MDIOCDETACH:
+#ifdef COMPAT_FREEBSD32
+	case MDIOCDETACH_32:
+#endif
 		error = kern_mddetach(td, &mdr);
 		break;
 	case MDIOCRESIZE:
+#ifdef COMPAT_FREEBSD32
+	case MDIOCRESIZE_32:
+#endif
 		error = kern_mdresize(&mdr);
 		break;
 	case MDIOCQUERY:
+#ifdef COMPAT_FREEBSD32
+	case MDIOCQUERY_32:
+#endif
 		error = kern_mdquery(&mdr);
 		break;
 	case MDIOCLIST:
+#ifdef COMPAT_FREEBSD32
+	case MDIOCLIST_32:
+#endif
 		error = kern_mdlist(&mdr);
 		break;
 	default:
@@ -1922,14 +1999,21 @@ mdctlioctl(struct cdev *dev, u_long cmd, caddr_t addr,
 
 	switch (cmd) {
 	case MDIOCATTACH:
-	case MDIOCQUERY:
-		mdio->md_unit = mdr.md_unit;
-		mdio->md_type = mdr.md_type;
-		mdio->md_mediasize = mdr.md_mediasize;
-		mdio->md_sectorsize = mdr.md_sectorsize;
-		mdio->md_options = mdr.md_options;
-		mdio->md_fwheads = mdr.md_fwheads;
-		mdio->md_fwsectors = mdr.md_fwsectors;
+	case MDIOCQUERY: {
+		struct md_ioctl *mdio = (struct md_ioctl *)addr;
+		MD_REQ2IOCTL(&mdr, mdio);
+		break;
+	}
+#ifdef COMPAT_FREEBSD32
+	case MDIOCATTACH_32:
+	case MDIOCQUERY_32: {
+		struct md_ioctl32 *mdio = (struct md_ioctl32 *)addr;
+		MD_REQ2IOCTL(&mdr, mdio);
+		break;
+	}
+#endif
+	default:
+		/* Other commands to not alter mdr. */
 		break;
 	}
 


More information about the svn-src-all mailing list