Date: Fri, 19 Dec 1997 23:32:20 +1100 From: Bruce Evans <bde@zeta.org.au> To: hasty@rah.star-gate.com, pb@fasterix.freenix.org Cc: current@FreeBSD.ORG, gjp@erols.com, gjp@erols.net Subject: Re: cvs commit: src/sys/i386/linux linux.h linux_ioctl.c Message-ID: <199712191232.XAA12685@godzilla.zeta.org.au>
next in thread | raw e-mail | index | archive | help
>With respect to ioperm , I moved linux_ioperm from linux_dummy.c to
>linux_misc.c and just have this for now:
>
>
>int
>linux_ioperm(struct proc *p, struct linux_ioperm_args *args)
>{
> int error;
>
> error = suser(p->p_ucred, &p->p_acflag);
> if (error != 0)
> return error;
> if (securelevel > 0)
> return EPERM;
> p->p_md.md_regs->tf_eflags |= PSL_IOPL;
> return 0;
>}
That's not what Linux ioperm does. Linux ioperm sets or clears bits in
the i/o permissions bitmap. It is like FreeBSD ioperm except it has a
cleaner interface and is presumably less buggy. FreeBSD ioperm is not
completely implemented. It is only available if the kernel was configured
with `options "VM86"'. It is a subcall of sysarch(undocumented). You
have to pass it a pointer to a poorly laid out struct giving the args,
something like this:
Linux: int ioperm(u_long from, u_long num, int turn_on);
FreeBSD: struct i386_ioperm_args { u_short from, num; u_char turn_on; } foo;
sysarch(I386_SET_IOPERM, /* XXX 1970's interface */ (char *)&foo);
Here are some fixes for the bugs. They are untested.
diff -c2 sys_machdep.c~ sys_machdep.c
*** sys_machdep.c~ Fri Nov 28 14:37:35 1997
--- sys_machdep.c Fri Nov 28 17:28:16 1997
***************
*** 181,185 ****
char *args;
{
! int i, error = 0;
struct i386_ioperm_args ua;
char *iomap;
--- 181,185 ----
char *args;
{
! int i, error;
struct i386_ioperm_args ua;
char *iomap;
***************
*** 188,194 ****
return (error);
- /* Only root can do this */
if (error = suser(p->p_ucred, &p->p_acflag))
return (error);
/*
* XXX
--- 188,195 ----
return (error);
if (error = suser(p->p_ucred, &p->p_acflag))
return (error);
+ if (securelevel > 0)
+ return (EPERM);
/*
* XXX
***************
*** 203,207 ****
iomap = (char *)p->p_addr->u_pcb.pcb_ext->ext_iomap;
! if ((int)(ua.start + ua.length) > 0xffff)
return (EINVAL);
--- 204,208 ----
iomap = (char *)p->p_addr->u_pcb.pcb_ext->ext_iomap;
! if (ua.start + ua.length > IOPAGES * PAGE_SIZE * NBBY)
return (EINVAL);
***************
*** 220,224 ****
char *args;
{
! int i, state, error = 0;
struct i386_ioperm_args ua;
char *iomap;
--- 221,225 ----
char *args;
{
! int i, state, error;
struct i386_ioperm_args ua;
char *iomap;
***************
*** 226,229 ****
--- 227,232 ----
if (error = copyin(args, &ua, sizeof(struct i386_ioperm_args)))
return (error);
+ if (ua.start >= IOPAGES * PAGE_SIZE * NBBY)
+ return (EINVAL);
if (p->p_addr->u_pcb.pcb_ext == 0) {
***************
*** 234,237 ****
--- 237,242 ----
iomap = (char *)p->p_addr->u_pcb.pcb_ext->ext_iomap;
+ i = ua.start;
+ state = (iomap[i >> 3] >> (i & 7)) & 1;
ua.enable = !state;
ua.length = 1;
Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199712191232.XAA12685>
