sunos_ioctl(): acquire a reference to the file.
This also fixes a locking botch reported in PR#25738.
This commit is contained in:
parent
2eabcd5e18
commit
c6c77837c9
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sunos_ioctl.c,v 1.48 2004/04/25 06:23:40 matt Exp $ */
|
||||
/* $NetBSD: sunos_ioctl.c,v 1.49 2004/06/01 10:27:39 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1993 Markus Wild.
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunos_ioctl.c,v 1.48 2004/04/25 06:23:40 matt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sunos_ioctl.c,v 1.49 2004/06/01 10:27:39 pk Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_execfmt.h"
|
||||
|
@ -422,11 +422,14 @@ sunos_sys_ioctl(l, v, retval)
|
|||
if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
|
||||
return EBADF;
|
||||
|
||||
FILE_USE(fp);
|
||||
|
||||
if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
|
||||
simple_unlock(&fp->f_slock);
|
||||
return EBADF;
|
||||
error = EBADF;
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = EPASSTHROUGH;
|
||||
ctl = fp->f_ops->fo_ioctl;
|
||||
|
||||
switch (SCARG(uap, com)) {
|
||||
|
@ -439,33 +442,38 @@ sunos_sys_ioctl(l, v, retval)
|
|||
|
||||
if ((error = copyin(SCARG(uap, data), (caddr_t)&disc,
|
||||
sizeof disc)) != 0)
|
||||
return error;
|
||||
break;
|
||||
|
||||
/* map SunOS NTTYDISC into our termios discipline */
|
||||
if (disc == 2)
|
||||
disc = 0;
|
||||
/* all other disciplines are not supported by NetBSD */
|
||||
if (disc)
|
||||
return ENXIO;
|
||||
if (disc) {
|
||||
error = ENXIO;
|
||||
break;
|
||||
}
|
||||
|
||||
return (*ctl)(fp, TIOCSETD, (caddr_t)&disc, p);
|
||||
error = (*ctl)(fp, TIOCSETD, (caddr_t)&disc, p);
|
||||
}
|
||||
case _IOW('t', 101, int): /* sun SUNOS_TIOCSSOFTCAR */
|
||||
{
|
||||
int x; /* unused */
|
||||
|
||||
return copyin((caddr_t)&x, SCARG(uap, data), sizeof x);
|
||||
error = copyin((caddr_t)&x, SCARG(uap, data), sizeof x);
|
||||
break;
|
||||
}
|
||||
case _IOR('t', 100, int): /* sun SUNOS_TIOCSSOFTCAR */
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
return copyout((caddr_t)&x, SCARG(uap, data), sizeof x);
|
||||
error = copyout((caddr_t)&x, SCARG(uap, data), sizeof x);
|
||||
break;
|
||||
}
|
||||
case _IO('t', 36): /* sun TIOCCONS, no parameters */
|
||||
{
|
||||
int on = 1;
|
||||
return (*ctl)(fp, TIOCCONS, (caddr_t)&on, p);
|
||||
error = (*ctl)(fp, TIOCCONS, (caddr_t)&on, p);
|
||||
break;
|
||||
}
|
||||
case _IOW('t', 37, struct sunos_ttysize):
|
||||
{
|
||||
|
@ -473,15 +481,16 @@ sunos_sys_ioctl(l, v, retval)
|
|||
struct sunos_ttysize ss;
|
||||
|
||||
if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
|
||||
return (error);
|
||||
break;
|
||||
|
||||
if ((error = copyin (SCARG(uap, data), &ss, sizeof (ss))) != 0)
|
||||
return error;
|
||||
break;
|
||||
|
||||
ws.ws_row = ss.ts_row;
|
||||
ws.ws_col = ss.ts_col;
|
||||
|
||||
return ((*ctl)(fp, TIOCSWINSZ, (caddr_t)&ws, p));
|
||||
error = (*ctl)(fp, TIOCSWINSZ, (caddr_t)&ws, p);
|
||||
break;
|
||||
}
|
||||
case _IOW('t', 38, struct sunos_ttysize):
|
||||
{
|
||||
|
@ -489,12 +498,13 @@ sunos_sys_ioctl(l, v, retval)
|
|||
struct sunos_ttysize ss;
|
||||
|
||||
if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
|
||||
return (error);
|
||||
break;
|
||||
|
||||
ss.ts_row = ws.ws_row;
|
||||
ss.ts_col = ws.ws_col;
|
||||
|
||||
return copyout ((caddr_t)&ss, SCARG(uap, data), sizeof (ss));
|
||||
error = copyout((caddr_t)&ss, SCARG(uap, data), sizeof (ss));
|
||||
break;
|
||||
}
|
||||
case _IOR('t', 119, int): /* TIOCGPGRP */
|
||||
{
|
||||
|
@ -502,10 +512,11 @@ sunos_sys_ioctl(l, v, retval)
|
|||
|
||||
error = (*ctl)(fp, TIOCGPGRP, (caddr_t)&pgrp, p);
|
||||
if (error == 0 && pgrp == 0)
|
||||
return (EIO);
|
||||
error = EIO;
|
||||
if (error)
|
||||
return (error);
|
||||
return copyout((caddr_t)&pgrp, SCARG(uap, data), sizeof(pgrp));
|
||||
break;
|
||||
error = copyout((caddr_t)&pgrp, SCARG(uap, data), sizeof(pgrp));
|
||||
break;
|
||||
}
|
||||
case _IOW('t', 130, int): /* TIOCSETPGRP: posix variant */
|
||||
SCARG(uap, com) = TIOCSPGRP;
|
||||
|
@ -528,9 +539,10 @@ sunos_sys_ioctl(l, v, retval)
|
|||
vp->v_type == VCHR &&
|
||||
major(vp->v_rdev) == 21)
|
||||
error = ENOTTY;
|
||||
return (error);
|
||||
break;
|
||||
}
|
||||
return copyout((caddr_t)&pgrp, SCARG(uap, data), sizeof(pgrp));
|
||||
error = copyout((caddr_t)&pgrp, SCARG(uap, data), sizeof(pgrp));
|
||||
break;
|
||||
}
|
||||
case _IO('t', 132):
|
||||
SCARG(uap, com) = TIOCSCTTY;
|
||||
|
@ -543,17 +555,17 @@ sunos_sys_ioctl(l, v, retval)
|
|||
struct sunos_termio st;
|
||||
|
||||
if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
|
||||
return error;
|
||||
break;
|
||||
|
||||
btios2stios (&bts, &sts);
|
||||
if (SCARG(uap, com) == SUNOS_TCGETA) {
|
||||
stios2stio (&sts, &st);
|
||||
return copyout((caddr_t)&st, SCARG(uap, data),
|
||||
error = copyout((caddr_t)&st, SCARG(uap, data),
|
||||
sizeof (st));
|
||||
} else
|
||||
return copyout((caddr_t)&sts, SCARG(uap, data),
|
||||
error = copyout((caddr_t)&sts, SCARG(uap, data),
|
||||
sizeof (sts));
|
||||
/*NOTREACHED*/
|
||||
break;
|
||||
}
|
||||
case SUNOS_TCSETA:
|
||||
case SUNOS_TCSETAW:
|
||||
|
@ -565,11 +577,11 @@ sunos_sys_ioctl(l, v, retval)
|
|||
|
||||
if ((error = copyin(SCARG(uap, data), (caddr_t)&st,
|
||||
sizeof (st))) != 0)
|
||||
return error;
|
||||
break;
|
||||
|
||||
/* get full BSD termios so we don't lose information */
|
||||
if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
|
||||
return error;
|
||||
break;
|
||||
|
||||
/*
|
||||
* convert to sun termios, copy in information from
|
||||
|
@ -579,8 +591,9 @@ sunos_sys_ioctl(l, v, retval)
|
|||
stio2stios(&st, &sts);
|
||||
stios2btios(&sts, &bts);
|
||||
|
||||
return (*ctl)(fp, SCARG(uap, com) - SUNOS_TCSETA + TIOCSETA,
|
||||
error = (*ctl)(fp, SCARG(uap, com) - SUNOS_TCSETA + TIOCSETA,
|
||||
(caddr_t)&bts, p);
|
||||
break;
|
||||
}
|
||||
case SUNOS_TCSETS:
|
||||
case SUNOS_TCSETSW:
|
||||
|
@ -591,10 +604,11 @@ sunos_sys_ioctl(l, v, retval)
|
|||
|
||||
if ((error = copyin (SCARG(uap, data), (caddr_t)&sts,
|
||||
sizeof (sts))) != 0)
|
||||
return error;
|
||||
break;
|
||||
stios2btios (&sts, &bts);
|
||||
return (*ctl)(fp, SCARG(uap, com) - SUNOS_TCSETS + TIOCSETA,
|
||||
error = (*ctl)(fp, SCARG(uap, com) - SUNOS_TCSETS + TIOCSETA,
|
||||
(caddr_t)&bts, p);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Pseudo-tty ioctl translations.
|
||||
|
@ -604,16 +618,18 @@ sunos_sys_ioctl(l, v, retval)
|
|||
|
||||
error = copyin (SCARG(uap, data), (caddr_t)&on, sizeof (on));
|
||||
if (error)
|
||||
return error;
|
||||
return (*ctl)(fp, TIOCUCNTL, (caddr_t)&on, p);
|
||||
break;
|
||||
error = (*ctl)(fp, TIOCUCNTL, (caddr_t)&on, p);
|
||||
break;
|
||||
}
|
||||
case _IOW('t', 33, int): { /* TIOCSIGNAL */
|
||||
int error, sig;
|
||||
|
||||
error = copyin (SCARG(uap, data), (caddr_t)&sig, sizeof (sig));
|
||||
if (error)
|
||||
return error;
|
||||
return (*ctl)(fp, TIOCSIG, (caddr_t)&sig, p);
|
||||
break;
|
||||
error = (*ctl)(fp, TIOCSIG, (caddr_t)&sig, p);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -623,41 +639,36 @@ sunos_sys_ioctl(l, v, retval)
|
|||
struct ifreq ifreq; \
|
||||
error = copyin (SCARG(uap, data), (caddr_t)&ifreq, sizeof (ifreq)); \
|
||||
if (error) \
|
||||
return error; \
|
||||
return (*ctl)(fp, a, (caddr_t)&ifreq, p); \
|
||||
break; \
|
||||
error = (*ctl)(fp, a, (caddr_t)&ifreq, p); \
|
||||
break; \
|
||||
}
|
||||
#define IFREQ_INOUT(a) { \
|
||||
struct ifreq ifreq; \
|
||||
error = copyin (SCARG(uap, data), (caddr_t)&ifreq, sizeof (ifreq)); \
|
||||
if (error) \
|
||||
return error; \
|
||||
break; \
|
||||
if ((error = (*ctl)(fp, a, (caddr_t)&ifreq, p)) != 0) \
|
||||
return error; \
|
||||
return copyout ((caddr_t)&ifreq, SCARG(uap, data), sizeof (ifreq)); \
|
||||
break; \
|
||||
error = copyout ((caddr_t)&ifreq, SCARG(uap, data), sizeof (ifreq)); \
|
||||
break; \
|
||||
}
|
||||
|
||||
case _IOW('i', 12, struct ifreq):
|
||||
/* SIOCSIFADDR */
|
||||
case _IOW('i', 12, struct ifreq): /* SIOCSIFADDR */
|
||||
case _IOW('i', 14, struct ifreq): /* SIOCSIFDSTADDR */
|
||||
case _IOW('i', 16, struct ifreq): /* SIOCSIFFLAGS */
|
||||
case _IOWR('i', 17, struct ifreq): /* SIOCGIFFLAGS */
|
||||
case _IOW('i', 30, struct arpreq): /* SIOCSARP */
|
||||
case _IOWR('i', 31, struct arpreq): /* SIOCGARP */
|
||||
case _IOW('i', 32, struct arpreq): /* SIOCDARP */
|
||||
break;
|
||||
|
||||
case _IOWR('i', 13, struct ifreq):
|
||||
IFREQ_INOUT(OSIOCGIFADDR);
|
||||
|
||||
case _IOW('i', 14, struct ifreq):
|
||||
/* SIOCSIFDSTADDR */
|
||||
break;
|
||||
|
||||
case _IOWR('i', 15, struct ifreq):
|
||||
IFREQ_INOUT(OSIOCGIFDSTADDR);
|
||||
|
||||
case _IOW('i', 16, struct ifreq):
|
||||
/* SIOCSIFFLAGS */
|
||||
break;
|
||||
|
||||
case _IOWR('i', 17, struct ifreq):
|
||||
/* SIOCGIFFLAGS */
|
||||
break;
|
||||
|
||||
case _IOW('i', 21, struct ifreq):
|
||||
IFREQ_IN(SIOCSIFMTU);
|
||||
|
||||
|
@ -682,18 +693,6 @@ sunos_sys_ioctl(l, v, retval)
|
|||
case _IOWR('i', 28, struct ifreq):
|
||||
IFREQ_IN(SIOCSIFMETRIC);
|
||||
|
||||
case _IOW('i', 30, struct arpreq):
|
||||
/* SIOCSARP */
|
||||
break;
|
||||
|
||||
case _IOWR('i', 31, struct arpreq):
|
||||
/* SIOCGARP */
|
||||
break;
|
||||
|
||||
case _IOW('i', 32, struct arpreq):
|
||||
/* SIOCDARP */
|
||||
break;
|
||||
|
||||
case _IOW('i', 18, struct ifreq): /* SIOCSIFMEM */
|
||||
case _IOWR('i', 19, struct ifreq): /* SIOCGIFMEM */
|
||||
case _IOW('i', 40, struct ifreq): /* SIOCUPPER */
|
||||
|
@ -705,7 +704,8 @@ sunos_sys_ioctl(l, v, retval)
|
|||
case _IOW('i', 48, int): /* SIOCSPROMISC */
|
||||
case _IOW('i', 49, struct ifreq): /* SIOCADDMULTI */
|
||||
case _IOW('i', 50, struct ifreq): /* SIOCDELMULTI */
|
||||
return EOPNOTSUPP;
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
|
||||
case _IOWR('i', 20, struct ifconf): /* SIOCGIFCONF */
|
||||
{
|
||||
|
@ -719,12 +719,13 @@ sunos_sys_ioctl(l, v, retval)
|
|||
error = copyin (SCARG(uap, data), (caddr_t)&ifconf,
|
||||
sizeof (ifconf));
|
||||
if (error)
|
||||
return error;
|
||||
break;
|
||||
error = (*ctl)(fp, OSIOCGIFCONF, (caddr_t)&ifconf, p);
|
||||
if (error)
|
||||
return error;
|
||||
return copyout ((caddr_t)&ifconf, SCARG(uap, data),
|
||||
break;
|
||||
error = copyout ((caddr_t)&ifconf, SCARG(uap, data),
|
||||
sizeof (ifconf));
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -738,7 +739,7 @@ sunos_sys_ioctl(l, v, retval)
|
|||
|
||||
error = (*ctl)(fp, AUDIO_GETINFO, (caddr_t)&aui, p);
|
||||
if (error)
|
||||
return error;
|
||||
break;
|
||||
|
||||
sunos_aui.play = *(struct sunos_audio_prinfo *)&aui.play;
|
||||
sunos_aui.record = *(struct sunos_audio_prinfo *)&aui.record;
|
||||
|
@ -758,8 +759,9 @@ sunos_sys_ioctl(l, v, retval)
|
|||
/*XXX*/sunos_aui.reserved[2] = 0;
|
||||
/*XXX*/sunos_aui.reserved[3] = 0;
|
||||
|
||||
return copyout ((caddr_t)&sunos_aui, SCARG(uap, data),
|
||||
error = copyout ((caddr_t)&sunos_aui, SCARG(uap, data),
|
||||
sizeof (sunos_aui));
|
||||
break;
|
||||
}
|
||||
|
||||
case _IOWR('A', 2, struct sunos_audio_info): /* AUDIO_SETINFO */
|
||||
|
@ -770,7 +772,7 @@ sunos_sys_ioctl(l, v, retval)
|
|||
error = copyin (SCARG(uap, data), (caddr_t)&sunos_aui,
|
||||
sizeof (sunos_aui));
|
||||
if (error)
|
||||
return error;
|
||||
break;
|
||||
|
||||
aui.play = *(struct audio_prinfo *)&sunos_aui.play;
|
||||
aui.record = *(struct audio_prinfo *)&sunos_aui.record;
|
||||
|
@ -801,17 +803,19 @@ sunos_sys_ioctl(l, v, retval)
|
|||
|
||||
error = (*ctl)(fp, AUDIO_SETINFO, (caddr_t)&aui, p);
|
||||
if (error)
|
||||
return error;
|
||||
break;
|
||||
/* Return new state */
|
||||
goto sunos_au_getinfo;
|
||||
}
|
||||
case _IO('A', 3): /* AUDIO_DRAIN */
|
||||
return (*ctl)(fp, AUDIO_DRAIN, (void *)0, p);
|
||||
error = (*ctl)(fp, AUDIO_DRAIN, (void *)0, p);
|
||||
break;
|
||||
case _IOR('A', 4, int): /* AUDIO_GETDEV */
|
||||
{
|
||||
int devtype = SUNOS_AUDIO_DEV_AMD;
|
||||
return copyout ((caddr_t)&devtype, SCARG(uap, data),
|
||||
error = copyout ((caddr_t)&devtype, SCARG(uap, data),
|
||||
sizeof (devtype));
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -834,16 +838,19 @@ sunos_sys_ioctl(l, v, retval)
|
|||
case SUNOS_S_FLUSHW: tmp = FWRITE;
|
||||
case SUNOS_S_FLUSHRW: tmp = FREAD|FWRITE;
|
||||
}
|
||||
return (*ctl)(fp, TIOCFLUSH, (caddr_t)&tmp, p);
|
||||
error = (*ctl)(fp, TIOCFLUSH, (caddr_t)&tmp, p);
|
||||
break;
|
||||
}
|
||||
case _IO('S', 9): /* I_SETSIG */
|
||||
{
|
||||
int on = 1;
|
||||
if (((int)(u_long)SCARG(uap, data) &
|
||||
(SUNOS_S_HIPRI|SUNOS_S_INPUT)) ==
|
||||
SUNOS_S_HIPRI)
|
||||
return EOPNOTSUPP;
|
||||
return (*ctl)(fp, FIOASYNC, (caddr_t)&on, p);
|
||||
(SUNOS_S_HIPRI|SUNOS_S_INPUT)) == SUNOS_S_HIPRI) {
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
error = (*ctl)(fp, FIOASYNC, (caddr_t)&on, p);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* SunOS disk ioctls, taken from arch/sparc/sparc/disksubr.c
|
||||
|
@ -856,7 +863,7 @@ sunos_sys_ioctl(l, v, retval)
|
|||
|
||||
error = (*ctl)(fp, DIOCGDINFO, (caddr_t)&dl, p);
|
||||
if (error)
|
||||
return (error);
|
||||
break;
|
||||
|
||||
#define datageom ((struct sun_dkgeom *)SCARG(uap, data))
|
||||
memset(SCARG(uap, data), 0, sizeof(*datageom));
|
||||
|
@ -884,20 +891,31 @@ sunos_sys_ioctl(l, v, retval)
|
|||
|
||||
error = (*ctl)(fp, DIOCGPART, (caddr_t)&pi, p);
|
||||
if (error)
|
||||
return (error);
|
||||
break;
|
||||
|
||||
if (pi.disklab->d_secpercyl == 0) {
|
||||
error = ERANGE; /* XXX */
|
||||
break;
|
||||
}
|
||||
if (pi.part->p_offset % pi.disklab->d_secpercyl != 0) {
|
||||
error = ERANGE; /* XXX */
|
||||
break;
|
||||
}
|
||||
|
||||
if (pi.disklab->d_secpercyl == 0)
|
||||
return (ERANGE); /* XXX */
|
||||
if (pi.part->p_offset % pi.disklab->d_secpercyl != 0)
|
||||
return (ERANGE); /* XXX */
|
||||
#define datapart ((struct sun_dkpart *)SCARG(uap, data))
|
||||
datapart->sdkp_cyloffset = pi.part->p_offset / pi.disklab->d_secpercyl;
|
||||
datapart->sdkp_nsectors = pi.part->p_size;
|
||||
#undef datapart
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return (sys_ioctl(l, uap, retval));
|
||||
|
||||
out:
|
||||
FILE_UNUSE(fp, p);
|
||||
if (error == EPASSTHROUGH)
|
||||
error = sys_ioctl(l, uap, retval);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* SunOS fcntl(2) cmds not implemented */
|
||||
|
|
Loading…
Reference in New Issue