Remove drm_linux.h, move the two useful defines into drm_drv.h (the only

place they're used). Use fd locking on -current. Actually copy in data
    from userspace to kernel in the linux-compat ioctl path. Make sure
    ioctl sizes are as expected in the ioctl handler functions.
This commit is contained in:
Eric Anholt 2002-08-21 07:14:21 +00:00
parent 8eedac5833
commit 77c35c043a
4 changed files with 152 additions and 34 deletions

View file

@ -1221,27 +1221,83 @@ int DRM(unlock)( DRM_IOCTL_ARGS )
}
#if DRM_LINUX
#define LINUX_IOCTL_DRM_MIN 0x6400
#define LINUX_IOCTL_DRM_MAX 0x64ff
static linux_ioctl_function_t DRM( linux_ioctl);
static struct linux_ioctl_handler DRM( handler) = {DRM( linux_ioctl), LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
SYSINIT (DRM( register), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &DRM( handler));
SYSUNINIT(DRM( unregister), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &DRM( handler));
#define LINUX_IOC_VOID IOC_VOID
#define LINUX_IOC_IN IOC_OUT /* Linux has the values the other way around */
#define LINUX_IOC_OUT IOC_IN
/*
* Linux emulation IOCTL
*/
static int
DRM(linux_ioctl)(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
{
u_long cmd = args->cmd;
#define STK_PARAMS 128
union {
char stkbuf[STK_PARAMS];
long align;
} ubuf;
caddr_t data=NULL, memp=NULL;
u_int size = IOCPARM_LEN(cmd);
int error;
#if (__FreeBSD_version >= 500000)
struct file *fp = p->td_proc->p_fd->fd_ofiles[args->fd];
struct file *fp;
#else
struct file *fp = p->p_fd->fd_ofiles[args->fd];
struct file *fp = p->p_fd->fd_ofiles[args->fd];
#endif
u_long cmd = args->cmd;
caddr_t data = (caddr_t) args->arg;
/*
* Pass the ioctl off to our standard handler.
*/
return(fo_ioctl(fp, cmd, data, p));
if ( size > STK_PARAMS ) {
if ( size > IOCPARM_MAX )
return EINVAL;
memp = malloc( (u_long)size, DRM(M_DRM), M_WAITOK );
data = memp;
} else {
data = ubuf.stkbuf;
}
if ( cmd & LINUX_IOC_IN ) {
if ( size ) {
error = copyin( (caddr_t)args->arg, data, (u_int)size );
if (error) {
if ( memp )
free( data, DRM(M_DRM) );
return error;
}
} else {
data = (caddr_t)args->arg;
}
} else if ( (cmd & LINUX_IOC_OUT) && size ) {
/*
* Zero the buffer so the user always
* gets back something deterministic.
*/
bzero( data, size );
} else if ( cmd & LINUX_IOC_VOID ) {
*(caddr_t *)data = (caddr_t)args->arg;
}
#if (__FreeBSD_version >= 500000)
if ( (error = fget( p, args->fd, &fp )) != 0 ) {
if ( memp )
free( memp, DRM(M_DRM) );
return (error);
}
error = fo_ioctl( fp, cmd, data, p->td_ucred, p );
fdrop( fp, p );
#else
error = fo_ioctl( fp, cmd, data, p );
#endif
if ( error == 0 && (cmd & LINUX_IOC_OUT) && size )
error = copyout( data, (caddr_t)args->arg, (u_int)size );
if ( memp )
free( memp, DRM(M_DRM) );
return error;
}
#endif /* DRM_LINUX */

View file

@ -65,7 +65,6 @@
#include <sys/proc.h>
#include <machine/../linux/linux.h>
#include <machine/../linux/linux_proto.h>
#include "drm_linux.h"
#endif
#define DRM_TIME_SLICE (hz/20) /* Time slice for GLXContexts */
@ -140,14 +139,18 @@ do { \
} \
} while (0)
#define DRM_COPY_TO_USER_IOCTL(arg1, arg2, arg3) \
*arg1 = arg2
#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \
arg1 = *arg2
#define DRM_COPY_TO_USER(arg1, arg2, arg3) \
copyout(arg2, arg1, arg3)
#define DRM_COPY_FROM_USER(arg1, arg2, arg3) \
copyin(arg2, arg1, arg3)
#define DRM_COPY_TO_USER_IOCTL(user, kern, size) \
if ( IOCPARM_LEN(cmd) != size) \
return EINVAL; \
*user = kern;
#define DRM_COPY_FROM_USER_IOCTL(kern, user, size) \
if ( IOCPARM_LEN(cmd) != size) \
return EINVAL; \
kern = *user;
#define DRM_COPY_TO_USER(user, kern, size) \
copyout(kern, user, size)
#define DRM_COPY_FROM_USER(kern, user, size) \
copyin(user, kern, size)
/* Macros for userspace access with checking readability once */
/* FIXME: can't find equivalent functionality for nocheck yet.
* It's be slower than linux, but should be correct.

View file

@ -1221,27 +1221,83 @@ int DRM(unlock)( DRM_IOCTL_ARGS )
}
#if DRM_LINUX
#define LINUX_IOCTL_DRM_MIN 0x6400
#define LINUX_IOCTL_DRM_MAX 0x64ff
static linux_ioctl_function_t DRM( linux_ioctl);
static struct linux_ioctl_handler DRM( handler) = {DRM( linux_ioctl), LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
SYSINIT (DRM( register), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &DRM( handler));
SYSUNINIT(DRM( unregister), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &DRM( handler));
#define LINUX_IOC_VOID IOC_VOID
#define LINUX_IOC_IN IOC_OUT /* Linux has the values the other way around */
#define LINUX_IOC_OUT IOC_IN
/*
* Linux emulation IOCTL
*/
static int
DRM(linux_ioctl)(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
{
u_long cmd = args->cmd;
#define STK_PARAMS 128
union {
char stkbuf[STK_PARAMS];
long align;
} ubuf;
caddr_t data=NULL, memp=NULL;
u_int size = IOCPARM_LEN(cmd);
int error;
#if (__FreeBSD_version >= 500000)
struct file *fp = p->td_proc->p_fd->fd_ofiles[args->fd];
struct file *fp;
#else
struct file *fp = p->p_fd->fd_ofiles[args->fd];
struct file *fp = p->p_fd->fd_ofiles[args->fd];
#endif
u_long cmd = args->cmd;
caddr_t data = (caddr_t) args->arg;
/*
* Pass the ioctl off to our standard handler.
*/
return(fo_ioctl(fp, cmd, data, p));
if ( size > STK_PARAMS ) {
if ( size > IOCPARM_MAX )
return EINVAL;
memp = malloc( (u_long)size, DRM(M_DRM), M_WAITOK );
data = memp;
} else {
data = ubuf.stkbuf;
}
if ( cmd & LINUX_IOC_IN ) {
if ( size ) {
error = copyin( (caddr_t)args->arg, data, (u_int)size );
if (error) {
if ( memp )
free( data, DRM(M_DRM) );
return error;
}
} else {
data = (caddr_t)args->arg;
}
} else if ( (cmd & LINUX_IOC_OUT) && size ) {
/*
* Zero the buffer so the user always
* gets back something deterministic.
*/
bzero( data, size );
} else if ( cmd & LINUX_IOC_VOID ) {
*(caddr_t *)data = (caddr_t)args->arg;
}
#if (__FreeBSD_version >= 500000)
if ( (error = fget( p, args->fd, &fp )) != 0 ) {
if ( memp )
free( memp, DRM(M_DRM) );
return (error);
}
error = fo_ioctl( fp, cmd, data, p->td_ucred, p );
fdrop( fp, p );
#else
error = fo_ioctl( fp, cmd, data, p );
#endif
if ( error == 0 && (cmd & LINUX_IOC_OUT) && size )
error = copyout( data, (caddr_t)args->arg, (u_int)size );
if ( memp )
free( memp, DRM(M_DRM) );
return error;
}
#endif /* DRM_LINUX */

View file

@ -65,7 +65,6 @@
#include <sys/proc.h>
#include <machine/../linux/linux.h>
#include <machine/../linux/linux_proto.h>
#include "drm_linux.h"
#endif
#define DRM_TIME_SLICE (hz/20) /* Time slice for GLXContexts */
@ -140,14 +139,18 @@ do { \
} \
} while (0)
#define DRM_COPY_TO_USER_IOCTL(arg1, arg2, arg3) \
*arg1 = arg2
#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \
arg1 = *arg2
#define DRM_COPY_TO_USER(arg1, arg2, arg3) \
copyout(arg2, arg1, arg3)
#define DRM_COPY_FROM_USER(arg1, arg2, arg3) \
copyin(arg2, arg1, arg3)
#define DRM_COPY_TO_USER_IOCTL(user, kern, size) \
if ( IOCPARM_LEN(cmd) != size) \
return EINVAL; \
*user = kern;
#define DRM_COPY_FROM_USER_IOCTL(kern, user, size) \
if ( IOCPARM_LEN(cmd) != size) \
return EINVAL; \
kern = *user;
#define DRM_COPY_TO_USER(user, kern, size) \
copyout(kern, user, size)
#define DRM_COPY_FROM_USER(kern, user, size) \
copyin(user, kern, size)
/* Macros for userspace access with checking readability once */
/* FIXME: can't find equivalent functionality for nocheck yet.
* It's be slower than linux, but should be correct.