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>