1999-12-14 22:35:36 +00:00
|
|
|
/* $NetBSD: osf1_misc.c,v 1.14 1998/05/20 16:34:29 chs Exp $ */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 1994, 1995 Carnegie-Mellon University.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Author: Chris G. Demetriou
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify and distribute this software and
|
|
|
|
* its documentation is hereby granted, provided that both the copyright
|
|
|
|
* notice and this permission notice appear in all copies of the
|
|
|
|
* software, derivative works or modified versions, and any portions
|
|
|
|
* thereof, and that both notices appear in supporting documentation.
|
|
|
|
*
|
|
|
|
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
|
|
|
|
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
|
|
|
|
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
|
|
|
|
*
|
|
|
|
* Carnegie Mellon requests users of this software to return to
|
|
|
|
*
|
|
|
|
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
|
|
|
|
* School of Computer Science
|
|
|
|
* Carnegie Mellon University
|
|
|
|
* Pittsburgh PA 15213-3890
|
|
|
|
*
|
|
|
|
* any improvements or extensions that they make and grant Carnegie the
|
|
|
|
* rights to redistribute these changes.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Additional Copyright (c) 1999 by Andrew Gallatin
|
|
|
|
* $FreeBSD$
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/bus.h>
|
|
|
|
#include <sys/dkstat.h>
|
|
|
|
#include <sys/exec.h>
|
|
|
|
#include <sys/fcntl.h>
|
1999-12-14 22:35:36 +00:00
|
|
|
#include <sys/filedesc.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/imgact.h>
|
1999-12-14 22:35:36 +00:00
|
|
|
#include <sys/kernel.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/lock.h>
|
1999-12-14 22:35:36 +00:00
|
|
|
#include <sys/malloc.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/file.h> /* Must come after sys/malloc.h */
|
1999-12-14 22:35:36 +00:00
|
|
|
#include <sys/mman.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/module.h>
|
1999-12-14 22:35:36 +00:00
|
|
|
#include <sys/mount.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/mutex.h>
|
|
|
|
#include <sys/namei.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/proc.h>
|
1999-12-14 22:35:36 +00:00
|
|
|
#include <sys/reboot.h>
|
|
|
|
#include <sys/resource.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/resourcevar.h>
|
|
|
|
#include <sys/selinfo.h>
|
|
|
|
#include <sys/pipe.h> /* Must come after sys/selinfo.h */
|
|
|
|
#include <sys/signal.h>
|
1999-12-14 22:35:36 +00:00
|
|
|
#include <sys/signalvar.h>
|
|
|
|
#include <sys/socket.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/socketvar.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <sys/sysent.h>
|
|
|
|
#include <sys/sysproto.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/unistd.h>
|
|
|
|
#include <sys/user.h>
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
#include <sys/vnode.h>
|
|
|
|
|
|
|
|
#include <alpha/osf1/exec_ecoff.h>
|
1999-12-14 22:35:36 +00:00
|
|
|
#include <alpha/osf1/osf1_signal.h>
|
|
|
|
#include <alpha/osf1/osf1_proto.h>
|
|
|
|
#include <alpha/osf1/osf1_syscall.h>
|
|
|
|
#include <alpha/osf1/osf1_util.h>
|
|
|
|
#include <alpha/osf1/osf1.h>
|
|
|
|
|
|
|
|
#include <vm/vm.h>
|
|
|
|
#include <vm/vm_kern.h>
|
|
|
|
#include <vm/vm_param.h>
|
|
|
|
#include <vm/pmap.h>
|
|
|
|
#include <vm/vm_map.h>
|
|
|
|
#include <vm/vm_extern.h>
|
|
|
|
|
|
|
|
#include <machine/cpu.h>
|
2000-10-25 00:14:11 +00:00
|
|
|
#include <machine/cpuconf.h>
|
1999-12-14 22:35:36 +00:00
|
|
|
#include <machine/fpu.h>
|
|
|
|
#include <machine/rpb.h>
|
|
|
|
|
2002-03-20 18:58:47 +00:00
|
|
|
static void cvtstat2osf1(struct stat *, struct osf1_stat *);
|
|
|
|
static int osf2bsd_pathconf(int *);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
static const char osf1_emul_path[] = "/compat/osf1";
|
|
|
|
/*
|
|
|
|
* [ taken from the linux emulator ]
|
|
|
|
* Search an alternate path before passing pathname arguments on
|
2001-02-06 10:39:38 +00:00
|
|
|
* to system calls. Useful for keeping a separate 'emulation tree'.
|
1999-12-14 22:35:36 +00:00
|
|
|
*
|
|
|
|
* If cflag is set, we check if an attempt can be made to create
|
|
|
|
* the named file, i.e. we check if the directory it should
|
|
|
|
* be in exists.
|
|
|
|
*/
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_emul_find(td, sgp, prefix, path, pbuf, cflag)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
caddr_t *sgp; /* Pointer to stackgap memory */
|
|
|
|
const char *prefix;
|
|
|
|
char *path;
|
|
|
|
char **pbuf;
|
|
|
|
int cflag;
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
size_t len, sz;
|
|
|
|
char *buf, *cp, *ptr;
|
2001-09-20 04:56:42 +00:00
|
|
|
struct ucred *ucred;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct nameidata nd;
|
|
|
|
struct nameidata ndroot;
|
|
|
|
struct vattr vat;
|
|
|
|
struct vattr vatroot;
|
|
|
|
|
|
|
|
buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
|
|
|
|
*pbuf = path;
|
|
|
|
|
|
|
|
for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
sz = MAXPATHLEN - (ptr - buf);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If sgp is not given then the path is already in kernel space
|
|
|
|
*/
|
|
|
|
if (sgp == NULL)
|
|
|
|
error = copystr(path, ptr, sz, &len);
|
|
|
|
else
|
|
|
|
error = copyinstr(path, ptr, sz, &len);
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
free(buf, M_TEMP);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*ptr != '/') {
|
|
|
|
free(buf, M_TEMP);
|
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We know that there is a / somewhere in this pathname.
|
|
|
|
* Search backwards for it, to find the file's parent dir
|
|
|
|
* to see if it exists in the alternate tree. If it does,
|
|
|
|
* and we want to create a file (cflag is set). We don't
|
|
|
|
* need to worry about the root comparison in this case.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (cflag) {
|
|
|
|
for (cp = &ptr[len] - 1; *cp != '/'; cp--)
|
|
|
|
;
|
|
|
|
*cp = '\0';
|
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
if ((error = namei(&nd)) != 0) {
|
|
|
|
free(buf, M_TEMP);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
*cp = '/';
|
|
|
|
} else {
|
2001-09-20 04:56:42 +00:00
|
|
|
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
if ((error = namei(&nd)) != 0) {
|
|
|
|
free(buf, M_TEMP);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We now compare the vnode of the osf1_root to the one
|
|
|
|
* vnode asked. If they resolve to be the same, then we
|
|
|
|
* ignore the match so that the real root gets used.
|
|
|
|
* This avoids the problem of traversing "../.." to find the
|
|
|
|
* root directory and never finding it, because "/" resolves
|
|
|
|
* to the emulation root directory. This is expensive :-(
|
|
|
|
*/
|
|
|
|
NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, osf1_emul_path,
|
2001-09-20 04:56:42 +00:00
|
|
|
td);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
if ((error = namei(&ndroot)) != 0) {
|
|
|
|
/* Cannot happen! */
|
|
|
|
free(buf, M_TEMP);
|
|
|
|
vrele(nd.ni_vp);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2002-02-27 18:32:23 +00:00
|
|
|
ucred = td->td_ucred;
|
2001-09-20 04:56:42 +00:00
|
|
|
if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
|
1999-12-14 22:35:36 +00:00
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
|
|
|
|
td)) != 0) {
|
1999-12-14 22:35:36 +00:00
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vat.va_fsid == vatroot.va_fsid &&
|
|
|
|
vat.va_fileid == vatroot.va_fileid) {
|
|
|
|
error = ENOENT;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
if (sgp == NULL)
|
|
|
|
*pbuf = buf;
|
|
|
|
else {
|
|
|
|
sz = &ptr[len] - buf;
|
|
|
|
*pbuf = stackgap_alloc(sgp, sz + 1);
|
|
|
|
error = copyout(buf, *pbuf, sz);
|
|
|
|
free(buf, M_TEMP);
|
|
|
|
}
|
|
|
|
|
|
|
|
vrele(nd.ni_vp);
|
|
|
|
if (!cflag)
|
|
|
|
vrele(ndroot.ni_vp);
|
|
|
|
|
|
|
|
return error;
|
|
|
|
|
|
|
|
bad:
|
|
|
|
vrele(ndroot.ni_vp);
|
|
|
|
vrele(nd.ni_vp);
|
|
|
|
free(buf, M_TEMP);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_open(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_open_args *uap;
|
|
|
|
{
|
|
|
|
struct open_args /* {
|
|
|
|
syscallarg(char *) path;
|
|
|
|
syscallarg(int) flags;
|
|
|
|
syscallarg(int) mode;
|
|
|
|
} */ a;
|
|
|
|
caddr_t sg;
|
|
|
|
|
|
|
|
sg = stackgap_init();
|
2001-09-20 04:56:42 +00:00
|
|
|
CHECKALTEXIST(td, &sg, uap->path);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
a.path = uap->path;
|
|
|
|
a.flags = uap->flags; /* XXX translate */
|
|
|
|
a.mode = uap->mode;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
return open(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
2002-08-30 04:04:37 +00:00
|
|
|
extern long totalphysmem;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_getsysinfo(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_getsysinfo_args *uap;
|
|
|
|
{
|
|
|
|
int error, retval;
|
2000-10-25 00:14:11 +00:00
|
|
|
int ncpus = 1; /* XXX until SMP */
|
|
|
|
int ophysmem;
|
|
|
|
int unit;
|
|
|
|
long percpu;
|
|
|
|
long proctype;
|
|
|
|
struct osf1_cpu_info cpuinfo;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
error = retval = 0;
|
|
|
|
|
|
|
|
switch(uap->op) {
|
2000-01-06 02:37:45 +00:00
|
|
|
case OSF_GET_MAX_UPROCS:
|
|
|
|
error = copyout(&maxprocperuid, uap->buffer,
|
|
|
|
sizeof(maxprocperuid));
|
|
|
|
retval = 1;
|
|
|
|
break;
|
2000-10-25 00:14:11 +00:00
|
|
|
case OSF_GET_PHYSMEM:
|
|
|
|
ophysmem = totalphysmem * (PAGE_SIZE >> 10);
|
|
|
|
error = copyout(&ophysmem, uap->buffer,
|
|
|
|
sizeof(ophysmem));
|
|
|
|
retval = 1;
|
|
|
|
break;
|
|
|
|
case OSF_GET_MAX_CPU:
|
|
|
|
case OSF_GET_CPUS_IN_BOX:
|
|
|
|
error = copyout(&ncpus, uap->buffer,
|
|
|
|
sizeof(ncpus));
|
|
|
|
retval = 1;
|
|
|
|
break;
|
1999-12-14 22:35:36 +00:00
|
|
|
case OSF_GET_IEEE_FP_CONTROL:
|
2001-09-20 04:56:42 +00:00
|
|
|
error = copyout(&td->td_pcb->pcb_fp_control,uap->buffer,
|
|
|
|
sizeof(td->td_pcb->pcb_fp_control));
|
1999-12-14 22:35:36 +00:00
|
|
|
retval = 1;
|
|
|
|
break;
|
2000-10-25 00:14:11 +00:00
|
|
|
case OSF_GET_CPU_INFO:
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2000-10-25 00:14:11 +00:00
|
|
|
if (uap->nbytes < sizeof(cpuinfo))
|
|
|
|
error = EINVAL;
|
|
|
|
else {
|
|
|
|
bzero(&cpuinfo, sizeof(cpuinfo));
|
|
|
|
unit = alpha_pal_whami();
|
|
|
|
cpuinfo.current_cpu = unit;
|
|
|
|
cpuinfo.cpus_in_box = ncpus;
|
|
|
|
cpuinfo.cpu_type =
|
|
|
|
LOCATE_PCS(hwrpb, unit)->pcs_proc_type;
|
|
|
|
cpuinfo.ncpus = ncpus;
|
|
|
|
cpuinfo.cpus_present = ncpus;
|
|
|
|
cpuinfo.cpus_running = ncpus;
|
|
|
|
cpuinfo.cpu_binding = 1;
|
|
|
|
cpuinfo.cpu_ex_binding = 0;
|
|
|
|
cpuinfo.mhz = hwrpb->rpb_cc_freq / 1000000;
|
|
|
|
error = copyout(&cpuinfo, uap->buffer,
|
|
|
|
sizeof(cpuinfo));
|
|
|
|
retval = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OSF_GET_PROC_TYPE:
|
1999-12-14 22:35:36 +00:00
|
|
|
if(uap->nbytes < sizeof(proctype))
|
|
|
|
error = EINVAL;
|
|
|
|
else {
|
|
|
|
unit = alpha_pal_whami();
|
|
|
|
proctype = LOCATE_PCS(hwrpb, unit)->pcs_proc_type;
|
|
|
|
error = copyout (&proctype, uap->buffer,
|
|
|
|
sizeof(percpu));
|
|
|
|
retval = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OSF_GET_HWRPB: { /* note -- osf/1 doesn't have rpb_tbhint[8] */
|
|
|
|
unsigned long rpb_size;
|
|
|
|
rpb_size = (unsigned long)&hwrpb->rpb_tbhint -
|
|
|
|
(unsigned long)hwrpb;
|
|
|
|
if(uap->nbytes < rpb_size){
|
|
|
|
uprintf("nbytes = %ld, sizeof(struct rpb) = %ld\n",
|
|
|
|
uap->nbytes, rpb_size);
|
|
|
|
error = EINVAL;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
error = copyout(hwrpb, uap->buffer, rpb_size);
|
|
|
|
retval = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2000-10-25 00:14:11 +00:00
|
|
|
case OSF_GET_PLATFORM_NAME:
|
|
|
|
error = copyout(platform.model, uap->buffer,
|
|
|
|
strlen(platform.model));
|
|
|
|
retval = 1;
|
|
|
|
break;
|
1999-12-14 22:35:36 +00:00
|
|
|
default:
|
|
|
|
printf("osf1_getsysinfo called with unknown op=%ld\n", uap->op);
|
|
|
|
return EINVAL;
|
|
|
|
}
|
2001-09-20 04:56:42 +00:00
|
|
|
td->td_retval[0] = retval;
|
1999-12-14 22:35:36 +00:00
|
|
|
return(error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_setsysinfo(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_setsysinfo_args *uap;
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
|
|
|
|
switch(uap->op) {
|
|
|
|
case OSF_SET_IEEE_FP_CONTROL:
|
|
|
|
{
|
|
|
|
u_int64_t temp, *fp_control;
|
|
|
|
|
|
|
|
if ((error = copyin(uap->buffer, &temp, sizeof(temp))))
|
|
|
|
break;
|
2001-09-20 04:56:42 +00:00
|
|
|
fp_control = &td->td_pcb->pcb_fp_control;
|
1999-12-14 22:35:36 +00:00
|
|
|
*fp_control = temp & IEEE_TRAP_ENABLE_MASK;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
uprintf("osf1_setsysinfo called with op=%ld\n", uap->op);
|
|
|
|
/*error = EINVAL;*/
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_getrlimit(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_getrlimit_args *uap;
|
|
|
|
{
|
|
|
|
struct __getrlimit_args /* {
|
|
|
|
syscallarg(u_int) which;
|
2000-10-25 00:37:34 +00:00
|
|
|
syscallarg(struct rlimit *) rlp;
|
1999-12-14 22:35:36 +00:00
|
|
|
} */ a;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->which >= OSF1_RLIMIT_NLIMITS)
|
1999-12-14 22:35:36 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->which <= OSF1_RLIMIT_LASTCOMMON)
|
|
|
|
a.which = uap->which;
|
|
|
|
else if (uap->which == OSF1_RLIMIT_NOFILE)
|
|
|
|
a.which = RLIMIT_NOFILE;
|
1999-12-14 22:35:36 +00:00
|
|
|
else
|
|
|
|
return (0);
|
2002-12-14 01:56:26 +00:00
|
|
|
a.rlp = (struct rlimit *)uap->rlp;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
return getrlimit(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_setrlimit(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_setrlimit_args *uap;
|
|
|
|
{
|
|
|
|
struct __setrlimit_args /* {
|
|
|
|
syscallarg(u_int) which;
|
2000-10-25 00:37:34 +00:00
|
|
|
syscallarg(struct rlimit *) rlp;
|
1999-12-14 22:35:36 +00:00
|
|
|
} */ a;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->which >= OSF1_RLIMIT_NLIMITS)
|
1999-12-14 22:35:36 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->which <= OSF1_RLIMIT_LASTCOMMON)
|
|
|
|
a.which = uap->which;
|
|
|
|
else if (uap->which == OSF1_RLIMIT_NOFILE)
|
|
|
|
a.which = RLIMIT_NOFILE;
|
1999-12-14 22:35:36 +00:00
|
|
|
else
|
|
|
|
return (0);
|
2002-12-14 01:56:26 +00:00
|
|
|
a.rlp = (struct rlimit *)uap->rlp;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
return setrlimit(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* As linux says, this is a total guess.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_set_program_attributes(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_set_program_attributes_args *uap;
|
|
|
|
{
|
2001-09-20 04:56:42 +00:00
|
|
|
struct vmspace *vm = td->td_proc->p_vmspace;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
vm->vm_taddr = (caddr_t)uap->text_start;
|
|
|
|
vm->vm_tsize = btoc(round_page(uap->text_len));
|
|
|
|
vm->vm_daddr = (caddr_t)uap->bss_start;
|
|
|
|
vm->vm_dsize = btoc(round_page(uap->bss_len));
|
|
|
|
|
|
|
|
return(KERN_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_mmap(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_mmap_args *uap;
|
|
|
|
{
|
|
|
|
struct mmap_args /* {
|
|
|
|
syscallarg(caddr_t) addr;
|
|
|
|
syscallarg(size_t) len;
|
|
|
|
syscallarg(int) prot;
|
|
|
|
syscallarg(int) flags;
|
|
|
|
syscallarg(int) fd;
|
|
|
|
syscallarg(long) pad;
|
|
|
|
syscallarg(off_t) pos;
|
|
|
|
} */ a;
|
|
|
|
int retval;
|
|
|
|
vm_map_t map;
|
|
|
|
vm_offset_t addr, len, newaddr;
|
|
|
|
|
2001-07-04 16:20:28 +00:00
|
|
|
GIANT_REQUIRED;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
a.addr = uap->addr;
|
|
|
|
a.len = uap->len;
|
|
|
|
a.prot = uap->prot;
|
|
|
|
a.fd = uap->fd;
|
|
|
|
a.pad = 0;
|
|
|
|
a.pos = uap->pos;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
a.flags = 0;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* OSF/1's mmap, unlike FreeBSD's, does its best to map memory at the
|
|
|
|
* user's requested address, even if MAP_FIXED is not set. Here we
|
|
|
|
* try to replicate this behaviour as much as we can because some
|
|
|
|
* applications (like /sbin/loader) depend on having things put as
|
|
|
|
* close to where they've requested as possible.
|
|
|
|
*/
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->addr != NULL)
|
|
|
|
addr = round_page((vm_offset_t)a.addr);
|
1999-12-14 22:35:36 +00:00
|
|
|
else
|
|
|
|
/*
|
|
|
|
* Try to use the apparent OSF/1 default placement of 0x10000 for
|
|
|
|
* NULL addrs, this helps to prevent non-64 bit clean binaries from
|
|
|
|
* SEGV'ing.
|
|
|
|
*/
|
|
|
|
addr = round_page((vm_offset_t)0x10000UL);
|
2002-12-14 01:56:26 +00:00
|
|
|
len = (vm_offset_t)a.len;
|
2001-09-20 04:56:42 +00:00
|
|
|
map = &td->td_proc->p_vmspace->vm_map;
|
1999-12-14 22:35:36 +00:00
|
|
|
if (!vm_map_findspace(map, addr, len, &newaddr)) {
|
2002-12-14 01:56:26 +00:00
|
|
|
a.addr = (caddr_t) newaddr;
|
|
|
|
a.flags |= (MAP_FIXED);
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
|
|
else
|
|
|
|
uprintf("osf1_mmap:vm_map_findspace failed for: %p 0x%lx\n",
|
|
|
|
(caddr_t)addr, len);
|
|
|
|
#endif
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->flags & OSF1_MAP_SHARED)
|
|
|
|
a.flags |= MAP_SHARED;
|
|
|
|
if (uap->flags & OSF1_MAP_PRIVATE)
|
|
|
|
a.flags |= MAP_PRIVATE;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
switch (uap->flags & OSF1_MAP_TYPE) {
|
1999-12-14 22:35:36 +00:00
|
|
|
case OSF1_MAP_ANONYMOUS:
|
2002-12-14 01:56:26 +00:00
|
|
|
a.flags |= MAP_ANON;
|
1999-12-14 22:35:36 +00:00
|
|
|
break;
|
|
|
|
case OSF1_MAP_FILE:
|
2002-12-14 01:56:26 +00:00
|
|
|
a.flags |= MAP_FILE;
|
1999-12-14 22:35:36 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->flags & OSF1_MAP_FIXED)
|
|
|
|
a.flags |= MAP_FIXED;
|
|
|
|
if (uap->flags & OSF1_MAP_HASSEMAPHORE)
|
|
|
|
a.flags |= MAP_HASSEMAPHORE;
|
|
|
|
if (uap->flags & OSF1_MAP_INHERIT)
|
2001-08-25 04:27:40 +00:00
|
|
|
return (EINVAL);
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->flags & OSF1_MAP_UNALIGNED)
|
1999-12-14 22:35:36 +00:00
|
|
|
return (EINVAL);
|
|
|
|
/*
|
|
|
|
* Emulate an osf/1 bug: Apparently, mmap'ed segments are always
|
|
|
|
* readable even if the user doesn't or in PROT_READ. This causes
|
|
|
|
* some buggy programs to segv.
|
|
|
|
*/
|
2002-12-14 01:56:26 +00:00
|
|
|
a.prot |= PROT_READ;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
retval = mmap(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
uprintf(
|
|
|
|
"\nosf1_mmap: addr=%p (%p), len = 0x%lx, prot=0x%x, fd=%d, pad=0, pos=0x%lx",
|
2002-12-14 01:56:26 +00:00
|
|
|
uap->addr, a.addr,uap->len, uap->prot,
|
|
|
|
uap->fd, uap->pos);
|
|
|
|
printf(" flags = 0x%x\n",uap->flags);
|
1999-12-14 22:35:36 +00:00
|
|
|
#endif
|
|
|
|
return (retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_msync(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_msync_args *uap;
|
|
|
|
{
|
|
|
|
struct msync_args a;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
a.addr = uap->addr;
|
|
|
|
a.len = uap->len;
|
1999-12-14 22:35:36 +00:00
|
|
|
a.flags = 0;
|
2002-12-14 01:56:26 +00:00
|
|
|
if(uap->flags & OSF1_MS_ASYNC)
|
|
|
|
a.flags |= MS_ASYNC;
|
|
|
|
if(uap->flags & OSF1_MS_SYNC)
|
|
|
|
a.flags |= MS_SYNC;
|
|
|
|
if(uap->flags & OSF1_MS_INVALIDATE)
|
|
|
|
a.flags |= MS_INVALIDATE;
|
2001-09-20 04:56:42 +00:00
|
|
|
return(msync(td, &a));
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct osf1_stat {
|
|
|
|
int32_t st_dev;
|
|
|
|
u_int32_t st_ino;
|
|
|
|
u_int32_t st_mode;
|
|
|
|
u_int16_t st_nlink;
|
|
|
|
u_int32_t st_uid;
|
|
|
|
u_int32_t st_gid;
|
|
|
|
int32_t st_rdev;
|
|
|
|
u_int64_t st_size;
|
|
|
|
int32_t st_atime_sec;
|
|
|
|
int32_t st_spare1;
|
|
|
|
int32_t st_mtime_sec;
|
|
|
|
int32_t st_spare2;
|
|
|
|
int32_t st_ctime_sec;
|
|
|
|
int32_t st_spare3;
|
|
|
|
u_int32_t st_blksize;
|
|
|
|
int32_t st_blocks;
|
|
|
|
u_int32_t st_flags;
|
|
|
|
u_int32_t st_gen;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get file status; this version follows links.
|
|
|
|
*/
|
|
|
|
/* ARGSUSED */
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_stat(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_stat_args *uap;
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
struct stat sb;
|
|
|
|
struct osf1_stat osb;
|
|
|
|
struct nameidata nd;
|
|
|
|
caddr_t sg;
|
|
|
|
|
|
|
|
sg = stackgap_init();
|
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
CHECKALTEXIST(td, &sg, uap->path);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
|
2002-12-14 01:56:26 +00:00
|
|
|
uap->path, td);
|
1999-12-14 22:35:36 +00:00
|
|
|
if ((error = namei(&nd)))
|
|
|
|
return (error);
|
Make similar changes to fo_stat() and fo_poll() as made earlier to
fo_read() and fo_write(): explicitly use the cred argument to fo_poll()
as "active_cred" using the passed file descriptor's f_cred reference
to provide access to the file credential. Add an active_cred
argument to fo_stat() so that implementers have access to the active
credential as well as the file credential. Generally modify callers
of fo_stat() to pass in td->td_ucred rather than fp->f_cred, which
was redundantly provided via the fp argument. This set of modifications
also permits threads to perform these operations on behalf of another
thread without modifying their credential.
Trickle this change down into fo_stat/poll() implementations:
- badfo_poll(), badfo_stat(): modify/add arguments.
- kqueue_poll(), kqueue_stat(): modify arguments.
- pipe_poll(), pipe_stat(): modify/add arguments, pass active_cred to
MAC checks rather than td->td_ucred.
- soo_poll(), soo_stat(): modify/add arguments, pass fp->f_cred rather
than cred to pru_sopoll() to maintain current semantics.
- sopoll(): moidfy arguments.
- vn_poll(), vn_statfile(): modify/add arguments, pass new arguments
to vn_stat(). Pass active_cred to MAC and fp->f_cred to VOP_POLL()
to maintian current semantics.
- vn_close(): rename cred to file_cred to reflect reality while I'm here.
- vn_stat(): Add active_cred and file_cred arguments to vn_stat()
and consumers so that this distinction is maintained at the VFS
as well as 'struct file' layer. Pass active_cred instead of
td->td_ucred to MAC and to VOP_GETATTR() to maintain current semantics.
- fifofs: modify the creation of a "filetemp" so that the file
credential is properly initialized and can be used in the socket
code if desired. Pass ap->a_td->td_ucred as the active
credential to soo_poll(). If we teach the vnop interface about
the distinction between file and active credentials, we would use
the active credential here.
Note that current inconsistent passing of active_cred vs. file_cred to
VOP's is maintained. It's not clear why GETATTR would be authorized
using active_cred while POLL would be authorized using file_cred at
the file system level.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-16 12:52:03 +00:00
|
|
|
error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
|
1999-12-14 22:35:36 +00:00
|
|
|
vput(nd.ni_vp);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
cvtstat2osf1(&sb, &osb);
|
2002-12-14 01:56:26 +00:00
|
|
|
error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
|
1999-12-14 22:35:36 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get file status; this version does not follow links.
|
|
|
|
*/
|
|
|
|
/* ARGSUSED */
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_lstat(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
register struct osf1_lstat_args *uap;
|
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
struct osf1_stat osb;
|
|
|
|
int error;
|
|
|
|
struct nameidata nd;
|
|
|
|
caddr_t sg = stackgap_init();
|
2001-01-24 10:27:11 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
CHECKALTEXIST(td, &sg, uap->path);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
|
2002-12-14 01:56:26 +00:00
|
|
|
uap->path, td);
|
1999-12-14 22:35:36 +00:00
|
|
|
if ((error = namei(&nd)))
|
|
|
|
return (error);
|
Make similar changes to fo_stat() and fo_poll() as made earlier to
fo_read() and fo_write(): explicitly use the cred argument to fo_poll()
as "active_cred" using the passed file descriptor's f_cred reference
to provide access to the file credential. Add an active_cred
argument to fo_stat() so that implementers have access to the active
credential as well as the file credential. Generally modify callers
of fo_stat() to pass in td->td_ucred rather than fp->f_cred, which
was redundantly provided via the fp argument. This set of modifications
also permits threads to perform these operations on behalf of another
thread without modifying their credential.
Trickle this change down into fo_stat/poll() implementations:
- badfo_poll(), badfo_stat(): modify/add arguments.
- kqueue_poll(), kqueue_stat(): modify arguments.
- pipe_poll(), pipe_stat(): modify/add arguments, pass active_cred to
MAC checks rather than td->td_ucred.
- soo_poll(), soo_stat(): modify/add arguments, pass fp->f_cred rather
than cred to pru_sopoll() to maintain current semantics.
- sopoll(): moidfy arguments.
- vn_poll(), vn_statfile(): modify/add arguments, pass new arguments
to vn_stat(). Pass active_cred to MAC and fp->f_cred to VOP_POLL()
to maintian current semantics.
- vn_close(): rename cred to file_cred to reflect reality while I'm here.
- vn_stat(): Add active_cred and file_cred arguments to vn_stat()
and consumers so that this distinction is maintained at the VFS
as well as 'struct file' layer. Pass active_cred instead of
td->td_ucred to MAC and to VOP_GETATTR() to maintain current semantics.
- fifofs: modify the creation of a "filetemp" so that the file
credential is properly initialized and can be used in the socket
code if desired. Pass ap->a_td->td_ucred as the active
credential to soo_poll(). If we teach the vnop interface about
the distinction between file and active credentials, we would use
the active credential here.
Note that current inconsistent passing of active_cred vs. file_cred to
VOP's is maintained. It's not clear why GETATTR would be authorized
using active_cred while POLL would be authorized using file_cred at
the file system level.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-16 12:52:03 +00:00
|
|
|
error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
|
1999-12-14 22:35:36 +00:00
|
|
|
vput(nd.ni_vp);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
cvtstat2osf1(&sb, &osb);
|
2002-12-14 01:56:26 +00:00
|
|
|
error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
|
1999-12-14 22:35:36 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return status information about a file descriptor.
|
|
|
|
*/
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_fstat(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
register struct osf1_fstat_args *uap;
|
|
|
|
{
|
2002-02-07 22:06:23 +00:00
|
|
|
struct file *fp;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct stat ub;
|
|
|
|
struct osf1_stat oub;
|
|
|
|
int error;
|
|
|
|
|
2002-01-14 00:13:45 +00:00
|
|
|
if ((error = fget(td, uap->fd, &fp)) != 0)
|
|
|
|
return (error);
|
Make similar changes to fo_stat() and fo_poll() as made earlier to
fo_read() and fo_write(): explicitly use the cred argument to fo_poll()
as "active_cred" using the passed file descriptor's f_cred reference
to provide access to the file credential. Add an active_cred
argument to fo_stat() so that implementers have access to the active
credential as well as the file credential. Generally modify callers
of fo_stat() to pass in td->td_ucred rather than fp->f_cred, which
was redundantly provided via the fp argument. This set of modifications
also permits threads to perform these operations on behalf of another
thread without modifying their credential.
Trickle this change down into fo_stat/poll() implementations:
- badfo_poll(), badfo_stat(): modify/add arguments.
- kqueue_poll(), kqueue_stat(): modify arguments.
- pipe_poll(), pipe_stat(): modify/add arguments, pass active_cred to
MAC checks rather than td->td_ucred.
- soo_poll(), soo_stat(): modify/add arguments, pass fp->f_cred rather
than cred to pru_sopoll() to maintain current semantics.
- sopoll(): moidfy arguments.
- vn_poll(), vn_statfile(): modify/add arguments, pass new arguments
to vn_stat(). Pass active_cred to MAC and fp->f_cred to VOP_POLL()
to maintian current semantics.
- vn_close(): rename cred to file_cred to reflect reality while I'm here.
- vn_stat(): Add active_cred and file_cred arguments to vn_stat()
and consumers so that this distinction is maintained at the VFS
as well as 'struct file' layer. Pass active_cred instead of
td->td_ucred to MAC and to VOP_GETATTR() to maintain current semantics.
- fifofs: modify the creation of a "filetemp" so that the file
credential is properly initialized and can be used in the socket
code if desired. Pass ap->a_td->td_ucred as the active
credential to soo_poll(). If we teach the vnop interface about
the distinction between file and active credentials, we would use
the active credential here.
Note that current inconsistent passing of active_cred vs. file_cred to
VOP's is maintained. It's not clear why GETATTR would be authorized
using active_cred while POLL would be authorized using file_cred at
the file system level.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
2002-08-16 12:52:03 +00:00
|
|
|
error = fo_stat(fp, &ub, td->td_ucred, td);
|
2002-01-13 11:58:06 +00:00
|
|
|
fdrop(fp, td);
|
1999-12-14 22:35:36 +00:00
|
|
|
cvtstat2osf1(&ub, &oub);
|
|
|
|
if (error == 0)
|
2002-12-14 01:56:26 +00:00
|
|
|
error = copyout((caddr_t)&oub, (caddr_t)uap->sb,
|
1999-12-14 22:35:36 +00:00
|
|
|
sizeof (oub));
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
#define bsd2osf_dev(dev) (umajor(dev) << 20 | uminor(dev))
|
|
|
|
#define osf2bsd_dev(dev) umakedev((umajor(dev) >> 20) & 0xfff, uminor(dev) & 0xfffff)
|
|
|
|
#else
|
|
|
|
#define minor(x) ((int)((x)&0xffff00ff))
|
|
|
|
#define major(x) ((int)(((u_int)(x) >> 8)&0xff))
|
|
|
|
#define makedev(x,y) ((dev_t)(((x) << 8) | (y)))
|
|
|
|
#define bsd2osf_dev(dev) (major(dev) << 20 | minor(dev))
|
|
|
|
#define osf2bsd_dev(dev) makedev(((dev) >> 20) & 0xfff, (dev) & 0xfffff)
|
|
|
|
#endif
|
|
|
|
/*
|
|
|
|
* Convert from a stat structure to an osf1 stat structure.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
cvtstat2osf1(st, ost)
|
|
|
|
struct stat *st;
|
|
|
|
struct osf1_stat *ost;
|
|
|
|
{
|
|
|
|
|
|
|
|
ost->st_dev = bsd2osf_dev(st->st_dev);
|
|
|
|
ost->st_ino = st->st_ino;
|
|
|
|
ost->st_mode = st->st_mode;
|
|
|
|
ost->st_nlink = st->st_nlink;
|
|
|
|
ost->st_uid = st->st_uid == -2 ? (u_int16_t) -2 : st->st_uid;
|
|
|
|
ost->st_gid = st->st_gid == -2 ? (u_int16_t) -2 : st->st_gid;
|
|
|
|
ost->st_rdev = bsd2osf_dev(st->st_rdev);
|
|
|
|
ost->st_size = st->st_size;
|
|
|
|
ost->st_atime_sec = st->st_atime;
|
|
|
|
ost->st_spare1 = 0;
|
|
|
|
ost->st_mtime_sec = st->st_mtime;
|
|
|
|
ost->st_spare2 = 0;
|
|
|
|
ost->st_ctime_sec = st->st_ctime;
|
|
|
|
ost->st_spare3 = 0;
|
|
|
|
ost->st_blksize = st->st_blksize;
|
|
|
|
ost->st_blocks = st->st_blocks;
|
|
|
|
ost->st_flags = st->st_flags;
|
|
|
|
ost->st_gen = st->st_gen;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_mknod(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_mknod_args *uap;
|
|
|
|
{
|
|
|
|
#if notanymore
|
|
|
|
struct mknod_args a;
|
|
|
|
caddr_t sg;
|
|
|
|
|
|
|
|
sg = stackgap_init();
|
2001-09-20 04:56:42 +00:00
|
|
|
CHECKALTEXIST(td, &sg, uap->path);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
a.path = uap->path;
|
|
|
|
a.mode = uap->mode;
|
|
|
|
a.dev = osf2bsd_dev(uap->dev);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
return mknod(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
#endif
|
|
|
|
printf("osf1_mknod no longer implemented\n");
|
|
|
|
return ENOSYS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_access(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_access_args *uap;
|
|
|
|
{
|
|
|
|
caddr_t sg;
|
|
|
|
|
|
|
|
sg = stackgap_init();
|
2001-09-20 04:56:42 +00:00
|
|
|
CHECKALTEXIST(td, &sg, uap->path);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
return access(td, (struct access_args *)uap);
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct osf1_flock {
|
|
|
|
short l_type;
|
|
|
|
short l_whence;
|
|
|
|
off_t l_start;
|
|
|
|
off_t l_len;
|
|
|
|
pid_t l_pid;
|
|
|
|
};
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_fcntl(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_fcntl_args *uap;
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
long tmp;
|
|
|
|
caddr_t oarg, sg;
|
|
|
|
struct fcntl_args a;
|
|
|
|
struct osf1_flock osf_flock;
|
|
|
|
struct flock bsd_flock;
|
|
|
|
struct flock *nflock;
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
switch (uap->cmd) {
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
case F_SETFL:
|
2002-12-14 01:56:26 +00:00
|
|
|
a.fd = uap->fd;
|
|
|
|
a.cmd = F_SETFL;
|
1999-12-14 22:35:36 +00:00
|
|
|
/* need to translate flags here */
|
|
|
|
tmp = 0;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((long)uap->arg & OSF1_FNONBLOCK)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= FNONBLOCK;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((long)uap->arg & OSF1_FAPPEND)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= FAPPEND;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((long)uap->arg & OSF1_FDEFER)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= FDEFER;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((long)uap->arg & OSF1_FASYNC)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= FASYNC;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((long)uap->arg & OSF1_FCREAT)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= O_CREAT;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((long)uap->arg & OSF1_FTRUNC)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= O_TRUNC;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((long)uap->arg & OSF1_FEXCL)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= O_EXCL;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((long)uap->arg & OSF1_FNDELAY)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= FNDELAY;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((long)uap->arg & OSF1_FSYNC)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= FFSYNC;
|
2002-12-14 01:56:26 +00:00
|
|
|
a.arg = tmp;
|
2001-09-20 04:56:42 +00:00
|
|
|
error = fcntl(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case F_SETLK:
|
|
|
|
case F_SETLKW:
|
|
|
|
case F_GETLK:
|
|
|
|
/*
|
|
|
|
* The OSF/1 flock stucture has a different order than
|
|
|
|
* the BSD one, but all else is the same. We must
|
|
|
|
* reorder the one we've gotten so that flock() groks it.
|
|
|
|
*/
|
|
|
|
if ((error = copyin(uap->arg, &osf_flock, sizeof(osf_flock))))
|
|
|
|
return error;
|
|
|
|
bsd_flock.l_type = osf_flock.l_type;
|
|
|
|
bsd_flock.l_whence = osf_flock.l_whence;
|
|
|
|
bsd_flock.l_start = osf_flock.l_start;
|
|
|
|
bsd_flock.l_len = osf_flock.l_len;
|
|
|
|
bsd_flock.l_pid = osf_flock.l_pid;
|
|
|
|
sg = stackgap_init();
|
|
|
|
nflock = stackgap_alloc(&sg, sizeof(struct flock));
|
|
|
|
if ((error = copyout(&bsd_flock, nflock, sizeof(bsd_flock))) != 0)
|
|
|
|
return error;
|
|
|
|
oarg = uap->arg;
|
|
|
|
uap->arg = nflock;
|
2001-09-20 04:56:42 +00:00
|
|
|
error = fcntl(td, (struct fcntl_args *) uap);
|
1999-12-14 22:35:36 +00:00
|
|
|
/* if (error) {
|
|
|
|
printf("fcntl called with cmd=%d, args=0x%lx\n returns %d\n",uap->cmd,(long)uap->arg,error);
|
|
|
|
printf("bsd_flock.l_type = 0x%x\n", bsd_flock.l_type);
|
|
|
|
printf("bsd_flock.l_whence = 0x%x\n", bsd_flock.l_whence);
|
|
|
|
printf("bsd_flock.l_start = 0x%lx\n", bsd_flock.l_start);
|
|
|
|
printf("bsd_flock.l_len = 0x%lx\n", bsd_flock.l_len);
|
|
|
|
printf("bsd_flock.l_pid = 0x%x\n", bsd_flock.l_pid);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
if ((uap->cmd == F_GETLK) && !error) {
|
|
|
|
osf_flock.l_type = F_UNLCK;
|
|
|
|
if ((error = copyout(&osf_flock, oarg,
|
|
|
|
sizeof(osf_flock))))
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2001-09-20 04:56:42 +00:00
|
|
|
error = fcntl(td, (struct fcntl_args *) uap);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
if ((uap->cmd == OSF1_F_GETFL) && !error ) {
|
2001-09-20 04:56:42 +00:00
|
|
|
tmp = td->td_retval[0] & O_ACCMODE;
|
|
|
|
if (td->td_retval[0] & FNONBLOCK)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= OSF1_FNONBLOCK;
|
2001-09-20 04:56:42 +00:00
|
|
|
if (td->td_retval[0] & FAPPEND)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= OSF1_FAPPEND;
|
2001-09-20 04:56:42 +00:00
|
|
|
if (td->td_retval[0] & FDEFER)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= OSF1_FDEFER;
|
2001-09-20 04:56:42 +00:00
|
|
|
if (td->td_retval[0] & FASYNC)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= OSF1_FASYNC;
|
2001-09-20 04:56:42 +00:00
|
|
|
if (td->td_retval[0] & O_CREAT)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= OSF1_FCREAT;
|
2001-09-20 04:56:42 +00:00
|
|
|
if (td->td_retval[0] & O_TRUNC)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= OSF1_FTRUNC;
|
2001-09-20 04:56:42 +00:00
|
|
|
if (td->td_retval[0] & O_EXCL)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= OSF1_FEXCL;
|
2001-09-20 04:56:42 +00:00
|
|
|
if (td->td_retval[0] & FNDELAY)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= OSF1_FNDELAY;
|
2001-09-20 04:56:42 +00:00
|
|
|
if (td->td_retval[0] & FFSYNC)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= OSF1_FSYNC;
|
2001-09-20 04:56:42 +00:00
|
|
|
td->td_retval[0] = tmp;
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_fcntl(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_fcntl_args *uap;
|
|
|
|
{
|
|
|
|
struct fcntl_args a;
|
|
|
|
long tmp;
|
|
|
|
int error;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
a.fd = uap->fd;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
switch (uap->cmd) {
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
case OSF1_F_DUPFD:
|
2002-12-14 01:56:26 +00:00
|
|
|
a.cmd = F_DUPFD;
|
|
|
|
a.arg = (long)uap->arg;
|
1999-12-14 22:35:36 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OSF1_F_GETFD:
|
2002-12-14 01:56:26 +00:00
|
|
|
a.cmd = F_GETFD;
|
|
|
|
a.arg = (long)uap->arg;
|
1999-12-14 22:35:36 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OSF1_F_SETFD:
|
2002-12-14 01:56:26 +00:00
|
|
|
a.cmd = F_SETFD;
|
|
|
|
a.arg = (long)uap->arg;
|
1999-12-14 22:35:36 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OSF1_F_GETFL:
|
2002-12-14 01:56:26 +00:00
|
|
|
a.cmd = F_GETFL;
|
|
|
|
a.arg = (long)uap->arg; /* ignored */
|
1999-12-14 22:35:36 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OSF1_F_SETFL:
|
2002-12-14 01:56:26 +00:00
|
|
|
a.cmd = F_SETFL;
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp = 0;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((long)uap->arg & OSF1_FAPPEND)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= FAPPEND;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((long)uap->arg & OSF1_FNONBLOCK)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= FNONBLOCK;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((long)uap->arg & OSF1_FASYNC)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= FASYNC;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((long)uap->arg & OSF1_FSYNC)
|
1999-12-14 22:35:36 +00:00
|
|
|
tmp |= FFSYNC;
|
2002-12-14 01:56:26 +00:00
|
|
|
a.arg = tmp;
|
1999-12-14 22:35:36 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default: /* XXX other cases */
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
error = fcntl(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
switch (uap->cmd) {
|
1999-12-14 22:35:36 +00:00
|
|
|
case OSF1_F_GETFL:
|
|
|
|
/* XXX */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_socket(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_socket_args *uap;
|
|
|
|
{
|
|
|
|
struct socket_args a;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->type > AF_LINK)
|
1999-12-14 22:35:36 +00:00
|
|
|
return (EINVAL); /* XXX After AF_LINK, divergence. */
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
a.domain = uap->domain;
|
|
|
|
a.type = uap->type;
|
|
|
|
a.protocol = uap->protocol;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
return socket(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_sendto(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
register struct osf1_sendto_args *uap;
|
|
|
|
{
|
|
|
|
struct sendto_args a;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->flags & ~0x7f) /* unsupported flags */
|
1999-12-14 22:35:36 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
a.s = uap->s;
|
|
|
|
a.buf = uap->buf;
|
|
|
|
a.len = uap->len;
|
|
|
|
a.flags = uap->flags;
|
|
|
|
a.to = (caddr_t)uap->to;
|
|
|
|
a.tolen = uap->tolen;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
return sendto(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_reboot(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_reboot_args *uap;
|
|
|
|
{
|
|
|
|
struct reboot_args a;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->opt & ~OSF1_RB_ALLFLAGS &&
|
|
|
|
uap->opt & (OSF1_RB_ALTBOOT|OSF1_RB_UNIPROC))
|
1999-12-14 22:35:36 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
a.opt = 0;
|
|
|
|
|
|
|
|
if (uap->opt & OSF1_RB_ASKNAME)
|
|
|
|
a.opt |= RB_ASKNAME;
|
|
|
|
if (uap->opt & OSF1_RB_SINGLE)
|
|
|
|
a.opt |= RB_SINGLE;
|
|
|
|
if (uap->opt & OSF1_RB_NOSYNC)
|
|
|
|
a.opt |= RB_NOSYNC;
|
|
|
|
if (uap->opt & OSF1_RB_HALT)
|
|
|
|
a.opt |= RB_HALT;
|
|
|
|
if (uap->opt & OSF1_RB_INITNAME)
|
|
|
|
a.opt |= RB_INITNAME;
|
|
|
|
if (uap->opt & OSF1_RB_DFLTROOT)
|
|
|
|
a.opt |= RB_DFLTROOT;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
return reboot(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_lseek(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_lseek_args *uap;
|
|
|
|
{
|
|
|
|
struct lseek_args a;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
a.fd = uap->fd;
|
|
|
|
a.pad = 0;
|
|
|
|
a.offset = uap->offset;
|
|
|
|
a.whence = uap->whence;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
return lseek(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* OSF/1 defines _POSIX_SAVED_IDS, which means that our normal
|
|
|
|
* setuid() won't work.
|
|
|
|
*
|
|
|
|
* Instead, by P1003.1b-1993, setuid() is supposed to work like:
|
2002-04-05 00:08:38 +00:00
|
|
|
* If the process has appropriate [super-user] privileges, the
|
1999-12-14 22:35:36 +00:00
|
|
|
* setuid() function sets the real user ID, effective user
|
|
|
|
* ID, and the saved set-user-ID to uid.
|
2002-04-05 00:08:38 +00:00
|
|
|
* If the process does not have appropriate privileges, but uid
|
1999-12-14 22:35:36 +00:00
|
|
|
* is equal to the real user ID or the saved set-user-ID, the
|
|
|
|
* setuid() function sets the effective user ID to uid; the
|
|
|
|
* real user ID and saved set-user-ID remain unchanged by
|
|
|
|
* this function call.
|
|
|
|
*/
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_setuid(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_setuid_args *uap;
|
|
|
|
{
|
2001-09-20 04:56:42 +00:00
|
|
|
struct proc *p;
|
1999-12-14 22:35:36 +00:00
|
|
|
int error;
|
|
|
|
uid_t uid;
|
2002-06-19 06:39:25 +00:00
|
|
|
struct uidinfo *uip;
|
2001-05-25 20:56:28 +00:00
|
|
|
struct ucred *newcred, *oldcred;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
p = td->td_proc;
|
2002-12-14 01:56:26 +00:00
|
|
|
uid = uap->uid;
|
2002-04-13 23:11:23 +00:00
|
|
|
newcred = crget();
|
2002-06-19 06:39:25 +00:00
|
|
|
uip = uifind(uid);
|
2002-04-13 23:11:23 +00:00
|
|
|
PROC_LOCK(p);
|
o Merge contents of struct pcred into struct ucred. Specifically, add the
real uid, saved uid, real gid, and saved gid to ucred, as well as the
pcred->pc_uidinfo, which was associated with the real uid, only rename
it to cr_ruidinfo so as not to conflict with cr_uidinfo, which
corresponds to the effective uid.
o Remove p_cred from struct proc; add p_ucred to struct proc, replacing
original macro that pointed.
p->p_ucred to p->p_cred->pc_ucred.
o Universally update code so that it makes use of ucred instead of pcred,
p->p_ucred instead of p->p_pcred, cr_ruidinfo instead of p_uidinfo,
cr_{r,sv}{u,g}id instead of p_*, etc.
o Remove pcred0 and its initialization from init_main.c; initialize
cr_ruidinfo there.
o Restruction many credential modification chunks to always crdup while
we figure out locking and optimizations; generally speaking, this
means moving to a structure like this:
newcred = crdup(oldcred);
...
p->p_ucred = newcred;
crfree(oldcred);
It's not race-free, but better than nothing. There are also races
in sys_process.c, all inter-process authorization, fork, exec, and
exit.
o Remove sigio->sio_ruid since sigio->sio_ucred now contains the ruid;
remove comments indicating that the old arrangement was a problem.
o Restructure exec1() a little to use newcred/oldcred arrangement, and
use improved uid management primitives.
o Clean up exit1() so as to do less work in credential cleanup due to
pcred removal.
o Clean up fork1() so as to do less work in credential cleanup and
allocation.
o Clean up ktrcanset() to take into account changes, and move to using
suser_xxx() instead of performing a direct uid==0 comparision.
o Improve commenting in various kern_prot.c credential modification
calls to better document current behavior. In a couple of places,
current behavior is a little questionable and we need to check
POSIX.1 to make sure it's "right". More commenting work still
remains to be done.
o Update credential management calls, such as crfree(), to take into
account new ruidinfo reference.
o Modify or add the following uid and gid helper routines:
change_euid()
change_egid()
change_ruid()
change_rgid()
change_svuid()
change_svgid()
In each case, the call now acts on a credential not a process, and as
such no longer requires more complicated process locking/etc. They
now assume the caller will do any necessary allocation of an
exclusive credential reference. Each is commented to document its
reference requirements.
o CANSIGIO() is simplified to require only credentials, not processes
and pcreds.
o Remove lots of (p_pcred==NULL) checks.
o Add an XXX to authorization code in nfs_lock.c, since it's
questionable, and needs to be considered carefully.
o Simplify posix4 authorization code to require only credentials, not
processes and pcreds. Note that this authorization, as well as
CANSIGIO(), needs to be updated to use the p_cansignal() and
p_cansched() centralized authorization routines, as they currently
do not take into account some desirable restrictions that are handled
by the centralized routines, as well as being inconsistent with other
similar authorization instances.
o Update libkvm to take these changes into account.
Obtained from: TrustedBSD Project
Reviewed by: green, bde, jhb, freebsd-arch, freebsd-audit
2001-05-25 16:59:11 +00:00
|
|
|
oldcred = p->p_ucred;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-04-01 21:31:13 +00:00
|
|
|
if ((error = suser_cred(p->p_ucred, PRISON_ROOT)) != 0 &&
|
2002-04-13 23:11:23 +00:00
|
|
|
uid != oldcred->cr_ruid && uid != oldcred->cr_svuid) {
|
|
|
|
PROC_UNLOCK(p);
|
2002-06-19 06:39:25 +00:00
|
|
|
uifree(uip);
|
2002-04-13 23:11:23 +00:00
|
|
|
crfree(newcred);
|
1999-12-14 22:35:36 +00:00
|
|
|
return (error);
|
2002-04-13 23:11:23 +00:00
|
|
|
}
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-04-13 23:11:23 +00:00
|
|
|
crcopy(newcred, oldcred);
|
1999-12-14 22:35:36 +00:00
|
|
|
if (error == 0) {
|
o Merge contents of struct pcred into struct ucred. Specifically, add the
real uid, saved uid, real gid, and saved gid to ucred, as well as the
pcred->pc_uidinfo, which was associated with the real uid, only rename
it to cr_ruidinfo so as not to conflict with cr_uidinfo, which
corresponds to the effective uid.
o Remove p_cred from struct proc; add p_ucred to struct proc, replacing
original macro that pointed.
p->p_ucred to p->p_cred->pc_ucred.
o Universally update code so that it makes use of ucred instead of pcred,
p->p_ucred instead of p->p_pcred, cr_ruidinfo instead of p_uidinfo,
cr_{r,sv}{u,g}id instead of p_*, etc.
o Remove pcred0 and its initialization from init_main.c; initialize
cr_ruidinfo there.
o Restruction many credential modification chunks to always crdup while
we figure out locking and optimizations; generally speaking, this
means moving to a structure like this:
newcred = crdup(oldcred);
...
p->p_ucred = newcred;
crfree(oldcred);
It's not race-free, but better than nothing. There are also races
in sys_process.c, all inter-process authorization, fork, exec, and
exit.
o Remove sigio->sio_ruid since sigio->sio_ucred now contains the ruid;
remove comments indicating that the old arrangement was a problem.
o Restructure exec1() a little to use newcred/oldcred arrangement, and
use improved uid management primitives.
o Clean up exit1() so as to do less work in credential cleanup due to
pcred removal.
o Clean up fork1() so as to do less work in credential cleanup and
allocation.
o Clean up ktrcanset() to take into account changes, and move to using
suser_xxx() instead of performing a direct uid==0 comparision.
o Improve commenting in various kern_prot.c credential modification
calls to better document current behavior. In a couple of places,
current behavior is a little questionable and we need to check
POSIX.1 to make sure it's "right". More commenting work still
remains to be done.
o Update credential management calls, such as crfree(), to take into
account new ruidinfo reference.
o Modify or add the following uid and gid helper routines:
change_euid()
change_egid()
change_ruid()
change_rgid()
change_svuid()
change_svgid()
In each case, the call now acts on a credential not a process, and as
such no longer requires more complicated process locking/etc. They
now assume the caller will do any necessary allocation of an
exclusive credential reference. Each is commented to document its
reference requirements.
o CANSIGIO() is simplified to require only credentials, not processes
and pcreds.
o Remove lots of (p_pcred==NULL) checks.
o Add an XXX to authorization code in nfs_lock.c, since it's
questionable, and needs to be considered carefully.
o Simplify posix4 authorization code to require only credentials, not
processes and pcreds. Note that this authorization, as well as
CANSIGIO(), needs to be updated to use the p_cansignal() and
p_cansched() centralized authorization routines, as they currently
do not take into account some desirable restrictions that are handled
by the centralized routines, as well as being inconsistent with other
similar authorization instances.
o Update libkvm to take these changes into account.
Obtained from: TrustedBSD Project
Reviewed by: green, bde, jhb, freebsd-arch, freebsd-audit
2001-05-25 16:59:11 +00:00
|
|
|
if (uid != oldcred->cr_ruid) {
|
2002-06-19 06:39:25 +00:00
|
|
|
change_ruid(newcred, uip);
|
2000-10-26 15:53:00 +00:00
|
|
|
setsugid(p);
|
|
|
|
}
|
o Merge contents of struct pcred into struct ucred. Specifically, add the
real uid, saved uid, real gid, and saved gid to ucred, as well as the
pcred->pc_uidinfo, which was associated with the real uid, only rename
it to cr_ruidinfo so as not to conflict with cr_uidinfo, which
corresponds to the effective uid.
o Remove p_cred from struct proc; add p_ucred to struct proc, replacing
original macro that pointed.
p->p_ucred to p->p_cred->pc_ucred.
o Universally update code so that it makes use of ucred instead of pcred,
p->p_ucred instead of p->p_pcred, cr_ruidinfo instead of p_uidinfo,
cr_{r,sv}{u,g}id instead of p_*, etc.
o Remove pcred0 and its initialization from init_main.c; initialize
cr_ruidinfo there.
o Restruction many credential modification chunks to always crdup while
we figure out locking and optimizations; generally speaking, this
means moving to a structure like this:
newcred = crdup(oldcred);
...
p->p_ucred = newcred;
crfree(oldcred);
It's not race-free, but better than nothing. There are also races
in sys_process.c, all inter-process authorization, fork, exec, and
exit.
o Remove sigio->sio_ruid since sigio->sio_ucred now contains the ruid;
remove comments indicating that the old arrangement was a problem.
o Restructure exec1() a little to use newcred/oldcred arrangement, and
use improved uid management primitives.
o Clean up exit1() so as to do less work in credential cleanup due to
pcred removal.
o Clean up fork1() so as to do less work in credential cleanup and
allocation.
o Clean up ktrcanset() to take into account changes, and move to using
suser_xxx() instead of performing a direct uid==0 comparision.
o Improve commenting in various kern_prot.c credential modification
calls to better document current behavior. In a couple of places,
current behavior is a little questionable and we need to check
POSIX.1 to make sure it's "right". More commenting work still
remains to be done.
o Update credential management calls, such as crfree(), to take into
account new ruidinfo reference.
o Modify or add the following uid and gid helper routines:
change_euid()
change_egid()
change_ruid()
change_rgid()
change_svuid()
change_svgid()
In each case, the call now acts on a credential not a process, and as
such no longer requires more complicated process locking/etc. They
now assume the caller will do any necessary allocation of an
exclusive credential reference. Each is commented to document its
reference requirements.
o CANSIGIO() is simplified to require only credentials, not processes
and pcreds.
o Remove lots of (p_pcred==NULL) checks.
o Add an XXX to authorization code in nfs_lock.c, since it's
questionable, and needs to be considered carefully.
o Simplify posix4 authorization code to require only credentials, not
processes and pcreds. Note that this authorization, as well as
CANSIGIO(), needs to be updated to use the p_cansignal() and
p_cansched() centralized authorization routines, as they currently
do not take into account some desirable restrictions that are handled
by the centralized routines, as well as being inconsistent with other
similar authorization instances.
o Update libkvm to take these changes into account.
Obtained from: TrustedBSD Project
Reviewed by: green, bde, jhb, freebsd-arch, freebsd-audit
2001-05-25 16:59:11 +00:00
|
|
|
if (oldcred->cr_svuid != uid) {
|
|
|
|
change_svuid(newcred, uid);
|
2000-10-26 15:53:00 +00:00
|
|
|
setsugid(p);
|
|
|
|
}
|
|
|
|
}
|
o Merge contents of struct pcred into struct ucred. Specifically, add the
real uid, saved uid, real gid, and saved gid to ucred, as well as the
pcred->pc_uidinfo, which was associated with the real uid, only rename
it to cr_ruidinfo so as not to conflict with cr_uidinfo, which
corresponds to the effective uid.
o Remove p_cred from struct proc; add p_ucred to struct proc, replacing
original macro that pointed.
p->p_ucred to p->p_cred->pc_ucred.
o Universally update code so that it makes use of ucred instead of pcred,
p->p_ucred instead of p->p_pcred, cr_ruidinfo instead of p_uidinfo,
cr_{r,sv}{u,g}id instead of p_*, etc.
o Remove pcred0 and its initialization from init_main.c; initialize
cr_ruidinfo there.
o Restruction many credential modification chunks to always crdup while
we figure out locking and optimizations; generally speaking, this
means moving to a structure like this:
newcred = crdup(oldcred);
...
p->p_ucred = newcred;
crfree(oldcred);
It's not race-free, but better than nothing. There are also races
in sys_process.c, all inter-process authorization, fork, exec, and
exit.
o Remove sigio->sio_ruid since sigio->sio_ucred now contains the ruid;
remove comments indicating that the old arrangement was a problem.
o Restructure exec1() a little to use newcred/oldcred arrangement, and
use improved uid management primitives.
o Clean up exit1() so as to do less work in credential cleanup due to
pcred removal.
o Clean up fork1() so as to do less work in credential cleanup and
allocation.
o Clean up ktrcanset() to take into account changes, and move to using
suser_xxx() instead of performing a direct uid==0 comparision.
o Improve commenting in various kern_prot.c credential modification
calls to better document current behavior. In a couple of places,
current behavior is a little questionable and we need to check
POSIX.1 to make sure it's "right". More commenting work still
remains to be done.
o Update credential management calls, such as crfree(), to take into
account new ruidinfo reference.
o Modify or add the following uid and gid helper routines:
change_euid()
change_egid()
change_ruid()
change_rgid()
change_svuid()
change_svgid()
In each case, the call now acts on a credential not a process, and as
such no longer requires more complicated process locking/etc. They
now assume the caller will do any necessary allocation of an
exclusive credential reference. Each is commented to document its
reference requirements.
o CANSIGIO() is simplified to require only credentials, not processes
and pcreds.
o Remove lots of (p_pcred==NULL) checks.
o Add an XXX to authorization code in nfs_lock.c, since it's
questionable, and needs to be considered carefully.
o Simplify posix4 authorization code to require only credentials, not
processes and pcreds. Note that this authorization, as well as
CANSIGIO(), needs to be updated to use the p_cansignal() and
p_cansched() centralized authorization routines, as they currently
do not take into account some desirable restrictions that are handled
by the centralized routines, as well as being inconsistent with other
similar authorization instances.
o Update libkvm to take these changes into account.
Obtained from: TrustedBSD Project
Reviewed by: green, bde, jhb, freebsd-arch, freebsd-audit
2001-05-25 16:59:11 +00:00
|
|
|
if (newcred->cr_uid != uid) {
|
2002-06-19 06:39:25 +00:00
|
|
|
change_euid(newcred, uip);
|
2000-10-26 15:53:00 +00:00
|
|
|
setsugid(p);
|
2001-01-25 01:09:44 +00:00
|
|
|
}
|
o Merge contents of struct pcred into struct ucred. Specifically, add the
real uid, saved uid, real gid, and saved gid to ucred, as well as the
pcred->pc_uidinfo, which was associated with the real uid, only rename
it to cr_ruidinfo so as not to conflict with cr_uidinfo, which
corresponds to the effective uid.
o Remove p_cred from struct proc; add p_ucred to struct proc, replacing
original macro that pointed.
p->p_ucred to p->p_cred->pc_ucred.
o Universally update code so that it makes use of ucred instead of pcred,
p->p_ucred instead of p->p_pcred, cr_ruidinfo instead of p_uidinfo,
cr_{r,sv}{u,g}id instead of p_*, etc.
o Remove pcred0 and its initialization from init_main.c; initialize
cr_ruidinfo there.
o Restruction many credential modification chunks to always crdup while
we figure out locking and optimizations; generally speaking, this
means moving to a structure like this:
newcred = crdup(oldcred);
...
p->p_ucred = newcred;
crfree(oldcred);
It's not race-free, but better than nothing. There are also races
in sys_process.c, all inter-process authorization, fork, exec, and
exit.
o Remove sigio->sio_ruid since sigio->sio_ucred now contains the ruid;
remove comments indicating that the old arrangement was a problem.
o Restructure exec1() a little to use newcred/oldcred arrangement, and
use improved uid management primitives.
o Clean up exit1() so as to do less work in credential cleanup due to
pcred removal.
o Clean up fork1() so as to do less work in credential cleanup and
allocation.
o Clean up ktrcanset() to take into account changes, and move to using
suser_xxx() instead of performing a direct uid==0 comparision.
o Improve commenting in various kern_prot.c credential modification
calls to better document current behavior. In a couple of places,
current behavior is a little questionable and we need to check
POSIX.1 to make sure it's "right". More commenting work still
remains to be done.
o Update credential management calls, such as crfree(), to take into
account new ruidinfo reference.
o Modify or add the following uid and gid helper routines:
change_euid()
change_egid()
change_ruid()
change_rgid()
change_svuid()
change_svgid()
In each case, the call now acts on a credential not a process, and as
such no longer requires more complicated process locking/etc. They
now assume the caller will do any necessary allocation of an
exclusive credential reference. Each is commented to document its
reference requirements.
o CANSIGIO() is simplified to require only credentials, not processes
and pcreds.
o Remove lots of (p_pcred==NULL) checks.
o Add an XXX to authorization code in nfs_lock.c, since it's
questionable, and needs to be considered carefully.
o Simplify posix4 authorization code to require only credentials, not
processes and pcreds. Note that this authorization, as well as
CANSIGIO(), needs to be updated to use the p_cansignal() and
p_cansched() centralized authorization routines, as they currently
do not take into account some desirable restrictions that are handled
by the centralized routines, as well as being inconsistent with other
similar authorization instances.
o Update libkvm to take these changes into account.
Obtained from: TrustedBSD Project
Reviewed by: green, bde, jhb, freebsd-arch, freebsd-audit
2001-05-25 16:59:11 +00:00
|
|
|
p->p_ucred = newcred;
|
2002-04-13 23:11:23 +00:00
|
|
|
PROC_UNLOCK(p);
|
2002-06-19 06:39:25 +00:00
|
|
|
uifree(uip);
|
o Merge contents of struct pcred into struct ucred. Specifically, add the
real uid, saved uid, real gid, and saved gid to ucred, as well as the
pcred->pc_uidinfo, which was associated with the real uid, only rename
it to cr_ruidinfo so as not to conflict with cr_uidinfo, which
corresponds to the effective uid.
o Remove p_cred from struct proc; add p_ucred to struct proc, replacing
original macro that pointed.
p->p_ucred to p->p_cred->pc_ucred.
o Universally update code so that it makes use of ucred instead of pcred,
p->p_ucred instead of p->p_pcred, cr_ruidinfo instead of p_uidinfo,
cr_{r,sv}{u,g}id instead of p_*, etc.
o Remove pcred0 and its initialization from init_main.c; initialize
cr_ruidinfo there.
o Restruction many credential modification chunks to always crdup while
we figure out locking and optimizations; generally speaking, this
means moving to a structure like this:
newcred = crdup(oldcred);
...
p->p_ucred = newcred;
crfree(oldcred);
It's not race-free, but better than nothing. There are also races
in sys_process.c, all inter-process authorization, fork, exec, and
exit.
o Remove sigio->sio_ruid since sigio->sio_ucred now contains the ruid;
remove comments indicating that the old arrangement was a problem.
o Restructure exec1() a little to use newcred/oldcred arrangement, and
use improved uid management primitives.
o Clean up exit1() so as to do less work in credential cleanup due to
pcred removal.
o Clean up fork1() so as to do less work in credential cleanup and
allocation.
o Clean up ktrcanset() to take into account changes, and move to using
suser_xxx() instead of performing a direct uid==0 comparision.
o Improve commenting in various kern_prot.c credential modification
calls to better document current behavior. In a couple of places,
current behavior is a little questionable and we need to check
POSIX.1 to make sure it's "right". More commenting work still
remains to be done.
o Update credential management calls, such as crfree(), to take into
account new ruidinfo reference.
o Modify or add the following uid and gid helper routines:
change_euid()
change_egid()
change_ruid()
change_rgid()
change_svuid()
change_svgid()
In each case, the call now acts on a credential not a process, and as
such no longer requires more complicated process locking/etc. They
now assume the caller will do any necessary allocation of an
exclusive credential reference. Each is commented to document its
reference requirements.
o CANSIGIO() is simplified to require only credentials, not processes
and pcreds.
o Remove lots of (p_pcred==NULL) checks.
o Add an XXX to authorization code in nfs_lock.c, since it's
questionable, and needs to be considered carefully.
o Simplify posix4 authorization code to require only credentials, not
processes and pcreds. Note that this authorization, as well as
CANSIGIO(), needs to be updated to use the p_cansignal() and
p_cansched() centralized authorization routines, as they currently
do not take into account some desirable restrictions that are handled
by the centralized routines, as well as being inconsistent with other
similar authorization instances.
o Update libkvm to take these changes into account.
Obtained from: TrustedBSD Project
Reviewed by: green, bde, jhb, freebsd-arch, freebsd-audit
2001-05-25 16:59:11 +00:00
|
|
|
crfree(oldcred);
|
1999-12-14 22:35:36 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* OSF/1 defines _POSIX_SAVED_IDS, which means that our normal
|
|
|
|
* setgid() won't work.
|
|
|
|
*
|
|
|
|
* If you change "uid" to "gid" in the discussion, above, about
|
|
|
|
* setuid(), you'll get a correct description of setgid().
|
|
|
|
*/
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_setgid(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_setgid_args *uap;
|
|
|
|
{
|
2001-09-20 04:56:42 +00:00
|
|
|
struct proc *p;
|
1999-12-14 22:35:36 +00:00
|
|
|
int error;
|
|
|
|
gid_t gid;
|
o Merge contents of struct pcred into struct ucred. Specifically, add the
real uid, saved uid, real gid, and saved gid to ucred, as well as the
pcred->pc_uidinfo, which was associated with the real uid, only rename
it to cr_ruidinfo so as not to conflict with cr_uidinfo, which
corresponds to the effective uid.
o Remove p_cred from struct proc; add p_ucred to struct proc, replacing
original macro that pointed.
p->p_ucred to p->p_cred->pc_ucred.
o Universally update code so that it makes use of ucred instead of pcred,
p->p_ucred instead of p->p_pcred, cr_ruidinfo instead of p_uidinfo,
cr_{r,sv}{u,g}id instead of p_*, etc.
o Remove pcred0 and its initialization from init_main.c; initialize
cr_ruidinfo there.
o Restruction many credential modification chunks to always crdup while
we figure out locking and optimizations; generally speaking, this
means moving to a structure like this:
newcred = crdup(oldcred);
...
p->p_ucred = newcred;
crfree(oldcred);
It's not race-free, but better than nothing. There are also races
in sys_process.c, all inter-process authorization, fork, exec, and
exit.
o Remove sigio->sio_ruid since sigio->sio_ucred now contains the ruid;
remove comments indicating that the old arrangement was a problem.
o Restructure exec1() a little to use newcred/oldcred arrangement, and
use improved uid management primitives.
o Clean up exit1() so as to do less work in credential cleanup due to
pcred removal.
o Clean up fork1() so as to do less work in credential cleanup and
allocation.
o Clean up ktrcanset() to take into account changes, and move to using
suser_xxx() instead of performing a direct uid==0 comparision.
o Improve commenting in various kern_prot.c credential modification
calls to better document current behavior. In a couple of places,
current behavior is a little questionable and we need to check
POSIX.1 to make sure it's "right". More commenting work still
remains to be done.
o Update credential management calls, such as crfree(), to take into
account new ruidinfo reference.
o Modify or add the following uid and gid helper routines:
change_euid()
change_egid()
change_ruid()
change_rgid()
change_svuid()
change_svgid()
In each case, the call now acts on a credential not a process, and as
such no longer requires more complicated process locking/etc. They
now assume the caller will do any necessary allocation of an
exclusive credential reference. Each is commented to document its
reference requirements.
o CANSIGIO() is simplified to require only credentials, not processes
and pcreds.
o Remove lots of (p_pcred==NULL) checks.
o Add an XXX to authorization code in nfs_lock.c, since it's
questionable, and needs to be considered carefully.
o Simplify posix4 authorization code to require only credentials, not
processes and pcreds. Note that this authorization, as well as
CANSIGIO(), needs to be updated to use the p_cansignal() and
p_cansched() centralized authorization routines, as they currently
do not take into account some desirable restrictions that are handled
by the centralized routines, as well as being inconsistent with other
similar authorization instances.
o Update libkvm to take these changes into account.
Obtained from: TrustedBSD Project
Reviewed by: green, bde, jhb, freebsd-arch, freebsd-audit
2001-05-25 16:59:11 +00:00
|
|
|
struct ucred *newcred, *oldcred;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
p = td->td_proc;
|
2002-12-14 01:56:26 +00:00
|
|
|
gid = uap->gid;
|
2002-04-13 23:11:23 +00:00
|
|
|
newcred = crget();
|
|
|
|
PROC_LOCK(p);
|
o Merge contents of struct pcred into struct ucred. Specifically, add the
real uid, saved uid, real gid, and saved gid to ucred, as well as the
pcred->pc_uidinfo, which was associated with the real uid, only rename
it to cr_ruidinfo so as not to conflict with cr_uidinfo, which
corresponds to the effective uid.
o Remove p_cred from struct proc; add p_ucred to struct proc, replacing
original macro that pointed.
p->p_ucred to p->p_cred->pc_ucred.
o Universally update code so that it makes use of ucred instead of pcred,
p->p_ucred instead of p->p_pcred, cr_ruidinfo instead of p_uidinfo,
cr_{r,sv}{u,g}id instead of p_*, etc.
o Remove pcred0 and its initialization from init_main.c; initialize
cr_ruidinfo there.
o Restruction many credential modification chunks to always crdup while
we figure out locking and optimizations; generally speaking, this
means moving to a structure like this:
newcred = crdup(oldcred);
...
p->p_ucred = newcred;
crfree(oldcred);
It's not race-free, but better than nothing. There are also races
in sys_process.c, all inter-process authorization, fork, exec, and
exit.
o Remove sigio->sio_ruid since sigio->sio_ucred now contains the ruid;
remove comments indicating that the old arrangement was a problem.
o Restructure exec1() a little to use newcred/oldcred arrangement, and
use improved uid management primitives.
o Clean up exit1() so as to do less work in credential cleanup due to
pcred removal.
o Clean up fork1() so as to do less work in credential cleanup and
allocation.
o Clean up ktrcanset() to take into account changes, and move to using
suser_xxx() instead of performing a direct uid==0 comparision.
o Improve commenting in various kern_prot.c credential modification
calls to better document current behavior. In a couple of places,
current behavior is a little questionable and we need to check
POSIX.1 to make sure it's "right". More commenting work still
remains to be done.
o Update credential management calls, such as crfree(), to take into
account new ruidinfo reference.
o Modify or add the following uid and gid helper routines:
change_euid()
change_egid()
change_ruid()
change_rgid()
change_svuid()
change_svgid()
In each case, the call now acts on a credential not a process, and as
such no longer requires more complicated process locking/etc. They
now assume the caller will do any necessary allocation of an
exclusive credential reference. Each is commented to document its
reference requirements.
o CANSIGIO() is simplified to require only credentials, not processes
and pcreds.
o Remove lots of (p_pcred==NULL) checks.
o Add an XXX to authorization code in nfs_lock.c, since it's
questionable, and needs to be considered carefully.
o Simplify posix4 authorization code to require only credentials, not
processes and pcreds. Note that this authorization, as well as
CANSIGIO(), needs to be updated to use the p_cansignal() and
p_cansched() centralized authorization routines, as they currently
do not take into account some desirable restrictions that are handled
by the centralized routines, as well as being inconsistent with other
similar authorization instances.
o Update libkvm to take these changes into account.
Obtained from: TrustedBSD Project
Reviewed by: green, bde, jhb, freebsd-arch, freebsd-audit
2001-05-25 16:59:11 +00:00
|
|
|
oldcred = p->p_ucred;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-04-01 21:31:13 +00:00
|
|
|
if (((error = suser_cred(p->p_ucred, PRISON_ROOT)) != 0 ) &&
|
2002-04-13 23:11:23 +00:00
|
|
|
gid != oldcred->cr_rgid && gid != oldcred->cr_svgid) {
|
|
|
|
PROC_UNLOCK(p);
|
|
|
|
crfree(newcred);
|
1999-12-14 22:35:36 +00:00
|
|
|
return (error);
|
2002-04-13 23:11:23 +00:00
|
|
|
}
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-04-13 23:11:23 +00:00
|
|
|
crcopy(newcred, oldcred);
|
1999-12-14 22:35:36 +00:00
|
|
|
if (error == 0) {
|
o Merge contents of struct pcred into struct ucred. Specifically, add the
real uid, saved uid, real gid, and saved gid to ucred, as well as the
pcred->pc_uidinfo, which was associated with the real uid, only rename
it to cr_ruidinfo so as not to conflict with cr_uidinfo, which
corresponds to the effective uid.
o Remove p_cred from struct proc; add p_ucred to struct proc, replacing
original macro that pointed.
p->p_ucred to p->p_cred->pc_ucred.
o Universally update code so that it makes use of ucred instead of pcred,
p->p_ucred instead of p->p_pcred, cr_ruidinfo instead of p_uidinfo,
cr_{r,sv}{u,g}id instead of p_*, etc.
o Remove pcred0 and its initialization from init_main.c; initialize
cr_ruidinfo there.
o Restruction many credential modification chunks to always crdup while
we figure out locking and optimizations; generally speaking, this
means moving to a structure like this:
newcred = crdup(oldcred);
...
p->p_ucred = newcred;
crfree(oldcred);
It's not race-free, but better than nothing. There are also races
in sys_process.c, all inter-process authorization, fork, exec, and
exit.
o Remove sigio->sio_ruid since sigio->sio_ucred now contains the ruid;
remove comments indicating that the old arrangement was a problem.
o Restructure exec1() a little to use newcred/oldcred arrangement, and
use improved uid management primitives.
o Clean up exit1() so as to do less work in credential cleanup due to
pcred removal.
o Clean up fork1() so as to do less work in credential cleanup and
allocation.
o Clean up ktrcanset() to take into account changes, and move to using
suser_xxx() instead of performing a direct uid==0 comparision.
o Improve commenting in various kern_prot.c credential modification
calls to better document current behavior. In a couple of places,
current behavior is a little questionable and we need to check
POSIX.1 to make sure it's "right". More commenting work still
remains to be done.
o Update credential management calls, such as crfree(), to take into
account new ruidinfo reference.
o Modify or add the following uid and gid helper routines:
change_euid()
change_egid()
change_ruid()
change_rgid()
change_svuid()
change_svgid()
In each case, the call now acts on a credential not a process, and as
such no longer requires more complicated process locking/etc. They
now assume the caller will do any necessary allocation of an
exclusive credential reference. Each is commented to document its
reference requirements.
o CANSIGIO() is simplified to require only credentials, not processes
and pcreds.
o Remove lots of (p_pcred==NULL) checks.
o Add an XXX to authorization code in nfs_lock.c, since it's
questionable, and needs to be considered carefully.
o Simplify posix4 authorization code to require only credentials, not
processes and pcreds. Note that this authorization, as well as
CANSIGIO(), needs to be updated to use the p_cansignal() and
p_cansched() centralized authorization routines, as they currently
do not take into account some desirable restrictions that are handled
by the centralized routines, as well as being inconsistent with other
similar authorization instances.
o Update libkvm to take these changes into account.
Obtained from: TrustedBSD Project
Reviewed by: green, bde, jhb, freebsd-arch, freebsd-audit
2001-05-25 16:59:11 +00:00
|
|
|
if (gid != oldcred->cr_rgid) {
|
|
|
|
change_rgid(newcred, gid);
|
|
|
|
setsugid(p);
|
|
|
|
}
|
|
|
|
if (oldcred->cr_svgid != gid) {
|
|
|
|
change_svgid(newcred, gid);
|
|
|
|
setsugid(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (newcred->cr_groups[0] != gid) {
|
|
|
|
change_egid(newcred, gid);
|
|
|
|
setsugid(p);
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
o Merge contents of struct pcred into struct ucred. Specifically, add the
real uid, saved uid, real gid, and saved gid to ucred, as well as the
pcred->pc_uidinfo, which was associated with the real uid, only rename
it to cr_ruidinfo so as not to conflict with cr_uidinfo, which
corresponds to the effective uid.
o Remove p_cred from struct proc; add p_ucred to struct proc, replacing
original macro that pointed.
p->p_ucred to p->p_cred->pc_ucred.
o Universally update code so that it makes use of ucred instead of pcred,
p->p_ucred instead of p->p_pcred, cr_ruidinfo instead of p_uidinfo,
cr_{r,sv}{u,g}id instead of p_*, etc.
o Remove pcred0 and its initialization from init_main.c; initialize
cr_ruidinfo there.
o Restruction many credential modification chunks to always crdup while
we figure out locking and optimizations; generally speaking, this
means moving to a structure like this:
newcred = crdup(oldcred);
...
p->p_ucred = newcred;
crfree(oldcred);
It's not race-free, but better than nothing. There are also races
in sys_process.c, all inter-process authorization, fork, exec, and
exit.
o Remove sigio->sio_ruid since sigio->sio_ucred now contains the ruid;
remove comments indicating that the old arrangement was a problem.
o Restructure exec1() a little to use newcred/oldcred arrangement, and
use improved uid management primitives.
o Clean up exit1() so as to do less work in credential cleanup due to
pcred removal.
o Clean up fork1() so as to do less work in credential cleanup and
allocation.
o Clean up ktrcanset() to take into account changes, and move to using
suser_xxx() instead of performing a direct uid==0 comparision.
o Improve commenting in various kern_prot.c credential modification
calls to better document current behavior. In a couple of places,
current behavior is a little questionable and we need to check
POSIX.1 to make sure it's "right". More commenting work still
remains to be done.
o Update credential management calls, such as crfree(), to take into
account new ruidinfo reference.
o Modify or add the following uid and gid helper routines:
change_euid()
change_egid()
change_ruid()
change_rgid()
change_svuid()
change_svgid()
In each case, the call now acts on a credential not a process, and as
such no longer requires more complicated process locking/etc. They
now assume the caller will do any necessary allocation of an
exclusive credential reference. Each is commented to document its
reference requirements.
o CANSIGIO() is simplified to require only credentials, not processes
and pcreds.
o Remove lots of (p_pcred==NULL) checks.
o Add an XXX to authorization code in nfs_lock.c, since it's
questionable, and needs to be considered carefully.
o Simplify posix4 authorization code to require only credentials, not
processes and pcreds. Note that this authorization, as well as
CANSIGIO(), needs to be updated to use the p_cansignal() and
p_cansched() centralized authorization routines, as they currently
do not take into account some desirable restrictions that are handled
by the centralized routines, as well as being inconsistent with other
similar authorization instances.
o Update libkvm to take these changes into account.
Obtained from: TrustedBSD Project
Reviewed by: green, bde, jhb, freebsd-arch, freebsd-audit
2001-05-25 16:59:11 +00:00
|
|
|
p->p_ucred = newcred;
|
2002-04-13 23:11:23 +00:00
|
|
|
PROC_UNLOCK(p);
|
o Merge contents of struct pcred into struct ucred. Specifically, add the
real uid, saved uid, real gid, and saved gid to ucred, as well as the
pcred->pc_uidinfo, which was associated with the real uid, only rename
it to cr_ruidinfo so as not to conflict with cr_uidinfo, which
corresponds to the effective uid.
o Remove p_cred from struct proc; add p_ucred to struct proc, replacing
original macro that pointed.
p->p_ucred to p->p_cred->pc_ucred.
o Universally update code so that it makes use of ucred instead of pcred,
p->p_ucred instead of p->p_pcred, cr_ruidinfo instead of p_uidinfo,
cr_{r,sv}{u,g}id instead of p_*, etc.
o Remove pcred0 and its initialization from init_main.c; initialize
cr_ruidinfo there.
o Restruction many credential modification chunks to always crdup while
we figure out locking and optimizations; generally speaking, this
means moving to a structure like this:
newcred = crdup(oldcred);
...
p->p_ucred = newcred;
crfree(oldcred);
It's not race-free, but better than nothing. There are also races
in sys_process.c, all inter-process authorization, fork, exec, and
exit.
o Remove sigio->sio_ruid since sigio->sio_ucred now contains the ruid;
remove comments indicating that the old arrangement was a problem.
o Restructure exec1() a little to use newcred/oldcred arrangement, and
use improved uid management primitives.
o Clean up exit1() so as to do less work in credential cleanup due to
pcred removal.
o Clean up fork1() so as to do less work in credential cleanup and
allocation.
o Clean up ktrcanset() to take into account changes, and move to using
suser_xxx() instead of performing a direct uid==0 comparision.
o Improve commenting in various kern_prot.c credential modification
calls to better document current behavior. In a couple of places,
current behavior is a little questionable and we need to check
POSIX.1 to make sure it's "right". More commenting work still
remains to be done.
o Update credential management calls, such as crfree(), to take into
account new ruidinfo reference.
o Modify or add the following uid and gid helper routines:
change_euid()
change_egid()
change_ruid()
change_rgid()
change_svuid()
change_svgid()
In each case, the call now acts on a credential not a process, and as
such no longer requires more complicated process locking/etc. They
now assume the caller will do any necessary allocation of an
exclusive credential reference. Each is commented to document its
reference requirements.
o CANSIGIO() is simplified to require only credentials, not processes
and pcreds.
o Remove lots of (p_pcred==NULL) checks.
o Add an XXX to authorization code in nfs_lock.c, since it's
questionable, and needs to be considered carefully.
o Simplify posix4 authorization code to require only credentials, not
processes and pcreds. Note that this authorization, as well as
CANSIGIO(), needs to be updated to use the p_cansignal() and
p_cansched() centralized authorization routines, as they currently
do not take into account some desirable restrictions that are handled
by the centralized routines, as well as being inconsistent with other
similar authorization instances.
o Update libkvm to take these changes into account.
Obtained from: TrustedBSD Project
Reviewed by: green, bde, jhb, freebsd-arch, freebsd-audit
2001-05-25 16:59:11 +00:00
|
|
|
crfree(oldcred);
|
1999-12-14 22:35:36 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The structures end up being the same... but we can't be sure that
|
|
|
|
* the other word of our iov_len is zero!
|
|
|
|
*/
|
|
|
|
struct osf1_iovec {
|
|
|
|
char *iov_base;
|
|
|
|
int iov_len;
|
|
|
|
};
|
|
|
|
#define STACKGAPLEN 400
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_readv(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_readv_args *uap;
|
|
|
|
{
|
|
|
|
int error, osize, nsize, i;
|
|
|
|
caddr_t sg;
|
|
|
|
struct readv_args /* {
|
|
|
|
syscallarg(int) fd;
|
|
|
|
syscallarg(struct iovec *) iovp;
|
|
|
|
syscallarg(u_int) iovcnt;
|
|
|
|
} */ a;
|
|
|
|
struct osf1_iovec *oio;
|
|
|
|
struct iovec *nio;
|
|
|
|
|
|
|
|
sg = stackgap_init();
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
|
1999-12-14 22:35:36 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
osize = uap->iovcnt * sizeof (struct osf1_iovec);
|
|
|
|
nsize = uap->iovcnt * sizeof (struct iovec);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
oio = malloc(osize, M_TEMP, M_WAITOK);
|
|
|
|
nio = malloc(nsize, M_TEMP, M_WAITOK);
|
|
|
|
|
|
|
|
error = 0;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((error = copyin(uap->iovp, oio, osize)))
|
1999-12-14 22:35:36 +00:00
|
|
|
goto punt;
|
2002-12-14 01:56:26 +00:00
|
|
|
for (i = 0; i < uap->iovcnt; i++) {
|
1999-12-14 22:35:36 +00:00
|
|
|
nio[i].iov_base = oio[i].iov_base;
|
|
|
|
nio[i].iov_len = oio[i].iov_len;
|
|
|
|
}
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
a.fd = uap->fd;
|
|
|
|
a.iovp = stackgap_alloc(&sg, nsize);
|
|
|
|
a.iovcnt = uap->iovcnt;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
|
1999-12-14 22:35:36 +00:00
|
|
|
goto punt;
|
2001-09-20 04:56:42 +00:00
|
|
|
error = readv(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
punt:
|
|
|
|
free(oio, M_TEMP);
|
|
|
|
free(nio, M_TEMP);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_writev(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_writev_args *uap;
|
|
|
|
{
|
|
|
|
int error, i, nsize, osize;
|
|
|
|
caddr_t sg;
|
|
|
|
struct writev_args /* {
|
|
|
|
syscallarg(int) fd;
|
|
|
|
syscallarg(struct iovec *) iovp;
|
|
|
|
syscallarg(u_int) iovcnt;
|
|
|
|
} */ a;
|
|
|
|
struct osf1_iovec *oio;
|
|
|
|
struct iovec *nio;
|
|
|
|
|
|
|
|
sg = stackgap_init();
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
|
1999-12-14 22:35:36 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
osize = uap->iovcnt * sizeof (struct osf1_iovec);
|
|
|
|
nsize = uap->iovcnt * sizeof (struct iovec);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
oio = malloc(osize, M_TEMP, M_WAITOK);
|
|
|
|
nio = malloc(nsize, M_TEMP, M_WAITOK);
|
|
|
|
|
|
|
|
error = 0;
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((error = copyin(uap->iovp, oio, osize)))
|
1999-12-14 22:35:36 +00:00
|
|
|
goto punt;
|
2002-12-14 01:56:26 +00:00
|
|
|
for (i = 0; i < uap->iovcnt; i++) {
|
1999-12-14 22:35:36 +00:00
|
|
|
nio[i].iov_base = oio[i].iov_base;
|
|
|
|
nio[i].iov_len = oio[i].iov_len;
|
|
|
|
}
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
a.fd = uap->fd;
|
|
|
|
a.iovp = stackgap_alloc(&sg, nsize);
|
|
|
|
a.iovcnt = uap->iovcnt;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
|
1999-12-14 22:35:36 +00:00
|
|
|
goto punt;
|
2001-09-20 04:56:42 +00:00
|
|
|
error = writev(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
|
|
|
punt:
|
|
|
|
free(oio, M_TEMP);
|
|
|
|
free(nio, M_TEMP);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* More of the stupid off_t padding!
|
|
|
|
*/
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_truncate(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_truncate_args *uap;
|
|
|
|
{
|
|
|
|
caddr_t sg;
|
|
|
|
struct truncate_args a;
|
|
|
|
|
|
|
|
sg = stackgap_init();
|
2001-09-20 04:56:42 +00:00
|
|
|
CHECKALTEXIST(td, &sg, uap->path);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
a.path = uap->path;
|
|
|
|
a.pad = 0;
|
|
|
|
a.length = uap->length;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
return truncate(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_ftruncate(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_ftruncate_args *uap;
|
|
|
|
{
|
|
|
|
struct ftruncate_args a;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
a.fd = uap->fd;
|
|
|
|
a.pad = 0;
|
|
|
|
a.length = uap->length;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
return ftruncate(td, &a);
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
osf2bsd_pathconf(name)
|
|
|
|
int *name;
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (*name) {
|
|
|
|
case _OSF1_PC_LINK_MAX:
|
|
|
|
case _OSF1_PC_MAX_CANON:
|
|
|
|
case _OSF1_PC_MAX_INPUT:
|
|
|
|
case _OSF1_PC_NAME_MAX:
|
|
|
|
*name -= 10;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case _OSF1_PC_PATH_MAX:
|
|
|
|
case _OSF1_PC_PIPE_BUF:
|
|
|
|
*name -= 9;
|
|
|
|
|
|
|
|
case _OSF1_PC_NO_TRUNC:
|
|
|
|
*name = _PC_NO_TRUNC;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case _OSF1_PC_CHOWN_RESTRICTED:
|
|
|
|
*name = _PC_CHOWN_RESTRICTED;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case _OSF1_PC_VDISABLE:
|
|
|
|
*name = _PC_VDISABLE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_pathconf(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_pathconf_args *uap;
|
|
|
|
{
|
|
|
|
|
|
|
|
if (osf2bsd_pathconf(&uap->name))
|
|
|
|
return (EINVAL);
|
|
|
|
else
|
2001-09-20 04:56:42 +00:00
|
|
|
return (pathconf(td, (void *)uap));
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_fpathconf(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_fpathconf_args *uap;
|
|
|
|
{
|
|
|
|
|
|
|
|
if (osf2bsd_pathconf(&uap->name))
|
|
|
|
return (EINVAL);
|
|
|
|
else
|
2001-09-20 04:56:42 +00:00
|
|
|
return (fpathconf(td, (void *)uap));
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_getrusage(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_getrusage_args *uap;
|
|
|
|
{
|
2001-09-20 04:56:42 +00:00
|
|
|
struct proc *p;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct rusage *rup;
|
|
|
|
struct osf1_rusage oru;
|
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
p = td->td_proc;
|
1999-12-14 22:35:36 +00:00
|
|
|
switch (uap->who) {
|
|
|
|
case RUSAGE_SELF:
|
|
|
|
rup = &p->p_stats->p_ru;
|
Change and clean the mutex lock interface.
mtx_enter(lock, type) becomes:
mtx_lock(lock) for sleep locks (MTX_DEF-initialized locks)
mtx_lock_spin(lock) for spin locks (MTX_SPIN-initialized)
similarily, for releasing a lock, we now have:
mtx_unlock(lock) for MTX_DEF and mtx_unlock_spin(lock) for MTX_SPIN.
We change the caller interface for the two different types of locks
because the semantics are entirely different for each case, and this
makes it explicitly clear and, at the same time, it rids us of the
extra `type' argument.
The enter->lock and exit->unlock change has been made with the idea
that we're "locking data" and not "entering locked code" in mind.
Further, remove all additional "flags" previously passed to the
lock acquire/release routines with the exception of two:
MTX_QUIET and MTX_NOSWITCH
The functionality of these flags is preserved and they can be passed
to the lock/unlock routines by calling the corresponding wrappers:
mtx_{lock, unlock}_flags(lock, flag(s)) and
mtx_{lock, unlock}_spin_flags(lock, flag(s)) for MTX_DEF and MTX_SPIN
locks, respectively.
Re-inline some lock acq/rel code; in the sleep lock case, we only
inline the _obtain_lock()s in order to ensure that the inlined code
fits into a cache line. In the spin lock case, we inline recursion and
actually only perform a function call if we need to spin. This change
has been made with the idea that we generally tend to avoid spin locks
and that also the spin locks that we do have and are heavily used
(i.e. sched_lock) do recurse, and therefore in an effort to reduce
function call overhead for some architectures (such as alpha), we
inline recursion for this case.
Create a new malloc type for the witness code and retire from using
the M_DEV type. The new type is called M_WITNESS and is only declared
if WITNESS is enabled.
Begin cleaning up some machdep/mutex.h code - specifically updated the
"optimized" inlined code in alpha/mutex.h and wrote MTX_LOCK_SPIN
and MTX_UNLOCK_SPIN asm macros for the i386/mutex.h as we presently
need those.
Finally, caught up to the interface changes in all sys code.
Contributors: jake, jhb, jasone (in no particular order)
2001-02-09 06:11:45 +00:00
|
|
|
mtx_lock_spin(&sched_lock);
|
1999-12-14 22:35:36 +00:00
|
|
|
calcru(p, &rup->ru_utime, &rup->ru_stime, NULL);
|
Change and clean the mutex lock interface.
mtx_enter(lock, type) becomes:
mtx_lock(lock) for sleep locks (MTX_DEF-initialized locks)
mtx_lock_spin(lock) for spin locks (MTX_SPIN-initialized)
similarily, for releasing a lock, we now have:
mtx_unlock(lock) for MTX_DEF and mtx_unlock_spin(lock) for MTX_SPIN.
We change the caller interface for the two different types of locks
because the semantics are entirely different for each case, and this
makes it explicitly clear and, at the same time, it rids us of the
extra `type' argument.
The enter->lock and exit->unlock change has been made with the idea
that we're "locking data" and not "entering locked code" in mind.
Further, remove all additional "flags" previously passed to the
lock acquire/release routines with the exception of two:
MTX_QUIET and MTX_NOSWITCH
The functionality of these flags is preserved and they can be passed
to the lock/unlock routines by calling the corresponding wrappers:
mtx_{lock, unlock}_flags(lock, flag(s)) and
mtx_{lock, unlock}_spin_flags(lock, flag(s)) for MTX_DEF and MTX_SPIN
locks, respectively.
Re-inline some lock acq/rel code; in the sleep lock case, we only
inline the _obtain_lock()s in order to ensure that the inlined code
fits into a cache line. In the spin lock case, we inline recursion and
actually only perform a function call if we need to spin. This change
has been made with the idea that we generally tend to avoid spin locks
and that also the spin locks that we do have and are heavily used
(i.e. sched_lock) do recurse, and therefore in an effort to reduce
function call overhead for some architectures (such as alpha), we
inline recursion for this case.
Create a new malloc type for the witness code and retire from using
the M_DEV type. The new type is called M_WITNESS and is only declared
if WITNESS is enabled.
Begin cleaning up some machdep/mutex.h code - specifically updated the
"optimized" inlined code in alpha/mutex.h and wrote MTX_LOCK_SPIN
and MTX_UNLOCK_SPIN asm macros for the i386/mutex.h as we presently
need those.
Finally, caught up to the interface changes in all sys code.
Contributors: jake, jhb, jasone (in no particular order)
2001-02-09 06:11:45 +00:00
|
|
|
mtx_unlock_spin(&sched_lock);
|
1999-12-14 22:35:36 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RUSAGE_CHILDREN:
|
|
|
|
rup = &p->p_stats->p_cru;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
TV_CP(rup->ru_utime, oru.ru_utime);
|
|
|
|
TV_CP(rup->ru_stime, oru.ru_stime);
|
|
|
|
bcopy(&(rup->ru_first), &(oru.ru_first),
|
|
|
|
(&(oru.ru_last) - &(oru.ru_first)));
|
|
|
|
|
|
|
|
return (copyout((caddr_t)&oru, (caddr_t)uap->rusage,
|
|
|
|
sizeof (struct osf1_rusage)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_wait4(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_wait4_args *uap;
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
caddr_t sg;
|
|
|
|
struct osf1_rusage *orusage, oru;
|
2000-01-29 06:31:27 +00:00
|
|
|
struct rusage *rusage = NULL, ru;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
orusage = uap->rusage;
|
2000-01-29 06:31:27 +00:00
|
|
|
if (orusage) {
|
|
|
|
sg = stackgap_init();
|
|
|
|
rusage = stackgap_alloc(&sg, sizeof(struct rusage));
|
2002-12-14 01:56:26 +00:00
|
|
|
uap->rusage = (struct osf1_rusage *)rusage;
|
2000-01-29 06:31:27 +00:00
|
|
|
}
|
2001-09-20 04:56:42 +00:00
|
|
|
if ((error = wait4(td, (struct wait_args *)uap)))
|
1999-12-14 22:35:36 +00:00
|
|
|
return error;
|
|
|
|
if (orusage && (error = copyin(rusage, &ru, sizeof(ru)) == 0)){
|
|
|
|
TV_CP(ru.ru_utime, oru.ru_utime);
|
|
|
|
TV_CP(ru.ru_stime, oru.ru_stime);
|
|
|
|
bcopy(&ru.ru_first, &oru.ru_first,
|
|
|
|
(&(oru.ru_last) - &(oru.ru_first)));
|
|
|
|
copyout(&oru, orusage, sizeof (struct osf1_rusage));
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_madvise(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_madvise_args *uap;
|
|
|
|
{
|
|
|
|
|
|
|
|
/* XXX */
|
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_execve(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_execve_args *uap;
|
|
|
|
{
|
|
|
|
caddr_t sg;
|
|
|
|
struct execve_args ap;
|
|
|
|
|
|
|
|
sg = stackgap_init();
|
2002-12-14 01:56:26 +00:00
|
|
|
CHECKALTEXIST(td, &sg, uap->path);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
ap.fname = uap->path;
|
|
|
|
ap.argv = uap->argp;
|
|
|
|
ap.envv = uap->envp;
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
return execve(td, &ap);
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_usleep_thread(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_usleep_thread_args *uap;
|
|
|
|
{
|
|
|
|
int error, s, timo;
|
|
|
|
struct osf1_timeval time;
|
|
|
|
struct timeval difftv, endtv, sleeptv, tv;
|
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
if ((error = copyin(uap->sleep, &time, sizeof time)))
|
1999-12-14 22:35:36 +00:00
|
|
|
return (error);
|
|
|
|
|
|
|
|
sleeptv.tv_sec = (u_long)time.tv_sec;
|
|
|
|
sleeptv.tv_usec = (u_long)time.tv_usec;
|
|
|
|
timo = tvtohz(&sleeptv);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Some callers use usleep(0) as a sort of thread-yield so make
|
|
|
|
* sure that the timeout is non-zero.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (timo == 0)
|
|
|
|
timo = 1;
|
|
|
|
s = splclock();
|
|
|
|
microtime(&tv);
|
|
|
|
splx(s);
|
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
tsleep(td, PUSER|PCATCH, "OSF/1", timo);
|
1999-12-14 22:35:36 +00:00
|
|
|
|
2002-12-14 01:56:26 +00:00
|
|
|
if (uap->slept != NULL) {
|
1999-12-14 22:35:36 +00:00
|
|
|
s = splclock();
|
|
|
|
microtime(&endtv);
|
|
|
|
timersub(&time, &endtv, &difftv);
|
|
|
|
splx(s);
|
|
|
|
if (tv.tv_sec < 0 || tv.tv_usec < 0)
|
|
|
|
tv.tv_sec = tv.tv_usec = 0;
|
|
|
|
TV_CP(difftv, time)
|
2002-12-14 01:56:26 +00:00
|
|
|
error = copyout(&time, uap->slept, sizeof time);
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
int osf1_gettimeofday(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
register struct osf1_gettimeofday_args *uap;
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
struct timeval atv;
|
|
|
|
struct osf1_timeval otv;
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
|
|
|
|
if (uap->tp) {
|
|
|
|
microtime(&atv);
|
|
|
|
otv.tv_sec = atv.tv_sec;
|
|
|
|
otv.tv_usec = atv.tv_usec;
|
|
|
|
if ((error = copyout((caddr_t)&otv, (caddr_t)uap->tp,
|
|
|
|
sizeof (otv))))
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
if (uap->tzp)
|
|
|
|
error = copyout((caddr_t)&tz, (caddr_t)uap->tzp, sizeof (tz));
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
int osf1_select(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
register struct osf1_select_args *uap;
|
|
|
|
{
|
|
|
|
if (uap->tv) {
|
|
|
|
int error;
|
|
|
|
caddr_t sg;
|
|
|
|
struct osf1_timeval otv;
|
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
sg = stackgap_init();
|
|
|
|
|
|
|
|
if ((error=copyin((caddr_t)uap->tv,(caddr_t)&otv,sizeof(otv))))
|
|
|
|
return(error);
|
|
|
|
TV_CP(otv,tv);
|
|
|
|
uap->tv = stackgap_alloc(&sg, sizeof(struct timeval));
|
|
|
|
if ((error=copyout((caddr_t)&tv, (caddr_t)uap->tv,sizeof(tv))))
|
|
|
|
return(error);
|
|
|
|
}
|
2001-09-20 04:56:42 +00:00
|
|
|
return(select(td, (struct select_args *)uap));
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_setitimer(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_setitimer_args *uap;
|
|
|
|
{
|
|
|
|
|
|
|
|
int error;
|
|
|
|
caddr_t old_oitv, sg;
|
|
|
|
struct itimerval itv;
|
|
|
|
struct osf1_itimerval otv;
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
old_oitv = (caddr_t)uap->oitv;
|
|
|
|
sg = stackgap_init();
|
|
|
|
|
|
|
|
if ((error = copyin((caddr_t)uap->itv,(caddr_t)&otv,sizeof(otv)))) {
|
|
|
|
printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
TV_CP(otv.it_interval,itv.it_interval);
|
|
|
|
TV_CP(otv.it_value,itv.it_value);
|
|
|
|
uap->itv = stackgap_alloc(&sg, sizeof(struct itimerval));
|
|
|
|
if ((error = copyout((caddr_t)&itv,(caddr_t)uap->itv,sizeof(itv)))) {
|
|
|
|
printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
uap->oitv = stackgap_alloc(&sg, sizeof(struct itimerval));
|
2001-09-20 04:56:42 +00:00
|
|
|
if ((error = setitimer(td, (struct setitimer_args *)uap))) {
|
1999-12-14 22:35:36 +00:00
|
|
|
printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
if ((error = copyin((caddr_t)uap->oitv,(caddr_t)&itv,sizeof(itv)))) {
|
|
|
|
printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
TV_CP(itv.it_interval,otv.it_interval);
|
|
|
|
TV_CP(itv.it_value,otv.it_value);
|
|
|
|
if (old_oitv
|
|
|
|
&& (error = copyout((caddr_t)&otv, old_oitv, sizeof(otv)))) {
|
|
|
|
printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
|
|
|
|
}
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_getitimer(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_getitimer_args *uap;
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
caddr_t old_itv, sg;
|
|
|
|
struct itimerval itv;
|
|
|
|
struct osf1_itimerval otv;
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
old_itv = (caddr_t)uap->itv;
|
|
|
|
sg = stackgap_init();
|
|
|
|
|
|
|
|
uap->itv = stackgap_alloc(&sg, sizeof(struct itimerval));
|
2001-09-20 04:56:42 +00:00
|
|
|
if ((error = getitimer(td, (struct getitimer_args *)uap))) {
|
1999-12-14 22:35:36 +00:00
|
|
|
printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
if ((error = copyin((caddr_t)uap->itv,(caddr_t)&itv,sizeof(itv)))) {
|
|
|
|
printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
TV_CP(itv.it_interval,otv.it_interval);
|
|
|
|
TV_CP(itv.it_value,otv.it_value);
|
|
|
|
if ((error = copyout((caddr_t)&otv, old_itv, sizeof(otv)))) {
|
|
|
|
printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
|
|
|
|
}
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_proplist_syscall(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_proplist_syscall_args *uap;
|
|
|
|
{
|
|
|
|
|
|
|
|
return(EOPNOTSUPP);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_ntpgettime(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_ntpgettime_args *uap;
|
|
|
|
{
|
|
|
|
|
|
|
|
return(ENOSYS);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_ntpadjtime(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_ntpadjtime_args *uap;
|
|
|
|
{
|
|
|
|
|
|
|
|
return(ENOSYS);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_setpgrp(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_setpgrp_args *uap;
|
|
|
|
{
|
|
|
|
|
2001-09-20 04:56:42 +00:00
|
|
|
return(setpgid(td, (struct setpgid_args *)uap));
|
1999-12-14 22:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_uswitch(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_uswitch_args *uap;
|
|
|
|
{
|
2001-09-20 04:56:42 +00:00
|
|
|
struct proc *p;
|
1999-12-14 22:35:36 +00:00
|
|
|
int rv;
|
|
|
|
vm_map_entry_t entry;
|
|
|
|
vm_offset_t zero;
|
|
|
|
|
2001-07-04 16:20:28 +00:00
|
|
|
GIANT_REQUIRED;
|
2001-09-20 04:56:42 +00:00
|
|
|
p = td->td_proc;
|
1999-12-14 22:35:36 +00:00
|
|
|
zero = 0;
|
|
|
|
|
|
|
|
if (uap->cmd == OSF1_USC_GET) {
|
2001-09-20 04:56:42 +00:00
|
|
|
if (vm_map_lookup_entry(&(p->p_vmspace->vm_map), 0, &entry))
|
|
|
|
td->td_retval[0] = OSF1_USW_NULLP;
|
1999-12-14 22:35:36 +00:00
|
|
|
else
|
2001-09-20 04:56:42 +00:00
|
|
|
td->td_retval[0] = 0;
|
1999-12-14 22:35:36 +00:00
|
|
|
return(KERN_SUCCESS);
|
|
|
|
} else if (uap->cmd == OSF1_USC_SET)
|
|
|
|
if (uap->mask & OSF1_USW_NULLP) {
|
|
|
|
rv = vm_mmap(&(p->p_vmspace->vm_map), &zero, PAGE_SIZE,
|
|
|
|
VM_PROT_READ, VM_PROT_ALL,
|
|
|
|
MAP_PRIVATE | MAP_FIXED | MAP_ANON, NULL, 0);
|
|
|
|
if (!rv)
|
|
|
|
return(KERN_SUCCESS);
|
|
|
|
else {
|
|
|
|
printf(
|
|
|
|
"osf1_uswitch:vm_mmap of zero page failed with status %d\n",
|
|
|
|
rv);
|
|
|
|
return(rv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_classcntl(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_classcntl_args *uap;
|
|
|
|
{
|
|
|
|
|
|
|
|
return(EACCES); /* class scheduling not enabled */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct osf1_tbl_loadavg
|
|
|
|
{
|
|
|
|
union {
|
|
|
|
long l[3];
|
|
|
|
double d[3];
|
|
|
|
} tl_avenrun;
|
|
|
|
int tl_lscale;
|
|
|
|
long tl_mach_factor[3]; /* ???? */
|
|
|
|
};
|
|
|
|
|
|
|
|
struct osf1_tbl_sysinfo {
|
|
|
|
long si_user;
|
|
|
|
long si_nice;
|
|
|
|
long si_sys;
|
|
|
|
long si_idle;
|
|
|
|
long si_hz;
|
|
|
|
long si_phz;
|
|
|
|
long si_boottime;
|
|
|
|
long wait;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define TBL_LOADAVG 3
|
|
|
|
#define TBL_SYSINFO 12
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_table(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_table_args /*{
|
|
|
|
long id;
|
|
|
|
long index;
|
|
|
|
void *addr;
|
|
|
|
long nel;
|
|
|
|
u_long lel;
|
|
|
|
}*/ *uap;
|
|
|
|
{
|
|
|
|
int retval;
|
|
|
|
struct osf1_tbl_loadavg ld;
|
|
|
|
struct osf1_tbl_sysinfo si;
|
|
|
|
|
|
|
|
retval = 0;
|
|
|
|
|
|
|
|
switch(uap->id) {
|
|
|
|
case TBL_LOADAVG: /* xemacs wants this */
|
|
|
|
if ((uap->index != 0) || (uap->nel != 1))
|
|
|
|
retval = EINVAL;
|
|
|
|
bcopy(&averunnable, &ld, sizeof(averunnable));
|
|
|
|
ld.tl_lscale = (u_int)averunnable.fscale;
|
|
|
|
retval = copyout(&ld, uap->addr, sizeof(ld));
|
|
|
|
break;
|
|
|
|
case TBL_SYSINFO:
|
|
|
|
if ((uap->index != 0) || (uap->nel != 1))
|
|
|
|
retval = EINVAL;
|
|
|
|
bzero(&si, sizeof(si));
|
|
|
|
#if 0
|
|
|
|
si.si_user = cp_time[CP_USER];
|
|
|
|
si.si_nice = cp_time[CP_NICE];
|
|
|
|
si.si_sys = cp_time[CP_SYS];
|
|
|
|
si.si_idle = cp_time[CP_IDLE];
|
|
|
|
si.wait = cp_time[CP_INTR];
|
|
|
|
#endif
|
|
|
|
si.si_hz = hz;
|
|
|
|
si.si_phz = profhz;
|
|
|
|
si.si_boottime = boottime.tv_sec;
|
|
|
|
retval = copyout(&si, uap->addr, sizeof(si));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
printf("osf1_table: %ld, %ld, %p, %ld %ld\n",
|
|
|
|
uap->id, uap->index, uap->addr, uap->nel, uap->lel);
|
|
|
|
retval = EINVAL;
|
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2001-09-20 04:56:42 +00:00
|
|
|
osf1_sysinfo(td, uap)
|
|
|
|
struct thread *td;
|
1999-12-14 22:35:36 +00:00
|
|
|
struct osf1_sysinfo_args /*{
|
|
|
|
int cmd;
|
|
|
|
char *buf;
|
|
|
|
long count;
|
|
|
|
}*/ *uap;
|
|
|
|
{
|
|
|
|
int name[2], retval;
|
|
|
|
size_t bytes, len;
|
|
|
|
char *string;
|
|
|
|
|
|
|
|
string = NULL;
|
|
|
|
|
|
|
|
switch(uap->cmd) {
|
|
|
|
case 1: /* OS */
|
|
|
|
string = "OSF1";
|
|
|
|
break;
|
|
|
|
case 2: /* hostname, from ogethostname */
|
|
|
|
len = uap->count;
|
|
|
|
name[0] = CTL_KERN;
|
|
|
|
name[1] = KERN_HOSTNAME;
|
2001-09-20 04:56:42 +00:00
|
|
|
retval = userland_sysctl(td, name, 2, uap->buf, &len,
|
1999-12-14 22:35:36 +00:00
|
|
|
1, 0, 0, &bytes);
|
2001-09-20 04:56:42 +00:00
|
|
|
td->td_retval[0] = bytes;
|
1999-12-14 22:35:36 +00:00
|
|
|
return(retval);
|
|
|
|
break;
|
|
|
|
case 3: /* release of osf1 */
|
|
|
|
string = "V4.0";
|
|
|
|
break;
|
|
|
|
case 4: /* minor version of osf1 */
|
|
|
|
string = "878";
|
|
|
|
break;
|
|
|
|
case 5: /* machine or arch */
|
|
|
|
case 6:
|
|
|
|
string = "alpha";
|
|
|
|
break;
|
|
|
|
case 7: /* serial number, real osf1 returns 0! */
|
|
|
|
string = "0";
|
|
|
|
break;
|
|
|
|
case 8: /* HW vendor */
|
|
|
|
string = "Digital";
|
|
|
|
break;
|
|
|
|
case 9: /* dunno, this is what du does.. */
|
|
|
|
return(ENOSYS);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return(EINVAL);
|
|
|
|
}
|
|
|
|
bytes = min(uap->count, strlen(string)+1);
|
|
|
|
copyout(string, uap->buf, bytes);
|
2001-09-20 04:56:42 +00:00
|
|
|
td->td_retval[0] = bytes;
|
1999-12-14 22:35:36 +00:00
|
|
|
return(0);
|
|
|
|
}
|