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
This commit is contained in:
Brooks Davis 2018-10-26 17:59:25 +00:00
parent 91b528c3b2
commit ed34a7fcf2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=339779
5 changed files with 52 additions and 36 deletions

View File

@ -58,22 +58,6 @@ __FBSDID("$FreeBSD$");
CTASSERT(sizeof(struct mem_range_op32) == 12);
static int
freebsd32_ioctl_fiodgname(struct thread *td,
struct freebsd32_ioctl_args *uap, struct file *fp)
{
struct fiodgname_arg fgn;
struct fiodgname_arg32 fgn32;
int error;
if ((error = copyin(uap->data, &fgn32, sizeof fgn32)) != 0)
return (error);
CP(fgn32, fgn, len);
PTRIN_CP(fgn32, fgn, buf);
error = fo_ioctl(fp, FIODGNAME, (caddr_t)&fgn, td->td_ucred, td);
return (error);
}
static int
freebsd32_ioctl_memrange(struct thread *td,
struct freebsd32_ioctl_args *uap, struct file *fp)
@ -237,10 +221,6 @@ freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap)
}
switch (uap->com) {
case FIODGNAME_32:
error = freebsd32_ioctl_fiodgname(td, uap, fp);
break;
case MEMRANGE_GET32: /* FALLTHROUGH */
case MEMRANGE_SET32:
error = freebsd32_ioctl_memrange(td, uap, fp);

View File

@ -38,11 +38,6 @@
typedef __uint32_t caddr_t32;
struct fiodgname_arg32 {
int len;
caddr_t32 buf;
};
struct mem_range_op32
{
caddr_t32 mo_desc;
@ -60,7 +55,6 @@ struct pci_bar_mmap32 {
int pbm_memattr;
};
#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)
#define SG_IO_32 _IOWR(SGIOC, 0x85, struct sg_io_hdr32)

View File

@ -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;

View File

@ -281,7 +281,11 @@ ptsdev_ioctl(struct file *fp, u_long cmd, void *data,
}
tty_unlock(tp);
return (0);
case FIODGNAME: {
case FIODGNAME:
#ifdef COMPAT_FREEBSD32
case FIODGNAME_32:
#endif
{
struct fiodgname_arg *fgn;
const char *p;
int i;
@ -292,7 +296,7 @@ ptsdev_ioctl(struct file *fp, u_long cmd, void *data,
i = strlen(p) + 1;
if (i > fgn->len)
return (EINVAL);
return copyout(p, fgn->buf, i);
return (copyout(p, fiodgname_buf_get_ptr(fgn, cmd), i));
}
/*

View File

@ -63,4 +63,16 @@ struct fiodgname_arg {
#define FIOSEEKDATA _IOWR('f', 97, off_t) /* SEEK_DATA */
#define FIOSEEKHOLE _IOWR('f', 98, off_t) /* SEEK_HOLE */
#ifdef _KERNEL
#ifdef COMPAT_FREEBSD32
struct fiodgname_arg32 {
int len;
uint32_t buf; /* (void *) */
};
#define FIODGNAME_32 _IOC_NEWTYPE(FIODGNAME, struct fiodgname_arg32)
#endif
void *fiodgname_buf_get_ptr(void *fgnp, u_long com);
#endif
#endif /* !_SYS_FILIO_H_ */