diff options
| author | Brooks Davis <brooks@FreeBSD.org> | 2018-03-27 16:07:54 +0000 |
|---|---|---|
| committer | Brooks Davis <brooks@FreeBSD.org> | 2018-03-27 16:07:54 +0000 |
| commit | 026cac821351142e0130eea17b1ba0e082ecbc69 (patch) | |
| tree | 190290030ec6c1f4f5cc8ba1e627d6c76dcdb5a3 /sys/dev/md | |
| parent | f137973487f6170f8cb3285ec58aed46e9e3e6f9 (diff) | |
Notes
Diffstat (limited to 'sys/dev/md')
| -rw-r--r-- | sys/dev/md/md.c | 130 |
1 files changed, 107 insertions, 23 deletions
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c index d976ced2391b..d5908e771613 100644 --- a/sys/dev/md/md.c +++ b/sys/dev/md/md.c @@ -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, struct thread *td) 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, int flags, 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; } |
