Make the old compat functions use the sysctl front door, rather than

crashing through the walls.
This should save Peters blood pressure and netscapes uname call.
This commit is contained in:
Poul-Henning Kamp 1995-11-09 20:22:12 +00:00
parent a4cc272814
commit b8da239623
2 changed files with 137 additions and 94 deletions

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
* $Id: kern_sysctl.c,v 1.31 1995/11/06 16:18:52 phk Exp $
* $Id: kern_sysctl.c,v 1.32 1995/11/08 08:46:01 phk Exp $
*/
/*
@ -183,7 +183,7 @@ sysctl_order_cmp(void *a, void *b)
static void
sysctl_order(void *arg)
{
int j,k;
int j;
struct linker_set *l = (struct linker_set *) arg;
struct sysctl_oid **oidpp;
@ -223,7 +223,7 @@ sysctl_sysctl_debug_dump_node(struct linker_set *l,int i)
printf(" ");
if ((*oidpp)->oid_number > 100) {
printf("Junk! %p nm %x # %x k %x a1 %x a2 %x h %x\n",
printf("Junk! %p # %d %s k %x a1 %p a2 %x h %p\n",
*oidpp,
(*oidpp)->oid_number, (*oidpp)->oid_name,
(*oidpp)->oid_kind, (*oidpp)->oid_arg1,
@ -371,15 +371,6 @@ static struct sysctl_lock {
int sl_locked;
} memlock;
struct sysctl_args {
int *name;
u_int namelen;
void *old;
size_t *oldlenp;
void *new;
size_t newlen;
};
/*
@ -444,25 +435,22 @@ sysctl_root SYSCTL_HANDLER_ARGS
return (i);
}
struct sysctl_args {
int *name;
u_int namelen;
void *old;
size_t *oldlenp;
void *new;
size_t newlen;
};
int
__sysctl(p, uap, retval)
struct proc *p;
register struct sysctl_args *uap;
int *retval;
{
int error, dolock = 1, i;
u_int savelen = 0, oldlen = 0;
sysctlfn *fn;
int name[CTL_MAXNAME];
void *oldp = 0;
void *newp = 0;
if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag)))
return (error);
/*
* all top-level sysctl names are non-terminal
*/
int error, name[CTL_MAXNAME];
if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
return (EINVAL);
@ -471,16 +459,43 @@ __sysctl(p, uap, retval)
if (error)
return (error);
if (uap->oldlenp &&
(error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen))))
return (userland_sysctl(p, name, uap->namelen,
uap->old, uap->oldlenp, 0,
uap->new, uap->newlen, retval));
}
/*
* This is used from various compatibility syscalls too. That's why name
* must be in kernel space.
*/
int
userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen, int *retval)
{
int error = 0, dolock = 1, i;
u_int savelen = 0, oldlen = 0;
sysctlfn *fn;
void *oldp = 0;
void *newp = 0;
if (new != NULL && (error = suser(p->p_ucred, &p->p_acflag)))
return (error);
if (uap->old)
if (oldlenp) {
if (inkernel) {
oldlen = *oldlenp;
} else {
error = copyin(oldlenp, &oldlen, sizeof(oldlen));
if (error)
return (error);
}
}
if (old)
oldp = malloc(oldlen, M_TEMP, M_WAITOK);
if (uap->newlen) {
newp = malloc(uap->newlen, M_TEMP, M_WAITOK);
error = copyin(uap->new, newp, uap->newlen);
if (newlen) {
newp = malloc(newlen, M_TEMP, M_WAITOK);
error = copyin(new, newp, newlen);
}
if (error) {
if (oldp)
@ -490,17 +505,21 @@ __sysctl(p, uap, retval)
return error;
}
error = sysctl_root(0, name, uap->namelen, oldp, &oldlen,
newp, uap->newlen);
error = sysctl_root(0, name, namelen, oldp, &oldlen,
newp, newlen);
if (!error || error == ENOMEM) {
if (uap->oldlenp) {
i = copyout(&oldlen, uap->oldlenp, sizeof(oldlen));
if (i)
error = i;
if (oldlenp) {
if (inkernel) {
*oldlenp = oldlen;
} else {
i = copyout(&oldlen, oldlenp, sizeof(oldlen));
if (i)
error = i;
}
}
if ((error == ENOMEM || !error ) && oldp) {
i = copyout(oldp, uap->old, oldlen);
i = copyout(oldp, old, oldlen);
if (i)
error = i;
free(oldp, M_TEMP);
@ -544,8 +563,8 @@ __sysctl(p, uap, retval)
default:
return (EOPNOTSUPP);
}
if (uap->old != NULL) {
if (!useracc(uap->old, oldlen, B_WRITE))
if (old != NULL) {
if (!useracc(old, oldlen, B_WRITE))
return (EFAULT);
while (memlock.sl_lock) {
memlock.sl_want = 1;
@ -554,18 +573,18 @@ __sysctl(p, uap, retval)
}
memlock.sl_lock = 1;
if (dolock)
vslock(uap->old, oldlen);
vslock(old, oldlen);
savelen = oldlen;
}
error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen,
uap->new, uap->newlen, p);
error = (*fn)(name + 1, namelen - 1, old, &oldlen,
new, newlen, p);
if (uap->old != NULL) {
if (old != NULL) {
if (dolock)
vsunlock(uap->old, savelen, B_WRITE);
vsunlock(old, savelen, B_WRITE);
memlock.sl_lock = 0;
if (memlock.sl_want) {
memlock.sl_want = 0;
@ -575,17 +594,23 @@ __sysctl(p, uap, retval)
#if 0
if (error) {
printf("SYSCTL_ERROR: ");
for(i=0;i<uap->namelen;i++)
for(i=0;i<namelen;i++)
printf("%d ", name[i]);
printf("= %d\n", error);
}
#endif
if (error)
return (error);
if (uap->oldlenp)
error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen));
*retval = oldlen;
return (0);
if (retval)
*retval = oldlen;
if (oldlenp) {
if (inkernel) {
*oldlenp = oldlen;
} else {
error = copyout(&oldlen, oldlenp, sizeof(oldlen));
}
}
return (error);
}
/*
@ -1170,54 +1195,64 @@ ogetkerninfo(p, uap, retval)
register struct getkerninfo_args *uap;
int *retval;
{
int error, name[5];
int error, name[6];
u_int size;
if (uap->size &&
(error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size))))
return (error);
switch (uap->op & 0xff00) {
case KINFO_RT:
name[0] = PF_ROUTE;
name[1] = 0;
name[2] = (uap->op & 0xff0000) >> 16;
name[3] = uap->op & 0xff;
name[4] = uap->arg;
error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p);
name[0] = CTL_NET;
name[1] = PF_ROUTE;
name[2] = 0;
name[3] = (uap->op & 0xff0000) >> 16;
name[4] = uap->op & 0xff;
name[5] = uap->arg;
error = userland_sysctl(p, name, 6, uap->where, uap->size,
0, 0, 0, 0);
break;
case KINFO_VNODE:
name[0] = KERN_VNODE;
error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
name[0] = CTL_KERN;
name[1] = KERN_VNODE;
error = userland_sysctl(p, name, 2, uap->where, uap->size,
0, 0, 0, 0);
break;
case KINFO_PROC:
name[0] = KERN_PROC;
name[1] = uap->op & 0xff;
name[2] = uap->arg;
error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p);
name[0] = CTL_KERN;
name[1] = KERN_PROC;
name[2] = uap->op & 0xff;
name[3] = uap->arg;
error = userland_sysctl(p, name, 4, uap->where, uap->size,
0, 0, 0, 0);
break;
case KINFO_FILE:
name[0] = KERN_FILE;
error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
name[0] = CTL_KERN;
name[1] = KERN_FILE;
error = userland_sysctl(p, name, 2, uap->where, uap->size,
0, 0, 0, 0);
break;
case KINFO_METER:
name[0] = VM_METER;
error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p);
name[0] = CTL_VM;
name[1] = VM_METER;
error = userland_sysctl(p, name, 2, uap->where, uap->size,
0, 0, 0, 0);
break;
case KINFO_LOADAVG:
name[0] = VM_LOADAVG;
error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p);
name[0] = CTL_VM;
name[1] = VM_LOADAVG;
error = userland_sysctl(p, name, 2, uap->where, uap->size,
0, 0, 0, 0);
break;
case KINFO_CLOCKRATE:
name[0] = KERN_CLOCKRATE;
error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
name[0] = CTL_KERN;
name[1] = KERN_CLOCKRATE;
error = userland_sysctl(p, name, 2, uap->where, uap->size,
0, 0, 0, 0);
break;
case KINFO_BSDI_SYSINFO: {

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)kern_xxx.c 8.2 (Berkeley) 11/14/93
* $Id: kern_xxx.c,v 1.13 1995/08/20 04:42:25 davidg Exp $
* $Id: kern_xxx.c,v 1.14 1995/09/06 15:23:20 nate Exp $
*/
#include <sys/param.h>
@ -94,10 +94,12 @@ ogethostname(p, uap, retval)
struct gethostname_args *uap;
int *retval;
{
int name;
int name[2];
name = KERN_HOSTNAME;
return (kern_sysctl(&name, 1, uap->hostname, &uap->len, 0, 0, p));
name[0] = CTL_KERN;
name[1] = KERN_HOSTNAME;
return (userland_sysctl(p, name, 2, uap->hostname, &uap->len,
1, 0, 0, 0));
}
struct sethostname_args {
@ -111,13 +113,15 @@ osethostname(p, uap, retval)
register struct sethostname_args *uap;
int *retval;
{
int name;
int name[2];
int error;
name[0] = CTL_KERN;
name[1] = KERN_HOSTNAME;
if ((error = suser(p->p_ucred, &p->p_acflag)))
return (error);
name = KERN_HOSTNAME;
return (kern_sysctl(&name, 1, 0, 0, uap->hostname, uap->len, p));
return (userland_sysctl(p, name, 2, 0, 0, 0,
uap->hostname, uap->len, 0));
}
struct gethostid_args {
@ -188,33 +192,36 @@ uname(p, uap, retval)
struct uname_args *uap;
int *retval;
{
int name;
int len;
int rtval;
int name[2], len, rtval, junk;
char *s, *us;
name = KERN_OSTYPE;
name[0] = CTL_KERN;
name[1] = KERN_OSTYPE;
len = sizeof uap->name->sysname;
rtval = kern_sysctl(&name, 1, uap->name->sysname, &len, 0, 0, p);
rtval = userland_sysctl(p, name, 2, uap->name->sysname, &len,
1, 0, 0, 0);
if( rtval) return rtval;
subyte( uap->name->sysname + sizeof(uap->name->sysname) - 1, 0);
name = KERN_HOSTNAME;
name[1] = KERN_HOSTNAME;
len = sizeof uap->name->nodename;
rtval = kern_sysctl(&name, 1, uap->name->nodename, &len, 0, 0, p);
rtval = userland_sysctl(p, name, 2, uap->name->nodename, &len,
1, 0, 0, 0);
if( rtval) return rtval;
subyte( uap->name->nodename + sizeof(uap->name->nodename) - 1, 0);
name = KERN_OSRELEASE;
name[1] = KERN_OSRELEASE;
len = sizeof uap->name->release;
rtval = kern_sysctl(&name, 1, uap->name->release, &len, 0, 0, p);
rtval = userland_sysctl(p, name, 2, uap->name->release, &len,
1, 0, 0, 0);
if( rtval) return rtval;
subyte( uap->name->release + sizeof(uap->name->release) - 1, 0);
/*
name = KERN_VERSION;
len = sizeof uap->name->version;
rtval = kern_sysctl(&name, 1, uap->name->version, &len, 0, 0, p);
rtval = userland_sysctl(p, name, 2, uap->name->version, &len,
1, 0, 0, 0);
if( rtval) return rtval;
subyte( uap->name->version + sizeof(uap->name->version) - 1, 0);
*/
@ -233,9 +240,10 @@ uname(p, uap, retval)
if( rtval)
return rtval;
name = HW_MACHINE;
name[1] = HW_MACHINE;
len = sizeof uap->name->machine;
rtval = hw_sysctl(&name, 1, uap->name->machine, &len, 0, 0, p);
rtval = userland_sysctl(p, name, 2, uap->name->machine, &len,
1, 0, 0, 0);
if( rtval) return rtval;
subyte( uap->name->machine + sizeof(uap->name->machine) - 1, 0);