diff options
author | Brooks Davis <brooks@FreeBSD.org> | 2018-10-26 17:59:25 +0000 |
---|---|---|
committer | Brooks Davis <brooks@FreeBSD.org> | 2018-10-26 17:59:25 +0000 |
commit | ed34a7fcf26fc1a36cf7b27d1a2d501bfd6b93df (patch) | |
tree | dc1efd1ecce565e0e8ea9909023209760c09ba9f /sys/fs | |
parent | 91b528c3b2c97f06cb6024159bdda4ca8544fe2e (diff) | |
download | src-ed34a7fcf26fc1a36cf7b27d1a2d501bfd6b93df.tar.gz src-ed34a7fcf26fc1a36cf7b27d1a2d501bfd6b93df.zip |
Move 32-bit compat support for FIODGNAME to the right place.
ioctl(2) commands only have meaning in the context of a file descriptor
so translating them in the syscall layer is incorrect.
The new handler users an accessor to retrieve/construct a pointer from
the last member of the passed structure and relies on type punning to
access the other member which requires no translation.
Unlike r339174 this change supports both places FIODGNAME is handled.
Reviewed by: kib
Obtained from: CheriBSD
Sponsored by: DARPA, AFRL
Differential Revision: https://reviews.freebsd.org/D17475
Notes
Notes:
svn path=/head/; revision=339779
Diffstat (limited to 'sys/fs')
-rw-r--r-- | sys/fs/devfs/devfs_vnops.c | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index 514a5914ab7e..5c0bf603ab9b 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -767,6 +767,29 @@ devfs_ioctl_f(struct file *fp, u_long com, void *data, struct ucred *cred, struc return (error); } +void * +fiodgname_buf_get_ptr(void *fgnp, u_long com) +{ + union { + struct fiodgname_arg fgn; +#ifdef COMPAT_FREEBSD32 + struct fiodgname_arg32 fgn32; +#endif + } *fgnup; + + fgnup = fgnp; + switch (com) { + case FIODGNAME: + return (fgnup->fgn.buf); +#ifdef COMPAT_FREEBSD32 + case FIODGNAME_32: + return ((void *)(uintptr_t)fgnup->fgn32.buf); +#endif + default: + panic("Unhandled ioctl command %ld", com); + } +} + static int devfs_ioctl(struct vop_ioctl_args *ap) { @@ -789,24 +812,27 @@ devfs_ioctl(struct vop_ioctl_args *ap) KASSERT(dev->si_refcount > 0, ("devfs: un-referenced struct cdev *(%s)", devtoname(dev))); - if (com == FIODTYPE) { + switch (com) { + case FIODTYPE: *(int *)ap->a_data = dsw->d_flags & D_TYPEMASK; error = 0; - goto out; - } else if (com == FIODGNAME) { + break; + case FIODGNAME: +#ifdef COMPAT_FREEBSD32 + case FIODGNAME_32: +#endif fgn = ap->a_data; p = devtoname(dev); i = strlen(p) + 1; if (i > fgn->len) error = EINVAL; else - error = copyout(p, fgn->buf, i); - goto out; + error = copyout(p, fiodgname_buf_get_ptr(fgn, com), i); + break; + default: + error = dsw->d_ioctl(dev, com, ap->a_data, ap->a_fflag, td); } - error = dsw->d_ioctl(dev, com, ap->a_data, ap->a_fflag, td); - -out: dev_relthread(dev, ref); if (error == ENOIOCTL) error = ENOTTY; |