summaryrefslogtreecommitdiffstats
path: root/sys/kern/sys_generic.c
diff options
context:
space:
mode:
authorru <ru@FreeBSD.org>2006-09-27 19:57:02 +0000
committerru <ru@FreeBSD.org>2006-09-27 19:57:02 +0000
commit4ef62e4ca582414062d69e20a1ccdade4a110938 (patch)
treea886251dab8c19f71a5bfd0199ec1d9b327b3513 /sys/kern/sys_generic.c
parentf6b387ce531fb4ba91958db5aadcb53f89d4ed1b (diff)
downloadFreeBSD-src-4ef62e4ca582414062d69e20a1ccdade4a110938.zip
FreeBSD-src-4ef62e4ca582414062d69e20a1ccdade4a110938.tar.gz
Fix our ioctl(2) implementation when the argument is "int". New
ioctls passing integer arguments should use the _IOWINT() macro. This fixes a lot of ioctl's not working on sparc64, most notable being keyboard/syscons ioctls. Full ABI compatibility is provided, with the bonus of fixing the handling of old ioctls on sparc64. Reviewed by: bde (with contributions) Tested by: emax, marius MFC after: 1 week
Diffstat (limited to 'sys/kern/sys_generic.c')
-rw-r--r--sys/kern/sys_generic.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index 13387ec..cab79b8 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -524,9 +524,9 @@ int
ioctl(struct thread *td, struct ioctl_args *uap)
{
u_long com;
- int error;
+ int arg, error;
u_int size;
- caddr_t data, memp;
+ caddr_t data;
if (uap->com > 0xffffffff) {
printf(
@@ -548,20 +548,24 @@ ioctl(struct thread *td, struct ioctl_args *uap)
#else
((com & (IOC_IN | IOC_OUT)) && size == 0) ||
#endif
- ((com & IOC_VOID) && size > 0))
+ ((com & IOC_VOID) && size > 0 && size != sizeof(int)))
return (ENOTTY);
if (size > 0) {
- memp = malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
- data = memp;
- } else {
- memp = NULL;
+ if (!(com & IOC_VOID))
+ data = malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
+ else {
+ /* Integer argument. */
+ arg = (intptr_t)uap->data;
+ data = (void *)&arg;
+ size = 0;
+ }
+ } else
data = (void *)&uap->data;
- }
if (com & IOC_IN) {
error = copyin(uap->data, data, (u_int)size);
if (error) {
- free(memp, M_IOCTLOPS);
+ free(data, M_IOCTLOPS);
return (error);
}
} else if (com & IOC_OUT) {
@@ -577,8 +581,8 @@ ioctl(struct thread *td, struct ioctl_args *uap)
if (error == 0 && (com & IOC_OUT))
error = copyout(data, uap->data, (u_int)size);
- if (memp != NULL)
- free(memp, M_IOCTLOPS);
+ if (size > 0)
+ free(data, M_IOCTLOPS);
return (error);
}
OpenPOWER on IntegriCloud