Index: head/include/Makefile =================================================================== --- head/include/Makefile (revision 164183) +++ head/include/Makefile (revision 164184) @@ -1,289 +1,289 @@ # @(#)Makefile 8.2 (Berkeley) 1/4/94 # $FreeBSD$ # # Doing a "make install" builds /usr/include. .include CLEANFILES= osreldate.h version vers.c SUBDIR= arpa gssapi protocols rpcsvc rpc INCS= a.out.h ar.h assert.h bitstring.h complex.h cpio.h _ctype.h ctype.h \ db.h \ dirent.h dlfcn.h elf.h elf-hints.h err.h fmtmsg.h fnmatch.h fstab.h \ fts.h ftw.h getopt.h glob.h grp.h gssapi.h \ histedit.h ieeefp.h ifaddrs.h \ inttypes.h iso646.h kenv.h langinfo.h libgen.h limits.h link.h \ locale.h malloc.h malloc_np.h memory.h monetary.h mpool.h mqueue.h \ ndbm.h netconfig.h \ netdb.h nl_types.h nlist.h nss.h nsswitch.h objformat.h paths.h \ printf.h proc_service.h pthread.h \ pthread_np.h pwd.h ranlib.h readpassphrase.h regex.h regexp.h \ res_update.h resolv.h runetype.h search.h setjmp.h sgtty.h \ signal.h stab.h \ stdbool.h stddef.h stdio.h stdlib.h string.h stringlist.h \ strings.h sysexits.h tar.h tgmath.h \ time.h timeconv.h timers.h ttyent.h \ ulimit.h unistd.h utime.h utmp.h uuid.h varargs.h vis.h wchar.h \ wctype.h wordexp.h MHDRS= float.h floatingpoint.h stdarg.h PHDRS= sched.h semaphore.h _semaphore.h LHDRS= aio.h errno.h fcntl.h linker_set.h poll.h stdint.h syslog.h \ termios.h ucontext.h LDIRS= bsm cam geom net net80211 netatalk netatm netgraph netinet netinet6 \ netipsec ${_netipx} netkey netnatm ${_netncp} netsmb \ nfs nfsclient nfsserver \ - pccard posix4 sys vm + pccard sys vm LSUBDIRS= cam/scsi \ dev/acpica dev/an dev/bktr dev/firewire dev/hwpmc \ dev/ic dev/iicbus ${_dev_ieee488} dev/lmc dev/ofw \ dev/pbio ${_dev_powermac_nvram} dev/ppbus dev/smbus dev/speaker dev/usb dev/utopia dev/vkbd dev/wi \ fs/devfs fs/fdescfs fs/fifofs fs/msdosfs fs/ntfs fs/nullfs \ ${_fs_nwfs} fs/portalfs fs/procfs fs/smbfs fs/udf fs/umapfs \ fs/unionfs \ geom/cache geom/concat geom/eli geom/gate geom/journal geom/label \ geom/mirror geom/nop geom/raid3 geom/shsec geom/stripe \ isofs/cd9660 \ netatm/ipatm netatm/sigpvc netatm/spans netatm/uni \ netgraph/atm netgraph/netflow \ security/audit \ security/mac_biba security/mac_bsdextended security/mac_lomac \ security/mac_mls security/mac_partition \ ufs/ffs ufs/ufs .if ${MACHINE_ARCH} == "powerpc" _dev_powermac_nvram= dev/powermac_nvram .endif .if ${MK_GPIB} != "no" _dev_ieee488= dev/ieee488 .endif .if ${MK_HESIOD} != "no" INCS+= hesiod.h .endif .if ${MK_BLUETOOTH} != "no" LSUBSUBDIRS= netgraph/bluetooth/include .endif # XXX unconditionally needed by #.if ${MK_IPX} != "no" _netipx= netipx #.endif .if ${MK_NCP} != "no" _netncp= netncp _fs_nwfs= fs/nwfs .endif # Define SHARED to indicate whether you want symbolic links to the system # source (``symlinks''), or a separate copy (``copies''). ``symlinks'' is # probably only useful for developers and should be avoided if you do not # wish to tie your /usr/include and /usr/src together. #SHARED= symlinks SHARED?= copies INCS+= osreldate.h osreldate.h: ${.CURDIR}/../sys/conf/newvers.sh ${.CURDIR}/../sys/sys/param.h \ ${.CURDIR}/Makefile @${ECHO} creating osreldate.h from newvers.sh @MAKE=${MAKE}; \ PARAMFILE=${.CURDIR}/../sys/sys/param.h; \ . ${.CURDIR}/../sys/conf/newvers.sh; \ echo "$$COPYRIGHT" > osreldate.h; \ echo "#ifdef _KERNEL" >> osreldate.h; \ echo "#error \" cannot be used in the kernel, use \"" >> osreldate.h; \ echo "#else" >> osreldate.h; \ echo "#undef __FreeBSD_version" >> osreldate.h; \ echo "#define __FreeBSD_version $$RELDATE" >> osreldate.h; \ echo "#endif" >> osreldate.h .for i in ${LHDRS} INCSLINKS+= sys/$i ${INCLUDEDIR}/$i .endfor .for i in ${MHDRS} INCSLINKS+= machine/$i ${INCLUDEDIR}/$i .endfor .for i in ${PHDRS} -INCSLINKS+= posix4/$i ${INCLUDEDIR}/$i +INCSLINKS+= sys/$i ${INCLUDEDIR}/$i .endfor .if ${MACHINE} != ${MACHINE_ARCH} _MARCH=${MACHINE_ARCH} .endif .include installincludes: ${SHARED} ${SHARED}: compat # Take care of stale directory-level symlinks. compat: .for i in ${LDIRS} ${LSUBDIRS} machine ${_MARCH} crypto if [ -L ${DESTDIR}${INCLUDEDIR}/$i ]; then \ rm -f ${DESTDIR}${INCLUDEDIR}/$i; \ fi .endfor mtree -deU ${MTREE_FOLLOWS_SYMLINKS} \ -f ${.CURDIR}/../etc/mtree/BSD.include.dist \ -p ${DESTDIR}${INCLUDEDIR} .if ${MK_BIND_LIBS} != "no" mtree -deU ${MTREE_FOLLOWS_SYMLINKS} \ -f ${.CURDIR}/../etc/mtree/BIND.include.dist \ -p ${DESTDIR}${INCLUDEDIR} .endif copies: .for i in ${LDIRS} ${LSUBDIRS} ${LSUBSUBDIRS} altq crypto machine machine/pc \ ${_MARCH} .if exists(${DESTDIR}${INCLUDEDIR}/$i) cd ${DESTDIR}${INCLUDEDIR}/$i; \ for h in *.h; do \ if [ -L $$h ]; then rm -f $$h; fi; \ done .endif .endfor .for i in ${LDIRS} ${LSUBDIRS:Ndev/acpica:Ndev/bktr} ${LSUBSUBDIRS} cd ${.CURDIR}/../sys; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 $i/*.h \ ${DESTDIR}${INCLUDEDIR}/$i .endfor cd ${.CURDIR}/../sys/dev/acpica; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 acpiio.h \ ${DESTDIR}${INCLUDEDIR}/dev/acpica cd ${.CURDIR}/../sys/dev/bktr; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ioctl_*.h \ ${DESTDIR}${INCLUDEDIR}/dev/bktr cd ${.CURDIR}/../sys/contrib/altq/altq; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/altq .if ${MK_IPFILTER} != "no" cd ${.CURDIR}/../sys/contrib/ipfilter/netinet; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/netinet .endif cd ${.CURDIR}/../sys/contrib/pf/net; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/net cd ${.CURDIR}/../sys/crypto; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 rijndael/rijndael.h \ ${DESTDIR}${INCLUDEDIR}/crypto cd ${.CURDIR}/../sys/opencrypto; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/crypto cd ${.CURDIR}/../sys/${MACHINE}/include; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/machine .if exists(${.CURDIR}/../sys/${MACHINE}/include/pc) cd ${.CURDIR}/../sys/${MACHINE}/include/pc; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/machine/pc .endif .if defined(_MARCH) ${INSTALL} -d -o ${BINOWN} -g ${BINGRP} -m 755 \ ${DESTDIR}${INCLUDEDIR}/${_MARCH}; \ cd ${.CURDIR}/../sys/${_MARCH}/include; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/${_MARCH} .if exists(${.CURDIR}/../sys/${_MARCH}/include/pc) ${INSTALL} -d -o ${BINOWN} -g ${BINGRP} -m 755 \ ${DESTDIR}${INCLUDEDIR}/${_MARCH}/pc; \ cd ${.CURDIR}/../sys/${_MARCH}/include/pc; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/${_MARCH}/pc .endif .endif symlinks: @${ECHO} "Setting up symlinks to kernel source tree..." .for i in ${LDIRS} cd ${.CURDIR}/../sys/$i; \ for h in *.h; do \ ln -fs ../../../sys/$i/$$h ${DESTDIR}${INCLUDEDIR}/$i; \ done .endfor .for i in ${LSUBDIRS:Ndev/acpica:Ndev/bktr} cd ${.CURDIR}/../sys/$i; \ for h in *.h; do \ ln -fs ../../../../sys/$i/$$h ${DESTDIR}${INCLUDEDIR}/$i; \ done .endfor cd ${.CURDIR}/../sys/dev/acpica; \ for h in acpiio.h; do \ ln -fs ../../../../sys/dev/acpica/$$h \ ${DESTDIR}${INCLUDEDIR}/dev/acpica; \ done cd ${.CURDIR}/../sys/dev/bktr; \ for h in ioctl_*.h; do \ ln -fs ../../../../sys/dev/bktr/$$h \ ${DESTDIR}${INCLUDEDIR}/dev/bktr; \ done .for i in ${LSUBSUBDIRS} cd ${.CURDIR}/../sys/$i; \ for h in *.h; do \ ln -fs ../../../../../sys/$i/$$h ${DESTDIR}${INCLUDEDIR}/$i; \ done .endfor cd ${.CURDIR}/../sys/contrib/altq/altq; \ for h in *.h; do \ ln -fs ../../../sys/contrib/altq/altq/$$h \ ${DESTDIR}${INCLUDEDIR}/altq; \ done .if ${MK_IPFILTER} != "no" cd ${.CURDIR}/../sys/contrib/ipfilter/netinet; \ for h in *.h; do \ ln -fs ../../../sys/contrib/ipfilter/netinet/$$h \ ${DESTDIR}${INCLUDEDIR}/netinet; \ done .endif cd ${.CURDIR}/../sys/contrib/pf/net; \ for h in *.h; do \ ln -fs ../../../sys/contrib/pf/net/$$h \ ${DESTDIR}${INCLUDEDIR}/net; \ done cd ${.CURDIR}/../sys/crypto; \ for h in rijndael/rijndael.h; do \ ln -fs ../../../sys/crypto/$$h \ ${DESTDIR}${INCLUDEDIR}/crypto; \ done cd ${.CURDIR}/../sys/opencrypto; \ for h in *.h; do \ ln -fs ../../../sys/opencrypto/$$h \ ${DESTDIR}${INCLUDEDIR}/crypto; \ done cd ${.CURDIR}/../sys/${MACHINE}/include; \ for h in *.h; do \ ln -fs ../../../sys/${MACHINE}/include/$$h \ ${DESTDIR}${INCLUDEDIR}/machine; \ done .if exists(${.CURDIR}/../sys/${MACHINE}/include/pc) cd ${.CURDIR}/../sys/${MACHINE}/include/pc; \ for h in *.h; do \ ln -fs ../../../../sys/${MACHINE}/include/pc/$$h \ ${DESTDIR}${INCLUDEDIR}/machine/pc; \ done .endif .if defined(_MARCH) ${INSTALL} -d -o ${BINOWN} -g ${BINGRP} -m 755 \ ${DESTDIR}${INCLUDEDIR}/${_MARCH}; \ cd ${.CURDIR}/../sys/${_MARCH}/include; \ for h in *.h; do \ ln -fs ../../../sys/${_MARCH}/include/$$h \ ${DESTDIR}${INCLUDEDIR}/${_MARCH}; \ done .if exists(${.CURDIR}/../sys/${_MARCH}/include/pc) ${INSTALL} -d -o ${BINOWN} -g ${BINGRP} -m 755 \ ${DESTDIR}${INCLUDEDIR}/${_MARCH}/pc; \ cd ${.CURDIR}/../sys/${_MARCH}/include/pc; \ for h in *.h; do \ ln -fs ../../../../sys/${_MARCH}/include/pc/$$h \ ${DESTDIR}${INCLUDEDIR}/${_MARCH}/pc; \ done .endif .endif Index: head/sys/Makefile =================================================================== --- head/sys/Makefile (revision 164183) +++ head/sys/Makefile (revision 164184) @@ -1,37 +1,37 @@ # $FreeBSD$ .include # The boot loader .if ${MK_BOOT} != "no" SUBDIR= boot .endif # Directories to include in cscope name file and TAGS. CSCOPEDIRS= coda compat conf contrib crypto ddb dev fs geom gnu i4b isa \ isofs kern libkern modules net net80211 netatalk netatm \ netgraph netinet netinet6 netipx netkey netnatm netncp \ - netsmb nfs nfsclient nfs4client rpc pccard pci posix4 sys \ + netsmb nfs nfsclient nfs4client rpc pccard pci sys \ ufs vm ${ARCHDIR} ARCHDIR ?= ${MACHINE} # Loadable kernel modules .if defined(MODULES_WITH_WORLD) SUBDIR+=modules .endif HTAGSFLAGS+= -at `awk -F= '/^RELEASE *=/{release=$2}; END {print "FreeBSD", release, "kernel"}' < conf/newvers.sh` cscope: ${.CURDIR}/cscopenamefile cd ${.CURDIR}; cscope -k -p4 -i cscopenamefile ${.CURDIR}/cscopenamefile: cd ${.CURDIR}; find ${CSCOPEDIRS} -name "*.[csh]" > ${.TARGET} TAGS ${.CURDIR}/TAGS: ${.CURDIR}/cscopenamefile rm -f ${.CURDIR}/TAGS cd ${.CURDIR}; xargs etags -a < ${.CURDIR}/cscopenamefile .include Index: head/sys/compat/linux/linux_misc.c =================================================================== --- head/sys/compat/linux/linux_misc.c (revision 164183) +++ head/sys/compat/linux/linux_misc.c (revision 164184) @@ -1,1601 +1,1600 @@ /*- * Copyright (c) 2002 Doug Rabson * Copyright (c) 1994-1995 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_compat.h" #include "opt_mac.h" #include #include #include #if defined(__i386__) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include - -#include #include #include #include #ifdef COMPAT_LINUX32 #include #include #else #include #include #endif #include #include #include #ifdef __i386__ #include #endif #define BSD_TO_LINUX_SIGNAL(sig) \ (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig) static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = { RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK, RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE, RLIMIT_MEMLOCK, -1 }; struct l_sysinfo { l_long uptime; /* Seconds since boot */ l_ulong loads[3]; /* 1, 5, and 15 minute load averages */ #define LINUX_SYSINFO_LOADS_SCALE 65536 l_ulong totalram; /* Total usable main memory size */ l_ulong freeram; /* Available memory size */ l_ulong sharedram; /* Amount of shared memory */ l_ulong bufferram; /* Memory used by buffers */ l_ulong totalswap; /* Total swap space size */ l_ulong freeswap; /* swap space still available */ l_ushort procs; /* Number of current processes */ l_ulong totalbig; l_ulong freebig; l_uint mem_unit; char _f[6]; /* Pads structure to 64 bytes */ }; int linux_sysinfo(struct thread *td, struct linux_sysinfo_args *args) { struct l_sysinfo sysinfo; vm_object_t object; int i, j; struct timespec ts; getnanouptime(&ts); if (ts.tv_nsec != 0) ts.tv_sec++; sysinfo.uptime = ts.tv_sec; /* Use the information from the mib to get our load averages */ for (i = 0; i < 3; i++) sysinfo.loads[i] = averunnable.ldavg[i] * LINUX_SYSINFO_LOADS_SCALE / averunnable.fscale; sysinfo.totalram = physmem * PAGE_SIZE; sysinfo.freeram = sysinfo.totalram - cnt.v_wire_count * PAGE_SIZE; sysinfo.sharedram = 0; mtx_lock(&vm_object_list_mtx); TAILQ_FOREACH(object, &vm_object_list, object_list) if (object->shadow_count > 1) sysinfo.sharedram += object->resident_page_count; mtx_unlock(&vm_object_list_mtx); sysinfo.sharedram *= PAGE_SIZE; sysinfo.bufferram = 0; swap_pager_status(&i, &j); sysinfo.totalswap= i * PAGE_SIZE; sysinfo.freeswap = (i - j) * PAGE_SIZE; sysinfo.procs = nprocs; /* The following are only present in newer Linux kernels. */ sysinfo.totalbig = 0; sysinfo.freebig = 0; sysinfo.mem_unit = 1; return copyout(&sysinfo, args->info, sizeof(sysinfo)); } int linux_alarm(struct thread *td, struct linux_alarm_args *args) { struct itimerval it, old_it; int error; #ifdef DEBUG if (ldebug(alarm)) printf(ARGS(alarm, "%u"), args->secs); #endif if (args->secs > 100000000) return (EINVAL); it.it_value.tv_sec = (long)args->secs; it.it_value.tv_usec = 0; it.it_interval.tv_sec = 0; it.it_interval.tv_usec = 0; error = kern_setitimer(td, ITIMER_REAL, &it, &old_it); if (error) return (error); if (timevalisset(&old_it.it_value)) { if (old_it.it_value.tv_usec != 0) old_it.it_value.tv_sec++; td->td_retval[0] = old_it.it_value.tv_sec; } return (0); } int linux_brk(struct thread *td, struct linux_brk_args *args) { struct vmspace *vm = td->td_proc->p_vmspace; vm_offset_t new, old; struct obreak_args /* { char * nsize; } */ tmp; #ifdef DEBUG if (ldebug(brk)) printf(ARGS(brk, "%p"), (void *)(uintptr_t)args->dsend); #endif old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize); new = (vm_offset_t)args->dsend; tmp.nsize = (char *) new; if (((caddr_t)new > vm->vm_daddr) && !obreak(td, &tmp)) td->td_retval[0] = (long)new; else td->td_retval[0] = (long)old; return 0; } #if defined(__i386__) /* XXX: what about amd64/linux32? */ int linux_uselib(struct thread *td, struct linux_uselib_args *args) { struct nameidata ni; struct vnode *vp; struct exec *a_out; struct vattr attr; vm_offset_t vmaddr; unsigned long file_offset; vm_offset_t buffer; unsigned long bss_size; char *library; int error; int locked, vfslocked; LCONVPATHEXIST(td, args->library, &library); #ifdef DEBUG if (ldebug(uselib)) printf(ARGS(uselib, "%s"), library); #endif a_out = NULL; vfslocked = 0; locked = 0; vp = NULL; NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, UIO_SYSSPACE, library, td); error = namei(&ni); LFREEPATH(library); if (error) goto cleanup; vp = ni.ni_vp; vfslocked = NDHASGIANT(&ni); NDFREE(&ni, NDF_ONLY_PNBUF); /* * From here on down, we have a locked vnode that must be unlocked. * XXX: The code below largely duplicates exec_check_permissions(). */ locked = 1; /* Writable? */ if (vp->v_writecount) { error = ETXTBSY; goto cleanup; } /* Executable? */ error = VOP_GETATTR(vp, &attr, td->td_ucred, td); if (error) goto cleanup; if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) { /* EACCESS is what exec(2) returns. */ error = ENOEXEC; goto cleanup; } /* Sensible size? */ if (attr.va_size == 0) { error = ENOEXEC; goto cleanup; } /* Can we access it? */ error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); if (error) goto cleanup; /* * XXX: This should use vn_open() so that it is properly authorized, * and to reduce code redundancy all over the place here. * XXX: Not really, it duplicates far more of exec_check_permissions() * than vn_open(). */ #ifdef MAC error = mac_check_vnode_open(td->td_ucred, vp, FREAD); if (error) goto cleanup; #endif error = VOP_OPEN(vp, FREAD, td->td_ucred, td, -1); if (error) goto cleanup; /* Pull in executable header into kernel_map */ error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE, VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, 0); if (error) goto cleanup; /* Is it a Linux binary ? */ if (((a_out->a_magic >> 16) & 0xff) != 0x64) { error = ENOEXEC; goto cleanup; } /* * While we are here, we should REALLY do some more checks */ /* Set file/virtual offset based on a.out variant. */ switch ((int)(a_out->a_magic & 0xffff)) { case 0413: /* ZMAGIC */ file_offset = 1024; break; case 0314: /* QMAGIC */ file_offset = 0; break; default: error = ENOEXEC; goto cleanup; } bss_size = round_page(a_out->a_bss); /* Check various fields in header for validity/bounds. */ if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) { error = ENOEXEC; goto cleanup; } /* text + data can't exceed file size */ if (a_out->a_data + a_out->a_text > attr.va_size) { error = EFAULT; goto cleanup; } /* * text/data/bss must not exceed limits * XXX - this is not complete. it should check current usage PLUS * the resources needed by this library. */ PROC_LOCK(td->td_proc); if (a_out->a_text > maxtsiz || a_out->a_data + bss_size > lim_cur(td->td_proc, RLIMIT_DATA)) { PROC_UNLOCK(td->td_proc); error = ENOMEM; goto cleanup; } PROC_UNLOCK(td->td_proc); /* * Prevent more writers. * XXX: Note that if any of the VM operations fail below we don't * clear this flag. */ vp->v_vflag |= VV_TEXT; /* * Lock no longer needed */ locked = 0; VOP_UNLOCK(vp, 0, td); VFS_UNLOCK_GIANT(vfslocked); /* * Check if file_offset page aligned. Currently we cannot handle * misalinged file offsets, and so we read in the entire image * (what a waste). */ if (file_offset & PAGE_MASK) { #ifdef DEBUG printf("uselib: Non page aligned binary %lu\n", file_offset); #endif /* Map text+data read/write/execute */ /* a_entry is the load address and is page aligned */ vmaddr = trunc_page(a_out->a_entry); /* get anon user mapping, read+write+execute */ error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0, &vmaddr, a_out->a_text + a_out->a_data, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) goto cleanup; /* map file into kernel_map */ error = vm_mmap(kernel_map, &buffer, round_page(a_out->a_text + a_out->a_data + file_offset), VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, trunc_page(file_offset)); if (error) goto cleanup; /* copy from kernel VM space to user space */ error = copyout(PTRIN(buffer + file_offset), (void *)vmaddr, a_out->a_text + a_out->a_data); /* release temporary kernel space */ vm_map_remove(kernel_map, buffer, buffer + round_page(a_out->a_text + a_out->a_data + file_offset)); if (error) goto cleanup; } else { #ifdef DEBUG printf("uselib: Page aligned binary %lu\n", file_offset); #endif /* * for QMAGIC, a_entry is 20 bytes beyond the load address * to skip the executable header */ vmaddr = trunc_page(a_out->a_entry); /* * Map it all into the process's space as a single * copy-on-write "data" segment. */ error = vm_mmap(&td->td_proc->p_vmspace->vm_map, &vmaddr, a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, OBJT_VNODE, vp, file_offset); if (error) goto cleanup; } #ifdef DEBUG printf("mem=%08lx = %08lx %08lx\n", (long)vmaddr, ((long*)vmaddr)[0], ((long*)vmaddr)[1]); #endif if (bss_size != 0) { /* Calculate BSS start address */ vmaddr = trunc_page(a_out->a_entry) + a_out->a_text + a_out->a_data; /* allocate some 'anon' space */ error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0, &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) goto cleanup; } cleanup: /* Unlock vnode if needed */ if (locked) { VOP_UNLOCK(vp, 0, td); VFS_UNLOCK_GIANT(vfslocked); } /* Release the kernel mapping. */ if (a_out) vm_map_remove(kernel_map, (vm_offset_t)a_out, (vm_offset_t)a_out + PAGE_SIZE); return error; } #endif /* __i386__ */ int linux_select(struct thread *td, struct linux_select_args *args) { l_timeval ltv; struct timeval tv0, tv1, utv, *tvp; int error; #ifdef DEBUG if (ldebug(select)) printf(ARGS(select, "%d, %p, %p, %p, %p"), args->nfds, (void *)args->readfds, (void *)args->writefds, (void *)args->exceptfds, (void *)args->timeout); #endif /* * Store current time for computation of the amount of * time left. */ if (args->timeout) { if ((error = copyin(args->timeout, <v, sizeof(ltv)))) goto select_out; utv.tv_sec = ltv.tv_sec; utv.tv_usec = ltv.tv_usec; #ifdef DEBUG if (ldebug(select)) printf(LMSG("incoming timeout (%jd/%ld)"), (intmax_t)utv.tv_sec, utv.tv_usec); #endif if (itimerfix(&utv)) { /* * The timeval was invalid. Convert it to something * valid that will act as it does under Linux. */ utv.tv_sec += utv.tv_usec / 1000000; utv.tv_usec %= 1000000; if (utv.tv_usec < 0) { utv.tv_sec -= 1; utv.tv_usec += 1000000; } if (utv.tv_sec < 0) timevalclear(&utv); } microtime(&tv0); tvp = &utv; } else tvp = NULL; error = kern_select(td, args->nfds, args->readfds, args->writefds, args->exceptfds, tvp); #ifdef DEBUG if (ldebug(select)) printf(LMSG("real select returns %d"), error); #endif if (error) { /* * See fs/select.c in the Linux kernel. Without this, * Maelstrom doesn't work. */ if (error == ERESTART) error = EINTR; goto select_out; } if (args->timeout) { if (td->td_retval[0]) { /* * Compute how much time was left of the timeout, * by subtracting the current time and the time * before we started the call, and subtracting * that result from the user-supplied value. */ microtime(&tv1); timevalsub(&tv1, &tv0); timevalsub(&utv, &tv1); if (utv.tv_sec < 0) timevalclear(&utv); } else timevalclear(&utv); #ifdef DEBUG if (ldebug(select)) printf(LMSG("outgoing timeout (%jd/%ld)"), (intmax_t)utv.tv_sec, utv.tv_usec); #endif ltv.tv_sec = utv.tv_sec; ltv.tv_usec = utv.tv_usec; if ((error = copyout(<v, args->timeout, sizeof(ltv)))) goto select_out; } select_out: #ifdef DEBUG if (ldebug(select)) printf(LMSG("select_out -> %d"), error); #endif return error; } int linux_mremap(struct thread *td, struct linux_mremap_args *args) { struct munmap_args /* { void *addr; size_t len; } */ bsd_args; int error = 0; #ifdef DEBUG if (ldebug(mremap)) printf(ARGS(mremap, "%p, %08lx, %08lx, %08lx"), (void *)(uintptr_t)args->addr, (unsigned long)args->old_len, (unsigned long)args->new_len, (unsigned long)args->flags); #endif args->new_len = round_page(args->new_len); args->old_len = round_page(args->old_len); if (args->new_len > args->old_len) { td->td_retval[0] = 0; return ENOMEM; } if (args->new_len < args->old_len) { bsd_args.addr = (caddr_t)((uintptr_t)args->addr + args->new_len); bsd_args.len = args->old_len - args->new_len; error = munmap(td, &bsd_args); } td->td_retval[0] = error ? 0 : (uintptr_t)args->addr; return error; } #define LINUX_MS_ASYNC 0x0001 #define LINUX_MS_INVALIDATE 0x0002 #define LINUX_MS_SYNC 0x0004 int linux_msync(struct thread *td, struct linux_msync_args *args) { struct msync_args bsd_args; bsd_args.addr = (caddr_t)(uintptr_t)args->addr; bsd_args.len = (uintptr_t)args->len; bsd_args.flags = args->fl & ~LINUX_MS_SYNC; return msync(td, &bsd_args); } int linux_time(struct thread *td, struct linux_time_args *args) { struct timeval tv; l_time_t tm; int error; #ifdef DEBUG if (ldebug(time)) printf(ARGS(time, "*")); #endif microtime(&tv); tm = tv.tv_sec; if (args->tm && (error = copyout(&tm, args->tm, sizeof(tm)))) return error; td->td_retval[0] = tm; return 0; } struct l_times_argv { l_long tms_utime; l_long tms_stime; l_long tms_cutime; l_long tms_cstime; }; #define CLK_TCK 100 /* Linux uses 100 */ #define CONVTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK)) int linux_times(struct thread *td, struct linux_times_args *args) { struct timeval tv, utime, stime, cutime, cstime; struct l_times_argv tms; struct proc *p; int error; #ifdef DEBUG if (ldebug(times)) printf(ARGS(times, "*")); #endif if (args->buf != NULL) { p = td->td_proc; PROC_LOCK(p); calcru(p, &utime, &stime); calccru(p, &cutime, &cstime); PROC_UNLOCK(p); tms.tms_utime = CONVTCK(utime); tms.tms_stime = CONVTCK(stime); tms.tms_cutime = CONVTCK(cutime); tms.tms_cstime = CONVTCK(cstime); if ((error = copyout(&tms, args->buf, sizeof(tms)))) return error; } microuptime(&tv); td->td_retval[0] = (int)CONVTCK(tv); return 0; } int linux_newuname(struct thread *td, struct linux_newuname_args *args) { struct l_new_utsname utsname; char osname[LINUX_MAX_UTSNAME]; char osrelease[LINUX_MAX_UTSNAME]; char *p; #ifdef DEBUG if (ldebug(newuname)) printf(ARGS(newuname, "*")); #endif linux_get_osname(td, osname); linux_get_osrelease(td, osrelease); bzero(&utsname, sizeof(utsname)); strlcpy(utsname.sysname, osname, LINUX_MAX_UTSNAME); getcredhostname(td->td_ucred, utsname.nodename, LINUX_MAX_UTSNAME); strlcpy(utsname.release, osrelease, LINUX_MAX_UTSNAME); strlcpy(utsname.version, version, LINUX_MAX_UTSNAME); for (p = utsname.version; *p != '\0'; ++p) if (*p == '\n') { *p = '\0'; break; } #ifdef __i386__ { const char *class; switch (cpu_class) { case CPUCLASS_686: class = "i686"; break; case CPUCLASS_586: class = "i586"; break; case CPUCLASS_486: class = "i486"; break; default: class = "i386"; } strlcpy(utsname.machine, class, LINUX_MAX_UTSNAME); } #elif defined(__amd64__) /* XXX: Linux can change 'personality'. */ #ifdef COMPAT_LINUX32 strlcpy(utsname.machine, "i686", LINUX_MAX_UTSNAME); #else strlcpy(utsname.machine, "x86_64", LINUX_MAX_UTSNAME); #endif /* COMPAT_LINUX32 */ #else /* something other than i386 or amd64 - assume we and Linux agree */ strlcpy(utsname.machine, machine, LINUX_MAX_UTSNAME); #endif /* __i386__ */ strlcpy(utsname.domainname, domainname, LINUX_MAX_UTSNAME); return (copyout(&utsname, args->buf, sizeof(utsname))); } #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) struct l_utimbuf { l_time_t l_actime; l_time_t l_modtime; }; int linux_utime(struct thread *td, struct linux_utime_args *args) { struct timeval tv[2], *tvp; struct l_utimbuf lut; char *fname; int error; LCONVPATHEXIST(td, args->fname, &fname); #ifdef DEBUG if (ldebug(utime)) printf(ARGS(utime, "%s, *"), fname); #endif if (args->times) { if ((error = copyin(args->times, &lut, sizeof lut))) { LFREEPATH(fname); return error; } tv[0].tv_sec = lut.l_actime; tv[0].tv_usec = 0; tv[1].tv_sec = lut.l_modtime; tv[1].tv_usec = 0; tvp = tv; } else tvp = NULL; error = kern_utimes(td, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE); LFREEPATH(fname); return (error); } #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ #define __WCLONE 0x80000000 int linux_waitpid(struct thread *td, struct linux_waitpid_args *args) { int error, options, tmpstat; #ifdef DEBUG if (ldebug(waitpid)) printf(ARGS(waitpid, "%d, %p, %d"), args->pid, (void *)args->status, args->options); #endif /* * this is necessary because the test in kern_wait doesnt * work because we mess with the options here */ if (args->options &~ (WUNTRACED|WNOHANG|WCONTINUED)) return (EINVAL); options = (args->options & (WNOHANG | WUNTRACED)); /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ if (args->options & __WCLONE) options |= WLINUXCLONE; error = kern_wait(td, args->pid, &tmpstat, options, NULL); if (error) return error; if (args->status) { tmpstat &= 0xffff; if (WIFSIGNALED(tmpstat)) tmpstat = (tmpstat & 0xffffff80) | BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); else if (WIFSTOPPED(tmpstat)) tmpstat = (tmpstat & 0xffff00ff) | (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); return copyout(&tmpstat, args->status, sizeof(int)); } return 0; } int linux_wait4(struct thread *td, struct linux_wait4_args *args) { int error, options, tmpstat; struct rusage ru, *rup; struct proc *p; #ifdef DEBUG if (ldebug(wait4)) printf(ARGS(wait4, "%d, %p, %d, %p"), args->pid, (void *)args->status, args->options, (void *)args->rusage); #endif options = (args->options & (WNOHANG | WUNTRACED)); /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ if (args->options & __WCLONE) options |= WLINUXCLONE; if (args->rusage != NULL) rup = &ru; else rup = NULL; error = kern_wait(td, args->pid, &tmpstat, options, rup); if (error) return error; p = td->td_proc; PROC_LOCK(p); sigqueue_delete(&p->p_sigqueue, SIGCHLD); PROC_UNLOCK(p); if (args->status) { tmpstat &= 0xffff; if (WIFSIGNALED(tmpstat)) tmpstat = (tmpstat & 0xffffff80) | BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); else if (WIFSTOPPED(tmpstat)) tmpstat = (tmpstat & 0xffff00ff) | (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); error = copyout(&tmpstat, args->status, sizeof(int)); } if (args->rusage != NULL && error == 0) error = copyout(&ru, args->rusage, sizeof(ru)); return (error); } int linux_mknod(struct thread *td, struct linux_mknod_args *args) { char *path; int error; LCONVPATHCREAT(td, args->path, &path); #ifdef DEBUG if (ldebug(mknod)) printf(ARGS(mknod, "%s, %d, %d"), path, args->mode, args->dev); #endif if (S_ISFIFO(args->mode)) error = kern_mkfifo(td, path, UIO_SYSSPACE, args->mode); else error = kern_mknod(td, path, UIO_SYSSPACE, args->mode, args->dev); LFREEPATH(path); return (error); } /* * UGH! This is just about the dumbest idea I've ever heard!! */ int linux_personality(struct thread *td, struct linux_personality_args *args) { #ifdef DEBUG if (ldebug(personality)) printf(ARGS(personality, "%lu"), (unsigned long)args->per); #endif if (args->per != 0) return EINVAL; /* Yes Jim, it's still a Linux... */ td->td_retval[0] = 0; return 0; } struct l_itimerval { l_timeval it_interval; l_timeval it_value; }; #define B2L_ITIMERVAL(bip, lip) \ (bip)->it_interval.tv_sec = (lip)->it_interval.tv_sec; \ (bip)->it_interval.tv_usec = (lip)->it_interval.tv_usec; \ (bip)->it_value.tv_sec = (lip)->it_value.tv_sec; \ (bip)->it_value.tv_usec = (lip)->it_value.tv_usec; int linux_setitimer(struct thread *td, struct linux_setitimer_args *uap) { int error; struct l_itimerval ls; struct itimerval aitv, oitv; #ifdef DEBUG if (ldebug(setitimer)) printf(ARGS(setitimer, "%p, %p"), (void *)uap->itv, (void *)uap->oitv); #endif if (uap->itv == NULL) { uap->itv = uap->oitv; return (linux_getitimer(td, (struct linux_getitimer_args *)uap)); } error = copyin(uap->itv, &ls, sizeof(ls)); if (error != 0) return (error); B2L_ITIMERVAL(&aitv, &ls); #ifdef DEBUG if (ldebug(setitimer)) { printf("setitimer: value: sec: %jd, usec: %ld\n", (intmax_t)aitv.it_value.tv_sec, aitv.it_value.tv_usec); printf("setitimer: interval: sec: %jd, usec: %ld\n", (intmax_t)aitv.it_interval.tv_sec, aitv.it_interval.tv_usec); } #endif error = kern_setitimer(td, uap->which, &aitv, &oitv); if (error != 0 || uap->oitv == NULL) return (error); B2L_ITIMERVAL(&ls, &oitv); return (copyout(&ls, uap->oitv, sizeof(ls))); } int linux_getitimer(struct thread *td, struct linux_getitimer_args *uap) { int error; struct l_itimerval ls; struct itimerval aitv; #ifdef DEBUG if (ldebug(getitimer)) printf(ARGS(getitimer, "%p"), (void *)uap->itv); #endif error = kern_getitimer(td, uap->which, &aitv); if (error != 0) return (error); B2L_ITIMERVAL(&ls, &aitv); return (copyout(&ls, uap->itv, sizeof(ls))); } int linux_nice(struct thread *td, struct linux_nice_args *args) { struct setpriority_args bsd_args; bsd_args.which = PRIO_PROCESS; bsd_args.who = 0; /* current process */ bsd_args.prio = args->inc; return setpriority(td, &bsd_args); } int linux_setgroups(struct thread *td, struct linux_setgroups_args *args) { struct ucred *newcred, *oldcred; l_gid_t linux_gidset[NGROUPS]; gid_t *bsd_gidset; int ngrp, error; struct proc *p; ngrp = args->gidsetsize; if (ngrp < 0 || ngrp >= NGROUPS) return (EINVAL); error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t)); if (error) return (error); newcred = crget(); p = td->td_proc; PROC_LOCK(p); oldcred = p->p_ucred; /* * cr_groups[0] holds egid. Setting the whole set from * the supplied set will cause egid to be changed too. * Keep cr_groups[0] unchanged to prevent that. */ if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, SUSER_ALLOWJAIL)) != 0) { PROC_UNLOCK(p); crfree(newcred); return (error); } crcopy(newcred, oldcred); if (ngrp > 0) { newcred->cr_ngroups = ngrp + 1; bsd_gidset = newcred->cr_groups; ngrp--; while (ngrp >= 0) { bsd_gidset[ngrp + 1] = linux_gidset[ngrp]; ngrp--; } } else newcred->cr_ngroups = 1; setsugid(p); p->p_ucred = newcred; PROC_UNLOCK(p); crfree(oldcred); return (0); } int linux_getgroups(struct thread *td, struct linux_getgroups_args *args) { struct ucred *cred; l_gid_t linux_gidset[NGROUPS]; gid_t *bsd_gidset; int bsd_gidsetsz, ngrp, error; cred = td->td_ucred; bsd_gidset = cred->cr_groups; bsd_gidsetsz = cred->cr_ngroups - 1; /* * cr_groups[0] holds egid. Returning the whole set * here will cause a duplicate. Exclude cr_groups[0] * to prevent that. */ if ((ngrp = args->gidsetsize) == 0) { td->td_retval[0] = bsd_gidsetsz; return (0); } if (ngrp < bsd_gidsetsz) return (EINVAL); ngrp = 0; while (ngrp < bsd_gidsetsz) { linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; ngrp++; } if ((error = copyout(linux_gidset, args->grouplist, ngrp * sizeof(l_gid_t)))) return (error); td->td_retval[0] = ngrp; return (0); } int linux_setrlimit(struct thread *td, struct linux_setrlimit_args *args) { struct rlimit bsd_rlim; struct l_rlimit rlim; u_int which; int error; #ifdef DEBUG if (ldebug(setrlimit)) printf(ARGS(setrlimit, "%d, %p"), args->resource, (void *)args->rlim); #endif if (args->resource >= LINUX_RLIM_NLIMITS) return (EINVAL); which = linux_to_bsd_resource[args->resource]; if (which == -1) return (EINVAL); error = copyin(args->rlim, &rlim, sizeof(rlim)); if (error) return (error); bsd_rlim.rlim_cur = (rlim_t)rlim.rlim_cur; bsd_rlim.rlim_max = (rlim_t)rlim.rlim_max; return (kern_setrlimit(td, which, &bsd_rlim)); } int linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args) { struct l_rlimit rlim; struct proc *p = td->td_proc; struct rlimit bsd_rlim; u_int which; #ifdef DEBUG if (ldebug(old_getrlimit)) printf(ARGS(old_getrlimit, "%d, %p"), args->resource, (void *)args->rlim); #endif if (args->resource >= LINUX_RLIM_NLIMITS) return (EINVAL); which = linux_to_bsd_resource[args->resource]; if (which == -1) return (EINVAL); PROC_LOCK(p); lim_rlimit(p, which, &bsd_rlim); PROC_UNLOCK(p); #ifdef COMPAT_LINUX32 rlim.rlim_cur = (unsigned int)bsd_rlim.rlim_cur; if (rlim.rlim_cur == UINT_MAX) rlim.rlim_cur = INT_MAX; rlim.rlim_max = (unsigned int)bsd_rlim.rlim_max; if (rlim.rlim_max == UINT_MAX) rlim.rlim_max = INT_MAX; #else rlim.rlim_cur = (unsigned long)bsd_rlim.rlim_cur; if (rlim.rlim_cur == ULONG_MAX) rlim.rlim_cur = LONG_MAX; rlim.rlim_max = (unsigned long)bsd_rlim.rlim_max; if (rlim.rlim_max == ULONG_MAX) rlim.rlim_max = LONG_MAX; #endif return (copyout(&rlim, args->rlim, sizeof(rlim))); } int linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args) { struct l_rlimit rlim; struct proc *p = td->td_proc; struct rlimit bsd_rlim; u_int which; #ifdef DEBUG if (ldebug(getrlimit)) printf(ARGS(getrlimit, "%d, %p"), args->resource, (void *)args->rlim); #endif if (args->resource >= LINUX_RLIM_NLIMITS) return (EINVAL); which = linux_to_bsd_resource[args->resource]; if (which == -1) return (EINVAL); PROC_LOCK(p); lim_rlimit(p, which, &bsd_rlim); PROC_UNLOCK(p); rlim.rlim_cur = (l_ulong)bsd_rlim.rlim_cur; rlim.rlim_max = (l_ulong)bsd_rlim.rlim_max; return (copyout(&rlim, args->rlim, sizeof(rlim))); } int linux_sched_setscheduler(struct thread *td, struct linux_sched_setscheduler_args *args) { struct sched_setscheduler_args bsd; #ifdef DEBUG if (ldebug(sched_setscheduler)) printf(ARGS(sched_setscheduler, "%d, %d, %p"), args->pid, args->policy, (const void *)args->param); #endif switch (args->policy) { case LINUX_SCHED_OTHER: bsd.policy = SCHED_OTHER; break; case LINUX_SCHED_FIFO: bsd.policy = SCHED_FIFO; break; case LINUX_SCHED_RR: bsd.policy = SCHED_RR; break; default: return EINVAL; } bsd.pid = args->pid; bsd.param = (struct sched_param *)args->param; return sched_setscheduler(td, &bsd); } int linux_sched_getscheduler(struct thread *td, struct linux_sched_getscheduler_args *args) { struct sched_getscheduler_args bsd; int error; #ifdef DEBUG if (ldebug(sched_getscheduler)) printf(ARGS(sched_getscheduler, "%d"), args->pid); #endif bsd.pid = args->pid; error = sched_getscheduler(td, &bsd); switch (td->td_retval[0]) { case SCHED_OTHER: td->td_retval[0] = LINUX_SCHED_OTHER; break; case SCHED_FIFO: td->td_retval[0] = LINUX_SCHED_FIFO; break; case SCHED_RR: td->td_retval[0] = LINUX_SCHED_RR; break; } return error; } int linux_sched_get_priority_max(struct thread *td, struct linux_sched_get_priority_max_args *args) { struct sched_get_priority_max_args bsd; #ifdef DEBUG if (ldebug(sched_get_priority_max)) printf(ARGS(sched_get_priority_max, "%d"), args->policy); #endif switch (args->policy) { case LINUX_SCHED_OTHER: bsd.policy = SCHED_OTHER; break; case LINUX_SCHED_FIFO: bsd.policy = SCHED_FIFO; break; case LINUX_SCHED_RR: bsd.policy = SCHED_RR; break; default: return EINVAL; } return sched_get_priority_max(td, &bsd); } int linux_sched_get_priority_min(struct thread *td, struct linux_sched_get_priority_min_args *args) { struct sched_get_priority_min_args bsd; #ifdef DEBUG if (ldebug(sched_get_priority_min)) printf(ARGS(sched_get_priority_min, "%d"), args->policy); #endif switch (args->policy) { case LINUX_SCHED_OTHER: bsd.policy = SCHED_OTHER; break; case LINUX_SCHED_FIFO: bsd.policy = SCHED_FIFO; break; case LINUX_SCHED_RR: bsd.policy = SCHED_RR; break; default: return EINVAL; } return sched_get_priority_min(td, &bsd); } #define REBOOT_CAD_ON 0x89abcdef #define REBOOT_CAD_OFF 0 #define REBOOT_HALT 0xcdef0123 #define REBOOT_RESTART 0x01234567 #define REBOOT_RESTART2 0xA1B2C3D4 #define REBOOT_POWEROFF 0x4321FEDC #define REBOOT_MAGIC1 0xfee1dead #define REBOOT_MAGIC2 0x28121969 #define REBOOT_MAGIC2A 0x05121996 #define REBOOT_MAGIC2B 0x16041998 int linux_reboot(struct thread *td, struct linux_reboot_args *args) { struct reboot_args bsd_args; #ifdef DEBUG if (ldebug(reboot)) printf(ARGS(reboot, "0x%x"), args->cmd); #endif if (args->magic1 != REBOOT_MAGIC1) return EINVAL; switch (args->magic2) { case REBOOT_MAGIC2: case REBOOT_MAGIC2A: case REBOOT_MAGIC2B: break; default: return EINVAL; } switch (args->cmd) { case REBOOT_CAD_ON: case REBOOT_CAD_OFF: return (priv_check(td, PRIV_REBOOT)); case REBOOT_HALT: bsd_args.opt = RB_HALT; break; case REBOOT_RESTART: case REBOOT_RESTART2: bsd_args.opt = 0; break; case REBOOT_POWEROFF: bsd_args.opt = RB_POWEROFF; break; default: return EINVAL; } return reboot(td, &bsd_args); } /* * The FreeBSD native getpid(2), getgid(2) and getuid(2) also modify * td->td_retval[1] when COMPAT_43 is defined. This * globbers registers that are assumed to be preserved. The following * lightweight syscalls fixes this. See also linux_getgid16() and * linux_getuid16() in linux_uid16.c. * * linux_getpid() - MP SAFE * linux_getgid() - MP SAFE * linux_getuid() - MP SAFE */ int linux_getpid(struct thread *td, struct linux_getpid_args *args) { struct linux_emuldata *em; char osrel[LINUX_MAX_UTSNAME]; linux_get_osrelease(td, osrel); if (strlen(osrel) >= 3 && osrel[2] == '6') { em = em_find(td->td_proc, EMUL_UNLOCKED); KASSERT(em != NULL, ("getpid: emuldata not found.\n")); td->td_retval[0] = em->shared->group_pid; EMUL_UNLOCK(&emul_lock); } else { PROC_LOCK(td->td_proc); td->td_retval[0] = td->td_proc->p_pid; PROC_UNLOCK(td->td_proc); } return (0); } int linux_gettid(struct thread *td, struct linux_gettid_args *args) { #ifdef DEBUG if (ldebug(gettid)) printf(ARGS(gettid, "")); #endif td->td_retval[0] = td->td_proc->p_pid; return (0); } int linux_getppid(struct thread *td, struct linux_getppid_args *args) { struct linux_emuldata *em; struct proc *p, *pp; char osrel[LINUX_MAX_UTSNAME]; linux_get_osrelease(td, osrel); if (strlen(osrel) >= 3 && osrel[2] != '6') { PROC_LOCK(td->td_proc); td->td_retval[0] = td->td_proc->p_pptr->p_pid; PROC_UNLOCK(td->td_proc); return (0); } em = em_find(td->td_proc, EMUL_UNLOCKED); KASSERT(em != NULL, ("getppid: process emuldata not found.\n")); /* find the group leader */ p = pfind(em->shared->group_pid); if (p == NULL) { #ifdef DEBUG printf(LMSG("parent process not found.\n")); #endif return (0); } pp = p->p_pptr; /* switch to parent */ PROC_LOCK(pp); PROC_UNLOCK(p); /* if its also linux process */ if (pp->p_sysent == &elf_linux_sysvec) { em = em_find(pp, EMUL_LOCKED); KASSERT(em != NULL, ("getppid: parent emuldata not found.\n")); td->td_retval[0] = em->shared->group_pid; } else td->td_retval[0] = pp->p_pid; EMUL_UNLOCK(&emul_lock); PROC_UNLOCK(pp); return (0); } int linux_getgid(struct thread *td, struct linux_getgid_args *args) { td->td_retval[0] = td->td_ucred->cr_rgid; return (0); } int linux_getuid(struct thread *td, struct linux_getuid_args *args) { td->td_retval[0] = td->td_ucred->cr_ruid; return (0); } int linux_getsid(struct thread *td, struct linux_getsid_args *args) { struct getsid_args bsd; bsd.pid = args->pid; return getsid(td, &bsd); } int linux_nosys(struct thread *td, struct nosys_args *ignore) { return (ENOSYS); } int linux_getpriority(struct thread *td, struct linux_getpriority_args *args) { struct getpriority_args bsd_args; int error; bsd_args.which = args->which; bsd_args.who = args->who; error = getpriority(td, &bsd_args); td->td_retval[0] = 20 - td->td_retval[0]; return error; } int linux_sethostname(struct thread *td, struct linux_sethostname_args *args) { int name[2]; name[0] = CTL_KERN; name[1] = KERN_HOSTNAME; return (userland_sysctl(td, name, 2, 0, 0, 0, args->hostname, args->len, 0, 0)); } int linux_exit_group(struct thread *td, struct linux_exit_group_args *args) { struct linux_emuldata *em, *td_em, *tmp_em; struct proc *sp; char osrel[LINUX_MAX_UTSNAME]; #ifdef DEBUG if (ldebug(exit_group)) printf(ARGS(exit_group, "%i"), args->error_code); #endif linux_get_osrelease(td, osrel); if (strlen(osrel) >= 3 && osrel[2] == '6') { td_em = em_find(td->td_proc, EMUL_UNLOCKED); KASSERT(td_em != NULL, ("exit_group: emuldata not found.\n")); EMUL_SHARED_RLOCK(&emul_shared_lock); LIST_FOREACH_SAFE(em, &td_em->shared->threads, threads, tmp_em) { if (em->pid == td_em->pid) continue; sp = pfind(em->pid); psignal(sp, SIGKILL); PROC_UNLOCK(sp); #ifdef DEBUG printf(LMSG("linux_sys_exit_group: kill PID %d\n"), em->pid); #endif } EMUL_SHARED_RUNLOCK(&emul_shared_lock); EMUL_UNLOCK(&emul_lock); } exit1(td, W_EXITCODE(args->error_code,0)); return (0); } int linux_prctl(struct thread *td, struct linux_prctl_args *args) { int error = 0; struct proc *p = td->td_proc; char comm[LINUX_MAX_COMM_LEN]; struct linux_emuldata *em; #ifdef DEBUG if (ldebug(prctl)) printf(ARGS(prctl, "%d, %d, %d, %d, %d"), args->option, args->arg2, args->arg3, args->arg4, args->arg5); #endif switch (args->option) { case LINUX_PR_SET_PDEATHSIG: if (!LINUX_SIG_VALID(args->arg2)) return (EINVAL); em = em_find(p, EMUL_UNLOCKED); KASSERT(em != NULL, ("prctl: emuldata not found.\n")); em->pdeath_signal = args->arg2; EMUL_UNLOCK(&emul_lock); break; case LINUX_PR_GET_PDEATHSIG: em = em_find(p, EMUL_UNLOCKED); KASSERT(em != NULL, ("prctl: emuldata not found.\n")); error = copyout(&em->pdeath_signal, (void *)(register_t) args->arg2, sizeof(em->pdeath_signal)); EMUL_UNLOCK(&emul_lock); break; case LINUX_PR_SET_NAME: comm[LINUX_MAX_COMM_LEN-1] = 0; error = copyin(comm, (void *)(register_t) args->arg2, LINUX_MAX_COMM_LEN-1); if (error) return (error); PROC_LOCK(p); strcpy(p->p_comm, comm); PROC_UNLOCK(p); break; case LINUX_PR_GET_NAME: error = copyout(&p->p_comm, (void *)(register_t) args->arg2, MAXCOMLEN+1); break; default: error = EINVAL; break; } return (error); } Index: head/sys/conf/files =================================================================== --- head/sys/conf/files (revision 164183) +++ head/sys/conf/files (revision 164184) @@ -1,2138 +1,2138 @@ # $FreeBSD$ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and # dependency lines other than the first are silently ignored. # acpi_quirks.h optional acpi \ dependency "$S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \ compile-with "${AWK} -f $S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \ no-obj no-implicit-rule before-depend \ clean "acpi_quirks.h" aicasm optional ahc | ahd \ dependency "$S/dev/aic7xxx/aicasm/*.[chyl]" \ compile-with "CC='${CC}' ${MAKE} -f $S/dev/aic7xxx/aicasm/Makefile MAKESRCPATH=$S/dev/aic7xxx/aicasm" \ no-obj no-implicit-rule \ clean "aicasm* y.tab.h" aic7xxx_seq.h optional ahc \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic7xxx_seq.h -r aic7xxx_reg.h -p aic7xxx_reg_print.c -i $S/dev/aic7xxx/aic7xxx_osm.h $S/dev/aic7xxx/aic7xxx.seq" \ no-obj no-implicit-rule before-depend local \ clean "aic7xxx_seq.h" \ dependency "$S/dev/aic7xxx/aic7xxx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic7xxx_reg.h optional ahc \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic7xxx_seq.h -r aic7xxx_reg.h -p aic7xxx_reg_print.c -i $S/dev/aic7xxx/aic7xxx_osm.h $S/dev/aic7xxx/aic7xxx.seq" \ no-obj no-implicit-rule before-depend local \ clean "aic7xxx_reg.h" \ dependency "$S/dev/aic7xxx/aic7xxx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic7xxx_reg_print.c optional ahc \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic7xxx_seq.h -r aic7xxx_reg.h -p aic7xxx_reg_print.c -i $S/dev/aic7xxx/aic7xxx_osm.h $S/dev/aic7xxx/aic7xxx.seq" \ no-obj no-implicit-rule local \ clean "aic7xxx_reg_print.c" \ dependency "$S/dev/aic7xxx/aic7xxx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic7xxx_reg_print.o optional ahc ahc_reg_pretty_print \ compile-with "${NORMAL_C}" \ no-implicit-rule local aic79xx_seq.h optional ahd pci \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic79xx_seq.h -r aic79xx_reg.h -p aic79xx_reg_print.c -i $S/dev/aic7xxx/aic79xx_osm.h $S/dev/aic7xxx/aic79xx.seq" \ no-obj no-implicit-rule before-depend local \ clean "aic79xx_seq.h" \ dependency "$S/dev/aic7xxx/aic79xx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic79xx_reg.h optional ahd pci \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic79xx_seq.h -r aic79xx_reg.h -p aic79xx_reg_print.c -i $S/dev/aic7xxx/aic79xx_osm.h $S/dev/aic7xxx/aic79xx.seq" \ no-obj no-implicit-rule before-depend local \ clean "aic79xx_reg.h" \ dependency "$S/dev/aic7xxx/aic79xx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic79xx_reg_print.c optional ahd pci \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic79xx_seq.h -r aic79xx_reg.h -p aic79xx_reg_print.c -i $S/dev/aic7xxx/aic79xx_osm.h $S/dev/aic7xxx/aic79xx.seq" \ no-obj no-implicit-rule local \ clean "aic79xx_reg_print.c" \ dependency "$S/dev/aic7xxx/aic79xx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic79xx_reg_print.o optional ahd pci ahd_reg_pretty_print \ compile-with "${NORMAL_C}" \ no-implicit-rule local emu10k1-alsa%diked.h optional snd_emu10k1 | snd_emu10kx \ dependency "$S/tools/emu10k1-mkalsa.sh $S/gnu/dev/sound/pci/emu10k1-alsa.h" \ compile-with "CC='${CC}' AWK=${AWK} sh $S/tools/emu10k1-mkalsa.sh $S/gnu/dev/sound/pci/emu10k1-alsa.h emu10k1-alsa%diked.h" \ no-obj no-implicit-rule before-depend \ clean "emu10k1-alsa%diked.h" p16v-alsa%diked.h optional snd_emu10kx pci \ dependency "$S/tools/emu10k1-mkalsa.sh $S/gnu/dev/sound/pci/p16v-alsa.h" \ compile-with "CC='${CC}' AWK=${AWK} sh $S/tools/emu10k1-mkalsa.sh $S/gnu/dev/sound/pci/p16v-alsa.h p16v-alsa%diked.h" \ no-obj no-implicit-rule before-depend \ clean "p16v-alsa%diked.h" p17v-alsa%diked.h optional snd_emu10kx pci \ dependency "$S/tools/emu10k1-mkalsa.sh $S/gnu/dev/sound/pci/p17v-alsa.h" \ compile-with "CC='${CC}' AWK=${AWK} sh $S/tools/emu10k1-mkalsa.sh $S/gnu/dev/sound/pci/p17v-alsa.h p17v-alsa%diked.h" \ no-obj no-implicit-rule before-depend \ clean "p17v-alsa%diked.h" miidevs.h optional miibus | mii \ dependency "$S/tools/miidevs2h.awk $S/dev/mii/miidevs" \ compile-with "${AWK} -f $S/tools/miidevs2h.awk $S/dev/mii/miidevs" \ no-obj no-implicit-rule before-depend \ clean "miidevs.h" pccarddevs.h standard \ dependency "$S/tools/pccarddevs2h.awk $S/dev/pccard/pccarddevs" \ compile-with "${AWK} -f $S/tools/pccarddevs2h.awk $S/dev/pccard/pccarddevs" \ no-obj no-implicit-rule before-depend \ clean "pccarddevs.h" usbdevs.h optional usb \ dependency "$S/tools/usbdevs2h.awk $S/dev/usb/usbdevs" \ compile-with "${AWK} -f $S/tools/usbdevs2h.awk $S/dev/usb/usbdevs -h" \ no-obj no-implicit-rule before-depend \ clean "usbdevs.h" usbdevs_data.h optional usb \ dependency "$S/tools/usbdevs2h.awk $S/dev/usb/usbdevs" \ compile-with "${AWK} -f $S/tools/usbdevs2h.awk $S/dev/usb/usbdevs -d" \ no-obj no-implicit-rule before-depend \ clean "usbdevs_data.h" cam/cam.c optional scbus cam/cam_periph.c optional scbus cam/cam_queue.c optional scbus cam/cam_sim.c optional scbus cam/cam_xpt.c optional scbus cam/scsi/scsi_all.c optional scbus cam/scsi/scsi_cd.c optional cd cam/scsi/scsi_ch.c optional ch cam/scsi/scsi_da.c optional da cam/scsi/scsi_low.c optional ct | ncv | nsp | stg cam/scsi/scsi_low_pisa.c optional ct | ncv | nsp | stg cam/scsi/scsi_pass.c optional pass cam/scsi/scsi_pt.c optional pt cam/scsi/scsi_sa.c optional sa cam/scsi/scsi_ses.c optional ses cam/scsi/scsi_targ_bh.c optional targbh cam/scsi/scsi_target.c optional targ coda/coda_fbsd.c optional vcoda coda/coda_namecache.c optional vcoda coda/coda_psdev.c optional vcoda coda/coda_subr.c optional vcoda coda/coda_venus.c optional vcoda coda/coda_vfsops.c optional vcoda coda/coda_vnops.c optional vcoda contrib/altq/altq/altq_cbq.c optional altq \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/altq/altq/altq_cdnr.c optional altq contrib/altq/altq/altq_hfsc.c optional altq \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/altq/altq/altq_priq.c optional altq \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/altq/altq/altq_red.c optional altq \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/altq/altq/altq_rio.c optional altq \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/altq/altq/altq_rmclass.c optional altq contrib/altq/altq/altq_subr.c optional altq \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/dev/acpica/dbcmds.c optional acpi acpi_debug contrib/dev/acpica/dbdisply.c optional acpi acpi_debug contrib/dev/acpica/dbexec.c optional acpi acpi_debug contrib/dev/acpica/dbfileio.c optional acpi acpi_debug contrib/dev/acpica/dbhistry.c optional acpi acpi_debug contrib/dev/acpica/dbinput.c optional acpi acpi_debug contrib/dev/acpica/dbstats.c optional acpi acpi_debug contrib/dev/acpica/dbutils.c optional acpi acpi_debug contrib/dev/acpica/dbxface.c optional acpi acpi_debug contrib/dev/acpica/dmbuffer.c optional acpi acpi_debug contrib/dev/acpica/dmnames.c optional acpi acpi_debug contrib/dev/acpica/dmopcode.c optional acpi acpi_debug contrib/dev/acpica/dmobject.c optional acpi acpi_debug contrib/dev/acpica/dmresrc.c optional acpi acpi_debug contrib/dev/acpica/dmresrcl.c optional acpi acpi_debug contrib/dev/acpica/dmresrcs.c optional acpi acpi_debug contrib/dev/acpica/dmutils.c optional acpi acpi_debug contrib/dev/acpica/dmwalk.c optional acpi acpi_debug contrib/dev/acpica/dsfield.c optional acpi contrib/dev/acpica/dsinit.c optional acpi contrib/dev/acpica/dsmethod.c optional acpi contrib/dev/acpica/dsmthdat.c optional acpi contrib/dev/acpica/dsobject.c optional acpi contrib/dev/acpica/dsopcode.c optional acpi contrib/dev/acpica/dsutils.c optional acpi contrib/dev/acpica/dswexec.c optional acpi contrib/dev/acpica/dswload.c optional acpi contrib/dev/acpica/dswscope.c optional acpi contrib/dev/acpica/dswstate.c optional acpi contrib/dev/acpica/evevent.c optional acpi contrib/dev/acpica/evgpe.c optional acpi contrib/dev/acpica/evgpeblk.c optional acpi contrib/dev/acpica/evmisc.c optional acpi contrib/dev/acpica/evregion.c optional acpi contrib/dev/acpica/evrgnini.c optional acpi contrib/dev/acpica/evsci.c optional acpi contrib/dev/acpica/evxface.c optional acpi contrib/dev/acpica/evxfevnt.c optional acpi contrib/dev/acpica/evxfregn.c optional acpi contrib/dev/acpica/exconfig.c optional acpi contrib/dev/acpica/exconvrt.c optional acpi contrib/dev/acpica/excreate.c optional acpi contrib/dev/acpica/exdump.c optional acpi contrib/dev/acpica/exfield.c optional acpi contrib/dev/acpica/exfldio.c optional acpi contrib/dev/acpica/exmisc.c optional acpi contrib/dev/acpica/exmutex.c optional acpi contrib/dev/acpica/exnames.c optional acpi contrib/dev/acpica/exoparg1.c optional acpi contrib/dev/acpica/exoparg2.c optional acpi contrib/dev/acpica/exoparg3.c optional acpi contrib/dev/acpica/exoparg6.c optional acpi contrib/dev/acpica/exprep.c optional acpi contrib/dev/acpica/exregion.c optional acpi contrib/dev/acpica/exresnte.c optional acpi contrib/dev/acpica/exresolv.c optional acpi contrib/dev/acpica/exresop.c optional acpi contrib/dev/acpica/exstore.c optional acpi contrib/dev/acpica/exstoren.c optional acpi contrib/dev/acpica/exstorob.c optional acpi contrib/dev/acpica/exsystem.c optional acpi contrib/dev/acpica/exutils.c optional acpi contrib/dev/acpica/hwacpi.c optional acpi contrib/dev/acpica/hwgpe.c optional acpi contrib/dev/acpica/hwregs.c optional acpi contrib/dev/acpica/hwsleep.c optional acpi contrib/dev/acpica/hwtimer.c optional acpi contrib/dev/acpica/nsaccess.c optional acpi contrib/dev/acpica/nsalloc.c optional acpi contrib/dev/acpica/nsdump.c optional acpi contrib/dev/acpica/nseval.c optional acpi contrib/dev/acpica/nsinit.c optional acpi contrib/dev/acpica/nsload.c optional acpi contrib/dev/acpica/nsnames.c optional acpi contrib/dev/acpica/nsobject.c optional acpi contrib/dev/acpica/nsparse.c optional acpi contrib/dev/acpica/nssearch.c optional acpi contrib/dev/acpica/nsutils.c optional acpi contrib/dev/acpica/nswalk.c optional acpi contrib/dev/acpica/nsxfeval.c optional acpi contrib/dev/acpica/nsxfname.c optional acpi contrib/dev/acpica/nsxfobj.c optional acpi contrib/dev/acpica/psargs.c optional acpi contrib/dev/acpica/psloop.c optional acpi contrib/dev/acpica/psopcode.c optional acpi contrib/dev/acpica/psparse.c optional acpi contrib/dev/acpica/psscope.c optional acpi contrib/dev/acpica/pstree.c optional acpi contrib/dev/acpica/psutils.c optional acpi contrib/dev/acpica/pswalk.c optional acpi contrib/dev/acpica/psxface.c optional acpi contrib/dev/acpica/rsaddr.c optional acpi contrib/dev/acpica/rscalc.c optional acpi contrib/dev/acpica/rscreate.c optional acpi contrib/dev/acpica/rsdump.c optional acpi contrib/dev/acpica/rsinfo.c optional acpi contrib/dev/acpica/rsio.c optional acpi contrib/dev/acpica/rsirq.c optional acpi contrib/dev/acpica/rslist.c optional acpi contrib/dev/acpica/rsmemory.c optional acpi contrib/dev/acpica/rsmisc.c optional acpi contrib/dev/acpica/rsutils.c optional acpi contrib/dev/acpica/rsxface.c optional acpi contrib/dev/acpica/tbconvrt.c optional acpi contrib/dev/acpica/tbget.c optional acpi contrib/dev/acpica/tbgetall.c optional acpi contrib/dev/acpica/tbinstal.c optional acpi contrib/dev/acpica/tbrsdt.c optional acpi contrib/dev/acpica/tbutils.c optional acpi contrib/dev/acpica/tbxface.c optional acpi contrib/dev/acpica/tbxfroot.c optional acpi contrib/dev/acpica/utalloc.c optional acpi contrib/dev/acpica/utcache.c optional acpi \ compile-with "${NORMAL_C} -DACPI_USE_LOCAL_CACHE" contrib/dev/acpica/utclib.c optional acpi contrib/dev/acpica/utcopy.c optional acpi contrib/dev/acpica/utdebug.c optional acpi contrib/dev/acpica/utdelete.c optional acpi contrib/dev/acpica/uteval.c optional acpi contrib/dev/acpica/utglobal.c optional acpi contrib/dev/acpica/utinit.c optional acpi contrib/dev/acpica/utmath.c optional acpi contrib/dev/acpica/utmisc.c optional acpi contrib/dev/acpica/utmutex.c optional acpi contrib/dev/acpica/utobject.c optional acpi contrib/dev/acpica/utstate.c optional acpi contrib/dev/acpica/utxface.c optional acpi contrib/ipfilter/netinet/fil.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_auth.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_fil_freebsd.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_frag.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_log.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_nat.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_proxy.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_state.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_lookup.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_pool.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_htable.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_sync.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/mlfk_ipl.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ngatm/netnatm/api/cc_conn.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_data.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_dump.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_port.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_sig.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_user.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/unisap.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/misc/straddr.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/misc/unimsg_common.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/msg/traffic.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/msg/uni_ie.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/msg/uni_msg.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/saal/saal_sscfu.c optional ngatm_sscfu \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/saal/saal_sscop.c optional ngatm_sscop \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_call.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_coord.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_party.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_print.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_reset.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_uni.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_unimsgcpy.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_verify.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/pf/net/if_pflog.c optional pflog \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/if_pfsync.c optional pfsync \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/pf.c optional pf \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/pf_if.c optional pf \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/pf_subr.c optional pf \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/pf_ioctl.c optional pf \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/pf_norm.c optional pf \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/pf_table.c optional pf \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/net/pf_osfp.c optional pf \ compile-with "${NORMAL_C} -I$S/contrib/pf" contrib/pf/netinet/in4_cksum.c optional pf inet crypto/blowfish/bf_ecb.c optional ipsec ipsec_esp crypto/blowfish/bf_skey.c optional crypto | ipsec ipsec_esp crypto/des/des_ecb.c optional crypto | ipsec ipsec_esp | netsmb crypto/des/des_setkey.c optional crypto | ipsec ipsec_esp | netsmb crypto/rc4/rc4.c optional netgraph_mppc_encryption crypto/rijndael/rijndael-alg-fst.c optional crypto | geom_bde | \ ipsec | random | wlan_ccmp crypto/rijndael/rijndael-api-fst.c optional geom_bde | random crypto/rijndael/rijndael-api.c optional crypto | ipsec | wlan_ccmp crypto/sha1.c optional carp | crypto | ipsec | \ netgraph_mppc_encryption | sctp crypto/sha2/sha2.c optional crypto | geom_bde | ipsec | random | \ sctp ddb/db_access.c optional ddb ddb/db_break.c optional ddb ddb/db_command.c optional ddb ddb/db_examine.c optional ddb ddb/db_expr.c optional ddb ddb/db_input.c optional ddb ddb/db_lex.c optional ddb ddb/db_main.c optional ddb ddb/db_output.c optional ddb ddb/db_print.c optional ddb ddb/db_ps.c optional ddb ddb/db_run.c optional ddb ddb/db_sym.c optional ddb ddb/db_thread.c optional ddb ddb/db_variables.c optional ddb ddb/db_watch.c optional ddb ddb/db_write_cmd.c optional ddb #dev/dpt/dpt_control.c optional dpt dev/aac/aac.c optional aac dev/aac/aac_cam.c optional aacp aac dev/aac/aac_debug.c optional aac dev/aac/aac_disk.c optional aac dev/aac/aac_linux.c optional aac compat_linux dev/aac/aac_pci.c optional aac pci dev/acpi_support/acpi_aiboost.c optional acpi_aiboost acpi dev/acpi_support/acpi_asus.c optional acpi_asus acpi dev/acpi_support/acpi_fujitsu.c optional acpi_fujitsu acpi dev/acpi_support/acpi_ibm.c optional acpi_ibm acpi dev/acpi_support/acpi_panasonic.c optional acpi_panasonic acpi dev/acpi_support/acpi_sony.c optional acpi_sony acpi dev/acpi_support/acpi_toshiba.c optional acpi_toshiba acpi dev/acpica/Osd/OsdDebug.c optional acpi dev/acpica/Osd/OsdHardware.c optional acpi dev/acpica/Osd/OsdInterrupt.c optional acpi dev/acpica/Osd/OsdMemory.c optional acpi dev/acpica/Osd/OsdSchedule.c optional acpi dev/acpica/Osd/OsdStream.c optional acpi dev/acpica/Osd/OsdSynch.c optional acpi dev/acpica/Osd/OsdTable.c optional acpi dev/acpica/acpi.c optional acpi dev/acpica/acpi_acad.c optional acpi dev/acpica/acpi_battery.c optional acpi dev/acpica/acpi_button.c optional acpi dev/acpica/acpi_cmbat.c optional acpi dev/acpica/acpi_cpu.c optional acpi dev/acpica/acpi_ec.c optional acpi dev/acpica/acpi_hpet.c optional acpi dev/acpica/acpi_isab.c optional acpi isa dev/acpica/acpi_lid.c optional acpi dev/acpica/acpi_package.c optional acpi dev/acpica/acpi_pci.c optional acpi pci dev/acpica/acpi_pci_link.c optional acpi pci dev/acpica/acpi_pcib.c optional acpi pci dev/acpica/acpi_pcib_acpi.c optional acpi pci dev/acpica/acpi_pcib_pci.c optional acpi pci dev/acpica/acpi_perf.c optional acpi dev/acpica/acpi_powerres.c optional acpi dev/acpica/acpi_quirk.c optional acpi dev/acpica/acpi_resource.c optional acpi dev/acpica/acpi_smbat.c optional acpi dev/acpica/acpi_thermal.c optional acpi dev/acpica/acpi_throttle.c optional acpi dev/acpica/acpi_timer.c optional acpi dev/acpica/acpi_video.c optional acpi_video acpi dev/acpica/acpi_dock.c optional acpi_dock acpi dev/adlink/adlink.c optional adlink dev/advansys/adv_eisa.c optional adv eisa dev/advansys/adv_pci.c optional adv pci dev/advansys/advansys.c optional adv dev/advansys/advlib.c optional adv dev/advansys/advmcode.c optional adv dev/advansys/adw_pci.c optional adw pci dev/advansys/adwcam.c optional adw dev/advansys/adwlib.c optional adw dev/advansys/adwmcode.c optional adw dev/aha/aha.c optional aha dev/aha/aha_isa.c optional aha isa dev/aha/aha_mca.c optional aha mca dev/ahb/ahb.c optional ahb eisa dev/aic/aic.c optional aic dev/aic/aic_pccard.c optional aic pccard dev/aic7xxx/ahc_eisa.c optional ahc eisa dev/aic7xxx/ahc_isa.c optional ahc isa dev/aic7xxx/ahc_pci.c optional ahc pci dev/aic7xxx/ahd_pci.c optional ahd pci dev/aic7xxx/aic7770.c optional ahc dev/aic7xxx/aic79xx.c optional ahd pci dev/aic7xxx/aic79xx_osm.c optional ahd pci dev/aic7xxx/aic79xx_pci.c optional ahd pci dev/aic7xxx/aic7xxx.c optional ahc dev/aic7xxx/aic7xxx_93cx6.c optional ahc dev/aic7xxx/aic7xxx_osm.c optional ahc dev/aic7xxx/aic7xxx_pci.c optional ahc pci dev/amd/amd.c optional amd dev/amr/amr.c optional amr dev/amr/amr_cam.c optional amr dev/amr/amr_disk.c optional amr dev/amr/amr_linux.c optional amr compat_linux dev/amr/amr_pci.c optional amr pci dev/an/if_an.c optional an dev/an/if_an_isa.c optional an isa dev/an/if_an_pccard.c optional an pccard dev/an/if_an_pci.c optional an pci dev/asr/asr.c optional asr pci dev/ata/ata_if.m optional ata dev/ata/ata-all.c optional ata dev/ata/ata-card.c optional ata pccard dev/ata/ata-cbus.c optional ata pc98 dev/ata/ata-chipset.c optional ata pci dev/ata/ata-disk.c optional atadisk dev/ata/ata-dma.c optional ata pci dev/ata/ata-isa.c optional ata isa dev/ata/ata-lowlevel.c optional ata dev/ata/ata-pci.c optional ata pci dev/ata/ata-queue.c optional ata dev/ata/ata-raid.c optional ataraid dev/ata/ata-usb.c optional atausb dev/ata/atapi-cam.c optional atapicam dev/ata/atapi-cd.c optional atapicd dev/ata/atapi-fd.c optional atapifd dev/ata/atapi-tape.c optional atapist dev/ath/ah_osdep.c optional ath_hal \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/ath_rate/amrr/amrr.c optional ath_rate_amrr dev/ath/ath_rate/onoe/onoe.c optional ath_rate_onoe \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/ath_rate/sample/sample.c optional ath_rate_sample \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_pci.c optional ath pci \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/awi/am79c930.c optional awi dev/awi/awi.c optional awi dev/awi/if_awi_pccard.c optional awi pccard dev/bce/if_bce.c optional bce dev/bfe/if_bfe.c optional bfe dev/bge/if_bge.c optional bge dev/bktr/bktr_audio.c optional bktr pci dev/bktr/bktr_card.c optional bktr pci dev/bktr/bktr_core.c optional bktr pci dev/bktr/bktr_i2c.c optional bktr pci smbus dev/bktr/bktr_os.c optional bktr pci dev/bktr/bktr_tuner.c optional bktr pci dev/bktr/msp34xx.c optional bktr pci dev/buslogic/bt.c optional bt dev/buslogic/bt_eisa.c optional bt eisa dev/buslogic/bt_isa.c optional bt isa dev/buslogic/bt_mca.c optional bt mca dev/buslogic/bt_pci.c optional bt pci dev/cardbus/cardbus.c optional cardbus dev/cardbus/cardbus_cis.c optional cardbus dev/cardbus/cardbus_device.c optional cardbus dev/ciss/ciss.c optional ciss dev/cm/smc90cx6.c optional cm dev/cnw/if_cnw.c optional cnw pccard dev/cpufreq/ichss.c optional cpufreq dev/cs/if_cs.c optional cs dev/cs/if_cs_isa.c optional cs isa dev/cs/if_cs_pccard.c optional cs pccard dev/cy/cy.c optional cy dev/cy/cy_isa.c optional cy isa dev/cy/cy_pci.c optional cy pci dev/dc/if_dc.c optional dc pci dev/dc/dcphy.c optional dc pci dev/dc/pnphy.c optional dc pci dev/dcons/dcons.c optional dcons dev/dcons/dcons_crom.c optional dcons_crom dev/dcons/dcons_os.c optional dcons dev/de/if_de.c optional de pci dev/digi/CX.c optional digi_CX dev/digi/CX_PCI.c optional digi_CX_PCI dev/digi/EPCX.c optional digi_EPCX dev/digi/EPCX_PCI.c optional digi_EPCX_PCI dev/digi/Xe.c optional digi_Xe dev/digi/Xem.c optional digi_Xem dev/digi/Xr.c optional digi_Xr dev/digi/digi.c optional digi dev/digi/digi_isa.c optional digi isa dev/digi/digi_pci.c optional digi pci dev/dpt/dpt_eisa.c optional dpt eisa dev/dpt/dpt_pci.c optional dpt pci dev/dpt/dpt_scsi.c optional dpt dev/drm/ati_pcigart.c optional drm dev/drm/drm_agpsupport.c optional drm dev/drm/drm_auth.c optional drm dev/drm/drm_bufs.c optional drm dev/drm/drm_context.c optional drm dev/drm/drm_dma.c optional drm dev/drm/drm_drawable.c optional drm dev/drm/drm_drv.c optional drm dev/drm/drm_fops.c optional drm dev/drm/drm_ioctl.c optional drm dev/drm/drm_irq.c optional drm dev/drm/drm_lock.c optional drm dev/drm/drm_memory.c optional drm dev/drm/drm_pci.c optional drm dev/drm/drm_scatter.c optional drm dev/drm/drm_sysctl.c optional drm dev/drm/drm_vm.c optional drm dev/drm/i915_dma.c optional i915drm dev/drm/i915_drv.c optional i915drm dev/drm/i915_irq.c optional i915drm dev/drm/i915_mem.c optional i915drm dev/drm/mach64_dma.c optional mach64drm dev/drm/mach64_drv.c optional mach64drm dev/drm/mach64_irq.c optional mach64drm dev/drm/mach64_state.c optional mach64drm dev/drm/mga_dma.c optional mgadrm dev/drm/mga_drv.c optional mgadrm dev/drm/mga_irq.c optional mgadrm dev/drm/mga_state.c optional mgadrm \ compile-with "${NORMAL_C} -finline-limit=13500" dev/drm/mga_warp.c optional mgadrm dev/drm/r128_cce.c optional r128drm dev/drm/r128_drv.c optional r128drm dev/drm/r128_irq.c optional r128drm dev/drm/r128_state.c optional r128drm \ compile-with "${NORMAL_C} -finline-limit=13500" dev/drm/r300_cmdbuf.c optional radeondrm dev/drm/radeon_cp.c optional radeondrm dev/drm/radeon_drv.c optional radeondrm dev/drm/radeon_irq.c optional radeondrm dev/drm/radeon_mem.c optional radeondrm dev/drm/radeon_state.c optional radeondrm dev/drm/savage_bci.c optional savagedrm dev/drm/savage_drv.c optional savagedrm dev/drm/savage_state.c optional savagedrm dev/drm/sis_drv.c optional sisdrm dev/drm/sis_ds.c optional sisdrm dev/drm/sis_mm.c optional sisdrm dev/drm/tdfx_drv.c optional tdfxdrm dev/ed/if_ed.c optional ed dev/ed/if_ed_novell.c optional ed dev/ed/if_ed_rtl80x9.c optional ed dev/ed/if_ed_pccard.c optional ed pccard dev/ed/if_ed_pci.c optional ed pci dev/eisa/eisa_if.m standard dev/eisa/eisaconf.c optional eisa dev/em/if_em.c optional em dev/em/if_em_hw.c optional em dev/en/if_en_pci.c optional en pci dev/en/midway.c optional en dev/ep/if_ep.c optional ep dev/ep/if_ep_eisa.c optional ep eisa dev/ep/if_ep_isa.c optional ep isa dev/ep/if_ep_mca.c optional ep mca dev/ep/if_ep_pccard.c optional ep pccard dev/esp/ncr53c9x.c optional esp dev/ex/if_ex.c optional ex dev/ex/if_ex_isa.c optional ex isa dev/ex/if_ex_pccard.c optional ex pccard dev/exca/exca.c optional cbb dev/fatm/if_fatm.c optional fatm pci dev/fb/splash.c optional splash dev/fe/if_fe.c optional fe dev/fe/if_fe_pccard.c optional fe pccard dev/firewire/firewire.c optional firewire dev/firewire/fwcrom.c optional firewire dev/firewire/fwdev.c optional firewire dev/firewire/fwdma.c optional firewire dev/firewire/fwmem.c optional firewire dev/firewire/fwohci.c optional firewire dev/firewire/fwohci_pci.c optional firewire pci dev/firewire/if_fwe.c optional fwe dev/firewire/if_fwip.c optional fwip dev/firewire/sbp.c optional sbp dev/firewire/sbp_targ.c optional sbp_targ dev/flash/at45.c optional at45 dev/fxp/if_fxp.c optional fxp dev/gem/if_gem.c optional gem dev/gem/if_gem_pci.c optional gem pci dev/harp/if_harp.c optional harp pci dev/hatm/if_hatm.c optional hatm pci dev/hatm/if_hatm_intr.c optional hatm pci dev/hatm/if_hatm_ioctl.c optional hatm pci dev/hatm/if_hatm_rx.c optional hatm pci dev/hatm/if_hatm_tx.c optional hatm pci dev/hfa/fore_buffer.c optional hfa dev/hfa/fore_command.c optional hfa dev/hfa/fore_globals.c optional hfa dev/hfa/fore_if.c optional hfa dev/hfa/fore_init.c optional hfa dev/hfa/fore_intr.c optional hfa dev/hfa/fore_output.c optional hfa dev/hfa/fore_receive.c optional hfa dev/hfa/fore_stats.c optional hfa dev/hfa/fore_timer.c optional hfa dev/hfa/fore_transmit.c optional hfa dev/hfa/fore_vcm.c optional hfa #dev/hfa/hfa_eisa.c optional hfa eisa dev/hfa/hfa_freebsd.c optional hfa dev/hfa/hfa_pci.c optional hfa pci #dev/hfa/hfa_sbus.c optional hfa sbus dev/hifn/hifn7751.c optional hifn dev/hme/if_hme.c optional hme dev/hme/if_hme_pci.c optional hme pci dev/hme/if_hme_sbus.c optional hme sbus dev/hwpmc/hwpmc_logging.c optional hwpmc dev/hwpmc/hwpmc_mod.c optional hwpmc dev/ichsmb/ichsmb.c optional ichsmb dev/ichsmb/ichsmb_pci.c optional ichsmb pci dev/ida/ida.c optional ida dev/ida/ida_disk.c optional ida dev/ida/ida_eisa.c optional ida eisa dev/ida/ida_pci.c optional ida pci dev/ie/if_ie.c optional ie isa nowerror dev/ie/if_ie_isa.c optional ie isa dev/ieee488/ibfoo.c optional pcii | tnt4882 dev/ieee488/pcii.c optional pcii dev/ieee488/tnt4882.c optional tnt4882 dev/ieee488/upd7210.c optional pcii | tnt4882 dev/iicbus/if_ic.c optional ic dev/iicbus/iic.c optional iic dev/iicbus/iicbb.c optional iicbb dev/iicbus/iicbb_if.m optional iicbb dev/iicbus/iicbus.c optional iicbus dev/iicbus/iicbus_if.m optional iicbus dev/iicbus/iiconf.c optional iicbus dev/iicbus/iicsmb.c optional iicsmb \ dependency "iicbus_if.h" dev/iir/iir.c optional iir dev/iir/iir_ctrl.c optional iir dev/iir/iir_pci.c optional iir pci dev/ips/ips.c optional ips dev/ips/ips_commands.c optional ips dev/ips/ips_disk.c optional ips dev/ips/ips_ioctl.c optional ips dev/ips/ips_pci.c optional ips pci dev/ipw/if_ipw.c optional ipw dev/isp/isp.c optional isp dev/isp/isp_freebsd.c optional isp dev/isp/isp_library.c optional isp dev/isp/isp_pci.c optional isp pci dev/isp/isp_sbus.c optional isp sbus dev/isp/isp_target.c optional isp dev/ispfw/ispfw.c optional ispfw dev/iwi/if_iwi.c optional iwi dev/ixgb/if_ixgb.c optional ixgb dev/ixgb/ixgb_ee.c optional ixgb dev/ixgb/ixgb_hw.c optional ixgb dev/joy/joy.c optional joy dev/joy/joy_isa.c optional joy isa dev/joy/joy_pccard.c optional joy pccard dev/kbdmux/kbdmux.c optional kbdmux dev/le/am7990.c optional le dev/le/am79900.c optional le dev/le/if_le_pci.c optional le pci dev/le/lance.c optional le dev/led/led.c standard dev/lge/if_lge.c optional lge dev/lmc/if_lmc.c optional lmc dev/mc146818/mc146818.c optional mc146818 dev/mca/mca_bus.c optional mca dev/mcd/mcd.c optional mcd isa nowerror dev/mcd/mcd_isa.c optional mcd isa nowerror dev/md/md.c optional md dev/mem/memdev.c optional mem dev/mfi/mfi.c optional mfi dev/mfi/mfi_debug.c optional mfi dev/mfi/mfi_pci.c optional mfi pci dev/mfi/mfi_disk.c optional mfi dev/mfi/mfi_linux.c optional mfi compat_linux dev/mii/acphy.c optional miibus | acphy dev/mii/amphy.c optional miibus | amphy dev/mii/bmtphy.c optional miibus | bmtphy dev/mii/brgphy.c optional miibus | brgphy dev/mii/ciphy.c optional miibus | ciphy dev/mii/e1000phy.c optional miibus | e1000phy # XXX only xl cards? dev/mii/exphy.c optional miibus | exphy dev/mii/gentbi.c optional miibus | gentbi # XXX only fxp cards? dev/mii/inphy.c optional miibus | inphy dev/mii/ip1000phy.c optional miibus | ip1000phy dev/mii/lxtphy.c optional miibus | lxtphy dev/mii/mii.c optional miibus | mii dev/mii/mii_physubr.c optional miibus | mii dev/mii/miibus_if.m optional miibus | mii dev/mii/mlphy.c optional miibus | mlphy dev/mii/nsgphy.c optional miibus | nsgphy dev/mii/nsphy.c optional miibus | nsphy dev/mii/pnaphy.c optional miibus | pnaphy dev/mii/qsphy.c optional miibus | qsphy dev/mii/rgephy.c optional miibus | rgephy # XXX rl and re only? dev/mii/rlphy.c optional miibus | rlphy # XXX rue only? dev/mii/ruephy.c optional miibus | ruephy dev/mii/tdkphy.c optional miibus | tdkphy dev/mii/tlphy.c optional miibus | tlphy dev/mii/ukphy.c optional miibus | mii dev/mii/ukphy_subr.c optional miibus | mii dev/mii/xmphy.c optional miibus | xmphy dev/mk48txx/mk48txx.c optional mk48txx dev/mlx/mlx.c optional mlx dev/mlx/mlx_disk.c optional mlx dev/mlx/mlx_pci.c optional mlx pci dev/mly/mly.c optional mly dev/mmc/mmc.c optional mmc dev/mmc/mmcbr_if.m optional mmc dev/mmc/mmcbus_if.m optional mmc dev/mmc/mmcsd.c optional mmcsd dev/mpt/mpt.c optional mpt dev/mpt/mpt_cam.c optional mpt dev/mpt/mpt_debug.c optional mpt dev/mpt/mpt_pci.c optional mpt pci dev/mpt/mpt_raid.c optional mpt dev/my/if_my.c optional my dev/ncv/ncr53c500.c optional ncv dev/ncv/ncr53c500_pccard.c optional ncv pccard dev/nge/if_nge.c optional nge dev/nmdm/nmdm.c optional nmdm dev/nsp/nsp.c optional nsp dev/nsp/nsp_pccard.c optional nsp pccard dev/null/null.c standard dev/patm/if_patm.c optional patm pci dev/patm/if_patm_attach.c optional patm pci dev/patm/if_patm_intr.c optional patm pci dev/patm/if_patm_ioctl.c optional patm pci dev/patm/if_patm_rtables.c optional patm pci dev/patm/if_patm_rx.c optional patm pci dev/patm/if_patm_tx.c optional patm pci dev/pbio/pbio.c optional pbio isa dev/pccard/card_if.m standard dev/pccard/pccard.c optional pccard dev/pccard/pccard_cis.c optional pccard dev/pccard/pccard_cis_quirks.c optional pccard dev/pccard/pccard_device.c optional pccard dev/pccard/power_if.m standard dev/pccbb/pccbb.c optional cbb dev/pccbb/pccbb_isa.c optional cbb isa dev/pccbb/pccbb_pci.c optional cbb pci dev/pcf/pcf.c optional pcf dev/pci/eisa_pci.c optional pci eisa dev/pci/fixup_pci.c optional pci dev/pci/hostb_pci.c optional pci dev/pci/ignore_pci.c optional pci dev/pci/isa_pci.c optional pci isa dev/pci/pci.c optional pci dev/pci/pci_if.m standard dev/pci/pci_pci.c optional pci dev/pci/pci_user.c optional pci dev/pci/pcib_if.m standard dev/pci/vga_pci.c optional pci dev/pdq/if_fea.c optional fea eisa dev/pdq/if_fpa.c optional fpa pci dev/pdq/pdq.c optional nowerror fea eisa | fpa pci dev/pdq/pdq_ifsubr.c optional nowerror fea eisa | fpa pci dev/ppbus/if_plip.c optional plip dev/ppbus/immio.c optional vpo dev/ppbus/lpbb.c optional lpbb dev/ppbus/lpt.c optional lpt dev/ppbus/pcfclock.c optional pcfclock dev/ppbus/ppb_1284.c optional ppbus dev/ppbus/ppb_base.c optional ppbus dev/ppbus/ppb_msq.c optional ppbus dev/ppbus/ppbconf.c optional ppbus dev/ppbus/ppbus_if.m optional ppbus dev/ppbus/ppi.c optional ppi dev/ppbus/pps.c optional pps dev/ppbus/vpo.c optional vpo dev/ppbus/vpoio.c optional vpo dev/ppc/ppc.c optional ppc dev/ppc/ppc_acpi.c optional ppc acpi dev/ppc/ppc_isa.c optional ppc isa dev/ppc/ppc_pci.c optional ppc pci dev/ppc/ppc_puc.c optional ppc puc dev/pst/pst-iop.c optional pst dev/pst/pst-pci.c optional pst pci dev/pst/pst-raid.c optional pst dev/puc/puc.c optional puc dev/puc/puc_cfg.c optional puc dev/puc/puc_pccard.c optional puc pccard dev/puc/puc_pci.c optional puc pci dev/puc/pucdata.c optional puc pci dev/ral/rt2560.c optional ral dev/ral/rt2661.c optional ral dev/ral/if_ralrate.c optional ral dev/ral/if_ral_pci.c optional ral pci dev/random/harvest.c standard dev/random/hash.c optional random dev/random/probe.c optional random dev/random/randomdev.c optional random dev/random/randomdev_soft.c optional random dev/random/yarrow.c optional random dev/ray/if_ray.c optional ray pccard dev/rc/rc.c optional rc dev/re/if_re.c optional re dev/rndtest/rndtest.c optional rndtest dev/rp/rp.c optional rp dev/rp/rp_isa.c optional rp isa dev/rp/rp_pci.c optional rp pci dev/safe/safe.c optional safe dev/sbsh/if_sbsh.c optional sbsh dev/scc/scc_if.m optional scc dev/scc/scc_bfe_ebus.c optional scc ebus dev/scc/scc_bfe_sbus.c optional scc fhc | scc sbus dev/scc/scc_core.c optional scc dev/scc/scc_dev_sab82532.c optional scc dev/scc/scc_dev_z8530.c optional scc dev/scd/scd.c optional scd isa dev/scd/scd_isa.c optional scd isa dev/si/si.c optional si dev/si/si2_z280.c optional si dev/si/si3_t225.c optional si dev/si/si_eisa.c optional si eisa dev/si/si_isa.c optional si isa dev/si/si_pci.c optional si pci dev/sk/if_sk.c optional sk pci dev/smbus/smb.c optional smb dev/smbus/smbconf.c optional smbus dev/smbus/smbus.c optional smbus dev/smbus/smbus_if.m optional smbus dev/sn/if_sn.c optional sn dev/sn/if_sn_isa.c optional sn isa dev/sn/if_sn_pccard.c optional sn pccard dev/snp/snp.c optional snp dev/sound/isa/ad1816.c optional snd_ad1816 isa dev/sound/isa/ess.c optional snd_ess isa dev/sound/isa/gusc.c optional snd_gusc isa dev/sound/isa/mss.c optional snd_mss isa dev/sound/isa/sb16.c optional snd_sb16 isa dev/sound/isa/sb8.c optional snd_sb8 isa dev/sound/isa/sbc.c optional snd_sbc isa dev/sound/isa/sndbuf_dma.c optional sound isa dev/sound/pci/als4000.c optional snd_als4000 pci dev/sound/pci/atiixp.c optional snd_atiixp pci #dev/sound/pci/au88x0.c optional snd_au88x0 pci dev/sound/pci/cmi.c optional snd_cmi pci dev/sound/pci/cs4281.c optional snd_cs4281 pci dev/sound/pci/csa.c optional snd_csa pci \ warning "kernel contains GPL contaminated csaimg.h header" dev/sound/pci/csapcm.c optional snd_csa pci dev/sound/pci/ds1.c optional snd_ds1 pci dev/sound/pci/emu10k1.c optional snd_emu10k1 pci \ dependency "emu10k1-alsa%diked.h" \ warning "kernel contains GPL contaminated emu10k1 headers" dev/sound/pci/emu10kx.c optional snd_emu10kx pci \ dependency "emu10k1-alsa%diked.h" \ dependency "p16v-alsa%diked.h" \ dependency "p17v-alsa%diked.h" \ warning "kernel contains GPL contaminated emu10kx headers" dev/sound/pci/emu10kx-pcm.c optional snd_emu10kx pci \ dependency "emu10k1-alsa%diked.h" \ dependency "p16v-alsa%diked.h" \ dependency "p17v-alsa%diked.h" \ warning "kernel contains GPL contaminated emu10kx headers" dev/sound/pci/emu10kx-midi.c optional snd_emu10kx pci \ dependency "emu10k1-alsa%diked.h" \ warning "kernel contains GPL contaminated emu10kx headers" dev/sound/pci/envy24.c optional snd_envy24 pci dev/sound/pci/envy24ht.c optional snd_envy24ht pci dev/sound/pci/es137x.c optional snd_es137x pci dev/sound/pci/fm801.c optional snd_fm801 pci dev/sound/pci/ich.c optional snd_ich pci dev/sound/pci/maestro.c optional snd_maestro pci dev/sound/pci/maestro3.c optional snd_maestro3 pci \ warning "kernel contains GPL contaminated maestro3 headers" dev/sound/pci/neomagic.c optional snd_neomagic pci dev/sound/pci/solo.c optional snd_solo pci dev/sound/pci/spicds.c optional snd_spicds pci dev/sound/pci/t4dwave.c optional snd_t4dwave pci dev/sound/pci/via8233.c optional snd_via8233 pci dev/sound/pci/via82c686.c optional snd_via82c686 pci dev/sound/pci/vibes.c optional snd_vibes pci dev/sound/pci/hda/hdac.c optional snd_hda pci dev/sound/pcm/ac97.c optional sound dev/sound/pcm/ac97_if.m optional sound dev/sound/pcm/ac97_patch.c optional sound dev/sound/pcm/buffer.c optional sound dev/sound/pcm/channel.c optional sound dev/sound/pcm/channel_if.m optional sound dev/sound/pcm/dsp.c optional sound dev/sound/pcm/fake.c optional sound dev/sound/pcm/feeder.c optional sound dev/sound/pcm/feeder_fmt.c optional sound dev/sound/pcm/feeder_if.m optional sound dev/sound/pcm/feeder_rate.c optional sound dev/sound/pcm/feeder_volume.c optional sound dev/sound/pcm/mixer.c optional sound dev/sound/pcm/mixer_if.m optional sound dev/sound/pcm/sndstat.c optional sound dev/sound/pcm/sound.c optional sound dev/sound/pcm/vchan.c optional sound #dev/sound/usb/upcm.c optional snd_upcm usb dev/sound/usb/uaudio.c optional snd_uaudio usb dev/sound/usb/uaudio_pcm.c optional snd_uaudio usb dev/sound/midi/midi.c optional sound dev/sound/midi/mpu401.c optional sound dev/sound/midi/mpu_if.m optional sound dev/sound/midi/mpufoi_if.m optional sound dev/sound/midi/sequencer.c optional sound dev/sound/midi/synth_if.m optional sound dev/spibus/spibus.c optional spibus \ dependency "spibus_if.h" dev/spibus/spibus_if.m optional spibus dev/sr/if_sr.c optional sr dev/sr/if_sr_pci.c optional sr pci dev/stg/tmc18c30.c optional stg dev/stg/tmc18c30_isa.c optional stg isa dev/stg/tmc18c30_pccard.c optional stg pccard dev/stg/tmc18c30_pci.c optional stg pci dev/stg/tmc18c30_subr.c optional stg dev/stge/if_stge.c optional stge dev/streams/streams.c optional streams dev/sym/sym_hipd.c optional sym \ dependency "$S/dev/sym/sym_{conf,defs}.h" dev/syscons/blank/blank_saver.c optional blank_saver dev/syscons/daemon/daemon_saver.c optional daemon_saver dev/syscons/dragon/dragon_saver.c optional dragon_saver dev/syscons/fade/fade_saver.c optional fade_saver dev/syscons/fire/fire_saver.c optional fire_saver dev/syscons/green/green_saver.c optional green_saver dev/syscons/logo/logo.c optional logo_saver dev/syscons/logo/logo_saver.c optional logo_saver dev/syscons/rain/rain_saver.c optional rain_saver dev/syscons/schistory.c optional sc dev/syscons/scmouse.c optional sc dev/syscons/scterm-dumb.c optional sc dev/syscons/scterm.c optional sc dev/syscons/scvidctl.c optional sc dev/syscons/snake/snake_saver.c optional snake_saver dev/syscons/star/star_saver.c optional star_saver dev/syscons/syscons.c optional sc dev/syscons/sysmouse.c optional sc dev/syscons/warp/warp_saver.c optional warp_saver dev/tdfx/tdfx_linux.c optional tdfx_linux tdfx compat_linux dev/tdfx/tdfx_pci.c optional tdfx pci dev/ti/if_ti.c optional ti pci dev/trm/trm.c optional trm dev/twa/tw_cl_fwimg.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_cl_init.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_cl_intr.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_cl_io.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_cl_misc.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_osl_cam.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_osl_freebsd.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twe/twe.c optional twe dev/twe/twe_freebsd.c optional twe dev/tx/if_tx.c optional tx dev/txp/if_txp.c optional txp dev/uart/uart_bus_acpi.c optional uart acpi #dev/uart/uart_bus_cbus.c optional uart cbus dev/uart/uart_bus_ebus.c optional uart ebus dev/uart/uart_bus_isa.c optional uart isa dev/uart/uart_bus_pccard.c optional uart pccard dev/uart/uart_bus_pci.c optional uart pci dev/uart/uart_bus_puc.c optional uart puc dev/uart/uart_bus_scc.c optional uart scc dev/uart/uart_core.c optional uart dev/uart/uart_dbg.c optional uart gdb dev/uart/uart_dev_ns8250.c optional uart uart_ns8250 dev/uart/uart_dev_sab82532.c optional uart uart_sab82532 dev/uart/uart_dev_sab82532.c optional uart scc dev/uart/uart_dev_z8530.c optional uart uart_z8530 dev/uart/uart_dev_z8530.c optional uart scc dev/uart/uart_if.m optional uart dev/uart/uart_subr.c optional uart dev/uart/uart_tty.c optional uart dev/ubsec/ubsec.c optional ubsec # # USB support dev/usb/ehci.c optional ehci dev/usb/ehci_pci.c optional ehci pci dev/usb/hid.c optional usb dev/usb/if_aue.c optional aue dev/usb/if_axe.c optional axe dev/usb/if_cdce.c optional cdce dev/usb/if_cue.c optional cue dev/usb/if_kue.c optional kue dev/usb/if_ural.c optional ural dev/usb/if_rue.c optional rue dev/usb/if_udav.c optional udav dev/usb/ohci.c optional ohci dev/usb/ohci_pci.c optional ohci pci dev/usb/sl811hs.c optional slhci dev/usb/slhci_pccard.c optional slhci pccard dev/usb/ubsa.c optional ubsa dev/usb/ubser.c optional ubser dev/usb/ucom.c optional ucom dev/usb/ucycom.c optional ucycom dev/usb/udbp.c optional udbp dev/usb/ufoma.c optional ufoma dev/usb/ufm.c optional ufm dev/usb/uftdi.c optional uftdi dev/usb/ugen.c optional ugen dev/usb/uhci.c optional uhci dev/usb/uhci_pci.c optional uhci pci dev/usb/uhid.c optional uhid dev/usb/uhub.c optional usb dev/usb/ukbd.c optional ukbd dev/usb/ulpt.c optional ulpt dev/usb/umass.c optional umass dev/usb/umct.c optional umct dev/usb/umodem.c optional umodem dev/usb/ums.c optional ums dev/usb/uplcom.c optional uplcom dev/usb/urio.c optional urio dev/usb/usb.c optional usb dev/usb/usb_ethersubr.c optional usb dev/usb/usb_if.m optional usb dev/usb/usb_mem.c optional usb dev/usb/usb_quirks.c optional usb dev/usb/usb_subr.c optional usb dev/usb/usbdi.c optional usb dev/usb/usbdi_util.c optional usb dev/usb/uscanner.c optional uscanner dev/usb/uvisor.c optional uvisor dev/usb/uvscom.c optional uvscom dev/utopia/idtphy.c optional utopia dev/utopia/suni.c optional utopia dev/utopia/utopia.c optional utopia dev/vge/if_vge.c optional vge dev/vkbd/vkbd.c optional vkbd dev/vx/if_vx.c optional vx dev/vx/if_vx_eisa.c optional vx eisa dev/vx/if_vx_pci.c optional vx pci dev/watchdog/watchdog.c standard dev/wds/wd7000.c optional wds isa dev/wi/if_wi.c optional wi dev/wi/if_wi_pccard.c optional wi pccard dev/wi/if_wi_pci.c optional wi pci dev/wl/if_wl.c optional wl isa dev/xe/if_xe.c optional xe dev/xe/if_xe_pccard.c optional xe pccard fs/deadfs/dead_vnops.c standard fs/devfs/devfs_devs.c standard fs/devfs/devfs_rule.c standard fs/devfs/devfs_vfsops.c standard fs/devfs/devfs_vnops.c standard fs/fdescfs/fdesc_vfsops.c optional fdescfs fs/fdescfs/fdesc_vnops.c optional fdescfs fs/fifofs/fifo_vnops.c standard fs/hpfs/hpfs_alsubr.c optional hpfs fs/hpfs/hpfs_lookup.c optional hpfs fs/hpfs/hpfs_subr.c optional hpfs fs/hpfs/hpfs_vfsops.c optional hpfs fs/hpfs/hpfs_vnops.c optional hpfs fs/msdosfs/msdosfs_conv.c optional msdosfs fs/msdosfs/msdosfs_denode.c optional msdosfs fs/msdosfs/msdosfs_fat.c optional msdosfs fs/msdosfs/msdosfs_fileno.c optional msdosfs_large fs/msdosfs/msdosfs_iconv.c optional msdosfs_iconv fs/msdosfs/msdosfs_lookup.c optional msdosfs fs/msdosfs/msdosfs_vfsops.c optional msdosfs fs/msdosfs/msdosfs_vnops.c optional msdosfs fs/ntfs/ntfs_compr.c optional ntfs fs/ntfs/ntfs_iconv.c optional ntfs_iconv fs/ntfs/ntfs_ihash.c optional ntfs fs/ntfs/ntfs_subr.c optional ntfs fs/ntfs/ntfs_vfsops.c optional ntfs fs/ntfs/ntfs_vnops.c optional ntfs fs/nullfs/null_subr.c optional nullfs fs/nullfs/null_vfsops.c optional nullfs fs/nullfs/null_vnops.c optional nullfs fs/nwfs/nwfs_io.c optional nwfs fs/nwfs/nwfs_ioctl.c optional nwfs fs/nwfs/nwfs_node.c optional nwfs fs/nwfs/nwfs_subr.c optional nwfs fs/nwfs/nwfs_vfsops.c optional nwfs fs/nwfs/nwfs_vnops.c optional nwfs fs/portalfs/portal_vfsops.c optional portalfs fs/portalfs/portal_vnops.c optional portalfs fs/procfs/procfs.c optional procfs fs/procfs/procfs_ctl.c optional procfs fs/procfs/procfs_dbregs.c optional procfs fs/procfs/procfs_fpregs.c optional procfs fs/procfs/procfs_ioctl.c optional procfs fs/procfs/procfs_map.c optional procfs fs/procfs/procfs_mem.c optional procfs fs/procfs/procfs_note.c optional procfs fs/procfs/procfs_regs.c optional procfs fs/procfs/procfs_rlimit.c optional procfs fs/procfs/procfs_status.c optional procfs fs/procfs/procfs_type.c optional procfs fs/pseudofs/pseudofs.c optional pseudofs fs/pseudofs/pseudofs_fileno.c optional pseudofs fs/pseudofs/pseudofs_vncache.c optional pseudofs fs/pseudofs/pseudofs_vnops.c optional pseudofs fs/smbfs/smbfs_io.c optional smbfs fs/smbfs/smbfs_node.c optional smbfs fs/smbfs/smbfs_smb.c optional smbfs fs/smbfs/smbfs_subr.c optional smbfs fs/smbfs/smbfs_vfsops.c optional smbfs fs/smbfs/smbfs_vnops.c optional smbfs fs/udf/osta.c optional udf fs/udf/udf_iconv.c optional udf_iconv fs/udf/udf_vfsops.c optional udf fs/udf/udf_vnops.c optional udf fs/umapfs/umap_subr.c optional umapfs fs/umapfs/umap_vfsops.c optional umapfs fs/umapfs/umap_vnops.c optional umapfs fs/unionfs/union_subr.c optional unionfs fs/unionfs/union_vfsops.c optional unionfs fs/unionfs/union_vnops.c optional unionfs gdb/gdb_cons.c optional gdb gdb/gdb_main.c optional gdb gdb/gdb_packet.c optional gdb geom/bde/g_bde.c optional geom_bde geom/bde/g_bde_crypt.c optional geom_bde geom/bde/g_bde_lock.c optional geom_bde geom/bde/g_bde_work.c optional geom_bde geom/cache/g_cache.c optional geom_cache geom/concat/g_concat.c optional geom_concat geom/eli/g_eli.c optional geom_eli geom/eli/g_eli_crypto.c optional geom_eli geom/eli/g_eli_ctl.c optional geom_eli geom/eli/g_eli_integrity.c optional geom_eli geom/eli/g_eli_key.c optional geom_eli geom/eli/g_eli_privacy.c optional geom_eli geom/eli/pkcs5v2.c optional geom_eli geom/gate/g_gate.c optional geom_gate geom/geom_aes.c optional geom_aes geom/geom_apple.c optional geom_apple geom/geom_bsd.c optional geom_bsd geom/geom_bsd_enc.c optional geom_bsd geom/geom_ccd.c optional ccd | geom_ccd geom/geom_ctl.c standard geom/geom_dev.c standard geom/geom_disk.c standard geom/geom_dump.c standard geom/geom_event.c standard geom/geom_fox.c optional geom_fox geom/geom_gpt.c optional geom_gpt geom/geom_io.c standard geom/geom_kern.c standard geom/geom_mbr.c optional geom_mbr geom/geom_mbr_enc.c optional geom_mbr geom/geom_pc98.c optional geom_pc98 geom/geom_pc98_enc.c optional geom_pc98 geom/geom_slice.c standard geom/geom_subr.c standard geom/geom_sunlabel.c optional geom_sunlabel geom/geom_sunlabel_enc.c optional geom_sunlabel geom/geom_vfs.c standard geom/geom_vol_ffs.c optional geom_vol geom/journal/g_journal.c optional geom_journal geom/journal/g_journal_ufs.c optional geom_journal geom/label/g_label.c optional geom_label geom/label/g_label_ext2fs.c optional geom_label geom/label/g_label_iso9660.c optional geom_label geom/label/g_label_msdosfs.c optional geom_label geom/label/g_label_ntfs.c optional geom_label geom/label/g_label_reiserfs.c optional geom_label geom/label/g_label_ufs.c optional geom_label geom/mirror/g_mirror.c optional geom_mirror geom/mirror/g_mirror_ctl.c optional geom_mirror geom/nop/g_nop.c optional geom_nop geom/raid3/g_raid3.c optional geom_raid3 geom/raid3/g_raid3_ctl.c optional geom_raid3 geom/shsec/g_shsec.c optional geom_shsec geom/stripe/g_stripe.c optional geom_stripe geom/uzip/g_uzip.c optional geom_uzip geom/zero/g_zero.c optional geom_zero gnu/fs/ext2fs/ext2_alloc.c optional ext2fs \ warning "kernel contains GPL contaminated ext2fs filesystem" gnu/fs/ext2fs/ext2_balloc.c optional ext2fs gnu/fs/ext2fs/ext2_bmap.c optional ext2fs gnu/fs/ext2fs/ext2_inode.c optional ext2fs gnu/fs/ext2fs/ext2_inode_cnv.c optional ext2fs gnu/fs/ext2fs/ext2_linux_balloc.c optional ext2fs gnu/fs/ext2fs/ext2_linux_ialloc.c optional ext2fs gnu/fs/ext2fs/ext2_lookup.c optional ext2fs gnu/fs/ext2fs/ext2_subr.c optional ext2fs gnu/fs/ext2fs/ext2_vfsops.c optional ext2fs gnu/fs/ext2fs/ext2_vnops.c optional ext2fs gnu/fs/reiserfs/reiserfs_hashes.c optional reiserfs \ warning "kernel contains GPL contaminated ReiserFS filesystem" gnu/fs/reiserfs/reiserfs_inode.c optional reiserfs gnu/fs/reiserfs/reiserfs_item_ops.c optional reiserfs gnu/fs/reiserfs/reiserfs_namei.c optional reiserfs gnu/fs/reiserfs/reiserfs_prints.c optional reiserfs gnu/fs/reiserfs/reiserfs_stree.c optional reiserfs gnu/fs/reiserfs/reiserfs_vfsops.c optional reiserfs gnu/fs/reiserfs/reiserfs_vnops.c optional reiserfs # # isdn4bsd device drivers # i4b/driver/i4b_trace.c optional i4btrc i4b/driver/i4b_rbch.c optional i4brbch i4b/driver/i4b_tel.c optional i4btel i4b/driver/i4b_ipr.c optional i4bipr net/slcompress.c optional i4bipr | i4bisppp i4b/driver/i4b_ctl.c optional i4bctl i4b/driver/i4b_ing.c optional i4bing i4b/driver/i4b_isppp.c optional i4bisppp # # isdn4bsd CAPI driver # i4b/capi/capi_l4if.c optional i4bcapi i4b/capi/capi_llif.c optional i4bcapi i4b/capi/capi_msgs.c optional i4bcapi # # isdn4bsd AVM B1/T1 CAPI driver # i4b/capi/iavc/iavc_pci.c optional iavc i4bcapi pci i4b/capi/iavc/iavc_isa.c optional iavc i4bcapi isa i4b/capi/iavc/iavc_lli.c optional iavc i4bcapi i4b/capi/iavc/iavc_card.c optional iavc i4bcapi # # isdn4bsd support # i4b/layer2/i4b_mbuf.c optional i4btrc # # isdn4bsd Q.921 handler # i4b/layer2/i4b_l2.c optional i4bq921 i4b/layer2/i4b_l2fsm.c optional i4bq921 i4b/layer2/i4b_uframe.c optional i4bq921 i4b/layer2/i4b_tei.c optional i4bq921 i4b/layer2/i4b_sframe.c optional i4bq921 i4b/layer2/i4b_iframe.c optional i4bq921 i4b/layer2/i4b_l2timer.c optional i4bq921 i4b/layer2/i4b_util.c optional i4bq921 i4b/layer2/i4b_lme.c optional i4bq921 # # isdn4bsd Q.931 handler # i4b/layer3/i4b_q931.c optional i4bq931 i4b/layer3/i4b_l3fsm.c optional i4bq931 i4b/layer3/i4b_l3timer.c optional i4bq931 i4b/layer3/i4b_l2if.c optional i4bq931 i4b/layer3/i4b_l4if.c optional i4bq931 i4b/layer3/i4b_q932fac.c optional i4bq931 # # isdn4bsd control device driver, interface to isdnd # i4b/layer4/i4b_i4bdrv.c optional i4b i4b/layer4/i4b_l4.c optional i4b i4b/layer4/i4b_l4mgmt.c optional i4b i4b/layer4/i4b_l4timer.c optional i4b # isa/isa_if.m standard isa/isa_common.c optional isa isa/isahint.c optional isa isa/orm.c optional isa isa/pnp.c optional isa isapnp isa/pnpparse.c optional isa isapnp isofs/cd9660/cd9660_bmap.c optional cd9660 isofs/cd9660/cd9660_lookup.c optional cd9660 isofs/cd9660/cd9660_node.c optional cd9660 isofs/cd9660/cd9660_rrip.c optional cd9660 isofs/cd9660/cd9660_util.c optional cd9660 isofs/cd9660/cd9660_vfsops.c optional cd9660 isofs/cd9660/cd9660_vnops.c optional cd9660 isofs/cd9660/cd9660_iconv.c optional cd9660_iconv kern/bus_if.m standard kern/clock_if.m optional genclock kern/cpufreq_if.m standard kern/device_if.m standard kern/imgact_elf.c standard kern/imgact_shell.c standard kern/inflate.c optional gzip kern/init_main.c standard kern/init_sysent.c standard +kern/ksched.c optional _kposix_priority_scheduling kern/kern_acct.c standard kern/kern_acl.c standard kern/kern_alq.c optional alq kern/kern_clock.c standard kern/kern_condvar.c standard kern/kern_conf.c standard kern/kern_cpu.c standard kern/kern_context.c standard kern/kern_descrip.c standard kern/kern_environment.c standard kern/kern_event.c standard kern/kern_exec.c standard kern/kern_exit.c standard kern/kern_fork.c standard kern/kern_idle.c standard kern/kern_intr.c standard kern/kern_jail.c standard kern/kern_kse.c standard kern/kern_kthread.c standard kern/kern_ktr.c optional ktr kern/kern_ktrace.c standard kern/kern_linker.c standard kern/kern_lock.c standard kern/kern_lockf.c standard kern/kern_mac.c standard kern/kern_malloc.c standard kern/kern_mbuf.c standard kern/kern_mib.c standard kern/kern_module.c standard kern/kern_mtxpool.c standard kern/kern_mutex.c standard kern/kern_ntptime.c standard kern/kern_physio.c standard kern/kern_pmc.c standard kern/kern_poll.c optional device_polling kern/kern_priv.c standard kern/kern_proc.c standard kern/kern_prot.c standard kern/kern_resource.c standard kern/kern_rwlock.c standard kern/kern_sema.c standard kern/kern_shutdown.c standard kern/kern_sig.c standard kern/kern_subr.c standard kern/kern_sx.c standard kern/kern_synch.c standard kern/kern_syscalls.c standard kern/kern_sysctl.c standard kern/kern_tc.c standard kern/kern_thr.c standard kern/kern_thread.c standard kern/kern_time.c standard kern/kern_timeout.c standard kern/kern_umtx.c standard kern/kern_uuid.c standard kern/kern_xxx.c standard kern/link_elf.c standard kern/linker_if.m standard kern/md4c.c optional netsmb kern/md5c.c standard +kern/p1003_1b.c standard +kern/posix4_mib.c standard kern/sched_4bsd.c optional sched_4bsd kern/sched_core.c optional sched_core kern/sched_ule.c optional sched_ule kern/serdev_if.m optional puc | scc kern/subr_acl_posix1e.c standard kern/subr_autoconf.c standard kern/subr_blist.c standard kern/subr_bus.c standard kern/subr_clock.c standard kern/subr_devstat.c standard kern/subr_disk.c standard kern/subr_eventhandler.c standard kern/subr_fattime.c standard kern/subr_firmware.c optional firmware kern/subr_hints.c standard kern/subr_kdb.c standard kern/subr_kobj.c standard kern/subr_lock.c standard kern/subr_log.c standard kern/subr_mbpool.c optional libmbpool kern/subr_mchain.c optional libmchain kern/subr_module.c standard kern/subr_msgbuf.c standard kern/subr_param.c standard kern/subr_pcpu.c standard kern/subr_power.c standard kern/subr_prf.c standard kern/subr_prof.c standard kern/subr_rman.c standard kern/subr_rtc.c optional genclock kern/subr_sbuf.c standard kern/subr_scanf.c standard kern/subr_sleepqueue.c standard kern/subr_smp.c standard kern/subr_stack.c optional ddb kern/subr_taskqueue.c standard kern/subr_trap.c standard kern/subr_turnstile.c standard kern/subr_unit.c standard kern/subr_witness.c optional witness kern/sys_generic.c standard kern/sys_pipe.c standard kern/sys_process.c standard kern/sys_socket.c standard kern/syscalls.c optional witness | invariants kern/sysv_ipc.c standard kern/sysv_msg.c optional sysvmsg kern/sysv_sem.c optional sysvsem kern/sysv_shm.c optional sysvshm kern/tty.c standard kern/tty_compat.c optional compat_43tty kern/tty_conf.c standard kern/tty_cons.c standard kern/tty_pty.c optional pty kern/tty_pts.c optional pty kern/tty_subr.c standard kern/tty_tty.c standard kern/uipc_accf.c optional inet kern/uipc_cow.c optional zero_copy_sockets kern/uipc_domain.c standard kern/uipc_mbuf.c standard kern/uipc_mbuf2.c standard kern/uipc_mqueue.c optional p1003_1b_mqueue kern/uipc_sem.c optional p1003_1b_semaphores kern/uipc_sockbuf.c standard kern/uipc_socket.c standard kern/uipc_socket2.c standard kern/uipc_syscalls.c standard kern/uipc_usrreq.c standard kern/vfs_aio.c optional vfs_aio kern/vfs_bio.c standard kern/vfs_cache.c standard kern/vfs_cluster.c standard kern/vfs_default.c standard kern/vfs_export.c standard kern/vfs_hash.c standard kern/vfs_init.c standard kern/vfs_lookup.c standard kern/vfs_mount.c standard kern/vfs_subr.c standard kern/vfs_syscalls.c standard kern/vfs_vnops.c standard # # These files in libkern/ are those needed by all architectures. Some # of the files in libkern/ are only needed on some architectures, e.g., # libkern/divdi3.c is needed by i386 but not alpha. Also, some of these # routines may be optimized for a particular platform. In either case, # the file should be moved to conf/files. from here. # libkern/arc4random.c standard libkern/bcd.c standard libkern/bsearch.c standard libkern/crc32.c standard libkern/fnmatch.c standard libkern/gets.c standard libkern/iconv.c optional libiconv libkern/iconv_converter_if.m optional libiconv libkern/iconv_xlat.c optional libiconv libkern/iconv_xlat16.c optional libiconv libkern/index.c standard libkern/inet_ntoa.c standard libkern/mcount.c optional profiling-routine libkern/qsort.c standard libkern/qsort_r.c standard libkern/random.c standard libkern/rindex.c standard libkern/scanc.c standard libkern/skpc.c standard libkern/strcasecmp.c standard libkern/strcat.c standard libkern/strcmp.c standard libkern/strcpy.c standard libkern/strdup.c standard libkern/strlcat.c standard libkern/strlcpy.c standard libkern/strlen.c standard libkern/strncmp.c standard libkern/strncpy.c standard libkern/strsep.c standard libkern/strspn.c standard libkern/strstr.c standard libkern/strtol.c standard libkern/strtoq.c standard libkern/strtoul.c standard libkern/strtouq.c standard libkern/strvalid.c standard net/bpf.c standard net/bpf_jitter.c optional bpf_jitter net/bpf_filter.c optional bpf | netgraph_bpf net/bridgestp.c optional if_bridge net/bsd_comp.c optional ppp_bsdcomp net/if.c standard net/if_arcsubr.c optional arcnet net/if_atmsubr.c optional atm net/if_bridge.c optional if_bridge net/if_clone.c standard net/if_disc.c optional disc net/if_ef.c optional ef net/if_enc.c optional enc net/if_ethersubr.c optional ether net/if_faith.c optional faith net/if_fddisubr.c optional fddi net/if_fwsubr.c optional fwip net/if_gif.c optional gif net/if_gre.c optional gre net/if_iso88025subr.c optional token net/if_loop.c optional loop net/if_media.c standard net/if_mib.c standard net/if_ppp.c optional ppp net/if_sl.c optional sl net/if_spppfr.c optional i4bisppp | sppp net/if_spppsubr.c optional i4bisppp | sppp net/if_stf.c optional stf net/if_tun.c optional tun net/if_tap.c optional tap net/if_vlan.c optional vlan net/netisr.c standard net/ppp_deflate.c optional ppp_deflate net/ppp_tty.c optional ppp net/pfil.c optional ether | inet net/radix.c standard net/raw_cb.c standard net/raw_usrreq.c standard net/route.c standard net/rtsock.c standard net/slcompress.c optional netgraph_vjc | ppp | sl | sppp net/zlib.c optional crypto | geom_uzip | ipsec | \ ppp_deflate net80211/ieee80211.c optional wlan net80211/ieee80211_acl.c optional wlan_acl net80211/ieee80211_crypto.c optional wlan net80211/ieee80211_crypto_ccmp.c optional wlan_ccmp net80211/ieee80211_crypto_none.c optional wlan net80211/ieee80211_crypto_tkip.c optional wlan_tkip net80211/ieee80211_crypto_wep.c optional wlan_wep net80211/ieee80211_freebsd.c optional wlan net80211/ieee80211_input.c optional wlan net80211/ieee80211_ioctl.c optional wlan net80211/ieee80211_node.c optional wlan net80211/ieee80211_output.c optional wlan net80211/ieee80211_proto.c optional wlan net80211/ieee80211_xauth.c optional wlan_xauth netatalk/aarp.c optional netatalk netatalk/at_control.c optional netatalk netatalk/at_proto.c optional netatalk netatalk/at_rmx.c optional netatalkdebug netatalk/ddp_input.c optional netatalk netatalk/ddp_output.c optional netatalk netatalk/ddp_pcb.c optional netatalk netatalk/ddp_usrreq.c optional netatalk netatm/atm_aal5.c optional atm_core netatm/atm_cm.c optional atm_core netatm/atm_device.c optional atm_core netatm/atm_if.c optional atm_core netatm/atm_proto.c optional atm_core netatm/atm_signal.c optional atm_core netatm/atm_socket.c optional atm_core netatm/atm_subr.c optional atm_core netatm/atm_usrreq.c optional atm_core netatm/ipatm/ipatm_event.c optional atm_ip atm_core netatm/ipatm/ipatm_if.c optional atm_ip atm_core netatm/ipatm/ipatm_input.c optional atm_ip atm_core netatm/ipatm/ipatm_load.c optional atm_ip atm_core netatm/ipatm/ipatm_output.c optional atm_ip atm_core netatm/ipatm/ipatm_usrreq.c optional atm_ip atm_core netatm/ipatm/ipatm_vcm.c optional atm_ip atm_core netatm/sigpvc/sigpvc_if.c optional atm_sigpvc atm_core netatm/sigpvc/sigpvc_subr.c optional atm_sigpvc atm_core netatm/spans/spans_arp.c optional atm_spans atm_core \ dependency "spans_xdr.h" netatm/spans/spans_cls.c optional atm_spans atm_core netatm/spans/spans_if.c optional atm_spans atm_core netatm/spans/spans_kxdr.c optional atm_spans atm_core netatm/spans/spans_msg.c optional atm_spans atm_core netatm/spans/spans_print.c optional atm_spans atm_core netatm/spans/spans_proto.c optional atm_spans atm_core netatm/spans/spans_subr.c optional atm_spans atm_core netatm/spans/spans_util.c optional atm_spans atm_core spans_xdr.h optional atm_spans atm_core \ before-depend \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "rpcgen -h -C $S/netatm/spans/spans_xdr.x | grep -v rpc/rpc.h > spans_xdr.h" \ clean "spans_xdr.h" \ no-obj no-implicit-rule spans_xdr.c optional atm_spans atm_core \ before-depend \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "rpcgen -c -C $S/netatm/spans/spans_xdr.x | grep -v rpc/rpc.h > spans_xdr.c" \ clean "spans_xdr.c" \ no-obj no-implicit-rule local spans_xdr.o optional atm_spans atm_core \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "${NORMAL_C}" \ no-implicit-rule local netatm/uni/q2110_sigaa.c optional atm_uni atm_core netatm/uni/q2110_sigcpcs.c optional atm_uni atm_core netatm/uni/q2110_subr.c optional atm_uni atm_core netatm/uni/qsaal1_sigaa.c optional atm_uni atm_core netatm/uni/qsaal1_sigcpcs.c optional atm_uni atm_core netatm/uni/qsaal1_subr.c optional atm_uni atm_core netatm/uni/sscf_uni.c optional atm_uni atm_core netatm/uni/sscf_uni_lower.c optional atm_uni atm_core netatm/uni/sscf_uni_upper.c optional atm_uni atm_core netatm/uni/sscop.c optional atm_uni atm_core netatm/uni/sscop_lower.c optional atm_uni atm_core netatm/uni/sscop_pdu.c optional atm_uni atm_core netatm/uni/sscop_sigaa.c optional atm_uni atm_core netatm/uni/sscop_sigcpcs.c optional atm_uni atm_core netatm/uni/sscop_subr.c optional atm_uni atm_core netatm/uni/sscop_timer.c optional atm_uni atm_core netatm/uni/sscop_upper.c optional atm_uni atm_core netatm/uni/uni_load.c optional atm_uni atm_core netatm/uni/uniarp.c optional atm_uni atm_core netatm/uni/uniarp_cache.c optional atm_uni atm_core netatm/uni/uniarp_input.c optional atm_uni atm_core netatm/uni/uniarp_output.c optional atm_uni atm_core netatm/uni/uniarp_timer.c optional atm_uni atm_core netatm/uni/uniarp_vcm.c optional atm_uni atm_core netatm/uni/uniip.c optional atm_uni atm_core netatm/uni/unisig_decode.c optional atm_uni atm_core netatm/uni/unisig_encode.c optional atm_uni atm_core netatm/uni/unisig_if.c optional atm_uni atm_core netatm/uni/unisig_mbuf.c optional atm_uni atm_core netatm/uni/unisig_msg.c optional atm_uni atm_core netatm/uni/unisig_print.c optional atm_uni atm_core netatm/uni/unisig_proto.c optional atm_uni atm_core netatm/uni/unisig_sigmgr_state.c optional atm_uni atm_core netatm/uni/unisig_subr.c optional atm_uni atm_core netatm/uni/unisig_util.c optional atm_uni atm_core netatm/uni/unisig_vc_state.c optional atm_uni atm_core netgraph/atm/atmpif/ng_atmpif.c optional netgraph_atm_atmpif netgraph/atm/atmpif/ng_atmpif_harp.c optional netgraph_atm_atmpif netgraph/atm/ccatm/ng_ccatm.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/atm/ng_atm.c optional ngatm_atm netgraph/atm/ngatmbase.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/atm/sscfu/ng_sscfu.c optional ngatm_sscfu \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/atm/sscop/ng_sscop.c optional ngatm_sscop \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/atm/uni/ng_uni.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/bluetooth/common/ng_bluetooth.c optional netgraph_bluetooth netgraph/bluetooth/drivers/bt3c/ng_bt3c_pccard.c optional netgraph_bluetooth_bt3c netgraph/bluetooth/drivers/h4/ng_h4.c optional netgraph_bluetooth_h4 netgraph/bluetooth/drivers/ubt/ng_ubt.c optional netgraph_bluetooth_ubt netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c optional netgraph_bluetooth_ubtbcmfw netgraph/bluetooth/hci/ng_hci_cmds.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_evnt.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_main.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_misc.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_ulpi.c optional netgraph_bluetooth_hci netgraph/bluetooth/l2cap/ng_l2cap_cmds.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_evnt.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_llpi.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_main.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_misc.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_ulpi.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/socket/ng_btsocket.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_hci_raw.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_l2cap.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_rfcomm.c optional netgraph_bluetooth_socket netgraph/netflow/netflow.c optional netgraph_netflow netgraph/netflow/ng_netflow.c optional netgraph_netflow netgraph/ng_UI.c optional netgraph_UI netgraph/ng_async.c optional netgraph_async netgraph/ng_atmllc.c optional netgraph_atmllc netgraph/ng_base.c optional netgraph netgraph/ng_bpf.c optional netgraph_bpf netgraph/ng_bridge.c optional netgraph_bridge netgraph/ng_cisco.c optional netgraph_cisco netgraph/ng_device.c optional netgraph_device netgraph/ng_echo.c optional netgraph_echo netgraph/ng_eiface.c optional netgraph_eiface netgraph/ng_ether.c optional netgraph_ether netgraph/ng_fec.c optional netgraph_fec netgraph/ng_frame_relay.c optional netgraph_frame_relay netgraph/ng_gif.c optional netgraph_gif netgraph/ng_gif_demux.c optional netgraph_gif_demux netgraph/ng_hole.c optional netgraph_hole netgraph/ng_iface.c optional netgraph_iface netgraph/ng_ip_input.c optional netgraph_ip_input netgraph/ng_ipfw.c optional netgraph_ipfw netgraph/ng_ksocket.c optional netgraph_ksocket netgraph/ng_l2tp.c optional netgraph_l2tp netgraph/ng_lmi.c optional netgraph_lmi netgraph/ng_mppc.c optional netgraph_mppc_compression | \ netgraph_mppc_encryption netgraph/ng_nat.c optional netgraph_nat netgraph/ng_one2many.c optional netgraph_one2many netgraph/ng_parse.c optional netgraph netgraph/ng_ppp.c optional netgraph_ppp netgraph/ng_pppoe.c optional netgraph_pppoe netgraph/ng_pptpgre.c optional netgraph_pptpgre netgraph/ng_rfc1490.c optional netgraph_rfc1490 netgraph/ng_socket.c optional netgraph_socket netgraph/ng_split.c optional netgraph_split netgraph/ng_sppp.c optional netgraph_sppp netgraph/ng_tag.c optional netgraph_tag netgraph/ng_tcpmss.c optional netgraph_tcpmss netgraph/ng_tee.c optional netgraph_tee netgraph/ng_tty.c optional netgraph_tty netgraph/ng_vjc.c optional netgraph_vjc netinet/accf_data.c optional accept_filter_data netinet/accf_http.c optional accept_filter_http netinet/if_atm.c optional atm netinet/if_ether.c optional ether netinet/igmp.c optional inet netinet/in.c optional inet netinet/ip_carp.c optional carp netinet/in_gif.c optional gif inet netinet/ip_gre.c optional gre inet netinet/ip_id.c optional inet netinet/in_pcb.c optional inet netinet/in_proto.c optional inet \ compile-with "${NORMAL_C} -I$S/contrib/pf" netinet/in_rmx.c optional inet netinet/ip_divert.c optional ipdivert netinet/ip_dummynet.c optional dummynet netinet/ip_ecn.c optional inet | inet6 netinet/ip_encap.c optional inet | inet6 netinet/ip_fastfwd.c optional inet netinet/ip_fw2.c optional ipfirewall netinet/ip_fw_pfil.c optional ipfirewall netinet/ip_icmp.c optional inet netinet/ip_input.c optional inet netinet/ip_ipsec.c optional ipsec netinet/ip_ipsec.c optional fast_ipsec netinet/ip_mroute.c optional mrouting netinet/ip_options.c optional inet netinet/ip_output.c optional inet netinet/raw_ip.c optional inet netinet/sctp_usrreq.c optional inet inet6 sctp netinet/sctp_pcb.c optional inet inet6 sctp netinet/sctputil.c optional inet inet6 sctp netinet/sctp_bsd_addr.c optional inet inet6 sctp netinet/sctp_timer.c optional inet inet6 sctp netinet/sctp_input.c optional inet inet6 sctp netinet/sctp_output.c optional inet inet6 sctp netinet/sctp_indata.c optional inet inet6 sctp netinet/sctp_asconf.c optional inet inet6 sctp netinet/sctp_peeloff.c optional inet inet6 sctp netinet/sctp_crc32.c optional inet inet6 sctp netinet/sctp_auth.c optional inet inet6 sctp netinet/tcp_debug.c optional tcpdebug netinet/tcp_hostcache.c optional inet netinet/tcp_input.c optional inet netinet/tcp_output.c optional inet netinet/tcp_sack.c optional inet netinet/tcp_subr.c optional inet netinet/tcp_syncache.c optional inet netinet/tcp_timer.c optional inet netinet/tcp_usrreq.c optional inet netinet/udp_usrreq.c optional inet netinet/libalias/alias.c optional libalias netinet/libalias/alias_db.c optional libalias netinet/libalias/alias_mod.c optional libalias netinet/libalias/alias_old.c optional libalias netinet/libalias/alias_proxy.c optional libalias netinet/libalias/alias_util.c optional libalias netinet6/ah_aesxcbcmac.c optional ipsec netinet6/ah_core.c optional ipsec netinet6/ah_input.c optional ipsec netinet6/ah_output.c optional ipsec netinet6/dest6.c optional inet6 netinet6/esp_aesctr.c optional ipsec ipsec_esp netinet6/esp_core.c optional ipsec ipsec_esp netinet6/esp_input.c optional ipsec ipsec_esp netinet6/esp_output.c optional ipsec ipsec_esp netinet6/esp_rijndael.c optional ipsec ipsec_esp netinet6/frag6.c optional inet6 netinet6/icmp6.c optional inet6 netinet6/in6.c optional inet6 netinet6/in6_cksum.c optional inet6 netinet6/in6_gif.c optional gif inet6 netinet6/in6_ifattach.c optional inet6 netinet6/in6_pcb.c optional inet6 netinet6/in6_proto.c optional inet6 netinet6/in6_rmx.c optional inet6 netinet6/in6_src.c optional inet6 netinet6/ip6_forward.c optional inet6 netinet6/ip6_id.c optional inet6 netinet6/ip6_input.c optional inet6 netinet6/ip6_mroute.c optional inet6 netinet6/ip6_output.c optional inet6 netinet6/ipcomp_core.c optional ipsec netinet6/ipcomp_input.c optional ipsec netinet6/ipcomp_output.c optional ipsec netinet6/ipsec.c optional ipsec netinet6/mld6.c optional inet6 netinet6/nd6.c optional inet6 netinet6/nd6_nbr.c optional inet6 netinet6/nd6_rtr.c optional inet6 netinet6/raw_ip6.c optional inet6 netinet6/route6.c optional inet6 netinet6/scope6.c optional inet6 netinet6/sctp6_usrreq.c optional inet6 sctp netinet6/udp6_output.c optional inet6 netinet6/udp6_usrreq.c optional inet6 netipsec/ipsec.c optional fast_ipsec netipsec/ipsec_input.c optional fast_ipsec netipsec/ipsec_mbuf.c optional fast_ipsec netipsec/ipsec_output.c optional fast_ipsec netipsec/key.c optional fast_ipsec netipsec/key_debug.c optional fast_ipsec netipsec/keysock.c optional fast_ipsec netipsec/xform_ah.c optional fast_ipsec netipsec/xform_esp.c optional fast_ipsec netipsec/xform_ipcomp.c optional fast_ipsec netipsec/xform_ipip.c optional fast_ipsec netipsec/xform_tcp.c optional fast_ipsec tcp_signature netipx/ipx.c optional ipx netipx/ipx_cksum.c optional ipx netipx/ipx_input.c optional ipx netipx/ipx_ip.c optional ipx netipx/ipx_outputfl.c optional ipx netipx/ipx_pcb.c optional ipx netipx/ipx_proto.c optional ipx netipx/ipx_usrreq.c optional ipx netipx/spx_debug.c optional ipx netipx/spx_usrreq.c optional ipx netkey/key.c optional ipsec netkey/key_debug.c optional ipsec netkey/keydb.c optional ipsec netkey/keysock.c optional ipsec netnatm/natm.c optional natm netnatm/natm_pcb.c optional natm netnatm/natm_proto.c optional natm netncp/ncp_conn.c optional ncp netncp/ncp_crypt.c optional ncp netncp/ncp_login.c optional ncp netncp/ncp_mod.c optional ncp netncp/ncp_ncp.c optional ncp netncp/ncp_nls.c optional ncp netncp/ncp_rq.c optional ncp netncp/ncp_sock.c optional ncp netncp/ncp_subr.c optional ncp netsmb/smb_conn.c optional netsmb netsmb/smb_crypt.c optional netsmb netsmb/smb_dev.c optional netsmb netsmb/smb_iod.c optional netsmb netsmb/smb_rq.c optional netsmb netsmb/smb_smb.c optional netsmb netsmb/smb_subr.c optional netsmb netsmb/smb_trantcp.c optional netsmb netsmb/smb_usr.c optional netsmb nfs/nfs_common.c optional nfsclient | nfsserver nfs4client/nfs4_dev.c optional nfsclient nfs4client/nfs4_idmap.c optional nfsclient nfs4client/nfs4_socket.c optional nfsclient nfs4client/nfs4_subs.c optional nfsclient nfs4client/nfs4_vfs_subs.c optional nfsclient nfs4client/nfs4_vfsops.c optional nfsclient nfs4client/nfs4_vn_subs.c optional nfsclient nfs4client/nfs4_vnops.c optional nfsclient nfsclient/bootp_subr.c optional bootp nfsclient nfsclient/krpc_subr.c optional bootp nfsclient nfsclient/nfs_bio.c optional nfsclient nfsclient/nfs_diskless.c optional nfsclient nfs_root nfsclient/nfs_node.c optional nfsclient nfsclient/nfs_socket.c optional nfsclient nfsclient/nfs_subs.c optional nfsclient nfsclient/nfs_nfsiod.c optional nfsclient nfsclient/nfs_vfsops.c optional nfsclient nfsclient/nfs_vnops.c optional nfsclient nfsclient/nfs_lock.c optional nfsclient nfsserver/nfs_serv.c optional nfsserver nfsserver/nfs_srvsock.c optional nfsserver nfsserver/nfs_srvcache.c optional nfsserver nfsserver/nfs_srvsubs.c optional nfsserver nfsserver/nfs_syscalls.c optional nfsserver # crypto support opencrypto/cast.c optional crypto | ipsec ipsec_esp opencrypto/criov.c optional crypto opencrypto/crypto.c optional crypto opencrypto/cryptodev.c optional cryptodev opencrypto/cryptosoft.c optional crypto opencrypto/deflate.c optional crypto opencrypto/rmd160.c optional crypto | ipsec opencrypto/skipjack.c optional crypto opencrypto/xform.c optional crypto pci/agp.c optional agp pci pci/agp_if.m optional agp pci pci/alpm.c optional alpm pci pci/amdpm.c optional amdpm pci | nfpm pci pci/amdsmb.c optional amdsmb pci pci/if_mn.c optional mn pci pci/if_pcn.c optional pcn pci pci/if_rl.c optional rl pci pci/if_sf.c optional sf pci pci/if_sis.c optional sis pci pci/if_ste.c optional ste pci pci/if_tl.c optional tl pci pci/if_vr.c optional vr pci pci/if_wb.c optional wb pci pci/if_xl.c optional xl pci pci/intpm.c optional intpm pci pci/ncr.c optional ncr pci pci/nfsmb.c optional nfsmb pci pci/viapm.c optional viapm pci pci/xrpu.c optional xrpu pci -posix4/ksched.c optional _kposix_priority_scheduling -posix4/p1003_1b.c standard -posix4/posix4_mib.c standard rpc/rpcclnt.c optional nfsclient security/audit/audit.c optional audit security/audit/audit_arg.c optional audit security/audit/audit_bsm.c optional audit security/audit/audit_bsm_klib.c optional audit security/audit/audit_bsm_token.c optional audit security/audit/audit_pipe.c optional audit security/audit/audit_syscalls.c standard security/audit/audit_trigger.c optional audit security/audit/audit_worker.c optional audit security/mac/mac_inet.c optional mac inet security/mac/mac_label.c optional mac security/mac/mac_net.c optional mac security/mac/mac_pipe.c optional mac security/mac/mac_posix_sem.c optional mac security/mac/mac_priv.c optional mac security/mac/mac_process.c optional mac security/mac/mac_socket.c optional mac security/mac/mac_system.c optional mac security/mac/mac_sysv_msg.c optional mac security/mac/mac_sysv_sem.c optional mac security/mac/mac_sysv_shm.c optional mac security/mac/mac_vfs.c optional mac security/mac_biba/mac_biba.c optional mac_biba security/mac_bsdextended/mac_bsdextended.c optional mac_bsdextended security/mac_ifoff/mac_ifoff.c optional mac_ifoff security/mac_lomac/mac_lomac.c optional mac_lomac security/mac_mls/mac_mls.c optional mac_mls security/mac_none/mac_none.c optional mac_none security/mac_partition/mac_partition.c optional mac_partition security/mac_portacl/mac_portacl.c optional mac_portacl security/mac_seeotheruids/mac_seeotheruids.c optional mac_seeotheruids security/mac_stub/mac_stub.c optional mac_stub security/mac_test/mac_test.c optional mac_test ufs/ffs/ffs_alloc.c optional ffs ufs/ffs/ffs_balloc.c optional ffs ufs/ffs/ffs_inode.c optional ffs ufs/ffs/ffs_snapshot.c optional ffs ufs/ffs/ffs_softdep.c optional ffs ufs/ffs/ffs_subr.c optional ffs ufs/ffs/ffs_tables.c optional ffs ufs/ffs/ffs_vfsops.c optional ffs ufs/ffs/ffs_vnops.c optional ffs ufs/ffs/ffs_rawread.c optional directio ufs/ufs/ufs_acl.c optional ffs ufs/ufs/ufs_bmap.c optional ffs ufs/ufs/ufs_dirhash.c optional ffs ufs/ufs/ufs_extattr.c optional ffs ufs/ufs/ufs_gjournal.c optional ffs ufs/ufs/ufs_inode.c optional ffs ufs/ufs/ufs_lookup.c optional ffs ufs/ufs/ufs_quota.c optional ffs ufs/ufs/ufs_vfsops.c optional ffs ufs/ufs/ufs_vnops.c optional ffs vm/default_pager.c standard vm/device_pager.c standard vm/phys_pager.c standard vm/redzone.c optional DEBUG_REDZONE vm/swap_pager.c standard vm/uma_core.c standard vm/uma_dbg.c standard vm/vm_contig.c standard vm/memguard.c optional DEBUG_MEMGUARD vm/vm_fault.c standard vm/vm_glue.c standard vm/vm_init.c standard vm/vm_kern.c standard vm/vm_map.c standard vm/vm_meter.c standard vm/vm_mmap.c standard vm/vm_object.c standard vm/vm_page.c standard vm/vm_pageout.c standard vm/vm_pageq.c standard vm/vm_pager.c standard vm/vm_unix.c standard vm/vm_zeroidle.c standard vm/vnode_pager.c standard # gnu/fs/xfs/xfs_alloc.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" \ warning "kernel contains GPL contaminated xfs filesystem" gnu/fs/xfs/xfs_alloc_btree.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_bit.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_bmap.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_bmap_btree.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_btree.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_buf_item.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_da_btree.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_dir.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_dir2.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_dir2_block.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_dir2_data.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_dir2_leaf.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_dir2_node.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_dir2_sf.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_dir2_trace.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_dir_leaf.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_error.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_extfree_item.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_fsops.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_ialloc.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_ialloc_btree.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_inode.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_inode_item.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_iocore.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_itable.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_dfrag.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_log.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_log_recover.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_mount.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_rename.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_trans.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_trans_ail.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_trans_buf.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_trans_extfree.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_trans_inode.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_trans_item.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_utils.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_vfsops.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_vnodeops.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_rw.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_attr_leaf.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_attr.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_dmops.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_qmops.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_iget.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/xfs_freebsd_iget.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/xfs_mountops.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/xfs_vnops.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/xfs_frw.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/xfs_buf.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/xfs_globals.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/xfs_dmistubs.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/xfs_super.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/xfs_stats.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/xfs_vfs.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/xfs_vnode.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/xfs_sysctl.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/xfs_fs_subr.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/xfs_ioctl.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/support/debug.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/support/ktrace.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/support/mrlock.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/support/uuid.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/FreeBSD/support/kmem.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_iomap.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" gnu/fs/xfs/xfs_behavior.c optional xfs \ compile-with "${NORMAL_C} -I$S/gnu/fs/xfs/FreeBSD -I$S/gnu/fs/xfs/FreeBSD/support -I$S/gnu/fs/xfs" Index: head/sys/i386/ibcs2/ibcs2_proto.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_proto.h (revision 164183) +++ head/sys/i386/ibcs2/ibcs2_proto.h (revision 164184) @@ -1,411 +1,411 @@ /* * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ * created from FreeBSD: src/sys/i386/ibcs2/syscalls.master,v 1.28 2006/07/28 19:05:27 jhb Exp */ #ifndef _IBCS2_SYSPROTO_H_ #define _IBCS2_SYSPROTO_H_ #include #include -#include +#include #include #include struct proc; struct thread; #define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \ 0 : sizeof(register_t) - sizeof(t)) #if BYTE_ORDER == LITTLE_ENDIAN #define PADL_(t) 0 #define PADR_(t) PAD_(t) #else #define PADL_(t) PAD_(t) #define PADR_(t) 0 #endif struct ibcs2_read_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; char nbytes_l_[PADL_(u_int)]; u_int nbytes; char nbytes_r_[PADR_(u_int)]; }; struct ibcs2_open_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; }; struct ibcs2_wait_args { char a1_l_[PADL_(int)]; int a1; char a1_r_[PADR_(int)]; char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)]; char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)]; }; struct ibcs2_creat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; }; struct ibcs2_unlink_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct ibcs2_execv_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char argp_l_[PADL_(char **)]; char ** argp; char argp_r_[PADR_(char **)]; }; struct ibcs2_chdir_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct ibcs2_time_args { char tp_l_[PADL_(ibcs2_time_t *)]; ibcs2_time_t * tp; char tp_r_[PADR_(ibcs2_time_t *)]; }; struct ibcs2_mknod_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; char dev_l_[PADL_(int)]; int dev; char dev_r_[PADR_(int)]; }; struct ibcs2_chmod_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; }; struct ibcs2_chown_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char uid_l_[PADL_(int)]; int uid; char uid_r_[PADR_(int)]; char gid_l_[PADL_(int)]; int gid; char gid_r_[PADR_(int)]; }; struct ibcs2_stat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char st_l_[PADL_(struct ibcs2_stat *)]; struct ibcs2_stat * st; char st_r_[PADR_(struct ibcs2_stat *)]; }; struct ibcs2_lseek_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char offset_l_[PADL_(long)]; long offset; char offset_r_[PADR_(long)]; char whence_l_[PADL_(int)]; int whence; char whence_r_[PADR_(int)]; }; struct ibcs2_mount_args { char special_l_[PADL_(char *)]; char * special; char special_r_[PADR_(char *)]; char dir_l_[PADL_(char *)]; char * dir; char dir_r_[PADR_(char *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; char fstype_l_[PADL_(int)]; int fstype; char fstype_r_[PADR_(int)]; char data_l_[PADL_(char *)]; char * data; char data_r_[PADR_(char *)]; char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)]; }; struct ibcs2_umount_args { char name_l_[PADL_(char *)]; char * name; char name_r_[PADR_(char *)]; }; struct ibcs2_setuid_args { char uid_l_[PADL_(int)]; int uid; char uid_r_[PADR_(int)]; }; struct ibcs2_stime_args { char timep_l_[PADL_(long *)]; long * timep; char timep_r_[PADR_(long *)]; }; struct ibcs2_alarm_args { char sec_l_[PADL_(unsigned)]; unsigned sec; char sec_r_[PADR_(unsigned)]; }; struct ibcs2_fstat_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char st_l_[PADL_(struct ibcs2_stat *)]; struct ibcs2_stat * st; char st_r_[PADR_(struct ibcs2_stat *)]; }; struct ibcs2_pause_args { register_t dummy; }; struct ibcs2_utime_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char buf_l_[PADL_(struct ibcs2_utimbuf *)]; struct ibcs2_utimbuf * buf; char buf_r_[PADR_(struct ibcs2_utimbuf *)]; }; struct ibcs2_stty_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char buf_l_[PADL_(struct sgttyb *)]; struct sgttyb * buf; char buf_r_[PADR_(struct sgttyb *)]; }; struct ibcs2_gtty_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char buf_l_[PADL_(struct sgttyb *)]; struct sgttyb * buf; char buf_r_[PADR_(struct sgttyb *)]; }; struct ibcs2_access_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct ibcs2_nice_args { char incr_l_[PADL_(int)]; int incr; char incr_r_[PADR_(int)]; }; struct ibcs2_statfs_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char buf_l_[PADL_(struct ibcs2_statfs *)]; struct ibcs2_statfs * buf; char buf_r_[PADR_(struct ibcs2_statfs *)]; char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)]; char fstype_l_[PADL_(int)]; int fstype; char fstype_r_[PADR_(int)]; }; struct ibcs2_kill_args { char pid_l_[PADL_(int)]; int pid; char pid_r_[PADR_(int)]; char signo_l_[PADL_(int)]; int signo; char signo_r_[PADR_(int)]; }; struct ibcs2_fstatfs_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char buf_l_[PADL_(struct ibcs2_statfs *)]; struct ibcs2_statfs * buf; char buf_r_[PADR_(struct ibcs2_statfs *)]; char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)]; char fstype_l_[PADL_(int)]; int fstype; char fstype_r_[PADR_(int)]; }; struct ibcs2_pgrpsys_args { char type_l_[PADL_(int)]; int type; char type_r_[PADR_(int)]; char dummy_l_[PADL_(caddr_t)]; caddr_t dummy; char dummy_r_[PADR_(caddr_t)]; char pid_l_[PADL_(int)]; int pid; char pid_r_[PADR_(int)]; char pgid_l_[PADL_(int)]; int pgid; char pgid_r_[PADR_(int)]; }; struct ibcs2_xenix_args { char a1_l_[PADL_(int)]; int a1; char a1_r_[PADR_(int)]; char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)]; char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)]; char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)]; char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)]; }; struct ibcs2_times_args { char tp_l_[PADL_(struct tms *)]; struct tms * tp; char tp_r_[PADR_(struct tms *)]; }; struct ibcs2_plock_args { char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; }; struct ibcs2_setgid_args { char gid_l_[PADL_(int)]; int gid; char gid_r_[PADR_(int)]; }; struct ibcs2_sigsys_args { char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)]; char fp_l_[PADL_(ibcs2_sig_t)]; ibcs2_sig_t fp; char fp_r_[PADR_(ibcs2_sig_t)]; }; struct ibcs2_msgsys_args { char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)]; char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)]; char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)]; char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)]; char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)]; char a6_l_[PADL_(int)]; int a6; char a6_r_[PADR_(int)]; }; struct ibcs2_sysi86_args { char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char arg_l_[PADL_(int *)]; int * arg; char arg_r_[PADR_(int *)]; }; struct ibcs2_shmsys_args { char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)]; char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)]; char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)]; char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)]; }; struct ibcs2_semsys_args { char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)]; char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)]; char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)]; char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)]; char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)]; }; struct ibcs2_ioctl_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char data_l_[PADL_(caddr_t)]; caddr_t data; char data_r_[PADR_(caddr_t)]; }; struct ibcs2_uadmin_args { char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char func_l_[PADL_(int)]; int func; char func_r_[PADR_(int)]; char data_l_[PADL_(caddr_t)]; caddr_t data; char data_r_[PADR_(caddr_t)]; }; struct ibcs2_utssys_args { char a1_l_[PADL_(int)]; int a1; char a1_r_[PADR_(int)]; char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)]; char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)]; }; struct ibcs2_execve_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char argp_l_[PADL_(char **)]; char ** argp; char argp_r_[PADR_(char **)]; char envp_l_[PADL_(char **)]; char ** envp; char envp_r_[PADR_(char **)]; }; struct ibcs2_fcntl_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char arg_l_[PADL_(char *)]; char * arg; char arg_r_[PADR_(char *)]; }; struct ibcs2_ulimit_args { char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char newlimit_l_[PADL_(int)]; int newlimit; char newlimit_r_[PADR_(int)]; }; struct ibcs2_rmdir_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct ibcs2_mkdir_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; }; struct ibcs2_getdents_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; char nbytes_l_[PADL_(int)]; int nbytes; char nbytes_r_[PADR_(int)]; }; struct ibcs2_sysfs_args { char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char d1_l_[PADL_(caddr_t)]; caddr_t d1; char d1_r_[PADR_(caddr_t)]; char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; }; struct ibcs2_getmsg_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char ctl_l_[PADL_(struct ibcs2_stropts *)]; struct ibcs2_stropts * ctl; char ctl_r_[PADR_(struct ibcs2_stropts *)]; char dat_l_[PADL_(struct ibcs2_stropts *)]; struct ibcs2_stropts * dat; char dat_r_[PADR_(struct ibcs2_stropts *)]; char flags_l_[PADL_(int *)]; int * flags; char flags_r_[PADR_(int *)]; }; struct ibcs2_putmsg_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char ctl_l_[PADL_(struct ibcs2_stropts *)]; struct ibcs2_stropts * ctl; char ctl_r_[PADR_(struct ibcs2_stropts *)]; char dat_l_[PADL_(struct ibcs2_stropts *)]; struct ibcs2_stropts * dat; char dat_r_[PADR_(struct ibcs2_stropts *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct ibcs2_secure_args { char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char a1_l_[PADL_(int)]; int a1; char a1_r_[PADR_(int)]; char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)]; char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)]; char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)]; char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)]; }; struct ibcs2_symlink_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char link_l_[PADL_(char *)]; char * link; char link_r_[PADR_(char *)]; }; struct ibcs2_lstat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char st_l_[PADL_(struct ibcs2_stat *)]; struct ibcs2_stat * st; char st_r_[PADR_(struct ibcs2_stat *)]; }; struct ibcs2_readlink_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; char count_l_[PADL_(int)]; int count; char count_r_[PADR_(int)]; }; struct ibcs2_isc_args { register_t dummy; }; int ibcs2_read(struct thread *, struct ibcs2_read_args *); int ibcs2_open(struct thread *, struct ibcs2_open_args *); int ibcs2_wait(struct thread *, struct ibcs2_wait_args *); int ibcs2_creat(struct thread *, struct ibcs2_creat_args *); int ibcs2_unlink(struct thread *, struct ibcs2_unlink_args *); int ibcs2_execv(struct thread *, struct ibcs2_execv_args *); int ibcs2_chdir(struct thread *, struct ibcs2_chdir_args *); int ibcs2_time(struct thread *, struct ibcs2_time_args *); int ibcs2_mknod(struct thread *, struct ibcs2_mknod_args *); int ibcs2_chmod(struct thread *, struct ibcs2_chmod_args *); int ibcs2_chown(struct thread *, struct ibcs2_chown_args *); int ibcs2_stat(struct thread *, struct ibcs2_stat_args *); int ibcs2_lseek(struct thread *, struct ibcs2_lseek_args *); int ibcs2_mount(struct thread *, struct ibcs2_mount_args *); int ibcs2_umount(struct thread *, struct ibcs2_umount_args *); int ibcs2_setuid(struct thread *, struct ibcs2_setuid_args *); int ibcs2_stime(struct thread *, struct ibcs2_stime_args *); int ibcs2_alarm(struct thread *, struct ibcs2_alarm_args *); int ibcs2_fstat(struct thread *, struct ibcs2_fstat_args *); int ibcs2_pause(struct thread *, struct ibcs2_pause_args *); int ibcs2_utime(struct thread *, struct ibcs2_utime_args *); int ibcs2_stty(struct thread *, struct ibcs2_stty_args *); int ibcs2_gtty(struct thread *, struct ibcs2_gtty_args *); int ibcs2_access(struct thread *, struct ibcs2_access_args *); int ibcs2_nice(struct thread *, struct ibcs2_nice_args *); int ibcs2_statfs(struct thread *, struct ibcs2_statfs_args *); int ibcs2_kill(struct thread *, struct ibcs2_kill_args *); int ibcs2_fstatfs(struct thread *, struct ibcs2_fstatfs_args *); int ibcs2_pgrpsys(struct thread *, struct ibcs2_pgrpsys_args *); int ibcs2_xenix(struct thread *, struct ibcs2_xenix_args *); int ibcs2_times(struct thread *, struct ibcs2_times_args *); int ibcs2_plock(struct thread *, struct ibcs2_plock_args *); int ibcs2_setgid(struct thread *, struct ibcs2_setgid_args *); int ibcs2_sigsys(struct thread *, struct ibcs2_sigsys_args *); int ibcs2_msgsys(struct thread *, struct ibcs2_msgsys_args *); int ibcs2_sysi86(struct thread *, struct ibcs2_sysi86_args *); int ibcs2_shmsys(struct thread *, struct ibcs2_shmsys_args *); int ibcs2_semsys(struct thread *, struct ibcs2_semsys_args *); int ibcs2_ioctl(struct thread *, struct ibcs2_ioctl_args *); int ibcs2_uadmin(struct thread *, struct ibcs2_uadmin_args *); int ibcs2_utssys(struct thread *, struct ibcs2_utssys_args *); int ibcs2_execve(struct thread *, struct ibcs2_execve_args *); int ibcs2_fcntl(struct thread *, struct ibcs2_fcntl_args *); int ibcs2_ulimit(struct thread *, struct ibcs2_ulimit_args *); int ibcs2_rmdir(struct thread *, struct ibcs2_rmdir_args *); int ibcs2_mkdir(struct thread *, struct ibcs2_mkdir_args *); int ibcs2_getdents(struct thread *, struct ibcs2_getdents_args *); int ibcs2_sysfs(struct thread *, struct ibcs2_sysfs_args *); int ibcs2_getmsg(struct thread *, struct ibcs2_getmsg_args *); int ibcs2_putmsg(struct thread *, struct ibcs2_putmsg_args *); int ibcs2_secure(struct thread *, struct ibcs2_secure_args *); int ibcs2_symlink(struct thread *, struct ibcs2_symlink_args *); int ibcs2_lstat(struct thread *, struct ibcs2_lstat_args *); int ibcs2_readlink(struct thread *, struct ibcs2_readlink_args *); int ibcs2_isc(struct thread *, struct ibcs2_isc_args *); #ifdef COMPAT_43 #endif /* COMPAT_43 */ #ifdef COMPAT_FREEBSD4 #endif /* COMPAT_FREEBSD4 */ #define IBCS2_SYS_AUE_ibcs2_read AUE_NULL #define IBCS2_SYS_AUE_ibcs2_open AUE_OPEN_RWTC #define IBCS2_SYS_AUE_ibcs2_wait AUE_WAIT4 #define IBCS2_SYS_AUE_ibcs2_creat AUE_CREAT #define IBCS2_SYS_AUE_ibcs2_unlink AUE_UNLINK #define IBCS2_SYS_AUE_ibcs2_execv AUE_EXECVE #define IBCS2_SYS_AUE_ibcs2_chdir AUE_CHDIR #define IBCS2_SYS_AUE_ibcs2_time AUE_NULL #define IBCS2_SYS_AUE_ibcs2_mknod AUE_MKNOD #define IBCS2_SYS_AUE_ibcs2_chmod AUE_CHMOD #define IBCS2_SYS_AUE_ibcs2_chown AUE_CHOWN #define IBCS2_SYS_AUE_ibcs2_stat AUE_STAT #define IBCS2_SYS_AUE_ibcs2_lseek AUE_LSEEK #define IBCS2_SYS_AUE_ibcs2_mount AUE_MOUNT #define IBCS2_SYS_AUE_ibcs2_umount AUE_UMOUNT #define IBCS2_SYS_AUE_ibcs2_setuid AUE_SETUID #define IBCS2_SYS_AUE_ibcs2_stime AUE_SETTIMEOFDAY #define IBCS2_SYS_AUE_ibcs2_alarm AUE_NULL #define IBCS2_SYS_AUE_ibcs2_fstat AUE_FSTAT #define IBCS2_SYS_AUE_ibcs2_pause AUE_NULL #define IBCS2_SYS_AUE_ibcs2_utime AUE_NULL #define IBCS2_SYS_AUE_ibcs2_stty AUE_NULL #define IBCS2_SYS_AUE_ibcs2_gtty AUE_NULL #define IBCS2_SYS_AUE_ibcs2_access AUE_ACCESS #define IBCS2_SYS_AUE_ibcs2_nice AUE_NICE #define IBCS2_SYS_AUE_ibcs2_statfs AUE_STATFS #define IBCS2_SYS_AUE_ibcs2_kill AUE_KILL #define IBCS2_SYS_AUE_ibcs2_fstatfs AUE_FSTATFS #define IBCS2_SYS_AUE_ibcs2_pgrpsys AUE_NULL #define IBCS2_SYS_AUE_ibcs2_xenix AUE_NULL #define IBCS2_SYS_AUE_ibcs2_times AUE_NULL #define IBCS2_SYS_AUE_ibcs2_plock AUE_NULL #define IBCS2_SYS_AUE_ibcs2_setgid AUE_SETGID #define IBCS2_SYS_AUE_ibcs2_sigsys AUE_NULL #define IBCS2_SYS_AUE_ibcs2_msgsys AUE_MSGSYS #define IBCS2_SYS_AUE_ibcs2_sysi86 AUE_NULL #define IBCS2_SYS_AUE_ibcs2_shmsys AUE_SHMSYS #define IBCS2_SYS_AUE_ibcs2_semsys AUE_SEMSYS #define IBCS2_SYS_AUE_ibcs2_ioctl AUE_IOCTL #define IBCS2_SYS_AUE_ibcs2_uadmin AUE_NULL #define IBCS2_SYS_AUE_ibcs2_utssys AUE_NULL #define IBCS2_SYS_AUE_ibcs2_execve AUE_EXECVE #define IBCS2_SYS_AUE_ibcs2_fcntl AUE_FCNTL #define IBCS2_SYS_AUE_ibcs2_ulimit AUE_NULL #define IBCS2_SYS_AUE_ibcs2_rmdir AUE_RMDIR #define IBCS2_SYS_AUE_ibcs2_mkdir AUE_MKDIR #define IBCS2_SYS_AUE_ibcs2_getdents AUE_GETDIRENTRIES #define IBCS2_SYS_AUE_ibcs2_sysfs AUE_NULL #define IBCS2_SYS_AUE_ibcs2_getmsg AUE_GETMSG #define IBCS2_SYS_AUE_ibcs2_putmsg AUE_PUTMSG #define IBCS2_SYS_AUE_ibcs2_secure AUE_NULL #define IBCS2_SYS_AUE_ibcs2_symlink AUE_SYMLINK #define IBCS2_SYS_AUE_ibcs2_lstat AUE_LSTAT #define IBCS2_SYS_AUE_ibcs2_readlink AUE_READLINK #define IBCS2_SYS_AUE_ibcs2_isc AUE_NULL #undef PAD_ #undef PADL_ #undef PADR_ #endif /* !_IBCS2_SYSPROTO_H_ */ Index: head/sys/i386/ibcs2/ibcs2_xenix.h =================================================================== --- head/sys/i386/ibcs2/ibcs2_xenix.h (revision 164183) +++ head/sys/i386/ibcs2/ibcs2_xenix.h (revision 164184) @@ -1,147 +1,147 @@ /* * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ * created from FreeBSD: src/sys/i386/ibcs2/syscalls.xenix,v 1.14 2006/07/28 19:05:27 jhb Exp */ #ifndef _IBCS2_XENIX_H_ #define _IBCS2_XENIX_H_ #include #include -#include +#include #include #include struct proc; struct thread; #define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \ 0 : sizeof(register_t) - sizeof(t)) #if BYTE_ORDER == LITTLE_ENDIAN #define PADL_(t) 0 #define PADR_(t) PAD_(t) #else #define PADL_(t) PAD_(t) #define PADR_(t) 0 #endif struct xenix_rdchk_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; }; struct xenix_chsize_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char size_l_[PADL_(long)]; long size; char size_r_[PADR_(long)]; }; struct xenix_ftime_args { char tp_l_[PADL_(struct timeb *)]; struct timeb * tp; char tp_r_[PADR_(struct timeb *)]; }; struct xenix_nap_args { char millisec_l_[PADL_(int)]; int millisec; char millisec_r_[PADR_(int)]; }; struct xenix_scoinfo_args { register_t dummy; }; struct xenix_eaccess_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct ibcs2_sigaction_args { char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)]; char act_l_[PADL_(struct ibcs2_sigaction *)]; struct ibcs2_sigaction * act; char act_r_[PADR_(struct ibcs2_sigaction *)]; char oact_l_[PADL_(struct ibcs2_sigaction *)]; struct ibcs2_sigaction * oact; char oact_r_[PADR_(struct ibcs2_sigaction *)]; }; struct ibcs2_sigprocmask_args { char how_l_[PADL_(int)]; int how; char how_r_[PADR_(int)]; char set_l_[PADL_(ibcs2_sigset_t *)]; ibcs2_sigset_t * set; char set_r_[PADR_(ibcs2_sigset_t *)]; char oset_l_[PADL_(ibcs2_sigset_t *)]; ibcs2_sigset_t * oset; char oset_r_[PADR_(ibcs2_sigset_t *)]; }; struct ibcs2_sigpending_args { char mask_l_[PADL_(ibcs2_sigset_t *)]; ibcs2_sigset_t * mask; char mask_r_[PADR_(ibcs2_sigset_t *)]; }; struct ibcs2_sigsuspend_args { char mask_l_[PADL_(ibcs2_sigset_t *)]; ibcs2_sigset_t * mask; char mask_r_[PADR_(ibcs2_sigset_t *)]; }; struct ibcs2_getgroups_args { char gidsetsize_l_[PADL_(int)]; int gidsetsize; char gidsetsize_r_[PADR_(int)]; char gidset_l_[PADL_(ibcs2_gid_t *)]; ibcs2_gid_t * gidset; char gidset_r_[PADR_(ibcs2_gid_t *)]; }; struct ibcs2_setgroups_args { char gidsetsize_l_[PADL_(int)]; int gidsetsize; char gidsetsize_r_[PADR_(int)]; char gidset_l_[PADL_(ibcs2_gid_t *)]; ibcs2_gid_t * gidset; char gidset_r_[PADR_(ibcs2_gid_t *)]; }; struct ibcs2_sysconf_args { char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)]; }; struct ibcs2_pathconf_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)]; }; struct ibcs2_fpathconf_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)]; }; struct ibcs2_rename_args { char from_l_[PADL_(char *)]; char * from; char from_r_[PADR_(char *)]; char to_l_[PADL_(char *)]; char * to; char to_r_[PADR_(char *)]; }; struct xenix_utsname_args { char addr_l_[PADL_(long)]; long addr; char addr_r_[PADR_(long)]; }; int xenix_rdchk(struct thread *, struct xenix_rdchk_args *); int xenix_chsize(struct thread *, struct xenix_chsize_args *); int xenix_ftime(struct thread *, struct xenix_ftime_args *); int xenix_nap(struct thread *, struct xenix_nap_args *); int xenix_scoinfo(struct thread *, struct xenix_scoinfo_args *); int xenix_eaccess(struct thread *, struct xenix_eaccess_args *); int ibcs2_sigaction(struct thread *, struct ibcs2_sigaction_args *); int ibcs2_sigprocmask(struct thread *, struct ibcs2_sigprocmask_args *); int ibcs2_sigpending(struct thread *, struct ibcs2_sigpending_args *); int ibcs2_sigsuspend(struct thread *, struct ibcs2_sigsuspend_args *); int ibcs2_getgroups(struct thread *, struct ibcs2_getgroups_args *); int ibcs2_setgroups(struct thread *, struct ibcs2_setgroups_args *); int ibcs2_sysconf(struct thread *, struct ibcs2_sysconf_args *); int ibcs2_pathconf(struct thread *, struct ibcs2_pathconf_args *); int ibcs2_fpathconf(struct thread *, struct ibcs2_fpathconf_args *); int ibcs2_rename(struct thread *, struct ibcs2_rename_args *); int xenix_utsname(struct thread *, struct xenix_utsname_args *); #ifdef COMPAT_43 #endif /* COMPAT_43 */ #ifdef COMPAT_FREEBSD4 #endif /* COMPAT_FREEBSD4 */ #define IBCS2_XENIX_AUE_xenix_rdchk AUE_NULL #define IBCS2_XENIX_AUE_xenix_chsize AUE_FTRUNCATE #define IBCS2_XENIX_AUE_xenix_ftime AUE_NULL #define IBCS2_XENIX_AUE_xenix_nap AUE_NULL #define IBCS2_XENIX_AUE_xenix_scoinfo AUE_NULL #define IBCS2_XENIX_AUE_xenix_eaccess AUE_EACCESS #define IBCS2_XENIX_AUE_ibcs2_sigaction AUE_NULL #define IBCS2_XENIX_AUE_ibcs2_sigprocmask AUE_NULL #define IBCS2_XENIX_AUE_ibcs2_sigpending AUE_NULL #define IBCS2_XENIX_AUE_ibcs2_sigsuspend AUE_NULL #define IBCS2_XENIX_AUE_ibcs2_getgroups AUE_GETGROUPS #define IBCS2_XENIX_AUE_ibcs2_setgroups AUE_SETGROUPS #define IBCS2_XENIX_AUE_ibcs2_sysconf AUE_NULL #define IBCS2_XENIX_AUE_ibcs2_pathconf AUE_PATHCONF #define IBCS2_XENIX_AUE_ibcs2_fpathconf AUE_FPATHCONF #define IBCS2_XENIX_AUE_ibcs2_rename AUE_RENAME #define IBCS2_XENIX_AUE_xenix_utsname AUE_NULL #undef PAD_ #undef PADL_ #undef PADR_ #endif /* !_IBCS2_XENIX_H_ */ Index: head/sys/i386/linux/linux_proto.h =================================================================== --- head/sys/i386/linux/linux_proto.h (revision 164183) +++ head/sys/i386/linux/linux_proto.h (revision 164184) @@ -1,1414 +1,1414 @@ /* * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.83 2006/10/29 14:02:39 netchild Exp */ #ifndef _LINUX_SYSPROTO_H_ #define _LINUX_SYSPROTO_H_ #include #include -#include +#include #include #include struct proc; struct thread; #define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \ 0 : sizeof(register_t) - sizeof(t)) #if BYTE_ORDER == LITTLE_ENDIAN #define PADL_(t) 0 #define PADR_(t) PAD_(t) #else #define PADL_(t) PAD_(t) #define PADR_(t) 0 #endif #define nosys linux_nosys struct linux_fork_args { register_t dummy; }; struct linux_open_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)]; }; struct linux_waitpid_args { char pid_l_[PADL_(l_pid_t)]; l_pid_t pid; char pid_r_[PADR_(l_pid_t)]; char status_l_[PADL_(l_int *)]; l_int * status; char status_r_[PADR_(l_int *)]; char options_l_[PADL_(l_int)]; l_int options; char options_r_[PADR_(l_int)]; }; struct linux_creat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)]; }; struct linux_link_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char to_l_[PADL_(char *)]; char * to; char to_r_[PADR_(char *)]; }; struct linux_unlink_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct linux_execve_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char argp_l_[PADL_(char **)]; char ** argp; char argp_r_[PADR_(char **)]; char envp_l_[PADL_(char **)]; char ** envp; char envp_r_[PADR_(char **)]; }; struct linux_chdir_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct linux_time_args { char tm_l_[PADL_(l_time_t *)]; l_time_t * tm; char tm_r_[PADR_(l_time_t *)]; }; struct linux_mknod_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)]; char dev_l_[PADL_(l_dev_t)]; l_dev_t dev; char dev_r_[PADR_(l_dev_t)]; }; struct linux_chmod_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(l_mode_t)]; l_mode_t mode; char mode_r_[PADR_(l_mode_t)]; }; struct linux_lchown16_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char uid_l_[PADL_(l_uid16_t)]; l_uid16_t uid; char uid_r_[PADR_(l_uid16_t)]; char gid_l_[PADL_(l_gid16_t)]; l_gid16_t gid; char gid_r_[PADR_(l_gid16_t)]; }; struct linux_stat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char up_l_[PADL_(struct linux_stat *)]; struct linux_stat * up; char up_r_[PADR_(struct linux_stat *)]; }; struct linux_lseek_args { char fdes_l_[PADL_(l_uint)]; l_uint fdes; char fdes_r_[PADR_(l_uint)]; char off_l_[PADL_(l_off_t)]; l_off_t off; char off_r_[PADR_(l_off_t)]; char whence_l_[PADL_(l_int)]; l_int whence; char whence_r_[PADR_(l_int)]; }; struct linux_getpid_args { register_t dummy; }; struct linux_mount_args { char specialfile_l_[PADL_(char *)]; char * specialfile; char specialfile_r_[PADR_(char *)]; char dir_l_[PADL_(char *)]; char * dir; char dir_r_[PADR_(char *)]; char filesystemtype_l_[PADL_(char *)]; char * filesystemtype; char filesystemtype_r_[PADR_(char *)]; char rwflag_l_[PADL_(l_ulong)]; l_ulong rwflag; char rwflag_r_[PADR_(l_ulong)]; char data_l_[PADL_(void *)]; void * data; char data_r_[PADR_(void *)]; }; struct linux_oldumount_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct linux_setuid16_args { char uid_l_[PADL_(l_uid16_t)]; l_uid16_t uid; char uid_r_[PADR_(l_uid16_t)]; }; struct linux_getuid16_args { register_t dummy; }; struct linux_stime_args { register_t dummy; }; struct linux_ptrace_args { char req_l_[PADL_(l_long)]; l_long req; char req_r_[PADR_(l_long)]; char pid_l_[PADL_(l_long)]; l_long pid; char pid_r_[PADR_(l_long)]; char addr_l_[PADL_(l_long)]; l_long addr; char addr_r_[PADR_(l_long)]; char data_l_[PADL_(l_long)]; l_long data; char data_r_[PADR_(l_long)]; }; struct linux_alarm_args { char secs_l_[PADL_(l_uint)]; l_uint secs; char secs_r_[PADR_(l_uint)]; }; struct linux_fstat_args { char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; char up_l_[PADL_(struct linux_stat *)]; struct linux_stat * up; char up_r_[PADR_(struct linux_stat *)]; }; struct linux_pause_args { register_t dummy; }; struct linux_utime_args { char fname_l_[PADL_(char *)]; char * fname; char fname_r_[PADR_(char *)]; char times_l_[PADL_(struct l_utimbuf *)]; struct l_utimbuf * times; char times_r_[PADR_(struct l_utimbuf *)]; }; struct linux_access_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; }; struct linux_nice_args { char inc_l_[PADL_(l_int)]; l_int inc; char inc_r_[PADR_(l_int)]; }; struct linux_kill_args { char pid_l_[PADL_(l_int)]; l_int pid; char pid_r_[PADR_(l_int)]; char signum_l_[PADL_(l_int)]; l_int signum; char signum_r_[PADR_(l_int)]; }; struct linux_rename_args { char from_l_[PADL_(char *)]; char * from; char from_r_[PADR_(char *)]; char to_l_[PADL_(char *)]; char * to; char to_r_[PADR_(char *)]; }; struct linux_mkdir_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)]; }; struct linux_rmdir_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct linux_pipe_args { char pipefds_l_[PADL_(l_ulong *)]; l_ulong * pipefds; char pipefds_r_[PADR_(l_ulong *)]; }; struct linux_times_args { char buf_l_[PADL_(struct l_times_argv *)]; struct l_times_argv * buf; char buf_r_[PADR_(struct l_times_argv *)]; }; struct linux_brk_args { char dsend_l_[PADL_(l_ulong)]; l_ulong dsend; char dsend_r_[PADR_(l_ulong)]; }; struct linux_setgid16_args { char gid_l_[PADL_(l_gid16_t)]; l_gid16_t gid; char gid_r_[PADR_(l_gid16_t)]; }; struct linux_getgid16_args { register_t dummy; }; struct linux_signal_args { char sig_l_[PADL_(l_int)]; l_int sig; char sig_r_[PADR_(l_int)]; char handler_l_[PADL_(l_handler_t)]; l_handler_t handler; char handler_r_[PADR_(l_handler_t)]; }; struct linux_geteuid16_args { register_t dummy; }; struct linux_getegid16_args { register_t dummy; }; struct linux_umount_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; }; struct linux_ioctl_args { char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; char cmd_l_[PADL_(l_uint)]; l_uint cmd; char cmd_r_[PADR_(l_uint)]; char arg_l_[PADL_(l_ulong)]; l_ulong arg; char arg_r_[PADR_(l_ulong)]; }; struct linux_fcntl_args { char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; char cmd_l_[PADL_(l_uint)]; l_uint cmd; char cmd_r_[PADR_(l_uint)]; char arg_l_[PADL_(l_ulong)]; l_ulong arg; char arg_r_[PADR_(l_ulong)]; }; struct linux_olduname_args { register_t dummy; }; struct linux_ustat_args { char dev_l_[PADL_(l_dev_t)]; l_dev_t dev; char dev_r_[PADR_(l_dev_t)]; char ubuf_l_[PADL_(struct l_ustat *)]; struct l_ustat * ubuf; char ubuf_r_[PADR_(struct l_ustat *)]; }; struct linux_getppid_args { register_t dummy; }; struct linux_sigaction_args { char sig_l_[PADL_(l_int)]; l_int sig; char sig_r_[PADR_(l_int)]; char nsa_l_[PADL_(l_osigaction_t *)]; l_osigaction_t * nsa; char nsa_r_[PADR_(l_osigaction_t *)]; char osa_l_[PADL_(l_osigaction_t *)]; l_osigaction_t * osa; char osa_r_[PADR_(l_osigaction_t *)]; }; struct linux_sgetmask_args { register_t dummy; }; struct linux_ssetmask_args { char mask_l_[PADL_(l_osigset_t)]; l_osigset_t mask; char mask_r_[PADR_(l_osigset_t)]; }; struct linux_setreuid16_args { char ruid_l_[PADL_(l_uid16_t)]; l_uid16_t ruid; char ruid_r_[PADR_(l_uid16_t)]; char euid_l_[PADL_(l_uid16_t)]; l_uid16_t euid; char euid_r_[PADR_(l_uid16_t)]; }; struct linux_setregid16_args { char rgid_l_[PADL_(l_gid16_t)]; l_gid16_t rgid; char rgid_r_[PADR_(l_gid16_t)]; char egid_l_[PADL_(l_gid16_t)]; l_gid16_t egid; char egid_r_[PADR_(l_gid16_t)]; }; struct linux_sigsuspend_args { char hist0_l_[PADL_(l_int)]; l_int hist0; char hist0_r_[PADR_(l_int)]; char hist1_l_[PADL_(l_int)]; l_int hist1; char hist1_r_[PADR_(l_int)]; char mask_l_[PADL_(l_osigset_t)]; l_osigset_t mask; char mask_r_[PADR_(l_osigset_t)]; }; struct linux_sigpending_args { char mask_l_[PADL_(l_osigset_t *)]; l_osigset_t * mask; char mask_r_[PADR_(l_osigset_t *)]; }; struct linux_sethostname_args { char hostname_l_[PADL_(char *)]; char * hostname; char hostname_r_[PADR_(char *)]; char len_l_[PADL_(u_int)]; u_int len; char len_r_[PADR_(u_int)]; }; struct linux_setrlimit_args { char resource_l_[PADL_(l_uint)]; l_uint resource; char resource_r_[PADR_(l_uint)]; char rlim_l_[PADL_(struct l_rlimit *)]; struct l_rlimit * rlim; char rlim_r_[PADR_(struct l_rlimit *)]; }; struct linux_old_getrlimit_args { char resource_l_[PADL_(l_uint)]; l_uint resource; char resource_r_[PADR_(l_uint)]; char rlim_l_[PADL_(struct l_rlimit *)]; struct l_rlimit * rlim; char rlim_r_[PADR_(struct l_rlimit *)]; }; struct linux_getgroups16_args { char gidsetsize_l_[PADL_(l_uint)]; l_uint gidsetsize; char gidsetsize_r_[PADR_(l_uint)]; char gidset_l_[PADL_(l_gid16_t *)]; l_gid16_t * gidset; char gidset_r_[PADR_(l_gid16_t *)]; }; struct linux_setgroups16_args { char gidsetsize_l_[PADL_(l_uint)]; l_uint gidsetsize; char gidsetsize_r_[PADR_(l_uint)]; char gidset_l_[PADL_(l_gid16_t *)]; l_gid16_t * gidset; char gidset_r_[PADR_(l_gid16_t *)]; }; struct linux_old_select_args { char ptr_l_[PADL_(struct l_old_select_argv *)]; struct l_old_select_argv * ptr; char ptr_r_[PADR_(struct l_old_select_argv *)]; }; struct linux_symlink_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char to_l_[PADL_(char *)]; char * to; char to_r_[PADR_(char *)]; }; struct linux_lstat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char up_l_[PADL_(struct ostat *)]; struct ostat * up; char up_r_[PADR_(struct ostat *)]; }; struct linux_readlink_args { char name_l_[PADL_(char *)]; char * name; char name_r_[PADR_(char *)]; char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; char count_l_[PADL_(l_int)]; l_int count; char count_r_[PADR_(l_int)]; }; struct linux_uselib_args { char library_l_[PADL_(char *)]; char * library; char library_r_[PADR_(char *)]; }; struct linux_reboot_args { char magic1_l_[PADL_(l_int)]; l_int magic1; char magic1_r_[PADR_(l_int)]; char magic2_l_[PADL_(l_int)]; l_int magic2; char magic2_r_[PADR_(l_int)]; char cmd_l_[PADL_(l_uint)]; l_uint cmd; char cmd_r_[PADR_(l_uint)]; char arg_l_[PADL_(void *)]; void * arg; char arg_r_[PADR_(void *)]; }; struct linux_readdir_args { char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; char dent_l_[PADL_(struct l_dirent *)]; struct l_dirent * dent; char dent_r_[PADR_(struct l_dirent *)]; char count_l_[PADL_(l_uint)]; l_uint count; char count_r_[PADR_(l_uint)]; }; struct linux_mmap_args { char ptr_l_[PADL_(struct l_mmap_argv *)]; struct l_mmap_argv * ptr; char ptr_r_[PADR_(struct l_mmap_argv *)]; }; struct linux_truncate_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char length_l_[PADL_(l_ulong)]; l_ulong length; char length_r_[PADR_(l_ulong)]; }; struct linux_ftruncate_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char length_l_[PADL_(long)]; long length; char length_r_[PADR_(long)]; }; struct linux_getpriority_args { char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)]; char who_l_[PADL_(int)]; int who; char who_r_[PADR_(int)]; }; struct linux_statfs_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char buf_l_[PADL_(struct l_statfs_buf *)]; struct l_statfs_buf * buf; char buf_r_[PADR_(struct l_statfs_buf *)]; }; struct linux_fstatfs_args { char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; char buf_l_[PADL_(struct l_statfs_buf *)]; struct l_statfs_buf * buf; char buf_r_[PADR_(struct l_statfs_buf *)]; }; struct linux_ioperm_args { char start_l_[PADL_(l_ulong)]; l_ulong start; char start_r_[PADR_(l_ulong)]; char length_l_[PADL_(l_ulong)]; l_ulong length; char length_r_[PADR_(l_ulong)]; char enable_l_[PADL_(l_int)]; l_int enable; char enable_r_[PADR_(l_int)]; }; struct linux_socketcall_args { char what_l_[PADL_(l_int)]; l_int what; char what_r_[PADR_(l_int)]; char args_l_[PADL_(l_ulong)]; l_ulong args; char args_r_[PADR_(l_ulong)]; }; struct linux_syslog_args { char type_l_[PADL_(l_int)]; l_int type; char type_r_[PADR_(l_int)]; char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; char len_l_[PADL_(l_int)]; l_int len; char len_r_[PADR_(l_int)]; }; struct linux_setitimer_args { char which_l_[PADL_(l_int)]; l_int which; char which_r_[PADR_(l_int)]; char itv_l_[PADL_(struct l_itimerval *)]; struct l_itimerval * itv; char itv_r_[PADR_(struct l_itimerval *)]; char oitv_l_[PADL_(struct l_itimerval *)]; struct l_itimerval * oitv; char oitv_r_[PADR_(struct l_itimerval *)]; }; struct linux_getitimer_args { char which_l_[PADL_(l_int)]; l_int which; char which_r_[PADR_(l_int)]; char itv_l_[PADL_(struct l_itimerval *)]; struct l_itimerval * itv; char itv_r_[PADR_(struct l_itimerval *)]; }; struct linux_newstat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char buf_l_[PADL_(struct l_newstat *)]; struct l_newstat * buf; char buf_r_[PADR_(struct l_newstat *)]; }; struct linux_newlstat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char buf_l_[PADL_(struct l_newstat *)]; struct l_newstat * buf; char buf_r_[PADR_(struct l_newstat *)]; }; struct linux_newfstat_args { char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; char buf_l_[PADL_(struct l_newstat *)]; struct l_newstat * buf; char buf_r_[PADR_(struct l_newstat *)]; }; struct linux_uname_args { register_t dummy; }; struct linux_iopl_args { char level_l_[PADL_(l_ulong)]; l_ulong level; char level_r_[PADR_(l_ulong)]; }; struct linux_vhangup_args { register_t dummy; }; struct linux_vm86old_args { register_t dummy; }; struct linux_wait4_args { char pid_l_[PADL_(l_pid_t)]; l_pid_t pid; char pid_r_[PADR_(l_pid_t)]; char status_l_[PADL_(l_uint *)]; l_uint * status; char status_r_[PADR_(l_uint *)]; char options_l_[PADL_(l_int)]; l_int options; char options_r_[PADR_(l_int)]; char rusage_l_[PADL_(struct l_rusage *)]; struct l_rusage * rusage; char rusage_r_[PADR_(struct l_rusage *)]; }; struct linux_swapoff_args { register_t dummy; }; struct linux_sysinfo_args { char info_l_[PADL_(struct l_sysinfo *)]; struct l_sysinfo * info; char info_r_[PADR_(struct l_sysinfo *)]; }; struct linux_ipc_args { char what_l_[PADL_(l_uint)]; l_uint what; char what_r_[PADR_(l_uint)]; char arg1_l_[PADL_(l_int)]; l_int arg1; char arg1_r_[PADR_(l_int)]; char arg2_l_[PADL_(l_int)]; l_int arg2; char arg2_r_[PADR_(l_int)]; char arg3_l_[PADL_(l_int)]; l_int arg3; char arg3_r_[PADR_(l_int)]; char ptr_l_[PADL_(void *)]; void * ptr; char ptr_r_[PADR_(void *)]; char arg5_l_[PADL_(l_long)]; l_long arg5; char arg5_r_[PADR_(l_long)]; }; struct linux_sigreturn_args { char sfp_l_[PADL_(struct l_sigframe *)]; struct l_sigframe * sfp; char sfp_r_[PADR_(struct l_sigframe *)]; }; struct linux_clone_args { char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; char stack_l_[PADL_(void *)]; void * stack; char stack_r_[PADR_(void *)]; char parent_tidptr_l_[PADL_(void *)]; void * parent_tidptr; char parent_tidptr_r_[PADR_(void *)]; char dummy_l_[PADL_(int)]; int dummy; char dummy_r_[PADR_(int)]; char child_tidptr_l_[PADL_(void *)]; void * child_tidptr; char child_tidptr_r_[PADR_(void *)]; }; struct linux_newuname_args { char buf_l_[PADL_(struct l_new_utsname *)]; struct l_new_utsname * buf; char buf_r_[PADR_(struct l_new_utsname *)]; }; struct linux_modify_ldt_args { char func_l_[PADL_(l_int)]; l_int func; char func_r_[PADR_(l_int)]; char ptr_l_[PADL_(void *)]; void * ptr; char ptr_r_[PADR_(void *)]; char bytecount_l_[PADL_(l_ulong)]; l_ulong bytecount; char bytecount_r_[PADR_(l_ulong)]; }; struct linux_adjtimex_args { register_t dummy; }; struct linux_sigprocmask_args { char how_l_[PADL_(l_int)]; l_int how; char how_r_[PADR_(l_int)]; char mask_l_[PADL_(l_osigset_t *)]; l_osigset_t * mask; char mask_r_[PADR_(l_osigset_t *)]; char omask_l_[PADL_(l_osigset_t *)]; l_osigset_t * omask; char omask_r_[PADR_(l_osigset_t *)]; }; struct linux_create_module_args { register_t dummy; }; struct linux_init_module_args { register_t dummy; }; struct linux_delete_module_args { register_t dummy; }; struct linux_get_kernel_syms_args { register_t dummy; }; struct linux_quotactl_args { register_t dummy; }; struct linux_bdflush_args { register_t dummy; }; struct linux_sysfs_args { char option_l_[PADL_(l_int)]; l_int option; char option_r_[PADR_(l_int)]; char arg1_l_[PADL_(l_ulong)]; l_ulong arg1; char arg1_r_[PADR_(l_ulong)]; char arg2_l_[PADL_(l_ulong)]; l_ulong arg2; char arg2_r_[PADR_(l_ulong)]; }; struct linux_personality_args { char per_l_[PADL_(l_ulong)]; l_ulong per; char per_r_[PADR_(l_ulong)]; }; struct linux_setfsuid16_args { char uid_l_[PADL_(l_uid16_t)]; l_uid16_t uid; char uid_r_[PADR_(l_uid16_t)]; }; struct linux_setfsgid16_args { char gid_l_[PADL_(l_gid16_t)]; l_gid16_t gid; char gid_r_[PADR_(l_gid16_t)]; }; struct linux_llseek_args { char fd_l_[PADL_(l_int)]; l_int fd; char fd_r_[PADR_(l_int)]; char ohigh_l_[PADL_(l_ulong)]; l_ulong ohigh; char ohigh_r_[PADR_(l_ulong)]; char olow_l_[PADL_(l_ulong)]; l_ulong olow; char olow_r_[PADR_(l_ulong)]; char res_l_[PADL_(l_loff_t *)]; l_loff_t * res; char res_r_[PADR_(l_loff_t *)]; char whence_l_[PADL_(l_uint)]; l_uint whence; char whence_r_[PADR_(l_uint)]; }; struct linux_getdents_args { char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; char dent_l_[PADL_(void *)]; void * dent; char dent_r_[PADR_(void *)]; char count_l_[PADL_(l_uint)]; l_uint count; char count_r_[PADR_(l_uint)]; }; struct linux_select_args { char nfds_l_[PADL_(l_int)]; l_int nfds; char nfds_r_[PADR_(l_int)]; char readfds_l_[PADL_(l_fd_set *)]; l_fd_set * readfds; char readfds_r_[PADR_(l_fd_set *)]; char writefds_l_[PADL_(l_fd_set *)]; l_fd_set * writefds; char writefds_r_[PADR_(l_fd_set *)]; char exceptfds_l_[PADL_(l_fd_set *)]; l_fd_set * exceptfds; char exceptfds_r_[PADR_(l_fd_set *)]; char timeout_l_[PADL_(struct l_timeval *)]; struct l_timeval * timeout; char timeout_r_[PADR_(struct l_timeval *)]; }; struct linux_msync_args { char addr_l_[PADL_(l_ulong)]; l_ulong addr; char addr_r_[PADR_(l_ulong)]; char len_l_[PADL_(l_size_t)]; l_size_t len; char len_r_[PADR_(l_size_t)]; char fl_l_[PADL_(l_int)]; l_int fl; char fl_r_[PADR_(l_int)]; }; struct linux_getsid_args { char pid_l_[PADL_(l_pid_t)]; l_pid_t pid; char pid_r_[PADR_(l_pid_t)]; }; struct linux_fdatasync_args { char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; }; struct linux_sysctl_args { char args_l_[PADL_(struct l___sysctl_args *)]; struct l___sysctl_args * args; char args_r_[PADR_(struct l___sysctl_args *)]; }; struct linux_sched_setscheduler_args { char pid_l_[PADL_(l_pid_t)]; l_pid_t pid; char pid_r_[PADR_(l_pid_t)]; char policy_l_[PADL_(l_int)]; l_int policy; char policy_r_[PADR_(l_int)]; char param_l_[PADL_(struct l_sched_param *)]; struct l_sched_param * param; char param_r_[PADR_(struct l_sched_param *)]; }; struct linux_sched_getscheduler_args { char pid_l_[PADL_(l_pid_t)]; l_pid_t pid; char pid_r_[PADR_(l_pid_t)]; }; struct linux_sched_get_priority_max_args { char policy_l_[PADL_(l_int)]; l_int policy; char policy_r_[PADR_(l_int)]; }; struct linux_sched_get_priority_min_args { char policy_l_[PADL_(l_int)]; l_int policy; char policy_r_[PADR_(l_int)]; }; struct linux_mremap_args { char addr_l_[PADL_(l_ulong)]; l_ulong addr; char addr_r_[PADR_(l_ulong)]; char old_len_l_[PADL_(l_ulong)]; l_ulong old_len; char old_len_r_[PADR_(l_ulong)]; char new_len_l_[PADL_(l_ulong)]; l_ulong new_len; char new_len_r_[PADR_(l_ulong)]; char flags_l_[PADL_(l_ulong)]; l_ulong flags; char flags_r_[PADR_(l_ulong)]; char new_addr_l_[PADL_(l_ulong)]; l_ulong new_addr; char new_addr_r_[PADR_(l_ulong)]; }; struct linux_setresuid16_args { char ruid_l_[PADL_(l_uid16_t)]; l_uid16_t ruid; char ruid_r_[PADR_(l_uid16_t)]; char euid_l_[PADL_(l_uid16_t)]; l_uid16_t euid; char euid_r_[PADR_(l_uid16_t)]; char suid_l_[PADL_(l_uid16_t)]; l_uid16_t suid; char suid_r_[PADR_(l_uid16_t)]; }; struct linux_getresuid16_args { char ruid_l_[PADL_(l_uid16_t *)]; l_uid16_t * ruid; char ruid_r_[PADR_(l_uid16_t *)]; char euid_l_[PADL_(l_uid16_t *)]; l_uid16_t * euid; char euid_r_[PADR_(l_uid16_t *)]; char suid_l_[PADL_(l_uid16_t *)]; l_uid16_t * suid; char suid_r_[PADR_(l_uid16_t *)]; }; struct linux_vm86_args { register_t dummy; }; struct linux_query_module_args { register_t dummy; }; struct linux_nfsservctl_args { register_t dummy; }; struct linux_setresgid16_args { char rgid_l_[PADL_(l_gid16_t)]; l_gid16_t rgid; char rgid_r_[PADR_(l_gid16_t)]; char egid_l_[PADL_(l_gid16_t)]; l_gid16_t egid; char egid_r_[PADR_(l_gid16_t)]; char sgid_l_[PADL_(l_gid16_t)]; l_gid16_t sgid; char sgid_r_[PADR_(l_gid16_t)]; }; struct linux_getresgid16_args { char rgid_l_[PADL_(l_gid16_t *)]; l_gid16_t * rgid; char rgid_r_[PADR_(l_gid16_t *)]; char egid_l_[PADL_(l_gid16_t *)]; l_gid16_t * egid; char egid_r_[PADR_(l_gid16_t *)]; char sgid_l_[PADL_(l_gid16_t *)]; l_gid16_t * sgid; char sgid_r_[PADR_(l_gid16_t *)]; }; struct linux_prctl_args { char option_l_[PADL_(l_int)]; l_int option; char option_r_[PADR_(l_int)]; char arg2_l_[PADL_(l_int)]; l_int arg2; char arg2_r_[PADR_(l_int)]; char arg3_l_[PADL_(l_int)]; l_int arg3; char arg3_r_[PADR_(l_int)]; char arg4_l_[PADL_(l_int)]; l_int arg4; char arg4_r_[PADR_(l_int)]; char arg5_l_[PADL_(l_int)]; l_int arg5; char arg5_r_[PADR_(l_int)]; }; struct linux_rt_sigreturn_args { char ucp_l_[PADL_(struct l_ucontext *)]; struct l_ucontext * ucp; char ucp_r_[PADR_(struct l_ucontext *)]; }; struct linux_rt_sigaction_args { char sig_l_[PADL_(l_int)]; l_int sig; char sig_r_[PADR_(l_int)]; char act_l_[PADL_(l_sigaction_t *)]; l_sigaction_t * act; char act_r_[PADR_(l_sigaction_t *)]; char oact_l_[PADL_(l_sigaction_t *)]; l_sigaction_t * oact; char oact_r_[PADR_(l_sigaction_t *)]; char sigsetsize_l_[PADL_(l_size_t)]; l_size_t sigsetsize; char sigsetsize_r_[PADR_(l_size_t)]; }; struct linux_rt_sigprocmask_args { char how_l_[PADL_(l_int)]; l_int how; char how_r_[PADR_(l_int)]; char mask_l_[PADL_(l_sigset_t *)]; l_sigset_t * mask; char mask_r_[PADR_(l_sigset_t *)]; char omask_l_[PADL_(l_sigset_t *)]; l_sigset_t * omask; char omask_r_[PADR_(l_sigset_t *)]; char sigsetsize_l_[PADL_(l_size_t)]; l_size_t sigsetsize; char sigsetsize_r_[PADR_(l_size_t)]; }; struct linux_rt_sigpending_args { char set_l_[PADL_(l_sigset_t *)]; l_sigset_t * set; char set_r_[PADR_(l_sigset_t *)]; char sigsetsize_l_[PADL_(l_size_t)]; l_size_t sigsetsize; char sigsetsize_r_[PADR_(l_size_t)]; }; struct linux_rt_sigtimedwait_args { register_t dummy; }; struct linux_rt_sigqueueinfo_args { register_t dummy; }; struct linux_rt_sigsuspend_args { char newset_l_[PADL_(l_sigset_t *)]; l_sigset_t * newset; char newset_r_[PADR_(l_sigset_t *)]; char sigsetsize_l_[PADL_(l_size_t)]; l_size_t sigsetsize; char sigsetsize_r_[PADR_(l_size_t)]; }; struct linux_pread_args { char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; char nbyte_l_[PADL_(l_size_t)]; l_size_t nbyte; char nbyte_r_[PADR_(l_size_t)]; char offset_l_[PADL_(l_loff_t)]; l_loff_t offset; char offset_r_[PADR_(l_loff_t)]; }; struct linux_pwrite_args { char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; char nbyte_l_[PADL_(l_size_t)]; l_size_t nbyte; char nbyte_r_[PADR_(l_size_t)]; char offset_l_[PADL_(l_loff_t)]; l_loff_t offset; char offset_r_[PADR_(l_loff_t)]; }; struct linux_chown16_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char uid_l_[PADL_(l_uid16_t)]; l_uid16_t uid; char uid_r_[PADR_(l_uid16_t)]; char gid_l_[PADL_(l_gid16_t)]; l_gid16_t gid; char gid_r_[PADR_(l_gid16_t)]; }; struct linux_getcwd_args { char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; char bufsize_l_[PADL_(l_ulong)]; l_ulong bufsize; char bufsize_r_[PADR_(l_ulong)]; }; struct linux_capget_args { register_t dummy; }; struct linux_capset_args { register_t dummy; }; struct linux_sigaltstack_args { char uss_l_[PADL_(l_stack_t *)]; l_stack_t * uss; char uss_r_[PADR_(l_stack_t *)]; char uoss_l_[PADL_(l_stack_t *)]; l_stack_t * uoss; char uoss_r_[PADR_(l_stack_t *)]; }; struct linux_sendfile_args { register_t dummy; }; struct linux_vfork_args { register_t dummy; }; struct linux_getrlimit_args { char resource_l_[PADL_(l_uint)]; l_uint resource; char resource_r_[PADR_(l_uint)]; char rlim_l_[PADL_(struct l_rlimit *)]; struct l_rlimit * rlim; char rlim_r_[PADR_(struct l_rlimit *)]; }; struct linux_mmap2_args { char addr_l_[PADL_(l_ulong)]; l_ulong addr; char addr_r_[PADR_(l_ulong)]; char len_l_[PADL_(l_ulong)]; l_ulong len; char len_r_[PADR_(l_ulong)]; char prot_l_[PADL_(l_ulong)]; l_ulong prot; char prot_r_[PADR_(l_ulong)]; char flags_l_[PADL_(l_ulong)]; l_ulong flags; char flags_r_[PADR_(l_ulong)]; char fd_l_[PADL_(l_ulong)]; l_ulong fd; char fd_r_[PADR_(l_ulong)]; char pgoff_l_[PADL_(l_ulong)]; l_ulong pgoff; char pgoff_r_[PADR_(l_ulong)]; }; struct linux_truncate64_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char length_l_[PADL_(l_loff_t)]; l_loff_t length; char length_r_[PADR_(l_loff_t)]; }; struct linux_ftruncate64_args { char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; char length_l_[PADL_(l_loff_t)]; l_loff_t length; char length_r_[PADR_(l_loff_t)]; }; struct linux_stat64_args { char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)]; char statbuf_l_[PADL_(struct l_stat64 *)]; struct l_stat64 * statbuf; char statbuf_r_[PADR_(struct l_stat64 *)]; char flags_l_[PADL_(l_long)]; l_long flags; char flags_r_[PADR_(l_long)]; }; struct linux_lstat64_args { char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)]; char statbuf_l_[PADL_(struct l_stat64 *)]; struct l_stat64 * statbuf; char statbuf_r_[PADR_(struct l_stat64 *)]; char flags_l_[PADL_(l_long)]; l_long flags; char flags_r_[PADR_(l_long)]; }; struct linux_fstat64_args { char fd_l_[PADL_(l_ulong)]; l_ulong fd; char fd_r_[PADR_(l_ulong)]; char statbuf_l_[PADL_(struct l_stat64 *)]; struct l_stat64 * statbuf; char statbuf_r_[PADR_(struct l_stat64 *)]; char flags_l_[PADL_(l_long)]; l_long flags; char flags_r_[PADR_(l_long)]; }; struct linux_lchown_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char uid_l_[PADL_(l_uid_t)]; l_uid_t uid; char uid_r_[PADR_(l_uid_t)]; char gid_l_[PADL_(l_gid_t)]; l_gid_t gid; char gid_r_[PADR_(l_gid_t)]; }; struct linux_getuid_args { register_t dummy; }; struct linux_getgid_args { register_t dummy; }; struct linux_getgroups_args { char gidsetsize_l_[PADL_(l_int)]; l_int gidsetsize; char gidsetsize_r_[PADR_(l_int)]; char grouplist_l_[PADL_(l_gid_t *)]; l_gid_t * grouplist; char grouplist_r_[PADR_(l_gid_t *)]; }; struct linux_setgroups_args { char gidsetsize_l_[PADL_(l_int)]; l_int gidsetsize; char gidsetsize_r_[PADR_(l_int)]; char grouplist_l_[PADL_(l_gid_t *)]; l_gid_t * grouplist; char grouplist_r_[PADR_(l_gid_t *)]; }; struct linux_chown_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char uid_l_[PADL_(l_uid_t)]; l_uid_t uid; char uid_r_[PADR_(l_uid_t)]; char gid_l_[PADL_(l_gid_t)]; l_gid_t gid; char gid_r_[PADR_(l_gid_t)]; }; struct linux_setfsuid_args { char uid_l_[PADL_(l_uid_t)]; l_uid_t uid; char uid_r_[PADR_(l_uid_t)]; }; struct linux_setfsgid_args { char gid_l_[PADL_(l_gid_t)]; l_gid_t gid; char gid_r_[PADR_(l_gid_t)]; }; struct linux_pivot_root_args { char new_root_l_[PADL_(char *)]; char * new_root; char new_root_r_[PADR_(char *)]; char put_old_l_[PADL_(char *)]; char * put_old; char put_old_r_[PADR_(char *)]; }; struct linux_mincore_args { char start_l_[PADL_(l_ulong)]; l_ulong start; char start_r_[PADR_(l_ulong)]; char len_l_[PADL_(l_size_t)]; l_size_t len; char len_r_[PADR_(l_size_t)]; char vec_l_[PADL_(u_char *)]; u_char * vec; char vec_r_[PADR_(u_char *)]; }; struct linux_getdents64_args { char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; char dirent_l_[PADL_(void *)]; void * dirent; char dirent_r_[PADR_(void *)]; char count_l_[PADL_(l_uint)]; l_uint count; char count_r_[PADR_(l_uint)]; }; struct linux_fcntl64_args { char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)]; char cmd_l_[PADL_(l_uint)]; l_uint cmd; char cmd_r_[PADR_(l_uint)]; char arg_l_[PADL_(l_ulong)]; l_ulong arg; char arg_r_[PADR_(l_ulong)]; }; struct linux_gettid_args { register_t dummy; }; struct linux_setxattr_args { register_t dummy; }; struct linux_lsetxattr_args { register_t dummy; }; struct linux_fsetxattr_args { register_t dummy; }; struct linux_getxattr_args { register_t dummy; }; struct linux_lgetxattr_args { register_t dummy; }; struct linux_fgetxattr_args { register_t dummy; }; struct linux_listxattr_args { register_t dummy; }; struct linux_llistxattr_args { register_t dummy; }; struct linux_flistxattr_args { register_t dummy; }; struct linux_removexattr_args { register_t dummy; }; struct linux_lremovexattr_args { register_t dummy; }; struct linux_fremovexattr_args { register_t dummy; }; struct linux_tkill_args { char tid_l_[PADL_(int)]; int tid; char tid_r_[PADR_(int)]; char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)]; }; struct linux_sys_futex_args { char uaddr_l_[PADL_(void *)]; void * uaddr; char uaddr_r_[PADR_(void *)]; char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)]; char val_l_[PADL_(int)]; int val; char val_r_[PADR_(int)]; char timeout_l_[PADL_(struct l_timespec *)]; struct l_timespec * timeout; char timeout_r_[PADR_(struct l_timespec *)]; char uaddr2_l_[PADL_(void *)]; void * uaddr2; char uaddr2_r_[PADR_(void *)]; char val3_l_[PADL_(int)]; int val3; char val3_r_[PADR_(int)]; }; struct linux_set_thread_area_args { char desc_l_[PADL_(struct l_user_desc *)]; struct l_user_desc * desc; char desc_r_[PADR_(struct l_user_desc *)]; }; struct linux_get_thread_area_args { char desc_l_[PADL_(struct l_user_desc *)]; struct l_user_desc * desc; char desc_r_[PADR_(struct l_user_desc *)]; }; struct linux_fadvise64_args { register_t dummy; }; struct linux_exit_group_args { char error_code_l_[PADL_(int)]; int error_code; char error_code_r_[PADR_(int)]; }; struct linux_lookup_dcookie_args { register_t dummy; }; struct linux_epoll_create_args { register_t dummy; }; struct linux_epoll_ctl_args { register_t dummy; }; struct linux_epoll_wait_args { register_t dummy; }; struct linux_remap_file_pages_args { register_t dummy; }; struct linux_set_tid_address_args { char tidptr_l_[PADL_(int *)]; int * tidptr; char tidptr_r_[PADR_(int *)]; }; struct linux_timer_create_args { char clock_id_l_[PADL_(clockid_t)]; clockid_t clock_id; char clock_id_r_[PADR_(clockid_t)]; char evp_l_[PADL_(struct sigevent *)]; struct sigevent * evp; char evp_r_[PADR_(struct sigevent *)]; char timerid_l_[PADL_(l_timer_t *)]; l_timer_t * timerid; char timerid_r_[PADR_(l_timer_t *)]; }; struct linux_timer_settime_args { char timerid_l_[PADL_(l_timer_t)]; l_timer_t timerid; char timerid_r_[PADR_(l_timer_t)]; char new_l_[PADL_(const struct itimerspec *)]; const struct itimerspec * new; char new_r_[PADR_(const struct itimerspec *)]; char old_l_[PADL_(struct itimerspec *)]; struct itimerspec * old; char old_r_[PADR_(struct itimerspec *)]; }; struct linux_timer_gettime_args { char timerid_l_[PADL_(l_timer_t)]; l_timer_t timerid; char timerid_r_[PADR_(l_timer_t)]; char setting_l_[PADL_(struct itimerspec *)]; struct itimerspec * setting; char setting_r_[PADR_(struct itimerspec *)]; }; struct linux_timer_getoverrun_args { char timerid_l_[PADL_(l_timer_t)]; l_timer_t timerid; char timerid_r_[PADR_(l_timer_t)]; }; struct linux_timer_delete_args { char timerid_l_[PADL_(l_timer_t)]; l_timer_t timerid; char timerid_r_[PADR_(l_timer_t)]; }; struct linux_clock_settime_args { char which_l_[PADL_(clockid_t)]; clockid_t which; char which_r_[PADR_(clockid_t)]; char tp_l_[PADL_(struct l_timespec *)]; struct l_timespec * tp; char tp_r_[PADR_(struct l_timespec *)]; }; struct linux_clock_gettime_args { char which_l_[PADL_(clockid_t)]; clockid_t which; char which_r_[PADR_(clockid_t)]; char tp_l_[PADL_(struct l_timespec *)]; struct l_timespec * tp; char tp_r_[PADR_(struct l_timespec *)]; }; struct linux_clock_getres_args { char which_l_[PADL_(clockid_t)]; clockid_t which; char which_r_[PADR_(clockid_t)]; char tp_l_[PADL_(struct l_timespec *)]; struct l_timespec * tp; char tp_r_[PADR_(struct l_timespec *)]; }; struct linux_clock_nanosleep_args { char which_l_[PADL_(clockid_t)]; clockid_t which; char which_r_[PADR_(clockid_t)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; char rqtp_l_[PADL_(struct l_timespec *)]; struct l_timespec * rqtp; char rqtp_r_[PADR_(struct l_timespec *)]; char rmtp_l_[PADL_(struct l_timespec *)]; struct l_timespec * rmtp; char rmtp_r_[PADR_(struct l_timespec *)]; }; struct linux_statfs64_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char buf_l_[PADL_(struct l_statfs64_buf *)]; struct l_statfs64_buf * buf; char buf_r_[PADR_(struct l_statfs64_buf *)]; }; struct linux_fstatfs64_args { register_t dummy; }; struct linux_tgkill_args { char tgid_l_[PADL_(int)]; int tgid; char tgid_r_[PADR_(int)]; char pid_l_[PADL_(int)]; int pid; char pid_r_[PADR_(int)]; char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)]; }; struct linux_utimes_args { register_t dummy; }; struct linux_fadvise64_64_args { register_t dummy; }; struct linux_mbind_args { register_t dummy; }; struct linux_get_mempolicy_args { register_t dummy; }; struct linux_set_mempolicy_args { register_t dummy; }; struct linux_mq_open_args { char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; char oflag_l_[PADL_(int)]; int oflag; char oflag_r_[PADR_(int)]; char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)]; char attr_l_[PADL_(struct mq_attr *)]; struct mq_attr * attr; char attr_r_[PADR_(struct mq_attr *)]; }; struct linux_mq_unlink_args { char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; }; struct linux_mq_timedsend_args { char mqd_l_[PADL_(l_mqd_t)]; l_mqd_t mqd; char mqd_r_[PADR_(l_mqd_t)]; char msg_ptr_l_[PADL_(const char *)]; const char * msg_ptr; char msg_ptr_r_[PADR_(const char *)]; char msg_len_l_[PADL_(size_t)]; size_t msg_len; char msg_len_r_[PADR_(size_t)]; char msg_prio_l_[PADL_(unsigned int)]; unsigned int msg_prio; char msg_prio_r_[PADR_(unsigned int)]; char abs_timeout_l_[PADL_(const struct l_timespec *)]; const struct l_timespec * abs_timeout; char abs_timeout_r_[PADR_(const struct l_timespec *)]; }; struct linux_mq_timedreceive_args { char mqd_l_[PADL_(l_mqd_t)]; l_mqd_t mqd; char mqd_r_[PADR_(l_mqd_t)]; char msg_ptr_l_[PADL_(char *)]; char * msg_ptr; char msg_ptr_r_[PADR_(char *)]; char msg_len_l_[PADL_(size_t)]; size_t msg_len; char msg_len_r_[PADR_(size_t)]; char msg_prio_l_[PADL_(unsigned int)]; unsigned int msg_prio; char msg_prio_r_[PADR_(unsigned int)]; char abs_timeout_l_[PADL_(const struct l_timespec *)]; const struct l_timespec * abs_timeout; char abs_timeout_r_[PADR_(const struct l_timespec *)]; }; struct linux_mq_notify_args { char mqd_l_[PADL_(l_mqd_t)]; l_mqd_t mqd; char mqd_r_[PADR_(l_mqd_t)]; char abs_timeout_l_[PADL_(const struct l_timespec *)]; const struct l_timespec * abs_timeout; char abs_timeout_r_[PADR_(const struct l_timespec *)]; }; struct linux_mq_getsetattr_args { char mqd_l_[PADL_(l_mqd_t)]; l_mqd_t mqd; char mqd_r_[PADR_(l_mqd_t)]; char attr_l_[PADL_(const struct mq_attr *)]; const struct mq_attr * attr; char attr_r_[PADR_(const struct mq_attr *)]; char oattr_l_[PADL_(struct mq_attr *)]; struct mq_attr * oattr; char oattr_r_[PADR_(struct mq_attr *)]; }; struct linux_kexec_load_args { register_t dummy; }; struct linux_waitid_args { register_t dummy; }; struct linux_add_key_args { register_t dummy; }; struct linux_request_key_args { register_t dummy; }; struct linux_keyctl_args { register_t dummy; }; struct linux_ioprio_set_args { register_t dummy; }; struct linux_ioprio_get_args { register_t dummy; }; struct linux_inotify_init_args { register_t dummy; }; struct linux_inotify_add_watch_args { register_t dummy; }; struct linux_inotify_rm_watch_args { register_t dummy; }; struct linux_migrate_pages_args { register_t dummy; }; struct linux_openat_args { register_t dummy; }; struct linux_mkdirat_args { register_t dummy; }; struct linux_mknodat_args { register_t dummy; }; struct linux_fchownat_args { register_t dummy; }; struct linux_futimesat_args { register_t dummy; }; struct linux_fstatat64_args { register_t dummy; }; struct linux_unlinkat_args { register_t dummy; }; struct linux_renameat_args { register_t dummy; }; struct linux_linkat_args { register_t dummy; }; struct linux_symlinkat_args { register_t dummy; }; struct linux_readlinkat_args { register_t dummy; }; struct linux_fchmodat_args { register_t dummy; }; struct linux_faccessat_args { register_t dummy; }; struct linux_pselect6_args { register_t dummy; }; struct linux_ppoll_args { register_t dummy; }; struct linux_unshare_args { register_t dummy; }; #define nosys linux_nosys int linux_fork(struct thread *, struct linux_fork_args *); int linux_open(struct thread *, struct linux_open_args *); int linux_waitpid(struct thread *, struct linux_waitpid_args *); int linux_creat(struct thread *, struct linux_creat_args *); int linux_link(struct thread *, struct linux_link_args *); int linux_unlink(struct thread *, struct linux_unlink_args *); int linux_execve(struct thread *, struct linux_execve_args *); int linux_chdir(struct thread *, struct linux_chdir_args *); int linux_time(struct thread *, struct linux_time_args *); int linux_mknod(struct thread *, struct linux_mknod_args *); int linux_chmod(struct thread *, struct linux_chmod_args *); int linux_lchown16(struct thread *, struct linux_lchown16_args *); int linux_stat(struct thread *, struct linux_stat_args *); int linux_lseek(struct thread *, struct linux_lseek_args *); int linux_getpid(struct thread *, struct linux_getpid_args *); int linux_mount(struct thread *, struct linux_mount_args *); int linux_oldumount(struct thread *, struct linux_oldumount_args *); int linux_setuid16(struct thread *, struct linux_setuid16_args *); int linux_getuid16(struct thread *, struct linux_getuid16_args *); int linux_stime(struct thread *, struct linux_stime_args *); int linux_ptrace(struct thread *, struct linux_ptrace_args *); int linux_alarm(struct thread *, struct linux_alarm_args *); int linux_fstat(struct thread *, struct linux_fstat_args *); int linux_pause(struct thread *, struct linux_pause_args *); int linux_utime(struct thread *, struct linux_utime_args *); int linux_access(struct thread *, struct linux_access_args *); int linux_nice(struct thread *, struct linux_nice_args *); int linux_kill(struct thread *, struct linux_kill_args *); int linux_rename(struct thread *, struct linux_rename_args *); int linux_mkdir(struct thread *, struct linux_mkdir_args *); int linux_rmdir(struct thread *, struct linux_rmdir_args *); int linux_pipe(struct thread *, struct linux_pipe_args *); int linux_times(struct thread *, struct linux_times_args *); int linux_brk(struct thread *, struct linux_brk_args *); int linux_setgid16(struct thread *, struct linux_setgid16_args *); int linux_getgid16(struct thread *, struct linux_getgid16_args *); int linux_signal(struct thread *, struct linux_signal_args *); int linux_geteuid16(struct thread *, struct linux_geteuid16_args *); int linux_getegid16(struct thread *, struct linux_getegid16_args *); int linux_umount(struct thread *, struct linux_umount_args *); int linux_ioctl(struct thread *, struct linux_ioctl_args *); int linux_fcntl(struct thread *, struct linux_fcntl_args *); int linux_olduname(struct thread *, struct linux_olduname_args *); int linux_ustat(struct thread *, struct linux_ustat_args *); int linux_getppid(struct thread *, struct linux_getppid_args *); int linux_sigaction(struct thread *, struct linux_sigaction_args *); int linux_sgetmask(struct thread *, struct linux_sgetmask_args *); int linux_ssetmask(struct thread *, struct linux_ssetmask_args *); int linux_setreuid16(struct thread *, struct linux_setreuid16_args *); int linux_setregid16(struct thread *, struct linux_setregid16_args *); int linux_sigsuspend(struct thread *, struct linux_sigsuspend_args *); int linux_sigpending(struct thread *, struct linux_sigpending_args *); int linux_sethostname(struct thread *, struct linux_sethostname_args *); int linux_setrlimit(struct thread *, struct linux_setrlimit_args *); int linux_old_getrlimit(struct thread *, struct linux_old_getrlimit_args *); int linux_getgroups16(struct thread *, struct linux_getgroups16_args *); int linux_setgroups16(struct thread *, struct linux_setgroups16_args *); int linux_old_select(struct thread *, struct linux_old_select_args *); int linux_symlink(struct thread *, struct linux_symlink_args *); int linux_lstat(struct thread *, struct linux_lstat_args *); int linux_readlink(struct thread *, struct linux_readlink_args *); int linux_uselib(struct thread *, struct linux_uselib_args *); int linux_reboot(struct thread *, struct linux_reboot_args *); int linux_readdir(struct thread *, struct linux_readdir_args *); int linux_mmap(struct thread *, struct linux_mmap_args *); int linux_truncate(struct thread *, struct linux_truncate_args *); int linux_ftruncate(struct thread *, struct linux_ftruncate_args *); int linux_getpriority(struct thread *, struct linux_getpriority_args *); int linux_statfs(struct thread *, struct linux_statfs_args *); int linux_fstatfs(struct thread *, struct linux_fstatfs_args *); int linux_ioperm(struct thread *, struct linux_ioperm_args *); int linux_socketcall(struct thread *, struct linux_socketcall_args *); int linux_syslog(struct thread *, struct linux_syslog_args *); int linux_setitimer(struct thread *, struct linux_setitimer_args *); int linux_getitimer(struct thread *, struct linux_getitimer_args *); int linux_newstat(struct thread *, struct linux_newstat_args *); int linux_newlstat(struct thread *, struct linux_newlstat_args *); int linux_newfstat(struct thread *, struct linux_newfstat_args *); int linux_uname(struct thread *, struct linux_uname_args *); int linux_iopl(struct thread *, struct linux_iopl_args *); int linux_vhangup(struct thread *, struct linux_vhangup_args *); int linux_vm86old(struct thread *, struct linux_vm86old_args *); int linux_wait4(struct thread *, struct linux_wait4_args *); int linux_swapoff(struct thread *, struct linux_swapoff_args *); int linux_sysinfo(struct thread *, struct linux_sysinfo_args *); int linux_ipc(struct thread *, struct linux_ipc_args *); int linux_sigreturn(struct thread *, struct linux_sigreturn_args *); int linux_clone(struct thread *, struct linux_clone_args *); int linux_newuname(struct thread *, struct linux_newuname_args *); int linux_modify_ldt(struct thread *, struct linux_modify_ldt_args *); int linux_adjtimex(struct thread *, struct linux_adjtimex_args *); int linux_sigprocmask(struct thread *, struct linux_sigprocmask_args *); int linux_create_module(struct thread *, struct linux_create_module_args *); int linux_init_module(struct thread *, struct linux_init_module_args *); int linux_delete_module(struct thread *, struct linux_delete_module_args *); int linux_get_kernel_syms(struct thread *, struct linux_get_kernel_syms_args *); int linux_quotactl(struct thread *, struct linux_quotactl_args *); int linux_bdflush(struct thread *, struct linux_bdflush_args *); int linux_sysfs(struct thread *, struct linux_sysfs_args *); int linux_personality(struct thread *, struct linux_personality_args *); int linux_setfsuid16(struct thread *, struct linux_setfsuid16_args *); int linux_setfsgid16(struct thread *, struct linux_setfsgid16_args *); int linux_llseek(struct thread *, struct linux_llseek_args *); int linux_getdents(struct thread *, struct linux_getdents_args *); int linux_select(struct thread *, struct linux_select_args *); int linux_msync(struct thread *, struct linux_msync_args *); int linux_getsid(struct thread *, struct linux_getsid_args *); int linux_fdatasync(struct thread *, struct linux_fdatasync_args *); int linux_sysctl(struct thread *, struct linux_sysctl_args *); int linux_sched_setscheduler(struct thread *, struct linux_sched_setscheduler_args *); int linux_sched_getscheduler(struct thread *, struct linux_sched_getscheduler_args *); int linux_sched_get_priority_max(struct thread *, struct linux_sched_get_priority_max_args *); int linux_sched_get_priority_min(struct thread *, struct linux_sched_get_priority_min_args *); int linux_mremap(struct thread *, struct linux_mremap_args *); int linux_setresuid16(struct thread *, struct linux_setresuid16_args *); int linux_getresuid16(struct thread *, struct linux_getresuid16_args *); int linux_vm86(struct thread *, struct linux_vm86_args *); int linux_query_module(struct thread *, struct linux_query_module_args *); int linux_nfsservctl(struct thread *, struct linux_nfsservctl_args *); int linux_setresgid16(struct thread *, struct linux_setresgid16_args *); int linux_getresgid16(struct thread *, struct linux_getresgid16_args *); int linux_prctl(struct thread *, struct linux_prctl_args *); int linux_rt_sigreturn(struct thread *, struct linux_rt_sigreturn_args *); int linux_rt_sigaction(struct thread *, struct linux_rt_sigaction_args *); int linux_rt_sigprocmask(struct thread *, struct linux_rt_sigprocmask_args *); int linux_rt_sigpending(struct thread *, struct linux_rt_sigpending_args *); int linux_rt_sigtimedwait(struct thread *, struct linux_rt_sigtimedwait_args *); int linux_rt_sigqueueinfo(struct thread *, struct linux_rt_sigqueueinfo_args *); int linux_rt_sigsuspend(struct thread *, struct linux_rt_sigsuspend_args *); int linux_pread(struct thread *, struct linux_pread_args *); int linux_pwrite(struct thread *, struct linux_pwrite_args *); int linux_chown16(struct thread *, struct linux_chown16_args *); int linux_getcwd(struct thread *, struct linux_getcwd_args *); int linux_capget(struct thread *, struct linux_capget_args *); int linux_capset(struct thread *, struct linux_capset_args *); int linux_sigaltstack(struct thread *, struct linux_sigaltstack_args *); int linux_sendfile(struct thread *, struct linux_sendfile_args *); int linux_vfork(struct thread *, struct linux_vfork_args *); int linux_getrlimit(struct thread *, struct linux_getrlimit_args *); int linux_mmap2(struct thread *, struct linux_mmap2_args *); int linux_truncate64(struct thread *, struct linux_truncate64_args *); int linux_ftruncate64(struct thread *, struct linux_ftruncate64_args *); int linux_stat64(struct thread *, struct linux_stat64_args *); int linux_lstat64(struct thread *, struct linux_lstat64_args *); int linux_fstat64(struct thread *, struct linux_fstat64_args *); int linux_lchown(struct thread *, struct linux_lchown_args *); int linux_getuid(struct thread *, struct linux_getuid_args *); int linux_getgid(struct thread *, struct linux_getgid_args *); int linux_getgroups(struct thread *, struct linux_getgroups_args *); int linux_setgroups(struct thread *, struct linux_setgroups_args *); int linux_chown(struct thread *, struct linux_chown_args *); int linux_setfsuid(struct thread *, struct linux_setfsuid_args *); int linux_setfsgid(struct thread *, struct linux_setfsgid_args *); int linux_pivot_root(struct thread *, struct linux_pivot_root_args *); int linux_mincore(struct thread *, struct linux_mincore_args *); int linux_getdents64(struct thread *, struct linux_getdents64_args *); int linux_fcntl64(struct thread *, struct linux_fcntl64_args *); int linux_gettid(struct thread *, struct linux_gettid_args *); int linux_setxattr(struct thread *, struct linux_setxattr_args *); int linux_lsetxattr(struct thread *, struct linux_lsetxattr_args *); int linux_fsetxattr(struct thread *, struct linux_fsetxattr_args *); int linux_getxattr(struct thread *, struct linux_getxattr_args *); int linux_lgetxattr(struct thread *, struct linux_lgetxattr_args *); int linux_fgetxattr(struct thread *, struct linux_fgetxattr_args *); int linux_listxattr(struct thread *, struct linux_listxattr_args *); int linux_llistxattr(struct thread *, struct linux_llistxattr_args *); int linux_flistxattr(struct thread *, struct linux_flistxattr_args *); int linux_removexattr(struct thread *, struct linux_removexattr_args *); int linux_lremovexattr(struct thread *, struct linux_lremovexattr_args *); int linux_fremovexattr(struct thread *, struct linux_fremovexattr_args *); int linux_tkill(struct thread *, struct linux_tkill_args *); int linux_sys_futex(struct thread *, struct linux_sys_futex_args *); int linux_set_thread_area(struct thread *, struct linux_set_thread_area_args *); int linux_get_thread_area(struct thread *, struct linux_get_thread_area_args *); int linux_fadvise64(struct thread *, struct linux_fadvise64_args *); int linux_exit_group(struct thread *, struct linux_exit_group_args *); int linux_lookup_dcookie(struct thread *, struct linux_lookup_dcookie_args *); int linux_epoll_create(struct thread *, struct linux_epoll_create_args *); int linux_epoll_ctl(struct thread *, struct linux_epoll_ctl_args *); int linux_epoll_wait(struct thread *, struct linux_epoll_wait_args *); int linux_remap_file_pages(struct thread *, struct linux_remap_file_pages_args *); int linux_set_tid_address(struct thread *, struct linux_set_tid_address_args *); int linux_timer_create(struct thread *, struct linux_timer_create_args *); int linux_timer_settime(struct thread *, struct linux_timer_settime_args *); int linux_timer_gettime(struct thread *, struct linux_timer_gettime_args *); int linux_timer_getoverrun(struct thread *, struct linux_timer_getoverrun_args *); int linux_timer_delete(struct thread *, struct linux_timer_delete_args *); int linux_clock_settime(struct thread *, struct linux_clock_settime_args *); int linux_clock_gettime(struct thread *, struct linux_clock_gettime_args *); int linux_clock_getres(struct thread *, struct linux_clock_getres_args *); int linux_clock_nanosleep(struct thread *, struct linux_clock_nanosleep_args *); int linux_statfs64(struct thread *, struct linux_statfs64_args *); int linux_fstatfs64(struct thread *, struct linux_fstatfs64_args *); int linux_tgkill(struct thread *, struct linux_tgkill_args *); int linux_utimes(struct thread *, struct linux_utimes_args *); int linux_fadvise64_64(struct thread *, struct linux_fadvise64_64_args *); int linux_mbind(struct thread *, struct linux_mbind_args *); int linux_get_mempolicy(struct thread *, struct linux_get_mempolicy_args *); int linux_set_mempolicy(struct thread *, struct linux_set_mempolicy_args *); int linux_mq_open(struct thread *, struct linux_mq_open_args *); int linux_mq_unlink(struct thread *, struct linux_mq_unlink_args *); int linux_mq_timedsend(struct thread *, struct linux_mq_timedsend_args *); int linux_mq_timedreceive(struct thread *, struct linux_mq_timedreceive_args *); int linux_mq_notify(struct thread *, struct linux_mq_notify_args *); int linux_mq_getsetattr(struct thread *, struct linux_mq_getsetattr_args *); int linux_kexec_load(struct thread *, struct linux_kexec_load_args *); int linux_waitid(struct thread *, struct linux_waitid_args *); int linux_add_key(struct thread *, struct linux_add_key_args *); int linux_request_key(struct thread *, struct linux_request_key_args *); int linux_keyctl(struct thread *, struct linux_keyctl_args *); int linux_ioprio_set(struct thread *, struct linux_ioprio_set_args *); int linux_ioprio_get(struct thread *, struct linux_ioprio_get_args *); int linux_inotify_init(struct thread *, struct linux_inotify_init_args *); int linux_inotify_add_watch(struct thread *, struct linux_inotify_add_watch_args *); int linux_inotify_rm_watch(struct thread *, struct linux_inotify_rm_watch_args *); int linux_migrate_pages(struct thread *, struct linux_migrate_pages_args *); int linux_openat(struct thread *, struct linux_openat_args *); int linux_mkdirat(struct thread *, struct linux_mkdirat_args *); int linux_mknodat(struct thread *, struct linux_mknodat_args *); int linux_fchownat(struct thread *, struct linux_fchownat_args *); int linux_futimesat(struct thread *, struct linux_futimesat_args *); int linux_fstatat64(struct thread *, struct linux_fstatat64_args *); int linux_unlinkat(struct thread *, struct linux_unlinkat_args *); int linux_renameat(struct thread *, struct linux_renameat_args *); int linux_linkat(struct thread *, struct linux_linkat_args *); int linux_symlinkat(struct thread *, struct linux_symlinkat_args *); int linux_readlinkat(struct thread *, struct linux_readlinkat_args *); int linux_fchmodat(struct thread *, struct linux_fchmodat_args *); int linux_faccessat(struct thread *, struct linux_faccessat_args *); int linux_pselect6(struct thread *, struct linux_pselect6_args *); int linux_ppoll(struct thread *, struct linux_ppoll_args *); int linux_unshare(struct thread *, struct linux_unshare_args *); #ifdef COMPAT_43 #define nosys linux_nosys #endif /* COMPAT_43 */ #ifdef COMPAT_FREEBSD4 #define nosys linux_nosys #endif /* COMPAT_FREEBSD4 */ #define LINUX_SYS_AUE_linux_fork AUE_FORK #define LINUX_SYS_AUE_linux_open AUE_OPEN_RWTC #define LINUX_SYS_AUE_linux_waitpid AUE_WAIT4 #define LINUX_SYS_AUE_linux_creat AUE_CREAT #define LINUX_SYS_AUE_linux_link AUE_LINK #define LINUX_SYS_AUE_linux_unlink AUE_UNLINK #define LINUX_SYS_AUE_linux_execve AUE_EXECVE #define LINUX_SYS_AUE_linux_chdir AUE_CHDIR #define LINUX_SYS_AUE_linux_time AUE_NULL #define LINUX_SYS_AUE_linux_mknod AUE_MKNOD #define LINUX_SYS_AUE_linux_chmod AUE_CHMOD #define LINUX_SYS_AUE_linux_lchown16 AUE_LCHOWN #define LINUX_SYS_AUE_linux_stat AUE_STAT #define LINUX_SYS_AUE_linux_lseek AUE_LSEEK #define LINUX_SYS_AUE_linux_getpid AUE_GETPID #define LINUX_SYS_AUE_linux_mount AUE_MOUNT #define LINUX_SYS_AUE_linux_oldumount AUE_UMOUNT #define LINUX_SYS_AUE_linux_setuid16 AUE_SETUID #define LINUX_SYS_AUE_linux_getuid16 AUE_GETUID #define LINUX_SYS_AUE_linux_stime AUE_SETTIMEOFDAY #define LINUX_SYS_AUE_linux_ptrace AUE_PTRACE #define LINUX_SYS_AUE_linux_alarm AUE_NULL #define LINUX_SYS_AUE_linux_fstat AUE_FSTAT #define LINUX_SYS_AUE_linux_pause AUE_NULL #define LINUX_SYS_AUE_linux_utime AUE_UTIME #define LINUX_SYS_AUE_linux_access AUE_ACCESS #define LINUX_SYS_AUE_linux_nice AUE_NICE #define LINUX_SYS_AUE_linux_kill AUE_KILL #define LINUX_SYS_AUE_linux_rename AUE_RENAME #define LINUX_SYS_AUE_linux_mkdir AUE_MKDIR #define LINUX_SYS_AUE_linux_rmdir AUE_RMDIR #define LINUX_SYS_AUE_linux_pipe AUE_PIPE #define LINUX_SYS_AUE_linux_times AUE_NULL #define LINUX_SYS_AUE_linux_brk AUE_NULL #define LINUX_SYS_AUE_linux_setgid16 AUE_SETGID #define LINUX_SYS_AUE_linux_getgid16 AUE_GETGID #define LINUX_SYS_AUE_linux_signal AUE_NULL #define LINUX_SYS_AUE_linux_geteuid16 AUE_GETEUID #define LINUX_SYS_AUE_linux_getegid16 AUE_GETEGID #define LINUX_SYS_AUE_linux_umount AUE_UMOUNT #define LINUX_SYS_AUE_linux_ioctl AUE_IOCTL #define LINUX_SYS_AUE_linux_fcntl AUE_FCNTL #define LINUX_SYS_AUE_linux_olduname AUE_NULL #define LINUX_SYS_AUE_linux_ustat AUE_NULL #define LINUX_SYS_AUE_linux_getppid AUE_GETPPID #define LINUX_SYS_AUE_linux_sigaction AUE_NULL #define LINUX_SYS_AUE_linux_sgetmask AUE_NULL #define LINUX_SYS_AUE_linux_ssetmask AUE_NULL #define LINUX_SYS_AUE_linux_setreuid16 AUE_SETREUID #define LINUX_SYS_AUE_linux_setregid16 AUE_SETREGID #define LINUX_SYS_AUE_linux_sigsuspend AUE_NULL #define LINUX_SYS_AUE_linux_sigpending AUE_NULL #define LINUX_SYS_AUE_linux_sethostname AUE_SYSCTL #define LINUX_SYS_AUE_linux_setrlimit AUE_SETRLIMIT #define LINUX_SYS_AUE_linux_old_getrlimit AUE_GETRLIMIT #define LINUX_SYS_AUE_linux_getgroups16 AUE_GETGROUPS #define LINUX_SYS_AUE_linux_setgroups16 AUE_SETGROUPS #define LINUX_SYS_AUE_linux_old_select AUE_SELECT #define LINUX_SYS_AUE_linux_symlink AUE_SYMLINK #define LINUX_SYS_AUE_linux_lstat AUE_LSTAT #define LINUX_SYS_AUE_linux_readlink AUE_READLINK #define LINUX_SYS_AUE_linux_uselib AUE_USELIB #define LINUX_SYS_AUE_linux_reboot AUE_REBOOT #define LINUX_SYS_AUE_linux_readdir AUE_GETDIRENTRIES #define LINUX_SYS_AUE_linux_mmap AUE_MMAP #define LINUX_SYS_AUE_linux_truncate AUE_TRUNCATE #define LINUX_SYS_AUE_linux_ftruncate AUE_FTRUNCATE #define LINUX_SYS_AUE_linux_getpriority AUE_GETPRIORITY #define LINUX_SYS_AUE_linux_statfs AUE_STATFS #define LINUX_SYS_AUE_linux_fstatfs AUE_FSTATFS #define LINUX_SYS_AUE_linux_ioperm AUE_NULL #define LINUX_SYS_AUE_linux_socketcall AUE_NULL #define LINUX_SYS_AUE_linux_syslog AUE_NULL #define LINUX_SYS_AUE_linux_setitimer AUE_SETITIMER #define LINUX_SYS_AUE_linux_getitimer AUE_GETITIMER #define LINUX_SYS_AUE_linux_newstat AUE_STAT #define LINUX_SYS_AUE_linux_newlstat AUE_LSTAT #define LINUX_SYS_AUE_linux_newfstat AUE_FSTAT #define LINUX_SYS_AUE_linux_uname AUE_NULL #define LINUX_SYS_AUE_linux_iopl AUE_NULL #define LINUX_SYS_AUE_linux_vhangup AUE_NULL #define LINUX_SYS_AUE_linux_vm86old AUE_NULL #define LINUX_SYS_AUE_linux_wait4 AUE_WAIT4 #define LINUX_SYS_AUE_linux_swapoff AUE_SWAPOFF #define LINUX_SYS_AUE_linux_sysinfo AUE_NULL #define LINUX_SYS_AUE_linux_ipc AUE_NULL #define LINUX_SYS_AUE_linux_sigreturn AUE_SIGRETURN #define LINUX_SYS_AUE_linux_clone AUE_RFORK #define LINUX_SYS_AUE_linux_newuname AUE_NULL #define LINUX_SYS_AUE_linux_modify_ldt AUE_NULL #define LINUX_SYS_AUE_linux_adjtimex AUE_ADJTIME #define LINUX_SYS_AUE_linux_sigprocmask AUE_SIGPROCMASK #define LINUX_SYS_AUE_linux_create_module AUE_NULL #define LINUX_SYS_AUE_linux_init_module AUE_NULL #define LINUX_SYS_AUE_linux_delete_module AUE_NULL #define LINUX_SYS_AUE_linux_get_kernel_syms AUE_NULL #define LINUX_SYS_AUE_linux_quotactl AUE_QUOTACTL #define LINUX_SYS_AUE_linux_bdflush AUE_BDFLUSH #define LINUX_SYS_AUE_linux_sysfs AUE_NULL #define LINUX_SYS_AUE_linux_personality AUE_PERSONALITY #define LINUX_SYS_AUE_linux_setfsuid16 AUE_SETFSUID #define LINUX_SYS_AUE_linux_setfsgid16 AUE_SETFSGID #define LINUX_SYS_AUE_linux_llseek AUE_LSEEK #define LINUX_SYS_AUE_linux_getdents AUE_GETDIRENTRIES #define LINUX_SYS_AUE_linux_select AUE_SELECT #define LINUX_SYS_AUE_linux_msync AUE_MSYNC #define LINUX_SYS_AUE_linux_getsid AUE_GETSID #define LINUX_SYS_AUE_linux_fdatasync AUE_NULL #define LINUX_SYS_AUE_linux_sysctl AUE_SYSCTL #define LINUX_SYS_AUE_linux_sched_setscheduler AUE_SCHED_SETSCHEDULER #define LINUX_SYS_AUE_linux_sched_getscheduler AUE_SCHED_GETSCHEDULER #define LINUX_SYS_AUE_linux_sched_get_priority_max AUE_SCHED_GET_PRIORITY_MAX #define LINUX_SYS_AUE_linux_sched_get_priority_min AUE_SCHED_GET_PRIORITY_MIN #define LINUX_SYS_AUE_linux_mremap AUE_NULL #define LINUX_SYS_AUE_linux_setresuid16 AUE_SETRESUID #define LINUX_SYS_AUE_linux_getresuid16 AUE_GETRESUID #define LINUX_SYS_AUE_linux_vm86 AUE_NULL #define LINUX_SYS_AUE_linux_query_module AUE_NULL #define LINUX_SYS_AUE_linux_nfsservctl AUE_NULL #define LINUX_SYS_AUE_linux_setresgid16 AUE_SETRESGID #define LINUX_SYS_AUE_linux_getresgid16 AUE_GETRESGID #define LINUX_SYS_AUE_linux_prctl AUE_PRCTL #define LINUX_SYS_AUE_linux_rt_sigreturn AUE_NULL #define LINUX_SYS_AUE_linux_rt_sigaction AUE_NULL #define LINUX_SYS_AUE_linux_rt_sigprocmask AUE_NULL #define LINUX_SYS_AUE_linux_rt_sigpending AUE_NULL #define LINUX_SYS_AUE_linux_rt_sigtimedwait AUE_NULL #define LINUX_SYS_AUE_linux_rt_sigqueueinfo AUE_NULL #define LINUX_SYS_AUE_linux_rt_sigsuspend AUE_NULL #define LINUX_SYS_AUE_linux_pread AUE_PREAD #define LINUX_SYS_AUE_linux_pwrite AUE_PWRITE #define LINUX_SYS_AUE_linux_chown16 AUE_CHOWN #define LINUX_SYS_AUE_linux_getcwd AUE_GETCWD #define LINUX_SYS_AUE_linux_capget AUE_CAPGET #define LINUX_SYS_AUE_linux_capset AUE_CAPSET #define LINUX_SYS_AUE_linux_sigaltstack AUE_NULL #define LINUX_SYS_AUE_linux_sendfile AUE_SENDFILE #define LINUX_SYS_AUE_linux_vfork AUE_VFORK #define LINUX_SYS_AUE_linux_getrlimit AUE_GETRLIMIT #define LINUX_SYS_AUE_linux_mmap2 AUE_MMAP #define LINUX_SYS_AUE_linux_truncate64 AUE_TRUNCATE #define LINUX_SYS_AUE_linux_ftruncate64 AUE_FTRUNCATE #define LINUX_SYS_AUE_linux_stat64 AUE_STAT #define LINUX_SYS_AUE_linux_lstat64 AUE_LSTAT #define LINUX_SYS_AUE_linux_fstat64 AUE_FSTAT #define LINUX_SYS_AUE_linux_lchown AUE_LCHOWN #define LINUX_SYS_AUE_linux_getuid AUE_GETUID #define LINUX_SYS_AUE_linux_getgid AUE_GETGID #define LINUX_SYS_AUE_linux_getgroups AUE_GETGROUPS #define LINUX_SYS_AUE_linux_setgroups AUE_SETGROUPS #define LINUX_SYS_AUE_linux_chown AUE_CHOWN #define LINUX_SYS_AUE_linux_setfsuid AUE_SETFSUID #define LINUX_SYS_AUE_linux_setfsgid AUE_SETFSGID #define LINUX_SYS_AUE_linux_pivot_root AUE_PIVOT_ROOT #define LINUX_SYS_AUE_linux_mincore AUE_MINCORE #define LINUX_SYS_AUE_linux_getdents64 AUE_GETDIRENTRIES #define LINUX_SYS_AUE_linux_fcntl64 AUE_FCNTL #define LINUX_SYS_AUE_linux_gettid AUE_NULL #define LINUX_SYS_AUE_linux_setxattr AUE_NULL #define LINUX_SYS_AUE_linux_lsetxattr AUE_NULL #define LINUX_SYS_AUE_linux_fsetxattr AUE_NULL #define LINUX_SYS_AUE_linux_getxattr AUE_NULL #define LINUX_SYS_AUE_linux_lgetxattr AUE_NULL #define LINUX_SYS_AUE_linux_fgetxattr AUE_NULL #define LINUX_SYS_AUE_linux_listxattr AUE_NULL #define LINUX_SYS_AUE_linux_llistxattr AUE_NULL #define LINUX_SYS_AUE_linux_flistxattr AUE_NULL #define LINUX_SYS_AUE_linux_removexattr AUE_NULL #define LINUX_SYS_AUE_linux_lremovexattr AUE_NULL #define LINUX_SYS_AUE_linux_fremovexattr AUE_NULL #define LINUX_SYS_AUE_linux_tkill AUE_NULL #define LINUX_SYS_AUE_linux_sys_futex AUE_NULL #define LINUX_SYS_AUE_linux_set_thread_area AUE_NULL #define LINUX_SYS_AUE_linux_get_thread_area AUE_NULL #define LINUX_SYS_AUE_linux_fadvise64 AUE_NULL #define LINUX_SYS_AUE_linux_exit_group AUE_EXIT #define LINUX_SYS_AUE_linux_lookup_dcookie AUE_NULL #define LINUX_SYS_AUE_linux_epoll_create AUE_NULL #define LINUX_SYS_AUE_linux_epoll_ctl AUE_NULL #define LINUX_SYS_AUE_linux_epoll_wait AUE_NULL #define LINUX_SYS_AUE_linux_remap_file_pages AUE_NULL #define LINUX_SYS_AUE_linux_set_tid_address AUE_NULL #define LINUX_SYS_AUE_linux_timer_create AUE_NULL #define LINUX_SYS_AUE_linux_timer_settime AUE_NULL #define LINUX_SYS_AUE_linux_timer_gettime AUE_NULL #define LINUX_SYS_AUE_linux_timer_getoverrun AUE_NULL #define LINUX_SYS_AUE_linux_timer_delete AUE_NULL #define LINUX_SYS_AUE_linux_clock_settime AUE_CLOCK_SETTIME #define LINUX_SYS_AUE_linux_clock_gettime AUE_NULL #define LINUX_SYS_AUE_linux_clock_getres AUE_NULL #define LINUX_SYS_AUE_linux_clock_nanosleep AUE_NULL #define LINUX_SYS_AUE_linux_statfs64 AUE_STATFS #define LINUX_SYS_AUE_linux_fstatfs64 AUE_FSTATFS #define LINUX_SYS_AUE_linux_tgkill AUE_NULL #define LINUX_SYS_AUE_linux_utimes AUE_UTIMES #define LINUX_SYS_AUE_linux_fadvise64_64 AUE_NULL #define LINUX_SYS_AUE_linux_mbind AUE_NULL #define LINUX_SYS_AUE_linux_get_mempolicy AUE_NULL #define LINUX_SYS_AUE_linux_set_mempolicy AUE_NULL #define LINUX_SYS_AUE_linux_mq_open AUE_NULL #define LINUX_SYS_AUE_linux_mq_unlink AUE_NULL #define LINUX_SYS_AUE_linux_mq_timedsend AUE_NULL #define LINUX_SYS_AUE_linux_mq_timedreceive AUE_NULL #define LINUX_SYS_AUE_linux_mq_notify AUE_NULL #define LINUX_SYS_AUE_linux_mq_getsetattr AUE_NULL #define LINUX_SYS_AUE_linux_kexec_load AUE_NULL #define LINUX_SYS_AUE_linux_waitid AUE_NULL #define LINUX_SYS_AUE_linux_add_key AUE_NULL #define LINUX_SYS_AUE_linux_request_key AUE_NULL #define LINUX_SYS_AUE_linux_keyctl AUE_NULL #define LINUX_SYS_AUE_linux_ioprio_set AUE_NULL #define LINUX_SYS_AUE_linux_ioprio_get AUE_NULL #define LINUX_SYS_AUE_linux_inotify_init AUE_NULL #define LINUX_SYS_AUE_linux_inotify_add_watch AUE_NULL #define LINUX_SYS_AUE_linux_inotify_rm_watch AUE_NULL #define LINUX_SYS_AUE_linux_migrate_pages AUE_NULL #define LINUX_SYS_AUE_linux_openat AUE_NULL #define LINUX_SYS_AUE_linux_mkdirat AUE_NULL #define LINUX_SYS_AUE_linux_mknodat AUE_NULL #define LINUX_SYS_AUE_linux_fchownat AUE_NULL #define LINUX_SYS_AUE_linux_futimesat AUE_NULL #define LINUX_SYS_AUE_linux_fstatat64 AUE_NULL #define LINUX_SYS_AUE_linux_unlinkat AUE_NULL #define LINUX_SYS_AUE_linux_renameat AUE_NULL #define LINUX_SYS_AUE_linux_linkat AUE_NULL #define LINUX_SYS_AUE_linux_symlinkat AUE_NULL #define LINUX_SYS_AUE_linux_readlinkat AUE_NULL #define LINUX_SYS_AUE_linux_fchmodat AUE_NULL #define LINUX_SYS_AUE_linux_faccessat AUE_NULL #define LINUX_SYS_AUE_linux_pselect6 AUE_NULL #define LINUX_SYS_AUE_linux_ppoll AUE_NULL #define LINUX_SYS_AUE_linux_unshare AUE_NULL #undef PAD_ #undef PADL_ #undef PADR_ #endif /* !_LINUX_SYSPROTO_H_ */ Index: head/sys/kern/Make.tags.inc =================================================================== --- head/sys/kern/Make.tags.inc (revision 164183) +++ head/sys/kern/Make.tags.inc (revision 164184) @@ -1,101 +1,99 @@ # $FreeBSD$ # @(#)Make.tags.inc 8.1 (Berkeley) 6/11/93 SYS?= ${.CURDIR}/.. # Common files for "make tags", included by the Makefile for each # architecture. # Put the /sys/sys include files at the end so that subroutine definitions # win when there is a struct tag with the same name (e.g., vmmeter). The # better solution would be for ctags to generate "struct vmmeter" tags. COMM= ${SYS}/dev/advansys/*.[ch] \ ${SYS}/dev/aha/*.[ch] \ ${SYS}/dev/aic7xxx/*.[ch] \ ${SYS}/dev/buslogic/*.[ch] \ ${SYS}/dev/ccd/*.[ch] \ ${SYS}/dev/dec/*.[ch] \ ${SYS}/dev/dpt/*.[ch] \ ${SYS}/dev/en/*.[ch] \ ${SYS}/dev/hea/*.[ch] \ ${SYS}/dev/hfa/*.[ch] \ ${SYS}/dev/iicbus/*.[ch] \ ${SYS}/dev/isp/*.[ch] \ ${SYS}/dev/pdq/*.[ch] \ ${SYS}/dev/ppbus/*.[ch] \ ${SYS}/dev/smbus/*.[ch] \ ${SYS}/dev/vx/*.[ch] \ ${SYS}/fs/deadfs/*.[ch] \ ${SYS}/fs/fdescfs/*.[ch] \ ${SYS}/fs/fifofs/*.[ch] \ ${SYS}/fs/msdosfs/*.[ch] \ ${SYS}/fs/nullfs/*.[ch] \ ${SYS}/fs/portalfs/*.[ch] \ ${SYS}/fs/procfs/*.[ch] \ ${SYS}/fs/specfs/*.[ch] \ ${SYS}/fs/umapfs/*.[ch] \ ${SYS}/fs/unionfs/*.[ch] \ ${SYS}/isofs/cd9660/*.[ch] \ ${SYS}/kern/*.[ch] \ ${SYS}/net/*.[ch] \ ${SYS}/netatalk/*.[ch] \ ${SYS}/netatm/*.[ch] \ ${SYS}/netinet/*.[ch] \ ${SYS}/netipx/*.[ch] \ ${SYS}/netkey/*.[ch] \ ${SYS}/netnatm/*.[ch] \ ${SYS}/nfs/*.[ch] \ ${SYS}/pci/*.[ch] \ - ${SYS}/posix4/*.[ch] \ ${SYS}/ufs/ffs/*.[ch] \ ${SYS}/ufs/ufs/*.[ch] \ ${SYS}/vm/*.[ch] \ ${SYS}/sys/*.[ch] COMMDIR1= ${SYS}/conf \ ${SYS}/kern \ ${SYS}/net \ ${SYS}/netatalk \ ${SYS}/netatm \ ${SYS}/netinet \ ${SYS}/netipx \ ${SYS}/netkey \ ${SYS}/netnatm \ ${SYS}/nfs \ ${SYS}/pci \ - ${SYS}/posix4 \ ${SYS}/vm \ ${SYS}/sys COMMDIR2= ${SYS}/dev/advansys \ ${SYS}/dev/aha \ ${SYS}/dev/aic7xxx \ ${SYS}/dev/buslogic \ ${SYS}/dev/ccd \ ${SYS}/dev/dec \ ${SYS}/dev/dpt \ ${SYS}/dev/en \ ${SYS}/dev/hea \ ${SYS}/dev/hfa \ ${SYS}/dev/iicbus \ ${SYS}/dev/isp \ ${SYS}/dev/pdq \ ${SYS}/dev/ppbus \ ${SYS}/dev/smbus \ ${SYS}/dev/vn \ ${SYS}/dev/vx \ ${SYS}/fs/deadfs \ ${SYS}/fs/devfs \ ${SYS}/fs/fdescfs \ ${SYS}/fs/fifofs \ ${SYS}/fs/msdosfs \ ${SYS}/fs/nullfs \ ${SYS}/fs/portalfs \ ${SYS}/fs/procfs \ ${SYS}/fs/specfs \ ${SYS}/fs/umapfs \ ${SYS}/fs/unionfs \ ${SYS}/isofs/cd9660 \ ${SYS}/ufs/ffs \ ${SYS}/ufs/ufs Index: head/sys/kern/kern_sig.c =================================================================== --- head/sys/kern/kern_sig.c (revision 164183) +++ head/sys/kern/kern_sig.c (revision 164184) @@ -1,3366 +1,3365 @@ /*- * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_sig.c 8.7 (Berkeley) 4/18/94 */ #include __FBSDID("$FreeBSD$"); #include "opt_compat.h" #include "opt_ktrace.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include -#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include #include #include #define ONSIG 32 /* NSIG for osig* syscalls. XXX. */ static int coredump(struct thread *); static char *expand_name(const char *, uid_t, pid_t); static int killpg1(struct thread *td, int sig, int pgid, int all); static int issignal(struct thread *p); static int sigprop(int sig); static void tdsigwakeup(struct thread *, int, sig_t, int); static void sig_suspend_threads(struct thread *, struct proc *, int); static int filt_sigattach(struct knote *kn); static void filt_sigdetach(struct knote *kn); static int filt_signal(struct knote *kn, long hint); static struct thread *sigtd(struct proc *p, int sig, int prop); #ifdef KSE static int do_tdsignal(struct proc *, struct thread *, int, ksiginfo_t *); #endif static void sigqueue_start(void); static uma_zone_t ksiginfo_zone = NULL; struct filterops sig_filtops = { 0, filt_sigattach, filt_sigdetach, filt_signal }; static int kern_logsigexit = 1; SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW, &kern_logsigexit, 0, "Log processes quitting on abnormal signals to syslog(3)"); static int kern_forcesigexit = 1; SYSCTL_INT(_kern, OID_AUTO, forcesigexit, CTLFLAG_RW, &kern_forcesigexit, 0, "Force trap signal to be handled"); SYSCTL_NODE(_kern, OID_AUTO, sigqueue, CTLFLAG_RW, 0, "POSIX real time signal"); static int max_pending_per_proc = 128; SYSCTL_INT(_kern_sigqueue, OID_AUTO, max_pending_per_proc, CTLFLAG_RW, &max_pending_per_proc, 0, "Max pending signals per proc"); static int preallocate_siginfo = 1024; TUNABLE_INT("kern.sigqueue.preallocate", &preallocate_siginfo); SYSCTL_INT(_kern_sigqueue, OID_AUTO, preallocate, CTLFLAG_RD, &preallocate_siginfo, 0, "Preallocated signal memory size"); static int signal_overflow = 0; SYSCTL_INT(_kern_sigqueue, OID_AUTO, overflow, CTLFLAG_RD, &signal_overflow, 0, "Number of signals overflew"); static int signal_alloc_fail = 0; SYSCTL_INT(_kern_sigqueue, OID_AUTO, alloc_fail, CTLFLAG_RD, &signal_alloc_fail, 0, "signals failed to be allocated"); SYSINIT(signal, SI_SUB_P1003_1B, SI_ORDER_FIRST+3, sigqueue_start, NULL); /* * Policy -- Can ucred cr1 send SIGIO to process cr2? * Should use cr_cansignal() once cr_cansignal() allows SIGIO and SIGURG * in the right situations. */ #define CANSIGIO(cr1, cr2) \ ((cr1)->cr_uid == 0 || \ (cr1)->cr_ruid == (cr2)->cr_ruid || \ (cr1)->cr_uid == (cr2)->cr_ruid || \ (cr1)->cr_ruid == (cr2)->cr_uid || \ (cr1)->cr_uid == (cr2)->cr_uid) int sugid_coredump; SYSCTL_INT(_kern, OID_AUTO, sugid_coredump, CTLFLAG_RW, &sugid_coredump, 0, "Enable coredumping set user/group ID processes"); static int do_coredump = 1; SYSCTL_INT(_kern, OID_AUTO, coredump, CTLFLAG_RW, &do_coredump, 0, "Enable/Disable coredumps"); static int set_core_nodump_flag = 0; SYSCTL_INT(_kern, OID_AUTO, nodump_coredump, CTLFLAG_RW, &set_core_nodump_flag, 0, "Enable setting the NODUMP flag on coredump files"); /* * Signal properties and actions. * The array below categorizes the signals and their default actions * according to the following properties: */ #define SA_KILL 0x01 /* terminates process by default */ #define SA_CORE 0x02 /* ditto and coredumps */ #define SA_STOP 0x04 /* suspend process */ #define SA_TTYSTOP 0x08 /* ditto, from tty */ #define SA_IGNORE 0x10 /* ignore by default */ #define SA_CONT 0x20 /* continue if suspended */ #define SA_CANTMASK 0x40 /* non-maskable, catchable */ #define SA_PROC 0x80 /* deliverable to any thread */ static int sigproptbl[NSIG] = { SA_KILL|SA_PROC, /* SIGHUP */ SA_KILL|SA_PROC, /* SIGINT */ SA_KILL|SA_CORE|SA_PROC, /* SIGQUIT */ SA_KILL|SA_CORE, /* SIGILL */ SA_KILL|SA_CORE, /* SIGTRAP */ SA_KILL|SA_CORE, /* SIGABRT */ SA_KILL|SA_CORE|SA_PROC, /* SIGEMT */ SA_KILL|SA_CORE, /* SIGFPE */ SA_KILL|SA_PROC, /* SIGKILL */ SA_KILL|SA_CORE, /* SIGBUS */ SA_KILL|SA_CORE, /* SIGSEGV */ SA_KILL|SA_CORE, /* SIGSYS */ SA_KILL|SA_PROC, /* SIGPIPE */ SA_KILL|SA_PROC, /* SIGALRM */ SA_KILL|SA_PROC, /* SIGTERM */ SA_IGNORE|SA_PROC, /* SIGURG */ SA_STOP|SA_PROC, /* SIGSTOP */ SA_STOP|SA_TTYSTOP|SA_PROC, /* SIGTSTP */ SA_IGNORE|SA_CONT|SA_PROC, /* SIGCONT */ SA_IGNORE|SA_PROC, /* SIGCHLD */ SA_STOP|SA_TTYSTOP|SA_PROC, /* SIGTTIN */ SA_STOP|SA_TTYSTOP|SA_PROC, /* SIGTTOU */ SA_IGNORE|SA_PROC, /* SIGIO */ SA_KILL, /* SIGXCPU */ SA_KILL, /* SIGXFSZ */ SA_KILL|SA_PROC, /* SIGVTALRM */ SA_KILL|SA_PROC, /* SIGPROF */ SA_IGNORE|SA_PROC, /* SIGWINCH */ SA_IGNORE|SA_PROC, /* SIGINFO */ SA_KILL|SA_PROC, /* SIGUSR1 */ SA_KILL|SA_PROC, /* SIGUSR2 */ }; static void sigqueue_start(void) { ksiginfo_zone = uma_zcreate("ksiginfo", sizeof(ksiginfo_t), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); uma_prealloc(ksiginfo_zone, preallocate_siginfo); p31b_setcfg(CTL_P1003_1B_REALTIME_SIGNALS, _POSIX_REALTIME_SIGNALS); p31b_setcfg(CTL_P1003_1B_RTSIG_MAX, SIGRTMAX - SIGRTMIN + 1); p31b_setcfg(CTL_P1003_1B_SIGQUEUE_MAX, max_pending_per_proc); } ksiginfo_t * ksiginfo_alloc(int wait) { int flags; flags = M_ZERO; if (! wait) flags |= M_NOWAIT; if (ksiginfo_zone != NULL) return ((ksiginfo_t *)uma_zalloc(ksiginfo_zone, flags)); return (NULL); } void ksiginfo_free(ksiginfo_t *ksi) { uma_zfree(ksiginfo_zone, ksi); } static __inline int ksiginfo_tryfree(ksiginfo_t *ksi) { if (!(ksi->ksi_flags & KSI_EXT)) { uma_zfree(ksiginfo_zone, ksi); return (1); } return (0); } void sigqueue_init(sigqueue_t *list, struct proc *p) { SIGEMPTYSET(list->sq_signals); SIGEMPTYSET(list->sq_kill); TAILQ_INIT(&list->sq_list); list->sq_proc = p; list->sq_flags = SQ_INIT; } /* * Get a signal's ksiginfo. * Return: * 0 - signal not found * others - signal number */ int sigqueue_get(sigqueue_t *sq, int signo, ksiginfo_t *si) { struct proc *p = sq->sq_proc; struct ksiginfo *ksi, *next; int count = 0; KASSERT(sq->sq_flags & SQ_INIT, ("sigqueue not inited")); if (!SIGISMEMBER(sq->sq_signals, signo)) return (0); if (SIGISMEMBER(sq->sq_kill, signo)) { count++; SIGDELSET(sq->sq_kill, signo); } TAILQ_FOREACH_SAFE(ksi, &sq->sq_list, ksi_link, next) { if (ksi->ksi_signo == signo) { if (count == 0) { TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link); ksi->ksi_sigq = NULL; ksiginfo_copy(ksi, si); if (ksiginfo_tryfree(ksi) && p != NULL) p->p_pendingcnt--; } count++; } } if (count <= 1) SIGDELSET(sq->sq_signals, signo); si->ksi_signo = signo; return (signo); } void sigqueue_take(ksiginfo_t *ksi) { struct ksiginfo *kp; struct proc *p; sigqueue_t *sq; if (ksi == NULL || (sq = ksi->ksi_sigq) == NULL) return; p = sq->sq_proc; TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link); ksi->ksi_sigq = NULL; if (!(ksi->ksi_flags & KSI_EXT) && p != NULL) p->p_pendingcnt--; for (kp = TAILQ_FIRST(&sq->sq_list); kp != NULL; kp = TAILQ_NEXT(kp, ksi_link)) { if (kp->ksi_signo == ksi->ksi_signo) break; } if (kp == NULL && !SIGISMEMBER(sq->sq_kill, ksi->ksi_signo)) SIGDELSET(sq->sq_signals, ksi->ksi_signo); } int sigqueue_add(sigqueue_t *sq, int signo, ksiginfo_t *si) { struct proc *p = sq->sq_proc; struct ksiginfo *ksi; int ret = 0; KASSERT(sq->sq_flags & SQ_INIT, ("sigqueue not inited")); if (signo == SIGKILL || signo == SIGSTOP || si == NULL) { SIGADDSET(sq->sq_kill, signo); goto out_set_bit; } /* directly insert the ksi, don't copy it */ if (si->ksi_flags & KSI_INS) { TAILQ_INSERT_TAIL(&sq->sq_list, si, ksi_link); si->ksi_sigq = sq; goto out_set_bit; } if (__predict_false(ksiginfo_zone == NULL)) { SIGADDSET(sq->sq_kill, signo); goto out_set_bit; } if (p != NULL && p->p_pendingcnt >= max_pending_per_proc) { signal_overflow++; ret = EAGAIN; } else if ((ksi = ksiginfo_alloc(0)) == NULL) { signal_alloc_fail++; ret = EAGAIN; } else { if (p != NULL) p->p_pendingcnt++; ksiginfo_copy(si, ksi); ksi->ksi_signo = signo; TAILQ_INSERT_TAIL(&sq->sq_list, ksi, ksi_link); ksi->ksi_sigq = sq; } if ((si->ksi_flags & KSI_TRAP) != 0) { if (ret != 0) SIGADDSET(sq->sq_kill, signo); ret = 0; goto out_set_bit; } if (ret != 0) return (ret); out_set_bit: SIGADDSET(sq->sq_signals, signo); return (ret); } void sigqueue_flush(sigqueue_t *sq) { struct proc *p = sq->sq_proc; ksiginfo_t *ksi; KASSERT(sq->sq_flags & SQ_INIT, ("sigqueue not inited")); if (p != NULL) PROC_LOCK_ASSERT(p, MA_OWNED); while ((ksi = TAILQ_FIRST(&sq->sq_list)) != NULL) { TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link); ksi->ksi_sigq = NULL; if (ksiginfo_tryfree(ksi) && p != NULL) p->p_pendingcnt--; } SIGEMPTYSET(sq->sq_signals); SIGEMPTYSET(sq->sq_kill); } void sigqueue_collect_set(sigqueue_t *sq, sigset_t *set) { ksiginfo_t *ksi; KASSERT(sq->sq_flags & SQ_INIT, ("sigqueue not inited")); TAILQ_FOREACH(ksi, &sq->sq_list, ksi_link) SIGADDSET(*set, ksi->ksi_signo); SIGSETOR(*set, sq->sq_kill); } void sigqueue_move_set(sigqueue_t *src, sigqueue_t *dst, sigset_t *setp) { sigset_t tmp, set; struct proc *p1, *p2; ksiginfo_t *ksi, *next; KASSERT(src->sq_flags & SQ_INIT, ("src sigqueue not inited")); KASSERT(dst->sq_flags & SQ_INIT, ("dst sigqueue not inited")); /* * make a copy, this allows setp to point to src or dst * sq_signals without trouble. */ set = *setp; p1 = src->sq_proc; p2 = dst->sq_proc; /* Move siginfo to target list */ TAILQ_FOREACH_SAFE(ksi, &src->sq_list, ksi_link, next) { if (SIGISMEMBER(set, ksi->ksi_signo)) { TAILQ_REMOVE(&src->sq_list, ksi, ksi_link); if (p1 != NULL) p1->p_pendingcnt--; TAILQ_INSERT_TAIL(&dst->sq_list, ksi, ksi_link); ksi->ksi_sigq = dst; if (p2 != NULL) p2->p_pendingcnt++; } } /* Move pending bits to target list */ tmp = src->sq_kill; SIGSETAND(tmp, set); SIGSETOR(dst->sq_kill, tmp); SIGSETNAND(src->sq_kill, tmp); tmp = src->sq_signals; SIGSETAND(tmp, set); SIGSETOR(dst->sq_signals, tmp); SIGSETNAND(src->sq_signals, tmp); /* Finally, rescan src queue and set pending bits for it */ sigqueue_collect_set(src, &src->sq_signals); } void sigqueue_move(sigqueue_t *src, sigqueue_t *dst, int signo) { sigset_t set; SIGEMPTYSET(set); SIGADDSET(set, signo); sigqueue_move_set(src, dst, &set); } void sigqueue_delete_set(sigqueue_t *sq, sigset_t *set) { struct proc *p = sq->sq_proc; ksiginfo_t *ksi, *next; KASSERT(sq->sq_flags & SQ_INIT, ("src sigqueue not inited")); /* Remove siginfo queue */ TAILQ_FOREACH_SAFE(ksi, &sq->sq_list, ksi_link, next) { if (SIGISMEMBER(*set, ksi->ksi_signo)) { TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link); ksi->ksi_sigq = NULL; if (ksiginfo_tryfree(ksi) && p != NULL) p->p_pendingcnt--; } } SIGSETNAND(sq->sq_kill, *set); SIGSETNAND(sq->sq_signals, *set); /* Finally, rescan queue and set pending bits for it */ sigqueue_collect_set(sq, &sq->sq_signals); } void sigqueue_delete(sigqueue_t *sq, int signo) { sigset_t set; SIGEMPTYSET(set); SIGADDSET(set, signo); sigqueue_delete_set(sq, &set); } /* Remove a set of signals for a process */ void sigqueue_delete_set_proc(struct proc *p, sigset_t *set) { sigqueue_t worklist; struct thread *td0; PROC_LOCK_ASSERT(p, MA_OWNED); sigqueue_init(&worklist, NULL); sigqueue_move_set(&p->p_sigqueue, &worklist, set); mtx_lock_spin(&sched_lock); FOREACH_THREAD_IN_PROC(p, td0) sigqueue_move_set(&td0->td_sigqueue, &worklist, set); mtx_unlock_spin(&sched_lock); sigqueue_flush(&worklist); } void sigqueue_delete_proc(struct proc *p, int signo) { sigset_t set; SIGEMPTYSET(set); SIGADDSET(set, signo); sigqueue_delete_set_proc(p, &set); } void sigqueue_delete_stopmask_proc(struct proc *p) { sigset_t set; SIGEMPTYSET(set); SIGADDSET(set, SIGSTOP); SIGADDSET(set, SIGTSTP); SIGADDSET(set, SIGTTIN); SIGADDSET(set, SIGTTOU); sigqueue_delete_set_proc(p, &set); } /* * Determine signal that should be delivered to process p, the current * process, 0 if none. If there is a pending stop signal with default * action, the process stops in issignal(). * * MP SAFE. */ int cursig(struct thread *td) { PROC_LOCK_ASSERT(td->td_proc, MA_OWNED); mtx_assert(&td->td_proc->p_sigacts->ps_mtx, MA_OWNED); mtx_assert(&sched_lock, MA_NOTOWNED); return (SIGPENDING(td) ? issignal(td) : 0); } /* * Arrange for ast() to handle unmasked pending signals on return to user * mode. This must be called whenever a signal is added to td_sigqueue or * unmasked in td_sigmask. */ void signotify(struct thread *td) { struct proc *p; #ifdef KSE sigset_t set, saved; #else sigset_t set; #endif p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); /* * If our mask changed we may have to move signal that were * previously masked by all threads to our sigqueue. */ set = p->p_sigqueue.sq_signals; #ifdef KSE if (p->p_flag & P_SA) saved = p->p_sigqueue.sq_signals; #endif SIGSETNAND(set, td->td_sigmask); if (! SIGISEMPTY(set)) sigqueue_move_set(&p->p_sigqueue, &td->td_sigqueue, &set); if (SIGPENDING(td)) { mtx_lock_spin(&sched_lock); td->td_flags |= TDF_NEEDSIGCHK | TDF_ASTPENDING; mtx_unlock_spin(&sched_lock); } #ifdef KSE if ((p->p_flag & P_SA) && !(p->p_flag & P_SIGEVENT)) { if (!SIGSETEQ(saved, p->p_sigqueue.sq_signals)) { /* pending set changed */ p->p_flag |= P_SIGEVENT; wakeup(&p->p_siglist); } } #endif } int sigonstack(size_t sp) { struct thread *td = curthread; return ((td->td_pflags & TDP_ALTSTACK) ? #if defined(COMPAT_43) ((td->td_sigstk.ss_size == 0) ? (td->td_sigstk.ss_flags & SS_ONSTACK) : ((sp - (size_t)td->td_sigstk.ss_sp) < td->td_sigstk.ss_size)) #else ((sp - (size_t)td->td_sigstk.ss_sp) < td->td_sigstk.ss_size) #endif : 0); } static __inline int sigprop(int sig) { if (sig > 0 && sig < NSIG) return (sigproptbl[_SIG_IDX(sig)]); return (0); } int sig_ffs(sigset_t *set) { int i; for (i = 0; i < _SIG_WORDS; i++) if (set->__bits[i]) return (ffs(set->__bits[i]) + (i * 32)); return (0); } /* * kern_sigaction * sigaction * freebsd4_sigaction * osigaction * * MPSAFE */ int kern_sigaction(td, sig, act, oact, flags) struct thread *td; register int sig; struct sigaction *act, *oact; int flags; { struct sigacts *ps; struct proc *p = td->td_proc; if (!_SIG_VALID(sig)) return (EINVAL); PROC_LOCK(p); ps = p->p_sigacts; mtx_lock(&ps->ps_mtx); if (oact) { oact->sa_handler = ps->ps_sigact[_SIG_IDX(sig)]; oact->sa_mask = ps->ps_catchmask[_SIG_IDX(sig)]; oact->sa_flags = 0; if (SIGISMEMBER(ps->ps_sigonstack, sig)) oact->sa_flags |= SA_ONSTACK; if (!SIGISMEMBER(ps->ps_sigintr, sig)) oact->sa_flags |= SA_RESTART; if (SIGISMEMBER(ps->ps_sigreset, sig)) oact->sa_flags |= SA_RESETHAND; if (SIGISMEMBER(ps->ps_signodefer, sig)) oact->sa_flags |= SA_NODEFER; if (SIGISMEMBER(ps->ps_siginfo, sig)) oact->sa_flags |= SA_SIGINFO; if (sig == SIGCHLD && ps->ps_flag & PS_NOCLDSTOP) oact->sa_flags |= SA_NOCLDSTOP; if (sig == SIGCHLD && ps->ps_flag & PS_NOCLDWAIT) oact->sa_flags |= SA_NOCLDWAIT; } if (act) { if ((sig == SIGKILL || sig == SIGSTOP) && act->sa_handler != SIG_DFL) { mtx_unlock(&ps->ps_mtx); PROC_UNLOCK(p); return (EINVAL); } /* * Change setting atomically. */ ps->ps_catchmask[_SIG_IDX(sig)] = act->sa_mask; SIG_CANTMASK(ps->ps_catchmask[_SIG_IDX(sig)]); if (act->sa_flags & SA_SIGINFO) { ps->ps_sigact[_SIG_IDX(sig)] = (__sighandler_t *)act->sa_sigaction; SIGADDSET(ps->ps_siginfo, sig); } else { ps->ps_sigact[_SIG_IDX(sig)] = act->sa_handler; SIGDELSET(ps->ps_siginfo, sig); } if (!(act->sa_flags & SA_RESTART)) SIGADDSET(ps->ps_sigintr, sig); else SIGDELSET(ps->ps_sigintr, sig); if (act->sa_flags & SA_ONSTACK) SIGADDSET(ps->ps_sigonstack, sig); else SIGDELSET(ps->ps_sigonstack, sig); if (act->sa_flags & SA_RESETHAND) SIGADDSET(ps->ps_sigreset, sig); else SIGDELSET(ps->ps_sigreset, sig); if (act->sa_flags & SA_NODEFER) SIGADDSET(ps->ps_signodefer, sig); else SIGDELSET(ps->ps_signodefer, sig); if (sig == SIGCHLD) { if (act->sa_flags & SA_NOCLDSTOP) ps->ps_flag |= PS_NOCLDSTOP; else ps->ps_flag &= ~PS_NOCLDSTOP; if (act->sa_flags & SA_NOCLDWAIT) { /* * Paranoia: since SA_NOCLDWAIT is implemented * by reparenting the dying child to PID 1 (and * trust it to reap the zombie), PID 1 itself * is forbidden to set SA_NOCLDWAIT. */ if (p->p_pid == 1) ps->ps_flag &= ~PS_NOCLDWAIT; else ps->ps_flag |= PS_NOCLDWAIT; } else ps->ps_flag &= ~PS_NOCLDWAIT; if (ps->ps_sigact[_SIG_IDX(SIGCHLD)] == SIG_IGN) ps->ps_flag |= PS_CLDSIGIGN; else ps->ps_flag &= ~PS_CLDSIGIGN; } /* * Set bit in ps_sigignore for signals that are set to SIG_IGN, * and for signals set to SIG_DFL where the default is to * ignore. However, don't put SIGCONT in ps_sigignore, as we * have to restart the process. */ if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN || (sigprop(sig) & SA_IGNORE && ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL)) { #ifdef KSE if ((p->p_flag & P_SA) && SIGISMEMBER(p->p_sigqueue.sq_signals, sig)) { p->p_flag |= P_SIGEVENT; wakeup(&p->p_siglist); } #endif /* never to be seen again */ sigqueue_delete_proc(p, sig); if (sig != SIGCONT) /* easier in psignal */ SIGADDSET(ps->ps_sigignore, sig); SIGDELSET(ps->ps_sigcatch, sig); } else { SIGDELSET(ps->ps_sigignore, sig); if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL) SIGDELSET(ps->ps_sigcatch, sig); else SIGADDSET(ps->ps_sigcatch, sig); } #ifdef COMPAT_FREEBSD4 if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN || ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL || (flags & KSA_FREEBSD4) == 0) SIGDELSET(ps->ps_freebsd4, sig); else SIGADDSET(ps->ps_freebsd4, sig); #endif #ifdef COMPAT_43 if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN || ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL || (flags & KSA_OSIGSET) == 0) SIGDELSET(ps->ps_osigset, sig); else SIGADDSET(ps->ps_osigset, sig); #endif } mtx_unlock(&ps->ps_mtx); PROC_UNLOCK(p); return (0); } #ifndef _SYS_SYSPROTO_H_ struct sigaction_args { int sig; struct sigaction *act; struct sigaction *oact; }; #endif /* * MPSAFE */ int sigaction(td, uap) struct thread *td; register struct sigaction_args *uap; { struct sigaction act, oact; register struct sigaction *actp, *oactp; int error; actp = (uap->act != NULL) ? &act : NULL; oactp = (uap->oact != NULL) ? &oact : NULL; if (actp) { error = copyin(uap->act, actp, sizeof(act)); if (error) return (error); } error = kern_sigaction(td, uap->sig, actp, oactp, 0); if (oactp && !error) error = copyout(oactp, uap->oact, sizeof(oact)); return (error); } #ifdef COMPAT_FREEBSD4 #ifndef _SYS_SYSPROTO_H_ struct freebsd4_sigaction_args { int sig; struct sigaction *act; struct sigaction *oact; }; #endif /* * MPSAFE */ int freebsd4_sigaction(td, uap) struct thread *td; register struct freebsd4_sigaction_args *uap; { struct sigaction act, oact; register struct sigaction *actp, *oactp; int error; actp = (uap->act != NULL) ? &act : NULL; oactp = (uap->oact != NULL) ? &oact : NULL; if (actp) { error = copyin(uap->act, actp, sizeof(act)); if (error) return (error); } error = kern_sigaction(td, uap->sig, actp, oactp, KSA_FREEBSD4); if (oactp && !error) error = copyout(oactp, uap->oact, sizeof(oact)); return (error); } #endif /* COMAPT_FREEBSD4 */ #ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */ #ifndef _SYS_SYSPROTO_H_ struct osigaction_args { int signum; struct osigaction *nsa; struct osigaction *osa; }; #endif /* * MPSAFE */ int osigaction(td, uap) struct thread *td; register struct osigaction_args *uap; { struct osigaction sa; struct sigaction nsa, osa; register struct sigaction *nsap, *osap; int error; if (uap->signum <= 0 || uap->signum >= ONSIG) return (EINVAL); nsap = (uap->nsa != NULL) ? &nsa : NULL; osap = (uap->osa != NULL) ? &osa : NULL; if (nsap) { error = copyin(uap->nsa, &sa, sizeof(sa)); if (error) return (error); nsap->sa_handler = sa.sa_handler; nsap->sa_flags = sa.sa_flags; OSIG2SIG(sa.sa_mask, nsap->sa_mask); } error = kern_sigaction(td, uap->signum, nsap, osap, KSA_OSIGSET); if (osap && !error) { sa.sa_handler = osap->sa_handler; sa.sa_flags = osap->sa_flags; SIG2OSIG(osap->sa_mask, sa.sa_mask); error = copyout(&sa, uap->osa, sizeof(sa)); } return (error); } #if !defined(__i386__) /* Avoid replicating the same stub everywhere */ int osigreturn(td, uap) struct thread *td; struct osigreturn_args *uap; { return (nosys(td, (struct nosys_args *)uap)); } #endif #endif /* COMPAT_43 */ /* * Initialize signal state for process 0; * set to ignore signals that are ignored by default. */ void siginit(p) struct proc *p; { register int i; struct sigacts *ps; PROC_LOCK(p); ps = p->p_sigacts; mtx_lock(&ps->ps_mtx); for (i = 1; i <= NSIG; i++) if (sigprop(i) & SA_IGNORE && i != SIGCONT) SIGADDSET(ps->ps_sigignore, i); mtx_unlock(&ps->ps_mtx); PROC_UNLOCK(p); } /* * Reset signals for an exec of the specified process. */ void execsigs(struct proc *p) { struct sigacts *ps; int sig; struct thread *td; /* * Reset caught signals. Held signals remain held * through td_sigmask (unless they were caught, * and are now ignored by default). */ PROC_LOCK_ASSERT(p, MA_OWNED); td = FIRST_THREAD_IN_PROC(p); ps = p->p_sigacts; mtx_lock(&ps->ps_mtx); while (SIGNOTEMPTY(ps->ps_sigcatch)) { sig = sig_ffs(&ps->ps_sigcatch); SIGDELSET(ps->ps_sigcatch, sig); if (sigprop(sig) & SA_IGNORE) { if (sig != SIGCONT) SIGADDSET(ps->ps_sigignore, sig); sigqueue_delete_proc(p, sig); } ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL; } /* * Reset stack state to the user stack. * Clear set of signals caught on the signal stack. */ td->td_sigstk.ss_flags = SS_DISABLE; td->td_sigstk.ss_size = 0; td->td_sigstk.ss_sp = 0; td->td_pflags &= ~TDP_ALTSTACK; /* * Reset no zombies if child dies flag as Solaris does. */ ps->ps_flag &= ~(PS_NOCLDWAIT | PS_CLDSIGIGN); if (ps->ps_sigact[_SIG_IDX(SIGCHLD)] == SIG_IGN) ps->ps_sigact[_SIG_IDX(SIGCHLD)] = SIG_DFL; mtx_unlock(&ps->ps_mtx); } /* * kern_sigprocmask() * * Manipulate signal mask. */ int kern_sigprocmask(td, how, set, oset, old) struct thread *td; int how; sigset_t *set, *oset; int old; { int error; PROC_LOCK(td->td_proc); if (oset != NULL) *oset = td->td_sigmask; error = 0; if (set != NULL) { switch (how) { case SIG_BLOCK: SIG_CANTMASK(*set); SIGSETOR(td->td_sigmask, *set); break; case SIG_UNBLOCK: SIGSETNAND(td->td_sigmask, *set); signotify(td); break; case SIG_SETMASK: SIG_CANTMASK(*set); if (old) SIGSETLO(td->td_sigmask, *set); else td->td_sigmask = *set; signotify(td); break; default: error = EINVAL; break; } } PROC_UNLOCK(td->td_proc); return (error); } /* * sigprocmask() - MP SAFE */ #ifndef _SYS_SYSPROTO_H_ struct sigprocmask_args { int how; const sigset_t *set; sigset_t *oset; }; #endif int sigprocmask(td, uap) register struct thread *td; struct sigprocmask_args *uap; { sigset_t set, oset; sigset_t *setp, *osetp; int error; setp = (uap->set != NULL) ? &set : NULL; osetp = (uap->oset != NULL) ? &oset : NULL; if (setp) { error = copyin(uap->set, setp, sizeof(set)); if (error) return (error); } error = kern_sigprocmask(td, uap->how, setp, osetp, 0); if (osetp && !error) { error = copyout(osetp, uap->oset, sizeof(oset)); } return (error); } #ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */ /* * osigprocmask() - MP SAFE */ #ifndef _SYS_SYSPROTO_H_ struct osigprocmask_args { int how; osigset_t mask; }; #endif int osigprocmask(td, uap) register struct thread *td; struct osigprocmask_args *uap; { sigset_t set, oset; int error; OSIG2SIG(uap->mask, set); error = kern_sigprocmask(td, uap->how, &set, &oset, 1); SIG2OSIG(oset, td->td_retval[0]); return (error); } #endif /* COMPAT_43 */ /* * MPSAFE */ int sigwait(struct thread *td, struct sigwait_args *uap) { ksiginfo_t ksi; sigset_t set; int error; error = copyin(uap->set, &set, sizeof(set)); if (error) { td->td_retval[0] = error; return (0); } error = kern_sigtimedwait(td, set, &ksi, NULL); if (error) { if (error == ERESTART) return (error); td->td_retval[0] = error; return (0); } error = copyout(&ksi.ksi_signo, uap->sig, sizeof(ksi.ksi_signo)); td->td_retval[0] = error; return (0); } /* * MPSAFE */ int sigtimedwait(struct thread *td, struct sigtimedwait_args *uap) { struct timespec ts; struct timespec *timeout; sigset_t set; ksiginfo_t ksi; int error; if (uap->timeout) { error = copyin(uap->timeout, &ts, sizeof(ts)); if (error) return (error); timeout = &ts; } else timeout = NULL; error = copyin(uap->set, &set, sizeof(set)); if (error) return (error); error = kern_sigtimedwait(td, set, &ksi, timeout); if (error) return (error); if (uap->info) error = copyout(&ksi.ksi_info, uap->info, sizeof(siginfo_t)); if (error == 0) td->td_retval[0] = ksi.ksi_signo; return (error); } /* * MPSAFE */ int sigwaitinfo(struct thread *td, struct sigwaitinfo_args *uap) { ksiginfo_t ksi; sigset_t set; int error; error = copyin(uap->set, &set, sizeof(set)); if (error) return (error); error = kern_sigtimedwait(td, set, &ksi, NULL); if (error) return (error); if (uap->info) error = copyout(&ksi.ksi_info, uap->info, sizeof(siginfo_t)); if (error == 0) td->td_retval[0] = ksi.ksi_signo; return (error); } int kern_sigtimedwait(struct thread *td, sigset_t waitset, ksiginfo_t *ksi, struct timespec *timeout) { struct sigacts *ps; sigset_t savedmask; struct proc *p; int error, sig, hz, i, timevalid = 0; struct timespec rts, ets, ts; struct timeval tv; p = td->td_proc; error = 0; sig = 0; SIG_CANTMASK(waitset); PROC_LOCK(p); ps = p->p_sigacts; savedmask = td->td_sigmask; if (timeout) { if (timeout->tv_nsec >= 0 && timeout->tv_nsec < 1000000000) { timevalid = 1; getnanouptime(&rts); ets = rts; timespecadd(&ets, timeout); } } restart: for (i = 1; i <= _SIG_MAXSIG; ++i) { if (!SIGISMEMBER(waitset, i)) continue; if (!SIGISMEMBER(td->td_sigqueue.sq_signals, i)) { if (SIGISMEMBER(p->p_sigqueue.sq_signals, i)) { #ifdef KSE if (p->p_flag & P_SA) { p->p_flag |= P_SIGEVENT; wakeup(&p->p_siglist); } #endif sigqueue_move(&p->p_sigqueue, &td->td_sigqueue, i); } else continue; } SIGFILLSET(td->td_sigmask); SIG_CANTMASK(td->td_sigmask); SIGDELSET(td->td_sigmask, i); mtx_lock(&ps->ps_mtx); sig = cursig(td); mtx_unlock(&ps->ps_mtx); if (sig) goto out; else { /* * Because cursig() may have stopped current thread, * after it is resumed, things may have already been * changed, it should rescan any pending signals. */ goto restart; } } if (error) goto out; /* * POSIX says this must be checked after looking for pending * signals. */ if (timeout) { if (!timevalid) { error = EINVAL; goto out; } getnanouptime(&rts); if (timespeccmp(&rts, &ets, >=)) { error = EAGAIN; goto out; } ts = ets; timespecsub(&ts, &rts); TIMESPEC_TO_TIMEVAL(&tv, &ts); hz = tvtohz(&tv); } else hz = 0; td->td_sigmask = savedmask; SIGSETNAND(td->td_sigmask, waitset); signotify(td); error = msleep(&ps, &p->p_mtx, PPAUSE|PCATCH, "sigwait", hz); if (timeout) { if (error == ERESTART) { /* timeout can not be restarted. */ error = EINTR; } else if (error == EAGAIN) { /* will calculate timeout by ourself. */ error = 0; } } goto restart; out: td->td_sigmask = savedmask; signotify(td); if (sig) { ksiginfo_init(ksi); sigqueue_get(&td->td_sigqueue, sig, ksi); ksi->ksi_signo = sig; if (ksi->ksi_code == SI_TIMER) itimer_accept(p, ksi->ksi_timerid, ksi); error = 0; #ifdef KTRACE if (KTRPOINT(td, KTR_PSIG)) { sig_t action; mtx_lock(&ps->ps_mtx); action = ps->ps_sigact[_SIG_IDX(sig)]; mtx_unlock(&ps->ps_mtx); ktrpsig(sig, action, &td->td_sigmask, 0); } #endif if (sig == SIGKILL) sigexit(td, sig); } PROC_UNLOCK(p); return (error); } #ifndef _SYS_SYSPROTO_H_ struct sigpending_args { sigset_t *set; }; #endif /* * MPSAFE */ int sigpending(td, uap) struct thread *td; struct sigpending_args *uap; { struct proc *p = td->td_proc; sigset_t pending; PROC_LOCK(p); pending = p->p_sigqueue.sq_signals; SIGSETOR(pending, td->td_sigqueue.sq_signals); PROC_UNLOCK(p); return (copyout(&pending, uap->set, sizeof(sigset_t))); } #ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */ #ifndef _SYS_SYSPROTO_H_ struct osigpending_args { int dummy; }; #endif /* * MPSAFE */ int osigpending(td, uap) struct thread *td; struct osigpending_args *uap; { struct proc *p = td->td_proc; sigset_t pending; PROC_LOCK(p); pending = p->p_sigqueue.sq_signals; SIGSETOR(pending, td->td_sigqueue.sq_signals); PROC_UNLOCK(p); SIG2OSIG(pending, td->td_retval[0]); return (0); } #endif /* COMPAT_43 */ #if defined(COMPAT_43) /* * Generalized interface signal handler, 4.3-compatible. */ #ifndef _SYS_SYSPROTO_H_ struct osigvec_args { int signum; struct sigvec *nsv; struct sigvec *osv; }; #endif /* * MPSAFE */ /* ARGSUSED */ int osigvec(td, uap) struct thread *td; register struct osigvec_args *uap; { struct sigvec vec; struct sigaction nsa, osa; register struct sigaction *nsap, *osap; int error; if (uap->signum <= 0 || uap->signum >= ONSIG) return (EINVAL); nsap = (uap->nsv != NULL) ? &nsa : NULL; osap = (uap->osv != NULL) ? &osa : NULL; if (nsap) { error = copyin(uap->nsv, &vec, sizeof(vec)); if (error) return (error); nsap->sa_handler = vec.sv_handler; OSIG2SIG(vec.sv_mask, nsap->sa_mask); nsap->sa_flags = vec.sv_flags; nsap->sa_flags ^= SA_RESTART; /* opposite of SV_INTERRUPT */ } error = kern_sigaction(td, uap->signum, nsap, osap, KSA_OSIGSET); if (osap && !error) { vec.sv_handler = osap->sa_handler; SIG2OSIG(osap->sa_mask, vec.sv_mask); vec.sv_flags = osap->sa_flags; vec.sv_flags &= ~SA_NOCLDWAIT; vec.sv_flags ^= SA_RESTART; error = copyout(&vec, uap->osv, sizeof(vec)); } return (error); } #ifndef _SYS_SYSPROTO_H_ struct osigblock_args { int mask; }; #endif /* * MPSAFE */ int osigblock(td, uap) register struct thread *td; struct osigblock_args *uap; { struct proc *p = td->td_proc; sigset_t set; OSIG2SIG(uap->mask, set); SIG_CANTMASK(set); PROC_LOCK(p); SIG2OSIG(td->td_sigmask, td->td_retval[0]); SIGSETOR(td->td_sigmask, set); PROC_UNLOCK(p); return (0); } #ifndef _SYS_SYSPROTO_H_ struct osigsetmask_args { int mask; }; #endif /* * MPSAFE */ int osigsetmask(td, uap) struct thread *td; struct osigsetmask_args *uap; { struct proc *p = td->td_proc; sigset_t set; OSIG2SIG(uap->mask, set); SIG_CANTMASK(set); PROC_LOCK(p); SIG2OSIG(td->td_sigmask, td->td_retval[0]); SIGSETLO(td->td_sigmask, set); signotify(td); PROC_UNLOCK(p); return (0); } #endif /* COMPAT_43 */ /* * Suspend calling thread until signal, providing mask to be set * in the meantime. */ #ifndef _SYS_SYSPROTO_H_ struct sigsuspend_args { const sigset_t *sigmask; }; #endif /* * MPSAFE */ /* ARGSUSED */ int sigsuspend(td, uap) struct thread *td; struct sigsuspend_args *uap; { sigset_t mask; int error; error = copyin(uap->sigmask, &mask, sizeof(mask)); if (error) return (error); return (kern_sigsuspend(td, mask)); } int kern_sigsuspend(struct thread *td, sigset_t mask) { struct proc *p = td->td_proc; /* * When returning from sigsuspend, we want * the old mask to be restored after the * signal handler has finished. Thus, we * save it here and mark the sigacts structure * to indicate this. */ PROC_LOCK(p); td->td_oldsigmask = td->td_sigmask; td->td_pflags |= TDP_OLDMASK; SIG_CANTMASK(mask); td->td_sigmask = mask; signotify(td); while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "pause", 0) == 0) /* void */; PROC_UNLOCK(p); /* always return EINTR rather than ERESTART... */ return (EINTR); } #ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */ /* * Compatibility sigsuspend call for old binaries. Note nonstandard calling * convention: libc stub passes mask, not pointer, to save a copyin. */ #ifndef _SYS_SYSPROTO_H_ struct osigsuspend_args { osigset_t mask; }; #endif /* * MPSAFE */ /* ARGSUSED */ int osigsuspend(td, uap) struct thread *td; struct osigsuspend_args *uap; { struct proc *p = td->td_proc; sigset_t mask; PROC_LOCK(p); td->td_oldsigmask = td->td_sigmask; td->td_pflags |= TDP_OLDMASK; OSIG2SIG(uap->mask, mask); SIG_CANTMASK(mask); SIGSETLO(td->td_sigmask, mask); signotify(td); while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0) /* void */; PROC_UNLOCK(p); /* always return EINTR rather than ERESTART... */ return (EINTR); } #endif /* COMPAT_43 */ #if defined(COMPAT_43) #ifndef _SYS_SYSPROTO_H_ struct osigstack_args { struct sigstack *nss; struct sigstack *oss; }; #endif /* * MPSAFE */ /* ARGSUSED */ int osigstack(td, uap) struct thread *td; register struct osigstack_args *uap; { struct sigstack nss, oss; int error = 0; if (uap->nss != NULL) { error = copyin(uap->nss, &nss, sizeof(nss)); if (error) return (error); } oss.ss_sp = td->td_sigstk.ss_sp; oss.ss_onstack = sigonstack(cpu_getstack(td)); if (uap->nss != NULL) { td->td_sigstk.ss_sp = nss.ss_sp; td->td_sigstk.ss_size = 0; td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK; td->td_pflags |= TDP_ALTSTACK; } if (uap->oss != NULL) error = copyout(&oss, uap->oss, sizeof(oss)); return (error); } #endif /* COMPAT_43 */ #ifndef _SYS_SYSPROTO_H_ struct sigaltstack_args { stack_t *ss; stack_t *oss; }; #endif /* * MPSAFE */ /* ARGSUSED */ int sigaltstack(td, uap) struct thread *td; register struct sigaltstack_args *uap; { stack_t ss, oss; int error; if (uap->ss != NULL) { error = copyin(uap->ss, &ss, sizeof(ss)); if (error) return (error); } error = kern_sigaltstack(td, (uap->ss != NULL) ? &ss : NULL, (uap->oss != NULL) ? &oss : NULL); if (error) return (error); if (uap->oss != NULL) error = copyout(&oss, uap->oss, sizeof(stack_t)); return (error); } int kern_sigaltstack(struct thread *td, stack_t *ss, stack_t *oss) { struct proc *p = td->td_proc; int oonstack; oonstack = sigonstack(cpu_getstack(td)); if (oss != NULL) { *oss = td->td_sigstk; oss->ss_flags = (td->td_pflags & TDP_ALTSTACK) ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; } if (ss != NULL) { if (oonstack) return (EPERM); if ((ss->ss_flags & ~SS_DISABLE) != 0) return (EINVAL); if (!(ss->ss_flags & SS_DISABLE)) { if (ss->ss_size < p->p_sysent->sv_minsigstksz) return (ENOMEM); td->td_sigstk = *ss; td->td_pflags |= TDP_ALTSTACK; } else { td->td_pflags &= ~TDP_ALTSTACK; } } return (0); } /* * Common code for kill process group/broadcast kill. * cp is calling process. */ static int killpg1(td, sig, pgid, all) register struct thread *td; int sig, pgid, all; { register struct proc *p; struct pgrp *pgrp; int nfound = 0; if (all) { /* * broadcast */ sx_slock(&allproc_lock); LIST_FOREACH(p, &allproc, p_list) { PROC_LOCK(p); if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || p == td->td_proc || p->p_state == PRS_NEW) { PROC_UNLOCK(p); continue; } if (p_cansignal(td, p, sig) == 0) { nfound++; if (sig) psignal(p, sig); } PROC_UNLOCK(p); } sx_sunlock(&allproc_lock); } else { sx_slock(&proctree_lock); if (pgid == 0) { /* * zero pgid means send to my process group. */ pgrp = td->td_proc->p_pgrp; PGRP_LOCK(pgrp); } else { pgrp = pgfind(pgid); if (pgrp == NULL) { sx_sunlock(&proctree_lock); return (ESRCH); } } sx_sunlock(&proctree_lock); LIST_FOREACH(p, &pgrp->pg_members, p_pglist) { PROC_LOCK(p); if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || p->p_state == PRS_NEW ) { PROC_UNLOCK(p); continue; } if (p_cansignal(td, p, sig) == 0) { nfound++; if (sig) psignal(p, sig); } PROC_UNLOCK(p); } PGRP_UNLOCK(pgrp); } return (nfound ? 0 : ESRCH); } #ifndef _SYS_SYSPROTO_H_ struct kill_args { int pid; int signum; }; #endif /* * MPSAFE */ /* ARGSUSED */ int kill(td, uap) register struct thread *td; register struct kill_args *uap; { register struct proc *p; int error; AUDIT_ARG(signum, uap->signum); if ((u_int)uap->signum > _SIG_MAXSIG) return (EINVAL); if (uap->pid > 0) { /* kill single process */ if ((p = pfind(uap->pid)) == NULL) { if ((p = zpfind(uap->pid)) == NULL) return (ESRCH); } AUDIT_ARG(process, p); error = p_cansignal(td, p, uap->signum); if (error == 0 && uap->signum) psignal(p, uap->signum); PROC_UNLOCK(p); return (error); } AUDIT_ARG(pid, uap->pid); switch (uap->pid) { case -1: /* broadcast signal */ return (killpg1(td, uap->signum, 0, 1)); case 0: /* signal own process group */ return (killpg1(td, uap->signum, 0, 0)); default: /* negative explicit process group */ return (killpg1(td, uap->signum, -uap->pid, 0)); } /* NOTREACHED */ } #if defined(COMPAT_43) #ifndef _SYS_SYSPROTO_H_ struct okillpg_args { int pgid; int signum; }; #endif /* * MPSAFE */ /* ARGSUSED */ int okillpg(td, uap) struct thread *td; register struct okillpg_args *uap; { AUDIT_ARG(signum, uap->signum); AUDIT_ARG(pid, uap->pgid); if ((u_int)uap->signum > _SIG_MAXSIG) return (EINVAL); return (killpg1(td, uap->signum, uap->pgid, 0)); } #endif /* COMPAT_43 */ #ifndef _SYS_SYSPROTO_H_ struct sigqueue_args { pid_t pid; int signum; /* union sigval */ void *value; }; #endif int sigqueue(struct thread *td, struct sigqueue_args *uap) { ksiginfo_t ksi; struct proc *p; int error; if ((u_int)uap->signum > _SIG_MAXSIG) return (EINVAL); /* * Specification says sigqueue can only send signal to * single process. */ if (uap->pid <= 0) return (EINVAL); if ((p = pfind(uap->pid)) == NULL) { if ((p = zpfind(uap->pid)) == NULL) return (ESRCH); } error = p_cansignal(td, p, uap->signum); if (error == 0 && uap->signum != 0) { ksiginfo_init(&ksi); ksi.ksi_signo = uap->signum; ksi.ksi_code = SI_QUEUE; ksi.ksi_pid = td->td_proc->p_pid; ksi.ksi_uid = td->td_ucred->cr_ruid; ksi.ksi_value.sival_ptr = uap->value; error = tdsignal(p, NULL, ksi.ksi_signo, &ksi); } PROC_UNLOCK(p); return (error); } /* * Send a signal to a process group. */ void gsignal(pgid, sig) int pgid, sig; { struct pgrp *pgrp; if (pgid != 0) { sx_slock(&proctree_lock); pgrp = pgfind(pgid); sx_sunlock(&proctree_lock); if (pgrp != NULL) { pgsignal(pgrp, sig, 0); PGRP_UNLOCK(pgrp); } } } /* * Send a signal to a process group. If checktty is 1, * limit to members which have a controlling terminal. */ void pgsignal(pgrp, sig, checkctty) struct pgrp *pgrp; int sig, checkctty; { register struct proc *p; if (pgrp) { PGRP_LOCK_ASSERT(pgrp, MA_OWNED); LIST_FOREACH(p, &pgrp->pg_members, p_pglist) { PROC_LOCK(p); if (checkctty == 0 || p->p_flag & P_CONTROLT) psignal(p, sig); PROC_UNLOCK(p); } } } /* * Send a signal caused by a trap to the current thread. * If it will be caught immediately, deliver it with correct code. * Otherwise, post it normally. * * MPSAFE */ void trapsignal(struct thread *td, ksiginfo_t *ksi) { struct sigacts *ps; struct proc *p; #ifdef KSE int error; #endif int sig; int code; p = td->td_proc; sig = ksi->ksi_signo; code = ksi->ksi_code; KASSERT(_SIG_VALID(sig), ("invalid signal")); #ifdef KSE if (td->td_pflags & TDP_SA) { if (td->td_mailbox == NULL) thread_user_enter(td); PROC_LOCK(p); SIGDELSET(td->td_sigmask, sig); mtx_lock_spin(&sched_lock); /* * Force scheduling an upcall, so UTS has chance to * process the signal before thread runs again in * userland. */ if (td->td_upcall) td->td_upcall->ku_flags |= KUF_DOUPCALL; mtx_unlock_spin(&sched_lock); } else { PROC_LOCK(p); } #else PROC_LOCK(p); #endif ps = p->p_sigacts; mtx_lock(&ps->ps_mtx); if ((p->p_flag & P_TRACED) == 0 && SIGISMEMBER(ps->ps_sigcatch, sig) && !SIGISMEMBER(td->td_sigmask, sig)) { p->p_stats->p_ru.ru_nsignals++; #ifdef KTRACE if (KTRPOINT(curthread, KTR_PSIG)) ktrpsig(sig, ps->ps_sigact[_SIG_IDX(sig)], &td->td_sigmask, code); #endif #ifdef KSE if (!(td->td_pflags & TDP_SA)) (*p->p_sysent->sv_sendsig)(ps->ps_sigact[_SIG_IDX(sig)], ksi, &td->td_sigmask); #else (*p->p_sysent->sv_sendsig)(ps->ps_sigact[_SIG_IDX(sig)], ksi, &td->td_sigmask); #endif #ifdef KSE else if (td->td_mailbox == NULL) { mtx_unlock(&ps->ps_mtx); /* UTS caused a sync signal */ p->p_code = code; /* XXX for core dump/debugger */ p->p_sig = sig; /* XXX to verify code */ sigexit(td, sig); } else { mtx_unlock(&ps->ps_mtx); SIGADDSET(td->td_sigmask, sig); PROC_UNLOCK(p); error = copyout(&ksi->ksi_info, &td->td_mailbox->tm_syncsig, sizeof(siginfo_t)); PROC_LOCK(p); /* UTS memory corrupted */ if (error) sigexit(td, SIGSEGV); mtx_lock(&ps->ps_mtx); } #endif SIGSETOR(td->td_sigmask, ps->ps_catchmask[_SIG_IDX(sig)]); if (!SIGISMEMBER(ps->ps_signodefer, sig)) SIGADDSET(td->td_sigmask, sig); if (SIGISMEMBER(ps->ps_sigreset, sig)) { /* * See kern_sigaction() for origin of this code. */ SIGDELSET(ps->ps_sigcatch, sig); if (sig != SIGCONT && sigprop(sig) & SA_IGNORE) SIGADDSET(ps->ps_sigignore, sig); ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL; } mtx_unlock(&ps->ps_mtx); } else { /* * Avoid a possible infinite loop if the thread * masking the signal or process is ignoring the * signal. */ if (kern_forcesigexit && (SIGISMEMBER(td->td_sigmask, sig) || ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN)) { SIGDELSET(td->td_sigmask, sig); SIGDELSET(ps->ps_sigcatch, sig); SIGDELSET(ps->ps_sigignore, sig); ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL; } mtx_unlock(&ps->ps_mtx); p->p_code = code; /* XXX for core dump/debugger */ p->p_sig = sig; /* XXX to verify code */ tdsignal(p, td, sig, ksi); } PROC_UNLOCK(p); } static struct thread * sigtd(struct proc *p, int sig, int prop) { struct thread *td, *signal_td; PROC_LOCK_ASSERT(p, MA_OWNED); /* * Check if current thread can handle the signal without * switching conetxt to another thread. */ if (curproc == p && !SIGISMEMBER(curthread->td_sigmask, sig)) return (curthread); signal_td = NULL; mtx_lock_spin(&sched_lock); FOREACH_THREAD_IN_PROC(p, td) { if (!SIGISMEMBER(td->td_sigmask, sig)) { signal_td = td; break; } } if (signal_td == NULL) signal_td = FIRST_THREAD_IN_PROC(p); mtx_unlock_spin(&sched_lock); return (signal_td); } /* * Send the signal to the process. If the signal has an action, the action * is usually performed by the target process rather than the caller; we add * the signal to the set of pending signals for the process. * * Exceptions: * o When a stop signal is sent to a sleeping process that takes the * default action, the process is stopped without awakening it. * o SIGCONT restarts stopped processes (or puts them back to sleep) * regardless of the signal action (eg, blocked or ignored). * * Other ignored signals are discarded immediately. * * MPSAFE */ void psignal(struct proc *p, int sig) { (void) tdsignal(p, NULL, sig, NULL); } int psignal_event(struct proc *p, struct sigevent *sigev, ksiginfo_t *ksi) { struct thread *td = NULL; PROC_LOCK_ASSERT(p, MA_OWNED); KASSERT(!KSI_ONQ(ksi), ("psignal_event: ksi on queue")); /* * ksi_code and other fields should be set before * calling this function. */ ksi->ksi_signo = sigev->sigev_signo; ksi->ksi_value = sigev->sigev_value; if (sigev->sigev_notify == SIGEV_THREAD_ID) { td = thread_find(p, sigev->sigev_notify_thread_id); if (td == NULL) return (ESRCH); } return (tdsignal(p, td, ksi->ksi_signo, ksi)); } /* * MPSAFE */ int tdsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi) { #ifdef KSE sigset_t saved; int ret; if (p->p_flag & P_SA) saved = p->p_sigqueue.sq_signals; ret = do_tdsignal(p, td, sig, ksi); if ((p->p_flag & P_SA) && !(p->p_flag & P_SIGEVENT)) { if (!SIGSETEQ(saved, p->p_sigqueue.sq_signals)) { /* pending set changed */ p->p_flag |= P_SIGEVENT; wakeup(&p->p_siglist); } } return (ret); } static int do_tdsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi) { #endif sig_t action; sigqueue_t *sigqueue; int prop; struct sigacts *ps; int intrval; int ret = 0; PROC_LOCK_ASSERT(p, MA_OWNED); if (!_SIG_VALID(sig)) #ifdef KSE panic("do_tdsignal(): invalid signal"); #else panic("tdsignal(): invalid signal"); #endif #ifdef KSE KASSERT(ksi == NULL || !KSI_ONQ(ksi), ("do_tdsignal: ksi on queue")); #else KASSERT(ksi == NULL || !KSI_ONQ(ksi), ("tdsignal: ksi on queue")); #endif /* * IEEE Std 1003.1-2001: return success when killing a zombie. */ if (p->p_state == PRS_ZOMBIE) { if (ksi && (ksi->ksi_flags & KSI_INS)) ksiginfo_tryfree(ksi); return (ret); } ps = p->p_sigacts; KNOTE_LOCKED(&p->p_klist, NOTE_SIGNAL | sig); prop = sigprop(sig); /* * If the signal is blocked and not destined for this thread, then * assign it to the process so that we can find it later in the first * thread that unblocks it. Otherwise, assign it to this thread now. */ if (td == NULL) { td = sigtd(p, sig, prop); if (SIGISMEMBER(td->td_sigmask, sig)) sigqueue = &p->p_sigqueue; else sigqueue = &td->td_sigqueue; } else { KASSERT(td->td_proc == p, ("invalid thread")); sigqueue = &td->td_sigqueue; } /* * If the signal is being ignored, * then we forget about it immediately. * (Note: we don't set SIGCONT in ps_sigignore, * and if it is set to SIG_IGN, * action will be SIG_DFL here.) */ mtx_lock(&ps->ps_mtx); if (SIGISMEMBER(ps->ps_sigignore, sig)) { mtx_unlock(&ps->ps_mtx); if (ksi && (ksi->ksi_flags & KSI_INS)) ksiginfo_tryfree(ksi); return (ret); } if (SIGISMEMBER(td->td_sigmask, sig)) action = SIG_HOLD; else if (SIGISMEMBER(ps->ps_sigcatch, sig)) action = SIG_CATCH; else action = SIG_DFL; if (SIGISMEMBER(ps->ps_sigintr, sig)) intrval = EINTR; else intrval = ERESTART; mtx_unlock(&ps->ps_mtx); if (prop & SA_CONT) sigqueue_delete_stopmask_proc(p); else if (prop & SA_STOP) { /* * If sending a tty stop signal to a member of an orphaned * process group, discard the signal here if the action * is default; don't stop the process below if sleeping, * and don't clear any pending SIGCONT. */ if ((prop & SA_TTYSTOP) && (p->p_pgrp->pg_jobc == 0) && (action == SIG_DFL)) { if (ksi && (ksi->ksi_flags & KSI_INS)) ksiginfo_tryfree(ksi); return (ret); } sigqueue_delete_proc(p, SIGCONT); if (p->p_flag & P_CONTINUED) { p->p_flag &= ~P_CONTINUED; PROC_LOCK(p->p_pptr); sigqueue_take(p->p_ksi); PROC_UNLOCK(p->p_pptr); } } ret = sigqueue_add(sigqueue, sig, ksi); if (ret != 0) return (ret); signotify(td); /* * Defer further processing for signals which are held, * except that stopped processes must be continued by SIGCONT. */ if (action == SIG_HOLD && !((prop & SA_CONT) && (p->p_flag & P_STOPPED_SIG))) return (ret); /* * SIGKILL: Remove procfs STOPEVENTs. */ if (sig == SIGKILL) { /* from procfs_ioctl.c: PIOCBIC */ p->p_stops = 0; /* from procfs_ioctl.c: PIOCCONT */ p->p_step = 0; wakeup(&p->p_step); } /* * Some signals have a process-wide effect and a per-thread * component. Most processing occurs when the process next * tries to cross the user boundary, however there are some * times when processing needs to be done immediatly, such as * waking up threads so that they can cross the user boundary. * We try do the per-process part here. */ if (P_SHOULDSTOP(p)) { /* * The process is in stopped mode. All the threads should be * either winding down or already on the suspended queue. */ if (p->p_flag & P_TRACED) { /* * The traced process is already stopped, * so no further action is necessary. * No signal can restart us. */ goto out; } if (sig == SIGKILL) { /* * SIGKILL sets process running. * It will die elsewhere. * All threads must be restarted. */ p->p_flag &= ~P_STOPPED_SIG; goto runfast; } if (prop & SA_CONT) { /* * If SIGCONT is default (or ignored), we continue the * process but don't leave the signal in sigqueue as * it has no further action. If SIGCONT is held, we * continue the process and leave the signal in * sigqueue. If the process catches SIGCONT, let it * handle the signal itself. If it isn't waiting on * an event, it goes back to run state. * Otherwise, process goes back to sleep state. */ p->p_flag &= ~P_STOPPED_SIG; if (p->p_numthreads == p->p_suspcount) { p->p_flag |= P_CONTINUED; p->p_xstat = SIGCONT; PROC_LOCK(p->p_pptr); childproc_continued(p); PROC_UNLOCK(p->p_pptr); } if (action == SIG_DFL) { sigqueue_delete(sigqueue, sig); } else if (action == SIG_CATCH) { #ifdef KSE /* * The process wants to catch it so it needs * to run at least one thread, but which one? * It would seem that the answer would be to * run an upcall in the next KSE to run, and * deliver the signal that way. In a NON KSE * process, we need to make sure that the * single thread is runnable asap. * XXXKSE for now however, make them all run. */ #else /* * The process wants to catch it so it needs * to run at least one thread, but which one? */ #endif goto runfast; } /* * The signal is not ignored or caught. */ mtx_lock_spin(&sched_lock); thread_unsuspend(p); mtx_unlock_spin(&sched_lock); goto out; } if (prop & SA_STOP) { /* * Already stopped, don't need to stop again * (If we did the shell could get confused). * Just make sure the signal STOP bit set. */ p->p_flag |= P_STOPPED_SIG; sigqueue_delete(sigqueue, sig); goto out; } /* * All other kinds of signals: * If a thread is sleeping interruptibly, simulate a * wakeup so that when it is continued it will be made * runnable and can look at the signal. However, don't make * the PROCESS runnable, leave it stopped. * It may run a bit until it hits a thread_suspend_check(). */ mtx_lock_spin(&sched_lock); if (TD_ON_SLEEPQ(td) && (td->td_flags & TDF_SINTR)) sleepq_abort(td, intrval); mtx_unlock_spin(&sched_lock); goto out; /* * Mutexes are short lived. Threads waiting on them will * hit thread_suspend_check() soon. */ } else if (p->p_state == PRS_NORMAL) { if (p->p_flag & P_TRACED || action == SIG_CATCH) { mtx_lock_spin(&sched_lock); tdsigwakeup(td, sig, action, intrval); mtx_unlock_spin(&sched_lock); goto out; } MPASS(action == SIG_DFL); if (prop & SA_STOP) { if (p->p_flag & P_PPWAIT) goto out; p->p_flag |= P_STOPPED_SIG; p->p_xstat = sig; mtx_lock_spin(&sched_lock); sig_suspend_threads(td, p, 1); if (p->p_numthreads == p->p_suspcount) { /* * only thread sending signal to another * process can reach here, if thread is sending * signal to its process, because thread does * not suspend itself here, p_numthreads * should never be equal to p_suspcount. */ thread_stopped(p); mtx_unlock_spin(&sched_lock); sigqueue_delete_proc(p, p->p_xstat); } else mtx_unlock_spin(&sched_lock); goto out; } else goto runfast; /* NOTREACHED */ } else { /* Not in "NORMAL" state. discard the signal. */ sigqueue_delete(sigqueue, sig); goto out; } /* * The process is not stopped so we need to apply the signal to all the * running threads. */ runfast: mtx_lock_spin(&sched_lock); tdsigwakeup(td, sig, action, intrval); thread_unsuspend(p); mtx_unlock_spin(&sched_lock); out: /* If we jump here, sched_lock should not be owned. */ mtx_assert(&sched_lock, MA_NOTOWNED); return (ret); } /* * The force of a signal has been directed against a single * thread. We need to see what we can do about knocking it * out of any sleep it may be in etc. */ static void tdsigwakeup(struct thread *td, int sig, sig_t action, int intrval) { struct proc *p = td->td_proc; register int prop; PROC_LOCK_ASSERT(p, MA_OWNED); mtx_assert(&sched_lock, MA_OWNED); prop = sigprop(sig); /* * Bring the priority of a thread up if we want it to get * killed in this lifetime. */ if (action == SIG_DFL && (prop & SA_KILL)) { if (p->p_nice > 0) sched_nice(td->td_proc, 0); if (td->td_priority > PUSER) sched_prio(td, PUSER); } if (TD_ON_SLEEPQ(td)) { /* * If thread is sleeping uninterruptibly * we can't interrupt the sleep... the signal will * be noticed when the process returns through * trap() or syscall(). */ if ((td->td_flags & TDF_SINTR) == 0) return; /* * If SIGCONT is default (or ignored) and process is * asleep, we are finished; the process should not * be awakened. */ if ((prop & SA_CONT) && action == SIG_DFL) { mtx_unlock_spin(&sched_lock); sigqueue_delete(&p->p_sigqueue, sig); /* * It may be on either list in this state. * Remove from both for now. */ sigqueue_delete(&td->td_sigqueue, sig); mtx_lock_spin(&sched_lock); return; } /* * Give low priority threads a better chance to run. */ if (td->td_priority > PUSER) sched_prio(td, PUSER); sleepq_abort(td, intrval); } else { /* * Other states do nothing with the signal immediately, * other than kicking ourselves if we are running. * It will either never be noticed, or noticed very soon. */ #ifdef SMP if (TD_IS_RUNNING(td) && td != curthread) forward_signal(td); #endif } } static void sig_suspend_threads(struct thread *td, struct proc *p, int sending) { struct thread *td2; PROC_LOCK_ASSERT(p, MA_OWNED); mtx_assert(&sched_lock, MA_OWNED); FOREACH_THREAD_IN_PROC(p, td2) { if ((TD_IS_SLEEPING(td2) || TD_IS_SWAPPED(td2)) && (td2->td_flags & TDF_SINTR) && !TD_IS_SUSPENDED(td2)) { thread_suspend_one(td2); } else { if (sending || td != td2) td2->td_flags |= TDF_ASTPENDING; #ifdef SMP if (TD_IS_RUNNING(td2) && td2 != td) forward_signal(td2); #endif } } } int ptracestop(struct thread *td, int sig) { struct proc *p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &p->p_mtx.mtx_object, "Stopping for traced signal"); mtx_lock_spin(&sched_lock); td->td_flags |= TDF_XSIG; mtx_unlock_spin(&sched_lock); td->td_xsig = sig; while ((p->p_flag & P_TRACED) && (td->td_flags & TDF_XSIG)) { if (p->p_flag & P_SINGLE_EXIT) { mtx_lock_spin(&sched_lock); td->td_flags &= ~TDF_XSIG; mtx_unlock_spin(&sched_lock); return (sig); } /* * Just make wait() to work, the last stopped thread * will win. */ p->p_xstat = sig; p->p_xthread = td; p->p_flag |= (P_STOPPED_SIG|P_STOPPED_TRACE); mtx_lock_spin(&sched_lock); sig_suspend_threads(td, p, 0); stopme: thread_stopped(p); thread_suspend_one(td); PROC_UNLOCK(p); DROP_GIANT(); mi_switch(SW_VOL, NULL); mtx_unlock_spin(&sched_lock); PICKUP_GIANT(); PROC_LOCK(p); if (!(p->p_flag & P_TRACED)) break; if (td->td_flags & TDF_DBSUSPEND) { if (p->p_flag & P_SINGLE_EXIT) break; mtx_lock_spin(&sched_lock); goto stopme; } } return (td->td_xsig); } /* * If the current process has received a signal (should be caught or cause * termination, should interrupt current syscall), return the signal number. * Stop signals with default action are processed immediately, then cleared; * they aren't returned. This is checked after each entry to the system for * a syscall or trap (though this can usually be done without calling issignal * by checking the pending signal masks in cursig.) The normal call * sequence is * * while (sig = cursig(curthread)) * postsig(sig); */ static int issignal(td) struct thread *td; { struct proc *p; struct sigacts *ps; sigset_t sigpending; int sig, prop, newsig; p = td->td_proc; ps = p->p_sigacts; mtx_assert(&ps->ps_mtx, MA_OWNED); PROC_LOCK_ASSERT(p, MA_OWNED); for (;;) { int traced = (p->p_flag & P_TRACED) || (p->p_stops & S_SIG); sigpending = td->td_sigqueue.sq_signals; SIGSETNAND(sigpending, td->td_sigmask); if (p->p_flag & P_PPWAIT) SIG_STOPSIGMASK(sigpending); if (SIGISEMPTY(sigpending)) /* no signal to send */ return (0); sig = sig_ffs(&sigpending); if (p->p_stops & S_SIG) { mtx_unlock(&ps->ps_mtx); stopevent(p, S_SIG, sig); mtx_lock(&ps->ps_mtx); } /* * We should see pending but ignored signals * only if P_TRACED was on when they were posted. */ if (SIGISMEMBER(ps->ps_sigignore, sig) && (traced == 0)) { sigqueue_delete(&td->td_sigqueue, sig); #ifdef KSE if (td->td_pflags & TDP_SA) SIGADDSET(td->td_sigmask, sig); #endif continue; } if (p->p_flag & P_TRACED && (p->p_flag & P_PPWAIT) == 0) { /* * If traced, always stop. */ mtx_unlock(&ps->ps_mtx); newsig = ptracestop(td, sig); mtx_lock(&ps->ps_mtx); #ifdef KSE if (td->td_pflags & TDP_SA) SIGADDSET(td->td_sigmask, sig); #endif if (sig != newsig) { ksiginfo_t ksi; /* * clear old signal. * XXX shrug off debugger, it causes siginfo to * be thrown away. */ sigqueue_get(&td->td_sigqueue, sig, &ksi); /* * If parent wants us to take the signal, * then it will leave it in p->p_xstat; * otherwise we just look for signals again. */ if (newsig == 0) continue; sig = newsig; /* * Put the new signal into td_sigqueue. If the * signal is being masked, look for other signals. */ SIGADDSET(td->td_sigqueue.sq_signals, sig); #ifdef KSE if (td->td_pflags & TDP_SA) SIGDELSET(td->td_sigmask, sig); #endif if (SIGISMEMBER(td->td_sigmask, sig)) continue; signotify(td); } /* * If the traced bit got turned off, go back up * to the top to rescan signals. This ensures * that p_sig* and p_sigact are consistent. */ if ((p->p_flag & P_TRACED) == 0) continue; } prop = sigprop(sig); /* * Decide whether the signal should be returned. * Return the signal's number, or fall through * to clear it from the pending mask. */ switch ((intptr_t)p->p_sigacts->ps_sigact[_SIG_IDX(sig)]) { case (intptr_t)SIG_DFL: /* * Don't take default actions on system processes. */ if (p->p_pid <= 1) { #ifdef DIAGNOSTIC /* * Are you sure you want to ignore SIGSEGV * in init? XXX */ printf("Process (pid %lu) got signal %d\n", (u_long)p->p_pid, sig); #endif break; /* == ignore */ } /* * If there is a pending stop signal to process * with default action, stop here, * then clear the signal. However, * if process is member of an orphaned * process group, ignore tty stop signals. */ if (prop & SA_STOP) { if (p->p_flag & P_TRACED || (p->p_pgrp->pg_jobc == 0 && prop & SA_TTYSTOP)) break; /* == ignore */ mtx_unlock(&ps->ps_mtx); WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &p->p_mtx.mtx_object, "Catching SIGSTOP"); p->p_flag |= P_STOPPED_SIG; p->p_xstat = sig; mtx_lock_spin(&sched_lock); sig_suspend_threads(td, p, 0); thread_stopped(p); thread_suspend_one(td); PROC_UNLOCK(p); DROP_GIANT(); mi_switch(SW_INVOL, NULL); mtx_unlock_spin(&sched_lock); PICKUP_GIANT(); PROC_LOCK(p); mtx_lock(&ps->ps_mtx); break; } else if (prop & SA_IGNORE) { /* * Except for SIGCONT, shouldn't get here. * Default action is to ignore; drop it. */ break; /* == ignore */ } else return (sig); /*NOTREACHED*/ case (intptr_t)SIG_IGN: /* * Masking above should prevent us ever trying * to take action on an ignored signal other * than SIGCONT, unless process is traced. */ if ((prop & SA_CONT) == 0 && (p->p_flag & P_TRACED) == 0) printf("issignal\n"); break; /* == ignore */ default: /* * This signal has an action, let * postsig() process it. */ return (sig); } sigqueue_delete(&td->td_sigqueue, sig); /* take the signal! */ } /* NOTREACHED */ } /* * MPSAFE */ void thread_stopped(struct proc *p) { int n; PROC_LOCK_ASSERT(p, MA_OWNED); mtx_assert(&sched_lock, MA_OWNED); n = p->p_suspcount; if (p == curproc) n++; if ((p->p_flag & P_STOPPED_SIG) && (n == p->p_numthreads)) { mtx_unlock_spin(&sched_lock); p->p_flag &= ~P_WAITED; PROC_LOCK(p->p_pptr); childproc_stopped(p, (p->p_flag & P_TRACED) ? CLD_TRAPPED : CLD_STOPPED); PROC_UNLOCK(p->p_pptr); mtx_lock_spin(&sched_lock); } } /* * Take the action for the specified signal * from the current set of pending signals. */ void postsig(sig) register int sig; { struct thread *td = curthread; register struct proc *p = td->td_proc; struct sigacts *ps; sig_t action; ksiginfo_t ksi; sigset_t returnmask; int code; KASSERT(sig != 0, ("postsig")); PROC_LOCK_ASSERT(p, MA_OWNED); ps = p->p_sigacts; mtx_assert(&ps->ps_mtx, MA_OWNED); ksiginfo_init(&ksi); sigqueue_get(&td->td_sigqueue, sig, &ksi); ksi.ksi_signo = sig; if (ksi.ksi_code == SI_TIMER) itimer_accept(p, ksi.ksi_timerid, &ksi); action = ps->ps_sigact[_SIG_IDX(sig)]; #ifdef KTRACE if (KTRPOINT(td, KTR_PSIG)) ktrpsig(sig, action, td->td_pflags & TDP_OLDMASK ? &td->td_oldsigmask : &td->td_sigmask, 0); #endif if (p->p_stops & S_SIG) { mtx_unlock(&ps->ps_mtx); stopevent(p, S_SIG, sig); mtx_lock(&ps->ps_mtx); } #ifdef KSE if (!(td->td_pflags & TDP_SA) && action == SIG_DFL) { #else if (action == SIG_DFL) { #endif /* * Default action, where the default is to kill * the process. (Other cases were ignored above.) */ mtx_unlock(&ps->ps_mtx); sigexit(td, sig); /* NOTREACHED */ } else { #ifdef KSE if (td->td_pflags & TDP_SA) { if (sig == SIGKILL) { mtx_unlock(&ps->ps_mtx); sigexit(td, sig); } } #endif /* * If we get here, the signal must be caught. */ KASSERT(action != SIG_IGN && !SIGISMEMBER(td->td_sigmask, sig), ("postsig action")); /* * Set the new mask value and also defer further * occurrences of this signal. * * Special case: user has done a sigsuspend. Here the * current mask is not of interest, but rather the * mask from before the sigsuspend is what we want * restored after the signal processing is completed. */ if (td->td_pflags & TDP_OLDMASK) { returnmask = td->td_oldsigmask; td->td_pflags &= ~TDP_OLDMASK; } else returnmask = td->td_sigmask; SIGSETOR(td->td_sigmask, ps->ps_catchmask[_SIG_IDX(sig)]); if (!SIGISMEMBER(ps->ps_signodefer, sig)) SIGADDSET(td->td_sigmask, sig); if (SIGISMEMBER(ps->ps_sigreset, sig)) { /* * See kern_sigaction() for origin of this code. */ SIGDELSET(ps->ps_sigcatch, sig); if (sig != SIGCONT && sigprop(sig) & SA_IGNORE) SIGADDSET(ps->ps_sigignore, sig); ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL; } p->p_stats->p_ru.ru_nsignals++; if (p->p_sig != sig) { code = 0; } else { code = p->p_code; p->p_code = 0; p->p_sig = 0; } #ifdef KSE if (td->td_pflags & TDP_SA) thread_signal_add(curthread, &ksi); else (*p->p_sysent->sv_sendsig)(action, &ksi, &returnmask); #else (*p->p_sysent->sv_sendsig)(action, &ksi, &returnmask); #endif } } /* * Kill the current process for stated reason. */ void killproc(p, why) struct proc *p; char *why; { PROC_LOCK_ASSERT(p, MA_OWNED); CTR3(KTR_PROC, "killproc: proc %p (pid %d, %s)", p, p->p_pid, p->p_comm); log(LOG_ERR, "pid %d (%s), uid %d, was killed: %s\n", p->p_pid, p->p_comm, p->p_ucred ? p->p_ucred->cr_uid : -1, why); psignal(p, SIGKILL); } /* * Force the current process to exit with the specified signal, dumping core * if appropriate. We bypass the normal tests for masked and caught signals, * allowing unrecoverable failures to terminate the process without changing * signal state. Mark the accounting record with the signal termination. * If dumping core, save the signal number for the debugger. Calls exit and * does not return. * * MPSAFE */ void sigexit(td, sig) struct thread *td; int sig; { struct proc *p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); p->p_acflag |= AXSIG; /* * We must be single-threading to generate a core dump. This * ensures that the registers in the core file are up-to-date. * Also, the ELF dump handler assumes that the thread list doesn't * change out from under it. * * XXX If another thread attempts to single-thread before us * (e.g. via fork()), we won't get a dump at all. */ if ((sigprop(sig) & SA_CORE) && (thread_single(SINGLE_NO_EXIT) == 0)) { p->p_sig = sig; /* * Log signals which would cause core dumps * (Log as LOG_INFO to appease those who don't want * these messages.) * XXX : Todo, as well as euid, write out ruid too * Note that coredump() drops proc lock. */ if (coredump(td) == 0) sig |= WCOREFLAG; if (kern_logsigexit) log(LOG_INFO, "pid %d (%s), uid %d: exited on signal %d%s\n", p->p_pid, p->p_comm, td->td_ucred ? td->td_ucred->cr_uid : -1, sig &~ WCOREFLAG, sig & WCOREFLAG ? " (core dumped)" : ""); } else PROC_UNLOCK(p); exit1(td, W_EXITCODE(0, sig)); /* NOTREACHED */ } /* * Send queued SIGCHLD to parent when child process's state * is changed. */ static void sigparent(struct proc *p, int reason, int status) { PROC_LOCK_ASSERT(p, MA_OWNED); PROC_LOCK_ASSERT(p->p_pptr, MA_OWNED); if (p->p_ksi != NULL) { p->p_ksi->ksi_signo = SIGCHLD; p->p_ksi->ksi_code = reason; p->p_ksi->ksi_status = status; p->p_ksi->ksi_pid = p->p_pid; p->p_ksi->ksi_uid = p->p_ucred->cr_ruid; if (KSI_ONQ(p->p_ksi)) return; } tdsignal(p->p_pptr, NULL, SIGCHLD, p->p_ksi); } static void childproc_jobstate(struct proc *p, int reason, int status) { struct sigacts *ps; PROC_LOCK_ASSERT(p, MA_OWNED); PROC_LOCK_ASSERT(p->p_pptr, MA_OWNED); /* * Wake up parent sleeping in kern_wait(), also send * SIGCHLD to parent, but SIGCHLD does not guarantee * that parent will awake, because parent may masked * the signal. */ p->p_pptr->p_flag |= P_STATCHILD; wakeup(p->p_pptr); ps = p->p_pptr->p_sigacts; mtx_lock(&ps->ps_mtx); if ((ps->ps_flag & PS_NOCLDSTOP) == 0) { mtx_unlock(&ps->ps_mtx); sigparent(p, reason, status); } else mtx_unlock(&ps->ps_mtx); } void childproc_stopped(struct proc *p, int reason) { childproc_jobstate(p, reason, p->p_xstat); } void childproc_continued(struct proc *p) { childproc_jobstate(p, CLD_CONTINUED, SIGCONT); } void childproc_exited(struct proc *p) { int reason; int status = p->p_xstat; /* convert to int */ reason = CLD_EXITED; if (WCOREDUMP(status)) reason = CLD_DUMPED; else if (WIFSIGNALED(status)) reason = CLD_KILLED; /* * XXX avoid calling wakeup(p->p_pptr), the work is * done in exit1(). */ sigparent(p, reason, status); } static char corefilename[MAXPATHLEN] = {"%N.core"}; SYSCTL_STRING(_kern, OID_AUTO, corefile, CTLFLAG_RW, corefilename, sizeof(corefilename), "process corefile name format string"); /* * expand_name(name, uid, pid) * Expand the name described in corefilename, using name, uid, and pid. * corefilename is a printf-like string, with three format specifiers: * %N name of process ("name") * %P process id (pid) * %U user id (uid) * For example, "%N.core" is the default; they can be disabled completely * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P". * This is controlled by the sysctl variable kern.corefile (see above). */ static char * expand_name(name, uid, pid) const char *name; uid_t uid; pid_t pid; { const char *format, *appendstr; char *temp; char buf[11]; /* Buffer for pid/uid -- max 4B */ size_t i, l, n; format = corefilename; temp = malloc(MAXPATHLEN, M_TEMP, M_NOWAIT | M_ZERO); if (temp == NULL) return (NULL); for (i = 0, n = 0; n < MAXPATHLEN && format[i]; i++) { switch (format[i]) { case '%': /* Format character */ i++; switch (format[i]) { case '%': appendstr = "%"; break; case 'N': /* process name */ appendstr = name; break; case 'P': /* process id */ sprintf(buf, "%u", pid); appendstr = buf; break; case 'U': /* user id */ sprintf(buf, "%u", uid); appendstr = buf; break; default: appendstr = ""; log(LOG_ERR, "Unknown format character %c in `%s'\n", format[i], format); } l = strlen(appendstr); if ((n + l) >= MAXPATHLEN) goto toolong; memcpy(temp + n, appendstr, l); n += l; break; default: temp[n++] = format[i]; } } if (format[i] != '\0') goto toolong; return (temp); toolong: log(LOG_ERR, "pid %ld (%s), uid (%lu): corename is too long\n", (long)pid, name, (u_long)uid); free(temp, M_TEMP); return (NULL); } /* * Dump a process' core. The main routine does some * policy checking, and creates the name of the coredump; * then it passes on a vnode and a size limit to the process-specific * coredump routine if there is one; if there _is not_ one, it returns * ENOSYS; otherwise it returns the error from the process-specific routine. */ static int coredump(struct thread *td) { struct proc *p = td->td_proc; register struct vnode *vp; register struct ucred *cred = td->td_ucred; struct flock lf; struct nameidata nd; struct vattr vattr; int error, error1, flags, locked; struct mount *mp; char *name; /* name of corefile */ off_t limit; int vfslocked; PROC_LOCK_ASSERT(p, MA_OWNED); MPASS((p->p_flag & P_HADTHREADS) == 0 || p->p_singlethread == td); _STOPEVENT(p, S_CORE, 0); if (((sugid_coredump == 0) && p->p_flag & P_SUGID) || do_coredump == 0) { PROC_UNLOCK(p); return (EFAULT); } /* * Note that the bulk of limit checking is done after * the corefile is created. The exception is if the limit * for corefiles is 0, in which case we don't bother * creating the corefile at all. This layout means that * a corefile is truncated instead of not being created, * if it is larger than the limit. */ limit = (off_t)lim_cur(p, RLIMIT_CORE); PROC_UNLOCK(p); if (limit == 0) return (EFBIG); restart: name = expand_name(p->p_comm, td->td_ucred->cr_uid, p->p_pid); if (name == NULL) return (EINVAL); NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, name, td); flags = O_CREAT | FWRITE | O_NOFOLLOW; error = vn_open(&nd, &flags, S_IRUSR | S_IWUSR, -1); free(name, M_TEMP); if (error) return (error); vfslocked = NDHASGIANT(&nd); NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; /* Don't dump to non-regular files or files with links. */ if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, td) || vattr.va_nlink != 1) { VOP_UNLOCK(vp, 0, td); error = EFAULT; goto close; } VOP_UNLOCK(vp, 0, td); lf.l_whence = SEEK_SET; lf.l_start = 0; lf.l_len = 0; lf.l_type = F_WRLCK; locked = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &lf, F_FLOCK) == 0); if (vn_start_write(vp, &mp, V_NOWAIT) != 0) { lf.l_type = F_UNLCK; if (locked) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK); if ((error = vn_close(vp, FWRITE, cred, td)) != 0) goto out; if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) goto out; VFS_UNLOCK_GIANT(vfslocked); goto restart; } VATTR_NULL(&vattr); vattr.va_size = 0; if (set_core_nodump_flag) vattr.va_flags = UF_NODUMP; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); VOP_LEASE(vp, td, cred, LEASE_WRITE); VOP_SETATTR(vp, &vattr, cred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); PROC_LOCK(p); p->p_acflag |= ACORE; PROC_UNLOCK(p); error = p->p_sysent->sv_coredump ? p->p_sysent->sv_coredump(td, vp, limit) : ENOSYS; if (locked) { lf.l_type = F_UNLCK; VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK); } close: error1 = vn_close(vp, FWRITE, cred, td); if (error == 0) error = error1; out: VFS_UNLOCK_GIANT(vfslocked); return (error); } /* * Nonexistent system call-- signal process (may want to handle it). * Flag error in case process won't see signal immediately (blocked or ignored). */ #ifndef _SYS_SYSPROTO_H_ struct nosys_args { int dummy; }; #endif /* * MPSAFE */ /* ARGSUSED */ int nosys(td, args) struct thread *td; struct nosys_args *args; { struct proc *p = td->td_proc; PROC_LOCK(p); psignal(p, SIGSYS); PROC_UNLOCK(p); return (ENOSYS); } /* * Send a SIGIO or SIGURG signal to a process or process group using * stored credentials rather than those of the current process. */ void pgsigio(sigiop, sig, checkctty) struct sigio **sigiop; int sig, checkctty; { struct sigio *sigio; SIGIO_LOCK(); sigio = *sigiop; if (sigio == NULL) { SIGIO_UNLOCK(); return; } if (sigio->sio_pgid > 0) { PROC_LOCK(sigio->sio_proc); if (CANSIGIO(sigio->sio_ucred, sigio->sio_proc->p_ucred)) psignal(sigio->sio_proc, sig); PROC_UNLOCK(sigio->sio_proc); } else if (sigio->sio_pgid < 0) { struct proc *p; PGRP_LOCK(sigio->sio_pgrp); LIST_FOREACH(p, &sigio->sio_pgrp->pg_members, p_pglist) { PROC_LOCK(p); if (CANSIGIO(sigio->sio_ucred, p->p_ucred) && (checkctty == 0 || (p->p_flag & P_CONTROLT))) psignal(p, sig); PROC_UNLOCK(p); } PGRP_UNLOCK(sigio->sio_pgrp); } SIGIO_UNLOCK(); } static int filt_sigattach(struct knote *kn) { struct proc *p = curproc; kn->kn_ptr.p_proc = p; kn->kn_flags |= EV_CLEAR; /* automatically set */ knlist_add(&p->p_klist, kn, 0); return (0); } static void filt_sigdetach(struct knote *kn) { struct proc *p = kn->kn_ptr.p_proc; knlist_remove(&p->p_klist, kn, 0); } /* * signal knotes are shared with proc knotes, so we apply a mask to * the hint in order to differentiate them from process hints. This * could be avoided by using a signal-specific knote list, but probably * isn't worth the trouble. */ static int filt_signal(struct knote *kn, long hint) { if (hint & NOTE_SIGNAL) { hint &= ~NOTE_SIGNAL; if (kn->kn_id == hint) kn->kn_data++; } return (kn->kn_data != 0); } struct sigacts * sigacts_alloc(void) { struct sigacts *ps; ps = malloc(sizeof(struct sigacts), M_SUBPROC, M_WAITOK | M_ZERO); ps->ps_refcnt = 1; mtx_init(&ps->ps_mtx, "sigacts", NULL, MTX_DEF); return (ps); } void sigacts_free(struct sigacts *ps) { mtx_lock(&ps->ps_mtx); ps->ps_refcnt--; if (ps->ps_refcnt == 0) { mtx_destroy(&ps->ps_mtx); free(ps, M_SUBPROC); } else mtx_unlock(&ps->ps_mtx); } struct sigacts * sigacts_hold(struct sigacts *ps) { mtx_lock(&ps->ps_mtx); ps->ps_refcnt++; mtx_unlock(&ps->ps_mtx); return (ps); } void sigacts_copy(struct sigacts *dest, struct sigacts *src) { KASSERT(dest->ps_refcnt == 1, ("sigacts_copy to shared dest")); mtx_lock(&src->ps_mtx); bcopy(src, dest, offsetof(struct sigacts, ps_refcnt)); mtx_unlock(&src->ps_mtx); } int sigacts_shared(struct sigacts *ps) { int shared; mtx_lock(&ps->ps_mtx); shared = ps->ps_refcnt > 1; mtx_unlock(&ps->ps_mtx); return (shared); } Index: head/sys/kern/kern_time.c =================================================================== --- head/sys/kern/kern_time.c (revision 164183) +++ head/sys/kern/kern_time.c (revision 164184) @@ -1,1562 +1,1561 @@ /*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_time.c 8.1 (Berkeley) 6/10/93 */ #include __FBSDID("$FreeBSD$"); #include "opt_mac.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include - -#include #include #include #include #define MAX_CLOCKS (CLOCK_MONOTONIC+1) static struct kclock posix_clocks[MAX_CLOCKS]; static uma_zone_t itimer_zone = NULL; /* * Time of day and interval timer support. * * These routines provide the kernel entry points to get and set * the time-of-day and per-process interval timers. Subroutines * here provide support for adding and subtracting timeval structures * and decrementing interval timers, optionally reloading the interval * timers when they expire. */ static int settime(struct thread *, struct timeval *); static void timevalfix(struct timeval *); static void no_lease_updatetime(int); static void itimer_start(void); static int itimer_init(void *, int, int); static void itimer_fini(void *, int); static void itimer_enter(struct itimer *); static void itimer_leave(struct itimer *); static struct itimer *itimer_find(struct proc *, int, int); static void itimers_alloc(struct proc *); static void itimers_event_hook_exec(void *arg, struct proc *p, struct image_params *imgp); static void itimers_event_hook_exit(void *arg, struct proc *p); static int realtimer_create(struct itimer *); static int realtimer_gettime(struct itimer *, struct itimerspec *); static int realtimer_settime(struct itimer *, int, struct itimerspec *, struct itimerspec *); static int realtimer_delete(struct itimer *); static void realtimer_clocktime(clockid_t, struct timespec *); static void realtimer_expire(void *); static void realtimer_event_hook(struct proc *, clockid_t, int event); static int kern_timer_create(struct thread *, clockid_t, struct sigevent *, int *, int); static int kern_timer_delete(struct thread *, int); int register_posix_clock(int, struct kclock *); void itimer_fire(struct itimer *it); int itimespecfix(struct timespec *ts); #define CLOCK_CALL(clock, call, arglist) \ ((*posix_clocks[clock].call) arglist) SYSINIT(posix_timer, SI_SUB_P1003_1B, SI_ORDER_FIRST+4, itimer_start, NULL); static void no_lease_updatetime(deltat) int deltat; { } void (*lease_updatetime)(int) = no_lease_updatetime; static int settime(struct thread *td, struct timeval *tv) { struct timeval delta, tv1, tv2; static struct timeval maxtime, laststep; struct timespec ts; int s; s = splclock(); microtime(&tv1); delta = *tv; timevalsub(&delta, &tv1); /* * If the system is secure, we do not allow the time to be * set to a value earlier than 1 second less than the highest * time we have yet seen. The worst a miscreant can do in * this circumstance is "freeze" time. He couldn't go * back to the past. * * We similarly do not allow the clock to be stepped more * than one second, nor more than once per second. This allows * a miscreant to make the clock march double-time, but no worse. */ if (securelevel_gt(td->td_ucred, 1) != 0) { if (delta.tv_sec < 0 || delta.tv_usec < 0) { /* * Update maxtime to latest time we've seen. */ if (tv1.tv_sec > maxtime.tv_sec) maxtime = tv1; tv2 = *tv; timevalsub(&tv2, &maxtime); if (tv2.tv_sec < -1) { tv->tv_sec = maxtime.tv_sec - 1; printf("Time adjustment clamped to -1 second\n"); } } else { if (tv1.tv_sec == laststep.tv_sec) { splx(s); return (EPERM); } if (delta.tv_sec > 1) { tv->tv_sec = tv1.tv_sec + 1; printf("Time adjustment clamped to +1 second\n"); } laststep = *tv; } } ts.tv_sec = tv->tv_sec; ts.tv_nsec = tv->tv_usec * 1000; mtx_lock(&Giant); tc_setclock(&ts); (void) splsoftclock(); lease_updatetime(delta.tv_sec); splx(s); resettodr(); mtx_unlock(&Giant); return (0); } #ifndef _SYS_SYSPROTO_H_ struct clock_gettime_args { clockid_t clock_id; struct timespec *tp; }; #endif /* * MPSAFE */ /* ARGSUSED */ int clock_gettime(struct thread *td, struct clock_gettime_args *uap) { struct timespec ats; int error; error = kern_clock_gettime(td, uap->clock_id, &ats); if (error == 0) error = copyout(&ats, uap->tp, sizeof(ats)); return (error); } int kern_clock_gettime(struct thread *td, clockid_t clock_id, struct timespec *ats) { struct timeval sys, user; struct proc *p; p = td->td_proc; switch (clock_id) { case CLOCK_REALTIME: /* Default to precise. */ case CLOCK_REALTIME_PRECISE: nanotime(ats); break; case CLOCK_REALTIME_FAST: getnanotime(ats); break; case CLOCK_VIRTUAL: PROC_LOCK(p); calcru(p, &user, &sys); PROC_UNLOCK(p); TIMEVAL_TO_TIMESPEC(&user, ats); break; case CLOCK_PROF: PROC_LOCK(p); calcru(p, &user, &sys); PROC_UNLOCK(p); timevaladd(&user, &sys); TIMEVAL_TO_TIMESPEC(&user, ats); break; case CLOCK_MONOTONIC: /* Default to precise. */ case CLOCK_MONOTONIC_PRECISE: case CLOCK_UPTIME: case CLOCK_UPTIME_PRECISE: nanouptime(ats); break; case CLOCK_UPTIME_FAST: case CLOCK_MONOTONIC_FAST: getnanouptime(ats); break; case CLOCK_SECOND: ats->tv_sec = time_second; ats->tv_nsec = 0; break; default: return (EINVAL); } return (0); } #ifndef _SYS_SYSPROTO_H_ struct clock_settime_args { clockid_t clock_id; const struct timespec *tp; }; #endif /* * MPSAFE */ /* ARGSUSED */ int clock_settime(struct thread *td, struct clock_settime_args *uap) { struct timespec ats; int error; if ((error = copyin(uap->tp, &ats, sizeof(ats))) != 0) return (error); return (kern_clock_settime(td, uap->clock_id, &ats)); } int kern_clock_settime(struct thread *td, clockid_t clock_id, struct timespec *ats) { struct timeval atv; int error; #ifdef MAC error = mac_check_system_settime(td->td_ucred); if (error) return (error); #endif if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0) return (error); if (clock_id != CLOCK_REALTIME) return (EINVAL); if (ats->tv_nsec < 0 || ats->tv_nsec >= 1000000000) return (EINVAL); /* XXX Don't convert nsec->usec and back */ TIMESPEC_TO_TIMEVAL(&atv, ats); error = settime(td, &atv); return (error); } #ifndef _SYS_SYSPROTO_H_ struct clock_getres_args { clockid_t clock_id; struct timespec *tp; }; #endif int clock_getres(struct thread *td, struct clock_getres_args *uap) { struct timespec ts; int error; if (uap->tp == NULL) return (0); error = kern_clock_getres(td, uap->clock_id, &ts); if (error == 0) error = copyout(&ts, uap->tp, sizeof(ts)); return (error); } int kern_clock_getres(struct thread *td, clockid_t clock_id, struct timespec *ts) { ts->tv_sec = 0; switch (clock_id) { case CLOCK_REALTIME: case CLOCK_REALTIME_FAST: case CLOCK_REALTIME_PRECISE: case CLOCK_MONOTONIC: case CLOCK_MONOTONIC_FAST: case CLOCK_MONOTONIC_PRECISE: case CLOCK_UPTIME: case CLOCK_UPTIME_FAST: case CLOCK_UPTIME_PRECISE: /* * Round up the result of the division cheaply by adding 1. * Rounding up is especially important if rounding down * would give 0. Perfect rounding is unimportant. */ ts->tv_nsec = 1000000000 / tc_getfrequency() + 1; break; case CLOCK_VIRTUAL: case CLOCK_PROF: /* Accurately round up here because we can do so cheaply. */ ts->tv_nsec = (1000000000 + hz - 1) / hz; break; case CLOCK_SECOND: ts->tv_sec = 1; ts->tv_nsec = 0; break; default: return (EINVAL); } return (0); } static int nanowait; int kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt) { struct timespec ts, ts2, ts3; struct timeval tv; int error; if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000) return (EINVAL); if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0)) return (0); getnanouptime(&ts); timespecadd(&ts, rqt); TIMESPEC_TO_TIMEVAL(&tv, rqt); for (;;) { error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp", tvtohz(&tv)); getnanouptime(&ts2); if (error != EWOULDBLOCK) { if (error == ERESTART) error = EINTR; if (rmt != NULL) { timespecsub(&ts, &ts2); if (ts.tv_sec < 0) timespecclear(&ts); *rmt = ts; } return (error); } if (timespeccmp(&ts2, &ts, >=)) return (0); ts3 = ts; timespecsub(&ts3, &ts2); TIMESPEC_TO_TIMEVAL(&tv, &ts3); } } #ifndef _SYS_SYSPROTO_H_ struct nanosleep_args { struct timespec *rqtp; struct timespec *rmtp; }; #endif /* * MPSAFE */ /* ARGSUSED */ int nanosleep(struct thread *td, struct nanosleep_args *uap) { struct timespec rmt, rqt; int error; error = copyin(uap->rqtp, &rqt, sizeof(rqt)); if (error) return (error); if (uap->rmtp && !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) return (EFAULT); error = kern_nanosleep(td, &rqt, &rmt); if (error && uap->rmtp) { int error2; error2 = copyout(&rmt, uap->rmtp, sizeof(rmt)); if (error2) error = error2; } return (error); } #ifndef _SYS_SYSPROTO_H_ struct gettimeofday_args { struct timeval *tp; struct timezone *tzp; }; #endif /* * MPSAFE */ /* ARGSUSED */ int gettimeofday(struct thread *td, struct gettimeofday_args *uap) { struct timeval atv; struct timezone rtz; int error = 0; if (uap->tp) { microtime(&atv); error = copyout(&atv, uap->tp, sizeof (atv)); } if (error == 0 && uap->tzp != NULL) { rtz.tz_minuteswest = tz_minuteswest; rtz.tz_dsttime = tz_dsttime; error = copyout(&rtz, uap->tzp, sizeof (rtz)); } return (error); } #ifndef _SYS_SYSPROTO_H_ struct settimeofday_args { struct timeval *tv; struct timezone *tzp; }; #endif /* * MPSAFE */ /* ARGSUSED */ int settimeofday(struct thread *td, struct settimeofday_args *uap) { struct timeval atv, *tvp; struct timezone atz, *tzp; int error; if (uap->tv) { error = copyin(uap->tv, &atv, sizeof(atv)); if (error) return (error); tvp = &atv; } else tvp = NULL; if (uap->tzp) { error = copyin(uap->tzp, &atz, sizeof(atz)); if (error) return (error); tzp = &atz; } else tzp = NULL; return (kern_settimeofday(td, tvp, tzp)); } int kern_settimeofday(struct thread *td, struct timeval *tv, struct timezone *tzp) { int error; #ifdef MAC error = mac_check_system_settime(td->td_ucred); if (error) return (error); #endif error = priv_check(td, PRIV_SETTIMEOFDAY); if (error) return (error); /* Verify all parameters before changing time. */ if (tv) { if (tv->tv_usec < 0 || tv->tv_usec >= 1000000) return (EINVAL); error = settime(td, tv); } if (tzp && error == 0) { tz_minuteswest = tzp->tz_minuteswest; tz_dsttime = tzp->tz_dsttime; } return (error); } /* * Get value of an interval timer. The process virtual and * profiling virtual time timers are kept in the p_stats area, since * they can be swapped out. These are kept internally in the * way they are specified externally: in time until they expire. * * The real time interval timer is kept in the process table slot * for the process, and its value (it_value) is kept as an * absolute time rather than as a delta, so that it is easy to keep * periodic real-time signals from drifting. * * Virtual time timers are processed in the hardclock() routine of * kern_clock.c. The real time timer is processed by a timeout * routine, called from the softclock() routine. Since a callout * may be delayed in real time due to interrupt processing in the system, * it is possible for the real time timeout routine (realitexpire, given below), * to be delayed in real time past when it is supposed to occur. It * does not suffice, therefore, to reload the real timer .it_value from the * real time timers .it_interval. Rather, we compute the next time in * absolute time the timer should go off. */ #ifndef _SYS_SYSPROTO_H_ struct getitimer_args { u_int which; struct itimerval *itv; }; #endif /* * MPSAFE */ int getitimer(struct thread *td, struct getitimer_args *uap) { struct itimerval aitv; int error; error = kern_getitimer(td, uap->which, &aitv); if (error != 0) return (error); return (copyout(&aitv, uap->itv, sizeof (struct itimerval))); } int kern_getitimer(struct thread *td, u_int which, struct itimerval *aitv) { struct proc *p = td->td_proc; struct timeval ctv; if (which > ITIMER_PROF) return (EINVAL); if (which == ITIMER_REAL) { /* * Convert from absolute to relative time in .it_value * part of real time timer. If time for real time timer * has passed return 0, else return difference between * current time and time for the timer to go off. */ PROC_LOCK(p); *aitv = p->p_realtimer; PROC_UNLOCK(p); if (timevalisset(&aitv->it_value)) { getmicrouptime(&ctv); if (timevalcmp(&aitv->it_value, &ctv, <)) timevalclear(&aitv->it_value); else timevalsub(&aitv->it_value, &ctv); } } else { mtx_lock_spin(&sched_lock); *aitv = p->p_stats->p_timer[which]; mtx_unlock_spin(&sched_lock); } return (0); } #ifndef _SYS_SYSPROTO_H_ struct setitimer_args { u_int which; struct itimerval *itv, *oitv; }; #endif /* * MPSAFE */ int setitimer(struct thread *td, struct setitimer_args *uap) { struct itimerval aitv, oitv; int error; if (uap->itv == NULL) { uap->itv = uap->oitv; return (getitimer(td, (struct getitimer_args *)uap)); } if ((error = copyin(uap->itv, &aitv, sizeof(struct itimerval)))) return (error); error = kern_setitimer(td, uap->which, &aitv, &oitv); if (error != 0 || uap->oitv == NULL) return (error); return (copyout(&oitv, uap->oitv, sizeof(struct itimerval))); } int kern_setitimer(struct thread *td, u_int which, struct itimerval *aitv, struct itimerval *oitv) { struct proc *p = td->td_proc; struct timeval ctv; if (aitv == NULL) return (kern_getitimer(td, which, oitv)); if (which > ITIMER_PROF) return (EINVAL); if (itimerfix(&aitv->it_value)) return (EINVAL); if (!timevalisset(&aitv->it_value)) timevalclear(&aitv->it_interval); else if (itimerfix(&aitv->it_interval)) return (EINVAL); if (which == ITIMER_REAL) { PROC_LOCK(p); if (timevalisset(&p->p_realtimer.it_value)) callout_stop(&p->p_itcallout); getmicrouptime(&ctv); if (timevalisset(&aitv->it_value)) { callout_reset(&p->p_itcallout, tvtohz(&aitv->it_value), realitexpire, p); timevaladd(&aitv->it_value, &ctv); } *oitv = p->p_realtimer; p->p_realtimer = *aitv; PROC_UNLOCK(p); if (timevalisset(&oitv->it_value)) { if (timevalcmp(&oitv->it_value, &ctv, <)) timevalclear(&oitv->it_value); else timevalsub(&oitv->it_value, &ctv); } } else { mtx_lock_spin(&sched_lock); *oitv = p->p_stats->p_timer[which]; p->p_stats->p_timer[which] = *aitv; mtx_unlock_spin(&sched_lock); } return (0); } /* * Real interval timer expired: * send process whose timer expired an alarm signal. * If time is not set up to reload, then just return. * Else compute next time timer should go off which is > current time. * This is where delay in processing this timeout causes multiple * SIGALRM calls to be compressed into one. * tvtohz() always adds 1 to allow for the time until the next clock * interrupt being strictly less than 1 clock tick, but we don't want * that here since we want to appear to be in sync with the clock * interrupt even when we're delayed. */ void realitexpire(void *arg) { struct proc *p; struct timeval ctv, ntv; p = (struct proc *)arg; PROC_LOCK(p); psignal(p, SIGALRM); if (!timevalisset(&p->p_realtimer.it_interval)) { timevalclear(&p->p_realtimer.it_value); if (p->p_flag & P_WEXIT) wakeup(&p->p_itcallout); PROC_UNLOCK(p); return; } for (;;) { timevaladd(&p->p_realtimer.it_value, &p->p_realtimer.it_interval); getmicrouptime(&ctv); if (timevalcmp(&p->p_realtimer.it_value, &ctv, >)) { ntv = p->p_realtimer.it_value; timevalsub(&ntv, &ctv); callout_reset(&p->p_itcallout, tvtohz(&ntv) - 1, realitexpire, p); PROC_UNLOCK(p); return; } } /*NOTREACHED*/ } /* * Check that a proposed value to load into the .it_value or * .it_interval part of an interval timer is acceptable, and * fix it to have at least minimal value (i.e. if it is less * than the resolution of the clock, round it up.) */ int itimerfix(struct timeval *tv) { if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec >= 1000000) return (EINVAL); if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) tv->tv_usec = tick; return (0); } /* * Decrement an interval timer by a specified number * of microseconds, which must be less than a second, * i.e. < 1000000. If the timer expires, then reload * it. In this case, carry over (usec - old value) to * reduce the value reloaded into the timer so that * the timer does not drift. This routine assumes * that it is called in a context where the timers * on which it is operating cannot change in value. */ int itimerdecr(struct itimerval *itp, int usec) { if (itp->it_value.tv_usec < usec) { if (itp->it_value.tv_sec == 0) { /* expired, and already in next interval */ usec -= itp->it_value.tv_usec; goto expire; } itp->it_value.tv_usec += 1000000; itp->it_value.tv_sec--; } itp->it_value.tv_usec -= usec; usec = 0; if (timevalisset(&itp->it_value)) return (1); /* expired, exactly at end of interval */ expire: if (timevalisset(&itp->it_interval)) { itp->it_value = itp->it_interval; itp->it_value.tv_usec -= usec; if (itp->it_value.tv_usec < 0) { itp->it_value.tv_usec += 1000000; itp->it_value.tv_sec--; } } else itp->it_value.tv_usec = 0; /* sec is already 0 */ return (0); } /* * Add and subtract routines for timevals. * N.B.: subtract routine doesn't deal with * results which are before the beginning, * it just gets very confused in this case. * Caveat emptor. */ void timevaladd(struct timeval *t1, const struct timeval *t2) { t1->tv_sec += t2->tv_sec; t1->tv_usec += t2->tv_usec; timevalfix(t1); } void timevalsub(struct timeval *t1, const struct timeval *t2) { t1->tv_sec -= t2->tv_sec; t1->tv_usec -= t2->tv_usec; timevalfix(t1); } static void timevalfix(struct timeval *t1) { if (t1->tv_usec < 0) { t1->tv_sec--; t1->tv_usec += 1000000; } if (t1->tv_usec >= 1000000) { t1->tv_sec++; t1->tv_usec -= 1000000; } } /* * ratecheck(): simple time-based rate-limit checking. */ int ratecheck(struct timeval *lasttime, const struct timeval *mininterval) { struct timeval tv, delta; int rv = 0; getmicrouptime(&tv); /* NB: 10ms precision */ delta = tv; timevalsub(&delta, lasttime); /* * check for 0,0 is so that the message will be seen at least once, * even if interval is huge. */ if (timevalcmp(&delta, mininterval, >=) || (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { *lasttime = tv; rv = 1; } return (rv); } /* * ppsratecheck(): packets (or events) per second limitation. * * Return 0 if the limit is to be enforced (e.g. the caller * should drop a packet because of the rate limitation). * * maxpps of 0 always causes zero to be returned. maxpps of -1 * always causes 1 to be returned; this effectively defeats rate * limiting. * * Note that we maintain the struct timeval for compatibility * with other bsd systems. We reuse the storage and just monitor * clock ticks for minimal overhead. */ int ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) { int now; /* * Reset the last time and counter if this is the first call * or more than a second has passed since the last update of * lasttime. */ now = ticks; if (lasttime->tv_sec == 0 || (u_int)(now - lasttime->tv_sec) >= hz) { lasttime->tv_sec = now; *curpps = 1; return (maxpps != 0); } else { (*curpps)++; /* NB: ignore potential overflow */ return (maxpps < 0 || *curpps < maxpps); } } static void itimer_start(void) { struct kclock rt_clock = { .timer_create = realtimer_create, .timer_delete = realtimer_delete, .timer_settime = realtimer_settime, .timer_gettime = realtimer_gettime, .event_hook = realtimer_event_hook }; itimer_zone = uma_zcreate("itimer", sizeof(struct itimer), NULL, NULL, itimer_init, itimer_fini, UMA_ALIGN_PTR, 0); register_posix_clock(CLOCK_REALTIME, &rt_clock); register_posix_clock(CLOCK_MONOTONIC, &rt_clock); p31b_setcfg(CTL_P1003_1B_TIMERS, 200112L); p31b_setcfg(CTL_P1003_1B_DELAYTIMER_MAX, INT_MAX); p31b_setcfg(CTL_P1003_1B_TIMER_MAX, TIMER_MAX); EVENTHANDLER_REGISTER(process_exit, itimers_event_hook_exit, (void *)ITIMER_EV_EXIT, EVENTHANDLER_PRI_ANY); EVENTHANDLER_REGISTER(process_exec, itimers_event_hook_exec, (void *)ITIMER_EV_EXEC, EVENTHANDLER_PRI_ANY); } int register_posix_clock(int clockid, struct kclock *clk) { if ((unsigned)clockid >= MAX_CLOCKS) { printf("%s: invalid clockid\n", __func__); return (0); } posix_clocks[clockid] = *clk; return (1); } static int itimer_init(void *mem, int size, int flags) { struct itimer *it; it = (struct itimer *)mem; mtx_init(&it->it_mtx, "itimer lock", NULL, MTX_DEF); return (0); } static void itimer_fini(void *mem, int size) { struct itimer *it; it = (struct itimer *)mem; mtx_destroy(&it->it_mtx); } static void itimer_enter(struct itimer *it) { mtx_assert(&it->it_mtx, MA_OWNED); it->it_usecount++; } static void itimer_leave(struct itimer *it) { mtx_assert(&it->it_mtx, MA_OWNED); KASSERT(it->it_usecount > 0, ("invalid it_usecount")); if (--it->it_usecount == 0 && (it->it_flags & ITF_WANTED) != 0) wakeup(it); } #ifndef _SYS_SYSPROTO_H_ struct ktimer_create_args { clockid_t clock_id; struct sigevent * evp; int * timerid; }; #endif int ktimer_create(struct thread *td, struct ktimer_create_args *uap) { struct sigevent *evp1, ev; int id; int error; if (uap->evp != NULL) { error = copyin(uap->evp, &ev, sizeof(ev)); if (error != 0) return (error); evp1 = &ev; } else evp1 = NULL; error = kern_timer_create(td, uap->clock_id, evp1, &id, -1); if (error == 0) { error = copyout(&id, uap->timerid, sizeof(int)); if (error != 0) kern_timer_delete(td, id); } return (error); } static int kern_timer_create(struct thread *td, clockid_t clock_id, struct sigevent *evp, int *timerid, int preset_id) { struct proc *p = td->td_proc; struct itimer *it; int id; int error; if (clock_id < 0 || clock_id >= MAX_CLOCKS) return (EINVAL); if (posix_clocks[clock_id].timer_create == NULL) return (EINVAL); if (evp != NULL) { if (evp->sigev_notify != SIGEV_NONE && evp->sigev_notify != SIGEV_SIGNAL && evp->sigev_notify != SIGEV_THREAD_ID) return (EINVAL); if ((evp->sigev_notify == SIGEV_SIGNAL || evp->sigev_notify == SIGEV_THREAD_ID) && !_SIG_VALID(evp->sigev_signo)) return (EINVAL); } if (p->p_itimers == NULL) itimers_alloc(p); it = uma_zalloc(itimer_zone, M_WAITOK); it->it_flags = 0; it->it_usecount = 0; it->it_active = 0; timespecclear(&it->it_time.it_value); timespecclear(&it->it_time.it_interval); it->it_overrun = 0; it->it_overrun_last = 0; it->it_clockid = clock_id; it->it_timerid = -1; it->it_proc = p; ksiginfo_init(&it->it_ksi); it->it_ksi.ksi_flags |= KSI_INS | KSI_EXT; error = CLOCK_CALL(clock_id, timer_create, (it)); if (error != 0) goto out; PROC_LOCK(p); if (preset_id != -1) { KASSERT(preset_id >= 0 && preset_id < 3, ("invalid preset_id")); id = preset_id; if (p->p_itimers->its_timers[id] != NULL) { PROC_UNLOCK(p); error = 0; goto out; } } else { /* * Find a free timer slot, skipping those reserved * for setitimer(). */ for (id = 3; id < TIMER_MAX; id++) if (p->p_itimers->its_timers[id] == NULL) break; if (id == TIMER_MAX) { PROC_UNLOCK(p); error = EAGAIN; goto out; } } it->it_timerid = id; p->p_itimers->its_timers[id] = it; if (evp != NULL) it->it_sigev = *evp; else { it->it_sigev.sigev_notify = SIGEV_SIGNAL; switch (clock_id) { default: case CLOCK_REALTIME: it->it_sigev.sigev_signo = SIGALRM; break; case CLOCK_VIRTUAL: it->it_sigev.sigev_signo = SIGVTALRM; break; case CLOCK_PROF: it->it_sigev.sigev_signo = SIGPROF; break; } it->it_sigev.sigev_value.sival_int = id; } if (it->it_sigev.sigev_notify == SIGEV_SIGNAL || it->it_sigev.sigev_notify == SIGEV_THREAD_ID) { it->it_ksi.ksi_signo = it->it_sigev.sigev_signo; it->it_ksi.ksi_code = SI_TIMER; it->it_ksi.ksi_value = it->it_sigev.sigev_value; it->it_ksi.ksi_timerid = id; } PROC_UNLOCK(p); *timerid = id; return (0); out: ITIMER_LOCK(it); CLOCK_CALL(it->it_clockid, timer_delete, (it)); ITIMER_UNLOCK(it); uma_zfree(itimer_zone, it); return (error); } #ifndef _SYS_SYSPROTO_H_ struct ktimer_delete_args { int timerid; }; #endif int ktimer_delete(struct thread *td, struct ktimer_delete_args *uap) { return (kern_timer_delete(td, uap->timerid)); } static struct itimer * itimer_find(struct proc *p, int timerid, int include_deleting) { struct itimer *it; PROC_LOCK_ASSERT(p, MA_OWNED); if ((p->p_itimers == NULL) || (timerid >= TIMER_MAX) || (it = p->p_itimers->its_timers[timerid]) == NULL) { return (NULL); } ITIMER_LOCK(it); if (!include_deleting && (it->it_flags & ITF_DELETING) != 0) { ITIMER_UNLOCK(it); it = NULL; } return (it); } static int kern_timer_delete(struct thread *td, int timerid) { struct proc *p = td->td_proc; struct itimer *it; PROC_LOCK(p); it = itimer_find(p, timerid, 0); if (it == NULL) { PROC_UNLOCK(p); return (EINVAL); } PROC_UNLOCK(p); it->it_flags |= ITF_DELETING; while (it->it_usecount > 0) { it->it_flags |= ITF_WANTED; msleep(it, &it->it_mtx, PPAUSE, "itimer", 0); } it->it_flags &= ~ITF_WANTED; CLOCK_CALL(it->it_clockid, timer_delete, (it)); ITIMER_UNLOCK(it); PROC_LOCK(p); if (KSI_ONQ(&it->it_ksi)) sigqueue_take(&it->it_ksi); p->p_itimers->its_timers[timerid] = NULL; PROC_UNLOCK(p); uma_zfree(itimer_zone, it); return (0); } #ifndef _SYS_SYSPROTO_H_ struct ktimer_settime_args { int timerid; int flags; const struct itimerspec * value; struct itimerspec * ovalue; }; #endif int ktimer_settime(struct thread *td, struct ktimer_settime_args *uap) { struct proc *p = td->td_proc; struct itimer *it; struct itimerspec val, oval, *ovalp; int error; error = copyin(uap->value, &val, sizeof(val)); if (error != 0) return (error); if (uap->ovalue != NULL) ovalp = &oval; else ovalp = NULL; PROC_LOCK(p); if (uap->timerid < 3 || (it = itimer_find(p, uap->timerid, 0)) == NULL) { PROC_UNLOCK(p); error = EINVAL; } else { PROC_UNLOCK(p); itimer_enter(it); error = CLOCK_CALL(it->it_clockid, timer_settime, (it, uap->flags, &val, ovalp)); itimer_leave(it); ITIMER_UNLOCK(it); } if (error == 0 && uap->ovalue != NULL) error = copyout(ovalp, uap->ovalue, sizeof(*ovalp)); return (error); } #ifndef _SYS_SYSPROTO_H_ struct ktimer_gettime_args { int timerid; struct itimerspec * value; }; #endif int ktimer_gettime(struct thread *td, struct ktimer_gettime_args *uap) { struct proc *p = td->td_proc; struct itimer *it; struct itimerspec val; int error; PROC_LOCK(p); if (uap->timerid < 3 || (it = itimer_find(p, uap->timerid, 0)) == NULL) { PROC_UNLOCK(p); error = EINVAL; } else { PROC_UNLOCK(p); itimer_enter(it); error = CLOCK_CALL(it->it_clockid, timer_gettime, (it, &val)); itimer_leave(it); ITIMER_UNLOCK(it); } if (error == 0) error = copyout(&val, uap->value, sizeof(val)); return (error); } #ifndef _SYS_SYSPROTO_H_ struct timer_getoverrun_args { int timerid; }; #endif int ktimer_getoverrun(struct thread *td, struct ktimer_getoverrun_args *uap) { struct proc *p = td->td_proc; struct itimer *it; int error ; PROC_LOCK(p); if (uap->timerid < 3 || (it = itimer_find(p, uap->timerid, 0)) == NULL) { PROC_UNLOCK(p); error = EINVAL; } else { td->td_retval[0] = it->it_overrun_last; ITIMER_UNLOCK(it); PROC_UNLOCK(p); error = 0; } return (error); } static int realtimer_create(struct itimer *it) { callout_init_mtx(&it->it_callout, &it->it_mtx, 0); return (0); } static int realtimer_delete(struct itimer *it) { mtx_assert(&it->it_mtx, MA_OWNED); callout_stop(&it->it_callout); return (0); } static int realtimer_gettime(struct itimer *it, struct itimerspec *ovalue) { struct timespec cts; mtx_assert(&it->it_mtx, MA_OWNED); realtimer_clocktime(it->it_clockid, &cts); *ovalue = it->it_time; if (ovalue->it_value.tv_sec != 0 || ovalue->it_value.tv_nsec != 0) { timespecsub(&ovalue->it_value, &cts); if (ovalue->it_value.tv_sec < 0 || (ovalue->it_value.tv_sec == 0 && ovalue->it_value.tv_nsec == 0)) { ovalue->it_value.tv_sec = 0; ovalue->it_value.tv_nsec = 1; } } return (0); } static int realtimer_settime(struct itimer *it, int flags, struct itimerspec *value, struct itimerspec *ovalue) { struct timespec cts, ts; struct timeval tv; struct itimerspec val; mtx_assert(&it->it_mtx, MA_OWNED); val = *value; if (itimespecfix(&val.it_value)) return (EINVAL); if (timespecisset(&val.it_value)) { if (itimespecfix(&val.it_interval)) return (EINVAL); } else { timespecclear(&val.it_interval); } if (ovalue != NULL) realtimer_gettime(it, ovalue); it->it_time = val; if (timespecisset(&val.it_value)) { realtimer_clocktime(it->it_clockid, &cts); ts = val.it_value; if ((flags & TIMER_ABSTIME) == 0) { /* Convert to absolute time. */ timespecadd(&it->it_time.it_value, &cts); } else { timespecsub(&ts, &cts); /* * We don't care if ts is negative, tztohz will * fix it. */ } TIMESPEC_TO_TIMEVAL(&tv, &ts); callout_reset(&it->it_callout, tvtohz(&tv), realtimer_expire, it); } else { callout_stop(&it->it_callout); } return (0); } static void realtimer_clocktime(clockid_t id, struct timespec *ts) { if (id == CLOCK_REALTIME) getnanotime(ts); else /* CLOCK_MONOTONIC */ getnanouptime(ts); } int itimer_accept(struct proc *p, int timerid, ksiginfo_t *ksi) { struct itimer *it; PROC_LOCK_ASSERT(p, MA_OWNED); it = itimer_find(p, timerid, 0); if (it != NULL) { ksi->ksi_overrun = it->it_overrun; it->it_overrun_last = it->it_overrun; it->it_overrun = 0; ITIMER_UNLOCK(it); return (0); } return (EINVAL); } int itimespecfix(struct timespec *ts) { if (ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000) return (EINVAL); if (ts->tv_sec == 0 && ts->tv_nsec != 0 && ts->tv_nsec < tick * 1000) ts->tv_nsec = tick * 1000; return (0); } static void realtimer_event_hook(struct proc *p, clockid_t clock_id, int event) { struct itimers *its; struct itimer *it; int i; /* * Timer 0 (ITIMER_REAL) is XSI interval timer, according to POSIX * specification, it should be inherited by new process image. */ if (event == ITIMER_EV_EXEC) i = 1; else i = 0; its = p->p_itimers; for (; i < TIMER_MAX; i++) { if ((it = its->its_timers[i]) != NULL && it->it_clockid == clock_id) { ITIMER_LOCK(it); callout_stop(&it->it_callout); ITIMER_UNLOCK(it); } } } /* Timeout callback for realtime timer */ static void realtimer_expire(void *arg) { struct timespec cts, ts; struct timeval tv; struct itimer *it; struct proc *p; it = (struct itimer *)arg; p = it->it_proc; realtimer_clocktime(it->it_clockid, &cts); /* Only fire if time is reached. */ if (timespeccmp(&cts, &it->it_time.it_value, >=)) { if (timespecisset(&it->it_time.it_interval)) { timespecadd(&it->it_time.it_value, &it->it_time.it_interval); while (timespeccmp(&cts, &it->it_time.it_value, >=)) { if (it->it_overrun < INT_MAX) it->it_overrun++; else it->it_ksi.ksi_errno = ERANGE; timespecadd(&it->it_time.it_value, &it->it_time.it_interval); } } else { /* single shot timer ? */ timespecclear(&it->it_time.it_value); } if (timespecisset(&it->it_time.it_value)) { ts = it->it_time.it_value; timespecsub(&ts, &cts); TIMESPEC_TO_TIMEVAL(&tv, &ts); callout_reset(&it->it_callout, tvtohz(&tv), realtimer_expire, it); } ITIMER_UNLOCK(it); itimer_fire(it); ITIMER_LOCK(it); } else if (timespecisset(&it->it_time.it_value)) { ts = it->it_time.it_value; timespecsub(&ts, &cts); TIMESPEC_TO_TIMEVAL(&tv, &ts); callout_reset(&it->it_callout, tvtohz(&tv), realtimer_expire, it); } } void itimer_fire(struct itimer *it) { struct proc *p = it->it_proc; int ret; if (it->it_sigev.sigev_notify == SIGEV_SIGNAL || it->it_sigev.sigev_notify == SIGEV_THREAD_ID) { PROC_LOCK(p); if (!KSI_ONQ(&it->it_ksi)) { it->it_ksi.ksi_errno = 0; ret = psignal_event(p, &it->it_sigev, &it->it_ksi); if (__predict_false(ret != 0)) { it->it_overrun++; /* * Broken userland code, thread went * away, disarm the timer. */ if (ret == ESRCH) { ITIMER_LOCK(it); timespecclear(&it->it_time.it_value); timespecclear(&it->it_time.it_interval); callout_stop(&it->it_callout); ITIMER_UNLOCK(it); } } } else { if (it->it_overrun < INT_MAX) it->it_overrun++; else it->it_ksi.ksi_errno = ERANGE; } PROC_UNLOCK(p); } } static void itimers_alloc(struct proc *p) { struct itimers *its; int i; its = malloc(sizeof (struct itimers), M_SUBPROC, M_WAITOK | M_ZERO); LIST_INIT(&its->its_virtual); LIST_INIT(&its->its_prof); TAILQ_INIT(&its->its_worklist); for (i = 0; i < TIMER_MAX; i++) its->its_timers[i] = NULL; PROC_LOCK(p); if (p->p_itimers == NULL) { p->p_itimers = its; PROC_UNLOCK(p); } else { PROC_UNLOCK(p); free(its, M_SUBPROC); } } static void itimers_event_hook_exec(void *arg, struct proc *p, struct image_params *imgp __unused) { itimers_event_hook_exit(arg, p); } /* Clean up timers when some process events are being triggered. */ static void itimers_event_hook_exit(void *arg, struct proc *p) { struct itimers *its; struct itimer *it; int event = (int)(intptr_t)arg; int i; if (p->p_itimers != NULL) { its = p->p_itimers; for (i = 0; i < MAX_CLOCKS; ++i) { if (posix_clocks[i].event_hook != NULL) CLOCK_CALL(i, event_hook, (p, i, event)); } /* * According to susv3, XSI interval timers should be inherited * by new image. */ if (event == ITIMER_EV_EXEC) i = 3; else if (event == ITIMER_EV_EXIT) i = 0; else panic("unhandled event"); for (; i < TIMER_MAX; ++i) { if ((it = its->its_timers[i]) != NULL) { PROC_LOCK(p); if (KSI_ONQ(&it->it_ksi)) sigqueue_take(&it->it_ksi); PROC_UNLOCK(p); uma_zfree(itimer_zone, its->its_timers[i]); its->its_timers[i] = NULL; } } if (its->its_timers[0] == NULL && its->its_timers[1] == NULL && its->its_timers[2] == NULL) { free(its, M_SUBPROC); p->p_itimers = NULL; } } } Index: head/sys/kern/makesyscalls.sh =================================================================== --- head/sys/kern/makesyscalls.sh (revision 164183) +++ head/sys/kern/makesyscalls.sh (revision 164184) @@ -1,507 +1,507 @@ #! /bin/sh - # @(#)makesyscalls.sh 8.1 (Berkeley) 6/10/93 # $FreeBSD$ set -e # name of compat options: compat=COMPAT_43 compat4=COMPAT_FREEBSD4 # output files: sysnames="syscalls.c" sysproto="../sys/sysproto.h" sysproto_h=_SYS_SYSPROTO_H_ syshdr="../sys/syscall.h" sysmk="../sys/syscall.mk" syssw="init_sysent.c" syscallprefix="SYS_" switchname="sysent" namesname="syscallnames" systrace="systrace_args.c" # tmp files: sysaue="sysent.aue.$$" sysdcl="sysent.dcl.$$" syscompat="sysent.compat.$$" syscompatdcl="sysent.compatdcl.$$" syscompat4="sysent.compat4.$$" syscompat4dcl="sysent.compat4dcl.$$" sysent="sysent.switch.$$" sysinc="sysinc.switch.$$" sysarg="sysarg.switch.$$" sysprotoend="sysprotoend.$$" trap "rm $sysaue $sysdcl $syscompat $syscompatdcl $syscompat4 $syscompat4dcl $sysent $sysinc $sysarg $sysprotoend" 0 touch $sysaue $sysdcl $syscompat $syscompatdcl $syscompat4 $syscompat4dcl $sysent $sysinc $sysarg $sysprotoend case $# in 0) echo "usage: $0 input-file " 1>&2 exit 1 ;; esac if [ -n "$2" -a -f "$2" ]; then . $2 fi sed -e ' s/\$//g :join /\\$/{a\ N s/\\\n// b join } 2,${ /^#/!s/\([{}()*,]\)/ \1 /g } ' < $1 | awk " BEGIN { sysaue = \"$sysaue\" sysdcl = \"$sysdcl\" sysproto = \"$sysproto\" sysprotoend = \"$sysprotoend\" sysproto_h = \"$sysproto_h\" syscompat = \"$syscompat\" syscompatdcl = \"$syscompatdcl\" syscompat4 = \"$syscompat4\" syscompat4dcl = \"$syscompat4dcl\" sysent = \"$sysent\" syssw = \"$syssw\" sysinc = \"$sysinc\" sysarg = \"$sysarg\" sysnames = \"$sysnames\" syshdr = \"$syshdr\" sysmk = \"$sysmk\" systrace = \"$systrace\" compat = \"$compat\" compat4 = \"$compat4\" syscallprefix = \"$syscallprefix\" switchname = \"$switchname\" namesname = \"$namesname\" infile = \"$1\" "' printf "/*\n * System call switch table.\n *\n" > syssw printf " * DO NOT EDIT-- this file is automatically generated.\n" > syssw printf " * $%s$\n", "FreeBSD" > syssw printf "/*\n * System call prototypes.\n *\n" > sysarg printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysarg printf " * $%s$\n", "FreeBSD" > sysarg printf "\n#ifdef %s\n\n", compat > syscompat printf "\n#ifdef %s\n\n", compat4 > syscompat4 printf "/*\n * System call names.\n *\n" > sysnames printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnames printf " * $%s$\n", "FreeBSD" > sysnames printf "/*\n * System call numbers.\n *\n" > syshdr printf " * DO NOT EDIT-- this file is automatically generated.\n" > syshdr printf " * $%s$\n", "FreeBSD" > syshdr printf "# FreeBSD system call names.\n" > sysmk printf "# DO NOT EDIT-- this file is automatically generated.\n" > sysmk printf "# $%s$\n", "FreeBSD" > sysmk printf "/*\n * System call argument to DTrace register array converstion.\n *\n" > systrace printf " * DO NOT EDIT-- this file is automatically generated.\n" > systrace printf " * $%s$\n", "FreeBSD" > systrace } NR == 1 { gsub("[$]FreeBSD: ", "", $0) gsub(" [$]", "", $0) printf " * created from%s\n */\n\n", $0 > syssw printf "\n/* The casts are bogus but will do for now. */\n" > sysent printf "struct sysent %s[] = {\n",switchname > sysent printf " * created from%s\n */\n\n", $0 > sysarg printf "#ifndef %s\n", sysproto_h > sysarg printf "#define\t%s\n\n", sysproto_h > sysarg printf "#include \n" > sysarg printf "#include \n" > sysarg - printf "#include \n" > sysarg + printf "#include \n" > sysarg printf "#include \n\n" > sysarg printf "#include \n\n" > sysarg printf "struct proc;\n\n" > sysarg printf "struct thread;\n\n" > sysarg printf "#define\tPAD_(t)\t(sizeof(register_t) <= sizeof(t) ? \\\n" > sysarg printf "\t\t0 : sizeof(register_t) - sizeof(t))\n\n" > sysarg printf "#if BYTE_ORDER == LITTLE_ENDIAN\n"> sysarg printf "#define\tPADL_(t)\t0\n" > sysarg printf "#define\tPADR_(t)\tPAD_(t)\n" > sysarg printf "#else\n" > sysarg printf "#define\tPADL_(t)\tPAD_(t)\n" > sysarg printf "#define\tPADR_(t)\t0\n" > sysarg printf "#endif\n\n" > sysarg printf " * created from%s\n */\n\n", $0 > sysnames printf "const char *%s[] = {\n", namesname > sysnames printf " * created from%s\n */\n\n", $0 > syshdr printf "# created from%s\nMIASM = ", $0 > sysmk printf " * This file is part of the DTrace syscall provider.\n */\n\n" > systrace printf "static void\nsystrace_args(int sysnum, void *params, u_int64_t *uarg, int *n_args)\n{\n" > systrace printf "\tint64_t *iarg = (int64_t *) uarg;\n" > systrace printf "\tswitch (sysnum) {\n" > systrace next } NF == 0 || $1 ~ /^;/ { next } $1 ~ /^#[ ]*include/ { print > sysinc next } $1 ~ /^#[ ]*if/ { print > sysent print > sysdcl print > sysarg print > syscompat print > syscompat4 print > sysnames savesyscall = syscall next } $1 ~ /^#[ ]*else/ { print > sysent print > sysdcl print > sysarg print > syscompat print > syscompat4 print > sysnames syscall = savesyscall next } $1 ~ /^#/ { print > sysent print > sysdcl print > sysarg print > syscompat print > syscompat4 print > sysnames next } syscall != $1 { printf "%s: line %d: syscall number out of sync at %d\n", infile, NR, syscall printf "line is:\n" print exit 1 } function align_sysent_comment(column) { printf("\t") > sysent column = column + 8 - column % 8 while (column < 56) { printf("\t") > sysent column = column + 8 } } function parserr(was, wanted) { printf "%s: line %d: unexpected %s (expected %s)\n", infile, NR, was, wanted exit 1 } function parseline() { f=4 # toss number, type, audit event argc= 0; argssize = "0" if ($NF != "}") { funcalias=$(NF-2) argalias=$(NF-1) rettype=$NF end=NF-3 } else { funcalias="" argalias="" rettype="int" end=NF } if ($3 == "NODEF") { auditev="AUE_NULL" funcname=$4 argssize = "AS(" $6 ")" return } if ($f != "{") parserr($f, "{") f++ if ($end != "}") parserr($end, "}") end-- if ($end != ";") parserr($end, ";") end-- if ($end != ")") parserr($end, ")") end-- f++ #function return type funcname=$f if (funcalias == "") funcalias = funcname if (argalias == "") { argalias = funcname "_args" if ($3 == "COMPAT") argalias = "o" argalias if ($3 == "COMPAT4") argalias = "freebsd4_" argalias } f++ if ($f != "(") parserr($f, ")") f++ if (f == end) { if ($f != "void") parserr($f, "argument definition") return } while (f <= end) { argc++ argtype[argc]="" oldf="" while (f < end && $(f+1) != ",") { if (argtype[argc] != "" && oldf != "*") argtype[argc] = argtype[argc]" "; argtype[argc] = argtype[argc]$f; oldf = $f; f++ } if (argtype[argc] == "") parserr($f, "argument definition") argname[argc]=$f; f += 2; # skip name, and any comma } if (argc != 0) argssize = "AS(" argalias ")" } { comment = $4 if (NF < 7) for (i = 5; i <= NF; i++) comment = comment " " $i } # # The AUE_ audit event identifier. # { auditev = $2; } $3 == "STD" || $3 == "NODEF" || $3 == "NOARGS" || $3 == "NOPROTO" \ || $3 == "NOIMPL" || $3 == "NOSTD" { parseline() printf("\t/* %s */\n\tcase %d: {\n", funcname, syscall) > systrace if (argc > 0) { printf("\t\tstruct %s *p = params;\n", argalias) > systrace for (i = 1; i <= argc; i++) { if (index(argtype[i], "*") > 0 || argtype[i] == "caddr_t") printf("\t\tuarg[%d] = (intptr_t) p->%s; /* %s */\n", \ i - 1, \ argname[i], argtype[i]) > systrace else if (substr(argtype[i], 1, 1) == "u" || argtype[i] == "size_t") printf("\t\tuarg[%d] = p->%s; /* %s */\n", \ i - 1, \ argname[i], argtype[i]) > systrace else printf("\t\tiarg[%d] = p->%s; /* %s */\n", \ i - 1, \ argname[i], argtype[i]) > systrace } } printf("\t\t*n_args = %d;\n\t\tbreak;\n\t}\n", argc) > systrace if ((!nosys || funcname != "nosys") && \ (funcname != "lkmnosys") && (funcname != "lkmressys")) { if (argc != 0 && $3 != "NOARGS" && $3 != "NOPROTO") { printf("struct %s {\n", argalias) > sysarg for (i = 1; i <= argc; i++) printf("\tchar %s_l_[PADL_(%s)]; " \ "%s %s; char %s_r_[PADR_(%s)];\n", argname[i], argtype[i], argtype[i], argname[i], argname[i], argtype[i]) > sysarg printf("};\n") > sysarg } else if ($3 != "NOARGS" && $3 != "NOPROTO" && \ $3 != "NODEF") printf("struct %s {\n\tregister_t dummy;\n};\n", argalias) > sysarg } if (($3 != "NOPROTO" && $3 != "NODEF" && \ (funcname != "nosys" || !nosys)) || \ (funcname == "lkmnosys" && !lkmnosys) || \ funcname == "lkmressys") { printf("%s\t%s(struct thread *, struct %s *)", rettype, funcname, argalias) > sysdcl printf(";\n") > sysdcl printf("#define\t%sAUE_%s\t%s\n", syscallprefix, funcalias, auditev) > sysaue } if (funcname == "nosys") nosys = 1 if (funcname == "lkmnosys") lkmnosys = 1 printf("\t{ %s, (sy_call_t *)", argssize) > sysent column = 8 + 2 + length(argssize) + 15 if ($3 == "NOIMPL") { printf("%s },", "nosys, AUE_NULL, NULL, 0, 0") > sysent column = column + length("nosys") + 3 } else if ($3 == "NOSTD") { printf("%s },", "lkmressys, AUE_NULL, NULL, 0, 0") > sysent column = column + length("lkmressys") + 3 } else { printf("%s, %s, NULL, 0, 0 },", funcname, auditev) > sysent column = column + length(funcname) + length(auditev) + 3 } align_sysent_comment(column) printf("/* %d = %s */\n", syscall, funcalias) > sysent printf("\t\"%s\",\t\t\t/* %d = %s */\n", funcalias, syscall, funcalias) > sysnames if ($3 != "NODEF") { printf("#define\t%s%s\t%d\n", syscallprefix, funcalias, syscall) > syshdr printf(" \\\n\t%s.o", funcalias) > sysmk } syscall++ next } $3 == "COMPAT" || $3 == "COMPAT4" || $3 == "CPT_NOA" { if ($3 == "COMPAT" || $3 == "CPT_NOA") { ncompat++ out = syscompat outdcl = syscompatdcl wrap = "compat" prefix = "o" } else if ($3 == "COMPAT4") { ncompat4++ out = syscompat4 outdcl = syscompat4dcl wrap = "compat4" prefix = "freebsd4_" } parseline() if (argc != 0 && $3 != "CPT_NOA") { printf("struct %s {\n", argalias) > out for (i = 1; i <= argc; i++) printf("\tchar %s_l_[PADL_(%s)]; %s %s; " \ "char %s_r_[PADR_(%s)];\n", argname[i], argtype[i], argtype[i], argname[i], argname[i], argtype[i]) > out printf("};\n") > out } else if($3 != "CPT_NOA") printf("struct %s {\n\tregister_t dummy;\n};\n", argalias) > sysarg printf("%s\t%s%s(struct thread *, struct %s *);\n", rettype, prefix, funcname, argalias) > outdcl printf("\t{ %s(%s,%s), %s, NULL, 0, 0 },", wrap, argssize, funcname, auditev) > sysent align_sysent_comment(8 + 9 + \ length(argssize) + 1 + length(funcname) + length(auditev) + 4) printf("/* %d = old %s */\n", syscall, funcalias) > sysent printf("\t\"old.%s\",\t\t/* %d = old %s */\n", funcalias, syscall, funcalias) > sysnames printf("\t\t\t\t/* %d is old %s */\n", syscall, funcalias) > syshdr syscall++ next } $3 == "LIBCOMPAT" { ncompat++ parseline() printf("%s\to%s();\n", rettype, funcname) > syscompatdcl printf("\t{ compat(%s,%s), %s, NULL, 0, 0 },", argssize, funcname, auditev) > sysent align_sysent_comment(8 + 9 + \ length(argssize) + 1 + length(funcname) + length(auditev) + 4) printf("/* %d = old %s */\n", syscall, funcalias) > sysent printf("\t\"old.%s\",\t\t/* %d = old %s */\n", funcalias, syscall, funcalias) > sysnames printf("#define\t%s%s\t%d\t/* compatibility; still used by libc */\n", syscallprefix, funcalias, syscall) > syshdr printf(" \\\n\t%s.o", funcalias) > sysmk syscall++ next } $3 == "OBSOL" { printf("\t{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 },") > sysent align_sysent_comment(34) printf("/* %d = obsolete %s */\n", syscall, comment) > sysent printf("\t\"obs_%s\",\t\t\t/* %d = obsolete %s */\n", $4, syscall, comment) > sysnames printf("\t\t\t\t/* %d is obsolete %s */\n", syscall, comment) > syshdr syscall++ next } $3 == "UNIMPL" { printf("\t{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 },\t\t\t/* %d = %s */\n", syscall, comment) > sysent printf("\t\"#%d\",\t\t\t/* %d = %s */\n", syscall, syscall, comment) > sysnames syscall++ next } { printf "%s: line %d: unrecognized keyword %s\n", infile, NR, $3 exit 1 } END { printf "\n#define AS(name) (sizeof(struct name) / sizeof(register_t))\n" > sysinc if (ncompat != 0 || ncompat4 != 0) printf "#include \"opt_compat.h\"\n\n" > syssw printf "#include \\n" > syssw if (ncompat != 0) { printf "\n#ifdef %s\n", compat > sysinc printf "#define compat(n, name) n, (sy_call_t *)__CONCAT(o,name)\n" > sysinc printf "#else\n" > sysinc printf "#define compat(n, name) 0, (sy_call_t *)nosys\n" > sysinc printf "#endif\n" > sysinc } if (ncompat4 != 0) { printf "\n#ifdef %s\n", compat4 > sysinc printf "#define compat4(n, name) n, (sy_call_t *)__CONCAT(freebsd4_,name)\n" > sysinc printf "#else\n" > sysinc printf "#define compat4(n, name) 0, (sy_call_t *)nosys\n" > sysinc printf "#endif\n" > sysinc } printf("\n#endif /* %s */\n\n", compat) > syscompatdcl printf("\n#endif /* %s */\n\n", compat4) > syscompat4dcl printf("\n#undef PAD_\n") > sysprotoend printf("#undef PADL_\n") > sysprotoend printf("#undef PADR_\n") > sysprotoend printf("\n#endif /* !%s */\n", sysproto_h) > sysprotoend printf("\n") > sysmk printf("};\n") > sysent printf("};\n") > sysnames printf("#define\t%sMAXSYSCALL\t%d\n", syscallprefix, syscall) \ > syshdr printf "\tdefault:\n\t\t*n_args = 0;\n\t\tbreak;\n\t};\n}\n" > systrace } ' cat $sysinc $sysent >> $syssw cat $sysarg $sysdcl \ $syscompat $syscompatdcl \ $syscompat4 $syscompat4dcl \ $sysaue $sysprotoend > $sysproto Index: head/sys/kern/uipc_mqueue.c =================================================================== --- head/sys/kern/uipc_mqueue.c (revision 164183) +++ head/sys/kern/uipc_mqueue.c (revision 164184) @@ -1,2496 +1,2496 @@ /*- * Copyright (c) 2005 David Xu * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * POSIX message queue implementation. * * 1) A mqueue filesystem can be mounted, each message queue appears * in mounted directory, user can change queue's permission and * ownership, or remove a queue. Manually creating a file in the * directory causes a message queue to be created in the kernel with * default message queue attributes applied and same name used, this * method is not advocated since mq_open syscall allows user to specify * different attributes. Also the file system can be mounted multiple * times at different mount points but shows same contents. * * 2) Standard POSIX message queue API. The syscalls do not use vfs layer, * but directly operate on internal data structure, this allows user to * use the IPC facility without having to mount mqueue file system. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include /* * Limits and constants */ #define MQFS_NAMELEN NAME_MAX #define MQFS_DELEN (8 + MQFS_NAMELEN) /* node types */ typedef enum { mqfstype_none = 0, mqfstype_root, mqfstype_dir, mqfstype_this, mqfstype_parent, mqfstype_file, mqfstype_symlink, } mqfs_type_t; struct mqfs_node; /* * mqfs_info: describes a mqfs instance */ struct mqfs_info { struct sx mi_lock; struct mqfs_node *mi_root; struct unrhdr *mi_unrhdr; }; struct mqfs_vdata { LIST_ENTRY(mqfs_vdata) mv_link; struct mqfs_node *mv_node; struct vnode *mv_vnode; struct task mv_task; }; /* * mqfs_node: describes a node (file or directory) within a mqfs */ struct mqfs_node { char mn_name[MQFS_NAMELEN+1]; struct mqfs_info *mn_info; struct mqfs_node *mn_parent; LIST_HEAD(,mqfs_node) mn_children; LIST_ENTRY(mqfs_node) mn_sibling; LIST_HEAD(,mqfs_vdata) mn_vnodes; int mn_refcount; mqfs_type_t mn_type; int mn_deleted; u_int32_t mn_fileno; void *mn_data; struct timespec mn_birth; struct timespec mn_ctime; struct timespec mn_atime; struct timespec mn_mtime; uid_t mn_uid; gid_t mn_gid; int mn_mode; }; #define VTON(vp) (((struct mqfs_vdata *)((vp)->v_data))->mv_node) #define VTOMQ(vp) ((struct mqueue *)(VTON(vp)->mn_data)) #define VFSTOMQFS(m) ((struct mqfs_info *)((m)->mnt_data)) #define FPTOMQ(fp) ((struct mqueue *)(((struct mqfs_node *) \ (fp)->f_data)->mn_data)) TAILQ_HEAD(msgq, mqueue_msg); struct mqueue; struct mqueue_notifier { LIST_ENTRY(mqueue_notifier) nt_link; struct sigevent nt_sigev; ksiginfo_t nt_ksi; struct proc *nt_proc; }; struct mqueue { struct mtx mq_mutex; int mq_flags; long mq_maxmsg; long mq_msgsize; long mq_curmsgs; long mq_totalbytes; struct msgq mq_msgq; int mq_receivers; int mq_senders; struct selinfo mq_rsel; struct selinfo mq_wsel; struct mqueue_notifier *mq_notifier; }; #define MQ_RSEL 0x01 #define MQ_WSEL 0x02 struct mqueue_msg { TAILQ_ENTRY(mqueue_msg) msg_link; unsigned int msg_prio; unsigned int msg_size; /* following real data... */ }; SYSCTL_NODE(_kern, OID_AUTO, mqueue, CTLFLAG_RW, 0, "POSIX real time message queue"); static int default_maxmsg = 10; static int default_msgsize = 1024; static int maxmsg = 100; SYSCTL_INT(_kern_mqueue, OID_AUTO, maxmsg, CTLFLAG_RW, &maxmsg, 0, "Default maximum messages in queue"); static int maxmsgsize = 16384; SYSCTL_INT(_kern_mqueue, OID_AUTO, maxmsgsize, CTLFLAG_RW, &maxmsgsize, 0, "Default maximum message size"); static int maxmq = 100; SYSCTL_INT(_kern_mqueue, OID_AUTO, maxmq, CTLFLAG_RW, &maxmq, 0, "maximum message queues"); static int curmq = 0; SYSCTL_INT(_kern_mqueue, OID_AUTO, curmq, CTLFLAG_RW, &curmq, 0, "current message queue number"); static int unloadable = 0; static MALLOC_DEFINE(M_MQUEUEDATA, "mqdata", "mqueue data"); static eventhandler_tag exit_tag; /* Only one instance per-system */ static struct mqfs_info mqfs_data; static uma_zone_t mqnode_zone; static uma_zone_t mqueue_zone; static uma_zone_t mvdata_zone; static uma_zone_t mqnoti_zone; static struct vop_vector mqfs_vnodeops; static struct fileops mqueueops; /* * Directory structure construction and manipulation */ #ifdef notyet static struct mqfs_node *mqfs_create_dir(struct mqfs_node *parent, const char *name, int namelen, struct ucred *cred, int mode); static struct mqfs_node *mqfs_create_link(struct mqfs_node *parent, const char *name, int namelen, struct ucred *cred, int mode); #endif static struct mqfs_node *mqfs_create_file(struct mqfs_node *parent, const char *name, int namelen, struct ucred *cred, int mode); static int mqfs_destroy(struct mqfs_node *mn); static void mqfs_fileno_alloc(struct mqfs_info *mi, struct mqfs_node *mn); static void mqfs_fileno_free(struct mqfs_info *mi, struct mqfs_node *mn); static int mqfs_allocv(struct mount *mp, struct vnode **vpp, struct mqfs_node *pn); /* * Message queue construction and maniplation */ static struct mqueue *mqueue_alloc(const struct mq_attr *attr); static void mqueue_free(struct mqueue *mq); static int mqueue_send(struct mqueue *mq, const char *msg_ptr, size_t msg_len, unsigned msg_prio, int waitok, const struct timespec *abs_timeout); static int mqueue_receive(struct mqueue *mq, char *msg_ptr, size_t msg_len, unsigned *msg_prio, int waitok, const struct timespec *abs_timeout); static int _mqueue_send(struct mqueue *mq, struct mqueue_msg *msg, int timo); static int _mqueue_recv(struct mqueue *mq, struct mqueue_msg **msg, int timo); static void mqueue_send_notification(struct mqueue *mq); static void mqueue_fdclose(struct thread *td, int fd, struct file *fp); static void mq_proc_exit(void *arg, struct proc *p); /* * kqueue filters */ static void filt_mqdetach(struct knote *kn); static int filt_mqread(struct knote *kn, long hint); static int filt_mqwrite(struct knote *kn, long hint); struct filterops mq_rfiltops = { 1, NULL, filt_mqdetach, filt_mqread }; struct filterops mq_wfiltops = { 1, NULL, filt_mqdetach, filt_mqwrite }; /* * Initialize fileno bitmap */ static void mqfs_fileno_init(struct mqfs_info *mi) { struct unrhdr *up; up = new_unrhdr(1, INT_MAX, NULL); mi->mi_unrhdr = up; } /* * Tear down fileno bitmap */ static void mqfs_fileno_uninit(struct mqfs_info *mi) { struct unrhdr *up; up = mi->mi_unrhdr; mi->mi_unrhdr = NULL; delete_unrhdr(up); } /* * Allocate a file number */ static void mqfs_fileno_alloc(struct mqfs_info *mi, struct mqfs_node *mn) { /* make sure our parent has a file number */ if (mn->mn_parent && !mn->mn_parent->mn_fileno) mqfs_fileno_alloc(mi, mn->mn_parent); switch (mn->mn_type) { case mqfstype_root: case mqfstype_dir: case mqfstype_file: case mqfstype_symlink: mn->mn_fileno = alloc_unr(mi->mi_unrhdr); break; case mqfstype_this: KASSERT(mn->mn_parent != NULL, ("mqfstype_this node has no parent")); mn->mn_fileno = mn->mn_parent->mn_fileno; break; case mqfstype_parent: KASSERT(mn->mn_parent != NULL, ("mqfstype_parent node has no parent")); if (mn->mn_parent == mi->mi_root) { mn->mn_fileno = mn->mn_parent->mn_fileno; break; } KASSERT(mn->mn_parent->mn_parent != NULL, ("mqfstype_parent node has no grandparent")); mn->mn_fileno = mn->mn_parent->mn_parent->mn_fileno; break; default: KASSERT(0, ("mqfs_fileno_alloc() called for unknown type node: %d", mn->mn_type)); break; } } /* * Release a file number */ static void mqfs_fileno_free(struct mqfs_info *mi, struct mqfs_node *mn) { switch (mn->mn_type) { case mqfstype_root: case mqfstype_dir: case mqfstype_file: case mqfstype_symlink: free_unr(mi->mi_unrhdr, mn->mn_fileno); break; case mqfstype_this: case mqfstype_parent: /* ignore these, as they don't "own" their file number */ break; default: KASSERT(0, ("mqfs_fileno_free() called for unknown type node: %d", mn->mn_type)); break; } } static __inline struct mqfs_node * mqnode_alloc(void) { return uma_zalloc(mqnode_zone, M_WAITOK | M_ZERO); } static __inline void mqnode_free(struct mqfs_node *node) { uma_zfree(mqnode_zone, node); } static __inline void mqnode_addref(struct mqfs_node *node) { atomic_fetchadd_int(&node->mn_refcount, 1); } static __inline void mqnode_release(struct mqfs_node *node) { int old, exp; old = atomic_fetchadd_int(&node->mn_refcount, -1); if (node->mn_type == mqfstype_dir || node->mn_type == mqfstype_root) exp = 3; /* include . and .. */ else exp = 1; if (old == exp) mqfs_destroy(node); } /* * Add a node to a directory */ static int mqfs_add_node(struct mqfs_node *parent, struct mqfs_node *node) { KASSERT(parent != NULL, ("%s(): parent is NULL", __func__)); KASSERT(parent->mn_info != NULL, ("%s(): parent has no mn_info", __func__)); KASSERT(parent->mn_type == mqfstype_dir || parent->mn_type == mqfstype_root, ("%s(): parent is not a directory", __func__)); node->mn_info = parent->mn_info; node->mn_parent = parent; LIST_INIT(&node->mn_children); LIST_INIT(&node->mn_vnodes); LIST_INSERT_HEAD(&parent->mn_children, node, mn_sibling); mqnode_addref(parent); return (0); } static struct mqfs_node * mqfs_create_node(const char *name, int namelen, struct ucred *cred, int mode, int nodetype) { struct mqfs_node *node; node = mqnode_alloc(); strncpy(node->mn_name, name, namelen); node->mn_type = nodetype; node->mn_refcount = 1; getnanotime(&node->mn_birth); node->mn_ctime = node->mn_atime = node->mn_mtime = node->mn_birth; node->mn_uid = cred->cr_uid; node->mn_gid = cred->cr_gid; node->mn_mode = mode; return (node); } /* * Create a file */ static struct mqfs_node * mqfs_create_file(struct mqfs_node *parent, const char *name, int namelen, struct ucred *cred, int mode) { struct mqfs_node *node; node = mqfs_create_node(name, namelen, cred, mode, mqfstype_file); if (mqfs_add_node(parent, node) != 0) { mqnode_free(node); return (NULL); } return (node); } /* * Add . and .. to a directory */ static int mqfs_fixup_dir(struct mqfs_node *parent) { struct mqfs_node *dir; dir = mqnode_alloc(); dir->mn_name[0] = '.'; dir->mn_type = mqfstype_this; dir->mn_refcount = 1; if (mqfs_add_node(parent, dir) != 0) { mqnode_free(dir); return (-1); } dir = mqnode_alloc(); dir->mn_name[0] = dir->mn_name[1] = '.'; dir->mn_type = mqfstype_parent; dir->mn_refcount = 1; if (mqfs_add_node(parent, dir) != 0) { mqnode_free(dir); return (-1); } return (0); } #ifdef notyet /* * Create a directory */ static struct mqfs_node * mqfs_create_dir(struct mqfs_node *parent, const char *name, int namelen, struct ucred *cred, int mode) { struct mqfs_node *node; node = mqfs_create_node(name, namelen, cred, mode, mqfstype_dir); if (mqfs_add_node(parent, node) != 0) { mqnode_free(node); return (NULL); } if (mqfs_fixup_dir(node) != 0) { mqfs_destroy(node); return (NULL); } return (node); } /* * Create a symlink */ static struct mqfs_node * mqfs_create_link(struct mqfs_node *parent, const char *name, int namelen, struct ucred *cred, int mode) { struct mqfs_node *node; node = mqfs_create_node(name, namelen, cred, mode, mqfstype_symlink); if (mqfs_add_node(parent, node) != 0) { mqnode_free(node); return (NULL); } return (node); } #endif /* * Destroy a node or a tree of nodes */ static int mqfs_destroy(struct mqfs_node *node) { struct mqfs_node *parent; KASSERT(node != NULL, ("%s(): node is NULL", __func__)); KASSERT(node->mn_info != NULL, ("%s(): node has no mn_info", __func__)); /* destroy children */ if (node->mn_type == mqfstype_dir || node->mn_type == mqfstype_root) while (! LIST_EMPTY(&node->mn_children)) mqfs_destroy(LIST_FIRST(&node->mn_children)); /* unlink from parent */ if ((parent = node->mn_parent) != NULL) { KASSERT(parent->mn_info == node->mn_info, ("%s(): parent has different mn_info", __func__)); LIST_REMOVE(node, mn_sibling); } if (node->mn_fileno != 0) mqfs_fileno_free(node->mn_info, node); if (node->mn_data != NULL) mqueue_free(node->mn_data); mqnode_free(node); return (0); } /* * Mount a mqfs instance */ static int mqfs_mount(struct mount *mp, struct thread *td) { struct statfs *sbp; if (mp->mnt_flag & MNT_UPDATE) return (EOPNOTSUPP); mp->mnt_data = &mqfs_data; MNT_ILOCK(mp); mp->mnt_flag |= MNT_LOCAL; mp->mnt_kern_flag |= MNTK_MPSAFE; MNT_IUNLOCK(mp); vfs_getnewfsid(mp); sbp = &mp->mnt_stat; vfs_mountedfrom(mp, "mqueue"); sbp->f_bsize = PAGE_SIZE; sbp->f_iosize = PAGE_SIZE; sbp->f_blocks = 1; sbp->f_bfree = 0; sbp->f_bavail = 0; sbp->f_files = 1; sbp->f_ffree = 0; return (0); } /* * Unmount a mqfs instance */ static int mqfs_unmount(struct mount *mp, int mntflags, struct thread *td) { int error; error = vflush(mp, 0, (mntflags & MNT_FORCE) ? FORCECLOSE : 0, td); return (error); } /* * Return a root vnode */ static int mqfs_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td) { struct mqfs_info *mqfs; int ret; mqfs = VFSTOMQFS(mp); sx_xlock(&mqfs->mi_lock); ret = mqfs_allocv(mp, vpp, mqfs->mi_root); sx_xunlock(&mqfs->mi_lock); return (ret); } /* * Return filesystem stats */ static int mqfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td) { /* XXX update statistics */ return (0); } /* * Initialize a mqfs instance */ static int mqfs_init(struct vfsconf *vfc) { struct mqfs_node *root; struct mqfs_info *mi; mqnode_zone = uma_zcreate("mqnode", sizeof(struct mqfs_node), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); mqueue_zone = uma_zcreate("mqueue", sizeof(struct mqueue), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); mvdata_zone = uma_zcreate("mvdata", sizeof(struct mqfs_vdata), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); mqnoti_zone = uma_zcreate("mqnotifier", sizeof(struct mqueue_notifier), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); mi = &mqfs_data; sx_init(&mi->mi_lock, "mqfs lock"); /* set up the root diretory */ root = mqfs_create_node("/", 1, curthread->td_ucred, 01777, mqfstype_root); root->mn_info = mi; LIST_INIT(&root->mn_children); LIST_INIT(&root->mn_vnodes); mi->mi_root = root; mqfs_fileno_init(mi); mqfs_fileno_alloc(mi, root); mqfs_fixup_dir(root); exit_tag = EVENTHANDLER_REGISTER(process_exit, mq_proc_exit, NULL, EVENTHANDLER_PRI_ANY); mq_fdclose = mqueue_fdclose; p31b_setcfg(CTL_P1003_1B_MESSAGE_PASSING, _POSIX_MESSAGE_PASSING); return (0); } /* * Destroy a mqfs instance */ static int mqfs_uninit(struct vfsconf *vfc) { struct mqfs_info *mi; if (!unloadable) return (EOPNOTSUPP); EVENTHANDLER_DEREGISTER(process_exit, exit_tag); mi = &mqfs_data; mqfs_destroy(mi->mi_root); mi->mi_root = NULL; mqfs_fileno_uninit(mi); sx_destroy(&mi->mi_lock); uma_zdestroy(mqnode_zone); uma_zdestroy(mqueue_zone); uma_zdestroy(mvdata_zone); uma_zdestroy(mqnoti_zone); return (0); } /* * task routine */ static void do_recycle(void *context, int pending __unused) { struct vnode *vp = (struct vnode *)context; vrecycle(vp, curthread); vdrop(vp); } /* * Allocate a vnode */ static int mqfs_allocv(struct mount *mp, struct vnode **vpp, struct mqfs_node *pn) { struct mqfs_vdata *vd; int error; LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) { if (vd->mv_vnode->v_mount == mp) break; } if (vd != NULL) { if (vget(vd->mv_vnode, 0, curthread) == 0) { *vpp = vd->mv_vnode; vn_lock(*vpp, LK_RETRY | LK_EXCLUSIVE, curthread); return (0); } /* XXX if this can happen, we're in trouble */ } error = getnewvnode("mqueue", mp, &mqfs_vnodeops, vpp); if (error) return (error); vd = uma_zalloc(mvdata_zone, M_WAITOK); (*vpp)->v_data = vd; vd->mv_vnode = *vpp; vd->mv_node = pn; TASK_INIT(&vd->mv_task, 0, do_recycle, *vpp); LIST_INSERT_HEAD(&pn->mn_vnodes, vd, mv_link); mqnode_addref(pn); switch (pn->mn_type) { case mqfstype_root: (*vpp)->v_vflag = VV_ROOT; /* fall through */ case mqfstype_dir: case mqfstype_this: case mqfstype_parent: (*vpp)->v_type = VDIR; break; case mqfstype_file: (*vpp)->v_type = VREG; break; case mqfstype_symlink: (*vpp)->v_type = VLNK; break; case mqfstype_none: KASSERT(0, ("mqfs_allocf called for null node\n")); default: panic("%s has unexpected type: %d", pn->mn_name, pn->mn_type); } vn_lock(*vpp, LK_RETRY | LK_EXCLUSIVE, curthread); return (0); } /* * Search a directory entry */ static struct mqfs_node * mqfs_search(struct mqfs_node *pd, const char *name, int len) { struct mqfs_node *pn; LIST_FOREACH(pn, &pd->mn_children, mn_sibling) { if (strncmp(pn->mn_name, name, len) == 0) return (pn); } return (NULL); } /* * Look up a file or directory */ static int mqfs_lookupx(struct vop_cachedlookup_args *ap) { struct componentname *cnp; struct vnode *dvp, **vpp; struct mqfs_node *pd; struct mqfs_node *pn; int nameiop, flags, error, namelen; char *pname; struct thread *td; cnp = ap->a_cnp; vpp = ap->a_vpp; dvp = ap->a_dvp; pname = cnp->cn_nameptr; namelen = cnp->cn_namelen; td = cnp->cn_thread; flags = cnp->cn_flags; nameiop = cnp->cn_nameiop; pd = VTON(dvp); pn = NULL; *vpp = NULLVP; if (dvp->v_type != VDIR) return (ENOTDIR); error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_thread); if (error) return (error); /* shortcut: check if the name is too long */ if (cnp->cn_namelen >= MQFS_NAMELEN) return (ENOENT); /* self */ if (namelen == 1 && pname[0] == '.') { if ((flags & ISLASTCN) && nameiop != LOOKUP) return (EINVAL); pn = pd; *vpp = dvp; VREF(dvp); return (0); } /* parent */ if (cnp->cn_flags & ISDOTDOT) { if (dvp->v_vflag & VV_ROOT) return (EIO); if ((flags & ISLASTCN) && nameiop != LOOKUP) return (EINVAL); VOP_UNLOCK(dvp, 0, cnp->cn_thread); KASSERT(pd->mn_parent, ("non-root directory has no parent")); pn = pd->mn_parent; error = mqfs_allocv(dvp->v_mount, vpp, pn); vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); return (error); } /* named node */ pn = mqfs_search(pd, pname, namelen); /* found */ if (pn != NULL) { /* DELETE */ if (nameiop == DELETE && (flags & ISLASTCN)) { error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td); if (error) return (error); if (*vpp == dvp) { VREF(dvp); *vpp = dvp; return (0); } } /* allocate vnode */ error = mqfs_allocv(dvp->v_mount, vpp, pn); if (error == 0 && cnp->cn_flags & MAKEENTRY) cache_enter(dvp, *vpp, cnp); return (error); } /* not found */ /* will create a new entry in the directory ? */ if ((nameiop == CREATE || nameiop == RENAME) && (flags & LOCKPARENT) && (flags & ISLASTCN)) { error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td); if (error) return (error); cnp->cn_flags |= SAVENAME; return (EJUSTRETURN); } return (ENOENT); } #if 0 struct vop_lookup_args { struct vop_generic_args a_gen; struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; }; #endif /* * vnode lookup operation */ static int mqfs_lookup(struct vop_cachedlookup_args *ap) { struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount); int rc; sx_xlock(&mqfs->mi_lock); rc = mqfs_lookupx(ap); sx_xunlock(&mqfs->mi_lock); return (rc); } #if 0 struct vop_create_args { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; struct vattr *a_vap; }; #endif /* * vnode creation operation */ static int mqfs_create(struct vop_create_args *ap) { struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount); struct componentname *cnp = ap->a_cnp; struct mqfs_node *pd; struct mqfs_node *pn; struct mqueue *mq; int error; pd = VTON(ap->a_dvp); if (pd->mn_type != mqfstype_root && pd->mn_type != mqfstype_dir) return (ENOTDIR); mq = mqueue_alloc(NULL); if (mq == NULL) return (EAGAIN); sx_xlock(&mqfs->mi_lock); #if 0 /* named node */ pn = mqfs_search(pd, cnp->cn_nameptr, cnp->cn_namelen); if (pn != NULL) { mqueue_free(mq); sx_xunlock(&mqfs->mi_lock); return (EEXIST); } #else if ((cnp->cn_flags & HASBUF) == 0) panic("%s: no name", __func__); #endif pn = mqfs_create_file(pd, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_cred, ap->a_vap->va_mode); if (pn == NULL) error = ENOSPC; else { error = mqfs_allocv(ap->a_dvp->v_mount, ap->a_vpp, pn); if (error) mqfs_destroy(pn); else pn->mn_data = mq; } sx_xunlock(&mqfs->mi_lock); if (error) mqueue_free(mq); return (error); } /* * Remove an entry */ static int do_unlink(struct mqfs_node *pn, struct ucred *ucred) { struct mqfs_node *parent; struct mqfs_vdata *vd; int error = 0; sx_assert(&pn->mn_info->mi_lock, SX_LOCKED); /* * XXXRW: Other instances of the message queue primitive are * allowed in jail? */ if (ucred->cr_uid != pn->mn_uid && (error = priv_check_cred(ucred, PRIV_MQ_ADMIN, 0)) != 0) error = EACCES; else if (!pn->mn_deleted) { parent = pn->mn_parent; pn->mn_parent = NULL; pn->mn_deleted = 1; LIST_REMOVE(pn, mn_sibling); LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) { cache_purge(vd->mv_vnode); vhold(vd->mv_vnode); taskqueue_enqueue(taskqueue_thread, &vd->mv_task); } mqnode_release(pn); mqnode_release(parent); } else error = ENOENT; return (error); } #if 0 struct vop_remove_args { struct vnode *a_dvp; struct vnode *a_vp; struct componentname *a_cnp; }; #endif /* * vnode removal operation */ static int mqfs_remove(struct vop_remove_args *ap) { struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount); struct mqfs_node *pn; int error; if (ap->a_vp->v_type == VDIR) return (EPERM); pn = VTON(ap->a_vp); sx_xlock(&mqfs->mi_lock); error = do_unlink(pn, ap->a_cnp->cn_cred); sx_xunlock(&mqfs->mi_lock); return (error); } #if 0 struct vop_inactive_args { struct vnode *a_vp; struct thread *a_td; }; #endif static int mqfs_inactive(struct vop_inactive_args *ap) { struct mqfs_node *pn = VTON(ap->a_vp); if (pn->mn_deleted) vrecycle(ap->a_vp, ap->a_td); return (0); } #if 0 struct vop_reclaim_args { struct vop_generic_args a_gen; struct vnode *a_vp; struct thread *a_td; }; #endif static int mqfs_reclaim(struct vop_reclaim_args *ap) { struct mqfs_info *mqfs = VFSTOMQFS(ap->a_vp->v_mount); struct vnode *vp = ap->a_vp; struct mqfs_node *pn; struct mqfs_vdata *vd; vd = vp->v_data; pn = vd->mv_node; sx_xlock(&mqfs->mi_lock); vp->v_data = NULL; LIST_REMOVE(vd, mv_link); uma_zfree(mvdata_zone, vd); mqnode_release(pn); sx_xunlock(&mqfs->mi_lock); return (0); } #if 0 struct vop_open_args { struct vop_generic_args a_gen; struct vnode *a_vp; int a_mode; struct ucred *a_cred; struct thread *a_td; int a_fdidx; }; #endif static int mqfs_open(struct vop_open_args *ap) { return (0); } #if 0 struct vop_close_args { struct vop_generic_args a_gen; struct vnode *a_vp; int a_fflag; struct ucred *a_cred; struct thread *a_td; }; #endif static int mqfs_close(struct vop_close_args *ap) { return (0); } #if 0 struct vop_access_args { struct vop_generic_args a_gen; struct vnode *a_vp; int a_mode; struct ucred *a_cred; struct thread *a_td; }; #endif /* * Verify permissions */ static int mqfs_access(struct vop_access_args *ap) { struct vnode *vp = ap->a_vp; struct vattr vattr; int error; error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_td); if (error) return (error); error = vaccess(vp->v_type, vattr.va_mode, vattr.va_uid, vattr.va_gid, ap->a_mode, ap->a_cred, NULL); return (error); } #if 0 struct vop_getattr_args { struct vop_generic_args a_gen; struct vnode *a_vp; struct vattr *a_vap; struct ucred *a_cred; struct thread *a_td; }; #endif /* * Get file attributes */ static int mqfs_getattr(struct vop_getattr_args *ap) { struct vnode *vp = ap->a_vp; struct mqfs_node *pn = VTON(vp); struct vattr *vap = ap->a_vap; int error = 0; VATTR_NULL(vap); vap->va_type = vp->v_type; vap->va_mode = pn->mn_mode; vap->va_nlink = 1; vap->va_uid = pn->mn_uid; vap->va_gid = pn->mn_gid; vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; vap->va_fileid = pn->mn_fileno; vap->va_size = 0; vap->va_blocksize = PAGE_SIZE; vap->va_bytes = vap->va_size = 0; vap->va_atime = pn->mn_atime; vap->va_mtime = pn->mn_mtime; vap->va_ctime = pn->mn_ctime; vap->va_birthtime = pn->mn_birth; vap->va_gen = 0; vap->va_flags = 0; vap->va_rdev = 0; vap->va_bytes = 0; vap->va_filerev = 0; vap->va_vaflags = 0; return (error); } #if 0 struct vop_setattr_args { struct vop_generic_args a_gen; struct vnode *a_vp; struct vattr *a_vap; struct ucred *a_cred; struct thread *a_td; }; #endif /* * Set attributes */ static int mqfs_setattr(struct vop_setattr_args *ap) { struct mqfs_node *pn; struct vattr *vap; struct vnode *vp; int c, error; uid_t uid; gid_t gid; vap = ap->a_vap; vp = ap->a_vp; if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || (vap->va_blocksize != VNOVAL) || (vap->va_flags != VNOVAL && vap->va_flags != 0) || (vap->va_rdev != VNOVAL) || ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { return (EINVAL); } pn = VTON(vp); error = c = 0; if (vap->va_uid == (uid_t)VNOVAL) uid = pn->mn_uid; else uid = vap->va_uid; if (vap->va_gid == (gid_t)VNOVAL) gid = pn->mn_gid; else gid = vap->va_gid; if (uid != pn->mn_uid || gid != pn->mn_gid) { /* * To modify the ownership of a file, must possess VADMIN * for that file. */ if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td))) return (error); /* * XXXRW: Why is there a privilege check here: shouldn't the * check in VOP_ACCESS() be enough? Also, are the group bits * below definitely right? */ if (((ap->a_cred->cr_uid != pn->mn_uid) || uid != pn->mn_uid || (gid != pn->mn_gid && !groupmember(gid, ap->a_cred))) && (error = priv_check_cred(ap->a_td->td_ucred, PRIV_MQ_ADMIN, SUSER_ALLOWJAIL)) != 0) return (error); pn->mn_uid = uid; pn->mn_gid = gid; c = 1; } if (vap->va_mode != (mode_t)VNOVAL) { if ((ap->a_cred->cr_uid != pn->mn_uid) && (error = priv_check_cred(ap->a_td->td_ucred, PRIV_MQ_ADMIN, SUSER_ALLOWJAIL))) return (error); pn->mn_mode = vap->va_mode; c = 1; } if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { /* See the comment in ufs_vnops::ufs_setattr(). */ if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td)) && ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || (error = VOP_ACCESS(vp, VWRITE, ap->a_cred, ap->a_td)))) return (error); if (vap->va_atime.tv_sec != VNOVAL) { pn->mn_atime = vap->va_atime; } if (vap->va_mtime.tv_sec != VNOVAL) { pn->mn_mtime = vap->va_mtime; } c = 1; } if (c) { vfs_timestamp(&pn->mn_ctime); } return (0); } #if 0 struct vop_read_args { struct vop_generic_args a_gen; struct vnode *a_vp; struct uio *a_uio; int a_ioflag; struct ucred *a_cred; }; #endif /* * Read from a file */ static int mqfs_read(struct vop_read_args *ap) { char buf[80]; struct vnode *vp = ap->a_vp; struct uio *uio = ap->a_uio; struct mqfs_node *pn; struct mqueue *mq; int len, error; if (vp->v_type != VREG) return (EINVAL); pn = VTON(vp); mq = VTOMQ(vp); snprintf(buf, sizeof(buf), "QSIZE:%-10ld MAXMSG:%-10ld CURMSG:%-10ld MSGSIZE:%-10ld\n", mq->mq_totalbytes, mq->mq_maxmsg, mq->mq_curmsgs, mq->mq_msgsize); buf[sizeof(buf)-1] = '\0'; len = strlen(buf); error = uiomove_frombuf(buf, len, uio); return (error); } #if 0 struct vop_readdir_args { struct vop_generic_args a_gen; struct vnode *a_vp; struct uio *a_uio; struct ucred *a_cred; int *a_eofflag; int *a_ncookies; u_long **a_cookies; }; #endif /* * Return directory entries. */ static int mqfs_readdir(struct vop_readdir_args *ap) { struct vnode *vp; struct mqfs_info *mi; struct mqfs_node *pd; struct mqfs_node *pn; struct dirent entry; struct uio *uio; int *tmp_ncookies = NULL; off_t offset; int error, i; vp = ap->a_vp; mi = VFSTOMQFS(vp->v_mount); pd = VTON(vp); uio = ap->a_uio; if (vp->v_type != VDIR) return (ENOTDIR); if (uio->uio_offset < 0) return (EINVAL); if (ap->a_ncookies != NULL) { tmp_ncookies = ap->a_ncookies; *ap->a_ncookies = 0; ap->a_ncookies = NULL; } error = 0; offset = 0; sx_xlock(&mi->mi_lock); LIST_FOREACH(pn, &pd->mn_children, mn_sibling) { entry.d_reclen = sizeof(entry); if (!pn->mn_fileno) mqfs_fileno_alloc(mi, pn); entry.d_fileno = pn->mn_fileno; for (i = 0; i < MQFS_NAMELEN - 1 && pn->mn_name[i] != '\0'; ++i) entry.d_name[i] = pn->mn_name[i]; entry.d_name[i] = 0; entry.d_namlen = i; switch (pn->mn_type) { case mqfstype_root: case mqfstype_dir: case mqfstype_this: case mqfstype_parent: entry.d_type = DT_DIR; break; case mqfstype_file: entry.d_type = DT_REG; break; case mqfstype_symlink: entry.d_type = DT_LNK; break; default: panic("%s has unexpected node type: %d", pn->mn_name, pn->mn_type); } if (entry.d_reclen > uio->uio_resid) break; if (offset >= uio->uio_offset) { error = vfs_read_dirent(ap, &entry, offset); if (error) break; } offset += entry.d_reclen; } sx_xunlock(&mi->mi_lock); uio->uio_offset = offset; if (tmp_ncookies != NULL) ap->a_ncookies = tmp_ncookies; return (error); } #ifdef notyet #if 0 struct vop_mkdir_args { struct vnode *a_dvp; struvt vnode **a_vpp; struvt componentname *a_cnp; struct vattr *a_vap; }; #endif /* * Create a directory. */ static int mqfs_mkdir(struct vop_mkdir_args *ap) { struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount); struct componentname *cnp = ap->a_cnp; struct mqfs_node *pd = VTON(ap->a_dvp); struct mqfs_node *pn; int error; if (pd->mn_type != mqfstype_root && pd->mn_type != mqfstype_dir) return (ENOTDIR); sx_xlock(&mqfs->mi_lock); #if 0 /* named node */ pn = mqfs_search(pd, cnp->cn_nameptr, cnp->cn_namelen); if (pn != NULL) { sx_xunlock(&mqfs->mi_lock); return (EEXIST); } #else if ((cnp->cn_flags & HASBUF) == 0) panic("%s: no name", __func__); #endif pn = mqfs_create_dir(pd, cnp->cn_nameptr, cnp->cn_namelen, ap->a_vap->cn_cred, ap->a_vap->va_mode); if (pn == NULL) error = ENOSPC; else error = mqfs_allocv(ap->a_dvp->v_mount, ap->a_vpp, pn); sx_xunlock(&mqfs->mi_lock); return (error); } #if 0 struct vop_rmdir_args { struct vnode *a_dvp; struct vnode *a_vp; struct componentname *a_cnp; }; #endif /* * Remove a directory. */ static int mqfs_rmdir(struct vop_rmdir_args *ap) { struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount); struct mqfs_node *pn = VTON(ap->a_vp); struct mqfs_node *pt; if (pn->mn_type != mqfstype_dir) return (ENOTDIR); sx_xlock(&mqfs->mi_lock); if (pn->mn_deleted) { sx_xunlock(&mqfs->mi_lock); return (ENOENT); } pt = LIST_FIRST(&pn->mn_children); pt = LIST_NEXT(pt, mn_sibling); pt = LIST_NEXT(pt, mn_sibling); if (pt != NULL) { sx_xunlock(&mqfs->mi_lock); return (ENOTEMPTY); } pt = pn->mn_parent; pn->mn_parent = NULL; pn->mn_deleted = 1; LIST_REMOVE(pn, mn_sibling); mqnode_release(pn); mqnode_release(pt); sx_xunlock(&mqfs->mi_lock); cache_purge(ap->a_vp); return (0); } #endif /* notyet */ /* * Allocate a message queue */ static struct mqueue * mqueue_alloc(const struct mq_attr *attr) { struct mqueue *mq; if (curmq >= maxmq) return (NULL); mq = uma_zalloc(mqueue_zone, M_WAITOK | M_ZERO); TAILQ_INIT(&mq->mq_msgq); if (attr != NULL) { mq->mq_maxmsg = attr->mq_maxmsg; mq->mq_msgsize = attr->mq_msgsize; } else { mq->mq_maxmsg = default_maxmsg; mq->mq_msgsize = default_msgsize; } mtx_init(&mq->mq_mutex, "mqueue", NULL, MTX_DEF); knlist_init(&mq->mq_rsel.si_note, &mq->mq_mutex, NULL, NULL, NULL); knlist_init(&mq->mq_wsel.si_note, &mq->mq_mutex, NULL, NULL, NULL); atomic_add_int(&curmq, 1); return (mq); } /* * Destroy a message queue */ static void mqueue_free(struct mqueue *mq) { struct mqueue_msg *msg; while ((msg = TAILQ_FIRST(&mq->mq_msgq)) != NULL) { TAILQ_REMOVE(&mq->mq_msgq, msg, msg_link); FREE(msg, M_MQUEUEDATA); } mtx_destroy(&mq->mq_mutex); knlist_destroy(&mq->mq_rsel.si_note); knlist_destroy(&mq->mq_wsel.si_note); uma_zfree(mqueue_zone, mq); atomic_add_int(&curmq, -1); } /* * Load a message from user space */ static struct mqueue_msg * mqueue_loadmsg(const char *msg_ptr, size_t msg_size, int msg_prio) { struct mqueue_msg *msg; size_t len; int error; len = sizeof(struct mqueue_msg) + msg_size; MALLOC(msg, struct mqueue_msg *, len, M_MQUEUEDATA, M_WAITOK); error = copyin(msg_ptr, ((char *)msg) + sizeof(struct mqueue_msg), msg_size); if (error) { FREE(msg, M_MQUEUEDATA); msg = NULL; } else { msg->msg_size = msg_size; msg->msg_prio = msg_prio; } return (msg); } /* * Save a message to user space */ static int mqueue_savemsg(struct mqueue_msg *msg, char *msg_ptr, int *msg_prio) { int error; error = copyout(((char *)msg) + sizeof(*msg), msg_ptr, msg->msg_size); if (error == 0 && msg_prio != NULL) error = copyout(&msg->msg_prio, msg_prio, sizeof(int)); return (error); } /* * Free a message's memory */ static __inline void mqueue_freemsg(struct mqueue_msg *msg) { FREE(msg, M_MQUEUEDATA); } /* * Send a message. if waitok is false, thread will not be * blocked if there is no data in queue, otherwise, absolute * time will be checked. */ int mqueue_send(struct mqueue *mq, const char *msg_ptr, size_t msg_len, unsigned msg_prio, int waitok, const struct timespec *abs_timeout) { struct mqueue_msg *msg; struct timespec ets, ts, ts2; struct timeval tv; int error; if (msg_prio >= MQ_PRIO_MAX) return (EINVAL); if (msg_len > mq->mq_msgsize) return (EMSGSIZE); msg = mqueue_loadmsg(msg_ptr, msg_len, msg_prio); if (msg == NULL) return (EFAULT); /* O_NONBLOCK case */ if (!waitok) { error = _mqueue_send(mq, msg, -1); if (error) goto bad; return (0); } /* we allow a null timeout (wait forever) */ if (abs_timeout == NULL) { error = _mqueue_send(mq, msg, 0); if (error) goto bad; return (0); } /* send it before checking time */ error = _mqueue_send(mq, msg, -1); if (error == 0) return (0); if (error != EAGAIN) goto bad; error = copyin(abs_timeout, &ets, sizeof(ets)); if (error != 0) goto bad; if (ets.tv_nsec >= 1000000000 || ets.tv_nsec < 0) { error = EINVAL; goto bad; } for (;;) { ts2 = ets; getnanotime(&ts); timespecsub(&ts2, &ts); if (ts2.tv_sec < 0 || (ts2.tv_sec == 0 && ts2.tv_nsec <= 0)) { error = ETIMEDOUT; break; } TIMESPEC_TO_TIMEVAL(&tv, &ts2); error = _mqueue_send(mq, msg, tvtohz(&tv)); if (error != ETIMEDOUT) break; } if (error == 0) return (0); bad: mqueue_freemsg(msg); return (error); } /* * Common routine to send a message */ static int _mqueue_send(struct mqueue *mq, struct mqueue_msg *msg, int timo) { struct mqueue_msg *msg2; int error = 0; mtx_lock(&mq->mq_mutex); while (mq->mq_curmsgs >= mq->mq_maxmsg && error == 0) { if (timo < 0) { mtx_unlock(&mq->mq_mutex); return (EAGAIN); } mq->mq_senders++; error = msleep(&mq->mq_senders, &mq->mq_mutex, PCATCH, "mqsend", timo); mq->mq_senders--; if (error == EAGAIN) error = ETIMEDOUT; } if (mq->mq_curmsgs >= mq->mq_maxmsg) { mtx_unlock(&mq->mq_mutex); return (error); } error = 0; if (TAILQ_EMPTY(&mq->mq_msgq)) { TAILQ_INSERT_HEAD(&mq->mq_msgq, msg, msg_link); } else { if (msg->msg_prio <= TAILQ_LAST(&mq->mq_msgq, msgq)->msg_prio) { TAILQ_INSERT_TAIL(&mq->mq_msgq, msg, msg_link); } else { TAILQ_FOREACH(msg2, &mq->mq_msgq, msg_link) { if (msg2->msg_prio < msg->msg_prio) break; } TAILQ_INSERT_BEFORE(msg2, msg, msg_link); } } mq->mq_curmsgs++; mq->mq_totalbytes += msg->msg_size; if (mq->mq_receivers) wakeup_one(&mq->mq_receivers); else if (mq->mq_notifier != NULL) mqueue_send_notification(mq); if (mq->mq_flags & MQ_RSEL) { mq->mq_flags &= ~MQ_RSEL; selwakeup(&mq->mq_rsel); } KNOTE_LOCKED(&mq->mq_rsel.si_note, 0); mtx_unlock(&mq->mq_mutex); return (0); } /* * Send realtime a signal to process which registered itself * successfully by mq_notify. */ static void mqueue_send_notification(struct mqueue *mq) { struct mqueue_notifier *nt; struct proc *p; mtx_assert(&mq->mq_mutex, MA_OWNED); nt = mq->mq_notifier; if (nt->nt_sigev.sigev_notify != SIGEV_NONE) { p = nt->nt_proc; PROC_LOCK(p); if (!KSI_ONQ(&nt->nt_ksi)) psignal_event(p, &nt->nt_sigev, &nt->nt_ksi); PROC_UNLOCK(p); } mq->mq_notifier = NULL; } /* * Get a message. if waitok is false, thread will not be * blocked if there is no data in queue, otherwise, absolute * time will be checked. */ int mqueue_receive(struct mqueue *mq, char *msg_ptr, size_t msg_len, unsigned *msg_prio, int waitok, const struct timespec *abs_timeout) { struct mqueue_msg *msg; struct timespec ets, ts, ts2; struct timeval tv; int error; if (msg_len < mq->mq_msgsize) return (EMSGSIZE); /* O_NONBLOCK case */ if (!waitok) { error = _mqueue_recv(mq, &msg, -1); if (error) return (error); goto received; } /* we allow a null timeout (wait forever). */ if (abs_timeout == NULL) { error = _mqueue_recv(mq, &msg, 0); if (error) return (error); goto received; } /* try to get a message before checking time */ error = _mqueue_recv(mq, &msg, -1); if (error == 0) goto received; if (error != EAGAIN) return (error); error = copyin(abs_timeout, &ets, sizeof(ets)); if (error != 0) return (error); if (ets.tv_nsec >= 1000000000 || ets.tv_nsec < 0) { error = EINVAL; return (error); } for (;;) { ts2 = ets; getnanotime(&ts); timespecsub(&ts2, &ts); if (ts2.tv_sec < 0 || (ts2.tv_sec == 0 && ts2.tv_nsec <= 0)) { error = ETIMEDOUT; return (error); } TIMESPEC_TO_TIMEVAL(&tv, &ts2); error = _mqueue_recv(mq, &msg, tvtohz(&tv)); if (error == 0) break; if (error != ETIMEDOUT) return (error); } received: error = mqueue_savemsg(msg, msg_ptr, msg_prio); if (error == 0) { curthread->td_retval[0] = msg->msg_size; curthread->td_retval[1] = 0; } mqueue_freemsg(msg); return (error); } /* * Common routine to receive a message */ static int _mqueue_recv(struct mqueue *mq, struct mqueue_msg **msg, int timo) { int error = 0; mtx_lock(&mq->mq_mutex); while ((*msg = TAILQ_FIRST(&mq->mq_msgq)) == NULL && error == 0) { if (timo < 0) { mtx_unlock(&mq->mq_mutex); return (EAGAIN); } mq->mq_receivers++; error = msleep(&mq->mq_receivers, &mq->mq_mutex, PCATCH, "mqrecv", timo); mq->mq_receivers--; if (error == EAGAIN) error = ETIMEDOUT; } if (*msg != NULL) { error = 0; TAILQ_REMOVE(&mq->mq_msgq, *msg, msg_link); mq->mq_curmsgs--; mq->mq_totalbytes -= (*msg)->msg_size; if (mq->mq_senders) wakeup_one(&mq->mq_senders); if (mq->mq_flags & MQ_WSEL) { mq->mq_flags &= ~MQ_WSEL; selwakeup(&mq->mq_wsel); } KNOTE_LOCKED(&mq->mq_wsel.si_note, 0); } if (mq->mq_notifier != NULL && mq->mq_receivers == 0 && !TAILQ_EMPTY(&mq->mq_msgq)) { mqueue_send_notification(mq); } mtx_unlock(&mq->mq_mutex); return (error); } static __inline struct mqueue_notifier * notifier_alloc(void) { return (uma_zalloc(mqnoti_zone, M_WAITOK | M_ZERO)); } static __inline void notifier_free(struct mqueue_notifier *p) { uma_zfree(mqnoti_zone, p); } static struct mqueue_notifier * notifier_search(struct proc *p, int fd) { struct mqueue_notifier *nt; LIST_FOREACH(nt, &p->p_mqnotifier, nt_link) { if (nt->nt_ksi.ksi_mqd == fd) break; } return (nt); } static __inline void notifier_insert(struct proc *p, struct mqueue_notifier *nt) { LIST_INSERT_HEAD(&p->p_mqnotifier, nt, nt_link); } static __inline void notifier_delete(struct proc *p, struct mqueue_notifier *nt) { LIST_REMOVE(nt, nt_link); notifier_free(nt); } static void notifier_remove(struct proc *p, struct mqueue *mq, int fd) { struct mqueue_notifier *nt; mtx_assert(&mq->mq_mutex, MA_OWNED); PROC_LOCK(p); nt = notifier_search(p, fd); if (nt != NULL) { if (mq->mq_notifier == nt) mq->mq_notifier = NULL; sigqueue_take(&nt->nt_ksi); notifier_delete(p, nt); } PROC_UNLOCK(p); } /* * Syscall to open a message queue */ int kmq_open(struct thread *td, struct kmq_open_args *uap) { char path[MQFS_NAMELEN + 1]; struct mq_attr attr, *pattr; struct mqfs_node *pn; struct filedesc *fdp; struct file *fp; struct mqueue *mq; int fd, error, len, flags, cmode; if ((uap->flags & O_ACCMODE) == O_ACCMODE) return (EINVAL); fdp = td->td_proc->p_fd; flags = FFLAGS(uap->flags); cmode = (((uap->mode & ~fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT); mq = NULL; if ((flags & O_CREAT) && (uap->attr != NULL)) { error = copyin(uap->attr, &attr, sizeof(attr)); if (error) return (error); if (attr.mq_maxmsg <= 0 || attr.mq_maxmsg > maxmsg) return (EINVAL); if (attr.mq_msgsize <= 0 || attr.mq_msgsize > maxmsgsize) return (EINVAL); pattr = &attr; } else pattr = NULL; error = copyinstr(uap->path, path, MQFS_NAMELEN + 1, NULL); if (error) return (error); /* * The first character of name must be a slash (/) character * and the remaining characters of name cannot include any slash * characters. */ len = strlen(path); if (len < 2 || path[0] != '/' || index(path + 1, '/') != NULL) return (EINVAL); error = falloc(td, &fp, &fd); if (error) return (error); sx_xlock(&mqfs_data.mi_lock); pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1); if (pn == NULL) { if (!(flags & O_CREAT)) { error = ENOENT; } else { mq = mqueue_alloc(pattr); if (mq == NULL) { error = ENFILE; } else { pn = mqfs_create_file(mqfs_data.mi_root, path + 1, len - 1, td->td_ucred, cmode); if (pn == NULL) { error = ENOSPC; mqueue_free(mq); } } } if (error == 0) { pn->mn_data = mq; } } else { if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) { error = EEXIST; } else { int acc_mode = 0; if (flags & FREAD) acc_mode |= VREAD; if (flags & FWRITE) acc_mode |= VWRITE; error = vaccess(VREG, pn->mn_mode, pn->mn_uid, pn->mn_gid, acc_mode, td->td_ucred, NULL); } } if (error) { sx_xunlock(&mqfs_data.mi_lock); fdclose(fdp, fp, fd, td); fdrop(fp, td); return (error); } mqnode_addref(pn); sx_xunlock(&mqfs_data.mi_lock); FILE_LOCK(fp); fp->f_flag = (flags & (FREAD | FWRITE | O_NONBLOCK)); fp->f_type = DTYPE_MQUEUE; fp->f_ops = &mqueueops; fp->f_data = pn; FILE_UNLOCK(fp); FILEDESC_LOCK_FAST(fdp); if (fdp->fd_ofiles[fd] == fp) fdp->fd_ofileflags[fd] |= UF_EXCLOSE; FILEDESC_UNLOCK_FAST(fdp); td->td_retval[0] = fd; fdrop(fp, td); return (0); } /* * Syscall to unlink a message queue */ int kmq_unlink(struct thread *td, struct kmq_unlink_args *uap) { char path[MQFS_NAMELEN+1]; struct mqfs_node *pn; int error, len; error = copyinstr(uap->path, path, MQFS_NAMELEN + 1, NULL); if (error) return (error); len = strlen(path); if (len < 2 || path[0] != '/' || index(path + 1, '/') != NULL) return (EINVAL); sx_xlock(&mqfs_data.mi_lock); pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1); if (pn != NULL) error = do_unlink(pn, td->td_ucred); else error = ENOENT; sx_xunlock(&mqfs_data.mi_lock); return (error); } typedef int (*_fgetf)(struct thread *, int, struct file **); /* * Get message queue by giving file slot */ static int _getmq(struct thread *td, int fd, _fgetf func, struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) { struct mqfs_node *pn; int error; error = func(td, fd, fpp); if (error) return (error); if (&mqueueops != (*fpp)->f_ops) { fdrop(*fpp, td); return (EBADF); } pn = (*fpp)->f_data; if (ppn) *ppn = pn; if (pmq) *pmq = pn->mn_data; return (0); } static __inline int getmq(struct thread *td, int fd, struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) { return _getmq(td, fd, fget, fpp, ppn, pmq); } static __inline int getmq_read(struct thread *td, int fd, struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) { return _getmq(td, fd, fget_read, fpp, ppn, pmq); } static __inline int getmq_write(struct thread *td, int fd, struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) { return _getmq(td, fd, fget_write, fpp, ppn, pmq); } /* * Syscall */ int kmq_setattr(struct thread *td, struct kmq_setattr_args *uap) { struct mqueue *mq; struct file *fp; struct mq_attr attr, oattr; int error; if (uap->attr) { error = copyin(uap->attr, &attr, sizeof(attr)); if (error) return (error); if (attr.mq_flags & ~O_NONBLOCK) return (EINVAL); } error = getmq(td, uap->mqd, &fp, NULL, &mq); if (error) return (error); oattr.mq_maxmsg = mq->mq_maxmsg; oattr.mq_msgsize = mq->mq_msgsize; oattr.mq_curmsgs = mq->mq_curmsgs; FILE_LOCK(fp); oattr.mq_flags = (O_NONBLOCK & fp->f_flag); if (uap->attr) { fp->f_flag &= ~O_NONBLOCK; fp->f_flag |= (attr.mq_flags & O_NONBLOCK); } FILE_UNLOCK(fp); fdrop(fp, td); if (uap->oattr) error = copyout(&oattr, uap->oattr, sizeof(oattr)); return (error); } /* * Syscall */ int kmq_timedreceive(struct thread *td, struct kmq_timedreceive_args *uap) { struct mqueue *mq; struct file *fp; int error; int waitok; error = getmq_read(td, uap->mqd, &fp, NULL, &mq); if (error) return (error); waitok = !(fp->f_flag & O_NONBLOCK); error = mqueue_receive(mq, uap->msg_ptr, uap->msg_len, uap->msg_prio, waitok, uap->abs_timeout); fdrop(fp, td); return (error); } /* * Syscall */ int kmq_timedsend(struct thread *td, struct kmq_timedsend_args *uap) { struct mqueue *mq; struct file *fp; int error, waitok; error = getmq_write(td, uap->mqd, &fp, NULL, &mq); if (error) return (error); waitok = !(fp->f_flag & O_NONBLOCK); error = mqueue_send(mq, uap->msg_ptr, uap->msg_len, uap->msg_prio, waitok, uap->abs_timeout); fdrop(fp, td); return (error); } /* * Syscall */ int kmq_notify(struct thread *td, struct kmq_notify_args *uap) { struct sigevent ev; struct filedesc *fdp; struct proc *p; struct mqueue *mq; struct file *fp; struct mqueue_notifier *nt, *newnt = NULL; int error; p = td->td_proc; fdp = td->td_proc->p_fd; if (uap->sigev) { error = copyin(uap->sigev, &ev, sizeof(ev)); if (error) return (error); if (ev.sigev_notify != SIGEV_SIGNAL && ev.sigev_notify != SIGEV_THREAD_ID && ev.sigev_notify != SIGEV_NONE) return (EINVAL); if ((ev.sigev_notify == SIGEV_SIGNAL || ev.sigev_notify == SIGEV_THREAD_ID) && !_SIG_VALID(ev.sigev_signo)) return (EINVAL); } error = getmq(td, uap->mqd, &fp, NULL, &mq); if (error) return (error); again: FILEDESC_LOCK_FAST(fdp); if (fget_locked(fdp, uap->mqd) != fp) { FILEDESC_UNLOCK_FAST(fdp); error = EBADF; goto out; } mtx_lock(&mq->mq_mutex); FILEDESC_UNLOCK_FAST(fdp); if (uap->sigev != NULL) { if (mq->mq_notifier != NULL) { error = EBUSY; } else { PROC_LOCK(p); nt = notifier_search(p, uap->mqd); if (nt == NULL) { if (newnt == NULL) { PROC_UNLOCK(p); mtx_unlock(&mq->mq_mutex); newnt = notifier_alloc(); goto again; } } if (nt != NULL) { sigqueue_take(&nt->nt_ksi); if (newnt != NULL) { notifier_free(newnt); newnt = NULL; } } else { nt = newnt; newnt = NULL; ksiginfo_init(&nt->nt_ksi); nt->nt_ksi.ksi_flags |= KSI_INS | KSI_EXT; nt->nt_ksi.ksi_code = SI_MESGQ; nt->nt_proc = p; nt->nt_ksi.ksi_mqd = uap->mqd; notifier_insert(p, nt); } nt->nt_sigev = ev; mq->mq_notifier = nt; PROC_UNLOCK(p); /* * if there is no receivers and message queue * is not empty, we should send notification * as soon as possible. */ if (mq->mq_receivers == 0 && !TAILQ_EMPTY(&mq->mq_msgq)) mqueue_send_notification(mq); } } else { notifier_remove(p, mq, uap->mqd); } mtx_unlock(&mq->mq_mutex); out: fdrop(fp, td); if (newnt != NULL) notifier_free(newnt); return (error); } static void mqueue_fdclose(struct thread *td, int fd, struct file *fp) { struct filedesc *fdp; struct mqueue *mq; fdp = td->td_proc->p_fd; FILEDESC_LOCK_ASSERT(fdp, MA_OWNED); if (fp->f_ops == &mqueueops) { mq = FPTOMQ(fp); mtx_lock(&mq->mq_mutex); notifier_remove(td->td_proc, mq, fd); /* have to wakeup thread in same process */ if (mq->mq_flags & MQ_RSEL) { mq->mq_flags &= ~MQ_RSEL; selwakeup(&mq->mq_rsel); } if (mq->mq_flags & MQ_WSEL) { mq->mq_flags &= ~MQ_WSEL; selwakeup(&mq->mq_wsel); } mtx_unlock(&mq->mq_mutex); } } static void mq_proc_exit(void *arg __unused, struct proc *p) { struct filedesc *fdp; struct file *fp; struct mqueue *mq; int i; fdp = p->p_fd; FILEDESC_LOCK_FAST(fdp); for (i = 0; i < fdp->fd_nfiles; ++i) { fp = fget_locked(fdp, i); if (fp != NULL && fp->f_ops == &mqueueops) { mq = FPTOMQ(fp); mtx_lock(&mq->mq_mutex); notifier_remove(p, FPTOMQ(fp), i); mtx_unlock(&mq->mq_mutex); } } FILEDESC_UNLOCK_FAST(fdp); KASSERT(LIST_EMPTY(&p->p_mqnotifier), ("mq notifiers left")); } static int mqf_read(struct file *fp, struct uio *uio, struct ucred *active_cred, int flags, struct thread *td) { return (EOPNOTSUPP); } static int mqf_write(struct file *fp, struct uio *uio, struct ucred *active_cred, int flags, struct thread *td) { return (EOPNOTSUPP); } static int mqf_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *active_cred, struct thread *td) { return (ENOTTY); } static int mqf_poll(struct file *fp, int events, struct ucred *active_cred, struct thread *td) { struct mqueue *mq = FPTOMQ(fp); int revents = 0; mtx_lock(&mq->mq_mutex); if (events & (POLLIN | POLLRDNORM)) { if (mq->mq_curmsgs) { revents |= events & (POLLIN | POLLRDNORM); } else { mq->mq_flags |= MQ_RSEL; selrecord(td, &mq->mq_rsel); } } if (events & POLLOUT) { if (mq->mq_curmsgs < mq->mq_maxmsg) revents |= POLLOUT; else { mq->mq_flags |= MQ_WSEL; selrecord(td, &mq->mq_wsel); } } mtx_unlock(&mq->mq_mutex); return (revents); } static int mqf_close(struct file *fp, struct thread *td) { struct mqfs_node *pn; FILE_LOCK(fp); fp->f_ops = &badfileops; FILE_UNLOCK(fp); pn = fp->f_data; fp->f_data = NULL; sx_xlock(&mqfs_data.mi_lock); mqnode_release(pn); sx_xunlock(&mqfs_data.mi_lock); return (0); } static int mqf_stat(struct file *fp, struct stat *st, struct ucred *active_cred, struct thread *td) { struct mqfs_node *pn = fp->f_data; bzero(st, sizeof *st); st->st_atimespec = pn->mn_atime; st->st_mtimespec = pn->mn_mtime; st->st_ctimespec = pn->mn_ctime; st->st_birthtimespec = pn->mn_birth; st->st_uid = pn->mn_uid; st->st_gid = pn->mn_gid; st->st_mode = S_IFIFO | pn->mn_mode; return (0); } static int mqf_kqfilter(struct file *fp, struct knote *kn) { struct mqueue *mq = FPTOMQ(fp); int error = 0; if (kn->kn_filter == EVFILT_READ) { kn->kn_fop = &mq_rfiltops; knlist_add(&mq->mq_rsel.si_note, kn, 0); } else if (kn->kn_filter == EVFILT_WRITE) { kn->kn_fop = &mq_wfiltops; knlist_add(&mq->mq_wsel.si_note, kn, 0); } else error = EINVAL; return (error); } static void filt_mqdetach(struct knote *kn) { struct mqueue *mq = FPTOMQ(kn->kn_fp); if (kn->kn_filter == EVFILT_READ) knlist_remove(&mq->mq_rsel.si_note, kn, 0); else if (kn->kn_filter == EVFILT_WRITE) knlist_remove(&mq->mq_wsel.si_note, kn, 0); else panic("filt_mqdetach"); } static int filt_mqread(struct knote *kn, long hint) { struct mqueue *mq = FPTOMQ(kn->kn_fp); mtx_assert(&mq->mq_mutex, MA_OWNED); return (mq->mq_curmsgs != 0); } static int filt_mqwrite(struct knote *kn, long hint) { struct mqueue *mq = FPTOMQ(kn->kn_fp); mtx_assert(&mq->mq_mutex, MA_OWNED); return (mq->mq_curmsgs < mq->mq_maxmsg); } static struct fileops mqueueops = { .fo_read = mqf_read, .fo_write = mqf_write, .fo_ioctl = mqf_ioctl, .fo_poll = mqf_poll, .fo_kqfilter = mqf_kqfilter, .fo_stat = mqf_stat, .fo_close = mqf_close }; static struct vop_vector mqfs_vnodeops = { .vop_default = &default_vnodeops, .vop_access = mqfs_access, .vop_cachedlookup = mqfs_lookup, .vop_lookup = vfs_cache_lookup, .vop_reclaim = mqfs_reclaim, .vop_create = mqfs_create, .vop_remove = mqfs_remove, .vop_inactive = mqfs_inactive, .vop_open = mqfs_open, .vop_close = mqfs_close, .vop_getattr = mqfs_getattr, .vop_setattr = mqfs_setattr, .vop_read = mqfs_read, .vop_write = VOP_EOPNOTSUPP, .vop_readdir = mqfs_readdir, .vop_mkdir = VOP_EOPNOTSUPP, .vop_rmdir = VOP_EOPNOTSUPP }; static struct vfsops mqfs_vfsops = { .vfs_init = mqfs_init, .vfs_uninit = mqfs_uninit, .vfs_mount = mqfs_mount, .vfs_unmount = mqfs_unmount, .vfs_root = mqfs_root, .vfs_statfs = mqfs_statfs, }; SYSCALL_MODULE_HELPER(kmq_open); SYSCALL_MODULE_HELPER(kmq_setattr); SYSCALL_MODULE_HELPER(kmq_timedsend); SYSCALL_MODULE_HELPER(kmq_timedreceive); SYSCALL_MODULE_HELPER(kmq_notify); SYSCALL_MODULE_HELPER(kmq_unlink); VFS_SET(mqfs_vfsops, mqueuefs, VFCF_SYNTHETIC); MODULE_VERSION(mqueuefs, 1); Index: head/sys/kern/uipc_sem.c =================================================================== --- head/sys/kern/uipc_sem.c (revision 164183) +++ head/sys/kern/uipc_sem.c (revision 164184) @@ -1,1012 +1,1011 @@ /*- * Copyright (c) 2002 Alfred Perlstein * Copyright (c) 2003-2005 SPARTA, Inc. * Copyright (c) 2005 Robert N. M. Watson * All rights reserved. * * This software was developed for the FreeBSD Project in part by Network * Associates Laboratories, the Security Research Division of Network * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), * as part of the DARPA CHATS research program. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_mac.h" #include "opt_posix.h" #include #include #include #include #include +#include #include #include +#include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include - -#include -#include -#include -#include +#include #include static int sem_count_proc(struct proc *p); static struct ksem *sem_lookup_byname(const char *name); static int sem_create(struct thread *td, const char *name, struct ksem **ksret, mode_t mode, unsigned int value); static void sem_free(struct ksem *ksnew); static int sem_perm(struct thread *td, struct ksem *ks); static void sem_enter(struct proc *p, struct ksem *ks); static int sem_leave(struct proc *p, struct ksem *ks); static void sem_exechook(void *arg, struct proc *p, struct image_params *imgp); static void sem_exithook(void *arg, struct proc *p); static void sem_forkhook(void *arg, struct proc *p1, struct proc *p2, int flags); static int sem_hasopen(struct thread *td, struct ksem *ks); static int kern_sem_close(struct thread *td, semid_t id); static int kern_sem_post(struct thread *td, semid_t id); static int kern_sem_wait(struct thread *td, semid_t id, int tryflag, struct timespec *abstime); static int kern_sem_init(struct thread *td, int dir, unsigned int value, semid_t *idp); static int kern_sem_open(struct thread *td, int dir, const char *name, int oflag, mode_t mode, unsigned int value, semid_t *idp); static int kern_sem_unlink(struct thread *td, const char *name); #ifndef SEM_MAX #define SEM_MAX 30 #endif #define SEM_MAX_NAMELEN 14 #define SEM_TO_ID(x) ((intptr_t)(x)) #define ID_TO_SEM(x) id_to_sem(x) /* * available semaphores go here, this includes sem_init and any semaphores * created via sem_open that have not yet been unlinked. */ LIST_HEAD(, ksem) ksem_head = LIST_HEAD_INITIALIZER(&ksem_head); /* * semaphores still in use but have been sem_unlink()'d go here. */ LIST_HEAD(, ksem) ksem_deadhead = LIST_HEAD_INITIALIZER(&ksem_deadhead); static struct mtx sem_lock; static MALLOC_DEFINE(M_SEM, "sems", "semaphore data"); static int nsems = 0; SYSCTL_DECL(_p1003_1b); SYSCTL_INT(_p1003_1b, OID_AUTO, nsems, CTLFLAG_RD, &nsems, 0, ""); static eventhandler_tag sem_exit_tag, sem_exec_tag, sem_fork_tag; #ifdef SEM_DEBUG #define DP(x) printf x #else #define DP(x) #endif static __inline void sem_ref(struct ksem *ks) { mtx_assert(&sem_lock, MA_OWNED); ks->ks_ref++; DP(("sem_ref: ks = %p, ref = %d\n", ks, ks->ks_ref)); } static __inline void sem_rel(struct ksem *ks) { mtx_assert(&sem_lock, MA_OWNED); DP(("sem_rel: ks = %p, ref = %d\n", ks, ks->ks_ref - 1)); if (--ks->ks_ref == 0) sem_free(ks); } static __inline struct ksem *id_to_sem(semid_t id); static __inline struct ksem * id_to_sem(semid_t id) { struct ksem *ks; mtx_assert(&sem_lock, MA_OWNED); DP(("id_to_sem: id = %0x,%p\n", id, (struct ksem *)id)); LIST_FOREACH(ks, &ksem_head, ks_entry) { DP(("id_to_sem: ks = %p\n", ks)); if (ks == (struct ksem *)id) return (ks); } return (NULL); } static struct ksem * sem_lookup_byname(const char *name) { struct ksem *ks; mtx_assert(&sem_lock, MA_OWNED); LIST_FOREACH(ks, &ksem_head, ks_entry) if (ks->ks_name != NULL && strcmp(ks->ks_name, name) == 0) return (ks); return (NULL); } static int sem_create(struct thread *td, const char *name, struct ksem **ksret, mode_t mode, unsigned int value) { struct ksem *ret; struct proc *p; struct ucred *uc; size_t len; int error; DP(("sem_create\n")); p = td->td_proc; uc = td->td_ucred; if (value > SEM_VALUE_MAX) return (EINVAL); ret = malloc(sizeof(*ret), M_SEM, M_WAITOK | M_ZERO); if (name != NULL) { len = strlen(name); if (len > SEM_MAX_NAMELEN) { free(ret, M_SEM); return (ENAMETOOLONG); } /* name must start with a '/' but not contain one. */ if (*name != '/' || len < 2 || index(name + 1, '/') != NULL) { free(ret, M_SEM); return (EINVAL); } ret->ks_name = malloc(len + 1, M_SEM, M_WAITOK); strcpy(ret->ks_name, name); } else { ret->ks_name = NULL; } ret->ks_mode = mode; ret->ks_value = value; ret->ks_ref = 1; ret->ks_waiters = 0; ret->ks_uid = uc->cr_uid; ret->ks_gid = uc->cr_gid; ret->ks_onlist = 0; cv_init(&ret->ks_cv, "sem"); LIST_INIT(&ret->ks_users); #ifdef MAC mac_init_posix_sem(ret); mac_create_posix_sem(uc, ret); #endif if (name != NULL) sem_enter(td->td_proc, ret); *ksret = ret; mtx_lock(&sem_lock); if (nsems >= p31b_getcfg(CTL_P1003_1B_SEM_NSEMS_MAX)) { sem_leave(td->td_proc, ret); sem_free(ret); error = ENFILE; } else { nsems++; error = 0; } mtx_unlock(&sem_lock); return (error); } #ifndef _SYS_SYSPROTO_H_ struct ksem_init_args { unsigned int value; semid_t *idp; }; int ksem_init(struct thread *td, struct ksem_init_args *uap); #endif int ksem_init(struct thread *td, struct ksem_init_args *uap) { int error; error = kern_sem_init(td, UIO_USERSPACE, uap->value, uap->idp); return (error); } static int kern_sem_init(struct thread *td, int dir, unsigned int value, semid_t *idp) { struct ksem *ks; semid_t id; int error; error = sem_create(td, NULL, &ks, S_IRWXU | S_IRWXG, value); if (error) return (error); id = SEM_TO_ID(ks); if (dir == UIO_USERSPACE) { error = copyout(&id, idp, sizeof(id)); if (error) { mtx_lock(&sem_lock); sem_rel(ks); mtx_unlock(&sem_lock); return (error); } } else { *idp = id; } mtx_lock(&sem_lock); LIST_INSERT_HEAD(&ksem_head, ks, ks_entry); ks->ks_onlist = 1; mtx_unlock(&sem_lock); return (error); } #ifndef _SYS_SYSPROTO_H_ struct ksem_open_args { char *name; int oflag; mode_t mode; unsigned int value; semid_t *idp; }; int ksem_open(struct thread *td, struct ksem_open_args *uap); #endif int ksem_open(struct thread *td, struct ksem_open_args *uap) { char name[SEM_MAX_NAMELEN + 1]; size_t done; int error; error = copyinstr(uap->name, name, SEM_MAX_NAMELEN + 1, &done); if (error) return (error); DP((">>> sem_open start\n")); error = kern_sem_open(td, UIO_USERSPACE, name, uap->oflag, uap->mode, uap->value, uap->idp); DP(("<<< sem_open end\n")); return (error); } static int kern_sem_open(struct thread *td, int dir, const char *name, int oflag, mode_t mode, unsigned int value, semid_t *idp) { struct ksem *ksnew, *ks; int error; semid_t id; ksnew = NULL; mtx_lock(&sem_lock); ks = sem_lookup_byname(name); /* * If we found it but O_EXCL is set, error. */ if (ks != NULL && (oflag & O_EXCL) != 0) { mtx_unlock(&sem_lock); return (EEXIST); } /* * If we didn't find it... */ if (ks == NULL) { /* * didn't ask for creation? error. */ if ((oflag & O_CREAT) == 0) { mtx_unlock(&sem_lock); return (ENOENT); } /* * We may block during creation, so drop the lock. */ mtx_unlock(&sem_lock); error = sem_create(td, name, &ksnew, mode, value); if (error != 0) return (error); id = SEM_TO_ID(ksnew); if (dir == UIO_USERSPACE) { DP(("about to copyout! %d to %p\n", id, idp)); error = copyout(&id, idp, sizeof(id)); if (error) { mtx_lock(&sem_lock); sem_leave(td->td_proc, ksnew); sem_rel(ksnew); mtx_unlock(&sem_lock); return (error); } } else { DP(("about to set! %d to %p\n", id, idp)); *idp = id; } /* * We need to make sure we haven't lost a race while * allocating during creation. */ mtx_lock(&sem_lock); ks = sem_lookup_byname(name); if (ks != NULL) { /* we lost... */ sem_leave(td->td_proc, ksnew); sem_rel(ksnew); /* we lost and we can't loose... */ if ((oflag & O_EXCL) != 0) { mtx_unlock(&sem_lock); return (EEXIST); } } else { DP(("sem_create: about to add to list...\n")); LIST_INSERT_HEAD(&ksem_head, ksnew, ks_entry); DP(("sem_create: setting list bit...\n")); ksnew->ks_onlist = 1; DP(("sem_create: done, about to unlock...\n")); } } else { #ifdef MAC error = mac_check_posix_sem_open(td->td_ucred, ks); if (error) goto err_open; #endif /* * if we aren't the creator, then enforce permissions. */ error = sem_perm(td, ks); if (error) goto err_open; sem_ref(ks); mtx_unlock(&sem_lock); id = SEM_TO_ID(ks); if (dir == UIO_USERSPACE) { error = copyout(&id, idp, sizeof(id)); if (error) { mtx_lock(&sem_lock); sem_rel(ks); mtx_unlock(&sem_lock); return (error); } } else { *idp = id; } sem_enter(td->td_proc, ks); mtx_lock(&sem_lock); sem_rel(ks); } err_open: mtx_unlock(&sem_lock); return (error); } static int sem_perm(struct thread *td, struct ksem *ks) { struct ucred *uc; /* * XXXRW: This permission routine appears to be incorrect. If the * user matches, we shouldn't go on to the group if the user * permissions don't allow the action? Not changed for now. To fix, * change from a series of if (); if (); to if () else if () else... */ uc = td->td_ucred; DP(("sem_perm: uc(%d,%d) ks(%d,%d,%o)\n", uc->cr_uid, uc->cr_gid, ks->ks_uid, ks->ks_gid, ks->ks_mode)); if ((uc->cr_uid == ks->ks_uid) && (ks->ks_mode & S_IWUSR) != 0) return (0); if ((uc->cr_gid == ks->ks_gid) && (ks->ks_mode & S_IWGRP) != 0) return (0); if ((ks->ks_mode & S_IWOTH) != 0) return (0); return (priv_check(td, PRIV_SEM_WRITE)); } static void sem_free(struct ksem *ks) { nsems--; if (ks->ks_onlist) LIST_REMOVE(ks, ks_entry); if (ks->ks_name != NULL) free(ks->ks_name, M_SEM); cv_destroy(&ks->ks_cv); free(ks, M_SEM); } static __inline struct kuser *sem_getuser(struct proc *p, struct ksem *ks); static __inline struct kuser * sem_getuser(struct proc *p, struct ksem *ks) { struct kuser *k; LIST_FOREACH(k, &ks->ks_users, ku_next) if (k->ku_pid == p->p_pid) return (k); return (NULL); } static int sem_hasopen(struct thread *td, struct ksem *ks) { return ((ks->ks_name == NULL && sem_perm(td, ks) == 0) || sem_getuser(td->td_proc, ks) != NULL); } static int sem_leave(struct proc *p, struct ksem *ks) { struct kuser *k; DP(("sem_leave: ks = %p\n", ks)); k = sem_getuser(p, ks); DP(("sem_leave: ks = %p, k = %p\n", ks, k)); if (k != NULL) { LIST_REMOVE(k, ku_next); sem_rel(ks); DP(("sem_leave: about to free k\n")); free(k, M_SEM); DP(("sem_leave: returning\n")); return (0); } return (EINVAL); } static void sem_enter(p, ks) struct proc *p; struct ksem *ks; { struct kuser *ku, *k; ku = malloc(sizeof(*ku), M_SEM, M_WAITOK); ku->ku_pid = p->p_pid; mtx_lock(&sem_lock); k = sem_getuser(p, ks); if (k != NULL) { mtx_unlock(&sem_lock); free(ku, M_TEMP); return; } LIST_INSERT_HEAD(&ks->ks_users, ku, ku_next); sem_ref(ks); mtx_unlock(&sem_lock); } #ifndef _SYS_SYSPROTO_H_ struct ksem_unlink_args { char *name; }; int ksem_unlink(struct thread *td, struct ksem_unlink_args *uap); #endif int ksem_unlink(struct thread *td, struct ksem_unlink_args *uap) { char name[SEM_MAX_NAMELEN + 1]; size_t done; int error; error = copyinstr(uap->name, name, SEM_MAX_NAMELEN + 1, &done); return (error ? error : kern_sem_unlink(td, name)); } static int kern_sem_unlink(struct thread *td, const char *name) { struct ksem *ks; int error; mtx_lock(&sem_lock); ks = sem_lookup_byname(name); if (ks != NULL) { #ifdef MAC error = mac_check_posix_sem_unlink(td->td_ucred, ks); if (error) { mtx_unlock(&sem_lock); return (error); } #endif error = sem_perm(td, ks); } else error = ENOENT; DP(("sem_unlink: '%s' ks = %p, error = %d\n", name, ks, error)); if (error == 0) { LIST_REMOVE(ks, ks_entry); LIST_INSERT_HEAD(&ksem_deadhead, ks, ks_entry); sem_rel(ks); } mtx_unlock(&sem_lock); return (error); } #ifndef _SYS_SYSPROTO_H_ struct ksem_close_args { semid_t id; }; int ksem_close(struct thread *td, struct ksem_close_args *uap); #endif int ksem_close(struct thread *td, struct ksem_close_args *uap) { return (kern_sem_close(td, uap->id)); } static int kern_sem_close(struct thread *td, semid_t id) { struct ksem *ks; int error; error = EINVAL; mtx_lock(&sem_lock); ks = ID_TO_SEM(id); /* this is not a valid operation for unnamed sems */ if (ks != NULL && ks->ks_name != NULL) error = sem_leave(td->td_proc, ks); mtx_unlock(&sem_lock); return (error); } #ifndef _SYS_SYSPROTO_H_ struct ksem_post_args { semid_t id; }; int ksem_post(struct thread *td, struct ksem_post_args *uap); #endif int ksem_post(struct thread *td, struct ksem_post_args *uap) { return (kern_sem_post(td, uap->id)); } static int kern_sem_post(struct thread *td, semid_t id) { struct ksem *ks; int error; mtx_lock(&sem_lock); ks = ID_TO_SEM(id); if (ks == NULL || !sem_hasopen(td, ks)) { error = EINVAL; goto err; } #ifdef MAC error = mac_check_posix_sem_post(td->td_ucred, ks); if (error) goto err; #endif if (ks->ks_value == SEM_VALUE_MAX) { error = EOVERFLOW; goto err; } ++ks->ks_value; if (ks->ks_waiters > 0) cv_signal(&ks->ks_cv); error = 0; err: mtx_unlock(&sem_lock); return (error); } #ifndef _SYS_SYSPROTO_H_ struct ksem_wait_args { semid_t id; }; int ksem_wait(struct thread *td, struct ksem_wait_args *uap); #endif int ksem_wait(struct thread *td, struct ksem_wait_args *uap) { return (kern_sem_wait(td, uap->id, 0, NULL)); } #ifndef _SYS_SYSPROTO_H_ struct ksem_timedwait_args { semid_t id; const struct timespec *abstime; }; int ksem_timedwait(struct thread *td, struct ksem_timedwait_args *uap); #endif int ksem_timedwait(struct thread *td, struct ksem_timedwait_args *uap) { struct timespec abstime; struct timespec *ts; int error; /* We allow a null timespec (wait forever). */ if (uap->abstime == NULL) ts = NULL; else { error = copyin(uap->abstime, &abstime, sizeof(abstime)); if (error != 0) return (error); if (abstime.tv_nsec >= 1000000000 || abstime.tv_nsec < 0) return (EINVAL); ts = &abstime; } return (kern_sem_wait(td, uap->id, 0, ts)); } #ifndef _SYS_SYSPROTO_H_ struct ksem_trywait_args { semid_t id; }; int ksem_trywait(struct thread *td, struct ksem_trywait_args *uap); #endif int ksem_trywait(struct thread *td, struct ksem_trywait_args *uap) { return (kern_sem_wait(td, uap->id, 1, NULL)); } static int kern_sem_wait(struct thread *td, semid_t id, int tryflag, struct timespec *abstime) { struct timespec ts1, ts2; struct timeval tv; struct ksem *ks; int error; DP((">>> kern_sem_wait entered!\n")); mtx_lock(&sem_lock); ks = ID_TO_SEM(id); if (ks == NULL) { DP(("kern_sem_wait ks == NULL\n")); error = EINVAL; goto err; } sem_ref(ks); if (!sem_hasopen(td, ks)) { DP(("kern_sem_wait hasopen failed\n")); error = EINVAL; goto err; } #ifdef MAC error = mac_check_posix_sem_wait(td->td_ucred, ks); if (error) { DP(("kern_sem_wait mac failed\n")); goto err; } #endif DP(("kern_sem_wait value = %d, tryflag %d\n", ks->ks_value, tryflag)); if (ks->ks_value == 0) { ks->ks_waiters++; if (tryflag != 0) error = EAGAIN; else if (abstime == NULL) error = cv_wait_sig(&ks->ks_cv, &sem_lock); else { for (;;) { ts1 = *abstime; getnanotime(&ts2); timespecsub(&ts1, &ts2); TIMESPEC_TO_TIMEVAL(&tv, &ts1); if (tv.tv_sec < 0) { error = ETIMEDOUT; break; } error = cv_timedwait_sig(&ks->ks_cv, &sem_lock, tvtohz(&tv)); if (error != EWOULDBLOCK) break; } } ks->ks_waiters--; if (error) goto err; } ks->ks_value--; error = 0; err: if (ks != NULL) sem_rel(ks); mtx_unlock(&sem_lock); DP(("<<< kern_sem_wait leaving, error = %d\n", error)); return (error); } #ifndef _SYS_SYSPROTO_H_ struct ksem_getvalue_args { semid_t id; int *val; }; int ksem_getvalue(struct thread *td, struct ksem_getvalue_args *uap); #endif int ksem_getvalue(struct thread *td, struct ksem_getvalue_args *uap) { struct ksem *ks; int error, val; mtx_lock(&sem_lock); ks = ID_TO_SEM(uap->id); if (ks == NULL || !sem_hasopen(td, ks)) { mtx_unlock(&sem_lock); return (EINVAL); } #ifdef MAC error = mac_check_posix_sem_getvalue(td->td_ucred, ks); if (error) { mtx_unlock(&sem_lock); return (error); } #endif val = ks->ks_value; mtx_unlock(&sem_lock); error = copyout(&val, uap->val, sizeof(val)); return (error); } #ifndef _SYS_SYSPROTO_H_ struct ksem_destroy_args { semid_t id; }; int ksem_destroy(struct thread *td, struct ksem_destroy_args *uap); #endif int ksem_destroy(struct thread *td, struct ksem_destroy_args *uap) { struct ksem *ks; int error; mtx_lock(&sem_lock); ks = ID_TO_SEM(uap->id); if (ks == NULL || !sem_hasopen(td, ks) || ks->ks_name != NULL) { error = EINVAL; goto err; } #ifdef MAC error = mac_check_posix_sem_destroy(td->td_ucred, ks); if (error) goto err; #endif if (ks->ks_waiters != 0) { error = EBUSY; goto err; } sem_rel(ks); error = 0; err: mtx_unlock(&sem_lock); return (error); } /* * Count the number of kusers associated with a proc, so as to guess at how * many to allocate when forking. */ static int sem_count_proc(struct proc *p) { struct ksem *ks; struct kuser *ku; int count; mtx_assert(&sem_lock, MA_OWNED); count = 0; LIST_FOREACH(ks, &ksem_head, ks_entry) { LIST_FOREACH(ku, &ks->ks_users, ku_next) { if (ku->ku_pid == p->p_pid) count++; } } LIST_FOREACH(ks, &ksem_deadhead, ks_entry) { LIST_FOREACH(ku, &ks->ks_users, ku_next) { if (ku->ku_pid == p->p_pid) count++; } } return (count); } /* * When a process forks, the child process must gain a reference to each open * semaphore in the parent process, whether it is unlinked or not. This * requires allocating a kuser structure for each semaphore reference in the * new process. Because the set of semaphores in the parent can change while * the fork is in progress, we have to handle races -- first we attempt to * allocate enough storage to acquire references to each of the semaphores, * then we enter the semaphores and release the temporary references. */ static void sem_forkhook(void *arg, struct proc *p1, struct proc *p2, int flags) { struct ksem *ks, **sem_array; int count, i, new_count; struct kuser *ku; mtx_lock(&sem_lock); count = sem_count_proc(p1); if (count == 0) { mtx_unlock(&sem_lock); return; } race_lost: mtx_assert(&sem_lock, MA_OWNED); mtx_unlock(&sem_lock); sem_array = malloc(sizeof(struct ksem *) * count, M_TEMP, M_WAITOK); mtx_lock(&sem_lock); new_count = sem_count_proc(p1); if (count < new_count) { /* Lost race, repeat and allocate more storage. */ free(sem_array, M_TEMP); count = new_count; goto race_lost; } /* * Given an array capable of storing an adequate number of semaphore * references, now walk the list of semaphores and acquire a new * reference for any semaphore opened by p1. */ count = new_count; i = 0; LIST_FOREACH(ks, &ksem_head, ks_entry) { LIST_FOREACH(ku, &ks->ks_users, ku_next) { if (ku->ku_pid == p1->p_pid) { sem_ref(ks); sem_array[i] = ks; i++; break; } } } LIST_FOREACH(ks, &ksem_deadhead, ks_entry) { LIST_FOREACH(ku, &ks->ks_users, ku_next) { if (ku->ku_pid == p1->p_pid) { sem_ref(ks); sem_array[i] = ks; i++; break; } } } mtx_unlock(&sem_lock); KASSERT(i == count, ("sem_forkhook: i != count (%d, %d)", i, count)); /* * Now cause p2 to enter each of the referenced semaphores, then * release our temporary reference. This is pretty inefficient. * Finally, free our temporary array. */ for (i = 0; i < count; i++) { sem_enter(p2, sem_array[i]); mtx_lock(&sem_lock); sem_rel(sem_array[i]); mtx_unlock(&sem_lock); } free(sem_array, M_TEMP); } static void sem_exechook(void *arg, struct proc *p, struct image_params *imgp __unused) { sem_exithook(arg, p); } static void sem_exithook(void *arg, struct proc *p) { struct ksem *ks, *ksnext; mtx_lock(&sem_lock); ks = LIST_FIRST(&ksem_head); while (ks != NULL) { ksnext = LIST_NEXT(ks, ks_entry); sem_leave(p, ks); ks = ksnext; } ks = LIST_FIRST(&ksem_deadhead); while (ks != NULL) { ksnext = LIST_NEXT(ks, ks_entry); sem_leave(p, ks); ks = ksnext; } mtx_unlock(&sem_lock); } static int sem_modload(struct module *module, int cmd, void *arg) { int error = 0; switch (cmd) { case MOD_LOAD: mtx_init(&sem_lock, "sem", "semaphore", MTX_DEF); p31b_setcfg(CTL_P1003_1B_SEM_NSEMS_MAX, SEM_MAX); p31b_setcfg(CTL_P1003_1B_SEM_VALUE_MAX, SEM_VALUE_MAX); sem_exit_tag = EVENTHANDLER_REGISTER(process_exit, sem_exithook, NULL, EVENTHANDLER_PRI_ANY); sem_exec_tag = EVENTHANDLER_REGISTER(process_exec, sem_exechook, NULL, EVENTHANDLER_PRI_ANY); sem_fork_tag = EVENTHANDLER_REGISTER(process_fork, sem_forkhook, NULL, EVENTHANDLER_PRI_ANY); break; case MOD_UNLOAD: if (nsems != 0) { error = EOPNOTSUPP; break; } EVENTHANDLER_DEREGISTER(process_exit, sem_exit_tag); EVENTHANDLER_DEREGISTER(process_exec, sem_exec_tag); EVENTHANDLER_DEREGISTER(process_fork, sem_fork_tag); mtx_destroy(&sem_lock); break; case MOD_SHUTDOWN: break; default: error = EINVAL; break; } return (error); } static moduledata_t sem_mod = { "sem", &sem_modload, NULL }; SYSCALL_MODULE_HELPER(ksem_init); SYSCALL_MODULE_HELPER(ksem_open); SYSCALL_MODULE_HELPER(ksem_unlink); SYSCALL_MODULE_HELPER(ksem_close); SYSCALL_MODULE_HELPER(ksem_post); SYSCALL_MODULE_HELPER(ksem_wait); SYSCALL_MODULE_HELPER(ksem_timedwait); SYSCALL_MODULE_HELPER(ksem_trywait); SYSCALL_MODULE_HELPER(ksem_getvalue); SYSCALL_MODULE_HELPER(ksem_destroy); DECLARE_MODULE(sem, sem_mod, SI_SUB_SYSV_SEM, SI_ORDER_FIRST); MODULE_VERSION(sem, 1); Index: head/sys/kern/vfs_aio.c =================================================================== --- head/sys/kern/vfs_aio.c (revision 164183) +++ head/sys/kern/vfs_aio.c (revision 164184) @@ -1,2322 +1,2322 @@ /*- * Copyright (c) 1997 John S. Dyson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. John S. Dyson's name may not be used to endorse or promote products * derived from this software without specific prior written permission. * * DISCLAIMER: This code isn't warranted to do anything useful. Anything * bad that happens because of using this software isn't the responsibility * of the author. This software is distributed AS-IS. */ /* * This file contains support for the POSIX 1003.1B AIO/LIO facility. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include #include #include #include #include #include #include #include #include "opt_vfs_aio.h" /* * Counter for allocating reference ids to new jobs. Wrapped to 1 on * overflow. (XXX will be removed soon.) */ static u_long jobrefid; /* * Counter for aio_fsync. */ static uint64_t jobseqno; #define JOBST_NULL 0 #define JOBST_JOBQSOCK 1 #define JOBST_JOBQGLOBAL 2 #define JOBST_JOBRUNNING 3 #define JOBST_JOBFINISHED 4 #define JOBST_JOBQBUF 5 #define JOBST_JOBQSYNC 6 #ifndef MAX_AIO_PER_PROC #define MAX_AIO_PER_PROC 32 #endif #ifndef MAX_AIO_QUEUE_PER_PROC #define MAX_AIO_QUEUE_PER_PROC 256 /* Bigger than AIO_LISTIO_MAX */ #endif #ifndef MAX_AIO_PROCS #define MAX_AIO_PROCS 32 #endif #ifndef MAX_AIO_QUEUE #define MAX_AIO_QUEUE 1024 /* Bigger than AIO_LISTIO_MAX */ #endif #ifndef TARGET_AIO_PROCS #define TARGET_AIO_PROCS 4 #endif #ifndef MAX_BUF_AIO #define MAX_BUF_AIO 16 #endif #ifndef AIOD_TIMEOUT_DEFAULT #define AIOD_TIMEOUT_DEFAULT (10 * hz) #endif #ifndef AIOD_LIFETIME_DEFAULT #define AIOD_LIFETIME_DEFAULT (30 * hz) #endif static SYSCTL_NODE(_vfs, OID_AUTO, aio, CTLFLAG_RW, 0, "Async IO management"); static int max_aio_procs = MAX_AIO_PROCS; SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_procs, CTLFLAG_RW, &max_aio_procs, 0, "Maximum number of kernel threads to use for handling async IO "); static int num_aio_procs = 0; SYSCTL_INT(_vfs_aio, OID_AUTO, num_aio_procs, CTLFLAG_RD, &num_aio_procs, 0, "Number of presently active kernel threads for async IO"); /* * The code will adjust the actual number of AIO processes towards this * number when it gets a chance. */ static int target_aio_procs = TARGET_AIO_PROCS; SYSCTL_INT(_vfs_aio, OID_AUTO, target_aio_procs, CTLFLAG_RW, &target_aio_procs, 0, "Preferred number of ready kernel threads for async IO"); static int max_queue_count = MAX_AIO_QUEUE; SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue, CTLFLAG_RW, &max_queue_count, 0, "Maximum number of aio requests to queue, globally"); static int num_queue_count = 0; SYSCTL_INT(_vfs_aio, OID_AUTO, num_queue_count, CTLFLAG_RD, &num_queue_count, 0, "Number of queued aio requests"); static int num_buf_aio = 0; SYSCTL_INT(_vfs_aio, OID_AUTO, num_buf_aio, CTLFLAG_RD, &num_buf_aio, 0, "Number of aio requests presently handled by the buf subsystem"); /* Number of async I/O thread in the process of being started */ /* XXX This should be local to aio_aqueue() */ static int num_aio_resv_start = 0; static int aiod_timeout; SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_timeout, CTLFLAG_RW, &aiod_timeout, 0, "Timeout value for synchronous aio operations"); static int aiod_lifetime; SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_lifetime, CTLFLAG_RW, &aiod_lifetime, 0, "Maximum lifetime for idle aiod"); static int unloadable = 0; SYSCTL_INT(_vfs_aio, OID_AUTO, unloadable, CTLFLAG_RW, &unloadable, 0, "Allow unload of aio (not recommended)"); static int max_aio_per_proc = MAX_AIO_PER_PROC; SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_per_proc, CTLFLAG_RW, &max_aio_per_proc, 0, "Maximum active aio requests per process (stored in the process)"); static int max_aio_queue_per_proc = MAX_AIO_QUEUE_PER_PROC; SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue_per_proc, CTLFLAG_RW, &max_aio_queue_per_proc, 0, "Maximum queued aio requests per process (stored in the process)"); static int max_buf_aio = MAX_BUF_AIO; SYSCTL_INT(_vfs_aio, OID_AUTO, max_buf_aio, CTLFLAG_RW, &max_buf_aio, 0, "Maximum buf aio requests per process (stored in the process)"); typedef struct oaiocb { int aio_fildes; /* File descriptor */ off_t aio_offset; /* File offset for I/O */ volatile void *aio_buf; /* I/O buffer in process space */ size_t aio_nbytes; /* Number of bytes for I/O */ struct osigevent aio_sigevent; /* Signal to deliver */ int aio_lio_opcode; /* LIO opcode */ int aio_reqprio; /* Request priority -- ignored */ struct __aiocb_private _aiocb_private; } oaiocb_t; /* * Below is a key of locks used to protect each member of struct aiocblist * aioliojob and kaioinfo and any backends. * * * - need not protected * a - locked by kaioinfo lock * b - locked by backend lock, the backend lock can be null in some cases, * for example, BIO belongs to this type, in this case, proc lock is * reused. * c - locked by aio_job_mtx, the lock for the generic file I/O backend. */ /* * Current, there is only two backends: BIO and generic file I/O. * socket I/O is served by generic file I/O, this is not a good idea, since * disk file I/O and any other types without O_NONBLOCK flag can block daemon * threads, if there is no thread to serve socket I/O, the socket I/O will be * delayed too long or starved, we should create some threads dedicated to * sockets to do non-blocking I/O, same for pipe and fifo, for these I/O * systems we really need non-blocking interface, fiddling O_NONBLOCK in file * structure is not safe because there is race between userland and aio * daemons. */ struct aiocblist { TAILQ_ENTRY(aiocblist) list; /* (b) internal list of for backend */ TAILQ_ENTRY(aiocblist) plist; /* (a) list of jobs for each backend */ TAILQ_ENTRY(aiocblist) allist; /* (a) list of all jobs in proc */ int jobflags; /* (a) job flags */ int jobstate; /* (b) job state */ int inputcharge; /* (*) input blockes */ int outputcharge; /* (*) output blockes */ struct buf *bp; /* (*) private to BIO backend, * buffer pointer */ struct proc *userproc; /* (*) user process */ struct ucred *cred; /* (*) active credential when created */ struct file *fd_file; /* (*) pointer to file structure */ struct aioliojob *lio; /* (*) optional lio job */ struct aiocb *uuaiocb; /* (*) pointer in userspace of aiocb */ struct knlist klist; /* (a) list of knotes */ struct aiocb uaiocb; /* (*) kernel I/O control block */ ksiginfo_t ksi; /* (a) realtime signal info */ struct task biotask; /* (*) private to BIO backend */ uint64_t seqno; /* (*) job number */ int pending; /* (a) number of pending I/O, aio_fsync only */ }; /* jobflags */ #define AIOCBLIST_DONE 0x01 #define AIOCBLIST_BUFDONE 0x02 #define AIOCBLIST_RUNDOWN 0x04 #define AIOCBLIST_CHECKSYNC 0x08 /* * AIO process info */ #define AIOP_FREE 0x1 /* proc on free queue */ struct aiothreadlist { int aiothreadflags; /* (c) AIO proc flags */ TAILQ_ENTRY(aiothreadlist) list; /* (c) list of processes */ struct thread *aiothread; /* (*) the AIO thread */ }; /* * data-structure for lio signal management */ struct aioliojob { int lioj_flags; /* (a) listio flags */ int lioj_count; /* (a) listio flags */ int lioj_finished_count; /* (a) listio flags */ struct sigevent lioj_signal; /* (a) signal on all I/O done */ TAILQ_ENTRY(aioliojob) lioj_list; /* (a) lio list */ struct knlist klist; /* (a) list of knotes */ ksiginfo_t lioj_ksi; /* (a) Realtime signal info */ }; #define LIOJ_SIGNAL 0x1 /* signal on all done (lio) */ #define LIOJ_SIGNAL_POSTED 0x2 /* signal has been posted */ #define LIOJ_KEVENT_POSTED 0x4 /* kevent triggered */ /* * per process aio data structure */ struct kaioinfo { struct mtx kaio_mtx; /* the lock to protect this struct */ int kaio_flags; /* (a) per process kaio flags */ int kaio_maxactive_count; /* (*) maximum number of AIOs */ int kaio_active_count; /* (c) number of currently used AIOs */ int kaio_qallowed_count; /* (*) maxiumu size of AIO queue */ int kaio_count; /* (a) size of AIO queue */ int kaio_ballowed_count; /* (*) maximum number of buffers */ int kaio_buffer_count; /* (a) number of physio buffers */ TAILQ_HEAD(,aiocblist) kaio_all; /* (a) all AIOs in the process */ TAILQ_HEAD(,aiocblist) kaio_done; /* (a) done queue for process */ TAILQ_HEAD(,aioliojob) kaio_liojoblist; /* (a) list of lio jobs */ TAILQ_HEAD(,aiocblist) kaio_jobqueue; /* (a) job queue for process */ TAILQ_HEAD(,aiocblist) kaio_bufqueue; /* (a) buffer job queue for process */ TAILQ_HEAD(,aiocblist) kaio_sockqueue; /* (a) queue for aios waiting on sockets, * NOT USED YET. */ TAILQ_HEAD(,aiocblist) kaio_syncqueue; /* (a) queue for aio_fsync */ struct task kaio_task; /* (*) task to kick aio threads */ }; #define AIO_LOCK(ki) mtx_lock(&(ki)->kaio_mtx) #define AIO_UNLOCK(ki) mtx_unlock(&(ki)->kaio_mtx) #define AIO_LOCK_ASSERT(ki, f) mtx_assert(&(ki)->kaio_mtx, (f)) #define AIO_MTX(ki) (&(ki)->kaio_mtx) #define KAIO_RUNDOWN 0x1 /* process is being run down */ #define KAIO_WAKEUP 0x2 /* wakeup process when there is a significant event */ static TAILQ_HEAD(,aiothreadlist) aio_freeproc; /* (c) Idle daemons */ static struct sema aio_newproc_sem; static struct mtx aio_job_mtx; static struct mtx aio_sock_mtx; static TAILQ_HEAD(,aiocblist) aio_jobs; /* (c) Async job list */ static struct unrhdr *aiod_unr; void aio_init_aioinfo(struct proc *p); static void aio_onceonly(void); static int aio_free_entry(struct aiocblist *aiocbe); static void aio_process(struct aiocblist *aiocbe); static int aio_newproc(int *); int aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lio, int type, int osigev); static void aio_physwakeup(struct buf *bp); static void aio_proc_rundown(void *arg, struct proc *p); static void aio_proc_rundown_exec(void *arg, struct proc *p, struct image_params *imgp); static int aio_qphysio(struct proc *p, struct aiocblist *iocb); static void biohelper(void *, int); static void aio_daemon(void *param); static void aio_swake_cb(struct socket *, struct sockbuf *); static int aio_unload(void); static void aio_bio_done_notify(struct proc *userp, struct aiocblist *aiocbe, int type); #define DONE_BUF 1 #define DONE_QUEUE 2 static int do_lio_listio(struct thread *td, struct lio_listio_args *uap, int oldsigev); static int aio_kick(struct proc *userp); static void aio_kick_nowait(struct proc *userp); static void aio_kick_helper(void *context, int pending); static int filt_aioattach(struct knote *kn); static void filt_aiodetach(struct knote *kn); static int filt_aio(struct knote *kn, long hint); static int filt_lioattach(struct knote *kn); static void filt_liodetach(struct knote *kn); static int filt_lio(struct knote *kn, long hint); /* * Zones for: * kaio Per process async io info * aiop async io thread data * aiocb async io jobs * aiol list io job pointer - internal to aio_suspend XXX * aiolio list io jobs */ static uma_zone_t kaio_zone, aiop_zone, aiocb_zone, aiol_zone, aiolio_zone; /* kqueue filters for aio */ static struct filterops aio_filtops = { 0, filt_aioattach, filt_aiodetach, filt_aio }; static struct filterops lio_filtops = { 0, filt_lioattach, filt_liodetach, filt_lio }; static eventhandler_tag exit_tag, exec_tag; TASKQUEUE_DEFINE_THREAD(aiod_bio); /* * Main operations function for use as a kernel module. */ static int aio_modload(struct module *module, int cmd, void *arg) { int error = 0; switch (cmd) { case MOD_LOAD: aio_onceonly(); break; case MOD_UNLOAD: error = aio_unload(); break; case MOD_SHUTDOWN: break; default: error = EINVAL; break; } return (error); } static moduledata_t aio_mod = { "aio", &aio_modload, NULL }; SYSCALL_MODULE_HELPER(aio_cancel); SYSCALL_MODULE_HELPER(aio_error); SYSCALL_MODULE_HELPER(aio_fsync); SYSCALL_MODULE_HELPER(aio_read); SYSCALL_MODULE_HELPER(aio_return); SYSCALL_MODULE_HELPER(aio_suspend); SYSCALL_MODULE_HELPER(aio_waitcomplete); SYSCALL_MODULE_HELPER(aio_write); SYSCALL_MODULE_HELPER(lio_listio); SYSCALL_MODULE_HELPER(oaio_read); SYSCALL_MODULE_HELPER(oaio_write); SYSCALL_MODULE_HELPER(olio_listio); DECLARE_MODULE(aio, aio_mod, SI_SUB_VFS, SI_ORDER_ANY); MODULE_VERSION(aio, 1); /* * Startup initialization */ static void aio_onceonly(void) { /* XXX: should probably just use so->callback */ aio_swake = &aio_swake_cb; exit_tag = EVENTHANDLER_REGISTER(process_exit, aio_proc_rundown, NULL, EVENTHANDLER_PRI_ANY); exec_tag = EVENTHANDLER_REGISTER(process_exec, aio_proc_rundown_exec, NULL, EVENTHANDLER_PRI_ANY); kqueue_add_filteropts(EVFILT_AIO, &aio_filtops); kqueue_add_filteropts(EVFILT_LIO, &lio_filtops); TAILQ_INIT(&aio_freeproc); sema_init(&aio_newproc_sem, 0, "aio_new_proc"); mtx_init(&aio_job_mtx, "aio_job", NULL, MTX_DEF); mtx_init(&aio_sock_mtx, "aio_sock", NULL, MTX_DEF); TAILQ_INIT(&aio_jobs); aiod_unr = new_unrhdr(1, INT_MAX, NULL); kaio_zone = uma_zcreate("AIO", sizeof(struct kaioinfo), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); aiop_zone = uma_zcreate("AIOP", sizeof(struct aiothreadlist), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); aiocb_zone = uma_zcreate("AIOCB", sizeof(struct aiocblist), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); aiol_zone = uma_zcreate("AIOL", AIO_LISTIO_MAX*sizeof(intptr_t) , NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); aiolio_zone = uma_zcreate("AIOLIO", sizeof(struct aioliojob), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); aiod_timeout = AIOD_TIMEOUT_DEFAULT; aiod_lifetime = AIOD_LIFETIME_DEFAULT; jobrefid = 1; async_io_version = _POSIX_VERSION; p31b_setcfg(CTL_P1003_1B_AIO_LISTIO_MAX, AIO_LISTIO_MAX); p31b_setcfg(CTL_P1003_1B_AIO_MAX, MAX_AIO_QUEUE); p31b_setcfg(CTL_P1003_1B_AIO_PRIO_DELTA_MAX, 0); } /* * Callback for unload of AIO when used as a module. */ static int aio_unload(void) { int error; /* * XXX: no unloads by default, it's too dangerous. * perhaps we could do it if locked out callers and then * did an aio_proc_rundown() on each process. * * jhb: aio_proc_rundown() needs to run on curproc though, * so I don't think that would fly. */ if (!unloadable) return (EOPNOTSUPP); error = kqueue_del_filteropts(EVFILT_AIO); if (error) return error; error = kqueue_del_filteropts(EVFILT_LIO); if (error) return error; async_io_version = 0; aio_swake = NULL; taskqueue_free(taskqueue_aiod_bio); delete_unrhdr(aiod_unr); uma_zdestroy(kaio_zone); uma_zdestroy(aiop_zone); uma_zdestroy(aiocb_zone); uma_zdestroy(aiol_zone); uma_zdestroy(aiolio_zone); EVENTHANDLER_DEREGISTER(process_exit, exit_tag); EVENTHANDLER_DEREGISTER(process_exec, exec_tag); mtx_destroy(&aio_job_mtx); mtx_destroy(&aio_sock_mtx); sema_destroy(&aio_newproc_sem); p31b_setcfg(CTL_P1003_1B_AIO_LISTIO_MAX, -1); p31b_setcfg(CTL_P1003_1B_AIO_MAX, -1); p31b_setcfg(CTL_P1003_1B_AIO_PRIO_DELTA_MAX, -1); return (0); } /* * Init the per-process aioinfo structure. The aioinfo limits are set * per-process for user limit (resource) management. */ void aio_init_aioinfo(struct proc *p) { struct kaioinfo *ki; ki = uma_zalloc(kaio_zone, M_WAITOK); mtx_init(&ki->kaio_mtx, "aiomtx", NULL, MTX_DEF); ki->kaio_flags = 0; ki->kaio_maxactive_count = max_aio_per_proc; ki->kaio_active_count = 0; ki->kaio_qallowed_count = max_aio_queue_per_proc; ki->kaio_count = 0; ki->kaio_ballowed_count = max_buf_aio; ki->kaio_buffer_count = 0; TAILQ_INIT(&ki->kaio_all); TAILQ_INIT(&ki->kaio_done); TAILQ_INIT(&ki->kaio_jobqueue); TAILQ_INIT(&ki->kaio_bufqueue); TAILQ_INIT(&ki->kaio_liojoblist); TAILQ_INIT(&ki->kaio_sockqueue); TAILQ_INIT(&ki->kaio_syncqueue); TASK_INIT(&ki->kaio_task, 0, aio_kick_helper, p); PROC_LOCK(p); if (p->p_aioinfo == NULL) { p->p_aioinfo = ki; PROC_UNLOCK(p); } else { PROC_UNLOCK(p); mtx_destroy(&ki->kaio_mtx); uma_zfree(kaio_zone, ki); } while (num_aio_procs < target_aio_procs) aio_newproc(NULL); } static int aio_sendsig(struct proc *p, struct sigevent *sigev, ksiginfo_t *ksi) { int ret = 0; PROC_LOCK(p); if (!KSI_ONQ(ksi)) { ksi->ksi_code = SI_ASYNCIO; ksi->ksi_flags |= KSI_EXT | KSI_INS; ret = psignal_event(p, sigev, ksi); } PROC_UNLOCK(p); return (ret); } /* * Free a job entry. Wait for completion if it is currently active, but don't * delay forever. If we delay, we return a flag that says that we have to * restart the queue scan. */ static int aio_free_entry(struct aiocblist *aiocbe) { struct kaioinfo *ki; struct aioliojob *lj; struct proc *p; p = aiocbe->userproc; MPASS(curproc == p); ki = p->p_aioinfo; MPASS(ki != NULL); AIO_LOCK_ASSERT(ki, MA_OWNED); MPASS(aiocbe->jobstate == JOBST_JOBFINISHED); atomic_subtract_int(&num_queue_count, 1); ki->kaio_count--; MPASS(ki->kaio_count >= 0); TAILQ_REMOVE(&ki->kaio_done, aiocbe, plist); TAILQ_REMOVE(&ki->kaio_all, aiocbe, allist); lj = aiocbe->lio; if (lj) { lj->lioj_count--; lj->lioj_finished_count--; if (lj->lioj_count == 0) { TAILQ_REMOVE(&ki->kaio_liojoblist, lj, lioj_list); /* lio is going away, we need to destroy any knotes */ knlist_delete(&lj->klist, curthread, 1); PROC_LOCK(p); sigqueue_take(&lj->lioj_ksi); PROC_UNLOCK(p); uma_zfree(aiolio_zone, lj); } } /* aiocbe is going away, we need to destroy any knotes */ knlist_delete(&aiocbe->klist, curthread, 1); PROC_LOCK(p); sigqueue_take(&aiocbe->ksi); PROC_UNLOCK(p); MPASS(aiocbe->bp == NULL); aiocbe->jobstate = JOBST_NULL; AIO_UNLOCK(ki); /* * The thread argument here is used to find the owning process * and is also passed to fo_close() which may pass it to various * places such as devsw close() routines. Because of that, we * need a thread pointer from the process owning the job that is * persistent and won't disappear out from under us or move to * another process. * * Currently, all the callers of this function call it to remove * an aiocblist from the current process' job list either via a * syscall or due to the current process calling exit() or * execve(). Thus, we know that p == curproc. We also know that * curthread can't exit since we are curthread. * * Therefore, we use curthread as the thread to pass to * knlist_delete(). This does mean that it is possible for the * thread pointer at close time to differ from the thread pointer * at open time, but this is already true of file descriptors in * a multithreaded process. */ fdrop(aiocbe->fd_file, curthread); crfree(aiocbe->cred); uma_zfree(aiocb_zone, aiocbe); AIO_LOCK(ki); return (0); } static void aio_proc_rundown_exec(void *arg, struct proc *p, struct image_params *imgp __unused) { aio_proc_rundown(arg, p); } /* * Rundown the jobs for a given process. */ static void aio_proc_rundown(void *arg, struct proc *p) { struct kaioinfo *ki; struct aioliojob *lj; struct aiocblist *cbe, *cbn; struct file *fp; struct socket *so; int remove; KASSERT(curthread->td_proc == p, ("%s: called on non-curproc", __func__)); ki = p->p_aioinfo; if (ki == NULL) return; AIO_LOCK(ki); ki->kaio_flags |= KAIO_RUNDOWN; restart: /* * Try to cancel all pending requests. This code simulates * aio_cancel on all pending I/O requests. */ TAILQ_FOREACH_SAFE(cbe, &ki->kaio_jobqueue, plist, cbn) { remove = 0; mtx_lock(&aio_job_mtx); if (cbe->jobstate == JOBST_JOBQGLOBAL) { TAILQ_REMOVE(&aio_jobs, cbe, list); remove = 1; } else if (cbe->jobstate == JOBST_JOBQSOCK) { fp = cbe->fd_file; MPASS(fp->f_type == DTYPE_SOCKET); so = fp->f_data; TAILQ_REMOVE(&so->so_aiojobq, cbe, list); remove = 1; } else if (cbe->jobstate == JOBST_JOBQSYNC) { TAILQ_REMOVE(&ki->kaio_syncqueue, cbe, list); remove = 1; } mtx_unlock(&aio_job_mtx); if (remove) { cbe->jobstate = JOBST_JOBFINISHED; cbe->uaiocb._aiocb_private.status = -1; cbe->uaiocb._aiocb_private.error = ECANCELED; TAILQ_REMOVE(&ki->kaio_jobqueue, cbe, plist); aio_bio_done_notify(p, cbe, DONE_QUEUE); } } /* Wait for all running I/O to be finished */ if (TAILQ_FIRST(&ki->kaio_bufqueue) || TAILQ_FIRST(&ki->kaio_jobqueue)) { ki->kaio_flags |= KAIO_WAKEUP; msleep(&p->p_aioinfo, AIO_MTX(ki), PRIBIO, "aioprn", hz); goto restart; } /* Free all completed I/O requests. */ while ((cbe = TAILQ_FIRST(&ki->kaio_done)) != NULL) aio_free_entry(cbe); while ((lj = TAILQ_FIRST(&ki->kaio_liojoblist)) != NULL) { if (lj->lioj_count == 0) { TAILQ_REMOVE(&ki->kaio_liojoblist, lj, lioj_list); knlist_delete(&lj->klist, curthread, 1); PROC_LOCK(p); sigqueue_take(&lj->lioj_ksi); PROC_UNLOCK(p); uma_zfree(aiolio_zone, lj); } else { panic("LIO job not cleaned up: C:%d, FC:%d\n", lj->lioj_count, lj->lioj_finished_count); } } AIO_UNLOCK(ki); taskqueue_drain(taskqueue_aiod_bio, &ki->kaio_task); uma_zfree(kaio_zone, ki); p->p_aioinfo = NULL; } /* * Select a job to run (called by an AIO daemon). */ static struct aiocblist * aio_selectjob(struct aiothreadlist *aiop) { struct aiocblist *aiocbe; struct kaioinfo *ki; struct proc *userp; mtx_assert(&aio_job_mtx, MA_OWNED); TAILQ_FOREACH(aiocbe, &aio_jobs, list) { userp = aiocbe->userproc; ki = userp->p_aioinfo; if (ki->kaio_active_count < ki->kaio_maxactive_count) { TAILQ_REMOVE(&aio_jobs, aiocbe, list); /* Account for currently active jobs. */ ki->kaio_active_count++; aiocbe->jobstate = JOBST_JOBRUNNING; break; } } return (aiocbe); } /* * Move all data to a permanent storage device, this code * simulates fsync syscall. */ static int aio_fsync_vnode(struct thread *td, struct vnode *vp) { struct mount *mp; int vfslocked; int error; vfslocked = VFS_LOCK_GIANT(vp->v_mount); if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) goto drop; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if (vp->v_object != NULL) { VM_OBJECT_LOCK(vp->v_object); vm_object_page_clean(vp->v_object, 0, 0, 0); VM_OBJECT_UNLOCK(vp->v_object); } error = VOP_FSYNC(vp, MNT_WAIT, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); drop: VFS_UNLOCK_GIANT(vfslocked); return (error); } /* * The AIO processing activity. This is the code that does the I/O request for * the non-physio version of the operations. The normal vn operations are used, * and this code should work in all instances for every type of file, including * pipes, sockets, fifos, and regular files. * * XXX I don't think it works well for socket, pipe, and fifo. */ static void aio_process(struct aiocblist *aiocbe) { struct ucred *td_savedcred; struct thread *td; struct proc *mycp; struct aiocb *cb; struct file *fp; struct socket *so; struct uio auio; struct iovec aiov; int cnt; int error; int oublock_st, oublock_end; int inblock_st, inblock_end; td = curthread; td_savedcred = td->td_ucred; td->td_ucred = aiocbe->cred; mycp = td->td_proc; cb = &aiocbe->uaiocb; fp = aiocbe->fd_file; if (cb->aio_lio_opcode == LIO_SYNC) { error = 0; cnt = 0; if (fp->f_vnode != NULL) error = aio_fsync_vnode(td, fp->f_vnode); cb->_aiocb_private.error = error; cb->_aiocb_private.status = 0; td->td_ucred = td_savedcred; return; } aiov.iov_base = (void *)(uintptr_t)cb->aio_buf; aiov.iov_len = cb->aio_nbytes; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_offset = cb->aio_offset; auio.uio_resid = cb->aio_nbytes; cnt = cb->aio_nbytes; auio.uio_segflg = UIO_USERSPACE; auio.uio_td = td; inblock_st = mycp->p_stats->p_ru.ru_inblock; oublock_st = mycp->p_stats->p_ru.ru_oublock; /* * aio_aqueue() acquires a reference to the file that is * released in aio_free_entry(). */ if (cb->aio_lio_opcode == LIO_READ) { auio.uio_rw = UIO_READ; error = fo_read(fp, &auio, fp->f_cred, FOF_OFFSET, td); } else { if (fp->f_type == DTYPE_VNODE) bwillwrite(); auio.uio_rw = UIO_WRITE; error = fo_write(fp, &auio, fp->f_cred, FOF_OFFSET, td); } inblock_end = mycp->p_stats->p_ru.ru_inblock; oublock_end = mycp->p_stats->p_ru.ru_oublock; aiocbe->inputcharge = inblock_end - inblock_st; aiocbe->outputcharge = oublock_end - oublock_st; if ((error) && (auio.uio_resid != cnt)) { if (error == ERESTART || error == EINTR || error == EWOULDBLOCK) error = 0; if ((error == EPIPE) && (cb->aio_lio_opcode == LIO_WRITE)) { int sigpipe = 1; if (fp->f_type == DTYPE_SOCKET) { so = fp->f_data; if (so->so_options & SO_NOSIGPIPE) sigpipe = 0; } if (sigpipe) { PROC_LOCK(aiocbe->userproc); psignal(aiocbe->userproc, SIGPIPE); PROC_UNLOCK(aiocbe->userproc); } } } cnt -= auio.uio_resid; cb->_aiocb_private.error = error; cb->_aiocb_private.status = cnt; td->td_ucred = td_savedcred; } static void aio_bio_done_notify(struct proc *userp, struct aiocblist *aiocbe, int type) { struct aioliojob *lj; struct kaioinfo *ki; struct aiocblist *scb, *scbn; int lj_done; ki = userp->p_aioinfo; AIO_LOCK_ASSERT(ki, MA_OWNED); lj = aiocbe->lio; lj_done = 0; if (lj) { lj->lioj_finished_count++; if (lj->lioj_count == lj->lioj_finished_count) lj_done = 1; } if (type == DONE_QUEUE) { aiocbe->jobflags |= AIOCBLIST_DONE; } else { aiocbe->jobflags |= AIOCBLIST_BUFDONE; } TAILQ_INSERT_TAIL(&ki->kaio_done, aiocbe, plist); aiocbe->jobstate = JOBST_JOBFINISHED; if (ki->kaio_flags & KAIO_RUNDOWN) goto notification_done; if (aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL || aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID) aio_sendsig(userp, &aiocbe->uaiocb.aio_sigevent, &aiocbe->ksi); KNOTE_LOCKED(&aiocbe->klist, 1); if (lj_done) { if (lj->lioj_signal.sigev_notify == SIGEV_KEVENT) { lj->lioj_flags |= LIOJ_KEVENT_POSTED; KNOTE_LOCKED(&lj->klist, 1); } if ((lj->lioj_flags & (LIOJ_SIGNAL|LIOJ_SIGNAL_POSTED)) == LIOJ_SIGNAL && (lj->lioj_signal.sigev_notify == SIGEV_SIGNAL || lj->lioj_signal.sigev_notify == SIGEV_THREAD_ID)) { aio_sendsig(userp, &lj->lioj_signal, &lj->lioj_ksi); lj->lioj_flags |= LIOJ_SIGNAL_POSTED; } } notification_done: if (aiocbe->jobflags & AIOCBLIST_CHECKSYNC) { TAILQ_FOREACH_SAFE(scb, &ki->kaio_syncqueue, list, scbn) { if (aiocbe->fd_file == scb->fd_file && aiocbe->seqno < scb->seqno) { if (--scb->pending == 0) { mtx_lock(&aio_job_mtx); scb->jobstate = JOBST_JOBQGLOBAL; TAILQ_REMOVE(&ki->kaio_syncqueue, scb, list); TAILQ_INSERT_TAIL(&aio_jobs, scb, list); aio_kick_nowait(userp); mtx_unlock(&aio_job_mtx); } } } } if (ki->kaio_flags & KAIO_WAKEUP) { ki->kaio_flags &= ~KAIO_WAKEUP; wakeup(&userp->p_aioinfo); } } /* * The AIO daemon, most of the actual work is done in aio_process, * but the setup (and address space mgmt) is done in this routine. */ static void aio_daemon(void *_id) { struct aiocblist *aiocbe; struct aiothreadlist *aiop; struct kaioinfo *ki; struct proc *curcp, *mycp, *userp; struct vmspace *myvm, *tmpvm; struct thread *td = curthread; int id = (intptr_t)_id; /* * Local copies of curproc (cp) and vmspace (myvm) */ mycp = td->td_proc; myvm = mycp->p_vmspace; KASSERT(mycp->p_textvp == NULL, ("kthread has a textvp")); /* * Allocate and ready the aio control info. There is one aiop structure * per daemon. */ aiop = uma_zalloc(aiop_zone, M_WAITOK); aiop->aiothread = td; aiop->aiothreadflags = 0; /* The daemon resides in its own pgrp. */ setsid(td, NULL); /* * Wakeup parent process. (Parent sleeps to keep from blasting away * and creating too many daemons.) */ sema_post(&aio_newproc_sem); mtx_lock(&aio_job_mtx); for (;;) { /* * curcp is the current daemon process context. * userp is the current user process context. */ curcp = mycp; /* * Take daemon off of free queue */ if (aiop->aiothreadflags & AIOP_FREE) { TAILQ_REMOVE(&aio_freeproc, aiop, list); aiop->aiothreadflags &= ~AIOP_FREE; } /* * Check for jobs. */ while ((aiocbe = aio_selectjob(aiop)) != NULL) { mtx_unlock(&aio_job_mtx); userp = aiocbe->userproc; /* * Connect to process address space for user program. */ if (userp != curcp) { /* * Save the current address space that we are * connected to. */ tmpvm = mycp->p_vmspace; /* * Point to the new user address space, and * refer to it. */ mycp->p_vmspace = userp->p_vmspace; atomic_add_int(&mycp->p_vmspace->vm_refcnt, 1); /* Activate the new mapping. */ pmap_activate(FIRST_THREAD_IN_PROC(mycp)); /* * If the old address space wasn't the daemons * own address space, then we need to remove the * daemon's reference from the other process * that it was acting on behalf of. */ if (tmpvm != myvm) { vmspace_free(tmpvm); } curcp = userp; } ki = userp->p_aioinfo; /* Do the I/O function. */ aio_process(aiocbe); mtx_lock(&aio_job_mtx); /* Decrement the active job count. */ ki->kaio_active_count--; mtx_unlock(&aio_job_mtx); AIO_LOCK(ki); TAILQ_REMOVE(&ki->kaio_jobqueue, aiocbe, plist); aio_bio_done_notify(userp, aiocbe, DONE_QUEUE); AIO_UNLOCK(ki); mtx_lock(&aio_job_mtx); } /* * Disconnect from user address space. */ if (curcp != mycp) { mtx_unlock(&aio_job_mtx); /* Get the user address space to disconnect from. */ tmpvm = mycp->p_vmspace; /* Get original address space for daemon. */ mycp->p_vmspace = myvm; /* Activate the daemon's address space. */ pmap_activate(FIRST_THREAD_IN_PROC(mycp)); #ifdef DIAGNOSTIC if (tmpvm == myvm) { printf("AIOD: vmspace problem -- %d\n", mycp->p_pid); } #endif /* Remove our vmspace reference. */ vmspace_free(tmpvm); curcp = mycp; mtx_lock(&aio_job_mtx); /* * We have to restart to avoid race, we only sleep if * no job can be selected, that should be * curcp == mycp. */ continue; } mtx_assert(&aio_job_mtx, MA_OWNED); TAILQ_INSERT_HEAD(&aio_freeproc, aiop, list); aiop->aiothreadflags |= AIOP_FREE; /* * If daemon is inactive for a long time, allow it to exit, * thereby freeing resources. */ if (msleep(aiop->aiothread, &aio_job_mtx, PRIBIO, "aiordy", aiod_lifetime)) { if (TAILQ_EMPTY(&aio_jobs)) { if ((aiop->aiothreadflags & AIOP_FREE) && (num_aio_procs > target_aio_procs)) { TAILQ_REMOVE(&aio_freeproc, aiop, list); num_aio_procs--; mtx_unlock(&aio_job_mtx); uma_zfree(aiop_zone, aiop); free_unr(aiod_unr, id); #ifdef DIAGNOSTIC if (mycp->p_vmspace->vm_refcnt <= 1) { printf("AIOD: bad vm refcnt for" " exiting daemon: %d\n", mycp->p_vmspace->vm_refcnt); } #endif kthread_exit(0); } } } } mtx_unlock(&aio_job_mtx); panic("shouldn't be here\n"); } /* * Create a new AIO daemon. This is mostly a kernel-thread fork routine. The * AIO daemon modifies its environment itself. */ static int aio_newproc(int *start) { int error; struct proc *p; int id; id = alloc_unr(aiod_unr); error = kthread_create(aio_daemon, (void *)(intptr_t)id, &p, RFNOWAIT, 0, "aiod%d", id); if (error == 0) { /* * Wait until daemon is started. */ sema_wait(&aio_newproc_sem); mtx_lock(&aio_job_mtx); num_aio_procs++; if (start != NULL) (*start)--; mtx_unlock(&aio_job_mtx); } else { free_unr(aiod_unr, id); } return (error); } /* * Try the high-performance, low-overhead physio method for eligible * VCHR devices. This method doesn't use an aio helper thread, and * thus has very low overhead. * * Assumes that the caller, aio_aqueue(), has incremented the file * structure's reference count, preventing its deallocation for the * duration of this call. */ static int aio_qphysio(struct proc *p, struct aiocblist *aiocbe) { struct aiocb *cb; struct file *fp; struct buf *bp; struct vnode *vp; struct kaioinfo *ki; struct aioliojob *lj; int error; cb = &aiocbe->uaiocb; fp = aiocbe->fd_file; if (fp->f_type != DTYPE_VNODE) return (-1); vp = fp->f_vnode; /* * If its not a disk, we don't want to return a positive error. * It causes the aio code to not fall through to try the thread * way when you're talking to a regular file. */ if (!vn_isdisk(vp, &error)) { if (error == ENOTBLK) return (-1); else return (error); } if (vp->v_bufobj.bo_bsize == 0) return (-1); if (cb->aio_nbytes % vp->v_bufobj.bo_bsize) return (-1); if (cb->aio_nbytes > vp->v_rdev->si_iosize_max) return (-1); if (cb->aio_nbytes > MAXPHYS - (((vm_offset_t) cb->aio_buf) & PAGE_MASK)) return (-1); ki = p->p_aioinfo; if (ki->kaio_buffer_count >= ki->kaio_ballowed_count) return (-1); /* Create and build a buffer header for a transfer. */ bp = (struct buf *)getpbuf(NULL); BUF_KERNPROC(bp); AIO_LOCK(ki); ki->kaio_count++; ki->kaio_buffer_count++; lj = aiocbe->lio; if (lj) lj->lioj_count++; AIO_UNLOCK(ki); /* * Get a copy of the kva from the physical buffer. */ error = 0; bp->b_bcount = cb->aio_nbytes; bp->b_bufsize = cb->aio_nbytes; bp->b_iodone = aio_physwakeup; bp->b_saveaddr = bp->b_data; bp->b_data = (void *)(uintptr_t)cb->aio_buf; bp->b_offset = cb->aio_offset; bp->b_iooffset = cb->aio_offset; bp->b_blkno = btodb(cb->aio_offset); bp->b_iocmd = cb->aio_lio_opcode == LIO_WRITE ? BIO_WRITE : BIO_READ; /* * Bring buffer into kernel space. */ if (vmapbuf(bp) < 0) { error = EFAULT; goto doerror; } AIO_LOCK(ki); aiocbe->bp = bp; bp->b_caller1 = (void *)aiocbe; TAILQ_INSERT_TAIL(&ki->kaio_bufqueue, aiocbe, plist); TAILQ_INSERT_TAIL(&ki->kaio_all, aiocbe, allist); aiocbe->jobstate = JOBST_JOBQBUF; cb->_aiocb_private.status = cb->aio_nbytes; AIO_UNLOCK(ki); atomic_add_int(&num_queue_count, 1); atomic_add_int(&num_buf_aio, 1); bp->b_error = 0; TASK_INIT(&aiocbe->biotask, 0, biohelper, aiocbe); /* Perform transfer. */ dev_strategy(vp->v_rdev, bp); return (0); doerror: AIO_LOCK(ki); ki->kaio_count--; ki->kaio_buffer_count--; if (lj) lj->lioj_count--; aiocbe->bp = NULL; AIO_UNLOCK(ki); relpbuf(bp, NULL); return (error); } /* * Wake up aio requests that may be serviceable now. */ static void aio_swake_cb(struct socket *so, struct sockbuf *sb) { struct aiocblist *cb, *cbn; int opcode; if (sb == &so->so_snd) opcode = LIO_WRITE; else opcode = LIO_READ; SOCKBUF_LOCK(sb); sb->sb_flags &= ~SB_AIO; mtx_lock(&aio_job_mtx); TAILQ_FOREACH_SAFE(cb, &so->so_aiojobq, list, cbn) { if (opcode == cb->uaiocb.aio_lio_opcode) { if (cb->jobstate != JOBST_JOBQSOCK) panic("invalid queue value"); /* XXX * We don't have actual sockets backend yet, * so we simply move the requests to the generic * file I/O backend. */ TAILQ_REMOVE(&so->so_aiojobq, cb, list); TAILQ_INSERT_TAIL(&aio_jobs, cb, list); aio_kick_nowait(cb->userproc); } } mtx_unlock(&aio_job_mtx); SOCKBUF_UNLOCK(sb); } /* * Queue a new AIO request. Choosing either the threaded or direct physio VCHR * technique is done in this code. */ int aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, int type, int oldsigev) { struct proc *p = td->td_proc; struct file *fp; struct socket *so; struct aiocblist *aiocbe, *cb; struct kaioinfo *ki; struct kevent kev; struct sockbuf *sb; int opcode; int error; int fd, kqfd; int jid; if (p->p_aioinfo == NULL) aio_init_aioinfo(p); ki = p->p_aioinfo; suword(&job->_aiocb_private.status, -1); suword(&job->_aiocb_private.error, 0); suword(&job->_aiocb_private.kernelinfo, -1); if (num_queue_count >= max_queue_count || ki->kaio_count >= ki->kaio_qallowed_count) { suword(&job->_aiocb_private.error, EAGAIN); return (EAGAIN); } aiocbe = uma_zalloc(aiocb_zone, M_WAITOK | M_ZERO); aiocbe->inputcharge = 0; aiocbe->outputcharge = 0; knlist_init(&aiocbe->klist, AIO_MTX(ki), NULL, NULL, NULL); if (oldsigev) { bzero(&aiocbe->uaiocb, sizeof(struct aiocb)); error = copyin(job, &aiocbe->uaiocb, sizeof(struct oaiocb)); bcopy(&aiocbe->uaiocb.__spare__, &aiocbe->uaiocb.aio_sigevent, sizeof(struct osigevent)); } else { error = copyin(job, &aiocbe->uaiocb, sizeof(struct aiocb)); } if (error) { suword(&job->_aiocb_private.error, error); uma_zfree(aiocb_zone, aiocbe); return (error); } if (aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT && aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_SIGNAL && aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_THREAD_ID && aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_NONE) { suword(&job->_aiocb_private.error, EINVAL); uma_zfree(aiocb_zone, aiocbe); return (EINVAL); } if ((aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL || aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID) && !_SIG_VALID(aiocbe->uaiocb.aio_sigevent.sigev_signo)) { uma_zfree(aiocb_zone, aiocbe); return (EINVAL); } ksiginfo_init(&aiocbe->ksi); /* Save userspace address of the job info. */ aiocbe->uuaiocb = job; /* Get the opcode. */ if (type != LIO_NOP) aiocbe->uaiocb.aio_lio_opcode = type; opcode = aiocbe->uaiocb.aio_lio_opcode; /* Fetch the file object for the specified file descriptor. */ fd = aiocbe->uaiocb.aio_fildes; switch (opcode) { case LIO_WRITE: error = fget_write(td, fd, &fp); break; case LIO_READ: error = fget_read(td, fd, &fp); break; default: error = fget(td, fd, &fp); } if (error) { uma_zfree(aiocb_zone, aiocbe); suword(&job->_aiocb_private.error, error); return (error); } if (opcode == LIO_SYNC && fp->f_vnode == NULL) { error = EINVAL; goto aqueue_fail; } if (opcode != LIO_SYNC && aiocbe->uaiocb.aio_offset == -1LL) { error = EINVAL; goto aqueue_fail; } aiocbe->fd_file = fp; mtx_lock(&aio_job_mtx); jid = jobrefid++; aiocbe->seqno = jobseqno++; mtx_unlock(&aio_job_mtx); error = suword(&job->_aiocb_private.kernelinfo, jid); if (error) { error = EINVAL; goto aqueue_fail; } aiocbe->uaiocb._aiocb_private.kernelinfo = (void *)(intptr_t)jid; if (opcode == LIO_NOP) { fdrop(fp, td); uma_zfree(aiocb_zone, aiocbe); return (0); } if ((opcode != LIO_READ) && (opcode != LIO_WRITE) && (opcode != LIO_SYNC)) { error = EINVAL; goto aqueue_fail; } if (aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT) goto no_kqueue; kqfd = aiocbe->uaiocb.aio_sigevent.sigev_notify_kqueue; kev.ident = (uintptr_t)aiocbe->uuaiocb; kev.filter = EVFILT_AIO; kev.flags = EV_ADD | EV_ENABLE | EV_FLAG1; kev.data = (intptr_t)aiocbe; kev.udata = aiocbe->uaiocb.aio_sigevent.sigev_value.sival_ptr; error = kqfd_register(kqfd, &kev, td, 1); aqueue_fail: if (error) { fdrop(fp, td); uma_zfree(aiocb_zone, aiocbe); suword(&job->_aiocb_private.error, error); goto done; } no_kqueue: suword(&job->_aiocb_private.error, EINPROGRESS); aiocbe->uaiocb._aiocb_private.error = EINPROGRESS; aiocbe->userproc = p; aiocbe->cred = crhold(td->td_ucred); aiocbe->jobflags = 0; aiocbe->lio = lj; if (opcode == LIO_SYNC) goto queueit; if (fp->f_type == DTYPE_SOCKET) { /* * Alternate queueing for socket ops: Reach down into the * descriptor to get the socket data. Then check to see if the * socket is ready to be read or written (based on the requested * operation). * * If it is not ready for io, then queue the aiocbe on the * socket, and set the flags so we get a call when sbnotify() * happens. * * Note if opcode is neither LIO_WRITE nor LIO_READ we lock * and unlock the snd sockbuf for no reason. */ so = fp->f_data; sb = (opcode == LIO_READ) ? &so->so_rcv : &so->so_snd; SOCKBUF_LOCK(sb); if (((opcode == LIO_READ) && (!soreadable(so))) || ((opcode == LIO_WRITE) && (!sowriteable(so)))) { sb->sb_flags |= SB_AIO; mtx_lock(&aio_job_mtx); TAILQ_INSERT_TAIL(&so->so_aiojobq, aiocbe, list); mtx_unlock(&aio_job_mtx); AIO_LOCK(ki); TAILQ_INSERT_TAIL(&ki->kaio_all, aiocbe, allist); TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, aiocbe, plist); aiocbe->jobstate = JOBST_JOBQSOCK; ki->kaio_count++; if (lj) lj->lioj_count++; AIO_UNLOCK(ki); SOCKBUF_UNLOCK(sb); atomic_add_int(&num_queue_count, 1); error = 0; goto done; } SOCKBUF_UNLOCK(sb); } if ((error = aio_qphysio(p, aiocbe)) == 0) goto done; #if 0 if (error > 0) { aiocbe->uaiocb._aiocb_private.error = error; suword(&job->_aiocb_private.error, error); goto done; } #endif queueit: /* No buffer for daemon I/O. */ aiocbe->bp = NULL; atomic_add_int(&num_queue_count, 1); AIO_LOCK(ki); ki->kaio_count++; if (lj) lj->lioj_count++; TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, aiocbe, plist); TAILQ_INSERT_TAIL(&ki->kaio_all, aiocbe, allist); if (opcode == LIO_SYNC) { TAILQ_FOREACH(cb, &ki->kaio_jobqueue, plist) { if (cb->fd_file == aiocbe->fd_file && cb->uaiocb.aio_lio_opcode != LIO_SYNC && cb->seqno < aiocbe->seqno) { cb->jobflags |= AIOCBLIST_CHECKSYNC; aiocbe->pending++; } } TAILQ_FOREACH(cb, &ki->kaio_bufqueue, plist) { if (cb->fd_file == aiocbe->fd_file && cb->uaiocb.aio_lio_opcode != LIO_SYNC && cb->seqno < aiocbe->seqno) { cb->jobflags |= AIOCBLIST_CHECKSYNC; aiocbe->pending++; } } if (aiocbe->pending != 0) { TAILQ_INSERT_TAIL(&ki->kaio_syncqueue, aiocbe, list); aiocbe->jobstate = JOBST_JOBQSYNC; AIO_UNLOCK(ki); goto done; } } mtx_lock(&aio_job_mtx); TAILQ_INSERT_TAIL(&aio_jobs, aiocbe, list); aiocbe->jobstate = JOBST_JOBQGLOBAL; aio_kick_nowait(p); mtx_unlock(&aio_job_mtx); AIO_UNLOCK(ki); error = 0; done: return (error); } static void aio_kick_nowait(struct proc *userp) { struct kaioinfo *ki = userp->p_aioinfo; struct aiothreadlist *aiop; mtx_assert(&aio_job_mtx, MA_OWNED); if ((aiop = TAILQ_FIRST(&aio_freeproc)) != NULL) { TAILQ_REMOVE(&aio_freeproc, aiop, list); aiop->aiothreadflags &= ~AIOP_FREE; wakeup(aiop->aiothread); } else if (((num_aio_resv_start + num_aio_procs) < max_aio_procs) && ((ki->kaio_active_count + num_aio_resv_start) < ki->kaio_maxactive_count)) { taskqueue_enqueue(taskqueue_aiod_bio, &ki->kaio_task); } } static int aio_kick(struct proc *userp) { struct kaioinfo *ki = userp->p_aioinfo; struct aiothreadlist *aiop; int error, ret = 0; mtx_assert(&aio_job_mtx, MA_OWNED); retryproc: if ((aiop = TAILQ_FIRST(&aio_freeproc)) != NULL) { TAILQ_REMOVE(&aio_freeproc, aiop, list); aiop->aiothreadflags &= ~AIOP_FREE; wakeup(aiop->aiothread); } else if (((num_aio_resv_start + num_aio_procs) < max_aio_procs) && ((ki->kaio_active_count + num_aio_resv_start) < ki->kaio_maxactive_count)) { num_aio_resv_start++; mtx_unlock(&aio_job_mtx); error = aio_newproc(&num_aio_resv_start); mtx_lock(&aio_job_mtx); if (error) { num_aio_resv_start--; goto retryproc; } } else { ret = -1; } return (ret); } static void aio_kick_helper(void *context, int pending) { struct proc *userp = context; mtx_lock(&aio_job_mtx); while (--pending >= 0) { if (aio_kick(userp)) break; } mtx_unlock(&aio_job_mtx); } /* * Support the aio_return system call, as a side-effect, kernel resources are * released. */ int aio_return(struct thread *td, struct aio_return_args *uap) { struct proc *p = td->td_proc; struct aiocblist *cb; struct aiocb *uaiocb; struct kaioinfo *ki; int status, error; ki = p->p_aioinfo; if (ki == NULL) return (EINVAL); uaiocb = uap->aiocbp; AIO_LOCK(ki); TAILQ_FOREACH(cb, &ki->kaio_done, plist) { if (cb->uuaiocb == uaiocb) break; } if (cb != NULL) { MPASS(cb->jobstate == JOBST_JOBFINISHED); status = cb->uaiocb._aiocb_private.status; error = cb->uaiocb._aiocb_private.error; td->td_retval[0] = status; if (cb->uaiocb.aio_lio_opcode == LIO_WRITE) { p->p_stats->p_ru.ru_oublock += cb->outputcharge; cb->outputcharge = 0; } else if (cb->uaiocb.aio_lio_opcode == LIO_READ) { p->p_stats->p_ru.ru_inblock += cb->inputcharge; cb->inputcharge = 0; } aio_free_entry(cb); AIO_UNLOCK(ki); suword(&uaiocb->_aiocb_private.error, error); suword(&uaiocb->_aiocb_private.status, status); } else { error = EINVAL; AIO_UNLOCK(ki); } return (error); } /* * Allow a process to wakeup when any of the I/O requests are completed. */ int aio_suspend(struct thread *td, struct aio_suspend_args *uap) { struct proc *p = td->td_proc; struct timeval atv; struct timespec ts; struct aiocb *const *cbptr, *cbp; struct kaioinfo *ki; struct aiocblist *cb, *cbfirst; struct aiocb **ujoblist; int njoblist; int error; int timo; int i; if (uap->nent < 0 || uap->nent > AIO_LISTIO_MAX) return (EINVAL); timo = 0; if (uap->timeout) { /* Get timespec struct. */ if ((error = copyin(uap->timeout, &ts, sizeof(ts))) != 0) return (error); if (ts.tv_nsec < 0 || ts.tv_nsec >= 1000000000) return (EINVAL); TIMESPEC_TO_TIMEVAL(&atv, &ts); if (itimerfix(&atv)) return (EINVAL); timo = tvtohz(&atv); } ki = p->p_aioinfo; if (ki == NULL) return (EAGAIN); njoblist = 0; ujoblist = uma_zalloc(aiol_zone, M_WAITOK); cbptr = uap->aiocbp; for (i = 0; i < uap->nent; i++) { cbp = (struct aiocb *)(intptr_t)fuword(&cbptr[i]); if (cbp == 0) continue; ujoblist[njoblist] = cbp; njoblist++; } if (njoblist == 0) { uma_zfree(aiol_zone, ujoblist); return (0); } AIO_LOCK(ki); for (;;) { cbfirst = NULL; error = 0; TAILQ_FOREACH(cb, &ki->kaio_all, allist) { for (i = 0; i < njoblist; i++) { if (cb->uuaiocb == ujoblist[i]) { if (cbfirst == NULL) cbfirst = cb; if (cb->jobstate == JOBST_JOBFINISHED) goto RETURN; } } } /* All tasks were finished. */ if (cbfirst == NULL) break; ki->kaio_flags |= KAIO_WAKEUP; error = msleep(&p->p_aioinfo, AIO_MTX(ki), PRIBIO | PCATCH, "aiospn", timo); if (error == ERESTART) error = EINTR; if (error) break; } RETURN: AIO_UNLOCK(ki); uma_zfree(aiol_zone, ujoblist); return (error); } /* * aio_cancel cancels any non-physio aio operations not currently in * progress. */ int aio_cancel(struct thread *td, struct aio_cancel_args *uap) { struct proc *p = td->td_proc; struct kaioinfo *ki; struct aiocblist *cbe, *cbn; struct file *fp; struct socket *so; int error; int remove; int cancelled = 0; int notcancelled = 0; struct vnode *vp; /* Lookup file object. */ error = fget(td, uap->fd, &fp); if (error) return (error); ki = p->p_aioinfo; if (ki == NULL) goto done; if (fp->f_type == DTYPE_VNODE) { vp = fp->f_vnode; if (vn_isdisk(vp, &error)) { fdrop(fp, td); td->td_retval[0] = AIO_NOTCANCELED; return (0); } } AIO_LOCK(ki); TAILQ_FOREACH_SAFE(cbe, &ki->kaio_jobqueue, plist, cbn) { if ((uap->fd == cbe->uaiocb.aio_fildes) && ((uap->aiocbp == NULL) || (uap->aiocbp == cbe->uuaiocb))) { remove = 0; mtx_lock(&aio_job_mtx); if (cbe->jobstate == JOBST_JOBQGLOBAL) { TAILQ_REMOVE(&aio_jobs, cbe, list); remove = 1; } else if (cbe->jobstate == JOBST_JOBQSOCK) { MPASS(fp->f_type == DTYPE_SOCKET); so = fp->f_data; TAILQ_REMOVE(&so->so_aiojobq, cbe, list); remove = 1; } else if (cbe->jobstate == JOBST_JOBQSYNC) { TAILQ_REMOVE(&ki->kaio_syncqueue, cbe, list); remove = 1; } mtx_unlock(&aio_job_mtx); if (remove) { TAILQ_REMOVE(&ki->kaio_jobqueue, cbe, plist); cbe->uaiocb._aiocb_private.status = -1; cbe->uaiocb._aiocb_private.error = ECANCELED; aio_bio_done_notify(p, cbe, DONE_QUEUE); cancelled++; } else { notcancelled++; } if (uap->aiocbp != NULL) break; } } AIO_UNLOCK(ki); done: fdrop(fp, td); if (uap->aiocbp != NULL) { if (cancelled) { td->td_retval[0] = AIO_CANCELED; return (0); } } if (notcancelled) { td->td_retval[0] = AIO_NOTCANCELED; return (0); } if (cancelled) { td->td_retval[0] = AIO_CANCELED; return (0); } td->td_retval[0] = AIO_ALLDONE; return (0); } /* * aio_error is implemented in the kernel level for compatibility purposes only. * For a user mode async implementation, it would be best to do it in a userland * subroutine. */ int aio_error(struct thread *td, struct aio_error_args *uap) { struct proc *p = td->td_proc; struct aiocblist *cb; struct kaioinfo *ki; int status; ki = p->p_aioinfo; if (ki == NULL) { td->td_retval[0] = EINVAL; return (0); } AIO_LOCK(ki); TAILQ_FOREACH(cb, &ki->kaio_all, allist) { if (cb->uuaiocb == uap->aiocbp) { if (cb->jobstate == JOBST_JOBFINISHED) td->td_retval[0] = cb->uaiocb._aiocb_private.error; else td->td_retval[0] = EINPROGRESS; AIO_UNLOCK(ki); return (0); } } AIO_UNLOCK(ki); /* * Hack for failure of aio_aqueue. */ status = fuword(&uap->aiocbp->_aiocb_private.status); if (status == -1) { td->td_retval[0] = fuword(&uap->aiocbp->_aiocb_private.error); return (0); } td->td_retval[0] = EINVAL; return (0); } /* syscall - asynchronous read from a file (REALTIME) */ int oaio_read(struct thread *td, struct oaio_read_args *uap) { return aio_aqueue(td, (struct aiocb *)uap->aiocbp, NULL, LIO_READ, 1); } int aio_read(struct thread *td, struct aio_read_args *uap) { return aio_aqueue(td, uap->aiocbp, NULL, LIO_READ, 0); } /* syscall - asynchronous write to a file (REALTIME) */ int oaio_write(struct thread *td, struct oaio_write_args *uap) { return aio_aqueue(td, (struct aiocb *)uap->aiocbp, NULL, LIO_WRITE, 1); } int aio_write(struct thread *td, struct aio_write_args *uap) { return aio_aqueue(td, uap->aiocbp, NULL, LIO_WRITE, 0); } /* syscall - list directed I/O (REALTIME) */ int olio_listio(struct thread *td, struct olio_listio_args *uap) { return do_lio_listio(td, (struct lio_listio_args *)uap, 1); } /* syscall - list directed I/O (REALTIME) */ int lio_listio(struct thread *td, struct lio_listio_args *uap) { return do_lio_listio(td, uap, 0); } static int do_lio_listio(struct thread *td, struct lio_listio_args *uap, int oldsigev) { struct proc *p = td->td_proc; struct aiocb *iocb, * const *cbptr; struct kaioinfo *ki; struct aioliojob *lj; struct kevent kev; int nent; int error; int nerror; int i; if ((uap->mode != LIO_NOWAIT) && (uap->mode != LIO_WAIT)) return (EINVAL); nent = uap->nent; if (nent < 0 || nent > AIO_LISTIO_MAX) return (EINVAL); if (p->p_aioinfo == NULL) aio_init_aioinfo(p); ki = p->p_aioinfo; lj = uma_zalloc(aiolio_zone, M_WAITOK); lj->lioj_flags = 0; lj->lioj_count = 0; lj->lioj_finished_count = 0; knlist_init(&lj->klist, AIO_MTX(ki), NULL, NULL, NULL); ksiginfo_init(&lj->lioj_ksi); /* * Setup signal. */ if (uap->sig && (uap->mode == LIO_NOWAIT)) { bzero(&lj->lioj_signal, sizeof(&lj->lioj_signal)); error = copyin(uap->sig, &lj->lioj_signal, oldsigev ? sizeof(struct osigevent) : sizeof(struct sigevent)); if (error) { uma_zfree(aiolio_zone, lj); return (error); } if (lj->lioj_signal.sigev_notify == SIGEV_KEVENT) { /* Assume only new style KEVENT */ kev.filter = EVFILT_LIO; kev.flags = EV_ADD | EV_ENABLE | EV_FLAG1; kev.ident = (uintptr_t)uap->acb_list; /* something unique */ kev.data = (intptr_t)lj; /* pass user defined sigval data */ kev.udata = lj->lioj_signal.sigev_value.sival_ptr; error = kqfd_register( lj->lioj_signal.sigev_notify_kqueue, &kev, td, 1); if (error) { uma_zfree(aiolio_zone, lj); return (error); } } else if (lj->lioj_signal.sigev_notify == SIGEV_NONE) { ; } else if (lj->lioj_signal.sigev_notify == SIGEV_SIGNAL || lj->lioj_signal.sigev_notify == SIGEV_THREAD_ID) { if (!_SIG_VALID(lj->lioj_signal.sigev_signo)) { uma_zfree(aiolio_zone, lj); return EINVAL; } lj->lioj_flags |= LIOJ_SIGNAL; } else { uma_zfree(aiolio_zone, lj); return EINVAL; } } AIO_LOCK(ki); TAILQ_INSERT_TAIL(&ki->kaio_liojoblist, lj, lioj_list); /* * Add extra aiocb count to avoid the lio to be freed * by other threads doing aio_waitcomplete or aio_return, * and prevent event from being sent until we have queued * all tasks. */ lj->lioj_count = 1; AIO_UNLOCK(ki); /* * Get pointers to the list of I/O requests. */ nerror = 0; cbptr = uap->acb_list; for (i = 0; i < uap->nent; i++) { iocb = (struct aiocb *)(intptr_t)fuword(&cbptr[i]); if (((intptr_t)iocb != -1) && ((intptr_t)iocb != 0)) { error = aio_aqueue(td, iocb, lj, LIO_NOP, oldsigev); if (error != 0) nerror++; } } error = 0; AIO_LOCK(ki); if (uap->mode == LIO_WAIT) { while (lj->lioj_count - 1 != lj->lioj_finished_count) { ki->kaio_flags |= KAIO_WAKEUP; error = msleep(&p->p_aioinfo, AIO_MTX(ki), PRIBIO | PCATCH, "aiospn", 0); if (error == ERESTART) error = EINTR; if (error) break; } } else { if (lj->lioj_count - 1 == lj->lioj_finished_count) { if (lj->lioj_signal.sigev_notify == SIGEV_KEVENT) { lj->lioj_flags |= LIOJ_KEVENT_POSTED; KNOTE_LOCKED(&lj->klist, 1); } if ((lj->lioj_flags & (LIOJ_SIGNAL|LIOJ_SIGNAL_POSTED)) == LIOJ_SIGNAL && (lj->lioj_signal.sigev_notify == SIGEV_SIGNAL || lj->lioj_signal.sigev_notify == SIGEV_THREAD_ID)) { aio_sendsig(p, &lj->lioj_signal, &lj->lioj_ksi); lj->lioj_flags |= LIOJ_SIGNAL_POSTED; } } } lj->lioj_count--; if (lj->lioj_count == 0) { TAILQ_REMOVE(&ki->kaio_liojoblist, lj, lioj_list); knlist_delete(&lj->klist, curthread, 1); PROC_LOCK(p); sigqueue_take(&lj->lioj_ksi); PROC_UNLOCK(p); AIO_UNLOCK(ki); uma_zfree(aiolio_zone, lj); } else AIO_UNLOCK(ki); if (nerror) return (EIO); return (error); } /* * Called from interrupt thread for physio, we should return as fast * as possible, so we schedule a biohelper task. */ static void aio_physwakeup(struct buf *bp) { struct aiocblist *aiocbe; aiocbe = (struct aiocblist *)bp->b_caller1; taskqueue_enqueue(taskqueue_aiod_bio, &aiocbe->biotask); } /* * Task routine to perform heavy tasks, process wakeup, and signals. */ static void biohelper(void *context, int pending) { struct aiocblist *aiocbe = context; struct buf *bp; struct proc *userp; struct kaioinfo *ki; int nblks; bp = aiocbe->bp; userp = aiocbe->userproc; ki = userp->p_aioinfo; AIO_LOCK(ki); aiocbe->uaiocb._aiocb_private.status -= bp->b_resid; aiocbe->uaiocb._aiocb_private.error = 0; if (bp->b_ioflags & BIO_ERROR) aiocbe->uaiocb._aiocb_private.error = bp->b_error; nblks = btodb(aiocbe->uaiocb.aio_nbytes); if (aiocbe->uaiocb.aio_lio_opcode == LIO_WRITE) aiocbe->outputcharge += nblks; else aiocbe->inputcharge += nblks; aiocbe->bp = NULL; TAILQ_REMOVE(&userp->p_aioinfo->kaio_bufqueue, aiocbe, plist); ki->kaio_buffer_count--; aio_bio_done_notify(userp, aiocbe, DONE_BUF); AIO_UNLOCK(ki); /* Release mapping into kernel space. */ vunmapbuf(bp); relpbuf(bp, NULL); atomic_subtract_int(&num_buf_aio, 1); } /* syscall - wait for the next completion of an aio request */ int aio_waitcomplete(struct thread *td, struct aio_waitcomplete_args *uap) { struct proc *p = td->td_proc; struct timeval atv; struct timespec ts; struct kaioinfo *ki; struct aiocblist *cb; struct aiocb *uuaiocb; int error, status, timo; suword(uap->aiocbp, (long)NULL); timo = 0; if (uap->timeout) { /* Get timespec struct. */ error = copyin(uap->timeout, &ts, sizeof(ts)); if (error) return (error); if ((ts.tv_nsec < 0) || (ts.tv_nsec >= 1000000000)) return (EINVAL); TIMESPEC_TO_TIMEVAL(&atv, &ts); if (itimerfix(&atv)) return (EINVAL); timo = tvtohz(&atv); } if (p->p_aioinfo == NULL) aio_init_aioinfo(p); ki = p->p_aioinfo; error = 0; cb = NULL; AIO_LOCK(ki); while ((cb = TAILQ_FIRST(&ki->kaio_done)) == NULL) { ki->kaio_flags |= KAIO_WAKEUP; error = msleep(&p->p_aioinfo, AIO_MTX(ki), PRIBIO | PCATCH, "aiowc", timo); if (timo && error == ERESTART) error = EINTR; if (error) break; } if (cb != NULL) { MPASS(cb->jobstate == JOBST_JOBFINISHED); uuaiocb = cb->uuaiocb; status = cb->uaiocb._aiocb_private.status; error = cb->uaiocb._aiocb_private.error; td->td_retval[0] = status; if (cb->uaiocb.aio_lio_opcode == LIO_WRITE) { p->p_stats->p_ru.ru_oublock += cb->outputcharge; cb->outputcharge = 0; } else if (cb->uaiocb.aio_lio_opcode == LIO_READ) { p->p_stats->p_ru.ru_inblock += cb->inputcharge; cb->inputcharge = 0; } aio_free_entry(cb); AIO_UNLOCK(ki); suword(uap->aiocbp, (long)uuaiocb); suword(&uuaiocb->_aiocb_private.error, error); suword(&uuaiocb->_aiocb_private.status, status); } else AIO_UNLOCK(ki); return (error); } int aio_fsync(struct thread *td, struct aio_fsync_args *uap) { struct proc *p = td->td_proc; struct kaioinfo *ki; if (uap->op != O_SYNC) /* XXX lack of O_DSYNC */ return (EINVAL); ki = p->p_aioinfo; if (ki == NULL) aio_init_aioinfo(p); return aio_aqueue(td, uap->aiocbp, NULL, LIO_SYNC, 0); } /* kqueue attach function */ static int filt_aioattach(struct knote *kn) { struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_sdata; /* * The aiocbe pointer must be validated before using it, so * registration is restricted to the kernel; the user cannot * set EV_FLAG1. */ if ((kn->kn_flags & EV_FLAG1) == 0) return (EPERM); kn->kn_flags &= ~EV_FLAG1; knlist_add(&aiocbe->klist, kn, 0); return (0); } /* kqueue detach function */ static void filt_aiodetach(struct knote *kn) { struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_sdata; if (!knlist_empty(&aiocbe->klist)) knlist_remove(&aiocbe->klist, kn, 0); } /* kqueue filter function */ /*ARGSUSED*/ static int filt_aio(struct knote *kn, long hint) { struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_sdata; kn->kn_data = aiocbe->uaiocb._aiocb_private.error; if (aiocbe->jobstate != JOBST_JOBFINISHED) return (0); kn->kn_flags |= EV_EOF; return (1); } /* kqueue attach function */ static int filt_lioattach(struct knote *kn) { struct aioliojob * lj = (struct aioliojob *)kn->kn_sdata; /* * The aioliojob pointer must be validated before using it, so * registration is restricted to the kernel; the user cannot * set EV_FLAG1. */ if ((kn->kn_flags & EV_FLAG1) == 0) return (EPERM); kn->kn_flags &= ~EV_FLAG1; knlist_add(&lj->klist, kn, 0); return (0); } /* kqueue detach function */ static void filt_liodetach(struct knote *kn) { struct aioliojob * lj = (struct aioliojob *)kn->kn_sdata; if (!knlist_empty(&lj->klist)) knlist_remove(&lj->klist, kn, 0); } /* kqueue filter function */ /*ARGSUSED*/ static int filt_lio(struct knote *kn, long hint) { struct aioliojob * lj = (struct aioliojob *)kn->kn_sdata; return (lj->lioj_flags & LIOJ_KEVENT_POSTED); } Index: head/sys/security/mac/mac_posix_sem.c =================================================================== --- head/sys/security/mac/mac_posix_sem.c (revision 164183) +++ head/sys/security/mac/mac_posix_sem.c (revision 164184) @@ -1,174 +1,173 @@ /*- * Copyright (c) 2003-2005 SPARTA, Inc. * All rights reserved. * * This software was developed for the FreeBSD Project in part by Network * Associates Laboratories, the Security Research Division of Network * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), * as part of the DARPA CHATS research program. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_mac.h" #include "opt_posix.h" #include #include +#include #include #include #include #include #include - -#include #include #include #include static int mac_enforce_posix_sem = 1; SYSCTL_INT(_security_mac, OID_AUTO, enforce_posix_sem, CTLFLAG_RW, &mac_enforce_posix_sem, 0, "Enforce MAC policy on global POSIX semaphores"); TUNABLE_INT("security.mac.enforce_posix_sem", &mac_enforce_posix_sem); static struct label * mac_posix_sem_label_alloc(void) { struct label *label; label = mac_labelzone_alloc(M_WAITOK); MAC_PERFORM(init_posix_sem_label, label); return (label); } void mac_init_posix_sem(struct ksem *ksemptr) { ksemptr->ks_label = mac_posix_sem_label_alloc(); } static void mac_posix_sem_label_free(struct label *label) { MAC_PERFORM(destroy_posix_sem_label, label); } void mac_destroy_posix_sem(struct ksem *ksemptr) { mac_posix_sem_label_free(ksemptr->ks_label); ksemptr->ks_label = NULL; } void mac_create_posix_sem(struct ucred *cred, struct ksem *ksemptr) { MAC_PERFORM(create_posix_sem, cred, ksemptr, ksemptr->ks_label); } int mac_check_posix_sem_destroy(struct ucred *cred, struct ksem *ksemptr) { int error; if (!mac_enforce_posix_sem) return (0); MAC_CHECK(check_posix_sem_destroy, cred, ksemptr, ksemptr->ks_label); return(error); } int mac_check_posix_sem_open(struct ucred *cred, struct ksem *ksemptr) { int error; if (!mac_enforce_posix_sem) return (0); MAC_CHECK(check_posix_sem_open, cred, ksemptr, ksemptr->ks_label); return(error); } int mac_check_posix_sem_getvalue(struct ucred *cred, struct ksem *ksemptr) { int error; if (!mac_enforce_posix_sem) return (0); MAC_CHECK(check_posix_sem_getvalue, cred, ksemptr, ksemptr->ks_label); return(error); } int mac_check_posix_sem_post(struct ucred *cred, struct ksem *ksemptr) { int error; if (!mac_enforce_posix_sem) return (0); MAC_CHECK(check_posix_sem_post, cred, ksemptr, ksemptr->ks_label); return(error); } int mac_check_posix_sem_unlink(struct ucred *cred, struct ksem *ksemptr) { int error; if (!mac_enforce_posix_sem) return (0); MAC_CHECK(check_posix_sem_unlink, cred, ksemptr, ksemptr->ks_label); return(error); } int mac_check_posix_sem_wait(struct ucred *cred, struct ksem *ksemptr) { int error; if (!mac_enforce_posix_sem) return (0); MAC_CHECK(check_posix_sem_wait, cred, ksemptr, ksemptr->ks_label); return(error); } Index: head/sys/security/mac_biba/mac_biba.c =================================================================== --- head/sys/security/mac_biba/mac_biba.c (revision 164183) +++ head/sys/security/mac_biba/mac_biba.c (revision 164184) @@ -1,3228 +1,3227 @@ /*- * Copyright (c) 1999-2002 Robert N. M. Watson * Copyright (c) 2001-2005 McAfee, Inc. * All rights reserved. * * This software was developed by Robert Watson for the TrustedBSD Project. * * This software was developed for the FreeBSD Project in part by McAfee * Research, the Security Research Division of McAfee, Inc. under * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA * CHATS research program. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Developed by the TrustedBSD Project. * Biba fixed label mandatory integrity policy. */ #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include - -#include #include #include #include #include #include #include #include #include #include #include #include #include SYSCTL_DECL(_security_mac); SYSCTL_NODE(_security_mac, OID_AUTO, biba, CTLFLAG_RW, 0, "TrustedBSD mac_biba policy controls"); static int mac_biba_label_size = sizeof(struct mac_biba); SYSCTL_INT(_security_mac_biba, OID_AUTO, label_size, CTLFLAG_RD, &mac_biba_label_size, 0, "Size of struct mac_biba"); static int mac_biba_enabled = 1; SYSCTL_INT(_security_mac_biba, OID_AUTO, enabled, CTLFLAG_RW, &mac_biba_enabled, 0, "Enforce MAC/Biba policy"); TUNABLE_INT("security.mac.biba.enabled", &mac_biba_enabled); static int destroyed_not_inited; SYSCTL_INT(_security_mac_biba, OID_AUTO, destroyed_not_inited, CTLFLAG_RD, &destroyed_not_inited, 0, "Count of labels destroyed but not inited"); static int trust_all_interfaces = 0; SYSCTL_INT(_security_mac_biba, OID_AUTO, trust_all_interfaces, CTLFLAG_RD, &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/Biba"); TUNABLE_INT("security.mac.biba.trust_all_interfaces", &trust_all_interfaces); static char trusted_interfaces[128]; SYSCTL_STRING(_security_mac_biba, OID_AUTO, trusted_interfaces, CTLFLAG_RD, trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/Biba"); TUNABLE_STR("security.mac.biba.trusted_interfaces", trusted_interfaces, sizeof(trusted_interfaces)); static int max_compartments = MAC_BIBA_MAX_COMPARTMENTS; SYSCTL_INT(_security_mac_biba, OID_AUTO, max_compartments, CTLFLAG_RD, &max_compartments, 0, "Maximum supported compartments"); static int ptys_equal = 0; SYSCTL_INT(_security_mac_biba, OID_AUTO, ptys_equal, CTLFLAG_RW, &ptys_equal, 0, "Label pty devices as biba/equal on create"); TUNABLE_INT("security.mac.biba.ptys_equal", &ptys_equal); static int interfaces_equal; SYSCTL_INT(_security_mac_biba, OID_AUTO, interfaces_equal, CTLFLAG_RW, &interfaces_equal, 0, "Label network interfaces as biba/equal on create"); TUNABLE_INT("security.mac.biba.interfaces_equal", &interfaces_equal); static int revocation_enabled = 0; SYSCTL_INT(_security_mac_biba, OID_AUTO, revocation_enabled, CTLFLAG_RW, &revocation_enabled, 0, "Revoke access to objects on relabel"); TUNABLE_INT("security.mac.biba.revocation_enabled", &revocation_enabled); static int mac_biba_slot; #define SLOT(l) ((struct mac_biba *)LABEL_TO_SLOT((l), mac_biba_slot).l_ptr) #define SLOT_SET(l, val) (LABEL_TO_SLOT((l), mac_biba_slot).l_ptr = (val)) static uma_zone_t zone_biba; static __inline int biba_bit_set_empty(u_char *set) { int i; for (i = 0; i < MAC_BIBA_MAX_COMPARTMENTS >> 3; i++) if (set[i] != 0) return (0); return (1); } static struct mac_biba * biba_alloc(int flag) { return (uma_zalloc(zone_biba, flag | M_ZERO)); } static void biba_free(struct mac_biba *mac_biba) { if (mac_biba != NULL) uma_zfree(zone_biba, mac_biba); else atomic_add_int(&destroyed_not_inited, 1); } static int biba_atmostflags(struct mac_biba *mac_biba, int flags) { if ((mac_biba->mb_flags & flags) != mac_biba->mb_flags) return (EINVAL); return (0); } static int mac_biba_dominate_element(struct mac_biba_element *a, struct mac_biba_element *b) { int bit; switch (a->mbe_type) { case MAC_BIBA_TYPE_EQUAL: case MAC_BIBA_TYPE_HIGH: return (1); case MAC_BIBA_TYPE_LOW: switch (b->mbe_type) { case MAC_BIBA_TYPE_GRADE: case MAC_BIBA_TYPE_HIGH: return (0); case MAC_BIBA_TYPE_EQUAL: case MAC_BIBA_TYPE_LOW: return (1); default: panic("mac_biba_dominate_element: b->mbe_type invalid"); } case MAC_BIBA_TYPE_GRADE: switch (b->mbe_type) { case MAC_BIBA_TYPE_EQUAL: case MAC_BIBA_TYPE_LOW: return (1); case MAC_BIBA_TYPE_HIGH: return (0); case MAC_BIBA_TYPE_GRADE: for (bit = 1; bit <= MAC_BIBA_MAX_COMPARTMENTS; bit++) if (!MAC_BIBA_BIT_TEST(bit, a->mbe_compartments) && MAC_BIBA_BIT_TEST(bit, b->mbe_compartments)) return (0); return (a->mbe_grade >= b->mbe_grade); default: panic("mac_biba_dominate_element: b->mbe_type invalid"); } default: panic("mac_biba_dominate_element: a->mbe_type invalid"); } return (0); } static int mac_biba_subject_dominate_high(struct mac_biba *mac_biba) { struct mac_biba_element *element; KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0, ("mac_biba_effective_in_range: mac_biba not effective")); element = &mac_biba->mb_effective; return (element->mbe_type == MAC_BIBA_TYPE_EQUAL || element->mbe_type == MAC_BIBA_TYPE_HIGH); } static int mac_biba_range_in_range(struct mac_biba *rangea, struct mac_biba *rangeb) { return (mac_biba_dominate_element(&rangeb->mb_rangehigh, &rangea->mb_rangehigh) && mac_biba_dominate_element(&rangea->mb_rangelow, &rangeb->mb_rangelow)); } static int mac_biba_effective_in_range(struct mac_biba *effective, struct mac_biba *range) { KASSERT((effective->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0, ("mac_biba_effective_in_range: a not effective")); KASSERT((range->mb_flags & MAC_BIBA_FLAG_RANGE) != 0, ("mac_biba_effective_in_range: b not range")); return (mac_biba_dominate_element(&range->mb_rangehigh, &effective->mb_effective) && mac_biba_dominate_element(&effective->mb_effective, &range->mb_rangelow)); return (1); } static int mac_biba_dominate_effective(struct mac_biba *a, struct mac_biba *b) { KASSERT((a->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0, ("mac_biba_dominate_effective: a not effective")); KASSERT((b->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0, ("mac_biba_dominate_effective: b not effective")); return (mac_biba_dominate_element(&a->mb_effective, &b->mb_effective)); } static int mac_biba_equal_element(struct mac_biba_element *a, struct mac_biba_element *b) { if (a->mbe_type == MAC_BIBA_TYPE_EQUAL || b->mbe_type == MAC_BIBA_TYPE_EQUAL) return (1); return (a->mbe_type == b->mbe_type && a->mbe_grade == b->mbe_grade); } static int mac_biba_equal_effective(struct mac_biba *a, struct mac_biba *b) { KASSERT((a->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0, ("mac_biba_equal_effective: a not effective")); KASSERT((b->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0, ("mac_biba_equal_effective: b not effective")); return (mac_biba_equal_element(&a->mb_effective, &b->mb_effective)); } static int mac_biba_contains_equal(struct mac_biba *mac_biba) { if (mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) if (mac_biba->mb_effective.mbe_type == MAC_BIBA_TYPE_EQUAL) return (1); if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) { if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL) return (1); if (mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL) return (1); } return (0); } static int mac_biba_subject_privileged(struct mac_biba *mac_biba) { KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAGS_BOTH) == MAC_BIBA_FLAGS_BOTH, ("mac_biba_subject_privileged: subject doesn't have both labels")); /* If the effective is EQUAL, it's ok. */ if (mac_biba->mb_effective.mbe_type == MAC_BIBA_TYPE_EQUAL) return (0); /* If either range endpoint is EQUAL, it's ok. */ if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL || mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL) return (0); /* If the range is low-high, it's ok. */ if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_LOW && mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_HIGH) return (0); /* It's not ok. */ return (EPERM); } static int mac_biba_high_effective(struct mac_biba *mac_biba) { KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0, ("mac_biba_equal_effective: mac_biba not effective")); return (mac_biba->mb_effective.mbe_type == MAC_BIBA_TYPE_HIGH); } static int mac_biba_valid(struct mac_biba *mac_biba) { if (mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) { switch (mac_biba->mb_effective.mbe_type) { case MAC_BIBA_TYPE_GRADE: break; case MAC_BIBA_TYPE_EQUAL: case MAC_BIBA_TYPE_HIGH: case MAC_BIBA_TYPE_LOW: if (mac_biba->mb_effective.mbe_grade != 0 || !MAC_BIBA_BIT_SET_EMPTY( mac_biba->mb_effective.mbe_compartments)) return (EINVAL); break; default: return (EINVAL); } } else { if (mac_biba->mb_effective.mbe_type != MAC_BIBA_TYPE_UNDEF) return (EINVAL); } if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) { switch (mac_biba->mb_rangelow.mbe_type) { case MAC_BIBA_TYPE_GRADE: break; case MAC_BIBA_TYPE_EQUAL: case MAC_BIBA_TYPE_HIGH: case MAC_BIBA_TYPE_LOW: if (mac_biba->mb_rangelow.mbe_grade != 0 || !MAC_BIBA_BIT_SET_EMPTY( mac_biba->mb_rangelow.mbe_compartments)) return (EINVAL); break; default: return (EINVAL); } switch (mac_biba->mb_rangehigh.mbe_type) { case MAC_BIBA_TYPE_GRADE: break; case MAC_BIBA_TYPE_EQUAL: case MAC_BIBA_TYPE_HIGH: case MAC_BIBA_TYPE_LOW: if (mac_biba->mb_rangehigh.mbe_grade != 0 || !MAC_BIBA_BIT_SET_EMPTY( mac_biba->mb_rangehigh.mbe_compartments)) return (EINVAL); break; default: return (EINVAL); } if (!mac_biba_dominate_element(&mac_biba->mb_rangehigh, &mac_biba->mb_rangelow)) return (EINVAL); } else { if (mac_biba->mb_rangelow.mbe_type != MAC_BIBA_TYPE_UNDEF || mac_biba->mb_rangehigh.mbe_type != MAC_BIBA_TYPE_UNDEF) return (EINVAL); } return (0); } static void mac_biba_set_range(struct mac_biba *mac_biba, u_short typelow, u_short gradelow, u_char *compartmentslow, u_short typehigh, u_short gradehigh, u_char *compartmentshigh) { mac_biba->mb_rangelow.mbe_type = typelow; mac_biba->mb_rangelow.mbe_grade = gradelow; if (compartmentslow != NULL) memcpy(mac_biba->mb_rangelow.mbe_compartments, compartmentslow, sizeof(mac_biba->mb_rangelow.mbe_compartments)); mac_biba->mb_rangehigh.mbe_type = typehigh; mac_biba->mb_rangehigh.mbe_grade = gradehigh; if (compartmentshigh != NULL) memcpy(mac_biba->mb_rangehigh.mbe_compartments, compartmentshigh, sizeof(mac_biba->mb_rangehigh.mbe_compartments)); mac_biba->mb_flags |= MAC_BIBA_FLAG_RANGE; } static void mac_biba_set_effective(struct mac_biba *mac_biba, u_short type, u_short grade, u_char *compartments) { mac_biba->mb_effective.mbe_type = type; mac_biba->mb_effective.mbe_grade = grade; if (compartments != NULL) memcpy(mac_biba->mb_effective.mbe_compartments, compartments, sizeof(mac_biba->mb_effective.mbe_compartments)); mac_biba->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE; } static void mac_biba_copy_range(struct mac_biba *labelfrom, struct mac_biba *labelto) { KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_RANGE) != 0, ("mac_biba_copy_range: labelfrom not range")); labelto->mb_rangelow = labelfrom->mb_rangelow; labelto->mb_rangehigh = labelfrom->mb_rangehigh; labelto->mb_flags |= MAC_BIBA_FLAG_RANGE; } static void mac_biba_copy_effective(struct mac_biba *labelfrom, struct mac_biba *labelto) { KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0, ("mac_biba_copy_effective: labelfrom not effective")); labelto->mb_effective = labelfrom->mb_effective; labelto->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE; } static void mac_biba_copy(struct mac_biba *source, struct mac_biba *dest) { if (source->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) mac_biba_copy_effective(source, dest); if (source->mb_flags & MAC_BIBA_FLAG_RANGE) mac_biba_copy_range(source, dest); } /* * Policy module operations. */ static void mac_biba_init(struct mac_policy_conf *conf) { zone_biba = uma_zcreate("mac_biba", sizeof(struct mac_biba), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); } /* * Label operations. */ static void mac_biba_init_label(struct label *label) { SLOT_SET(label, biba_alloc(M_WAITOK)); } static int mac_biba_init_label_waitcheck(struct label *label, int flag) { SLOT_SET(label, biba_alloc(flag)); if (SLOT(label) == NULL) return (ENOMEM); return (0); } static void mac_biba_destroy_label(struct label *label) { biba_free(SLOT(label)); SLOT_SET(label, NULL); } /* * mac_biba_element_to_string() accepts an sbuf and Biba element. It * converts the Biba element to a string and stores the result in the * sbuf; if there isn't space in the sbuf, -1 is returned. */ static int mac_biba_element_to_string(struct sbuf *sb, struct mac_biba_element *element) { int i, first; switch (element->mbe_type) { case MAC_BIBA_TYPE_HIGH: return (sbuf_printf(sb, "high")); case MAC_BIBA_TYPE_LOW: return (sbuf_printf(sb, "low")); case MAC_BIBA_TYPE_EQUAL: return (sbuf_printf(sb, "equal")); case MAC_BIBA_TYPE_GRADE: if (sbuf_printf(sb, "%d", element->mbe_grade) == -1) return (-1); first = 1; for (i = 1; i <= MAC_BIBA_MAX_COMPARTMENTS; i++) { if (MAC_BIBA_BIT_TEST(i, element->mbe_compartments)) { if (first) { if (sbuf_putc(sb, ':') == -1) return (-1); if (sbuf_printf(sb, "%d", i) == -1) return (-1); first = 0; } else { if (sbuf_printf(sb, "+%d", i) == -1) return (-1); } } } return (0); default: panic("mac_biba_element_to_string: invalid type (%d)", element->mbe_type); } } /* * mac_biba_to_string() converts a Biba label to a string, and places * the results in the passed sbuf. It returns 0 on success, or EINVAL * if there isn't room in the sbuf. Note: the sbuf will be modified * even in a failure case, so the caller may need to revert the sbuf * by restoring the offset if that's undesired. */ static int mac_biba_to_string(struct sbuf *sb, struct mac_biba *mac_biba) { if (mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) { if (mac_biba_element_to_string(sb, &mac_biba->mb_effective) == -1) return (EINVAL); } if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) { if (sbuf_putc(sb, '(') == -1) return (EINVAL); if (mac_biba_element_to_string(sb, &mac_biba->mb_rangelow) == -1) return (EINVAL); if (sbuf_putc(sb, '-') == -1) return (EINVAL); if (mac_biba_element_to_string(sb, &mac_biba->mb_rangehigh) == -1) return (EINVAL); if (sbuf_putc(sb, ')') == -1) return (EINVAL); } return (0); } static int mac_biba_externalize_label(struct label *label, char *element_name, struct sbuf *sb, int *claimed) { struct mac_biba *mac_biba; if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0) return (0); (*claimed)++; mac_biba = SLOT(label); return (mac_biba_to_string(sb, mac_biba)); } static int mac_biba_parse_element(struct mac_biba_element *element, char *string) { char *compartment, *end, *grade; int value; if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) { element->mbe_type = MAC_BIBA_TYPE_HIGH; element->mbe_grade = MAC_BIBA_TYPE_UNDEF; } else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) { element->mbe_type = MAC_BIBA_TYPE_LOW; element->mbe_grade = MAC_BIBA_TYPE_UNDEF; } else if (strcmp(string, "equal") == 0 || strcmp(string, "eq") == 0) { element->mbe_type = MAC_BIBA_TYPE_EQUAL; element->mbe_grade = MAC_BIBA_TYPE_UNDEF; } else { element->mbe_type = MAC_BIBA_TYPE_GRADE; /* * Numeric grade piece of the element. */ grade = strsep(&string, ":"); value = strtol(grade, &end, 10); if (end == grade || *end != '\0') return (EINVAL); if (value < 0 || value > 65535) return (EINVAL); element->mbe_grade = value; /* * Optional compartment piece of the element. If none * are included, we assume that the label has no * compartments. */ if (string == NULL) return (0); if (*string == '\0') return (0); while ((compartment = strsep(&string, "+")) != NULL) { value = strtol(compartment, &end, 10); if (compartment == end || *end != '\0') return (EINVAL); if (value < 1 || value > MAC_BIBA_MAX_COMPARTMENTS) return (EINVAL); MAC_BIBA_BIT_SET(value, element->mbe_compartments); } } return (0); } /* * Note: destructively consumes the string, make a local copy before * calling if that's a problem. */ static int mac_biba_parse(struct mac_biba *mac_biba, char *string) { char *rangehigh, *rangelow, *effective; int error; effective = strsep(&string, "("); if (*effective == '\0') effective = NULL; if (string != NULL) { rangelow = strsep(&string, "-"); if (string == NULL) return (EINVAL); rangehigh = strsep(&string, ")"); if (string == NULL) return (EINVAL); if (*string != '\0') return (EINVAL); } else { rangelow = NULL; rangehigh = NULL; } KASSERT((rangelow != NULL && rangehigh != NULL) || (rangelow == NULL && rangehigh == NULL), ("mac_biba_parse: range mismatch")); bzero(mac_biba, sizeof(*mac_biba)); if (effective != NULL) { error = mac_biba_parse_element(&mac_biba->mb_effective, effective); if (error) return (error); mac_biba->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE; } if (rangelow != NULL) { error = mac_biba_parse_element(&mac_biba->mb_rangelow, rangelow); if (error) return (error); error = mac_biba_parse_element(&mac_biba->mb_rangehigh, rangehigh); if (error) return (error); mac_biba->mb_flags |= MAC_BIBA_FLAG_RANGE; } error = mac_biba_valid(mac_biba); if (error) return (error); return (0); } static int mac_biba_internalize_label(struct label *label, char *element_name, char *element_data, int *claimed) { struct mac_biba *mac_biba, mac_biba_temp; int error; if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0) return (0); (*claimed)++; error = mac_biba_parse(&mac_biba_temp, element_data); if (error) return (error); mac_biba = SLOT(label); *mac_biba = mac_biba_temp; return (0); } static void mac_biba_copy_label(struct label *src, struct label *dest) { *SLOT(dest) = *SLOT(src); } /* * Labeling event operations: file system objects, and things that look * a lot like file system objects. */ static void mac_biba_create_devfs_device(struct ucred *cred, struct mount *mp, struct cdev *dev, struct devfs_dirent *devfs_dirent, struct label *label) { struct mac_biba *mac_biba; int biba_type; mac_biba = SLOT(label); if (strcmp(dev->si_name, "null") == 0 || strcmp(dev->si_name, "zero") == 0 || strcmp(dev->si_name, "random") == 0 || strncmp(dev->si_name, "fd/", strlen("fd/")) == 0) biba_type = MAC_BIBA_TYPE_EQUAL; else if (ptys_equal && (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 || strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0)) biba_type = MAC_BIBA_TYPE_EQUAL; else biba_type = MAC_BIBA_TYPE_HIGH; mac_biba_set_effective(mac_biba, biba_type, 0, NULL); } static void mac_biba_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label) { struct mac_biba *mac_biba; mac_biba = SLOT(label); mac_biba_set_effective(mac_biba, MAC_BIBA_TYPE_HIGH, 0, NULL); } static void mac_biba_create_devfs_symlink(struct ucred *cred, struct mount *mp, struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de, struct label *delabel) { struct mac_biba *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(delabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_mount(struct ucred *cred, struct mount *mp, struct label *mntlabel, struct label *fslabel) { struct mac_biba *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(mntlabel); mac_biba_copy_effective(source, dest); dest = SLOT(fslabel); mac_biba_copy_effective(source, dest); } static void mac_biba_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct label *label) { struct mac_biba *source, *dest; source = SLOT(label); dest = SLOT(vnodelabel); mac_biba_copy(source, dest); } static void mac_biba_update_devfsdirent(struct mount *mp, struct devfs_dirent *devfs_dirent, struct label *direntlabel, struct vnode *vp, struct label *vnodelabel) { struct mac_biba *source, *dest; source = SLOT(vnodelabel); dest = SLOT(direntlabel); mac_biba_copy(source, dest); } static void mac_biba_associate_vnode_devfs(struct mount *mp, struct label *fslabel, struct devfs_dirent *de, struct label *delabel, struct vnode *vp, struct label *vlabel) { struct mac_biba *source, *dest; source = SLOT(delabel); dest = SLOT(vlabel); mac_biba_copy_effective(source, dest); } static int mac_biba_associate_vnode_extattr(struct mount *mp, struct label *fslabel, struct vnode *vp, struct label *vlabel) { struct mac_biba temp, *source, *dest; int buflen, error; source = SLOT(fslabel); dest = SLOT(vlabel); buflen = sizeof(temp); bzero(&temp, buflen); error = vn_extattr_get(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE, MAC_BIBA_EXTATTR_NAME, &buflen, (char *) &temp, curthread); if (error == ENOATTR || error == EOPNOTSUPP) { /* Fall back to the fslabel. */ mac_biba_copy_effective(source, dest); return (0); } else if (error) return (error); if (buflen != sizeof(temp)) { printf("mac_biba_associate_vnode_extattr: bad size %d\n", buflen); return (EPERM); } if (mac_biba_valid(&temp) != 0) { printf("mac_biba_associate_vnode_extattr: invalid\n"); return (EPERM); } if ((temp.mb_flags & MAC_BIBA_FLAGS_BOTH) != MAC_BIBA_FLAG_EFFECTIVE) { printf("mac_biba_associate_vnode_extattr: not effective\n"); return (EPERM); } mac_biba_copy_effective(&temp, dest); return (0); } static void mac_biba_associate_vnode_singlelabel(struct mount *mp, struct label *fslabel, struct vnode *vp, struct label *vlabel) { struct mac_biba *source, *dest; source = SLOT(fslabel); dest = SLOT(vlabel); mac_biba_copy_effective(source, dest); } static int mac_biba_create_vnode_extattr(struct ucred *cred, struct mount *mp, struct label *fslabel, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *vlabel, struct componentname *cnp) { struct mac_biba *source, *dest, temp; size_t buflen; int error; buflen = sizeof(temp); bzero(&temp, buflen); source = SLOT(cred->cr_label); dest = SLOT(vlabel); mac_biba_copy_effective(source, &temp); error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE, MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread); if (error == 0) mac_biba_copy_effective(source, dest); return (error); } static int mac_biba_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, struct label *vlabel, struct label *intlabel) { struct mac_biba *source, temp; size_t buflen; int error; buflen = sizeof(temp); bzero(&temp, buflen); source = SLOT(intlabel); if ((source->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) == 0) return (0); mac_biba_copy_effective(source, &temp); error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE, MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread); return (error); } /* * Labeling event operations: IPC object. */ static void mac_biba_create_inpcb_from_socket(struct socket *so, struct label *solabel, struct inpcb *inp, struct label *inplabel) { struct mac_biba *source, *dest; source = SLOT(solabel); dest = SLOT(inplabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_mbuf_from_socket(struct socket *so, struct label *socketlabel, struct mbuf *m, struct label *mbuflabel) { struct mac_biba *source, *dest; source = SLOT(socketlabel); dest = SLOT(mbuflabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_socket(struct ucred *cred, struct socket *socket, struct label *socketlabel) { struct mac_biba *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(socketlabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_pipe(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { struct mac_biba *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(pipelabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_posix_sem(struct ucred *cred, struct ksem *ksemptr, struct label *ks_label) { struct mac_biba *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(ks_label); mac_biba_copy_effective(source, dest); } static void mac_biba_create_socket_from_socket(struct socket *oldsocket, struct label *oldsocketlabel, struct socket *newsocket, struct label *newsocketlabel) { struct mac_biba *source, *dest; source = SLOT(oldsocketlabel); dest = SLOT(newsocketlabel); mac_biba_copy_effective(source, dest); } static void mac_biba_relabel_socket(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct label *newlabel) { struct mac_biba *source, *dest; source = SLOT(newlabel); dest = SLOT(socketlabel); mac_biba_copy(source, dest); } static void mac_biba_relabel_pipe(struct ucred *cred, struct pipepair *pp, struct label *pipelabel, struct label *newlabel) { struct mac_biba *source, *dest; source = SLOT(newlabel); dest = SLOT(pipelabel); mac_biba_copy(source, dest); } static void mac_biba_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel, struct socket *socket, struct label *socketpeerlabel) { struct mac_biba *source, *dest; source = SLOT(mbuflabel); dest = SLOT(socketpeerlabel); mac_biba_copy_effective(source, dest); } /* * Labeling event operations: System V IPC objects. */ static void mac_biba_create_sysv_msgmsg(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqlabel, struct msg *msgptr, struct label *msglabel) { struct mac_biba *source, *dest; /* Ignore the msgq label */ source = SLOT(cred->cr_label); dest = SLOT(msglabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_sysv_msgqueue(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqlabel) { struct mac_biba *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(msqlabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_sysv_sem(struct ucred *cred, struct semid_kernel *semakptr, struct label *semalabel) { struct mac_biba *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(semalabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_sysv_shm(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmlabel) { struct mac_biba *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(shmlabel); mac_biba_copy_effective(source, dest); } /* * Labeling event operations: network objects. */ static void mac_biba_set_socket_peer_from_socket(struct socket *oldsocket, struct label *oldsocketlabel, struct socket *newsocket, struct label *newsocketpeerlabel) { struct mac_biba *source, *dest; source = SLOT(oldsocketlabel); dest = SLOT(newsocketpeerlabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d, struct label *bpflabel) { struct mac_biba *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(bpflabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel) { char tifname[IFNAMSIZ], *p, *q; char tiflist[sizeof(trusted_interfaces)]; struct mac_biba *dest; int len, type; dest = SLOT(ifnetlabel); if (ifnet->if_type == IFT_LOOP || interfaces_equal != 0) { type = MAC_BIBA_TYPE_EQUAL; goto set; } if (trust_all_interfaces) { type = MAC_BIBA_TYPE_HIGH; goto set; } type = MAC_BIBA_TYPE_LOW; if (trusted_interfaces[0] == '\0' || !strvalid(trusted_interfaces, sizeof(trusted_interfaces))) goto set; bzero(tiflist, sizeof(tiflist)); for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++) if(*p != ' ' && *p != '\t') *q = *p; for (p = q = tiflist;; p++) { if (*p == ',' || *p == '\0') { len = p - q; if (len < IFNAMSIZ) { bzero(tifname, sizeof(tifname)); bcopy(q, tifname, len); if (strcmp(tifname, ifnet->if_xname) == 0) { type = MAC_BIBA_TYPE_HIGH; break; } } else { *p = '\0'; printf("mac_biba warning: interface name " "\"%s\" is too long (must be < %d)\n", q, IFNAMSIZ); } if (*p == '\0') break; q = p + 1; } } set: mac_biba_set_effective(dest, type, 0, NULL); mac_biba_set_range(dest, type, 0, NULL, type, 0, NULL); } static void mac_biba_create_ipq(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel) { struct mac_biba *source, *dest; source = SLOT(fragmentlabel); dest = SLOT(ipqlabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel, struct mbuf *datagram, struct label *datagramlabel) { struct mac_biba *source, *dest; source = SLOT(ipqlabel); dest = SLOT(datagramlabel); /* Just use the head, since we require them all to match. */ mac_biba_copy_effective(source, dest); } static void mac_biba_create_fragment(struct mbuf *datagram, struct label *datagramlabel, struct mbuf *fragment, struct label *fragmentlabel) { struct mac_biba *source, *dest; source = SLOT(datagramlabel); dest = SLOT(fragmentlabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_mbuf_from_inpcb(struct inpcb *inp, struct label *inplabel, struct mbuf *m, struct label *mlabel) { struct mac_biba *source, *dest; source = SLOT(inplabel); dest = SLOT(mlabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *mbuf, struct label *mbuflabel) { struct mac_biba *dest; dest = SLOT(mbuflabel); mac_biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL); } static void mac_biba_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel, struct mbuf *mbuf, struct label *mbuflabel) { struct mac_biba *source, *dest; source = SLOT(bpflabel); dest = SLOT(mbuflabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *m, struct label *mbuflabel) { struct mac_biba *source, *dest; source = SLOT(ifnetlabel); dest = SLOT(mbuflabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *newmbuf, struct label *newmbuflabel) { struct mac_biba *source, *dest; source = SLOT(oldmbuflabel); dest = SLOT(newmbuflabel); mac_biba_copy_effective(source, dest); } static void mac_biba_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel, struct mbuf *newmbuf, struct label *newmbuflabel) { struct mac_biba *source, *dest; source = SLOT(oldmbuflabel); dest = SLOT(newmbuflabel); mac_biba_copy_effective(source, dest); } static int mac_biba_fragment_match(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel) { struct mac_biba *a, *b; a = SLOT(ipqlabel); b = SLOT(fragmentlabel); return (mac_biba_equal_effective(a, b)); } static void mac_biba_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet, struct label *ifnetlabel, struct label *newlabel) { struct mac_biba *source, *dest; source = SLOT(newlabel); dest = SLOT(ifnetlabel); mac_biba_copy(source, dest); } static void mac_biba_update_ipq(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel) { /* NOOP: we only accept matching labels, so no need to update */ } static void mac_biba_inpcb_sosetlabel(struct socket *so, struct label *solabel, struct inpcb *inp, struct label *inplabel) { struct mac_biba *source, *dest; source = SLOT(solabel); dest = SLOT(inplabel); mac_biba_copy(source, dest); } static void mac_biba_create_mbuf_from_firewall(struct mbuf *m, struct label *label) { struct mac_biba *dest; dest = SLOT(label); /* XXX: where is the label for the firewall really comming from? */ mac_biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL); } /* * Labeling event operations: processes. */ static void mac_biba_create_proc0(struct ucred *cred) { struct mac_biba *dest; dest = SLOT(cred->cr_label); mac_biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL); mac_biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL, MAC_BIBA_TYPE_HIGH, 0, NULL); } static void mac_biba_create_proc1(struct ucred *cred) { struct mac_biba *dest; dest = SLOT(cred->cr_label); mac_biba_set_effective(dest, MAC_BIBA_TYPE_HIGH, 0, NULL); mac_biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL, MAC_BIBA_TYPE_HIGH, 0, NULL); } static void mac_biba_relabel_cred(struct ucred *cred, struct label *newlabel) { struct mac_biba *source, *dest; source = SLOT(newlabel); dest = SLOT(cred->cr_label); mac_biba_copy(source, dest); } /* * Label cleanup/flush operations */ static void mac_biba_cleanup_sysv_msgmsg(struct label *msglabel) { bzero(SLOT(msglabel), sizeof(struct mac_biba)); } static void mac_biba_cleanup_sysv_msgqueue(struct label *msqlabel) { bzero(SLOT(msqlabel), sizeof(struct mac_biba)); } static void mac_biba_cleanup_sysv_sem(struct label *semalabel) { bzero(SLOT(semalabel), sizeof(struct mac_biba)); } static void mac_biba_cleanup_sysv_shm(struct label *shmlabel) { bzero(SLOT(shmlabel), sizeof(struct mac_biba)); } /* * Access control checks. */ static int mac_biba_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel, struct ifnet *ifnet, struct label *ifnetlabel) { struct mac_biba *a, *b; if (!mac_biba_enabled) return (0); a = SLOT(bpflabel); b = SLOT(ifnetlabel); if (mac_biba_equal_effective(a, b)) return (0); return (EACCES); } static int mac_biba_check_cred_relabel(struct ucred *cred, struct label *newlabel) { struct mac_biba *subj, *new; int error; subj = SLOT(cred->cr_label); new = SLOT(newlabel); /* * If there is a Biba label update for the credential, it may * be an update of the effective, range, or both. */ error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH); if (error) return (error); /* * If the Biba label is to be changed, authorize as appropriate. */ if (new->mb_flags & MAC_BIBA_FLAGS_BOTH) { /* * If the change request modifies both the Biba label * effective and range, check that the new effective will be * in the new range. */ if ((new->mb_flags & MAC_BIBA_FLAGS_BOTH) == MAC_BIBA_FLAGS_BOTH && !mac_biba_effective_in_range(new, new)) return (EINVAL); /* * To change the Biba effective label on a credential, the * new effective label must be in the current range. */ if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE && !mac_biba_effective_in_range(new, subj)) return (EPERM); /* * To change the Biba range on a credential, the new * range label must be in the current range. */ if (new->mb_flags & MAC_BIBA_FLAG_RANGE && !mac_biba_range_in_range(new, subj)) return (EPERM); /* * To have EQUAL in any component of the new credential * Biba label, the subject must already have EQUAL in * their label. */ if (mac_biba_contains_equal(new)) { error = mac_biba_subject_privileged(subj); if (error) return (error); } } return (0); } static int mac_biba_check_cred_visible(struct ucred *u1, struct ucred *u2) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(u1->cr_label); obj = SLOT(u2->cr_label); /* XXX: range */ if (!mac_biba_dominate_effective(obj, subj)) return (ESRCH); return (0); } static int mac_biba_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet, struct label *ifnetlabel, struct label *newlabel) { struct mac_biba *subj, *new; int error; subj = SLOT(cred->cr_label); new = SLOT(newlabel); /* * If there is a Biba label update for the interface, it may * be an update of the effective, range, or both. */ error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH); if (error) return (error); /* * Relabling network interfaces requires Biba privilege. */ error = mac_biba_subject_privileged(subj); if (error) return (error); return (0); } static int mac_biba_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *m, struct label *mbuflabel) { struct mac_biba *p, *i; if (!mac_biba_enabled) return (0); p = SLOT(mbuflabel); i = SLOT(ifnetlabel); return (mac_biba_effective_in_range(p, i) ? 0 : EACCES); } static int mac_biba_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel, struct mbuf *m, struct label *mlabel) { struct mac_biba *p, *i; if (!mac_biba_enabled) return (0); p = SLOT(mlabel); i = SLOT(inplabel); return (mac_biba_equal_effective(p, i) ? 0 : EACCES); } static int mac_biba_check_sysv_msgrcv(struct ucred *cred, struct msg *msgptr, struct label *msglabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(msglabel); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_sysv_msgrmid(struct ucred *cred, struct msg *msgptr, struct label *msglabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(msglabel); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_sysv_msqget(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(msqklabel); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_sysv_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(msqklabel); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_sysv_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(msqklabel); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_sysv_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel, int cmd) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(msqklabel); switch(cmd) { case IPC_RMID: case IPC_SET: if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); break; case IPC_STAT: if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); break; default: return (EACCES); } return (0); } static int mac_biba_check_sysv_semctl(struct ucred *cred, struct semid_kernel *semakptr, struct label *semaklabel, int cmd) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(semaklabel); switch(cmd) { case IPC_RMID: case IPC_SET: case SETVAL: case SETALL: if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); break; case IPC_STAT: case GETVAL: case GETPID: case GETNCNT: case GETZCNT: case GETALL: if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); break; default: return (EACCES); } return (0); } static int mac_biba_check_sysv_semget(struct ucred *cred, struct semid_kernel *semakptr, struct label *semaklabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(semaklabel); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_sysv_semop(struct ucred *cred, struct semid_kernel *semakptr, struct label *semaklabel, size_t accesstype) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(semaklabel); if (accesstype & SEM_R) if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); if (accesstype & SEM_A) if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_sysv_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmseglabel, int shmflg) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(shmseglabel); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); if ((shmflg & SHM_RDONLY) == 0) { if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); } return (0); } static int mac_biba_check_sysv_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmseglabel, int cmd) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(shmseglabel); switch(cmd) { case IPC_RMID: case IPC_SET: if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); break; case IPC_STAT: case SHM_STAT: if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); break; default: return (EACCES); } return (0); } static int mac_biba_check_sysv_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmseglabel, int shmflg) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(shmseglabel); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_kld_load(struct ucred *cred, struct vnode *vp, struct label *label) { struct mac_biba *subj, *obj; int error; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); error = mac_biba_subject_privileged(subj); if (error) return (error); obj = SLOT(label); if (!mac_biba_high_effective(obj)) return (EACCES); return (0); } static int mac_biba_check_kld_unload(struct ucred *cred) { struct mac_biba *subj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); return (mac_biba_subject_privileged(subj)); } static int mac_biba_check_mount_stat(struct ucred *cred, struct mount *mp, struct label *mntlabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(mntlabel); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp, struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data) { if(!mac_biba_enabled) return (0); /* XXX: This will be implemented soon... */ return (0); } static int mac_biba_check_pipe_poll(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT((pipelabel)); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_pipe_read(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT((pipelabel)); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_pipe_relabel(struct ucred *cred, struct pipepair *pp, struct label *pipelabel, struct label *newlabel) { struct mac_biba *subj, *obj, *new; int error; new = SLOT(newlabel); subj = SLOT(cred->cr_label); obj = SLOT(pipelabel); /* * If there is a Biba label update for a pipe, it must be a * effective update. */ error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE); if (error) return (error); /* * To perform a relabel of a pipe (Biba label or not), Biba must * authorize the relabel. */ if (!mac_biba_effective_in_range(obj, subj)) return (EPERM); /* * If the Biba label is to be changed, authorize as appropriate. */ if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) { /* * To change the Biba label on a pipe, the new pipe label * must be in the subject range. */ if (!mac_biba_effective_in_range(new, subj)) return (EPERM); /* * To change the Biba label on a pipe to be EQUAL, the * subject must have appropriate privilege. */ if (mac_biba_contains_equal(new)) { error = mac_biba_subject_privileged(subj); if (error) return (error); } } return (0); } static int mac_biba_check_pipe_stat(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT((pipelabel)); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_pipe_write(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT((pipelabel)); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_posix_sem_write(struct ucred *cred, struct ksem *ksemptr, struct label *ks_label) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(ks_label); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_posix_sem_rdonly(struct ucred *cred, struct ksem *ksemptr, struct label *ks_label) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(ks_label); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_proc_debug(struct ucred *cred, struct proc *proc) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(proc->p_ucred->cr_label); /* XXX: range checks */ if (!mac_biba_dominate_effective(obj, subj)) return (ESRCH); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_proc_sched(struct ucred *cred, struct proc *proc) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(proc->p_ucred->cr_label); /* XXX: range checks */ if (!mac_biba_dominate_effective(obj, subj)) return (ESRCH); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(proc->p_ucred->cr_label); /* XXX: range checks */ if (!mac_biba_dominate_effective(obj, subj)) return (ESRCH); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_socket_deliver(struct socket *so, struct label *socketlabel, struct mbuf *m, struct label *mbuflabel) { struct mac_biba *p, *s; if (!mac_biba_enabled) return (0); p = SLOT(mbuflabel); s = SLOT(socketlabel); return (mac_biba_equal_effective(p, s) ? 0 : EACCES); } static int mac_biba_check_socket_relabel(struct ucred *cred, struct socket *so, struct label *socketlabel, struct label *newlabel) { struct mac_biba *subj, *obj, *new; int error; new = SLOT(newlabel); subj = SLOT(cred->cr_label); obj = SLOT(socketlabel); /* * If there is a Biba label update for the socket, it may be * an update of effective. */ error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE); if (error) return (error); /* * To relabel a socket, the old socket effective must be in the subject * range. */ if (!mac_biba_effective_in_range(obj, subj)) return (EPERM); /* * If the Biba label is to be changed, authorize as appropriate. */ if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) { /* * To relabel a socket, the new socket effective must be in * the subject range. */ if (!mac_biba_effective_in_range(new, subj)) return (EPERM); /* * To change the Biba label on the socket to contain EQUAL, * the subject must have appropriate privilege. */ if (mac_biba_contains_equal(new)) { error = mac_biba_subject_privileged(subj); if (error) return (error); } } return (0); } static int mac_biba_check_socket_visible(struct ucred *cred, struct socket *socket, struct label *socketlabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(socketlabel); if (!mac_biba_dominate_effective(obj, subj)) return (ENOENT); return (0); } static int mac_biba_check_sysarch_ioperm(struct ucred *cred) { struct mac_biba *subj; int error; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); error = mac_biba_subject_privileged(subj); if (error) return (error); return (0); } static int mac_biba_check_system_acct(struct ucred *cred, struct vnode *vp, struct label *label) { struct mac_biba *subj, *obj; int error; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); error = mac_biba_subject_privileged(subj); if (error) return (error); if (label == NULL) return (0); obj = SLOT(label); if (!mac_biba_high_effective(obj)) return (EACCES); return (0); } static int mac_biba_check_system_settime(struct ucred *cred) { struct mac_biba *subj; int error; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); error = mac_biba_subject_privileged(subj); if (error) return (error); return (0); } static int mac_biba_check_system_swapon(struct ucred *cred, struct vnode *vp, struct label *label) { struct mac_biba *subj, *obj; int error; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); error = mac_biba_subject_privileged(subj); if (error) return (error); if (!mac_biba_high_effective(obj)) return (EACCES); return (0); } static int mac_biba_check_system_swapoff(struct ucred *cred, struct vnode *vp, struct label *label) { struct mac_biba *subj, *obj; int error; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); error = mac_biba_subject_privileged(subj); if (error) return (error); return (0); } static int mac_biba_check_system_sysctl(struct ucred *cred, struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req) { struct mac_biba *subj; int error; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); /* * Treat sysctl variables without CTLFLAG_ANYBODY flag as * biba/high, but also require privilege to change them. */ if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) { if (!mac_biba_subject_dominate_high(subj)) return (EACCES); error = mac_biba_subject_privileged(subj); if (error) return (error); } return (0); } static int mac_biba_check_vnode_chdir(struct ucred *cred, struct vnode *dvp, struct label *dlabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_vnode_chroot(struct ucred *cred, struct vnode *dvp, struct label *dlabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_vnode_create(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct componentname *cnp, struct vattr *vap) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); obj = SLOT(label); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace, const char *name) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_vnode_exec(struct ucred *cred, struct vnode *vp, struct label *label, struct image_params *imgp, struct label *execlabel) { struct mac_biba *subj, *obj, *exec; int error; if (execlabel != NULL) { /* * We currently don't permit labels to be changed at * exec-time as part of Biba, so disallow non-NULL * Biba label elements in the execlabel. */ exec = SLOT(execlabel); error = biba_atmostflags(exec, 0); if (error) return (error); } if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_vnode_getacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace, const char *name, struct uio *uio) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_vnode_link(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); obj = SLOT(label); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_vnode_listextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct componentname *cnp) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_vnode_mmap(struct ucred *cred, struct vnode *vp, struct label *label, int prot, int flags) { struct mac_biba *subj, *obj; /* * Rely on the use of open()-time protections to handle * non-revocation cases. */ if (!mac_biba_enabled || !revocation_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); } if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) { if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); } return (0); } static int mac_biba_check_vnode_open(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, int acc_mode) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(vnodelabel); /* XXX privilege override for admin? */ if (acc_mode & (VREAD | VEXEC | VSTAT)) { if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); } if (acc_mode & (VWRITE | VAPPEND | VADMIN)) { if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); } return (0); } static int mac_biba_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label) { struct mac_biba *subj, *obj; if (!mac_biba_enabled || !revocation_enabled) return (0); subj = SLOT(active_cred->cr_label); obj = SLOT(label); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label) { struct mac_biba *subj, *obj; if (!mac_biba_enabled || !revocation_enabled) return (0); subj = SLOT(active_cred->cr_label); obj = SLOT(label); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_vnode_readdir(struct ucred *cred, struct vnode *dvp, struct label *dlabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_vnode_readlink(struct ucred *cred, struct vnode *vp, struct label *label) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_vnode_relabel(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct label *newlabel) { struct mac_biba *old, *new, *subj; int error; old = SLOT(vnodelabel); new = SLOT(newlabel); subj = SLOT(cred->cr_label); /* * If there is a Biba label update for the vnode, it must be a * effective label. */ error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE); if (error) return (error); /* * To perform a relabel of the vnode (Biba label or not), Biba must * authorize the relabel. */ if (!mac_biba_effective_in_range(old, subj)) return (EPERM); /* * If the Biba label is to be changed, authorize as appropriate. */ if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) { /* * To change the Biba label on a vnode, the new vnode label * must be in the subject range. */ if (!mac_biba_effective_in_range(new, subj)) return (EPERM); /* * To change the Biba label on the vnode to be EQUAL, * the subject must have appropriate privilege. */ if (mac_biba_contains_equal(new)) { error = mac_biba_subject_privileged(subj); if (error) return (error); } } return (0); } static int mac_biba_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); obj = SLOT(label); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, int samedir, struct componentname *cnp) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); if (vp != NULL) { obj = SLOT(label); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); } return (0); } static int mac_biba_check_vnode_revoke(struct ucred *cred, struct vnode *vp, struct label *label) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_vnode_setacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type, struct acl *acl) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, int attrnamespace, const char *name, struct uio *uio) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(vnodelabel); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); /* XXX: protect the MAC EA in a special way? */ return (0); } static int mac_biba_check_vnode_setflags(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, u_long flags) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(vnodelabel); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_vnode_setmode(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, mode_t mode) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(vnodelabel); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_vnode_setowner(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, uid_t uid, gid_t gid) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(vnodelabel); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct timespec atime, struct timespec mtime) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(vnodelabel); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_biba_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *vnodelabel) { struct mac_biba *subj, *obj; if (!mac_biba_enabled) return (0); subj = SLOT(active_cred->cr_label); obj = SLOT(vnodelabel); if (!mac_biba_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_biba_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label) { struct mac_biba *subj, *obj; if (!mac_biba_enabled || !revocation_enabled) return (0); subj = SLOT(active_cred->cr_label); obj = SLOT(label); if (!mac_biba_dominate_effective(subj, obj)) return (EACCES); return (0); } static void mac_biba_associate_nfsd_label(struct ucred *cred) { struct mac_biba *label; label = SLOT(cred->cr_label); mac_biba_set_effective(label, MAC_BIBA_TYPE_LOW, 0, NULL); mac_biba_set_range(label, MAC_BIBA_TYPE_LOW, 0, NULL, MAC_BIBA_TYPE_HIGH, 0, NULL); } static struct mac_policy_ops mac_biba_ops = { .mpo_init = mac_biba_init, .mpo_init_bpfdesc_label = mac_biba_init_label, .mpo_init_cred_label = mac_biba_init_label, .mpo_init_devfsdirent_label = mac_biba_init_label, .mpo_init_ifnet_label = mac_biba_init_label, .mpo_init_inpcb_label = mac_biba_init_label_waitcheck, .mpo_init_sysv_msgmsg_label = mac_biba_init_label, .mpo_init_sysv_msgqueue_label = mac_biba_init_label, .mpo_init_sysv_sem_label = mac_biba_init_label, .mpo_init_sysv_shm_label = mac_biba_init_label, .mpo_init_ipq_label = mac_biba_init_label_waitcheck, .mpo_init_mbuf_label = mac_biba_init_label_waitcheck, .mpo_init_mount_label = mac_biba_init_label, .mpo_init_mount_fs_label = mac_biba_init_label, .mpo_init_pipe_label = mac_biba_init_label, .mpo_init_posix_sem_label = mac_biba_init_label, .mpo_init_socket_label = mac_biba_init_label_waitcheck, .mpo_init_socket_peer_label = mac_biba_init_label_waitcheck, .mpo_init_vnode_label = mac_biba_init_label, .mpo_destroy_bpfdesc_label = mac_biba_destroy_label, .mpo_destroy_cred_label = mac_biba_destroy_label, .mpo_destroy_devfsdirent_label = mac_biba_destroy_label, .mpo_destroy_ifnet_label = mac_biba_destroy_label, .mpo_destroy_inpcb_label = mac_biba_destroy_label, .mpo_destroy_sysv_msgmsg_label = mac_biba_destroy_label, .mpo_destroy_sysv_msgqueue_label = mac_biba_destroy_label, .mpo_destroy_sysv_sem_label = mac_biba_destroy_label, .mpo_destroy_sysv_shm_label = mac_biba_destroy_label, .mpo_destroy_ipq_label = mac_biba_destroy_label, .mpo_destroy_mbuf_label = mac_biba_destroy_label, .mpo_destroy_mount_label = mac_biba_destroy_label, .mpo_destroy_mount_fs_label = mac_biba_destroy_label, .mpo_destroy_pipe_label = mac_biba_destroy_label, .mpo_destroy_posix_sem_label = mac_biba_destroy_label, .mpo_destroy_socket_label = mac_biba_destroy_label, .mpo_destroy_socket_peer_label = mac_biba_destroy_label, .mpo_destroy_vnode_label = mac_biba_destroy_label, .mpo_copy_cred_label = mac_biba_copy_label, .mpo_copy_ifnet_label = mac_biba_copy_label, .mpo_copy_mbuf_label = mac_biba_copy_label, .mpo_copy_pipe_label = mac_biba_copy_label, .mpo_copy_socket_label = mac_biba_copy_label, .mpo_copy_vnode_label = mac_biba_copy_label, .mpo_externalize_cred_label = mac_biba_externalize_label, .mpo_externalize_ifnet_label = mac_biba_externalize_label, .mpo_externalize_pipe_label = mac_biba_externalize_label, .mpo_externalize_socket_label = mac_biba_externalize_label, .mpo_externalize_socket_peer_label = mac_biba_externalize_label, .mpo_externalize_vnode_label = mac_biba_externalize_label, .mpo_internalize_cred_label = mac_biba_internalize_label, .mpo_internalize_ifnet_label = mac_biba_internalize_label, .mpo_internalize_pipe_label = mac_biba_internalize_label, .mpo_internalize_socket_label = mac_biba_internalize_label, .mpo_internalize_vnode_label = mac_biba_internalize_label, .mpo_create_devfs_device = mac_biba_create_devfs_device, .mpo_create_devfs_directory = mac_biba_create_devfs_directory, .mpo_create_devfs_symlink = mac_biba_create_devfs_symlink, .mpo_create_mount = mac_biba_create_mount, .mpo_relabel_vnode = mac_biba_relabel_vnode, .mpo_update_devfsdirent = mac_biba_update_devfsdirent, .mpo_associate_vnode_devfs = mac_biba_associate_vnode_devfs, .mpo_associate_vnode_extattr = mac_biba_associate_vnode_extattr, .mpo_associate_vnode_singlelabel = mac_biba_associate_vnode_singlelabel, .mpo_create_vnode_extattr = mac_biba_create_vnode_extattr, .mpo_setlabel_vnode_extattr = mac_biba_setlabel_vnode_extattr, .mpo_create_mbuf_from_socket = mac_biba_create_mbuf_from_socket, .mpo_create_pipe = mac_biba_create_pipe, .mpo_create_posix_sem = mac_biba_create_posix_sem, .mpo_create_socket = mac_biba_create_socket, .mpo_create_socket_from_socket = mac_biba_create_socket_from_socket, .mpo_relabel_pipe = mac_biba_relabel_pipe, .mpo_relabel_socket = mac_biba_relabel_socket, .mpo_set_socket_peer_from_mbuf = mac_biba_set_socket_peer_from_mbuf, .mpo_set_socket_peer_from_socket = mac_biba_set_socket_peer_from_socket, .mpo_create_bpfdesc = mac_biba_create_bpfdesc, .mpo_create_datagram_from_ipq = mac_biba_create_datagram_from_ipq, .mpo_create_fragment = mac_biba_create_fragment, .mpo_create_ifnet = mac_biba_create_ifnet, .mpo_create_inpcb_from_socket = mac_biba_create_inpcb_from_socket, .mpo_create_sysv_msgmsg = mac_biba_create_sysv_msgmsg, .mpo_create_sysv_msgqueue = mac_biba_create_sysv_msgqueue, .mpo_create_sysv_sem = mac_biba_create_sysv_sem, .mpo_create_sysv_shm = mac_biba_create_sysv_shm, .mpo_create_ipq = mac_biba_create_ipq, .mpo_create_mbuf_from_inpcb = mac_biba_create_mbuf_from_inpcb, .mpo_create_mbuf_linklayer = mac_biba_create_mbuf_linklayer, .mpo_create_mbuf_from_bpfdesc = mac_biba_create_mbuf_from_bpfdesc, .mpo_create_mbuf_from_ifnet = mac_biba_create_mbuf_from_ifnet, .mpo_create_mbuf_multicast_encap = mac_biba_create_mbuf_multicast_encap, .mpo_create_mbuf_netlayer = mac_biba_create_mbuf_netlayer, .mpo_fragment_match = mac_biba_fragment_match, .mpo_relabel_ifnet = mac_biba_relabel_ifnet, .mpo_update_ipq = mac_biba_update_ipq, .mpo_inpcb_sosetlabel = mac_biba_inpcb_sosetlabel, .mpo_create_proc0 = mac_biba_create_proc0, .mpo_create_proc1 = mac_biba_create_proc1, .mpo_relabel_cred = mac_biba_relabel_cred, .mpo_cleanup_sysv_msgmsg = mac_biba_cleanup_sysv_msgmsg, .mpo_cleanup_sysv_msgqueue = mac_biba_cleanup_sysv_msgqueue, .mpo_cleanup_sysv_sem = mac_biba_cleanup_sysv_sem, .mpo_cleanup_sysv_shm = mac_biba_cleanup_sysv_shm, .mpo_check_bpfdesc_receive = mac_biba_check_bpfdesc_receive, .mpo_check_cred_relabel = mac_biba_check_cred_relabel, .mpo_check_cred_visible = mac_biba_check_cred_visible, .mpo_check_ifnet_relabel = mac_biba_check_ifnet_relabel, .mpo_check_ifnet_transmit = mac_biba_check_ifnet_transmit, .mpo_check_inpcb_deliver = mac_biba_check_inpcb_deliver, .mpo_check_sysv_msgrcv = mac_biba_check_sysv_msgrcv, .mpo_check_sysv_msgrmid = mac_biba_check_sysv_msgrmid, .mpo_check_sysv_msqget = mac_biba_check_sysv_msqget, .mpo_check_sysv_msqsnd = mac_biba_check_sysv_msqsnd, .mpo_check_sysv_msqrcv = mac_biba_check_sysv_msqrcv, .mpo_check_sysv_msqctl = mac_biba_check_sysv_msqctl, .mpo_check_sysv_semctl = mac_biba_check_sysv_semctl, .mpo_check_sysv_semget = mac_biba_check_sysv_semget, .mpo_check_sysv_semop = mac_biba_check_sysv_semop, .mpo_check_sysv_shmat = mac_biba_check_sysv_shmat, .mpo_check_sysv_shmctl = mac_biba_check_sysv_shmctl, .mpo_check_sysv_shmget = mac_biba_check_sysv_shmget, .mpo_check_kld_load = mac_biba_check_kld_load, .mpo_check_kld_unload = mac_biba_check_kld_unload, .mpo_check_mount_stat = mac_biba_check_mount_stat, .mpo_check_pipe_ioctl = mac_biba_check_pipe_ioctl, .mpo_check_pipe_poll = mac_biba_check_pipe_poll, .mpo_check_pipe_read = mac_biba_check_pipe_read, .mpo_check_pipe_relabel = mac_biba_check_pipe_relabel, .mpo_check_pipe_stat = mac_biba_check_pipe_stat, .mpo_check_pipe_write = mac_biba_check_pipe_write, .mpo_check_posix_sem_destroy = mac_biba_check_posix_sem_write, .mpo_check_posix_sem_getvalue = mac_biba_check_posix_sem_rdonly, .mpo_check_posix_sem_open = mac_biba_check_posix_sem_write, .mpo_check_posix_sem_post = mac_biba_check_posix_sem_write, .mpo_check_posix_sem_unlink = mac_biba_check_posix_sem_write, .mpo_check_posix_sem_wait = mac_biba_check_posix_sem_write, .mpo_check_proc_debug = mac_biba_check_proc_debug, .mpo_check_proc_sched = mac_biba_check_proc_sched, .mpo_check_proc_signal = mac_biba_check_proc_signal, .mpo_check_socket_deliver = mac_biba_check_socket_deliver, .mpo_check_socket_relabel = mac_biba_check_socket_relabel, .mpo_check_socket_visible = mac_biba_check_socket_visible, .mpo_check_sysarch_ioperm = mac_biba_check_sysarch_ioperm, .mpo_check_system_acct = mac_biba_check_system_acct, .mpo_check_system_settime = mac_biba_check_system_settime, .mpo_check_system_swapon = mac_biba_check_system_swapon, .mpo_check_system_swapoff = mac_biba_check_system_swapoff, .mpo_check_system_sysctl = mac_biba_check_system_sysctl, .mpo_check_vnode_access = mac_biba_check_vnode_open, .mpo_check_vnode_chdir = mac_biba_check_vnode_chdir, .mpo_check_vnode_chroot = mac_biba_check_vnode_chroot, .mpo_check_vnode_create = mac_biba_check_vnode_create, .mpo_check_vnode_delete = mac_biba_check_vnode_delete, .mpo_check_vnode_deleteacl = mac_biba_check_vnode_deleteacl, .mpo_check_vnode_deleteextattr = mac_biba_check_vnode_deleteextattr, .mpo_check_vnode_exec = mac_biba_check_vnode_exec, .mpo_check_vnode_getacl = mac_biba_check_vnode_getacl, .mpo_check_vnode_getextattr = mac_biba_check_vnode_getextattr, .mpo_check_vnode_link = mac_biba_check_vnode_link, .mpo_check_vnode_listextattr = mac_biba_check_vnode_listextattr, .mpo_check_vnode_lookup = mac_biba_check_vnode_lookup, .mpo_check_vnode_mmap = mac_biba_check_vnode_mmap, .mpo_check_vnode_open = mac_biba_check_vnode_open, .mpo_check_vnode_poll = mac_biba_check_vnode_poll, .mpo_check_vnode_read = mac_biba_check_vnode_read, .mpo_check_vnode_readdir = mac_biba_check_vnode_readdir, .mpo_check_vnode_readlink = mac_biba_check_vnode_readlink, .mpo_check_vnode_relabel = mac_biba_check_vnode_relabel, .mpo_check_vnode_rename_from = mac_biba_check_vnode_rename_from, .mpo_check_vnode_rename_to = mac_biba_check_vnode_rename_to, .mpo_check_vnode_revoke = mac_biba_check_vnode_revoke, .mpo_check_vnode_setacl = mac_biba_check_vnode_setacl, .mpo_check_vnode_setextattr = mac_biba_check_vnode_setextattr, .mpo_check_vnode_setflags = mac_biba_check_vnode_setflags, .mpo_check_vnode_setmode = mac_biba_check_vnode_setmode, .mpo_check_vnode_setowner = mac_biba_check_vnode_setowner, .mpo_check_vnode_setutimes = mac_biba_check_vnode_setutimes, .mpo_check_vnode_stat = mac_biba_check_vnode_stat, .mpo_check_vnode_write = mac_biba_check_vnode_write, .mpo_associate_nfsd_label = mac_biba_associate_nfsd_label, .mpo_create_mbuf_from_firewall = mac_biba_create_mbuf_from_firewall, }; MAC_POLICY_SET(&mac_biba_ops, mac_biba, "TrustedBSD MAC/Biba", MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS, &mac_biba_slot); Index: head/sys/security/mac_mls/mac_mls.c =================================================================== --- head/sys/security/mac_mls/mac_mls.c (revision 164183) +++ head/sys/security/mac_mls/mac_mls.c (revision 164184) @@ -1,2990 +1,2989 @@ /*- * Copyright (c) 1999-2002 Robert N. M. Watson * Copyright (c) 2001-2005 McAfee, Inc. * All rights reserved. * * This software was developed by Robert Watson for the TrustedBSD Project. * * This software was developed for the FreeBSD Project in part by McAfee * Research, the Security Research Division of McAfee, Inc. under * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA * CHATS research program. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Developed by the TrustedBSD Project. * MLS fixed label mandatory confidentiality policy. */ #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include - -#include #include #include #include #include #include #include #include #include #include #include #include #include SYSCTL_DECL(_security_mac); SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0, "TrustedBSD mac_mls policy controls"); static int mac_mls_label_size = sizeof(struct mac_mls); SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD, &mac_mls_label_size, 0, "Size of struct mac_mls"); static int mac_mls_enabled = 1; SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW, &mac_mls_enabled, 0, "Enforce MAC/MLS policy"); TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled); static int destroyed_not_inited; SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD, &destroyed_not_inited, 0, "Count of labels destroyed but not inited"); static int ptys_equal = 0; SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW, &ptys_equal, 0, "Label pty devices as mls/equal on create"); TUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal); static int revocation_enabled = 0; SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW, &revocation_enabled, 0, "Revoke access to objects on relabel"); TUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled); static int max_compartments = MAC_MLS_MAX_COMPARTMENTS; SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD, &max_compartments, 0, "Maximum compartments the policy supports"); static int mac_mls_slot; #define SLOT(l) ((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr) #define SLOT_SET(l, val) (LABEL_TO_SLOT((l), mac_mls_slot).l_ptr = (val)) static uma_zone_t zone_mls; static __inline int mls_bit_set_empty(u_char *set) { int i; for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++) if (set[i] != 0) return (0); return (1); } static struct mac_mls * mls_alloc(int flag) { return (uma_zalloc(zone_mls, flag | M_ZERO)); } static void mls_free(struct mac_mls *mac_mls) { if (mac_mls != NULL) uma_zfree(zone_mls, mac_mls); else atomic_add_int(&destroyed_not_inited, 1); } static int mls_atmostflags(struct mac_mls *mac_mls, int flags) { if ((mac_mls->mm_flags & flags) != mac_mls->mm_flags) return (EINVAL); return (0); } static int mac_mls_dominate_element(struct mac_mls_element *a, struct mac_mls_element *b) { int bit; switch (a->mme_type) { case MAC_MLS_TYPE_EQUAL: case MAC_MLS_TYPE_HIGH: return (1); case MAC_MLS_TYPE_LOW: switch (b->mme_type) { case MAC_MLS_TYPE_LEVEL: case MAC_MLS_TYPE_HIGH: return (0); case MAC_MLS_TYPE_EQUAL: case MAC_MLS_TYPE_LOW: return (1); default: panic("mac_mls_dominate_element: b->mme_type invalid"); } case MAC_MLS_TYPE_LEVEL: switch (b->mme_type) { case MAC_MLS_TYPE_EQUAL: case MAC_MLS_TYPE_LOW: return (1); case MAC_MLS_TYPE_HIGH: return (0); case MAC_MLS_TYPE_LEVEL: for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++) if (!MAC_MLS_BIT_TEST(bit, a->mme_compartments) && MAC_MLS_BIT_TEST(bit, b->mme_compartments)) return (0); return (a->mme_level >= b->mme_level); default: panic("mac_mls_dominate_element: b->mme_type invalid"); } default: panic("mac_mls_dominate_element: a->mme_type invalid"); } return (0); } static int mac_mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb) { return (mac_mls_dominate_element(&rangeb->mm_rangehigh, &rangea->mm_rangehigh) && mac_mls_dominate_element(&rangea->mm_rangelow, &rangeb->mm_rangelow)); } static int mac_mls_effective_in_range(struct mac_mls *effective, struct mac_mls *range) { KASSERT((effective->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0, ("mac_mls_effective_in_range: a not effective")); KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0, ("mac_mls_effective_in_range: b not range")); return (mac_mls_dominate_element(&range->mm_rangehigh, &effective->mm_effective) && mac_mls_dominate_element(&effective->mm_effective, &range->mm_rangelow)); return (1); } static int mac_mls_dominate_effective(struct mac_mls *a, struct mac_mls *b) { KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0, ("mac_mls_dominate_effective: a not effective")); KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0, ("mac_mls_dominate_effective: b not effective")); return (mac_mls_dominate_element(&a->mm_effective, &b->mm_effective)); } static int mac_mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b) { if (a->mme_type == MAC_MLS_TYPE_EQUAL || b->mme_type == MAC_MLS_TYPE_EQUAL) return (1); return (a->mme_type == b->mme_type && a->mme_level == b->mme_level); } static int mac_mls_equal_effective(struct mac_mls *a, struct mac_mls *b) { KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0, ("mac_mls_equal_effective: a not effective")); KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0, ("mac_mls_equal_effective: b not effective")); return (mac_mls_equal_element(&a->mm_effective, &b->mm_effective)); } static int mac_mls_contains_equal(struct mac_mls *mac_mls) { if (mac_mls->mm_flags & MAC_MLS_FLAG_EFFECTIVE) if (mac_mls->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL) return (1); if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) { if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL) return (1); if (mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL) return (1); } return (0); } static int mac_mls_subject_privileged(struct mac_mls *mac_mls) { KASSERT((mac_mls->mm_flags & MAC_MLS_FLAGS_BOTH) == MAC_MLS_FLAGS_BOTH, ("mac_mls_subject_privileged: subject doesn't have both labels")); /* If the effective is EQUAL, it's ok. */ if (mac_mls->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL) return (0); /* If either range endpoint is EQUAL, it's ok. */ if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL || mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL) return (0); /* If the range is low-high, it's ok. */ if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW && mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH) return (0); /* It's not ok. */ return (EPERM); } static int mac_mls_valid(struct mac_mls *mac_mls) { if (mac_mls->mm_flags & MAC_MLS_FLAG_EFFECTIVE) { switch (mac_mls->mm_effective.mme_type) { case MAC_MLS_TYPE_LEVEL: break; case MAC_MLS_TYPE_EQUAL: case MAC_MLS_TYPE_HIGH: case MAC_MLS_TYPE_LOW: if (mac_mls->mm_effective.mme_level != 0 || !MAC_MLS_BIT_SET_EMPTY( mac_mls->mm_effective.mme_compartments)) return (EINVAL); break; default: return (EINVAL); } } else { if (mac_mls->mm_effective.mme_type != MAC_MLS_TYPE_UNDEF) return (EINVAL); } if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) { switch (mac_mls->mm_rangelow.mme_type) { case MAC_MLS_TYPE_LEVEL: break; case MAC_MLS_TYPE_EQUAL: case MAC_MLS_TYPE_HIGH: case MAC_MLS_TYPE_LOW: if (mac_mls->mm_rangelow.mme_level != 0 || !MAC_MLS_BIT_SET_EMPTY( mac_mls->mm_rangelow.mme_compartments)) return (EINVAL); break; default: return (EINVAL); } switch (mac_mls->mm_rangehigh.mme_type) { case MAC_MLS_TYPE_LEVEL: break; case MAC_MLS_TYPE_EQUAL: case MAC_MLS_TYPE_HIGH: case MAC_MLS_TYPE_LOW: if (mac_mls->mm_rangehigh.mme_level != 0 || !MAC_MLS_BIT_SET_EMPTY( mac_mls->mm_rangehigh.mme_compartments)) return (EINVAL); break; default: return (EINVAL); } if (!mac_mls_dominate_element(&mac_mls->mm_rangehigh, &mac_mls->mm_rangelow)) return (EINVAL); } else { if (mac_mls->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF || mac_mls->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF) return (EINVAL); } return (0); } static void mac_mls_set_range(struct mac_mls *mac_mls, u_short typelow, u_short levellow, u_char *compartmentslow, u_short typehigh, u_short levelhigh, u_char *compartmentshigh) { mac_mls->mm_rangelow.mme_type = typelow; mac_mls->mm_rangelow.mme_level = levellow; if (compartmentslow != NULL) memcpy(mac_mls->mm_rangelow.mme_compartments, compartmentslow, sizeof(mac_mls->mm_rangelow.mme_compartments)); mac_mls->mm_rangehigh.mme_type = typehigh; mac_mls->mm_rangehigh.mme_level = levelhigh; if (compartmentshigh != NULL) memcpy(mac_mls->mm_rangehigh.mme_compartments, compartmentshigh, sizeof(mac_mls->mm_rangehigh.mme_compartments)); mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE; } static void mac_mls_set_effective(struct mac_mls *mac_mls, u_short type, u_short level, u_char *compartments) { mac_mls->mm_effective.mme_type = type; mac_mls->mm_effective.mme_level = level; if (compartments != NULL) memcpy(mac_mls->mm_effective.mme_compartments, compartments, sizeof(mac_mls->mm_effective.mme_compartments)); mac_mls->mm_flags |= MAC_MLS_FLAG_EFFECTIVE; } static void mac_mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto) { KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0, ("mac_mls_copy_range: labelfrom not range")); labelto->mm_rangelow = labelfrom->mm_rangelow; labelto->mm_rangehigh = labelfrom->mm_rangehigh; labelto->mm_flags |= MAC_MLS_FLAG_RANGE; } static void mac_mls_copy_effective(struct mac_mls *labelfrom, struct mac_mls *labelto) { KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0, ("mac_mls_copy_effective: labelfrom not effective")); labelto->mm_effective = labelfrom->mm_effective; labelto->mm_flags |= MAC_MLS_FLAG_EFFECTIVE; } static void mac_mls_copy(struct mac_mls *source, struct mac_mls *dest) { if (source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) mac_mls_copy_effective(source, dest); if (source->mm_flags & MAC_MLS_FLAG_RANGE) mac_mls_copy_range(source, dest); } /* * Policy module operations. */ static void mac_mls_init(struct mac_policy_conf *conf) { zone_mls = uma_zcreate("mac_mls", sizeof(struct mac_mls), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); } /* * Label operations. */ static void mac_mls_init_label(struct label *label) { SLOT_SET(label, mls_alloc(M_WAITOK)); } static int mac_mls_init_label_waitcheck(struct label *label, int flag) { SLOT_SET(label, mls_alloc(flag)); if (SLOT(label) == NULL) return (ENOMEM); return (0); } static void mac_mls_destroy_label(struct label *label) { mls_free(SLOT(label)); SLOT_SET(label, NULL); } /* * mac_mls_element_to_string() accepts an sbuf and MLS element. It * converts the MLS element to a string and stores the result in the * sbuf; if there isn't space in the sbuf, -1 is returned. */ static int mac_mls_element_to_string(struct sbuf *sb, struct mac_mls_element *element) { int i, first; switch (element->mme_type) { case MAC_MLS_TYPE_HIGH: return (sbuf_printf(sb, "high")); case MAC_MLS_TYPE_LOW: return (sbuf_printf(sb, "low")); case MAC_MLS_TYPE_EQUAL: return (sbuf_printf(sb, "equal")); case MAC_MLS_TYPE_LEVEL: if (sbuf_printf(sb, "%d", element->mme_level) == -1) return (-1); first = 1; for (i = 1; i <= MAC_MLS_MAX_COMPARTMENTS; i++) { if (MAC_MLS_BIT_TEST(i, element->mme_compartments)) { if (first) { if (sbuf_putc(sb, ':') == -1) return (-1); if (sbuf_printf(sb, "%d", i) == -1) return (-1); first = 0; } else { if (sbuf_printf(sb, "+%d", i) == -1) return (-1); } } } return (0); default: panic("mac_mls_element_to_string: invalid type (%d)", element->mme_type); } } /* * mac_mls_to_string() converts an MLS label to a string, and places * the results in the passed sbuf. It returns 0 on success, or EINVAL * if there isn't room in the sbuf. Note: the sbuf will be modified * even in a failure case, so the caller may need to revert the sbuf * by restoring the offset if that's undesired. */ static int mac_mls_to_string(struct sbuf *sb, struct mac_mls *mac_mls) { if (mac_mls->mm_flags & MAC_MLS_FLAG_EFFECTIVE) { if (mac_mls_element_to_string(sb, &mac_mls->mm_effective) == -1) return (EINVAL); } if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) { if (sbuf_putc(sb, '(') == -1) return (EINVAL); if (mac_mls_element_to_string(sb, &mac_mls->mm_rangelow) == -1) return (EINVAL); if (sbuf_putc(sb, '-') == -1) return (EINVAL); if (mac_mls_element_to_string(sb, &mac_mls->mm_rangehigh) == -1) return (EINVAL); if (sbuf_putc(sb, ')') == -1) return (EINVAL); } return (0); } static int mac_mls_externalize_label(struct label *label, char *element_name, struct sbuf *sb, int *claimed) { struct mac_mls *mac_mls; if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0) return (0); (*claimed)++; mac_mls = SLOT(label); return (mac_mls_to_string(sb, mac_mls)); } static int mac_mls_parse_element(struct mac_mls_element *element, char *string) { char *compartment, *end, *level; int value; if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) { element->mme_type = MAC_MLS_TYPE_HIGH; element->mme_level = MAC_MLS_TYPE_UNDEF; } else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) { element->mme_type = MAC_MLS_TYPE_LOW; element->mme_level = MAC_MLS_TYPE_UNDEF; } else if (strcmp(string, "equal") == 0 || strcmp(string, "eq") == 0) { element->mme_type = MAC_MLS_TYPE_EQUAL; element->mme_level = MAC_MLS_TYPE_UNDEF; } else { element->mme_type = MAC_MLS_TYPE_LEVEL; /* * Numeric level piece of the element. */ level = strsep(&string, ":"); value = strtol(level, &end, 10); if (end == level || *end != '\0') return (EINVAL); if (value < 0 || value > 65535) return (EINVAL); element->mme_level = value; /* * Optional compartment piece of the element. If none * are included, we assume that the label has no * compartments. */ if (string == NULL) return (0); if (*string == '\0') return (0); while ((compartment = strsep(&string, "+")) != NULL) { value = strtol(compartment, &end, 10); if (compartment == end || *end != '\0') return (EINVAL); if (value < 1 || value > MAC_MLS_MAX_COMPARTMENTS) return (EINVAL); MAC_MLS_BIT_SET(value, element->mme_compartments); } } return (0); } /* * Note: destructively consumes the string, make a local copy before * calling if that's a problem. */ static int mac_mls_parse(struct mac_mls *mac_mls, char *string) { char *rangehigh, *rangelow, *effective; int error; effective = strsep(&string, "("); if (*effective == '\0') effective = NULL; if (string != NULL) { rangelow = strsep(&string, "-"); if (string == NULL) return (EINVAL); rangehigh = strsep(&string, ")"); if (string == NULL) return (EINVAL); if (*string != '\0') return (EINVAL); } else { rangelow = NULL; rangehigh = NULL; } KASSERT((rangelow != NULL && rangehigh != NULL) || (rangelow == NULL && rangehigh == NULL), ("mac_mls_parse: range mismatch")); bzero(mac_mls, sizeof(*mac_mls)); if (effective != NULL) { error = mac_mls_parse_element(&mac_mls->mm_effective, effective); if (error) return (error); mac_mls->mm_flags |= MAC_MLS_FLAG_EFFECTIVE; } if (rangelow != NULL) { error = mac_mls_parse_element(&mac_mls->mm_rangelow, rangelow); if (error) return (error); error = mac_mls_parse_element(&mac_mls->mm_rangehigh, rangehigh); if (error) return (error); mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE; } error = mac_mls_valid(mac_mls); if (error) return (error); return (0); } static int mac_mls_internalize_label(struct label *label, char *element_name, char *element_data, int *claimed) { struct mac_mls *mac_mls, mac_mls_temp; int error; if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0) return (0); (*claimed)++; error = mac_mls_parse(&mac_mls_temp, element_data); if (error) return (error); mac_mls = SLOT(label); *mac_mls = mac_mls_temp; return (0); } static void mac_mls_copy_label(struct label *src, struct label *dest) { *SLOT(dest) = *SLOT(src); } /* * Labeling event operations: file system objects, and things that look * a lot like file system objects. */ static void mac_mls_create_devfs_device(struct ucred *cred, struct mount *mp, struct cdev *dev, struct devfs_dirent *devfs_dirent, struct label *label) { struct mac_mls *mac_mls; int mls_type; mac_mls = SLOT(label); if (strcmp(dev->si_name, "null") == 0 || strcmp(dev->si_name, "zero") == 0 || strcmp(dev->si_name, "random") == 0 || strncmp(dev->si_name, "fd/", strlen("fd/")) == 0) mls_type = MAC_MLS_TYPE_EQUAL; else if (strcmp(dev->si_name, "kmem") == 0 || strcmp(dev->si_name, "mem") == 0) mls_type = MAC_MLS_TYPE_HIGH; else if (ptys_equal && (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 || strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0)) mls_type = MAC_MLS_TYPE_EQUAL; else mls_type = MAC_MLS_TYPE_LOW; mac_mls_set_effective(mac_mls, mls_type, 0, NULL); } static void mac_mls_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label) { struct mac_mls *mac_mls; mac_mls = SLOT(label); mac_mls_set_effective(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL); } static void mac_mls_create_devfs_symlink(struct ucred *cred, struct mount *mp, struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de, struct label *delabel) { struct mac_mls *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(delabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_mount(struct ucred *cred, struct mount *mp, struct label *mntlabel, struct label *fslabel) { struct mac_mls *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(mntlabel); mac_mls_copy_effective(source, dest); dest = SLOT(fslabel); mac_mls_copy_effective(source, dest); } static void mac_mls_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct label *label) { struct mac_mls *source, *dest; source = SLOT(label); dest = SLOT(vnodelabel); mac_mls_copy(source, dest); } static void mac_mls_update_devfsdirent(struct mount *mp, struct devfs_dirent *devfs_dirent, struct label *direntlabel, struct vnode *vp, struct label *vnodelabel) { struct mac_mls *source, *dest; source = SLOT(vnodelabel); dest = SLOT(direntlabel); mac_mls_copy_effective(source, dest); } static void mac_mls_associate_vnode_devfs(struct mount *mp, struct label *fslabel, struct devfs_dirent *de, struct label *delabel, struct vnode *vp, struct label *vlabel) { struct mac_mls *source, *dest; source = SLOT(delabel); dest = SLOT(vlabel); mac_mls_copy_effective(source, dest); } static int mac_mls_associate_vnode_extattr(struct mount *mp, struct label *fslabel, struct vnode *vp, struct label *vlabel) { struct mac_mls temp, *source, *dest; int buflen, error; source = SLOT(fslabel); dest = SLOT(vlabel); buflen = sizeof(temp); bzero(&temp, buflen); error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE, MAC_MLS_EXTATTR_NAME, &buflen, (char *) &temp, curthread); if (error == ENOATTR || error == EOPNOTSUPP) { /* Fall back to the fslabel. */ mac_mls_copy_effective(source, dest); return (0); } else if (error) return (error); if (buflen != sizeof(temp)) { printf("mac_mls_associate_vnode_extattr: bad size %d\n", buflen); return (EPERM); } if (mac_mls_valid(&temp) != 0) { printf("mac_mls_associate_vnode_extattr: invalid\n"); return (EPERM); } if ((temp.mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_EFFECTIVE) { printf("mac_mls_associated_vnode_extattr: not effective\n"); return (EPERM); } mac_mls_copy_effective(&temp, dest); return (0); } static void mac_mls_associate_vnode_singlelabel(struct mount *mp, struct label *fslabel, struct vnode *vp, struct label *vlabel) { struct mac_mls *source, *dest; source = SLOT(fslabel); dest = SLOT(vlabel); mac_mls_copy_effective(source, dest); } static int mac_mls_create_vnode_extattr(struct ucred *cred, struct mount *mp, struct label *fslabel, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *vlabel, struct componentname *cnp) { struct mac_mls *source, *dest, temp; size_t buflen; int error; buflen = sizeof(temp); bzero(&temp, buflen); source = SLOT(cred->cr_label); dest = SLOT(vlabel); mac_mls_copy_effective(source, &temp); error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE, MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread); if (error == 0) mac_mls_copy_effective(source, dest); return (error); } static int mac_mls_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, struct label *vlabel, struct label *intlabel) { struct mac_mls *source, temp; size_t buflen; int error; buflen = sizeof(temp); bzero(&temp, buflen); source = SLOT(intlabel); if ((source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) == 0) return (0); mac_mls_copy_effective(source, &temp); error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE, MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread); return (error); } /* * Labeling event operations: IPC object. */ static void mac_mls_create_inpcb_from_socket(struct socket *so, struct label *solabel, struct inpcb *inp, struct label *inplabel) { struct mac_mls *source, *dest; source = SLOT(solabel); dest = SLOT(inplabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_mbuf_from_socket(struct socket *so, struct label *socketlabel, struct mbuf *m, struct label *mbuflabel) { struct mac_mls *source, *dest; source = SLOT(socketlabel); dest = SLOT(mbuflabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_socket(struct ucred *cred, struct socket *socket, struct label *socketlabel) { struct mac_mls *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(socketlabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_pipe(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { struct mac_mls *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(pipelabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_posix_sem(struct ucred *cred, struct ksem *ksemptr, struct label *ks_label) { struct mac_mls *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(ks_label); mac_mls_copy_effective(source, dest); } static void mac_mls_create_socket_from_socket(struct socket *oldsocket, struct label *oldsocketlabel, struct socket *newsocket, struct label *newsocketlabel) { struct mac_mls *source, *dest; source = SLOT(oldsocketlabel); dest = SLOT(newsocketlabel); mac_mls_copy_effective(source, dest); } static void mac_mls_relabel_socket(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct label *newlabel) { struct mac_mls *source, *dest; source = SLOT(newlabel); dest = SLOT(socketlabel); mac_mls_copy(source, dest); } static void mac_mls_relabel_pipe(struct ucred *cred, struct pipepair *pp, struct label *pipelabel, struct label *newlabel) { struct mac_mls *source, *dest; source = SLOT(newlabel); dest = SLOT(pipelabel); mac_mls_copy(source, dest); } static void mac_mls_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel, struct socket *socket, struct label *socketpeerlabel) { struct mac_mls *source, *dest; source = SLOT(mbuflabel); dest = SLOT(socketpeerlabel); mac_mls_copy_effective(source, dest); } /* * Labeling event operations: System V IPC objects. */ static void mac_mls_create_sysv_msgmsg(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqlabel, struct msg *msgptr, struct label *msglabel) { struct mac_mls *source, *dest; /* Ignore the msgq label */ source = SLOT(cred->cr_label); dest = SLOT(msglabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_sysv_msgqueue(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqlabel) { struct mac_mls *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(msqlabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_sysv_sem(struct ucred *cred, struct semid_kernel *semakptr, struct label *semalabel) { struct mac_mls *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(semalabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_sysv_shm(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmlabel) { struct mac_mls *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(shmlabel); mac_mls_copy_effective(source, dest); } /* * Labeling event operations: network objects. */ static void mac_mls_set_socket_peer_from_socket(struct socket *oldsocket, struct label *oldsocketlabel, struct socket *newsocket, struct label *newsocketpeerlabel) { struct mac_mls *source, *dest; source = SLOT(oldsocketlabel); dest = SLOT(newsocketpeerlabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d, struct label *bpflabel) { struct mac_mls *source, *dest; source = SLOT(cred->cr_label); dest = SLOT(bpflabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel) { struct mac_mls *dest; int type; dest = SLOT(ifnetlabel); if (ifnet->if_type == IFT_LOOP) type = MAC_MLS_TYPE_EQUAL; else type = MAC_MLS_TYPE_LOW; mac_mls_set_effective(dest, type, 0, NULL); mac_mls_set_range(dest, type, 0, NULL, type, 0, NULL); } static void mac_mls_create_ipq(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel) { struct mac_mls *source, *dest; source = SLOT(fragmentlabel); dest = SLOT(ipqlabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel, struct mbuf *datagram, struct label *datagramlabel) { struct mac_mls *source, *dest; source = SLOT(ipqlabel); dest = SLOT(datagramlabel); /* Just use the head, since we require them all to match. */ mac_mls_copy_effective(source, dest); } static void mac_mls_create_fragment(struct mbuf *datagram, struct label *datagramlabel, struct mbuf *fragment, struct label *fragmentlabel) { struct mac_mls *source, *dest; source = SLOT(datagramlabel); dest = SLOT(fragmentlabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_mbuf_from_inpcb(struct inpcb *inp, struct label *inplabel, struct mbuf *m, struct label *mlabel) { struct mac_mls *source, *dest; source = SLOT(inplabel); dest = SLOT(mlabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *mbuf, struct label *mbuflabel) { struct mac_mls *dest; dest = SLOT(mbuflabel); mac_mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL); } static void mac_mls_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel, struct mbuf *mbuf, struct label *mbuflabel) { struct mac_mls *source, *dest; source = SLOT(bpflabel); dest = SLOT(mbuflabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *m, struct label *mbuflabel) { struct mac_mls *source, *dest; source = SLOT(ifnetlabel); dest = SLOT(mbuflabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *newmbuf, struct label *newmbuflabel) { struct mac_mls *source, *dest; source = SLOT(oldmbuflabel); dest = SLOT(newmbuflabel); mac_mls_copy_effective(source, dest); } static void mac_mls_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel, struct mbuf *newmbuf, struct label *newmbuflabel) { struct mac_mls *source, *dest; source = SLOT(oldmbuflabel); dest = SLOT(newmbuflabel); mac_mls_copy_effective(source, dest); } static int mac_mls_fragment_match(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel) { struct mac_mls *a, *b; a = SLOT(ipqlabel); b = SLOT(fragmentlabel); return (mac_mls_equal_effective(a, b)); } static void mac_mls_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet, struct label *ifnetlabel, struct label *newlabel) { struct mac_mls *source, *dest; source = SLOT(newlabel); dest = SLOT(ifnetlabel); mac_mls_copy(source, dest); } static void mac_mls_update_ipq(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel) { /* NOOP: we only accept matching labels, so no need to update */ } static void mac_mls_inpcb_sosetlabel(struct socket *so, struct label *solabel, struct inpcb *inp, struct label *inplabel) { struct mac_mls *source, *dest; source = SLOT(solabel); dest = SLOT(inplabel); mac_mls_copy(source, dest); } static void mac_mls_create_mbuf_from_firewall(struct mbuf *m, struct label *mbuflabel) { struct mac_mls *dest; dest = SLOT(mbuflabel); /* XXX: where is the label for the firewall really comming from? */ mac_mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL); } /* * Labeling event operations: processes. */ static void mac_mls_create_proc0(struct ucred *cred) { struct mac_mls *dest; dest = SLOT(cred->cr_label); mac_mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL); mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0, NULL); } static void mac_mls_create_proc1(struct ucred *cred) { struct mac_mls *dest; dest = SLOT(cred->cr_label); mac_mls_set_effective(dest, MAC_MLS_TYPE_LOW, 0, NULL); mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0, NULL); } static void mac_mls_relabel_cred(struct ucred *cred, struct label *newlabel) { struct mac_mls *source, *dest; source = SLOT(newlabel); dest = SLOT(cred->cr_label); mac_mls_copy(source, dest); } /* * Label cleanup/flush operations. */ static void mac_mls_cleanup_sysv_msgmsg(struct label *msglabel) { bzero(SLOT(msglabel), sizeof(struct mac_mls)); } static void mac_mls_cleanup_sysv_msgqueue(struct label *msqlabel) { bzero(SLOT(msqlabel), sizeof(struct mac_mls)); } static void mac_mls_cleanup_sysv_sem(struct label *semalabel) { bzero(SLOT(semalabel), sizeof(struct mac_mls)); } static void mac_mls_cleanup_sysv_shm(struct label *shmlabel) { bzero(SLOT(shmlabel), sizeof(struct mac_mls)); } /* * Access control checks. */ static int mac_mls_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel, struct ifnet *ifnet, struct label *ifnetlabel) { struct mac_mls *a, *b; if (!mac_mls_enabled) return (0); a = SLOT(bpflabel); b = SLOT(ifnetlabel); if (mac_mls_equal_effective(a, b)) return (0); return (EACCES); } static int mac_mls_check_cred_relabel(struct ucred *cred, struct label *newlabel) { struct mac_mls *subj, *new; int error; subj = SLOT(cred->cr_label); new = SLOT(newlabel); /* * If there is an MLS label update for the credential, it may be * an update of effective, range, or both. */ error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH); if (error) return (error); /* * If the MLS label is to be changed, authorize as appropriate. */ if (new->mm_flags & MAC_MLS_FLAGS_BOTH) { /* * If the change request modifies both the MLS label effective * and range, check that the new effective will be in the * new range. */ if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) == MAC_MLS_FLAGS_BOTH && !mac_mls_effective_in_range(new, new)) return (EINVAL); /* * To change the MLS effective label on a credential, the * new effective label must be in the current range. */ if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE && !mac_mls_effective_in_range(new, subj)) return (EPERM); /* * To change the MLS range label on a credential, the * new range must be in the current range. */ if (new->mm_flags & MAC_MLS_FLAG_RANGE && !mac_mls_range_in_range(new, subj)) return (EPERM); /* * To have EQUAL in any component of the new credential * MLS label, the subject must already have EQUAL in * their label. */ if (mac_mls_contains_equal(new)) { error = mac_mls_subject_privileged(subj); if (error) return (error); } } return (0); } static int mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(u1->cr_label); obj = SLOT(u2->cr_label); /* XXX: range */ if (!mac_mls_dominate_effective(subj, obj)) return (ESRCH); return (0); } static int mac_mls_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet, struct label *ifnetlabel, struct label *newlabel) { struct mac_mls *subj, *new; int error; subj = SLOT(cred->cr_label); new = SLOT(newlabel); /* * If there is an MLS label update for the interface, it may * be an update of effective, range, or both. */ error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH); if (error) return (error); /* * Relabeling network interfaces requires MLS privilege. */ error = mac_mls_subject_privileged(subj); return (0); } static int mac_mls_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *m, struct label *mbuflabel) { struct mac_mls *p, *i; if (!mac_mls_enabled) return (0); p = SLOT(mbuflabel); i = SLOT(ifnetlabel); return (mac_mls_effective_in_range(p, i) ? 0 : EACCES); } static int mac_mls_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel, struct mbuf *m, struct label *mlabel) { struct mac_mls *p, *i; if (!mac_mls_enabled) return (0); p = SLOT(mlabel); i = SLOT(inplabel); return (mac_mls_equal_effective(p, i) ? 0 : EACCES); } static int mac_mls_check_sysv_msgrcv(struct ucred *cred, struct msg *msgptr, struct label *msglabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(msglabel); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_sysv_msgrmid(struct ucred *cred, struct msg *msgptr, struct label *msglabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(msglabel); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_sysv_msqget(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(msqklabel); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_sysv_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(msqklabel); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_sysv_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(msqklabel); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_sysv_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel, int cmd) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(msqklabel); switch(cmd) { case IPC_RMID: case IPC_SET: if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); break; case IPC_STAT: if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); break; default: return (EACCES); } return (0); } static int mac_mls_check_sysv_semctl(struct ucred *cred, struct semid_kernel *semakptr, struct label *semaklabel, int cmd) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(semaklabel); switch(cmd) { case IPC_RMID: case IPC_SET: case SETVAL: case SETALL: if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); break; case IPC_STAT: case GETVAL: case GETPID: case GETNCNT: case GETZCNT: case GETALL: if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); break; default: return (EACCES); } return (0); } static int mac_mls_check_sysv_semget(struct ucred *cred, struct semid_kernel *semakptr, struct label *semaklabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(semaklabel); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_sysv_semop(struct ucred *cred, struct semid_kernel *semakptr, struct label *semaklabel, size_t accesstype) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(semaklabel); if( accesstype & SEM_R ) if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); if( accesstype & SEM_A ) if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_sysv_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmseglabel, int shmflg) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(shmseglabel); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); if ((shmflg & SHM_RDONLY) == 0) if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_sysv_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmseglabel, int cmd) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(shmseglabel); switch(cmd) { case IPC_RMID: case IPC_SET: if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); break; case IPC_STAT: case SHM_STAT: if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); break; default: return (EACCES); } return (0); } static int mac_mls_check_sysv_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmseglabel, int shmflg) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(shmseglabel); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_mount_stat(struct ucred *cred, struct mount *mp, struct label *mntlabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(mntlabel); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp, struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data) { if(!mac_mls_enabled) return (0); /* XXX: This will be implemented soon... */ return (0); } static int mac_mls_check_pipe_poll(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT((pipelabel)); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_pipe_read(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT((pipelabel)); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_pipe_relabel(struct ucred *cred, struct pipepair *pp, struct label *pipelabel, struct label *newlabel) { struct mac_mls *subj, *obj, *new; int error; new = SLOT(newlabel); subj = SLOT(cred->cr_label); obj = SLOT(pipelabel); /* * If there is an MLS label update for a pipe, it must be a * effective update. */ error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE); if (error) return (error); /* * To perform a relabel of a pipe (MLS label or not), MLS must * authorize the relabel. */ if (!mac_mls_effective_in_range(obj, subj)) return (EPERM); /* * If the MLS label is to be changed, authorize as appropriate. */ if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) { /* * To change the MLS label on a pipe, the new pipe label * must be in the subject range. */ if (!mac_mls_effective_in_range(new, subj)) return (EPERM); /* * To change the MLS label on a pipe to be EQUAL, the * subject must have appropriate privilege. */ if (mac_mls_contains_equal(new)) { error = mac_mls_subject_privileged(subj); if (error) return (error); } } return (0); } static int mac_mls_check_pipe_stat(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT((pipelabel)); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_pipe_write(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT((pipelabel)); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_posix_sem_write(struct ucred *cred, struct ksem *ksemptr, struct label *ks_label) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(ks_label); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_posix_sem_rdonly(struct ucred *cred, struct ksem *ksemptr, struct label *ks_label) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(ks_label); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_proc_debug(struct ucred *cred, struct proc *proc) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(proc->p_ucred->cr_label); /* XXX: range checks */ if (!mac_mls_dominate_effective(subj, obj)) return (ESRCH); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_proc_sched(struct ucred *cred, struct proc *proc) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(proc->p_ucred->cr_label); /* XXX: range checks */ if (!mac_mls_dominate_effective(subj, obj)) return (ESRCH); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(proc->p_ucred->cr_label); /* XXX: range checks */ if (!mac_mls_dominate_effective(subj, obj)) return (ESRCH); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_socket_deliver(struct socket *so, struct label *socketlabel, struct mbuf *m, struct label *mbuflabel) { struct mac_mls *p, *s; if (!mac_mls_enabled) return (0); p = SLOT(mbuflabel); s = SLOT(socketlabel); return (mac_mls_equal_effective(p, s) ? 0 : EACCES); } static int mac_mls_check_socket_relabel(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct label *newlabel) { struct mac_mls *subj, *obj, *new; int error; new = SLOT(newlabel); subj = SLOT(cred->cr_label); obj = SLOT(socketlabel); /* * If there is an MLS label update for the socket, it may be * an update of effective. */ error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE); if (error) return (error); /* * To relabel a socket, the old socket effective must be in the subject * range. */ if (!mac_mls_effective_in_range(obj, subj)) return (EPERM); /* * If the MLS label is to be changed, authorize as appropriate. */ if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) { /* * To relabel a socket, the new socket effective must be in * the subject range. */ if (!mac_mls_effective_in_range(new, subj)) return (EPERM); /* * To change the MLS label on the socket to contain EQUAL, * the subject must have appropriate privilege. */ if (mac_mls_contains_equal(new)) { error = mac_mls_subject_privileged(subj); if (error) return (error); } } return (0); } static int mac_mls_check_socket_visible(struct ucred *cred, struct socket *socket, struct label *socketlabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(socketlabel); if (!mac_mls_dominate_effective(subj, obj)) return (ENOENT); return (0); } static int mac_mls_check_system_swapon(struct ucred *cred, struct vnode *vp, struct label *label) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_mls_dominate_effective(obj, subj) || !mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_vnode_chdir(struct ucred *cred, struct vnode *dvp, struct label *dlabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_vnode_chroot(struct ucred *cred, struct vnode *dvp, struct label *dlabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_vnode_create(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct componentname *cnp, struct vattr *vap) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); obj = SLOT(label); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace, const char *name) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_vnode_exec(struct ucred *cred, struct vnode *vp, struct label *label, struct image_params *imgp, struct label *execlabel) { struct mac_mls *subj, *obj, *exec; int error; if (execlabel != NULL) { /* * We currently don't permit labels to be changed at * exec-time as part of MLS, so disallow non-NULL * MLS label elements in the execlabel. */ exec = SLOT(execlabel); error = mls_atmostflags(exec, 0); if (error) return (error); } if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_vnode_getacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace, const char *name, struct uio *uio) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_vnode_link(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); obj = SLOT(dlabel); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_vnode_listextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct componentname *cnp) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_vnode_mmap(struct ucred *cred, struct vnode *vp, struct label *label, int prot, int flags) { struct mac_mls *subj, *obj; /* * Rely on the use of open()-time protections to handle * non-revocation cases. */ if (!mac_mls_enabled || !revocation_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); } if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) { if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); } return (0); } static int mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, int acc_mode) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(vnodelabel); /* XXX privilege override for admin? */ if (acc_mode & (VREAD | VEXEC | VSTAT)) { if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); } if (acc_mode & (VWRITE | VAPPEND | VADMIN)) { if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); } return (0); } static int mac_mls_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label) { struct mac_mls *subj, *obj; if (!mac_mls_enabled || !revocation_enabled) return (0); subj = SLOT(active_cred->cr_label); obj = SLOT(label); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label) { struct mac_mls *subj, *obj; if (!mac_mls_enabled || !revocation_enabled) return (0); subj = SLOT(active_cred->cr_label); obj = SLOT(label); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_vnode_readdir(struct ucred *cred, struct vnode *dvp, struct label *dlabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_vnode_readlink(struct ucred *cred, struct vnode *vp, struct label *vnodelabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(vnodelabel); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_vnode_relabel(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct label *newlabel) { struct mac_mls *old, *new, *subj; int error; old = SLOT(vnodelabel); new = SLOT(newlabel); subj = SLOT(cred->cr_label); /* * If there is an MLS label update for the vnode, it must be a * effective label. */ error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE); if (error) return (error); /* * To perform a relabel of the vnode (MLS label or not), MLS must * authorize the relabel. */ if (!mac_mls_effective_in_range(old, subj)) return (EPERM); /* * If the MLS label is to be changed, authorize as appropriate. */ if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) { /* * To change the MLS label on a vnode, the new vnode label * must be in the subject range. */ if (!mac_mls_effective_in_range(new, subj)) return (EPERM); /* * To change the MLS label on the vnode to be EQUAL, * the subject must have appropriate privilege. */ if (mac_mls_contains_equal(new)) { error = mac_mls_subject_privileged(subj); if (error) return (error); } } return (0); } static int mac_mls_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); obj = SLOT(label); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, int samedir, struct componentname *cnp) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(dlabel); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); if (vp != NULL) { obj = SLOT(label); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); } return (0); } static int mac_mls_check_vnode_revoke(struct ucred *cred, struct vnode *vp, struct label *label) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_vnode_setacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type, struct acl *acl) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(label); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, int attrnamespace, const char *name, struct uio *uio) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(vnodelabel); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); /* XXX: protect the MAC EA in a special way? */ return (0); } static int mac_mls_check_vnode_setflags(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, u_long flags) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(vnodelabel); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_vnode_setmode(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, mode_t mode) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(vnodelabel); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_vnode_setowner(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, uid_t uid, gid_t gid) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(vnodelabel); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct timespec atime, struct timespec mtime) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(cred->cr_label); obj = SLOT(vnodelabel); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static int mac_mls_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *vnodelabel) { struct mac_mls *subj, *obj; if (!mac_mls_enabled) return (0); subj = SLOT(active_cred->cr_label); obj = SLOT(vnodelabel); if (!mac_mls_dominate_effective(subj, obj)) return (EACCES); return (0); } static int mac_mls_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label) { struct mac_mls *subj, *obj; if (!mac_mls_enabled || !revocation_enabled) return (0); subj = SLOT(active_cred->cr_label); obj = SLOT(label); if (!mac_mls_dominate_effective(obj, subj)) return (EACCES); return (0); } static void mac_mls_associate_nfsd_label(struct ucred *cred) { struct mac_mls *label; label = SLOT(cred->cr_label); mac_mls_set_effective(label, MAC_MLS_TYPE_LOW, 0, NULL); mac_mls_set_range(label, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0, NULL); } static struct mac_policy_ops mac_mls_ops = { .mpo_init = mac_mls_init, .mpo_init_bpfdesc_label = mac_mls_init_label, .mpo_init_cred_label = mac_mls_init_label, .mpo_init_devfsdirent_label = mac_mls_init_label, .mpo_init_ifnet_label = mac_mls_init_label, .mpo_init_inpcb_label = mac_mls_init_label_waitcheck, .mpo_init_sysv_msgmsg_label = mac_mls_init_label, .mpo_init_sysv_msgqueue_label = mac_mls_init_label, .mpo_init_sysv_sem_label = mac_mls_init_label, .mpo_init_sysv_shm_label = mac_mls_init_label, .mpo_init_ipq_label = mac_mls_init_label_waitcheck, .mpo_init_mbuf_label = mac_mls_init_label_waitcheck, .mpo_init_mount_label = mac_mls_init_label, .mpo_init_mount_fs_label = mac_mls_init_label, .mpo_init_pipe_label = mac_mls_init_label, .mpo_init_posix_sem_label = mac_mls_init_label, .mpo_init_socket_label = mac_mls_init_label_waitcheck, .mpo_init_socket_peer_label = mac_mls_init_label_waitcheck, .mpo_init_vnode_label = mac_mls_init_label, .mpo_destroy_bpfdesc_label = mac_mls_destroy_label, .mpo_destroy_cred_label = mac_mls_destroy_label, .mpo_destroy_devfsdirent_label = mac_mls_destroy_label, .mpo_destroy_ifnet_label = mac_mls_destroy_label, .mpo_destroy_inpcb_label = mac_mls_destroy_label, .mpo_destroy_sysv_msgmsg_label = mac_mls_destroy_label, .mpo_destroy_sysv_msgqueue_label = mac_mls_destroy_label, .mpo_destroy_sysv_sem_label = mac_mls_destroy_label, .mpo_destroy_sysv_shm_label = mac_mls_destroy_label, .mpo_destroy_ipq_label = mac_mls_destroy_label, .mpo_destroy_mbuf_label = mac_mls_destroy_label, .mpo_destroy_mount_label = mac_mls_destroy_label, .mpo_destroy_mount_fs_label = mac_mls_destroy_label, .mpo_destroy_pipe_label = mac_mls_destroy_label, .mpo_destroy_posix_sem_label = mac_mls_destroy_label, .mpo_destroy_socket_label = mac_mls_destroy_label, .mpo_destroy_socket_peer_label = mac_mls_destroy_label, .mpo_destroy_vnode_label = mac_mls_destroy_label, .mpo_copy_cred_label = mac_mls_copy_label, .mpo_copy_ifnet_label = mac_mls_copy_label, .mpo_copy_mbuf_label = mac_mls_copy_label, .mpo_copy_pipe_label = mac_mls_copy_label, .mpo_copy_socket_label = mac_mls_copy_label, .mpo_copy_vnode_label = mac_mls_copy_label, .mpo_externalize_cred_label = mac_mls_externalize_label, .mpo_externalize_ifnet_label = mac_mls_externalize_label, .mpo_externalize_pipe_label = mac_mls_externalize_label, .mpo_externalize_socket_label = mac_mls_externalize_label, .mpo_externalize_socket_peer_label = mac_mls_externalize_label, .mpo_externalize_vnode_label = mac_mls_externalize_label, .mpo_internalize_cred_label = mac_mls_internalize_label, .mpo_internalize_ifnet_label = mac_mls_internalize_label, .mpo_internalize_pipe_label = mac_mls_internalize_label, .mpo_internalize_socket_label = mac_mls_internalize_label, .mpo_internalize_vnode_label = mac_mls_internalize_label, .mpo_create_devfs_device = mac_mls_create_devfs_device, .mpo_create_devfs_directory = mac_mls_create_devfs_directory, .mpo_create_devfs_symlink = mac_mls_create_devfs_symlink, .mpo_create_mount = mac_mls_create_mount, .mpo_relabel_vnode = mac_mls_relabel_vnode, .mpo_update_devfsdirent = mac_mls_update_devfsdirent, .mpo_associate_vnode_devfs = mac_mls_associate_vnode_devfs, .mpo_associate_vnode_extattr = mac_mls_associate_vnode_extattr, .mpo_associate_vnode_singlelabel = mac_mls_associate_vnode_singlelabel, .mpo_create_vnode_extattr = mac_mls_create_vnode_extattr, .mpo_setlabel_vnode_extattr = mac_mls_setlabel_vnode_extattr, .mpo_create_mbuf_from_socket = mac_mls_create_mbuf_from_socket, .mpo_create_pipe = mac_mls_create_pipe, .mpo_create_posix_sem = mac_mls_create_posix_sem, .mpo_create_socket = mac_mls_create_socket, .mpo_create_socket_from_socket = mac_mls_create_socket_from_socket, .mpo_relabel_pipe = mac_mls_relabel_pipe, .mpo_relabel_socket = mac_mls_relabel_socket, .mpo_set_socket_peer_from_mbuf = mac_mls_set_socket_peer_from_mbuf, .mpo_set_socket_peer_from_socket = mac_mls_set_socket_peer_from_socket, .mpo_create_bpfdesc = mac_mls_create_bpfdesc, .mpo_create_datagram_from_ipq = mac_mls_create_datagram_from_ipq, .mpo_create_fragment = mac_mls_create_fragment, .mpo_create_ifnet = mac_mls_create_ifnet, .mpo_create_inpcb_from_socket = mac_mls_create_inpcb_from_socket, .mpo_create_ipq = mac_mls_create_ipq, .mpo_create_sysv_msgmsg = mac_mls_create_sysv_msgmsg, .mpo_create_sysv_msgqueue = mac_mls_create_sysv_msgqueue, .mpo_create_sysv_sem = mac_mls_create_sysv_sem, .mpo_create_sysv_shm = mac_mls_create_sysv_shm, .mpo_create_mbuf_from_inpcb = mac_mls_create_mbuf_from_inpcb, .mpo_create_mbuf_linklayer = mac_mls_create_mbuf_linklayer, .mpo_create_mbuf_from_bpfdesc = mac_mls_create_mbuf_from_bpfdesc, .mpo_create_mbuf_from_ifnet = mac_mls_create_mbuf_from_ifnet, .mpo_create_mbuf_multicast_encap = mac_mls_create_mbuf_multicast_encap, .mpo_create_mbuf_netlayer = mac_mls_create_mbuf_netlayer, .mpo_fragment_match = mac_mls_fragment_match, .mpo_relabel_ifnet = mac_mls_relabel_ifnet, .mpo_update_ipq = mac_mls_update_ipq, .mpo_inpcb_sosetlabel = mac_mls_inpcb_sosetlabel, .mpo_create_proc0 = mac_mls_create_proc0, .mpo_create_proc1 = mac_mls_create_proc1, .mpo_relabel_cred = mac_mls_relabel_cred, .mpo_cleanup_sysv_msgmsg = mac_mls_cleanup_sysv_msgmsg, .mpo_cleanup_sysv_msgqueue = mac_mls_cleanup_sysv_msgqueue, .mpo_cleanup_sysv_sem = mac_mls_cleanup_sysv_sem, .mpo_cleanup_sysv_shm = mac_mls_cleanup_sysv_shm, .mpo_check_bpfdesc_receive = mac_mls_check_bpfdesc_receive, .mpo_check_cred_relabel = mac_mls_check_cred_relabel, .mpo_check_cred_visible = mac_mls_check_cred_visible, .mpo_check_ifnet_relabel = mac_mls_check_ifnet_relabel, .mpo_check_ifnet_transmit = mac_mls_check_ifnet_transmit, .mpo_check_inpcb_deliver = mac_mls_check_inpcb_deliver, .mpo_check_sysv_msgrcv = mac_mls_check_sysv_msgrcv, .mpo_check_sysv_msgrmid = mac_mls_check_sysv_msgrmid, .mpo_check_sysv_msqget = mac_mls_check_sysv_msqget, .mpo_check_sysv_msqsnd = mac_mls_check_sysv_msqsnd, .mpo_check_sysv_msqrcv = mac_mls_check_sysv_msqrcv, .mpo_check_sysv_msqctl = mac_mls_check_sysv_msqctl, .mpo_check_sysv_semctl = mac_mls_check_sysv_semctl, .mpo_check_sysv_semget = mac_mls_check_sysv_semget, .mpo_check_sysv_semop = mac_mls_check_sysv_semop, .mpo_check_sysv_shmat = mac_mls_check_sysv_shmat, .mpo_check_sysv_shmctl = mac_mls_check_sysv_shmctl, .mpo_check_sysv_shmget = mac_mls_check_sysv_shmget, .mpo_check_mount_stat = mac_mls_check_mount_stat, .mpo_check_pipe_ioctl = mac_mls_check_pipe_ioctl, .mpo_check_pipe_poll = mac_mls_check_pipe_poll, .mpo_check_pipe_read = mac_mls_check_pipe_read, .mpo_check_pipe_relabel = mac_mls_check_pipe_relabel, .mpo_check_pipe_stat = mac_mls_check_pipe_stat, .mpo_check_pipe_write = mac_mls_check_pipe_write, .mpo_check_posix_sem_destroy = mac_mls_check_posix_sem_write, .mpo_check_posix_sem_getvalue = mac_mls_check_posix_sem_rdonly, .mpo_check_posix_sem_open = mac_mls_check_posix_sem_write, .mpo_check_posix_sem_post = mac_mls_check_posix_sem_write, .mpo_check_posix_sem_unlink = mac_mls_check_posix_sem_write, .mpo_check_posix_sem_wait = mac_mls_check_posix_sem_write, .mpo_check_proc_debug = mac_mls_check_proc_debug, .mpo_check_proc_sched = mac_mls_check_proc_sched, .mpo_check_proc_signal = mac_mls_check_proc_signal, .mpo_check_socket_deliver = mac_mls_check_socket_deliver, .mpo_check_socket_relabel = mac_mls_check_socket_relabel, .mpo_check_socket_visible = mac_mls_check_socket_visible, .mpo_check_system_swapon = mac_mls_check_system_swapon, .mpo_check_vnode_access = mac_mls_check_vnode_open, .mpo_check_vnode_chdir = mac_mls_check_vnode_chdir, .mpo_check_vnode_chroot = mac_mls_check_vnode_chroot, .mpo_check_vnode_create = mac_mls_check_vnode_create, .mpo_check_vnode_delete = mac_mls_check_vnode_delete, .mpo_check_vnode_deleteacl = mac_mls_check_vnode_deleteacl, .mpo_check_vnode_deleteextattr = mac_mls_check_vnode_deleteextattr, .mpo_check_vnode_exec = mac_mls_check_vnode_exec, .mpo_check_vnode_getacl = mac_mls_check_vnode_getacl, .mpo_check_vnode_getextattr = mac_mls_check_vnode_getextattr, .mpo_check_vnode_link = mac_mls_check_vnode_link, .mpo_check_vnode_listextattr = mac_mls_check_vnode_listextattr, .mpo_check_vnode_lookup = mac_mls_check_vnode_lookup, .mpo_check_vnode_mmap = mac_mls_check_vnode_mmap, .mpo_check_vnode_open = mac_mls_check_vnode_open, .mpo_check_vnode_poll = mac_mls_check_vnode_poll, .mpo_check_vnode_read = mac_mls_check_vnode_read, .mpo_check_vnode_readdir = mac_mls_check_vnode_readdir, .mpo_check_vnode_readlink = mac_mls_check_vnode_readlink, .mpo_check_vnode_relabel = mac_mls_check_vnode_relabel, .mpo_check_vnode_rename_from = mac_mls_check_vnode_rename_from, .mpo_check_vnode_rename_to = mac_mls_check_vnode_rename_to, .mpo_check_vnode_revoke = mac_mls_check_vnode_revoke, .mpo_check_vnode_setacl = mac_mls_check_vnode_setacl, .mpo_check_vnode_setextattr = mac_mls_check_vnode_setextattr, .mpo_check_vnode_setflags = mac_mls_check_vnode_setflags, .mpo_check_vnode_setmode = mac_mls_check_vnode_setmode, .mpo_check_vnode_setowner = mac_mls_check_vnode_setowner, .mpo_check_vnode_setutimes = mac_mls_check_vnode_setutimes, .mpo_check_vnode_stat = mac_mls_check_vnode_stat, .mpo_check_vnode_write = mac_mls_check_vnode_write, .mpo_associate_nfsd_label = mac_mls_associate_nfsd_label, .mpo_create_mbuf_from_firewall = mac_mls_create_mbuf_from_firewall, }; MAC_POLICY_SET(&mac_mls_ops, mac_mls, "TrustedBSD MAC/MLS", MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS, &mac_mls_slot); Index: head/sys/security/mac_stub/mac_stub.c =================================================================== --- head/sys/security/mac_stub/mac_stub.c (revision 164183) +++ head/sys/security/mac_stub/mac_stub.c (revision 164184) @@ -1,1597 +1,1596 @@ /*- * Copyright (c) 1999-2002 Robert N. M. Watson * Copyright (c) 2001-2005 McAfee, Inc. * Copyright (c) 2005 SPARTA, Inc. * All rights reserved. * * This software was developed by Robert Watson for the TrustedBSD Project. * * This software was developed for the FreeBSD Project in part by McAfee * Research, the Security Research Division of McAfee, Inc. under * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA * CHATS research program. * * This software was enhanced by SPARTA ISSO under SPAWAR contract * N66001-04-C-6019 ("SEFOS"). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Developed by the TrustedBSD Project. * * Stub module that implements a NOOP for most (if not all) MAC Framework * policy entry points. */ #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include - -#include #include #include #include #include #include #include #include #include #include #include SYSCTL_DECL(_security_mac); SYSCTL_NODE(_security_mac, OID_AUTO, stub, CTLFLAG_RW, 0, "TrustedBSD mac_stub policy controls"); static int stub_enabled = 1; SYSCTL_INT(_security_mac_stub, OID_AUTO, enabled, CTLFLAG_RW, &stub_enabled, 0, "Enforce mac_stub policy"); /* * Policy module operations. */ static void stub_destroy(struct mac_policy_conf *conf) { } static void stub_init(struct mac_policy_conf *conf) { } static int stub_syscall(struct thread *td, int call, void *arg) { return (0); } /* * Label operations. */ static void stub_init_label(struct label *label) { } static int stub_init_label_waitcheck(struct label *label, int flag) { return (0); } static void stub_destroy_label(struct label *label) { } static void stub_copy_label(struct label *src, struct label *dest) { } static int stub_externalize_label(struct label *label, char *element_name, struct sbuf *sb, int *claimed) { return (0); } static int stub_internalize_label(struct label *label, char *element_name, char *element_data, int *claimed) { return (0); } /* * Labeling event operations: file system objects, and things that look * a lot like file system objects. */ static void stub_associate_vnode_devfs(struct mount *mp, struct label *fslabel, struct devfs_dirent *de, struct label *delabel, struct vnode *vp, struct label *vlabel) { } static int stub_associate_vnode_extattr(struct mount *mp, struct label *fslabel, struct vnode *vp, struct label *vlabel) { return (0); } static void stub_associate_vnode_singlelabel(struct mount *mp, struct label *fslabel, struct vnode *vp, struct label *vlabel) { } static void stub_create_devfs_device(struct ucred *cred, struct mount *mp, struct cdev *dev, struct devfs_dirent *devfs_dirent, struct label *label) { } static void stub_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label) { } static void stub_create_devfs_symlink(struct ucred *cred, struct mount *mp, struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de, struct label *delabel) { } static int stub_create_vnode_extattr(struct ucred *cred, struct mount *mp, struct label *fslabel, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *vlabel, struct componentname *cnp) { return (0); } static void stub_create_mount(struct ucred *cred, struct mount *mp, struct label *mntlabel, struct label *fslabel) { } static void stub_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct label *label) { } static int stub_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, struct label *vlabel, struct label *intlabel) { return (0); } static void stub_update_devfsdirent(struct mount *mp, struct devfs_dirent *devfs_dirent, struct label *direntlabel, struct vnode *vp, struct label *vnodelabel) { } /* * Labeling event operations: IPC object. */ static void stub_create_mbuf_from_socket(struct socket *so, struct label *socketlabel, struct mbuf *m, struct label *mbuflabel) { } static void stub_create_socket(struct ucred *cred, struct socket *socket, struct label *socketlabel) { } static void stub_create_pipe(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { } static void stub_create_posix_sem(struct ucred *cred, struct ksem *ksemptr, struct label *ks_label) { } static void stub_create_socket_from_socket(struct socket *oldsocket, struct label *oldsocketlabel, struct socket *newsocket, struct label *newsocketlabel) { } static void stub_relabel_socket(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct label *newlabel) { } static void stub_relabel_pipe(struct ucred *cred, struct pipepair *pp, struct label *pipelabel, struct label *newlabel) { } static void stub_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel, struct socket *socket, struct label *socketpeerlabel) { } static void stub_set_socket_peer_from_socket(struct socket *oldsocket, struct label *oldsocketlabel, struct socket *newsocket, struct label *newsocketpeerlabel) { } /* * Labeling event operations: network objects. */ static void stub_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d, struct label *bpflabel) { } static void stub_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel, struct mbuf *datagram, struct label *datagramlabel) { } static void stub_create_fragment(struct mbuf *datagram, struct label *datagramlabel, struct mbuf *fragment, struct label *fragmentlabel) { } static void stub_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel) { } static void stub_create_inpcb_from_socket(struct socket *so, struct label *solabel, struct inpcb *inp, struct label *inplabel) { } static void stub_create_sysv_msgmsg(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqlabel, struct msg *msgptr, struct label *msglabel) { } static void stub_create_sysv_msgqueue(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqlabel) { } static void stub_create_sysv_sem(struct ucred *cred, struct semid_kernel *semakptr, struct label *semalabel) { } static void stub_create_sysv_shm(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmalabel) { } static void stub_create_ipq(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel) { } static void stub_create_mbuf_from_inpcb(struct inpcb *inp, struct label *inplabel, struct mbuf *m, struct label *mlabel) { } static void stub_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *mbuf, struct label *mbuflabel) { } static void stub_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel, struct mbuf *mbuf, struct label *mbuflabel) { } static void stub_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *m, struct label *mbuflabel) { } static void stub_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *newmbuf, struct label *newmbuflabel) { } static void stub_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel, struct mbuf *newmbuf, struct label *newmbuflabel) { } static int stub_fragment_match(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel) { return (1); } static void stub_reflect_mbuf_icmp(struct mbuf *m, struct label *mlabel) { } static void stub_reflect_mbuf_tcp(struct mbuf *m, struct label *mlabel) { } static void stub_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet, struct label *ifnetlabel, struct label *newlabel) { } static void stub_update_ipq(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel) { } static void stub_inpcb_sosetlabel(struct socket *so, struct label *solabel, struct inpcb *inp, struct label *inplabel) { } /* * Labeling event operations: processes. */ static void stub_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, struct label *vnodelabel, struct label *interpvnodelabel, struct image_params *imgp, struct label *execlabel) { } static int stub_execve_will_transition(struct ucred *old, struct vnode *vp, struct label *vnodelabel, struct label *interpvnodelabel, struct image_params *imgp, struct label *execlabel) { return (0); } static void stub_create_proc0(struct ucred *cred) { } static void stub_create_proc1(struct ucred *cred) { } static void stub_relabel_cred(struct ucred *cred, struct label *newlabel) { } static void stub_thread_userret(struct thread *td) { } /* * Label cleanup/flush operations */ static void stub_cleanup_sysv_msgmsg(struct label *msglabel) { } static void stub_cleanup_sysv_msgqueue(struct label *msqlabel) { } static void stub_cleanup_sysv_sem(struct label *semalabel) { } static void stub_cleanup_sysv_shm(struct label *shmlabel) { } /* * Access control checks. */ static int stub_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel, struct ifnet *ifnet, struct label *ifnet_label) { return (0); } static int stub_check_cred_relabel(struct ucred *cred, struct label *newlabel) { return (0); } static int stub_check_cred_visible(struct ucred *u1, struct ucred *u2) { return (0); } static int stub_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet, struct label *ifnetlabel, struct label *newlabel) { return (0); } static int stub_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *m, struct label *mbuflabel) { return (0); } static int stub_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel, struct mbuf *m, struct label *mlabel) { return (0); } static int stub_check_sysv_msgmsq(struct ucred *cred, struct msg *msgptr, struct label *msglabel, struct msqid_kernel *msqkptr, struct label *msqklabel) { return (0); } static int stub_check_sysv_msgrcv(struct ucred *cred, struct msg *msgptr, struct label *msglabel) { return (0); } static int stub_check_sysv_msgrmid(struct ucred *cred, struct msg *msgptr, struct label *msglabel) { return (0); } static int stub_check_sysv_msqget(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel) { return (0); } static int stub_check_sysv_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel) { return (0); } static int stub_check_sysv_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel) { return (0); } static int stub_check_sysv_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel, int cmd) { return (0); } static int stub_check_sysv_semctl(struct ucred *cred, struct semid_kernel *semakptr, struct label *semaklabel, int cmd) { return (0); } static int stub_check_sysv_semget(struct ucred *cred, struct semid_kernel *semakptr, struct label *semaklabel) { return (0); } static int stub_check_sysv_semop(struct ucred *cred, struct semid_kernel *semakptr, struct label *semaklabel, size_t accesstype) { return (0); } static int stub_check_sysv_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmseglabel, int shmflg) { return (0); } static int stub_check_sysv_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmseglabel, int cmd) { return (0); } static int stub_check_sysv_shmdt(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmseglabel) { return (0); } static int stub_check_sysv_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmseglabel, int shmflg) { return (0); } static int stub_check_kenv_dump(struct ucred *cred) { return (0); } static int stub_check_kenv_get(struct ucred *cred, char *name) { return (0); } static int stub_check_kenv_set(struct ucred *cred, char *name, char *value) { return (0); } static int stub_check_kenv_unset(struct ucred *cred, char *name) { return (0); } static int stub_check_kld_load(struct ucred *cred, struct vnode *vp, struct label *vlabel) { return (0); } static int stub_check_kld_stat(struct ucred *cred) { return (0); } static int stub_check_kld_unload(struct ucred *cred) { return (0); } static int stub_check_mount_stat(struct ucred *cred, struct mount *mp, struct label *mntlabel) { return (0); } static int stub_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp, struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data) { return (0); } static int stub_check_pipe_poll(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { return (0); } static int stub_check_pipe_read(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { return (0); } static int stub_check_pipe_relabel(struct ucred *cred, struct pipepair *pp, struct label *pipelabel, struct label *newlabel) { return (0); } static int stub_check_pipe_stat(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { return (0); } static int stub_check_pipe_write(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { return (0); } static int stub_check_posix_sem_destroy(struct ucred *cred, struct ksem *ksemptr, struct label *ks_label) { return (0); } static int stub_check_posix_sem_getvalue(struct ucred *cred, struct ksem *ksemptr, struct label *ks_label) { return (0); } static int stub_check_posix_sem_open(struct ucred *cred, struct ksem *ksemptr, struct label *ks_label) { return (0); } static int stub_check_posix_sem_post(struct ucred *cred, struct ksem *ksemptr, struct label *ks_label) { return (0); } static int stub_check_posix_sem_unlink(struct ucred *cred, struct ksem *ksemptr, struct label *ks_label) { return (0); } static int stub_check_posix_sem_wait(struct ucred *cred, struct ksem *ksemptr, struct label *ks_label) { return (0); } static int stub_check_proc_debug(struct ucred *cred, struct proc *proc) { return (0); } static int stub_check_proc_sched(struct ucred *cred, struct proc *proc) { return (0); } static int stub_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) { return (0); } static int stub_check_proc_wait(struct ucred *cred, struct proc *proc) { return (0); } static int stub_check_proc_setuid(struct ucred *cred, uid_t uid) { return (0); } static int stub_check_proc_seteuid(struct ucred *cred, uid_t euid) { return (0); } static int stub_check_proc_setgid(struct ucred *cred, gid_t gid) { return (0); } static int stub_check_proc_setegid(struct ucred *cred, gid_t egid) { return (0); } static int stub_check_proc_setgroups(struct ucred *cred, int ngroups, gid_t *gidset) { return (0); } static int stub_check_proc_setreuid(struct ucred *cred, uid_t ruid, uid_t euid) { return (0); } static int stub_check_proc_setregid(struct ucred *cred, gid_t rgid, gid_t egid) { return (0); } static int stub_check_proc_setresuid(struct ucred *cred, uid_t ruid, uid_t euid, uid_t suid) { return (0); } static int stub_check_proc_setresgid(struct ucred *cred, gid_t rgid, gid_t egid, gid_t sgid) { return (0); } static int stub_check_socket_accept(struct ucred *cred, struct socket *socket, struct label *socketlabel) { return (0); } static int stub_check_socket_bind(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct sockaddr *sockaddr) { return (0); } static int stub_check_socket_connect(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct sockaddr *sockaddr) { return (0); } static int stub_check_socket_create(struct ucred *cred, int domain, int type, int protocol) { return (0); } static int stub_check_socket_deliver(struct socket *so, struct label *socketlabel, struct mbuf *m, struct label *mbuflabel) { return (0); } static int stub_check_socket_listen(struct ucred *cred, struct socket *so, struct label *socketlabel) { return (0); } static int stub_check_socket_poll(struct ucred *cred, struct socket *so, struct label *socketlabel) { return (0); } static int stub_check_socket_receive(struct ucred *cred, struct socket *so, struct label *socketlabel) { return (0); } static int stub_check_socket_relabel(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct label *newlabel) { return (0); } static int stub_check_socket_send(struct ucred *cred, struct socket *so, struct label *socketlabel) { return (0); } static int stub_check_socket_stat(struct ucred *cred, struct socket *so, struct label *socketlabel) { return (0); } static int stub_check_socket_visible(struct ucred *cred, struct socket *socket, struct label *socketlabel) { return (0); } static int stub_check_sysarch_ioperm(struct ucred *cred) { return (0); } static int stub_check_system_acct(struct ucred *cred, struct vnode *vp, struct label *vlabel) { return (0); } static int stub_check_system_reboot(struct ucred *cred, int how) { return (0); } static int stub_check_system_settime(struct ucred *cred) { return (0); } static int stub_check_system_swapon(struct ucred *cred, struct vnode *vp, struct label *label) { return (0); } static int stub_check_system_swapoff(struct ucred *cred, struct vnode *vp, struct label *label) { return (0); } static int stub_check_system_sysctl(struct ucred *cred, struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req) { return (0); } static int stub_check_vnode_access(struct ucred *cred, struct vnode *vp, struct label *label, int acc_mode) { return (0); } static int stub_check_vnode_chdir(struct ucred *cred, struct vnode *dvp, struct label *dlabel) { return (0); } static int stub_check_vnode_chroot(struct ucred *cred, struct vnode *dvp, struct label *dlabel) { return (0); } static int stub_check_vnode_create(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct componentname *cnp, struct vattr *vap) { return (0); } static int stub_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp) { return (0); } static int stub_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type) { return (0); } static int stub_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace, const char *name) { return (0); } static int stub_check_vnode_exec(struct ucred *cred, struct vnode *vp, struct label *label, struct image_params *imgp, struct label *execlabel) { return (0); } static int stub_check_vnode_getacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type) { return (0); } static int stub_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace, const char *name, struct uio *uio) { return (0); } static int stub_check_vnode_link(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp) { return (0); } static int stub_check_vnode_listextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace) { return (0); } static int stub_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct componentname *cnp) { return (0); } static int stub_check_vnode_mmap(struct ucred *cred, struct vnode *vp, struct label *label, int prot, int flags) { return (0); } static int stub_check_vnode_open(struct ucred *cred, struct vnode *vp, struct label *filelabel, int acc_mode) { return (0); } static int stub_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label) { return (0); } static int stub_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label) { return (0); } static int stub_check_vnode_readdir(struct ucred *cred, struct vnode *vp, struct label *dlabel) { return (0); } static int stub_check_vnode_readlink(struct ucred *cred, struct vnode *vp, struct label *vnodelabel) { return (0); } static int stub_check_vnode_relabel(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct label *newlabel) { return (0); } static int stub_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp) { return (0); } static int stub_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, int samedir, struct componentname *cnp) { return (0); } static int stub_check_vnode_revoke(struct ucred *cred, struct vnode *vp, struct label *label) { return (0); } static int stub_check_vnode_setacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type, struct acl *acl) { return (0); } static int stub_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace, const char *name, struct uio *uio) { return (0); } static int stub_check_vnode_setflags(struct ucred *cred, struct vnode *vp, struct label *label, u_long flags) { return (0); } static int stub_check_vnode_setmode(struct ucred *cred, struct vnode *vp, struct label *label, mode_t mode) { return (0); } static int stub_check_vnode_setowner(struct ucred *cred, struct vnode *vp, struct label *label, uid_t uid, gid_t gid) { return (0); } static int stub_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, struct label *label, struct timespec atime, struct timespec mtime) { return (0); } static int stub_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label) { return (0); } static int stub_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label) { return (0); } static int stub_priv_check(struct ucred *cred, int priv) { return (0); } static int stub_priv_grant(struct ucred *cred, int priv) { return (EPERM); } static struct mac_policy_ops mac_stub_ops = { .mpo_destroy = stub_destroy, .mpo_init = stub_init, .mpo_syscall = stub_syscall, .mpo_init_bpfdesc_label = stub_init_label, .mpo_init_cred_label = stub_init_label, .mpo_init_devfsdirent_label = stub_init_label, .mpo_init_ifnet_label = stub_init_label, .mpo_init_inpcb_label = stub_init_label_waitcheck, .mpo_init_sysv_msgmsg_label = stub_init_label, .mpo_init_sysv_msgqueue_label = stub_init_label, .mpo_init_sysv_sem_label = stub_init_label, .mpo_init_sysv_shm_label = stub_init_label, .mpo_init_ipq_label = stub_init_label_waitcheck, .mpo_init_mbuf_label = stub_init_label_waitcheck, .mpo_init_mount_label = stub_init_label, .mpo_init_mount_fs_label = stub_init_label, .mpo_init_pipe_label = stub_init_label, .mpo_init_posix_sem_label = stub_init_label, .mpo_init_socket_label = stub_init_label_waitcheck, .mpo_init_socket_peer_label = stub_init_label_waitcheck, .mpo_init_vnode_label = stub_init_label, .mpo_destroy_bpfdesc_label = stub_destroy_label, .mpo_destroy_cred_label = stub_destroy_label, .mpo_destroy_devfsdirent_label = stub_destroy_label, .mpo_destroy_ifnet_label = stub_destroy_label, .mpo_destroy_inpcb_label = stub_destroy_label, .mpo_destroy_sysv_msgmsg_label = stub_destroy_label, .mpo_destroy_sysv_msgqueue_label = stub_destroy_label, .mpo_destroy_sysv_sem_label = stub_destroy_label, .mpo_destroy_sysv_shm_label = stub_destroy_label, .mpo_destroy_ipq_label = stub_destroy_label, .mpo_destroy_mbuf_label = stub_destroy_label, .mpo_destroy_mount_label = stub_destroy_label, .mpo_destroy_mount_fs_label = stub_destroy_label, .mpo_destroy_pipe_label = stub_destroy_label, .mpo_destroy_posix_sem_label = stub_destroy_label, .mpo_destroy_socket_label = stub_destroy_label, .mpo_destroy_socket_peer_label = stub_destroy_label, .mpo_destroy_vnode_label = stub_destroy_label, .mpo_copy_cred_label = stub_copy_label, .mpo_copy_ifnet_label = stub_copy_label, .mpo_copy_mbuf_label = stub_copy_label, .mpo_copy_pipe_label = stub_copy_label, .mpo_copy_socket_label = stub_copy_label, .mpo_copy_vnode_label = stub_copy_label, .mpo_externalize_cred_label = stub_externalize_label, .mpo_externalize_ifnet_label = stub_externalize_label, .mpo_externalize_pipe_label = stub_externalize_label, .mpo_externalize_socket_label = stub_externalize_label, .mpo_externalize_socket_peer_label = stub_externalize_label, .mpo_externalize_vnode_label = stub_externalize_label, .mpo_internalize_cred_label = stub_internalize_label, .mpo_internalize_ifnet_label = stub_internalize_label, .mpo_internalize_pipe_label = stub_internalize_label, .mpo_internalize_socket_label = stub_internalize_label, .mpo_internalize_vnode_label = stub_internalize_label, .mpo_associate_vnode_devfs = stub_associate_vnode_devfs, .mpo_associate_vnode_extattr = stub_associate_vnode_extattr, .mpo_associate_vnode_singlelabel = stub_associate_vnode_singlelabel, .mpo_create_devfs_device = stub_create_devfs_device, .mpo_create_devfs_directory = stub_create_devfs_directory, .mpo_create_devfs_symlink = stub_create_devfs_symlink, .mpo_create_sysv_msgmsg = stub_create_sysv_msgmsg, .mpo_create_sysv_msgqueue = stub_create_sysv_msgqueue, .mpo_create_sysv_sem = stub_create_sysv_sem, .mpo_create_sysv_shm = stub_create_sysv_shm, .mpo_create_vnode_extattr = stub_create_vnode_extattr, .mpo_create_mount = stub_create_mount, .mpo_relabel_vnode = stub_relabel_vnode, .mpo_setlabel_vnode_extattr = stub_setlabel_vnode_extattr, .mpo_update_devfsdirent = stub_update_devfsdirent, .mpo_create_mbuf_from_socket = stub_create_mbuf_from_socket, .mpo_create_pipe = stub_create_pipe, .mpo_create_posix_sem = stub_create_posix_sem, .mpo_create_socket = stub_create_socket, .mpo_create_socket_from_socket = stub_create_socket_from_socket, .mpo_relabel_pipe = stub_relabel_pipe, .mpo_relabel_socket = stub_relabel_socket, .mpo_set_socket_peer_from_mbuf = stub_set_socket_peer_from_mbuf, .mpo_set_socket_peer_from_socket = stub_set_socket_peer_from_socket, .mpo_create_bpfdesc = stub_create_bpfdesc, .mpo_create_ifnet = stub_create_ifnet, .mpo_create_inpcb_from_socket = stub_create_inpcb_from_socket, .mpo_create_ipq = stub_create_ipq, .mpo_create_datagram_from_ipq = stub_create_datagram_from_ipq, .mpo_create_fragment = stub_create_fragment, .mpo_create_mbuf_from_inpcb = stub_create_mbuf_from_inpcb, .mpo_create_mbuf_linklayer = stub_create_mbuf_linklayer, .mpo_create_mbuf_from_bpfdesc = stub_create_mbuf_from_bpfdesc, .mpo_create_mbuf_from_ifnet = stub_create_mbuf_from_ifnet, .mpo_create_mbuf_multicast_encap = stub_create_mbuf_multicast_encap, .mpo_create_mbuf_netlayer = stub_create_mbuf_netlayer, .mpo_fragment_match = stub_fragment_match, .mpo_reflect_mbuf_icmp = stub_reflect_mbuf_icmp, .mpo_reflect_mbuf_tcp = stub_reflect_mbuf_tcp, .mpo_relabel_ifnet = stub_relabel_ifnet, .mpo_update_ipq = stub_update_ipq, .mpo_inpcb_sosetlabel = stub_inpcb_sosetlabel, .mpo_execve_transition = stub_execve_transition, .mpo_execve_will_transition = stub_execve_will_transition, .mpo_create_proc0 = stub_create_proc0, .mpo_create_proc1 = stub_create_proc1, .mpo_relabel_cred = stub_relabel_cred, .mpo_thread_userret = stub_thread_userret, .mpo_cleanup_sysv_msgmsg = stub_cleanup_sysv_msgmsg, .mpo_cleanup_sysv_msgqueue = stub_cleanup_sysv_msgqueue, .mpo_cleanup_sysv_sem = stub_cleanup_sysv_sem, .mpo_cleanup_sysv_shm = stub_cleanup_sysv_shm, .mpo_check_bpfdesc_receive = stub_check_bpfdesc_receive, .mpo_check_cred_relabel = stub_check_cred_relabel, .mpo_check_cred_visible = stub_check_cred_visible, .mpo_check_ifnet_relabel = stub_check_ifnet_relabel, .mpo_check_ifnet_transmit = stub_check_ifnet_transmit, .mpo_check_inpcb_deliver = stub_check_inpcb_deliver, .mpo_check_sysv_msgmsq = stub_check_sysv_msgmsq, .mpo_check_sysv_msgrcv = stub_check_sysv_msgrcv, .mpo_check_sysv_msgrmid = stub_check_sysv_msgrmid, .mpo_check_sysv_msqget = stub_check_sysv_msqget, .mpo_check_sysv_msqsnd = stub_check_sysv_msqsnd, .mpo_check_sysv_msqrcv = stub_check_sysv_msqrcv, .mpo_check_sysv_msqctl = stub_check_sysv_msqctl, .mpo_check_sysv_semctl = stub_check_sysv_semctl, .mpo_check_sysv_semget = stub_check_sysv_semget, .mpo_check_sysv_semop = stub_check_sysv_semop, .mpo_check_sysv_shmat = stub_check_sysv_shmat, .mpo_check_sysv_shmctl = stub_check_sysv_shmctl, .mpo_check_sysv_shmdt = stub_check_sysv_shmdt, .mpo_check_sysv_shmget = stub_check_sysv_shmget, .mpo_check_kenv_dump = stub_check_kenv_dump, .mpo_check_kenv_get = stub_check_kenv_get, .mpo_check_kenv_set = stub_check_kenv_set, .mpo_check_kenv_unset = stub_check_kenv_unset, .mpo_check_kld_load = stub_check_kld_load, .mpo_check_kld_stat = stub_check_kld_stat, .mpo_check_kld_unload = stub_check_kld_unload, .mpo_check_mount_stat = stub_check_mount_stat, .mpo_check_pipe_ioctl = stub_check_pipe_ioctl, .mpo_check_pipe_poll = stub_check_pipe_poll, .mpo_check_pipe_read = stub_check_pipe_read, .mpo_check_pipe_relabel = stub_check_pipe_relabel, .mpo_check_pipe_stat = stub_check_pipe_stat, .mpo_check_pipe_write = stub_check_pipe_write, .mpo_check_posix_sem_destroy = stub_check_posix_sem_destroy, .mpo_check_posix_sem_getvalue = stub_check_posix_sem_getvalue, .mpo_check_posix_sem_open = stub_check_posix_sem_open, .mpo_check_posix_sem_post = stub_check_posix_sem_post, .mpo_check_posix_sem_unlink = stub_check_posix_sem_unlink, .mpo_check_posix_sem_wait = stub_check_posix_sem_wait, .mpo_check_proc_debug = stub_check_proc_debug, .mpo_check_proc_sched = stub_check_proc_sched, .mpo_check_proc_setuid = stub_check_proc_setuid, .mpo_check_proc_seteuid = stub_check_proc_seteuid, .mpo_check_proc_setgid = stub_check_proc_setgid, .mpo_check_proc_setegid = stub_check_proc_setegid, .mpo_check_proc_setgroups = stub_check_proc_setgroups, .mpo_check_proc_setreuid = stub_check_proc_setreuid, .mpo_check_proc_setregid = stub_check_proc_setregid, .mpo_check_proc_setresuid = stub_check_proc_setresuid, .mpo_check_proc_setresgid = stub_check_proc_setresgid, .mpo_check_proc_signal = stub_check_proc_signal, .mpo_check_proc_wait = stub_check_proc_wait, .mpo_check_socket_accept = stub_check_socket_accept, .mpo_check_socket_bind = stub_check_socket_bind, .mpo_check_socket_connect = stub_check_socket_connect, .mpo_check_socket_create = stub_check_socket_create, .mpo_check_socket_deliver = stub_check_socket_deliver, .mpo_check_socket_listen = stub_check_socket_listen, .mpo_check_socket_poll = stub_check_socket_poll, .mpo_check_socket_receive = stub_check_socket_receive, .mpo_check_socket_relabel = stub_check_socket_relabel, .mpo_check_socket_send = stub_check_socket_send, .mpo_check_socket_stat = stub_check_socket_stat, .mpo_check_socket_visible = stub_check_socket_visible, .mpo_check_sysarch_ioperm = stub_check_sysarch_ioperm, .mpo_check_system_acct = stub_check_system_acct, .mpo_check_system_reboot = stub_check_system_reboot, .mpo_check_system_settime = stub_check_system_settime, .mpo_check_system_swapon = stub_check_system_swapon, .mpo_check_system_swapoff = stub_check_system_swapoff, .mpo_check_system_sysctl = stub_check_system_sysctl, .mpo_check_vnode_access = stub_check_vnode_access, .mpo_check_vnode_chdir = stub_check_vnode_chdir, .mpo_check_vnode_chroot = stub_check_vnode_chroot, .mpo_check_vnode_create = stub_check_vnode_create, .mpo_check_vnode_delete = stub_check_vnode_delete, .mpo_check_vnode_deleteacl = stub_check_vnode_deleteacl, .mpo_check_vnode_deleteextattr = stub_check_vnode_deleteextattr, .mpo_check_vnode_exec = stub_check_vnode_exec, .mpo_check_vnode_getacl = stub_check_vnode_getacl, .mpo_check_vnode_getextattr = stub_check_vnode_getextattr, .mpo_check_vnode_link = stub_check_vnode_link, .mpo_check_vnode_listextattr = stub_check_vnode_listextattr, .mpo_check_vnode_lookup = stub_check_vnode_lookup, .mpo_check_vnode_mmap = stub_check_vnode_mmap, .mpo_check_vnode_open = stub_check_vnode_open, .mpo_check_vnode_poll = stub_check_vnode_poll, .mpo_check_vnode_read = stub_check_vnode_read, .mpo_check_vnode_readdir = stub_check_vnode_readdir, .mpo_check_vnode_readlink = stub_check_vnode_readlink, .mpo_check_vnode_relabel = stub_check_vnode_relabel, .mpo_check_vnode_rename_from = stub_check_vnode_rename_from, .mpo_check_vnode_rename_to = stub_check_vnode_rename_to, .mpo_check_vnode_revoke = stub_check_vnode_revoke, .mpo_check_vnode_setacl = stub_check_vnode_setacl, .mpo_check_vnode_setextattr = stub_check_vnode_setextattr, .mpo_check_vnode_setflags = stub_check_vnode_setflags, .mpo_check_vnode_setmode = stub_check_vnode_setmode, .mpo_check_vnode_setowner = stub_check_vnode_setowner, .mpo_check_vnode_setutimes = stub_check_vnode_setutimes, .mpo_check_vnode_stat = stub_check_vnode_stat, .mpo_check_vnode_write = stub_check_vnode_write, .mpo_priv_check = stub_priv_check, .mpo_priv_grant = stub_priv_grant, }; MAC_POLICY_SET(&mac_stub_ops, mac_stub, "TrustedBSD MAC/Stub", MPC_LOADTIME_FLAG_UNLOADOK, NULL); Index: head/sys/security/mac_test/mac_test.c =================================================================== --- head/sys/security/mac_test/mac_test.c (revision 164183) +++ head/sys/security/mac_test/mac_test.c (revision 164184) @@ -1,2615 +1,2614 @@ /*- * Copyright (c) 1999-2002 Robert N. M. Watson * Copyright (c) 2001-2005 McAfee, Inc. * All rights reserved. * * This software was developed by Robert Watson for the TrustedBSD Project. * * This software was developed for the FreeBSD Project in part by McAfee * Research, the Security Research Division of McAfee, Inc. under * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA * CHATS research program. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Developed by the TrustedBSD Project. * Generic mandatory access module that does nothing. */ #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include - -#include #include #include #include #include #include #include #include SYSCTL_DECL(_security_mac); SYSCTL_NODE(_security_mac, OID_AUTO, test, CTLFLAG_RW, 0, "TrustedBSD mac_test policy controls"); static int mac_test_enabled = 1; SYSCTL_INT(_security_mac_test, OID_AUTO, enabled, CTLFLAG_RW, &mac_test_enabled, 0, "Enforce test policy"); #define BPFMAGIC 0xfe1ad1b6 #define DEVFSMAGIC 0x9ee79c32 #define IFNETMAGIC 0xc218b120 #define INPCBMAGIC 0x4440f7bb #define IPQMAGIC 0x206188ef #define MBUFMAGIC 0xbbefa5bb #define MOUNTMAGIC 0xc7c46e47 #define SOCKETMAGIC 0x9199c6cd #define SYSVIPCMSQMAGIC 0xea672391 #define SYSVIPCMSGMAGIC 0x8bbba61e #define SYSVIPCSEMMAGIC 0x896e8a0b #define SYSVIPCSHMMAGIC 0x76119ab0 #define PIPEMAGIC 0xdc6c9919 #define POSIXSEMMAGIC 0x78ae980c #define PROCMAGIC 0x3b4be98f #define CREDMAGIC 0x9a5a4987 #define VNODEMAGIC 0x1a67a45c #define EXMAGIC 0x849ba1fd #define SLOT(x) LABEL_TO_SLOT((x), test_slot).l_long #define ASSERT_BPF_LABEL(x) KASSERT(SLOT(x) == BPFMAGIC || \ SLOT(x) == 0, ("%s: Bad BPF label", __func__ )) #define ASSERT_DEVFS_LABEL(x) KASSERT(SLOT(x) == DEVFSMAGIC || \ SLOT(x) == 0, ("%s: Bad DEVFS label", __func__ )) #define ASSERT_IFNET_LABEL(x) KASSERT(SLOT(x) == IFNETMAGIC || \ SLOT(x) == 0, ("%s: Bad IFNET label", __func__ )) #define ASSERT_INPCB_LABEL(x) KASSERT(SLOT(x) == INPCBMAGIC || \ SLOT(x) == 0, ("%s: Bad INPCB label", __func__ )) #define ASSERT_IPQ_LABEL(x) KASSERT(SLOT(x) == IPQMAGIC || \ SLOT(x) == 0, ("%s: Bad IPQ label", __func__ )) #define ASSERT_MBUF_LABEL(x) KASSERT(x == NULL || \ SLOT(x) == MBUFMAGIC || SLOT(x) == 0, \ ("%s: Bad MBUF label", __func__ )) #define ASSERT_MOUNT_LABEL(x) KASSERT(SLOT(x) == MOUNTMAGIC || \ SLOT(x) == 0, ("%s: Bad MOUNT label", __func__ )) #define ASSERT_SOCKET_LABEL(x) KASSERT(SLOT(x) == SOCKETMAGIC || \ SLOT(x) == 0, ("%s: Bad SOCKET label", __func__ )) #define ASSERT_SYSVIPCMSQ_LABEL(x) KASSERT(SLOT(x) == SYSVIPCMSQMAGIC || \ SLOT(x) == 0, ("%s: Bad SYSVIPCMSQ label", __func__ )) #define ASSERT_SYSVIPCMSG_LABEL(x) KASSERT(SLOT(x) == SYSVIPCMSGMAGIC || \ SLOT(x) == 0, ("%s: Bad SYSVIPCMSG label", __func__ )) #define ASSERT_SYSVIPCSEM_LABEL(x) KASSERT(SLOT(x) == SYSVIPCSEMMAGIC || \ SLOT(x) == 0, ("%s: Bad SYSVIPCSEM label", __func__ )) #define ASSERT_SYSVIPCSHM_LABEL(x) KASSERT(SLOT(x) == SYSVIPCSHMMAGIC || \ SLOT(x) == 0, ("%s: Bad SYSVIPCSHM label", __func__ )) #define ASSERT_PIPE_LABEL(x) KASSERT(SLOT(x) == PIPEMAGIC || \ SLOT(x) == 0, ("%s: Bad PIPE label", __func__ )) #define ASSERT_POSIX_LABEL(x) KASSERT(SLOT(x) == POSIXSEMMAGIC || \ SLOT(x) == 0, ("%s: Bad POSIX ksem label", __func__ )) #define ASSERT_PROC_LABEL(x) KASSERT(SLOT(x) == PROCMAGIC || \ SLOT(x) == 0, ("%s: Bad PROC label", __func__ )) #define ASSERT_CRED_LABEL(x) KASSERT(SLOT(x) == CREDMAGIC || \ SLOT(x) == 0, ("%s: Bad CRED label", __func__ )) #define ASSERT_VNODE_LABEL(x) KASSERT(SLOT(x) == VNODEMAGIC || \ SLOT(x) == 0, ("%s: Bad VNODE label", __func__ )) static int test_slot; SYSCTL_INT(_security_mac_test, OID_AUTO, slot, CTLFLAG_RD, &test_slot, 0, "Slot allocated by framework"); static int init_count_bpfdesc; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_bpfdesc, CTLFLAG_RD, &init_count_bpfdesc, 0, "bpfdesc init calls"); static int init_count_cred; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_cred, CTLFLAG_RD, &init_count_cred, 0, "cred init calls"); static int init_count_devfsdirent; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_devfsdirent, CTLFLAG_RD, &init_count_devfsdirent, 0, "devfsdirent init calls"); static int init_count_ifnet; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_ifnet, CTLFLAG_RD, &init_count_ifnet, 0, "ifnet init calls"); static int init_count_inpcb; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_inpcb, CTLFLAG_RD, &init_count_inpcb, 0, "inpcb init calls"); static int init_count_sysv_msg; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_sysv_msg, CTLFLAG_RD, &init_count_sysv_msg, 0, "ipc_msg init calls"); static int init_count_sysv_msq; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_sysv_msq, CTLFLAG_RD, &init_count_sysv_msq, 0, "ipc_msq init calls"); static int init_count_sysv_sem; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_sysv_sem, CTLFLAG_RD, &init_count_sysv_sem, 0, "ipc_sema init calls"); static int init_count_sysv_shm; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_sysv_shm, CTLFLAG_RD, &init_count_sysv_shm, 0, "ipc_shm init calls"); static int init_count_ipq; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_ipq, CTLFLAG_RD, &init_count_ipq, 0, "ipq init calls"); static int init_count_mbuf; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_mbuf, CTLFLAG_RD, &init_count_mbuf, 0, "mbuf init calls"); static int init_count_mount; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_mount, CTLFLAG_RD, &init_count_mount, 0, "mount init calls"); static int init_count_mount_fslabel; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_mount_fslabel, CTLFLAG_RD, &init_count_mount_fslabel, 0, "mount_fslabel init calls"); static int init_count_socket; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_socket, CTLFLAG_RD, &init_count_socket, 0, "socket init calls"); static int init_count_socket_peerlabel; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_socket_peerlabel, CTLFLAG_RD, &init_count_socket_peerlabel, 0, "socket_peerlabel init calls"); static int init_count_pipe; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_pipe, CTLFLAG_RD, &init_count_pipe, 0, "pipe init calls"); static int init_count_posixsems; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_posixsems, CTLFLAG_RD, &init_count_posixsems, 0, "posix sems init calls"); static int init_count_proc; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_proc, CTLFLAG_RD, &init_count_proc, 0, "proc init calls"); static int init_count_vnode; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_vnode, CTLFLAG_RD, &init_count_vnode, 0, "vnode init calls"); static int destroy_count_bpfdesc; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_bpfdesc, CTLFLAG_RD, &destroy_count_bpfdesc, 0, "bpfdesc destroy calls"); static int destroy_count_cred; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_cred, CTLFLAG_RD, &destroy_count_cred, 0, "cred destroy calls"); static int destroy_count_devfsdirent; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_devfsdirent, CTLFLAG_RD, &destroy_count_devfsdirent, 0, "devfsdirent destroy calls"); static int destroy_count_ifnet; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_ifnet, CTLFLAG_RD, &destroy_count_ifnet, 0, "ifnet destroy calls"); static int destroy_count_inpcb; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_inpcb, CTLFLAG_RD, &destroy_count_inpcb, 0, "inpcb destroy calls"); static int destroy_count_sysv_msg; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_sysv_msg, CTLFLAG_RD, &destroy_count_sysv_msg, 0, "ipc_msg destroy calls"); static int destroy_count_sysv_msq; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_sysv_msq, CTLFLAG_RD, &destroy_count_sysv_msq, 0, "ipc_msq destroy calls"); static int destroy_count_sysv_sem; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_sysv_sem, CTLFLAG_RD, &destroy_count_sysv_sem, 0, "ipc_sema destroy calls"); static int destroy_count_sysv_shm; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_sysv_shm, CTLFLAG_RD, &destroy_count_sysv_shm, 0, "ipc_shm destroy calls"); static int destroy_count_ipq; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_ipq, CTLFLAG_RD, &destroy_count_ipq, 0, "ipq destroy calls"); static int destroy_count_mbuf; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_mbuf, CTLFLAG_RD, &destroy_count_mbuf, 0, "mbuf destroy calls"); static int destroy_count_mount; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_mount, CTLFLAG_RD, &destroy_count_mount, 0, "mount destroy calls"); static int destroy_count_mount_fslabel; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_mount_fslabel, CTLFLAG_RD, &destroy_count_mount_fslabel, 0, "mount_fslabel destroy calls"); static int destroy_count_socket; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_socket, CTLFLAG_RD, &destroy_count_socket, 0, "socket destroy calls"); static int destroy_count_socket_peerlabel; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_socket_peerlabel, CTLFLAG_RD, &destroy_count_socket_peerlabel, 0, "socket_peerlabel destroy calls"); static int destroy_count_pipe; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_pipe, CTLFLAG_RD, &destroy_count_pipe, 0, "pipe destroy calls"); static int destroy_count_posixsems; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_posixsems, CTLFLAG_RD, &destroy_count_posixsems, 0, "posix sems destroy calls"); static int destroy_count_proc; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_proc, CTLFLAG_RD, &destroy_count_proc, 0, "proc destroy calls"); static int destroy_count_vnode; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_vnode, CTLFLAG_RD, &destroy_count_vnode, 0, "vnode destroy calls"); static int externalize_count; SYSCTL_INT(_security_mac_test, OID_AUTO, externalize_count, CTLFLAG_RD, &externalize_count, 0, "Subject/object externalize calls"); static int internalize_count; SYSCTL_INT(_security_mac_test, OID_AUTO, internalize_count, CTLFLAG_RD, &internalize_count, 0, "Subject/object internalize calls"); #ifdef KDB #define DEBUGGER(x) kdb_enter(x) #else #define DEBUGGER(x) printf("mac_test: %s\n", (x)) #endif /* * Policy module operations. */ static void mac_test_destroy(struct mac_policy_conf *conf) { } static void mac_test_init(struct mac_policy_conf *conf) { } static int mac_test_syscall(struct thread *td, int call, void *arg) { return (0); } /* * Label operations. */ static void mac_test_init_bpfdesc_label(struct label *label) { SLOT(label) = BPFMAGIC; atomic_add_int(&init_count_bpfdesc, 1); } static void mac_test_init_cred_label(struct label *label) { SLOT(label) = CREDMAGIC; atomic_add_int(&init_count_cred, 1); } static void mac_test_init_devfsdirent_label(struct label *label) { SLOT(label) = DEVFSMAGIC; atomic_add_int(&init_count_devfsdirent, 1); } static void mac_test_init_ifnet_label(struct label *label) { SLOT(label) = IFNETMAGIC; atomic_add_int(&init_count_ifnet, 1); } static int mac_test_init_inpcb_label(struct label *label, int flag) { if (flag & M_WAITOK) WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "mac_test_init_inpcb_label() at %s:%d", __FILE__, __LINE__); SLOT(label) = INPCBMAGIC; atomic_add_int(&init_count_inpcb, 1); return (0); } static void mac_test_init_sysv_msgmsg_label(struct label *label) { SLOT(label) = SYSVIPCMSGMAGIC; atomic_add_int(&init_count_sysv_msg, 1); } static void mac_test_init_sysv_msgqueue_label(struct label *label) { SLOT(label) = SYSVIPCMSQMAGIC; atomic_add_int(&init_count_sysv_msq, 1); } static void mac_test_init_sysv_sem_label(struct label *label) { SLOT(label) = SYSVIPCSEMMAGIC; atomic_add_int(&init_count_sysv_sem, 1); } static void mac_test_init_sysv_shm_label(struct label *label) { SLOT(label) = SYSVIPCSHMMAGIC; atomic_add_int(&init_count_sysv_shm, 1); } static int mac_test_init_ipq_label(struct label *label, int flag) { if (flag & M_WAITOK) WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "mac_test_init_ipq_label() at %s:%d", __FILE__, __LINE__); SLOT(label) = IPQMAGIC; atomic_add_int(&init_count_ipq, 1); return (0); } static int mac_test_init_mbuf_label(struct label *label, int flag) { if (flag & M_WAITOK) WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "mac_test_init_mbuf_label() at %s:%d", __FILE__, __LINE__); SLOT(label) = MBUFMAGIC; atomic_add_int(&init_count_mbuf, 1); return (0); } static void mac_test_init_mount_label(struct label *label) { SLOT(label) = MOUNTMAGIC; atomic_add_int(&init_count_mount, 1); } static void mac_test_init_mount_fs_label(struct label *label) { SLOT(label) = MOUNTMAGIC; atomic_add_int(&init_count_mount_fslabel, 1); } static int mac_test_init_socket_label(struct label *label, int flag) { if (flag & M_WAITOK) WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "mac_test_init_socket_label() at %s:%d", __FILE__, __LINE__); SLOT(label) = SOCKETMAGIC; atomic_add_int(&init_count_socket, 1); return (0); } static int mac_test_init_socket_peer_label(struct label *label, int flag) { if (flag & M_WAITOK) WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "mac_test_init_socket_peer_label() at %s:%d", __FILE__, __LINE__); SLOT(label) = SOCKETMAGIC; atomic_add_int(&init_count_socket_peerlabel, 1); return (0); } static void mac_test_init_pipe_label(struct label *label) { SLOT(label) = PIPEMAGIC; atomic_add_int(&init_count_pipe, 1); } static void mac_test_init_posix_sem_label(struct label *label) { SLOT(label) = POSIXSEMMAGIC; atomic_add_int(&init_count_posixsems, 1); } static void mac_test_init_proc_label(struct label *label) { SLOT(label) = PROCMAGIC; atomic_add_int(&init_count_proc, 1); } static void mac_test_init_vnode_label(struct label *label) { SLOT(label) = VNODEMAGIC; atomic_add_int(&init_count_vnode, 1); } static void mac_test_destroy_bpfdesc_label(struct label *label) { if (SLOT(label) == BPFMAGIC || SLOT(label) == 0) { atomic_add_int(&destroy_count_bpfdesc, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_bpfdesc: dup destroy"); } else { DEBUGGER("mac_test_destroy_bpfdesc: corrupted label"); } } static void mac_test_destroy_cred_label(struct label *label) { if (SLOT(label) == CREDMAGIC || SLOT(label) == 0) { atomic_add_int(&destroy_count_cred, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_cred: dup destroy"); } else { DEBUGGER("mac_test_destroy_cred: corrupted label"); } } static void mac_test_destroy_devfsdirent_label(struct label *label) { if (SLOT(label) == DEVFSMAGIC || SLOT(label) == 0) { atomic_add_int(&destroy_count_devfsdirent, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_devfsdirent: dup destroy"); } else { DEBUGGER("mac_test_destroy_devfsdirent: corrupted label"); } } static void mac_test_destroy_ifnet_label(struct label *label) { if (SLOT(label) == IFNETMAGIC || SLOT(label) == 0) { atomic_add_int(&destroy_count_ifnet, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_ifnet: dup destroy"); } else { DEBUGGER("mac_test_destroy_ifnet: corrupted label"); } } static void mac_test_destroy_inpcb_label(struct label *label) { if (SLOT(label) == INPCBMAGIC || SLOT(label) == 0) { atomic_add_int(&destroy_count_inpcb, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_inpcb: dup destroy"); } else { DEBUGGER("mac_test_destroy_inpcb: corrupted label"); } } static void mac_test_destroy_sysv_msgmsg_label(struct label *label) { if (SLOT(label) == SYSVIPCMSGMAGIC || SLOT(label) == 0) { atomic_add_int(&destroy_count_sysv_msg, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_sysv_msgmsg_label: dup destroy"); } else { DEBUGGER( "mac_test_destroy_sysv_msgmsg_label: corrupted label"); } } static void mac_test_destroy_sysv_msgqueue_label(struct label *label) { if (SLOT(label) == SYSVIPCMSQMAGIC || SLOT(label) == 0) { atomic_add_int(&destroy_count_sysv_msq, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_sysv_msgqueue_label: dup destroy"); } else { DEBUGGER( "mac_test_destroy_sysv_msgqueue_label: corrupted label"); } } static void mac_test_destroy_sysv_sem_label(struct label *label) { if (SLOT(label) == SYSVIPCSEMMAGIC || SLOT(label) == 0) { atomic_add_int(&destroy_count_sysv_sem, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_sysv_sem_label: dup destroy"); } else { DEBUGGER("mac_test_destroy_sysv_sem_label: corrupted label"); } } static void mac_test_destroy_sysv_shm_label(struct label *label) { if (SLOT(label) == SYSVIPCSHMMAGIC || SLOT(label) == 0) { atomic_add_int(&destroy_count_sysv_shm, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_sysv_shm_label: dup destroy"); } else { DEBUGGER("mac_test_destroy_sysv_shm_label: corrupted label"); } } static void mac_test_destroy_ipq_label(struct label *label) { if (SLOT(label) == IPQMAGIC || SLOT(label) == 0) { atomic_add_int(&destroy_count_ipq, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_ipq: dup destroy"); } else { DEBUGGER("mac_test_destroy_ipq: corrupted label"); } } static void mac_test_destroy_mbuf_label(struct label *label) { /* * If we're loaded dynamically, there may be mbufs in flight that * didn't have label storage allocated for them. Handle this * gracefully. */ if (label == NULL) return; if (SLOT(label) == MBUFMAGIC || SLOT(label) == 0) { atomic_add_int(&destroy_count_mbuf, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_mbuf: dup destroy"); } else { DEBUGGER("mac_test_destroy_mbuf: corrupted label"); } } static void mac_test_destroy_mount_label(struct label *label) { if ((SLOT(label) == MOUNTMAGIC || SLOT(label) == 0)) { atomic_add_int(&destroy_count_mount, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_mount: dup destroy"); } else { DEBUGGER("mac_test_destroy_mount: corrupted label"); } } static void mac_test_destroy_mount_fs_label(struct label *label) { if ((SLOT(label) == MOUNTMAGIC || SLOT(label) == 0)) { atomic_add_int(&destroy_count_mount_fslabel, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_mount_fslabel: dup destroy"); } else { DEBUGGER("mac_test_destroy_mount_fslabel: corrupted label"); } } static void mac_test_destroy_socket_label(struct label *label) { if ((SLOT(label) == SOCKETMAGIC || SLOT(label) == 0)) { atomic_add_int(&destroy_count_socket, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_socket: dup destroy"); } else { DEBUGGER("mac_test_destroy_socket: corrupted label"); } } static void mac_test_destroy_socket_peer_label(struct label *label) { if ((SLOT(label) == SOCKETMAGIC || SLOT(label) == 0)) { atomic_add_int(&destroy_count_socket_peerlabel, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_socket_peerlabel: dup destroy"); } else { DEBUGGER("mac_test_destroy_socket_peerlabel: corrupted label"); } } static void mac_test_destroy_pipe_label(struct label *label) { if ((SLOT(label) == PIPEMAGIC || SLOT(label) == 0)) { atomic_add_int(&destroy_count_pipe, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_pipe: dup destroy"); } else { DEBUGGER("mac_test_destroy_pipe: corrupted label"); } } static void mac_test_destroy_posix_sem_label(struct label *label) { if ((SLOT(label) == POSIXSEMMAGIC || SLOT(label) == 0)) { atomic_add_int(&destroy_count_posixsems, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_posix_sem: dup destroy"); } else { DEBUGGER("mac_test_destroy_posix_sem: corrupted label"); } } static void mac_test_destroy_proc_label(struct label *label) { if ((SLOT(label) == PROCMAGIC || SLOT(label) == 0)) { atomic_add_int(&destroy_count_proc, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_proc: dup destroy"); } else { DEBUGGER("mac_test_destroy_proc: corrupted label"); } } static void mac_test_destroy_vnode_label(struct label *label) { if (SLOT(label) == VNODEMAGIC || SLOT(label) == 0) { atomic_add_int(&destroy_count_vnode, 1); SLOT(label) = EXMAGIC; } else if (SLOT(label) == EXMAGIC) { DEBUGGER("mac_test_destroy_vnode: dup destroy"); } else { DEBUGGER("mac_test_destroy_vnode: corrupted label"); } } static void mac_test_copy_cred_label(struct label *src, struct label *dest) { ASSERT_CRED_LABEL(src); ASSERT_CRED_LABEL(dest); } static void mac_test_copy_ifnet_label(struct label *src, struct label *dest) { ASSERT_IFNET_LABEL(src); ASSERT_IFNET_LABEL(dest); } static void mac_test_copy_mbuf_label(struct label *src, struct label *dest) { ASSERT_MBUF_LABEL(src); ASSERT_MBUF_LABEL(dest); } static void mac_test_copy_pipe_label(struct label *src, struct label *dest) { ASSERT_PIPE_LABEL(src); ASSERT_PIPE_LABEL(dest); } static void mac_test_copy_socket_label(struct label *src, struct label *dest) { ASSERT_SOCKET_LABEL(src); ASSERT_SOCKET_LABEL(dest); } static void mac_test_copy_vnode_label(struct label *src, struct label *dest) { ASSERT_VNODE_LABEL(src); ASSERT_VNODE_LABEL(dest); } static int mac_test_externalize_label(struct label *label, char *element_name, struct sbuf *sb, int *claimed) { atomic_add_int(&externalize_count, 1); KASSERT(SLOT(label) != EXMAGIC, ("mac_test_externalize_label: destroyed label")); return (0); } static int mac_test_internalize_label(struct label *label, char *element_name, char *element_data, int *claimed) { atomic_add_int(&internalize_count, 1); KASSERT(SLOT(label) != EXMAGIC, ("mac_test_internalize_label: destroyed label")); return (0); } /* * Labeling event operations: file system objects, and things that look * a lot like file system objects. */ static void mac_test_associate_vnode_devfs(struct mount *mp, struct label *fslabel, struct devfs_dirent *de, struct label *delabel, struct vnode *vp, struct label *vlabel) { ASSERT_MOUNT_LABEL(fslabel); ASSERT_DEVFS_LABEL(delabel); ASSERT_VNODE_LABEL(vlabel); } static int mac_test_associate_vnode_extattr(struct mount *mp, struct label *fslabel, struct vnode *vp, struct label *vlabel) { ASSERT_MOUNT_LABEL(fslabel); ASSERT_VNODE_LABEL(vlabel); return (0); } static void mac_test_associate_vnode_singlelabel(struct mount *mp, struct label *fslabel, struct vnode *vp, struct label *vlabel) { ASSERT_MOUNT_LABEL(fslabel); ASSERT_VNODE_LABEL(vlabel); } static void mac_test_create_devfs_device(struct ucred *cred, struct mount *mp, struct cdev *dev, struct devfs_dirent *devfs_dirent, struct label *label) { if (cred != NULL) { ASSERT_CRED_LABEL(cred->cr_label); } ASSERT_DEVFS_LABEL(label); } static void mac_test_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label) { ASSERT_DEVFS_LABEL(label); } static void mac_test_create_devfs_symlink(struct ucred *cred, struct mount *mp, struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de, struct label *delabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_DEVFS_LABEL(ddlabel); ASSERT_DEVFS_LABEL(delabel); } static int mac_test_create_vnode_extattr(struct ucred *cred, struct mount *mp, struct label *fslabel, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *vlabel, struct componentname *cnp) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_MOUNT_LABEL(fslabel); ASSERT_VNODE_LABEL(dlabel); return (0); } static void mac_test_create_mount(struct ucred *cred, struct mount *mp, struct label *mntlabel, struct label *fslabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_MOUNT_LABEL(mntlabel); ASSERT_MOUNT_LABEL(fslabel); } static void mac_test_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct label *label) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(vnodelabel); ASSERT_VNODE_LABEL(label); } static int mac_test_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, struct label *vlabel, struct label *intlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(vlabel); ASSERT_VNODE_LABEL(intlabel); return (0); } static void mac_test_update_devfsdirent(struct mount *mp, struct devfs_dirent *devfs_dirent, struct label *direntlabel, struct vnode *vp, struct label *vnodelabel) { ASSERT_DEVFS_LABEL(direntlabel); ASSERT_VNODE_LABEL(vnodelabel); } /* * Labeling event operations: IPC object. */ static void mac_test_create_mbuf_from_socket(struct socket *so, struct label *socketlabel, struct mbuf *m, struct label *mbuflabel) { ASSERT_SOCKET_LABEL(socketlabel); ASSERT_MBUF_LABEL(mbuflabel); } static void mac_test_create_socket(struct ucred *cred, struct socket *socket, struct label *socketlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SOCKET_LABEL(socketlabel); } static void mac_test_create_pipe(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_PIPE_LABEL(pipelabel); } static void mac_test_create_posix_sem(struct ucred *cred, struct ksem *ksem, struct label *posixlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_POSIX_LABEL(posixlabel); } static void mac_test_create_socket_from_socket(struct socket *oldsocket, struct label *oldsocketlabel, struct socket *newsocket, struct label *newsocketlabel) { ASSERT_SOCKET_LABEL(oldsocketlabel); ASSERT_SOCKET_LABEL(newsocketlabel); } static void mac_test_relabel_socket(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct label *newlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SOCKET_LABEL(newlabel); } static void mac_test_relabel_pipe(struct ucred *cred, struct pipepair *pp, struct label *pipelabel, struct label *newlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_PIPE_LABEL(pipelabel); ASSERT_PIPE_LABEL(newlabel); } static void mac_test_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel, struct socket *socket, struct label *socketpeerlabel) { ASSERT_MBUF_LABEL(mbuflabel); ASSERT_SOCKET_LABEL(socketpeerlabel); } /* * Labeling event operations: network objects. */ static void mac_test_set_socket_peer_from_socket(struct socket *oldsocket, struct label *oldsocketlabel, struct socket *newsocket, struct label *newsocketpeerlabel) { ASSERT_SOCKET_LABEL(oldsocketlabel); ASSERT_SOCKET_LABEL(newsocketpeerlabel); } static void mac_test_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d, struct label *bpflabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_BPF_LABEL(bpflabel); } static void mac_test_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel, struct mbuf *datagram, struct label *datagramlabel) { ASSERT_IPQ_LABEL(ipqlabel); ASSERT_MBUF_LABEL(datagramlabel); } static void mac_test_create_fragment(struct mbuf *datagram, struct label *datagramlabel, struct mbuf *fragment, struct label *fragmentlabel) { ASSERT_MBUF_LABEL(datagramlabel); ASSERT_MBUF_LABEL(fragmentlabel); } static void mac_test_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel) { ASSERT_IFNET_LABEL(ifnetlabel); } static void mac_test_create_inpcb_from_socket(struct socket *so, struct label *solabel, struct inpcb *inp, struct label *inplabel) { ASSERT_SOCKET_LABEL(solabel); ASSERT_INPCB_LABEL(inplabel); } static void mac_test_create_sysv_msgmsg(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqlabel, struct msg *msgptr, struct label *msglabel) { ASSERT_SYSVIPCMSG_LABEL(msglabel); ASSERT_SYSVIPCMSQ_LABEL(msqlabel); } static void mac_test_create_sysv_msgqueue(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqlabel) { ASSERT_SYSVIPCMSQ_LABEL(msqlabel); } static void mac_test_create_sysv_sem(struct ucred *cred, struct semid_kernel *semakptr, struct label *semalabel) { ASSERT_SYSVIPCSEM_LABEL(semalabel); } static void mac_test_create_sysv_shm(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmlabel) { ASSERT_SYSVIPCSHM_LABEL(shmlabel); } static void mac_test_create_ipq(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel) { ASSERT_MBUF_LABEL(fragmentlabel); ASSERT_IPQ_LABEL(ipqlabel); } static void mac_test_create_mbuf_from_inpcb(struct inpcb *inp, struct label *inplabel, struct mbuf *m, struct label *mlabel) { ASSERT_INPCB_LABEL(inplabel); ASSERT_MBUF_LABEL(mlabel); } static void mac_test_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *mbuf, struct label *mbuflabel) { ASSERT_IFNET_LABEL(ifnetlabel); ASSERT_MBUF_LABEL(mbuflabel); } static void mac_test_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel, struct mbuf *mbuf, struct label *mbuflabel) { ASSERT_BPF_LABEL(bpflabel); ASSERT_MBUF_LABEL(mbuflabel); } static void mac_test_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *m, struct label *mbuflabel) { ASSERT_IFNET_LABEL(ifnetlabel); ASSERT_MBUF_LABEL(mbuflabel); } static void mac_test_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *newmbuf, struct label *newmbuflabel) { ASSERT_MBUF_LABEL(oldmbuflabel); ASSERT_IFNET_LABEL(ifnetlabel); ASSERT_MBUF_LABEL(newmbuflabel); } static void mac_test_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel, struct mbuf *newmbuf, struct label *newmbuflabel) { ASSERT_MBUF_LABEL(oldmbuflabel); ASSERT_MBUF_LABEL(newmbuflabel); } static int mac_test_fragment_match(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel) { ASSERT_MBUF_LABEL(fragmentlabel); ASSERT_IPQ_LABEL(ipqlabel); return (1); } static void mac_test_reflect_mbuf_icmp(struct mbuf *m, struct label *mlabel) { ASSERT_MBUF_LABEL(mlabel); } static void mac_test_reflect_mbuf_tcp(struct mbuf *m, struct label *mlabel) { ASSERT_MBUF_LABEL(mlabel); } static void mac_test_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet, struct label *ifnetlabel, struct label *newlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_IFNET_LABEL(ifnetlabel); ASSERT_IFNET_LABEL(newlabel); } static void mac_test_update_ipq(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel) { ASSERT_MBUF_LABEL(fragmentlabel); ASSERT_IPQ_LABEL(ipqlabel); } static void mac_test_inpcb_sosetlabel(struct socket *so, struct label *solabel, struct inpcb *inp, struct label *inplabel) { ASSERT_SOCKET_LABEL(solabel); ASSERT_INPCB_LABEL(inplabel); } /* * Labeling event operations: processes. */ static void mac_test_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, struct label *filelabel, struct label *interpvnodelabel, struct image_params *imgp, struct label *execlabel) { ASSERT_CRED_LABEL(old->cr_label); ASSERT_CRED_LABEL(new->cr_label); ASSERT_VNODE_LABEL(filelabel); if (interpvnodelabel != NULL) { ASSERT_VNODE_LABEL(interpvnodelabel); } if (execlabel != NULL) { ASSERT_CRED_LABEL(execlabel); } } static int mac_test_execve_will_transition(struct ucred *old, struct vnode *vp, struct label *filelabel, struct label *interpvnodelabel, struct image_params *imgp, struct label *execlabel) { ASSERT_CRED_LABEL(old->cr_label); ASSERT_VNODE_LABEL(filelabel); if (interpvnodelabel != NULL) { ASSERT_VNODE_LABEL(interpvnodelabel); } if (execlabel != NULL) { ASSERT_CRED_LABEL(execlabel); } return (0); } static void mac_test_create_proc0(struct ucred *cred) { ASSERT_CRED_LABEL(cred->cr_label); } static void mac_test_create_proc1(struct ucred *cred) { ASSERT_CRED_LABEL(cred->cr_label); } static void mac_test_relabel_cred(struct ucred *cred, struct label *newlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_CRED_LABEL(newlabel); } static void mac_test_thread_userret(struct thread *td) { printf("mac_test_thread_userret(process = %d)\n", curthread->td_proc->p_pid); } /* * Label cleanup/flush operations */ static void mac_test_cleanup_sysv_msgmsg(struct label *msglabel) { ASSERT_SYSVIPCMSG_LABEL(msglabel); } static void mac_test_cleanup_sysv_msgqueue(struct label *msqlabel) { ASSERT_SYSVIPCMSQ_LABEL(msqlabel); } static void mac_test_cleanup_sysv_sem(struct label *semalabel) { ASSERT_SYSVIPCSEM_LABEL(semalabel); } static void mac_test_cleanup_sysv_shm(struct label *shmlabel) { ASSERT_SYSVIPCSHM_LABEL(shmlabel); } /* * Access control checks. */ static int mac_test_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel, struct ifnet *ifnet, struct label *ifnetlabel) { ASSERT_BPF_LABEL(bpflabel); ASSERT_IFNET_LABEL(ifnetlabel); return (0); } static int mac_test_check_cred_relabel(struct ucred *cred, struct label *newlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_CRED_LABEL(newlabel); return (0); } static int mac_test_check_cred_visible(struct ucred *u1, struct ucred *u2) { ASSERT_CRED_LABEL(u1->cr_label); ASSERT_CRED_LABEL(u2->cr_label); return (0); } static int mac_test_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet, struct label *ifnetlabel, struct label *newlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_IFNET_LABEL(ifnetlabel); ASSERT_IFNET_LABEL(newlabel); return (0); } static int mac_test_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *m, struct label *mbuflabel) { ASSERT_IFNET_LABEL(ifnetlabel); ASSERT_MBUF_LABEL(mbuflabel); return (0); } static int mac_test_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel, struct mbuf *m, struct label *mlabel) { ASSERT_INPCB_LABEL(inplabel); ASSERT_MBUF_LABEL(mlabel); return (0); } static int mac_test_check_sysv_msgmsq(struct ucred *cred, struct msg *msgptr, struct label *msglabel, struct msqid_kernel *msqkptr, struct label *msqklabel) { ASSERT_SYSVIPCMSQ_LABEL(msqklabel); ASSERT_SYSVIPCMSG_LABEL(msglabel); ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_sysv_msgrcv(struct ucred *cred, struct msg *msgptr, struct label *msglabel) { ASSERT_SYSVIPCMSG_LABEL(msglabel); ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_sysv_msgrmid(struct ucred *cred, struct msg *msgptr, struct label *msglabel) { ASSERT_SYSVIPCMSG_LABEL(msglabel); ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_sysv_msqget(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel) { ASSERT_SYSVIPCMSQ_LABEL(msqklabel); ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_sysv_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel) { ASSERT_SYSVIPCMSQ_LABEL(msqklabel); ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_sysv_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel) { ASSERT_SYSVIPCMSQ_LABEL(msqklabel); ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_sysv_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr, struct label *msqklabel, int cmd) { ASSERT_SYSVIPCMSQ_LABEL(msqklabel); ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_sysv_semctl(struct ucred *cred, struct semid_kernel *semakptr, struct label *semaklabel, int cmd) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SYSVIPCSEM_LABEL(semaklabel); return (0); } static int mac_test_check_sysv_semget(struct ucred *cred, struct semid_kernel *semakptr, struct label *semaklabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SYSVIPCSEM_LABEL(semaklabel); return (0); } static int mac_test_check_sysv_semop(struct ucred *cred, struct semid_kernel *semakptr, struct label *semaklabel, size_t accesstype) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SYSVIPCSEM_LABEL(semaklabel); return (0); } static int mac_test_check_sysv_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmseglabel, int shmflg) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SYSVIPCSHM_LABEL(shmseglabel); return (0); } static int mac_test_check_sysv_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmseglabel, int cmd) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SYSVIPCSHM_LABEL(shmseglabel); return (0); } static int mac_test_check_sysv_shmdt(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmseglabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SYSVIPCSHM_LABEL(shmseglabel); return (0); } static int mac_test_check_sysv_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr, struct label *shmseglabel, int shmflg) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SYSVIPCSHM_LABEL(shmseglabel); return (0); } static int mac_test_check_kenv_dump(struct ucred *cred) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_kenv_get(struct ucred *cred, char *name) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_kenv_set(struct ucred *cred, char *name, char *value) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_kenv_unset(struct ucred *cred, char *name) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_kld_load(struct ucred *cred, struct vnode *vp, struct label *label) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_kld_stat(struct ucred *cred) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_kld_unload(struct ucred *cred) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_mount_stat(struct ucred *cred, struct mount *mp, struct label *mntlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_MOUNT_LABEL(mntlabel); return (0); } static int mac_test_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp, struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_PIPE_LABEL(pipelabel); return (0); } static int mac_test_check_pipe_poll(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_PIPE_LABEL(pipelabel); return (0); } static int mac_test_check_pipe_read(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_PIPE_LABEL(pipelabel); return (0); } static int mac_test_check_pipe_relabel(struct ucred *cred, struct pipepair *pp, struct label *pipelabel, struct label *newlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_PIPE_LABEL(pipelabel); ASSERT_PIPE_LABEL(newlabel); return (0); } static int mac_test_check_pipe_stat(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_PIPE_LABEL(pipelabel); return (0); } static int mac_test_check_pipe_write(struct ucred *cred, struct pipepair *pp, struct label *pipelabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_PIPE_LABEL(pipelabel); return (0); } static int mac_test_check_posix_sem(struct ucred *cred, struct ksem *ksemptr, struct label *ks_label) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_POSIX_LABEL(ks_label); return (0); } static int mac_test_check_proc_debug(struct ucred *cred, struct proc *proc) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_CRED_LABEL(proc->p_ucred->cr_label); return (0); } static int mac_test_check_proc_sched(struct ucred *cred, struct proc *proc) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_CRED_LABEL(proc->p_ucred->cr_label); return (0); } static int mac_test_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_CRED_LABEL(proc->p_ucred->cr_label); return (0); } static int mac_test_check_proc_setuid(struct ucred *cred, uid_t uid) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_proc_seteuid(struct ucred *cred, uid_t euid) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_proc_setgid(struct ucred *cred, gid_t gid) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_proc_setegid(struct ucred *cred, gid_t egid) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_proc_setgroups(struct ucred *cred, int ngroups, gid_t *gidset) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_proc_setreuid(struct ucred *cred, uid_t ruid, uid_t euid) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_proc_setregid(struct ucred *cred, gid_t rgid, gid_t egid) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_proc_setresuid(struct ucred *cred, uid_t ruid, uid_t euid, uid_t suid) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_proc_setresgid(struct ucred *cred, gid_t rgid, gid_t egid, gid_t sgid) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_proc_wait(struct ucred *cred, struct proc *proc) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_CRED_LABEL(proc->p_ucred->cr_label); return (0); } static int mac_test_check_socket_accept(struct ucred *cred, struct socket *socket, struct label *socketlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SOCKET_LABEL(socketlabel); return (0); } static int mac_test_check_socket_bind(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct sockaddr *sockaddr) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SOCKET_LABEL(socketlabel); return (0); } static int mac_test_check_socket_connect(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct sockaddr *sockaddr) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SOCKET_LABEL(socketlabel); return (0); } static int mac_test_check_socket_deliver(struct socket *socket, struct label *socketlabel, struct mbuf *m, struct label *mbuflabel) { ASSERT_SOCKET_LABEL(socketlabel); ASSERT_MBUF_LABEL(mbuflabel); return (0); } static int mac_test_check_socket_listen(struct ucred *cred, struct socket *socket, struct label *socketlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SOCKET_LABEL(socketlabel); return (0); } static int mac_test_check_socket_poll(struct ucred *cred, struct socket *socket, struct label *socketlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SOCKET_LABEL(socketlabel); return (0); } static int mac_test_check_socket_receive(struct ucred *cred, struct socket *socket, struct label *socketlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SOCKET_LABEL(socketlabel); return (0); } static int mac_test_check_socket_relabel(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct label *newlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SOCKET_LABEL(socketlabel); ASSERT_SOCKET_LABEL(newlabel); return (0); } static int mac_test_check_socket_send(struct ucred *cred, struct socket *socket, struct label *socketlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SOCKET_LABEL(socketlabel); return (0); } static int mac_test_check_socket_stat(struct ucred *cred, struct socket *socket, struct label *socketlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SOCKET_LABEL(socketlabel); return (0); } static int mac_test_check_socket_visible(struct ucred *cred, struct socket *socket, struct label *socketlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_SOCKET_LABEL(socketlabel); return (0); } static int mac_test_check_sysarch_ioperm(struct ucred *cred) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_system_acct(struct ucred *cred, struct vnode *vp, struct label *label) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_system_reboot(struct ucred *cred, int how) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_system_settime(struct ucred *cred) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_system_swapon(struct ucred *cred, struct vnode *vp, struct label *label) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_system_swapoff(struct ucred *cred, struct vnode *vp, struct label *label) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_system_sysctl(struct ucred *cred, struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req) { ASSERT_CRED_LABEL(cred->cr_label); return (0); } static int mac_test_check_vnode_access(struct ucred *cred, struct vnode *vp, struct label *label, int acc_mode) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_chdir(struct ucred *cred, struct vnode *dvp, struct label *dlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(dlabel); return (0); } static int mac_test_check_vnode_chroot(struct ucred *cred, struct vnode *dvp, struct label *dlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(dlabel); return (0); } static int mac_test_check_vnode_create(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct componentname *cnp, struct vattr *vap) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(dlabel); return (0); } static int mac_test_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(dlabel); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace, const char *name) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_exec(struct ucred *cred, struct vnode *vp, struct label *label, struct image_params *imgp, struct label *execlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); if (execlabel != NULL) { ASSERT_CRED_LABEL(execlabel); } return (0); } static int mac_test_check_vnode_getacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace, const char *name, struct uio *uio) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_link(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(dlabel); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_listextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct componentname *cnp) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(dlabel); return (0); } static int mac_test_check_vnode_mmap(struct ucred *cred, struct vnode *vp, struct label *label, int prot, int flags) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_open(struct ucred *cred, struct vnode *vp, struct label *filelabel, int acc_mode) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(filelabel); return (0); } static int mac_test_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label) { ASSERT_CRED_LABEL(active_cred->cr_label); ASSERT_CRED_LABEL(file_cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label) { ASSERT_CRED_LABEL(active_cred->cr_label); if (file_cred != NULL) { ASSERT_CRED_LABEL(file_cred->cr_label); } ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_readdir(struct ucred *cred, struct vnode *dvp, struct label *dlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(dlabel); return (0); } static int mac_test_check_vnode_readlink(struct ucred *cred, struct vnode *vp, struct label *vnodelabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(vnodelabel); return (0); } static int mac_test_check_vnode_relabel(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct label *newlabel) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(vnodelabel); ASSERT_VNODE_LABEL(newlabel); return (0); } static int mac_test_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(dlabel); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, int samedir, struct componentname *cnp) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(dlabel); if (vp != NULL) { ASSERT_VNODE_LABEL(label); } return (0); } static int mac_test_check_vnode_revoke(struct ucred *cred, struct vnode *vp, struct label *label) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_setacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type, struct acl *acl) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace, const char *name, struct uio *uio) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_setflags(struct ucred *cred, struct vnode *vp, struct label *label, u_long flags) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_setmode(struct ucred *cred, struct vnode *vp, struct label *label, mode_t mode) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_setowner(struct ucred *cred, struct vnode *vp, struct label *label, uid_t uid, gid_t gid) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, struct label *label, struct timespec atime, struct timespec mtime) { ASSERT_CRED_LABEL(cred->cr_label); ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label) { ASSERT_CRED_LABEL(active_cred->cr_label); if (file_cred != NULL) { ASSERT_CRED_LABEL(file_cred->cr_label); } ASSERT_VNODE_LABEL(label); return (0); } static int mac_test_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label) { ASSERT_CRED_LABEL(active_cred->cr_label); if (file_cred != NULL) { ASSERT_CRED_LABEL(file_cred->cr_label); } ASSERT_VNODE_LABEL(label); return (0); } static struct mac_policy_ops mac_test_ops = { .mpo_destroy = mac_test_destroy, .mpo_init = mac_test_init, .mpo_syscall = mac_test_syscall, .mpo_init_bpfdesc_label = mac_test_init_bpfdesc_label, .mpo_init_cred_label = mac_test_init_cred_label, .mpo_init_devfsdirent_label = mac_test_init_devfsdirent_label, .mpo_init_ifnet_label = mac_test_init_ifnet_label, .mpo_init_sysv_msgmsg_label = mac_test_init_sysv_msgmsg_label, .mpo_init_sysv_msgqueue_label = mac_test_init_sysv_msgqueue_label, .mpo_init_sysv_sem_label = mac_test_init_sysv_sem_label, .mpo_init_sysv_shm_label = mac_test_init_sysv_shm_label, .mpo_init_inpcb_label = mac_test_init_inpcb_label, .mpo_init_ipq_label = mac_test_init_ipq_label, .mpo_init_mbuf_label = mac_test_init_mbuf_label, .mpo_init_mount_label = mac_test_init_mount_label, .mpo_init_mount_fs_label = mac_test_init_mount_fs_label, .mpo_init_pipe_label = mac_test_init_pipe_label, .mpo_init_posix_sem_label = mac_test_init_posix_sem_label, .mpo_init_proc_label = mac_test_init_proc_label, .mpo_init_socket_label = mac_test_init_socket_label, .mpo_init_socket_peer_label = mac_test_init_socket_peer_label, .mpo_init_vnode_label = mac_test_init_vnode_label, .mpo_destroy_bpfdesc_label = mac_test_destroy_bpfdesc_label, .mpo_destroy_cred_label = mac_test_destroy_cred_label, .mpo_destroy_devfsdirent_label = mac_test_destroy_devfsdirent_label, .mpo_destroy_ifnet_label = mac_test_destroy_ifnet_label, .mpo_destroy_sysv_msgmsg_label = mac_test_destroy_sysv_msgmsg_label, .mpo_destroy_sysv_msgqueue_label = mac_test_destroy_sysv_msgqueue_label, .mpo_destroy_sysv_sem_label = mac_test_destroy_sysv_sem_label, .mpo_destroy_sysv_shm_label = mac_test_destroy_sysv_shm_label, .mpo_destroy_inpcb_label = mac_test_destroy_inpcb_label, .mpo_destroy_ipq_label = mac_test_destroy_ipq_label, .mpo_destroy_mbuf_label = mac_test_destroy_mbuf_label, .mpo_destroy_mount_label = mac_test_destroy_mount_label, .mpo_destroy_mount_fs_label = mac_test_destroy_mount_fs_label, .mpo_destroy_pipe_label = mac_test_destroy_pipe_label, .mpo_destroy_posix_sem_label = mac_test_destroy_posix_sem_label, .mpo_destroy_proc_label = mac_test_destroy_proc_label, .mpo_destroy_socket_label = mac_test_destroy_socket_label, .mpo_destroy_socket_peer_label = mac_test_destroy_socket_peer_label, .mpo_destroy_vnode_label = mac_test_destroy_vnode_label, .mpo_copy_cred_label = mac_test_copy_cred_label, .mpo_copy_ifnet_label = mac_test_copy_ifnet_label, .mpo_copy_mbuf_label = mac_test_copy_mbuf_label, .mpo_copy_pipe_label = mac_test_copy_pipe_label, .mpo_copy_socket_label = mac_test_copy_socket_label, .mpo_copy_vnode_label = mac_test_copy_vnode_label, .mpo_externalize_cred_label = mac_test_externalize_label, .mpo_externalize_ifnet_label = mac_test_externalize_label, .mpo_externalize_pipe_label = mac_test_externalize_label, .mpo_externalize_socket_label = mac_test_externalize_label, .mpo_externalize_socket_peer_label = mac_test_externalize_label, .mpo_externalize_vnode_label = mac_test_externalize_label, .mpo_internalize_cred_label = mac_test_internalize_label, .mpo_internalize_ifnet_label = mac_test_internalize_label, .mpo_internalize_pipe_label = mac_test_internalize_label, .mpo_internalize_socket_label = mac_test_internalize_label, .mpo_internalize_vnode_label = mac_test_internalize_label, .mpo_associate_vnode_devfs = mac_test_associate_vnode_devfs, .mpo_associate_vnode_extattr = mac_test_associate_vnode_extattr, .mpo_associate_vnode_singlelabel = mac_test_associate_vnode_singlelabel, .mpo_create_devfs_device = mac_test_create_devfs_device, .mpo_create_devfs_directory = mac_test_create_devfs_directory, .mpo_create_devfs_symlink = mac_test_create_devfs_symlink, .mpo_create_vnode_extattr = mac_test_create_vnode_extattr, .mpo_create_mount = mac_test_create_mount, .mpo_relabel_vnode = mac_test_relabel_vnode, .mpo_setlabel_vnode_extattr = mac_test_setlabel_vnode_extattr, .mpo_update_devfsdirent = mac_test_update_devfsdirent, .mpo_create_mbuf_from_socket = mac_test_create_mbuf_from_socket, .mpo_create_pipe = mac_test_create_pipe, .mpo_create_posix_sem = mac_test_create_posix_sem, .mpo_create_socket = mac_test_create_socket, .mpo_create_socket_from_socket = mac_test_create_socket_from_socket, .mpo_relabel_pipe = mac_test_relabel_pipe, .mpo_relabel_socket = mac_test_relabel_socket, .mpo_set_socket_peer_from_mbuf = mac_test_set_socket_peer_from_mbuf, .mpo_set_socket_peer_from_socket = mac_test_set_socket_peer_from_socket, .mpo_create_bpfdesc = mac_test_create_bpfdesc, .mpo_create_ifnet = mac_test_create_ifnet, .mpo_create_inpcb_from_socket = mac_test_create_inpcb_from_socket, .mpo_create_sysv_msgmsg = mac_test_create_sysv_msgmsg, .mpo_create_sysv_msgqueue = mac_test_create_sysv_msgqueue, .mpo_create_sysv_sem = mac_test_create_sysv_sem, .mpo_create_sysv_shm = mac_test_create_sysv_shm, .mpo_create_datagram_from_ipq = mac_test_create_datagram_from_ipq, .mpo_create_fragment = mac_test_create_fragment, .mpo_create_ipq = mac_test_create_ipq, .mpo_create_mbuf_from_inpcb = mac_test_create_mbuf_from_inpcb, .mpo_create_mbuf_linklayer = mac_test_create_mbuf_linklayer, .mpo_create_mbuf_from_bpfdesc = mac_test_create_mbuf_from_bpfdesc, .mpo_create_mbuf_from_ifnet = mac_test_create_mbuf_from_ifnet, .mpo_create_mbuf_multicast_encap = mac_test_create_mbuf_multicast_encap, .mpo_create_mbuf_netlayer = mac_test_create_mbuf_netlayer, .mpo_fragment_match = mac_test_fragment_match, .mpo_reflect_mbuf_icmp = mac_test_reflect_mbuf_icmp, .mpo_reflect_mbuf_tcp = mac_test_reflect_mbuf_tcp, .mpo_relabel_ifnet = mac_test_relabel_ifnet, .mpo_update_ipq = mac_test_update_ipq, .mpo_inpcb_sosetlabel = mac_test_inpcb_sosetlabel, .mpo_execve_transition = mac_test_execve_transition, .mpo_execve_will_transition = mac_test_execve_will_transition, .mpo_create_proc0 = mac_test_create_proc0, .mpo_create_proc1 = mac_test_create_proc1, .mpo_relabel_cred = mac_test_relabel_cred, .mpo_thread_userret = mac_test_thread_userret, .mpo_cleanup_sysv_msgmsg = mac_test_cleanup_sysv_msgmsg, .mpo_cleanup_sysv_msgqueue = mac_test_cleanup_sysv_msgqueue, .mpo_cleanup_sysv_sem = mac_test_cleanup_sysv_sem, .mpo_cleanup_sysv_shm = mac_test_cleanup_sysv_shm, .mpo_check_bpfdesc_receive = mac_test_check_bpfdesc_receive, .mpo_check_cred_relabel = mac_test_check_cred_relabel, .mpo_check_cred_visible = mac_test_check_cred_visible, .mpo_check_ifnet_relabel = mac_test_check_ifnet_relabel, .mpo_check_ifnet_transmit = mac_test_check_ifnet_transmit, .mpo_check_inpcb_deliver = mac_test_check_inpcb_deliver, .mpo_check_sysv_msgmsq = mac_test_check_sysv_msgmsq, .mpo_check_sysv_msgrcv = mac_test_check_sysv_msgrcv, .mpo_check_sysv_msgrmid = mac_test_check_sysv_msgrmid, .mpo_check_sysv_msqget = mac_test_check_sysv_msqget, .mpo_check_sysv_msqsnd = mac_test_check_sysv_msqsnd, .mpo_check_sysv_msqrcv = mac_test_check_sysv_msqrcv, .mpo_check_sysv_msqctl = mac_test_check_sysv_msqctl, .mpo_check_sysv_semctl = mac_test_check_sysv_semctl, .mpo_check_sysv_semget = mac_test_check_sysv_semget, .mpo_check_sysv_semop = mac_test_check_sysv_semop, .mpo_check_sysv_shmat = mac_test_check_sysv_shmat, .mpo_check_sysv_shmctl = mac_test_check_sysv_shmctl, .mpo_check_sysv_shmdt = mac_test_check_sysv_shmdt, .mpo_check_sysv_shmget = mac_test_check_sysv_shmget, .mpo_check_kenv_dump = mac_test_check_kenv_dump, .mpo_check_kenv_get = mac_test_check_kenv_get, .mpo_check_kenv_set = mac_test_check_kenv_set, .mpo_check_kenv_unset = mac_test_check_kenv_unset, .mpo_check_kld_load = mac_test_check_kld_load, .mpo_check_kld_stat = mac_test_check_kld_stat, .mpo_check_kld_unload = mac_test_check_kld_unload, .mpo_check_mount_stat = mac_test_check_mount_stat, .mpo_check_pipe_ioctl = mac_test_check_pipe_ioctl, .mpo_check_pipe_poll = mac_test_check_pipe_poll, .mpo_check_pipe_read = mac_test_check_pipe_read, .mpo_check_pipe_relabel = mac_test_check_pipe_relabel, .mpo_check_pipe_stat = mac_test_check_pipe_stat, .mpo_check_pipe_write = mac_test_check_pipe_write, .mpo_check_posix_sem_destroy = mac_test_check_posix_sem, .mpo_check_posix_sem_getvalue = mac_test_check_posix_sem, .mpo_check_posix_sem_open = mac_test_check_posix_sem, .mpo_check_posix_sem_post = mac_test_check_posix_sem, .mpo_check_posix_sem_unlink = mac_test_check_posix_sem, .mpo_check_posix_sem_wait = mac_test_check_posix_sem, .mpo_check_proc_debug = mac_test_check_proc_debug, .mpo_check_proc_sched = mac_test_check_proc_sched, .mpo_check_proc_setuid = mac_test_check_proc_setuid, .mpo_check_proc_seteuid = mac_test_check_proc_seteuid, .mpo_check_proc_setgid = mac_test_check_proc_setgid, .mpo_check_proc_setegid = mac_test_check_proc_setegid, .mpo_check_proc_setgroups = mac_test_check_proc_setgroups, .mpo_check_proc_setreuid = mac_test_check_proc_setreuid, .mpo_check_proc_setregid = mac_test_check_proc_setregid, .mpo_check_proc_setresuid = mac_test_check_proc_setresuid, .mpo_check_proc_setresgid = mac_test_check_proc_setresgid, .mpo_check_proc_signal = mac_test_check_proc_signal, .mpo_check_proc_wait = mac_test_check_proc_wait, .mpo_check_socket_accept = mac_test_check_socket_accept, .mpo_check_socket_bind = mac_test_check_socket_bind, .mpo_check_socket_connect = mac_test_check_socket_connect, .mpo_check_socket_deliver = mac_test_check_socket_deliver, .mpo_check_socket_listen = mac_test_check_socket_listen, .mpo_check_socket_poll = mac_test_check_socket_poll, .mpo_check_socket_receive = mac_test_check_socket_receive, .mpo_check_socket_relabel = mac_test_check_socket_relabel, .mpo_check_socket_send = mac_test_check_socket_send, .mpo_check_socket_stat = mac_test_check_socket_stat, .mpo_check_socket_visible = mac_test_check_socket_visible, .mpo_check_sysarch_ioperm = mac_test_check_sysarch_ioperm, .mpo_check_system_acct = mac_test_check_system_acct, .mpo_check_system_reboot = mac_test_check_system_reboot, .mpo_check_system_settime = mac_test_check_system_settime, .mpo_check_system_swapon = mac_test_check_system_swapon, .mpo_check_system_swapoff = mac_test_check_system_swapoff, .mpo_check_system_sysctl = mac_test_check_system_sysctl, .mpo_check_vnode_access = mac_test_check_vnode_access, .mpo_check_vnode_chdir = mac_test_check_vnode_chdir, .mpo_check_vnode_chroot = mac_test_check_vnode_chroot, .mpo_check_vnode_create = mac_test_check_vnode_create, .mpo_check_vnode_delete = mac_test_check_vnode_delete, .mpo_check_vnode_deleteacl = mac_test_check_vnode_deleteacl, .mpo_check_vnode_deleteextattr = mac_test_check_vnode_deleteextattr, .mpo_check_vnode_exec = mac_test_check_vnode_exec, .mpo_check_vnode_getacl = mac_test_check_vnode_getacl, .mpo_check_vnode_getextattr = mac_test_check_vnode_getextattr, .mpo_check_vnode_link = mac_test_check_vnode_link, .mpo_check_vnode_listextattr = mac_test_check_vnode_listextattr, .mpo_check_vnode_lookup = mac_test_check_vnode_lookup, .mpo_check_vnode_mmap = mac_test_check_vnode_mmap, .mpo_check_vnode_open = mac_test_check_vnode_open, .mpo_check_vnode_poll = mac_test_check_vnode_poll, .mpo_check_vnode_read = mac_test_check_vnode_read, .mpo_check_vnode_readdir = mac_test_check_vnode_readdir, .mpo_check_vnode_readlink = mac_test_check_vnode_readlink, .mpo_check_vnode_relabel = mac_test_check_vnode_relabel, .mpo_check_vnode_rename_from = mac_test_check_vnode_rename_from, .mpo_check_vnode_rename_to = mac_test_check_vnode_rename_to, .mpo_check_vnode_revoke = mac_test_check_vnode_revoke, .mpo_check_vnode_setacl = mac_test_check_vnode_setacl, .mpo_check_vnode_setextattr = mac_test_check_vnode_setextattr, .mpo_check_vnode_setflags = mac_test_check_vnode_setflags, .mpo_check_vnode_setmode = mac_test_check_vnode_setmode, .mpo_check_vnode_setowner = mac_test_check_vnode_setowner, .mpo_check_vnode_setutimes = mac_test_check_vnode_setutimes, .mpo_check_vnode_stat = mac_test_check_vnode_stat, .mpo_check_vnode_write = mac_test_check_vnode_write, }; MAC_POLICY_SET(&mac_test_ops, mac_test, "TrustedBSD MAC/Test", MPC_LOADTIME_FLAG_UNLOADOK | MPC_LOADTIME_FLAG_LABELMBUFS, &test_slot); Index: head/sys/sys/sysproto.h =================================================================== --- head/sys/sys/sysproto.h (revision 164183) +++ head/sys/sys/sysproto.h (revision 164184) @@ -1,2373 +1,2373 @@ /* * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.231 2006/11/03 15:23:14 rrs Exp */ #ifndef _SYS_SYSPROTO_H_ #define _SYS_SYSPROTO_H_ #include #include -#include #include +#include #include struct proc; struct thread; #define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \ 0 : sizeof(register_t) - sizeof(t)) #if BYTE_ORDER == LITTLE_ENDIAN #define PADL_(t) 0 #define PADR_(t) PAD_(t) #else #define PADL_(t) PAD_(t) #define PADR_(t) 0 #endif struct nosys_args { register_t dummy; }; struct sys_exit_args { char rval_l_[PADL_(int)]; int rval; char rval_r_[PADR_(int)]; }; struct fork_args { register_t dummy; }; struct read_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char buf_l_[PADL_(void *)]; void * buf; char buf_r_[PADR_(void *)]; char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)]; }; struct write_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char buf_l_[PADL_(const void *)]; const void * buf; char buf_r_[PADR_(const void *)]; char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)]; }; struct open_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; }; struct close_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; }; struct wait_args { char pid_l_[PADL_(int)]; int pid; char pid_r_[PADR_(int)]; char status_l_[PADL_(int *)]; int * status; char status_r_[PADR_(int *)]; char options_l_[PADL_(int)]; int options; char options_r_[PADR_(int)]; char rusage_l_[PADL_(struct rusage *)]; struct rusage * rusage; char rusage_r_[PADR_(struct rusage *)]; }; struct link_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char link_l_[PADL_(char *)]; char * link; char link_r_[PADR_(char *)]; }; struct unlink_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct chdir_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct fchdir_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; }; struct mknod_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; char dev_l_[PADL_(int)]; int dev; char dev_r_[PADR_(int)]; }; struct chmod_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; }; struct chown_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char uid_l_[PADL_(int)]; int uid; char uid_r_[PADR_(int)]; char gid_l_[PADL_(int)]; int gid; char gid_r_[PADR_(int)]; }; struct obreak_args { char nsize_l_[PADL_(char *)]; char * nsize; char nsize_r_[PADR_(char *)]; }; struct getpid_args { register_t dummy; }; struct mount_args { char type_l_[PADL_(char *)]; char * type; char type_r_[PADR_(char *)]; char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; char data_l_[PADL_(caddr_t)]; caddr_t data; char data_r_[PADR_(caddr_t)]; }; struct unmount_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct setuid_args { char uid_l_[PADL_(uid_t)]; uid_t uid; char uid_r_[PADR_(uid_t)]; }; struct getuid_args { register_t dummy; }; struct geteuid_args { register_t dummy; }; struct ptrace_args { char req_l_[PADL_(int)]; int req; char req_r_[PADR_(int)]; char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)]; char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)]; char data_l_[PADL_(int)]; int data; char data_r_[PADR_(int)]; }; struct recvmsg_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char msg_l_[PADL_(struct msghdr *)]; struct msghdr * msg; char msg_r_[PADR_(struct msghdr *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct sendmsg_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char msg_l_[PADL_(struct msghdr *)]; struct msghdr * msg; char msg_r_[PADR_(struct msghdr *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct recvfrom_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char buf_l_[PADL_(caddr_t)]; caddr_t buf; char buf_r_[PADR_(caddr_t)]; char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; char from_l_[PADL_(struct sockaddr *__restrict)]; struct sockaddr *__restrict from; char from_r_[PADR_(struct sockaddr *__restrict)]; char fromlenaddr_l_[PADL_(__socklen_t *__restrict)]; __socklen_t *__restrict fromlenaddr; char fromlenaddr_r_[PADR_(__socklen_t *__restrict)]; }; struct accept_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char name_l_[PADL_(struct sockaddr *__restrict)]; struct sockaddr *__restrict name; char name_r_[PADR_(struct sockaddr *__restrict)]; char anamelen_l_[PADL_(__socklen_t *__restrict)]; __socklen_t *__restrict anamelen; char anamelen_r_[PADR_(__socklen_t *__restrict)]; }; struct getpeername_args { char fdes_l_[PADL_(int)]; int fdes; char fdes_r_[PADR_(int)]; char asa_l_[PADL_(struct sockaddr *__restrict)]; struct sockaddr *__restrict asa; char asa_r_[PADR_(struct sockaddr *__restrict)]; char alen_l_[PADL_(__socklen_t *__restrict)]; __socklen_t *__restrict alen; char alen_r_[PADR_(__socklen_t *__restrict)]; }; struct getsockname_args { char fdes_l_[PADL_(int)]; int fdes; char fdes_r_[PADR_(int)]; char asa_l_[PADL_(struct sockaddr *__restrict)]; struct sockaddr *__restrict asa; char asa_r_[PADR_(struct sockaddr *__restrict)]; char alen_l_[PADL_(__socklen_t *__restrict)]; __socklen_t *__restrict alen; char alen_r_[PADR_(__socklen_t *__restrict)]; }; struct access_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct chflags_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct fchflags_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct sync_args { register_t dummy; }; struct kill_args { char pid_l_[PADL_(int)]; int pid; char pid_r_[PADR_(int)]; char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)]; }; struct getppid_args { register_t dummy; }; struct dup_args { char fd_l_[PADL_(u_int)]; u_int fd; char fd_r_[PADR_(u_int)]; }; struct pipe_args { register_t dummy; }; struct getegid_args { register_t dummy; }; struct profil_args { char samples_l_[PADL_(caddr_t)]; caddr_t samples; char samples_r_[PADR_(caddr_t)]; char size_l_[PADL_(size_t)]; size_t size; char size_r_[PADR_(size_t)]; char offset_l_[PADL_(size_t)]; size_t offset; char offset_r_[PADR_(size_t)]; char scale_l_[PADL_(u_int)]; u_int scale; char scale_r_[PADR_(u_int)]; }; struct ktrace_args { char fname_l_[PADL_(const char *)]; const char * fname; char fname_r_[PADR_(const char *)]; char ops_l_[PADL_(int)]; int ops; char ops_r_[PADR_(int)]; char facs_l_[PADL_(int)]; int facs; char facs_r_[PADR_(int)]; char pid_l_[PADL_(int)]; int pid; char pid_r_[PADR_(int)]; }; struct getgid_args { register_t dummy; }; struct getlogin_args { char namebuf_l_[PADL_(char *)]; char * namebuf; char namebuf_r_[PADR_(char *)]; char namelen_l_[PADL_(u_int)]; u_int namelen; char namelen_r_[PADR_(u_int)]; }; struct setlogin_args { char namebuf_l_[PADL_(char *)]; char * namebuf; char namebuf_r_[PADR_(char *)]; }; struct acct_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct osigpending_args { register_t dummy; }; struct sigaltstack_args { char ss_l_[PADL_(stack_t *)]; stack_t * ss; char ss_r_[PADR_(stack_t *)]; char oss_l_[PADL_(stack_t *)]; stack_t * oss; char oss_r_[PADR_(stack_t *)]; }; struct ioctl_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char com_l_[PADL_(u_long)]; u_long com; char com_r_[PADR_(u_long)]; char data_l_[PADL_(caddr_t)]; caddr_t data; char data_r_[PADR_(caddr_t)]; }; struct reboot_args { char opt_l_[PADL_(int)]; int opt; char opt_r_[PADR_(int)]; }; struct revoke_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct symlink_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char link_l_[PADL_(char *)]; char * link; char link_r_[PADR_(char *)]; }; struct readlink_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; char count_l_[PADL_(int)]; int count; char count_r_[PADR_(int)]; }; struct execve_args { char fname_l_[PADL_(char *)]; char * fname; char fname_r_[PADR_(char *)]; char argv_l_[PADL_(char **)]; char ** argv; char argv_r_[PADR_(char **)]; char envv_l_[PADL_(char **)]; char ** envv; char envv_r_[PADR_(char **)]; }; struct umask_args { char newmask_l_[PADL_(int)]; int newmask; char newmask_r_[PADR_(int)]; }; struct chroot_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct getpagesize_args { register_t dummy; }; struct msync_args { char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)]; char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct vfork_args { register_t dummy; }; struct sbrk_args { char incr_l_[PADL_(int)]; int incr; char incr_r_[PADR_(int)]; }; struct sstk_args { char incr_l_[PADL_(int)]; int incr; char incr_r_[PADR_(int)]; }; struct ovadvise_args { char anom_l_[PADL_(int)]; int anom; char anom_r_[PADR_(int)]; }; struct munmap_args { char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)]; char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; }; struct mprotect_args { char addr_l_[PADL_(const void *)]; const void * addr; char addr_r_[PADR_(const void *)]; char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)]; }; struct madvise_args { char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)]; char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; char behav_l_[PADL_(int)]; int behav; char behav_r_[PADR_(int)]; }; struct mincore_args { char addr_l_[PADL_(const void *)]; const void * addr; char addr_r_[PADR_(const void *)]; char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; char vec_l_[PADL_(char *)]; char * vec; char vec_r_[PADR_(char *)]; }; struct getgroups_args { char gidsetsize_l_[PADL_(u_int)]; u_int gidsetsize; char gidsetsize_r_[PADR_(u_int)]; char gidset_l_[PADL_(gid_t *)]; gid_t * gidset; char gidset_r_[PADR_(gid_t *)]; }; struct setgroups_args { char gidsetsize_l_[PADL_(u_int)]; u_int gidsetsize; char gidsetsize_r_[PADR_(u_int)]; char gidset_l_[PADL_(gid_t *)]; gid_t * gidset; char gidset_r_[PADR_(gid_t *)]; }; struct getpgrp_args { register_t dummy; }; struct setpgid_args { char pid_l_[PADL_(int)]; int pid; char pid_r_[PADR_(int)]; char pgid_l_[PADL_(int)]; int pgid; char pgid_r_[PADR_(int)]; }; struct setitimer_args { char which_l_[PADL_(u_int)]; u_int which; char which_r_[PADR_(u_int)]; char itv_l_[PADL_(struct itimerval *)]; struct itimerval * itv; char itv_r_[PADR_(struct itimerval *)]; char oitv_l_[PADL_(struct itimerval *)]; struct itimerval * oitv; char oitv_r_[PADR_(struct itimerval *)]; }; struct owait_args { register_t dummy; }; struct swapon_args { char name_l_[PADL_(char *)]; char * name; char name_r_[PADR_(char *)]; }; struct getitimer_args { char which_l_[PADL_(u_int)]; u_int which; char which_r_[PADR_(u_int)]; char itv_l_[PADL_(struct itimerval *)]; struct itimerval * itv; char itv_r_[PADR_(struct itimerval *)]; }; struct getdtablesize_args { register_t dummy; }; struct dup2_args { char from_l_[PADL_(u_int)]; u_int from; char from_r_[PADR_(u_int)]; char to_l_[PADL_(u_int)]; u_int to; char to_r_[PADR_(u_int)]; }; struct fcntl_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char arg_l_[PADL_(long)]; long arg; char arg_r_[PADR_(long)]; }; struct select_args { char nd_l_[PADL_(int)]; int nd; char nd_r_[PADR_(int)]; char in_l_[PADL_(fd_set *)]; fd_set * in; char in_r_[PADR_(fd_set *)]; char ou_l_[PADL_(fd_set *)]; fd_set * ou; char ou_r_[PADR_(fd_set *)]; char ex_l_[PADL_(fd_set *)]; fd_set * ex; char ex_r_[PADR_(fd_set *)]; char tv_l_[PADL_(struct timeval *)]; struct timeval * tv; char tv_r_[PADR_(struct timeval *)]; }; struct fsync_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; }; struct setpriority_args { char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)]; char who_l_[PADL_(int)]; int who; char who_r_[PADR_(int)]; char prio_l_[PADL_(int)]; int prio; char prio_r_[PADR_(int)]; }; struct socket_args { char domain_l_[PADL_(int)]; int domain; char domain_r_[PADR_(int)]; char type_l_[PADL_(int)]; int type; char type_r_[PADR_(int)]; char protocol_l_[PADL_(int)]; int protocol; char protocol_r_[PADR_(int)]; }; struct connect_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char name_l_[PADL_(caddr_t)]; caddr_t name; char name_r_[PADR_(caddr_t)]; char namelen_l_[PADL_(int)]; int namelen; char namelen_r_[PADR_(int)]; }; struct getpriority_args { char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)]; char who_l_[PADL_(int)]; int who; char who_r_[PADR_(int)]; }; struct bind_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char name_l_[PADL_(caddr_t)]; caddr_t name; char name_r_[PADR_(caddr_t)]; char namelen_l_[PADL_(int)]; int namelen; char namelen_r_[PADR_(int)]; }; struct setsockopt_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char level_l_[PADL_(int)]; int level; char level_r_[PADR_(int)]; char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)]; char val_l_[PADL_(caddr_t)]; caddr_t val; char val_r_[PADR_(caddr_t)]; char valsize_l_[PADL_(int)]; int valsize; char valsize_r_[PADR_(int)]; }; struct listen_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char backlog_l_[PADL_(int)]; int backlog; char backlog_r_[PADR_(int)]; }; struct gettimeofday_args { char tp_l_[PADL_(struct timeval *)]; struct timeval * tp; char tp_r_[PADR_(struct timeval *)]; char tzp_l_[PADL_(struct timezone *)]; struct timezone * tzp; char tzp_r_[PADR_(struct timezone *)]; }; struct getrusage_args { char who_l_[PADL_(int)]; int who; char who_r_[PADR_(int)]; char rusage_l_[PADL_(struct rusage *)]; struct rusage * rusage; char rusage_r_[PADR_(struct rusage *)]; }; struct getsockopt_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char level_l_[PADL_(int)]; int level; char level_r_[PADR_(int)]; char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)]; char val_l_[PADL_(caddr_t)]; caddr_t val; char val_r_[PADR_(caddr_t)]; char avalsize_l_[PADL_(int *)]; int * avalsize; char avalsize_r_[PADR_(int *)]; }; struct readv_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char iovp_l_[PADL_(struct iovec *)]; struct iovec * iovp; char iovp_r_[PADR_(struct iovec *)]; char iovcnt_l_[PADL_(u_int)]; u_int iovcnt; char iovcnt_r_[PADR_(u_int)]; }; struct writev_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char iovp_l_[PADL_(struct iovec *)]; struct iovec * iovp; char iovp_r_[PADR_(struct iovec *)]; char iovcnt_l_[PADL_(u_int)]; u_int iovcnt; char iovcnt_r_[PADR_(u_int)]; }; struct settimeofday_args { char tv_l_[PADL_(struct timeval *)]; struct timeval * tv; char tv_r_[PADR_(struct timeval *)]; char tzp_l_[PADL_(struct timezone *)]; struct timezone * tzp; char tzp_r_[PADR_(struct timezone *)]; }; struct fchown_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char uid_l_[PADL_(int)]; int uid; char uid_r_[PADR_(int)]; char gid_l_[PADL_(int)]; int gid; char gid_r_[PADR_(int)]; }; struct fchmod_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; }; struct setreuid_args { char ruid_l_[PADL_(int)]; int ruid; char ruid_r_[PADR_(int)]; char euid_l_[PADL_(int)]; int euid; char euid_r_[PADR_(int)]; }; struct setregid_args { char rgid_l_[PADL_(int)]; int rgid; char rgid_r_[PADR_(int)]; char egid_l_[PADL_(int)]; int egid; char egid_r_[PADR_(int)]; }; struct rename_args { char from_l_[PADL_(char *)]; char * from; char from_r_[PADR_(char *)]; char to_l_[PADL_(char *)]; char * to; char to_r_[PADR_(char *)]; }; struct flock_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char how_l_[PADL_(int)]; int how; char how_r_[PADR_(int)]; }; struct mkfifo_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; }; struct sendto_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char buf_l_[PADL_(caddr_t)]; caddr_t buf; char buf_r_[PADR_(caddr_t)]; char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; char to_l_[PADL_(caddr_t)]; caddr_t to; char to_r_[PADR_(caddr_t)]; char tolen_l_[PADL_(int)]; int tolen; char tolen_r_[PADR_(int)]; }; struct shutdown_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char how_l_[PADL_(int)]; int how; char how_r_[PADR_(int)]; }; struct socketpair_args { char domain_l_[PADL_(int)]; int domain; char domain_r_[PADR_(int)]; char type_l_[PADL_(int)]; int type; char type_r_[PADR_(int)]; char protocol_l_[PADL_(int)]; int protocol; char protocol_r_[PADR_(int)]; char rsv_l_[PADL_(int *)]; int * rsv; char rsv_r_[PADR_(int *)]; }; struct mkdir_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; }; struct rmdir_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct utimes_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char tptr_l_[PADL_(struct timeval *)]; struct timeval * tptr; char tptr_r_[PADR_(struct timeval *)]; }; struct adjtime_args { char delta_l_[PADL_(struct timeval *)]; struct timeval * delta; char delta_r_[PADR_(struct timeval *)]; char olddelta_l_[PADL_(struct timeval *)]; struct timeval * olddelta; char olddelta_r_[PADR_(struct timeval *)]; }; struct ogethostid_args { register_t dummy; }; struct setsid_args { register_t dummy; }; struct quotactl_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char uid_l_[PADL_(int)]; int uid; char uid_r_[PADR_(int)]; char arg_l_[PADL_(caddr_t)]; caddr_t arg; char arg_r_[PADR_(caddr_t)]; }; struct oquota_args { register_t dummy; }; struct nfssvc_args { char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)]; char argp_l_[PADL_(caddr_t)]; caddr_t argp; char argp_r_[PADR_(caddr_t)]; }; struct lgetfh_args { char fname_l_[PADL_(char *)]; char * fname; char fname_r_[PADR_(char *)]; char fhp_l_[PADL_(struct fhandle *)]; struct fhandle * fhp; char fhp_r_[PADR_(struct fhandle *)]; }; struct getfh_args { char fname_l_[PADL_(char *)]; char * fname; char fname_r_[PADR_(char *)]; char fhp_l_[PADL_(struct fhandle *)]; struct fhandle * fhp; char fhp_r_[PADR_(struct fhandle *)]; }; struct getdomainname_args { char domainname_l_[PADL_(char *)]; char * domainname; char domainname_r_[PADR_(char *)]; char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)]; }; struct setdomainname_args { char domainname_l_[PADL_(char *)]; char * domainname; char domainname_r_[PADR_(char *)]; char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)]; }; struct uname_args { char name_l_[PADL_(struct utsname *)]; struct utsname * name; char name_r_[PADR_(struct utsname *)]; }; struct sysarch_args { char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)]; char parms_l_[PADL_(char *)]; char * parms; char parms_r_[PADR_(char *)]; }; struct rtprio_args { char function_l_[PADL_(int)]; int function; char function_r_[PADR_(int)]; char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)]; char rtp_l_[PADL_(struct rtprio *)]; struct rtprio * rtp; char rtp_r_[PADR_(struct rtprio *)]; }; struct semsys_args { char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)]; char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)]; char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)]; char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)]; char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)]; }; struct msgsys_args { char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)]; char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)]; char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)]; char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)]; char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)]; char a6_l_[PADL_(int)]; int a6; char a6_r_[PADR_(int)]; }; struct shmsys_args { char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)]; char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)]; char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)]; char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)]; }; struct pread_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char buf_l_[PADL_(void *)]; void * buf; char buf_r_[PADR_(void *)]; char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)]; char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)]; char offset_l_[PADL_(off_t)]; off_t offset; char offset_r_[PADR_(off_t)]; }; struct pwrite_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char buf_l_[PADL_(const void *)]; const void * buf; char buf_r_[PADR_(const void *)]; char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)]; char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)]; char offset_l_[PADL_(off_t)]; off_t offset; char offset_r_[PADR_(off_t)]; }; struct ntp_adjtime_args { char tp_l_[PADL_(struct timex *)]; struct timex * tp; char tp_r_[PADR_(struct timex *)]; }; struct setgid_args { char gid_l_[PADL_(gid_t)]; gid_t gid; char gid_r_[PADR_(gid_t)]; }; struct setegid_args { char egid_l_[PADL_(gid_t)]; gid_t egid; char egid_r_[PADR_(gid_t)]; }; struct seteuid_args { char euid_l_[PADL_(uid_t)]; uid_t euid; char euid_r_[PADR_(uid_t)]; }; struct stat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char ub_l_[PADL_(struct stat *)]; struct stat * ub; char ub_r_[PADR_(struct stat *)]; }; struct fstat_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char sb_l_[PADL_(struct stat *)]; struct stat * sb; char sb_r_[PADR_(struct stat *)]; }; struct lstat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char ub_l_[PADL_(struct stat *)]; struct stat * ub; char ub_r_[PADR_(struct stat *)]; }; struct pathconf_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)]; }; struct fpathconf_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)]; }; struct __getrlimit_args { char which_l_[PADL_(u_int)]; u_int which; char which_r_[PADR_(u_int)]; char rlp_l_[PADL_(struct rlimit *)]; struct rlimit * rlp; char rlp_r_[PADR_(struct rlimit *)]; }; struct __setrlimit_args { char which_l_[PADL_(u_int)]; u_int which; char which_r_[PADR_(u_int)]; char rlp_l_[PADL_(struct rlimit *)]; struct rlimit * rlp; char rlp_r_[PADR_(struct rlimit *)]; }; struct getdirentries_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; char count_l_[PADL_(u_int)]; u_int count; char count_r_[PADR_(u_int)]; char basep_l_[PADL_(long *)]; long * basep; char basep_r_[PADR_(long *)]; }; struct mmap_args { char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)]; char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)]; char pos_l_[PADL_(off_t)]; off_t pos; char pos_r_[PADR_(off_t)]; }; struct lseek_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)]; char offset_l_[PADL_(off_t)]; off_t offset; char offset_r_[PADR_(off_t)]; char whence_l_[PADL_(int)]; int whence; char whence_r_[PADR_(int)]; }; struct truncate_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)]; char length_l_[PADL_(off_t)]; off_t length; char length_r_[PADR_(off_t)]; }; struct ftruncate_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)]; char length_l_[PADL_(off_t)]; off_t length; char length_r_[PADR_(off_t)]; }; struct sysctl_args { char name_l_[PADL_(int *)]; int * name; char name_r_[PADR_(int *)]; char namelen_l_[PADL_(u_int)]; u_int namelen; char namelen_r_[PADR_(u_int)]; char old_l_[PADL_(void *)]; void * old; char old_r_[PADR_(void *)]; char oldlenp_l_[PADL_(size_t *)]; size_t * oldlenp; char oldlenp_r_[PADR_(size_t *)]; char new_l_[PADL_(void *)]; void * new; char new_r_[PADR_(void *)]; char newlen_l_[PADL_(size_t)]; size_t newlen; char newlen_r_[PADR_(size_t)]; }; struct mlock_args { char addr_l_[PADL_(const void *)]; const void * addr; char addr_r_[PADR_(const void *)]; char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; }; struct munlock_args { char addr_l_[PADL_(const void *)]; const void * addr; char addr_r_[PADR_(const void *)]; char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; }; struct undelete_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct futimes_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char tptr_l_[PADL_(struct timeval *)]; struct timeval * tptr; char tptr_r_[PADR_(struct timeval *)]; }; struct getpgid_args { char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)]; }; struct poll_args { char fds_l_[PADL_(struct pollfd *)]; struct pollfd * fds; char fds_r_[PADR_(struct pollfd *)]; char nfds_l_[PADL_(u_int)]; u_int nfds; char nfds_r_[PADR_(u_int)]; char timeout_l_[PADL_(int)]; int timeout; char timeout_r_[PADR_(int)]; }; struct __semctl_args { char semid_l_[PADL_(int)]; int semid; char semid_r_[PADR_(int)]; char semnum_l_[PADL_(int)]; int semnum; char semnum_r_[PADR_(int)]; char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char arg_l_[PADL_(union semun *)]; union semun * arg; char arg_r_[PADR_(union semun *)]; }; struct semget_args { char key_l_[PADL_(key_t)]; key_t key; char key_r_[PADR_(key_t)]; char nsems_l_[PADL_(int)]; int nsems; char nsems_r_[PADR_(int)]; char semflg_l_[PADL_(int)]; int semflg; char semflg_r_[PADR_(int)]; }; struct semop_args { char semid_l_[PADL_(int)]; int semid; char semid_r_[PADR_(int)]; char sops_l_[PADL_(struct sembuf *)]; struct sembuf * sops; char sops_r_[PADR_(struct sembuf *)]; char nsops_l_[PADL_(size_t)]; size_t nsops; char nsops_r_[PADR_(size_t)]; }; struct msgctl_args { char msqid_l_[PADL_(int)]; int msqid; char msqid_r_[PADR_(int)]; char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char buf_l_[PADL_(struct msqid_ds *)]; struct msqid_ds * buf; char buf_r_[PADR_(struct msqid_ds *)]; }; struct msgget_args { char key_l_[PADL_(key_t)]; key_t key; char key_r_[PADR_(key_t)]; char msgflg_l_[PADL_(int)]; int msgflg; char msgflg_r_[PADR_(int)]; }; struct msgsnd_args { char msqid_l_[PADL_(int)]; int msqid; char msqid_r_[PADR_(int)]; char msgp_l_[PADL_(const void *)]; const void * msgp; char msgp_r_[PADR_(const void *)]; char msgsz_l_[PADL_(size_t)]; size_t msgsz; char msgsz_r_[PADR_(size_t)]; char msgflg_l_[PADL_(int)]; int msgflg; char msgflg_r_[PADR_(int)]; }; struct msgrcv_args { char msqid_l_[PADL_(int)]; int msqid; char msqid_r_[PADR_(int)]; char msgp_l_[PADL_(void *)]; void * msgp; char msgp_r_[PADR_(void *)]; char msgsz_l_[PADL_(size_t)]; size_t msgsz; char msgsz_r_[PADR_(size_t)]; char msgtyp_l_[PADL_(long)]; long msgtyp; char msgtyp_r_[PADR_(long)]; char msgflg_l_[PADL_(int)]; int msgflg; char msgflg_r_[PADR_(int)]; }; struct shmat_args { char shmid_l_[PADL_(int)]; int shmid; char shmid_r_[PADR_(int)]; char shmaddr_l_[PADL_(const void *)]; const void * shmaddr; char shmaddr_r_[PADR_(const void *)]; char shmflg_l_[PADL_(int)]; int shmflg; char shmflg_r_[PADR_(int)]; }; struct shmctl_args { char shmid_l_[PADL_(int)]; int shmid; char shmid_r_[PADR_(int)]; char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char buf_l_[PADL_(struct shmid_ds *)]; struct shmid_ds * buf; char buf_r_[PADR_(struct shmid_ds *)]; }; struct shmdt_args { char shmaddr_l_[PADL_(const void *)]; const void * shmaddr; char shmaddr_r_[PADR_(const void *)]; }; struct shmget_args { char key_l_[PADL_(key_t)]; key_t key; char key_r_[PADR_(key_t)]; char size_l_[PADL_(size_t)]; size_t size; char size_r_[PADR_(size_t)]; char shmflg_l_[PADL_(int)]; int shmflg; char shmflg_r_[PADR_(int)]; }; struct clock_gettime_args { char clock_id_l_[PADL_(clockid_t)]; clockid_t clock_id; char clock_id_r_[PADR_(clockid_t)]; char tp_l_[PADL_(struct timespec *)]; struct timespec * tp; char tp_r_[PADR_(struct timespec *)]; }; struct clock_settime_args { char clock_id_l_[PADL_(clockid_t)]; clockid_t clock_id; char clock_id_r_[PADR_(clockid_t)]; char tp_l_[PADL_(const struct timespec *)]; const struct timespec * tp; char tp_r_[PADR_(const struct timespec *)]; }; struct clock_getres_args { char clock_id_l_[PADL_(clockid_t)]; clockid_t clock_id; char clock_id_r_[PADR_(clockid_t)]; char tp_l_[PADL_(struct timespec *)]; struct timespec * tp; char tp_r_[PADR_(struct timespec *)]; }; struct ktimer_create_args { char clock_id_l_[PADL_(clockid_t)]; clockid_t clock_id; char clock_id_r_[PADR_(clockid_t)]; char evp_l_[PADL_(struct sigevent *)]; struct sigevent * evp; char evp_r_[PADR_(struct sigevent *)]; char timerid_l_[PADL_(int *)]; int * timerid; char timerid_r_[PADR_(int *)]; }; struct ktimer_delete_args { char timerid_l_[PADL_(int)]; int timerid; char timerid_r_[PADR_(int)]; }; struct ktimer_settime_args { char timerid_l_[PADL_(int)]; int timerid; char timerid_r_[PADR_(int)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; char value_l_[PADL_(const struct itimerspec *)]; const struct itimerspec * value; char value_r_[PADR_(const struct itimerspec *)]; char ovalue_l_[PADL_(struct itimerspec *)]; struct itimerspec * ovalue; char ovalue_r_[PADR_(struct itimerspec *)]; }; struct ktimer_gettime_args { char timerid_l_[PADL_(int)]; int timerid; char timerid_r_[PADR_(int)]; char value_l_[PADL_(struct itimerspec *)]; struct itimerspec * value; char value_r_[PADR_(struct itimerspec *)]; }; struct ktimer_getoverrun_args { char timerid_l_[PADL_(int)]; int timerid; char timerid_r_[PADR_(int)]; }; struct nanosleep_args { char rqtp_l_[PADL_(const struct timespec *)]; const struct timespec * rqtp; char rqtp_r_[PADR_(const struct timespec *)]; char rmtp_l_[PADL_(struct timespec *)]; struct timespec * rmtp; char rmtp_r_[PADR_(struct timespec *)]; }; struct ntp_gettime_args { char ntvp_l_[PADL_(struct ntptimeval *)]; struct ntptimeval * ntvp; char ntvp_r_[PADR_(struct ntptimeval *)]; }; struct minherit_args { char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)]; char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; char inherit_l_[PADL_(int)]; int inherit; char inherit_r_[PADR_(int)]; }; struct rfork_args { char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct openbsd_poll_args { char fds_l_[PADL_(struct pollfd *)]; struct pollfd * fds; char fds_r_[PADR_(struct pollfd *)]; char nfds_l_[PADL_(u_int)]; u_int nfds; char nfds_r_[PADR_(u_int)]; char timeout_l_[PADL_(int)]; int timeout; char timeout_r_[PADR_(int)]; }; struct issetugid_args { register_t dummy; }; struct lchown_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char uid_l_[PADL_(int)]; int uid; char uid_r_[PADR_(int)]; char gid_l_[PADL_(int)]; int gid; char gid_r_[PADR_(int)]; }; struct aio_read_args { char aiocbp_l_[PADL_(struct aiocb *)]; struct aiocb * aiocbp; char aiocbp_r_[PADR_(struct aiocb *)]; }; struct aio_write_args { char aiocbp_l_[PADL_(struct aiocb *)]; struct aiocb * aiocbp; char aiocbp_r_[PADR_(struct aiocb *)]; }; struct lio_listio_args { char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; char acb_list_l_[PADL_(struct aiocb *const *)]; struct aiocb *const * acb_list; char acb_list_r_[PADR_(struct aiocb *const *)]; char nent_l_[PADL_(int)]; int nent; char nent_r_[PADR_(int)]; char sig_l_[PADL_(struct sigevent *)]; struct sigevent * sig; char sig_r_[PADR_(struct sigevent *)]; }; struct getdents_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; char count_l_[PADL_(size_t)]; size_t count; char count_r_[PADR_(size_t)]; }; struct lchmod_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)]; }; struct lutimes_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char tptr_l_[PADL_(struct timeval *)]; struct timeval * tptr; char tptr_r_[PADR_(struct timeval *)]; }; struct nstat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char ub_l_[PADL_(struct nstat *)]; struct nstat * ub; char ub_r_[PADR_(struct nstat *)]; }; struct nfstat_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char sb_l_[PADL_(struct nstat *)]; struct nstat * sb; char sb_r_[PADR_(struct nstat *)]; }; struct nlstat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char ub_l_[PADL_(struct nstat *)]; struct nstat * ub; char ub_r_[PADR_(struct nstat *)]; }; struct preadv_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char iovp_l_[PADL_(struct iovec *)]; struct iovec * iovp; char iovp_r_[PADR_(struct iovec *)]; char iovcnt_l_[PADL_(u_int)]; u_int iovcnt; char iovcnt_r_[PADR_(u_int)]; char offset_l_[PADL_(off_t)]; off_t offset; char offset_r_[PADR_(off_t)]; }; struct pwritev_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char iovp_l_[PADL_(struct iovec *)]; struct iovec * iovp; char iovp_r_[PADR_(struct iovec *)]; char iovcnt_l_[PADL_(u_int)]; u_int iovcnt; char iovcnt_r_[PADR_(u_int)]; char offset_l_[PADL_(off_t)]; off_t offset; char offset_r_[PADR_(off_t)]; }; struct fhopen_args { char u_fhp_l_[PADL_(const struct fhandle *)]; const struct fhandle * u_fhp; char u_fhp_r_[PADR_(const struct fhandle *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct fhstat_args { char u_fhp_l_[PADL_(const struct fhandle *)]; const struct fhandle * u_fhp; char u_fhp_r_[PADR_(const struct fhandle *)]; char sb_l_[PADL_(struct stat *)]; struct stat * sb; char sb_r_[PADR_(struct stat *)]; }; struct modnext_args { char modid_l_[PADL_(int)]; int modid; char modid_r_[PADR_(int)]; }; struct modstat_args { char modid_l_[PADL_(int)]; int modid; char modid_r_[PADR_(int)]; char stat_l_[PADL_(struct module_stat *)]; struct module_stat * stat; char stat_r_[PADR_(struct module_stat *)]; }; struct modfnext_args { char modid_l_[PADL_(int)]; int modid; char modid_r_[PADR_(int)]; }; struct modfind_args { char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; }; struct kldload_args { char file_l_[PADL_(const char *)]; const char * file; char file_r_[PADR_(const char *)]; }; struct kldunload_args { char fileid_l_[PADL_(int)]; int fileid; char fileid_r_[PADR_(int)]; }; struct kldfind_args { char file_l_[PADL_(const char *)]; const char * file; char file_r_[PADR_(const char *)]; }; struct kldnext_args { char fileid_l_[PADL_(int)]; int fileid; char fileid_r_[PADR_(int)]; }; struct kldstat_args { char fileid_l_[PADL_(int)]; int fileid; char fileid_r_[PADR_(int)]; char stat_l_[PADL_(struct kld_file_stat *)]; struct kld_file_stat * stat; char stat_r_[PADR_(struct kld_file_stat *)]; }; struct kldfirstmod_args { char fileid_l_[PADL_(int)]; int fileid; char fileid_r_[PADR_(int)]; }; struct getsid_args { char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)]; }; struct setresuid_args { char ruid_l_[PADL_(uid_t)]; uid_t ruid; char ruid_r_[PADR_(uid_t)]; char euid_l_[PADL_(uid_t)]; uid_t euid; char euid_r_[PADR_(uid_t)]; char suid_l_[PADL_(uid_t)]; uid_t suid; char suid_r_[PADR_(uid_t)]; }; struct setresgid_args { char rgid_l_[PADL_(gid_t)]; gid_t rgid; char rgid_r_[PADR_(gid_t)]; char egid_l_[PADL_(gid_t)]; gid_t egid; char egid_r_[PADR_(gid_t)]; char sgid_l_[PADL_(gid_t)]; gid_t sgid; char sgid_r_[PADR_(gid_t)]; }; struct aio_return_args { char aiocbp_l_[PADL_(struct aiocb *)]; struct aiocb * aiocbp; char aiocbp_r_[PADR_(struct aiocb *)]; }; struct aio_suspend_args { char aiocbp_l_[PADL_(struct aiocb *const *)]; struct aiocb *const * aiocbp; char aiocbp_r_[PADR_(struct aiocb *const *)]; char nent_l_[PADL_(int)]; int nent; char nent_r_[PADR_(int)]; char timeout_l_[PADL_(const struct timespec *)]; const struct timespec * timeout; char timeout_r_[PADR_(const struct timespec *)]; }; struct aio_cancel_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char aiocbp_l_[PADL_(struct aiocb *)]; struct aiocb * aiocbp; char aiocbp_r_[PADR_(struct aiocb *)]; }; struct aio_error_args { char aiocbp_l_[PADL_(struct aiocb *)]; struct aiocb * aiocbp; char aiocbp_r_[PADR_(struct aiocb *)]; }; struct oaio_read_args { char aiocbp_l_[PADL_(struct oaiocb *)]; struct oaiocb * aiocbp; char aiocbp_r_[PADR_(struct oaiocb *)]; }; struct oaio_write_args { char aiocbp_l_[PADL_(struct oaiocb *)]; struct oaiocb * aiocbp; char aiocbp_r_[PADR_(struct oaiocb *)]; }; struct olio_listio_args { char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; char acb_list_l_[PADL_(struct oaiocb *const *)]; struct oaiocb *const * acb_list; char acb_list_r_[PADR_(struct oaiocb *const *)]; char nent_l_[PADL_(int)]; int nent; char nent_r_[PADR_(int)]; char sig_l_[PADL_(struct osigevent *)]; struct osigevent * sig; char sig_r_[PADR_(struct osigevent *)]; }; struct yield_args { register_t dummy; }; struct mlockall_args { char how_l_[PADL_(int)]; int how; char how_r_[PADR_(int)]; }; struct munlockall_args { register_t dummy; }; struct __getcwd_args { char buf_l_[PADL_(u_char *)]; u_char * buf; char buf_r_[PADR_(u_char *)]; char buflen_l_[PADL_(u_int)]; u_int buflen; char buflen_r_[PADR_(u_int)]; }; struct sched_setparam_args { char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)]; char param_l_[PADL_(const struct sched_param *)]; const struct sched_param * param; char param_r_[PADR_(const struct sched_param *)]; }; struct sched_getparam_args { char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)]; char param_l_[PADL_(struct sched_param *)]; struct sched_param * param; char param_r_[PADR_(struct sched_param *)]; }; struct sched_setscheduler_args { char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)]; char policy_l_[PADL_(int)]; int policy; char policy_r_[PADR_(int)]; char param_l_[PADL_(const struct sched_param *)]; const struct sched_param * param; char param_r_[PADR_(const struct sched_param *)]; }; struct sched_getscheduler_args { char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)]; }; struct sched_yield_args { register_t dummy; }; struct sched_get_priority_max_args { char policy_l_[PADL_(int)]; int policy; char policy_r_[PADR_(int)]; }; struct sched_get_priority_min_args { char policy_l_[PADL_(int)]; int policy; char policy_r_[PADR_(int)]; }; struct sched_rr_get_interval_args { char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)]; char interval_l_[PADL_(struct timespec *)]; struct timespec * interval; char interval_r_[PADR_(struct timespec *)]; }; struct utrace_args { char addr_l_[PADL_(const void *)]; const void * addr; char addr_r_[PADR_(const void *)]; char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; }; struct kldsym_args { char fileid_l_[PADL_(int)]; int fileid; char fileid_r_[PADR_(int)]; char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char data_l_[PADL_(void *)]; void * data; char data_r_[PADR_(void *)]; }; struct jail_args { char jail_l_[PADL_(struct jail *)]; struct jail * jail; char jail_r_[PADR_(struct jail *)]; }; struct sigprocmask_args { char how_l_[PADL_(int)]; int how; char how_r_[PADR_(int)]; char set_l_[PADL_(const sigset_t *)]; const sigset_t * set; char set_r_[PADR_(const sigset_t *)]; char oset_l_[PADL_(sigset_t *)]; sigset_t * oset; char oset_r_[PADR_(sigset_t *)]; }; struct sigsuspend_args { char sigmask_l_[PADL_(const sigset_t *)]; const sigset_t * sigmask; char sigmask_r_[PADR_(const sigset_t *)]; }; struct sigpending_args { char set_l_[PADL_(sigset_t *)]; sigset_t * set; char set_r_[PADR_(sigset_t *)]; }; struct sigtimedwait_args { char set_l_[PADL_(const sigset_t *)]; const sigset_t * set; char set_r_[PADR_(const sigset_t *)]; char info_l_[PADL_(siginfo_t *)]; siginfo_t * info; char info_r_[PADR_(siginfo_t *)]; char timeout_l_[PADL_(const struct timespec *)]; const struct timespec * timeout; char timeout_r_[PADR_(const struct timespec *)]; }; struct sigwaitinfo_args { char set_l_[PADL_(const sigset_t *)]; const sigset_t * set; char set_r_[PADR_(const sigset_t *)]; char info_l_[PADL_(siginfo_t *)]; siginfo_t * info; char info_r_[PADR_(siginfo_t *)]; }; struct __acl_get_file_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct __acl_set_file_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct __acl_get_fd_args { char filedes_l_[PADL_(int)]; int filedes; char filedes_r_[PADR_(int)]; char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct __acl_set_fd_args { char filedes_l_[PADL_(int)]; int filedes; char filedes_r_[PADR_(int)]; char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct __acl_delete_file_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; }; struct __acl_delete_fd_args { char filedes_l_[PADL_(int)]; int filedes; char filedes_r_[PADR_(int)]; char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; }; struct __acl_aclcheck_file_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct __acl_aclcheck_fd_args { char filedes_l_[PADL_(int)]; int filedes; char filedes_r_[PADR_(int)]; char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct extattrctl_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char filename_l_[PADL_(const char *)]; const char * filename; char filename_r_[PADR_(const char *)]; char attrnamespace_l_[PADL_(int)]; int attrnamespace; char attrnamespace_r_[PADR_(int)]; char attrname_l_[PADL_(const char *)]; const char * attrname; char attrname_r_[PADR_(const char *)]; }; struct extattr_set_file_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char attrnamespace_l_[PADL_(int)]; int attrnamespace; char attrnamespace_r_[PADR_(int)]; char attrname_l_[PADL_(const char *)]; const char * attrname; char attrname_r_[PADR_(const char *)]; char data_l_[PADL_(void *)]; void * data; char data_r_[PADR_(void *)]; char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)]; }; struct extattr_get_file_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char attrnamespace_l_[PADL_(int)]; int attrnamespace; char attrnamespace_r_[PADR_(int)]; char attrname_l_[PADL_(const char *)]; const char * attrname; char attrname_r_[PADR_(const char *)]; char data_l_[PADL_(void *)]; void * data; char data_r_[PADR_(void *)]; char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)]; }; struct extattr_delete_file_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char attrnamespace_l_[PADL_(int)]; int attrnamespace; char attrnamespace_r_[PADR_(int)]; char attrname_l_[PADL_(const char *)]; const char * attrname; char attrname_r_[PADR_(const char *)]; }; struct aio_waitcomplete_args { char aiocbp_l_[PADL_(struct aiocb **)]; struct aiocb ** aiocbp; char aiocbp_r_[PADR_(struct aiocb **)]; char timeout_l_[PADL_(struct timespec *)]; struct timespec * timeout; char timeout_r_[PADR_(struct timespec *)]; }; struct getresuid_args { char ruid_l_[PADL_(uid_t *)]; uid_t * ruid; char ruid_r_[PADR_(uid_t *)]; char euid_l_[PADL_(uid_t *)]; uid_t * euid; char euid_r_[PADR_(uid_t *)]; char suid_l_[PADL_(uid_t *)]; uid_t * suid; char suid_r_[PADR_(uid_t *)]; }; struct getresgid_args { char rgid_l_[PADL_(gid_t *)]; gid_t * rgid; char rgid_r_[PADR_(gid_t *)]; char egid_l_[PADL_(gid_t *)]; gid_t * egid; char egid_r_[PADR_(gid_t *)]; char sgid_l_[PADL_(gid_t *)]; gid_t * sgid; char sgid_r_[PADR_(gid_t *)]; }; struct kqueue_args { register_t dummy; }; struct kevent_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char changelist_l_[PADL_(struct kevent *)]; struct kevent * changelist; char changelist_r_[PADR_(struct kevent *)]; char nchanges_l_[PADL_(int)]; int nchanges; char nchanges_r_[PADR_(int)]; char eventlist_l_[PADL_(struct kevent *)]; struct kevent * eventlist; char eventlist_r_[PADR_(struct kevent *)]; char nevents_l_[PADL_(int)]; int nevents; char nevents_r_[PADR_(int)]; char timeout_l_[PADL_(const struct timespec *)]; const struct timespec * timeout; char timeout_r_[PADR_(const struct timespec *)]; }; struct extattr_set_fd_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char attrnamespace_l_[PADL_(int)]; int attrnamespace; char attrnamespace_r_[PADR_(int)]; char attrname_l_[PADL_(const char *)]; const char * attrname; char attrname_r_[PADR_(const char *)]; char data_l_[PADL_(void *)]; void * data; char data_r_[PADR_(void *)]; char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)]; }; struct extattr_get_fd_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char attrnamespace_l_[PADL_(int)]; int attrnamespace; char attrnamespace_r_[PADR_(int)]; char attrname_l_[PADL_(const char *)]; const char * attrname; char attrname_r_[PADR_(const char *)]; char data_l_[PADL_(void *)]; void * data; char data_r_[PADR_(void *)]; char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)]; }; struct extattr_delete_fd_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char attrnamespace_l_[PADL_(int)]; int attrnamespace; char attrnamespace_r_[PADR_(int)]; char attrname_l_[PADL_(const char *)]; const char * attrname; char attrname_r_[PADR_(const char *)]; }; struct __setugid_args { char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)]; }; struct nfsclnt_args { char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)]; char argp_l_[PADL_(caddr_t)]; caddr_t argp; char argp_r_[PADR_(caddr_t)]; }; struct eaccess_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct nmount_args { char iovp_l_[PADL_(struct iovec *)]; struct iovec * iovp; char iovp_r_[PADR_(struct iovec *)]; char iovcnt_l_[PADL_(unsigned int)]; unsigned int iovcnt; char iovcnt_r_[PADR_(unsigned int)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct kse_exit_args { register_t dummy; }; struct kse_wakeup_args { char mbx_l_[PADL_(struct kse_mailbox *)]; struct kse_mailbox * mbx; char mbx_r_[PADR_(struct kse_mailbox *)]; }; struct kse_create_args { char mbx_l_[PADL_(struct kse_mailbox *)]; struct kse_mailbox * mbx; char mbx_r_[PADR_(struct kse_mailbox *)]; char newgroup_l_[PADL_(int)]; int newgroup; char newgroup_r_[PADR_(int)]; }; struct kse_thr_interrupt_args { char tmbx_l_[PADL_(struct kse_thr_mailbox *)]; struct kse_thr_mailbox * tmbx; char tmbx_r_[PADR_(struct kse_thr_mailbox *)]; char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char data_l_[PADL_(long)]; long data; char data_r_[PADR_(long)]; }; struct kse_release_args { char timeout_l_[PADL_(struct timespec *)]; struct timespec * timeout; char timeout_r_[PADR_(struct timespec *)]; }; struct __mac_get_proc_args { char mac_p_l_[PADL_(struct mac *)]; struct mac * mac_p; char mac_p_r_[PADR_(struct mac *)]; }; struct __mac_set_proc_args { char mac_p_l_[PADL_(struct mac *)]; struct mac * mac_p; char mac_p_r_[PADR_(struct mac *)]; }; struct __mac_get_fd_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char mac_p_l_[PADL_(struct mac *)]; struct mac * mac_p; char mac_p_r_[PADR_(struct mac *)]; }; struct __mac_get_file_args { char path_p_l_[PADL_(const char *)]; const char * path_p; char path_p_r_[PADR_(const char *)]; char mac_p_l_[PADL_(struct mac *)]; struct mac * mac_p; char mac_p_r_[PADR_(struct mac *)]; }; struct __mac_set_fd_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char mac_p_l_[PADL_(struct mac *)]; struct mac * mac_p; char mac_p_r_[PADR_(struct mac *)]; }; struct __mac_set_file_args { char path_p_l_[PADL_(const char *)]; const char * path_p; char path_p_r_[PADR_(const char *)]; char mac_p_l_[PADL_(struct mac *)]; struct mac * mac_p; char mac_p_r_[PADR_(struct mac *)]; }; struct kenv_args { char what_l_[PADL_(int)]; int what; char what_r_[PADR_(int)]; char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; char value_l_[PADL_(char *)]; char * value; char value_r_[PADR_(char *)]; char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)]; }; struct lchflags_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct uuidgen_args { char store_l_[PADL_(struct uuid *)]; struct uuid * store; char store_r_[PADR_(struct uuid *)]; char count_l_[PADL_(int)]; int count; char count_r_[PADR_(int)]; }; struct sendfile_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char offset_l_[PADL_(off_t)]; off_t offset; char offset_r_[PADR_(off_t)]; char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)]; char hdtr_l_[PADL_(struct sf_hdtr *)]; struct sf_hdtr * hdtr; char hdtr_r_[PADR_(struct sf_hdtr *)]; char sbytes_l_[PADL_(off_t *)]; off_t * sbytes; char sbytes_r_[PADR_(off_t *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct mac_syscall_args { char policy_l_[PADL_(const char *)]; const char * policy; char policy_r_[PADR_(const char *)]; char call_l_[PADL_(int)]; int call; char call_r_[PADR_(int)]; char arg_l_[PADL_(void *)]; void * arg; char arg_r_[PADR_(void *)]; }; struct getfsstat_args { char buf_l_[PADL_(struct statfs *)]; struct statfs * buf; char buf_r_[PADR_(struct statfs *)]; char bufsize_l_[PADL_(long)]; long bufsize; char bufsize_r_[PADR_(long)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct statfs_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char buf_l_[PADL_(struct statfs *)]; struct statfs * buf; char buf_r_[PADR_(struct statfs *)]; }; struct fstatfs_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char buf_l_[PADL_(struct statfs *)]; struct statfs * buf; char buf_r_[PADR_(struct statfs *)]; }; struct fhstatfs_args { char u_fhp_l_[PADL_(const struct fhandle *)]; const struct fhandle * u_fhp; char u_fhp_r_[PADR_(const struct fhandle *)]; char buf_l_[PADL_(struct statfs *)]; struct statfs * buf; char buf_r_[PADR_(struct statfs *)]; }; struct ksem_close_args { char id_l_[PADL_(semid_t)]; semid_t id; char id_r_[PADR_(semid_t)]; }; struct ksem_post_args { char id_l_[PADL_(semid_t)]; semid_t id; char id_r_[PADR_(semid_t)]; }; struct ksem_wait_args { char id_l_[PADL_(semid_t)]; semid_t id; char id_r_[PADR_(semid_t)]; }; struct ksem_trywait_args { char id_l_[PADL_(semid_t)]; semid_t id; char id_r_[PADR_(semid_t)]; }; struct ksem_init_args { char idp_l_[PADL_(semid_t *)]; semid_t * idp; char idp_r_[PADR_(semid_t *)]; char value_l_[PADL_(unsigned int)]; unsigned int value; char value_r_[PADR_(unsigned int)]; }; struct ksem_open_args { char idp_l_[PADL_(semid_t *)]; semid_t * idp; char idp_r_[PADR_(semid_t *)]; char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; char oflag_l_[PADL_(int)]; int oflag; char oflag_r_[PADR_(int)]; char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)]; char value_l_[PADL_(unsigned int)]; unsigned int value; char value_r_[PADR_(unsigned int)]; }; struct ksem_unlink_args { char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; }; struct ksem_getvalue_args { char id_l_[PADL_(semid_t)]; semid_t id; char id_r_[PADR_(semid_t)]; char val_l_[PADL_(int *)]; int * val; char val_r_[PADR_(int *)]; }; struct ksem_destroy_args { char id_l_[PADL_(semid_t)]; semid_t id; char id_r_[PADR_(semid_t)]; }; struct __mac_get_pid_args { char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)]; char mac_p_l_[PADL_(struct mac *)]; struct mac * mac_p; char mac_p_r_[PADR_(struct mac *)]; }; struct __mac_get_link_args { char path_p_l_[PADL_(const char *)]; const char * path_p; char path_p_r_[PADR_(const char *)]; char mac_p_l_[PADL_(struct mac *)]; struct mac * mac_p; char mac_p_r_[PADR_(struct mac *)]; }; struct __mac_set_link_args { char path_p_l_[PADL_(const char *)]; const char * path_p; char path_p_r_[PADR_(const char *)]; char mac_p_l_[PADL_(struct mac *)]; struct mac * mac_p; char mac_p_r_[PADR_(struct mac *)]; }; struct extattr_set_link_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char attrnamespace_l_[PADL_(int)]; int attrnamespace; char attrnamespace_r_[PADR_(int)]; char attrname_l_[PADL_(const char *)]; const char * attrname; char attrname_r_[PADR_(const char *)]; char data_l_[PADL_(void *)]; void * data; char data_r_[PADR_(void *)]; char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)]; }; struct extattr_get_link_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char attrnamespace_l_[PADL_(int)]; int attrnamespace; char attrnamespace_r_[PADR_(int)]; char attrname_l_[PADL_(const char *)]; const char * attrname; char attrname_r_[PADR_(const char *)]; char data_l_[PADL_(void *)]; void * data; char data_r_[PADR_(void *)]; char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)]; }; struct extattr_delete_link_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char attrnamespace_l_[PADL_(int)]; int attrnamespace; char attrnamespace_r_[PADR_(int)]; char attrname_l_[PADL_(const char *)]; const char * attrname; char attrname_r_[PADR_(const char *)]; }; struct __mac_execve_args { char fname_l_[PADL_(char *)]; char * fname; char fname_r_[PADR_(char *)]; char argv_l_[PADL_(char **)]; char ** argv; char argv_r_[PADR_(char **)]; char envv_l_[PADL_(char **)]; char ** envv; char envv_r_[PADR_(char **)]; char mac_p_l_[PADL_(struct mac *)]; struct mac * mac_p; char mac_p_r_[PADR_(struct mac *)]; }; struct sigaction_args { char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)]; char act_l_[PADL_(const struct sigaction *)]; const struct sigaction * act; char act_r_[PADR_(const struct sigaction *)]; char oact_l_[PADL_(struct sigaction *)]; struct sigaction * oact; char oact_r_[PADR_(struct sigaction *)]; }; struct sigreturn_args { char sigcntxp_l_[PADL_(const struct __ucontext *)]; const struct __ucontext * sigcntxp; char sigcntxp_r_[PADR_(const struct __ucontext *)]; }; struct getcontext_args { char ucp_l_[PADL_(struct __ucontext *)]; struct __ucontext * ucp; char ucp_r_[PADR_(struct __ucontext *)]; }; struct setcontext_args { char ucp_l_[PADL_(const struct __ucontext *)]; const struct __ucontext * ucp; char ucp_r_[PADR_(const struct __ucontext *)]; }; struct swapcontext_args { char oucp_l_[PADL_(struct __ucontext *)]; struct __ucontext * oucp; char oucp_r_[PADR_(struct __ucontext *)]; char ucp_l_[PADL_(const struct __ucontext *)]; const struct __ucontext * ucp; char ucp_r_[PADR_(const struct __ucontext *)]; }; struct swapoff_args { char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; }; struct __acl_get_link_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct __acl_set_link_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct __acl_delete_link_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; }; struct __acl_aclcheck_link_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)]; char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)]; }; struct sigwait_args { char set_l_[PADL_(const sigset_t *)]; const sigset_t * set; char set_r_[PADR_(const sigset_t *)]; char sig_l_[PADL_(int *)]; int * sig; char sig_r_[PADR_(int *)]; }; struct thr_create_args { char ctx_l_[PADL_(ucontext_t *)]; ucontext_t * ctx; char ctx_r_[PADR_(ucontext_t *)]; char id_l_[PADL_(long *)]; long * id; char id_r_[PADR_(long *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct thr_exit_args { char state_l_[PADL_(long *)]; long * state; char state_r_[PADR_(long *)]; }; struct thr_self_args { char id_l_[PADL_(long *)]; long * id; char id_r_[PADR_(long *)]; }; struct thr_kill_args { char id_l_[PADL_(long)]; long id; char id_r_[PADR_(long)]; char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)]; }; struct _umtx_lock_args { char umtx_l_[PADL_(struct umtx *)]; struct umtx * umtx; char umtx_r_[PADR_(struct umtx *)]; }; struct _umtx_unlock_args { char umtx_l_[PADL_(struct umtx *)]; struct umtx * umtx; char umtx_r_[PADR_(struct umtx *)]; }; struct jail_attach_args { char jid_l_[PADL_(int)]; int jid; char jid_r_[PADR_(int)]; }; struct extattr_list_fd_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char attrnamespace_l_[PADL_(int)]; int attrnamespace; char attrnamespace_r_[PADR_(int)]; char data_l_[PADL_(void *)]; void * data; char data_r_[PADR_(void *)]; char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)]; }; struct extattr_list_file_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char attrnamespace_l_[PADL_(int)]; int attrnamespace; char attrnamespace_r_[PADR_(int)]; char data_l_[PADL_(void *)]; void * data; char data_r_[PADR_(void *)]; char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)]; }; struct extattr_list_link_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char attrnamespace_l_[PADL_(int)]; int attrnamespace; char attrnamespace_r_[PADR_(int)]; char data_l_[PADL_(void *)]; void * data; char data_r_[PADR_(void *)]; char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)]; }; struct kse_switchin_args { char tmbx_l_[PADL_(struct kse_thr_mailbox *)]; struct kse_thr_mailbox * tmbx; char tmbx_r_[PADR_(struct kse_thr_mailbox *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct ksem_timedwait_args { char id_l_[PADL_(semid_t)]; semid_t id; char id_r_[PADR_(semid_t)]; char abstime_l_[PADL_(const struct timespec *)]; const struct timespec * abstime; char abstime_r_[PADR_(const struct timespec *)]; }; struct thr_suspend_args { char timeout_l_[PADL_(const struct timespec *)]; const struct timespec * timeout; char timeout_r_[PADR_(const struct timespec *)]; }; struct thr_wake_args { char id_l_[PADL_(long)]; long id; char id_r_[PADR_(long)]; }; struct kldunloadf_args { char fileid_l_[PADL_(int)]; int fileid; char fileid_r_[PADR_(int)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct audit_args { char record_l_[PADL_(const void *)]; const void * record; char record_r_[PADR_(const void *)]; char length_l_[PADL_(u_int)]; u_int length; char length_r_[PADR_(u_int)]; }; struct auditon_args { char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)]; char data_l_[PADL_(void *)]; void * data; char data_r_[PADR_(void *)]; char length_l_[PADL_(u_int)]; u_int length; char length_r_[PADR_(u_int)]; }; struct getauid_args { char auid_l_[PADL_(uid_t *)]; uid_t * auid; char auid_r_[PADR_(uid_t *)]; }; struct setauid_args { char auid_l_[PADL_(uid_t *)]; uid_t * auid; char auid_r_[PADR_(uid_t *)]; }; struct getaudit_args { char auditinfo_l_[PADL_(struct auditinfo *)]; struct auditinfo * auditinfo; char auditinfo_r_[PADR_(struct auditinfo *)]; }; struct setaudit_args { char auditinfo_l_[PADL_(struct auditinfo *)]; struct auditinfo * auditinfo; char auditinfo_r_[PADR_(struct auditinfo *)]; }; struct getaudit_addr_args { char auditinfo_addr_l_[PADL_(struct auditinfo_addr *)]; struct auditinfo_addr * auditinfo_addr; char auditinfo_addr_r_[PADR_(struct auditinfo_addr *)]; char length_l_[PADL_(u_int)]; u_int length; char length_r_[PADR_(u_int)]; }; struct setaudit_addr_args { char auditinfo_addr_l_[PADL_(struct auditinfo_addr *)]; struct auditinfo_addr * auditinfo_addr; char auditinfo_addr_r_[PADR_(struct auditinfo_addr *)]; char length_l_[PADL_(u_int)]; u_int length; char length_r_[PADR_(u_int)]; }; struct auditctl_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; }; struct _umtx_op_args { char obj_l_[PADL_(void *)]; void * obj; char obj_r_[PADR_(void *)]; char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)]; char val_l_[PADL_(u_long)]; u_long val; char val_r_[PADR_(u_long)]; char uaddr1_l_[PADL_(void *)]; void * uaddr1; char uaddr1_r_[PADR_(void *)]; char uaddr2_l_[PADL_(void *)]; void * uaddr2; char uaddr2_r_[PADR_(void *)]; }; struct thr_new_args { char param_l_[PADL_(struct thr_param *)]; struct thr_param * param; char param_r_[PADR_(struct thr_param *)]; char param_size_l_[PADL_(int)]; int param_size; char param_size_r_[PADR_(int)]; }; struct sigqueue_args { char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)]; char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)]; char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; }; struct kmq_open_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)]; char attr_l_[PADL_(const struct mq_attr *)]; const struct mq_attr * attr; char attr_r_[PADR_(const struct mq_attr *)]; }; struct kmq_setattr_args { char mqd_l_[PADL_(int)]; int mqd; char mqd_r_[PADR_(int)]; char attr_l_[PADL_(const struct mq_attr *)]; const struct mq_attr * attr; char attr_r_[PADR_(const struct mq_attr *)]; char oattr_l_[PADL_(struct mq_attr *)]; struct mq_attr * oattr; char oattr_r_[PADR_(struct mq_attr *)]; }; struct kmq_timedreceive_args { char mqd_l_[PADL_(int)]; int mqd; char mqd_r_[PADR_(int)]; char msg_ptr_l_[PADL_(char *)]; char * msg_ptr; char msg_ptr_r_[PADR_(char *)]; char msg_len_l_[PADL_(size_t)]; size_t msg_len; char msg_len_r_[PADR_(size_t)]; char msg_prio_l_[PADL_(unsigned *)]; unsigned * msg_prio; char msg_prio_r_[PADR_(unsigned *)]; char abs_timeout_l_[PADL_(const struct timespec *)]; const struct timespec * abs_timeout; char abs_timeout_r_[PADR_(const struct timespec *)]; }; struct kmq_timedsend_args { char mqd_l_[PADL_(int)]; int mqd; char mqd_r_[PADR_(int)]; char msg_ptr_l_[PADL_(const char *)]; const char * msg_ptr; char msg_ptr_r_[PADR_(const char *)]; char msg_len_l_[PADL_(size_t)]; size_t msg_len; char msg_len_r_[PADR_(size_t)]; char msg_prio_l_[PADL_(unsigned)]; unsigned msg_prio; char msg_prio_r_[PADR_(unsigned)]; char abs_timeout_l_[PADL_(const struct timespec *)]; const struct timespec * abs_timeout; char abs_timeout_r_[PADR_(const struct timespec *)]; }; struct kmq_notify_args { char mqd_l_[PADL_(int)]; int mqd; char mqd_r_[PADR_(int)]; char sigev_l_[PADL_(const struct sigevent *)]; const struct sigevent * sigev; char sigev_r_[PADR_(const struct sigevent *)]; }; struct kmq_unlink_args { char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)]; }; struct abort2_args { char why_l_[PADL_(const char *)]; const char * why; char why_r_[PADR_(const char *)]; char nargs_l_[PADL_(int)]; int nargs; char nargs_r_[PADR_(int)]; char args_l_[PADL_(void **)]; void ** args; char args_r_[PADR_(void **)]; }; struct thr_set_name_args { char id_l_[PADL_(long)]; long id; char id_r_[PADR_(long)]; char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)]; }; struct aio_fsync_args { char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)]; char aiocbp_l_[PADL_(struct aiocb *)]; struct aiocb * aiocbp; char aiocbp_r_[PADR_(struct aiocb *)]; }; struct rtprio_thread_args { char function_l_[PADL_(int)]; int function; char function_r_[PADR_(int)]; char lwpid_l_[PADL_(lwpid_t)]; lwpid_t lwpid; char lwpid_r_[PADR_(lwpid_t)]; char rtp_l_[PADL_(struct rtprio *)]; struct rtprio * rtp; char rtp_r_[PADR_(struct rtprio *)]; }; struct sctp_peeloff_args { char sd_l_[PADL_(int)]; int sd; char sd_r_[PADR_(int)]; char name_l_[PADL_(uint32_t)]; uint32_t name; char name_r_[PADR_(uint32_t)]; }; struct sctp_generic_sendmsg_args { char sd_l_[PADL_(int)]; int sd; char sd_r_[PADR_(int)]; char msg_l_[PADL_(caddr_t)]; caddr_t msg; char msg_r_[PADR_(caddr_t)]; char mlen_l_[PADL_(int)]; int mlen; char mlen_r_[PADR_(int)]; char to_l_[PADL_(caddr_t)]; caddr_t to; char to_r_[PADR_(caddr_t)]; char tolen_l_[PADL_(__socklen_t)]; __socklen_t tolen; char tolen_r_[PADR_(__socklen_t)]; char sinfo_l_[PADL_(struct sctp_sndrcvinfo *)]; struct sctp_sndrcvinfo * sinfo; char sinfo_r_[PADR_(struct sctp_sndrcvinfo *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct sctp_generic_sendmsg_iov_args { char sd_l_[PADL_(int)]; int sd; char sd_r_[PADR_(int)]; char iov_l_[PADL_(struct iovec *)]; struct iovec * iov; char iov_r_[PADR_(struct iovec *)]; char iovlen_l_[PADL_(int)]; int iovlen; char iovlen_r_[PADR_(int)]; char to_l_[PADL_(caddr_t)]; caddr_t to; char to_r_[PADR_(caddr_t)]; char tolen_l_[PADL_(__socklen_t)]; __socklen_t tolen; char tolen_r_[PADR_(__socklen_t)]; char sinfo_l_[PADL_(struct sctp_sndrcvinfo *)]; struct sctp_sndrcvinfo * sinfo; char sinfo_r_[PADR_(struct sctp_sndrcvinfo *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct sctp_generic_recvmsg_args { char sd_l_[PADL_(int)]; int sd; char sd_r_[PADR_(int)]; char iov_l_[PADL_(struct iovec *)]; struct iovec * iov; char iov_r_[PADR_(struct iovec *)]; char iovlen_l_[PADL_(int)]; int iovlen; char iovlen_r_[PADR_(int)]; char from_l_[PADL_(struct sockaddr *)]; struct sockaddr * from; char from_r_[PADR_(struct sockaddr *)]; char fromlenaddr_l_[PADL_(__socklen_t *)]; __socklen_t * fromlenaddr; char fromlenaddr_r_[PADR_(__socklen_t *)]; char sinfo_l_[PADL_(struct sctp_sndrcvinfo *)]; struct sctp_sndrcvinfo * sinfo; char sinfo_r_[PADR_(struct sctp_sndrcvinfo *)]; char msg_flags_l_[PADL_(int *)]; int * msg_flags; char msg_flags_r_[PADR_(int *)]; }; int nosys(struct thread *, struct nosys_args *); void sys_exit(struct thread *, struct sys_exit_args *); int fork(struct thread *, struct fork_args *); int read(struct thread *, struct read_args *); int write(struct thread *, struct write_args *); int open(struct thread *, struct open_args *); int close(struct thread *, struct close_args *); int wait4(struct thread *, struct wait_args *); int link(struct thread *, struct link_args *); int unlink(struct thread *, struct unlink_args *); int chdir(struct thread *, struct chdir_args *); int fchdir(struct thread *, struct fchdir_args *); int mknod(struct thread *, struct mknod_args *); int chmod(struct thread *, struct chmod_args *); int chown(struct thread *, struct chown_args *); int obreak(struct thread *, struct obreak_args *); int getpid(struct thread *, struct getpid_args *); int mount(struct thread *, struct mount_args *); int unmount(struct thread *, struct unmount_args *); int setuid(struct thread *, struct setuid_args *); int getuid(struct thread *, struct getuid_args *); int geteuid(struct thread *, struct geteuid_args *); int ptrace(struct thread *, struct ptrace_args *); int recvmsg(struct thread *, struct recvmsg_args *); int sendmsg(struct thread *, struct sendmsg_args *); int recvfrom(struct thread *, struct recvfrom_args *); int accept(struct thread *, struct accept_args *); int getpeername(struct thread *, struct getpeername_args *); int getsockname(struct thread *, struct getsockname_args *); int access(struct thread *, struct access_args *); int chflags(struct thread *, struct chflags_args *); int fchflags(struct thread *, struct fchflags_args *); int sync(struct thread *, struct sync_args *); int kill(struct thread *, struct kill_args *); int getppid(struct thread *, struct getppid_args *); int dup(struct thread *, struct dup_args *); int pipe(struct thread *, struct pipe_args *); int getegid(struct thread *, struct getegid_args *); int profil(struct thread *, struct profil_args *); int ktrace(struct thread *, struct ktrace_args *); int getgid(struct thread *, struct getgid_args *); int getlogin(struct thread *, struct getlogin_args *); int setlogin(struct thread *, struct setlogin_args *); int acct(struct thread *, struct acct_args *); int sigaltstack(struct thread *, struct sigaltstack_args *); int ioctl(struct thread *, struct ioctl_args *); int reboot(struct thread *, struct reboot_args *); int revoke(struct thread *, struct revoke_args *); int symlink(struct thread *, struct symlink_args *); int readlink(struct thread *, struct readlink_args *); int execve(struct thread *, struct execve_args *); int umask(struct thread *, struct umask_args *); int chroot(struct thread *, struct chroot_args *); int msync(struct thread *, struct msync_args *); int vfork(struct thread *, struct vfork_args *); int sbrk(struct thread *, struct sbrk_args *); int sstk(struct thread *, struct sstk_args *); int ovadvise(struct thread *, struct ovadvise_args *); int munmap(struct thread *, struct munmap_args *); int mprotect(struct thread *, struct mprotect_args *); int madvise(struct thread *, struct madvise_args *); int mincore(struct thread *, struct mincore_args *); int getgroups(struct thread *, struct getgroups_args *); int setgroups(struct thread *, struct setgroups_args *); int getpgrp(struct thread *, struct getpgrp_args *); int setpgid(struct thread *, struct setpgid_args *); int setitimer(struct thread *, struct setitimer_args *); int swapon(struct thread *, struct swapon_args *); int getitimer(struct thread *, struct getitimer_args *); int getdtablesize(struct thread *, struct getdtablesize_args *); int dup2(struct thread *, struct dup2_args *); int fcntl(struct thread *, struct fcntl_args *); int select(struct thread *, struct select_args *); int fsync(struct thread *, struct fsync_args *); int setpriority(struct thread *, struct setpriority_args *); int socket(struct thread *, struct socket_args *); int connect(struct thread *, struct connect_args *); int getpriority(struct thread *, struct getpriority_args *); int bind(struct thread *, struct bind_args *); int setsockopt(struct thread *, struct setsockopt_args *); int listen(struct thread *, struct listen_args *); int gettimeofday(struct thread *, struct gettimeofday_args *); int getrusage(struct thread *, struct getrusage_args *); int getsockopt(struct thread *, struct getsockopt_args *); int readv(struct thread *, struct readv_args *); int writev(struct thread *, struct writev_args *); int settimeofday(struct thread *, struct settimeofday_args *); int fchown(struct thread *, struct fchown_args *); int fchmod(struct thread *, struct fchmod_args *); int setreuid(struct thread *, struct setreuid_args *); int setregid(struct thread *, struct setregid_args *); int rename(struct thread *, struct rename_args *); int flock(struct thread *, struct flock_args *); int mkfifo(struct thread *, struct mkfifo_args *); int sendto(struct thread *, struct sendto_args *); int shutdown(struct thread *, struct shutdown_args *); int socketpair(struct thread *, struct socketpair_args *); int mkdir(struct thread *, struct mkdir_args *); int rmdir(struct thread *, struct rmdir_args *); int utimes(struct thread *, struct utimes_args *); int adjtime(struct thread *, struct adjtime_args *); int setsid(struct thread *, struct setsid_args *); int quotactl(struct thread *, struct quotactl_args *); int nfssvc(struct thread *, struct nfssvc_args *); int lgetfh(struct thread *, struct lgetfh_args *); int getfh(struct thread *, struct getfh_args *); int getdomainname(struct thread *, struct getdomainname_args *); int setdomainname(struct thread *, struct setdomainname_args *); int uname(struct thread *, struct uname_args *); int sysarch(struct thread *, struct sysarch_args *); int rtprio(struct thread *, struct rtprio_args *); int semsys(struct thread *, struct semsys_args *); int msgsys(struct thread *, struct msgsys_args *); int shmsys(struct thread *, struct shmsys_args *); int pread(struct thread *, struct pread_args *); int pwrite(struct thread *, struct pwrite_args *); int ntp_adjtime(struct thread *, struct ntp_adjtime_args *); int setgid(struct thread *, struct setgid_args *); int setegid(struct thread *, struct setegid_args *); int seteuid(struct thread *, struct seteuid_args *); int stat(struct thread *, struct stat_args *); int fstat(struct thread *, struct fstat_args *); int lstat(struct thread *, struct lstat_args *); int pathconf(struct thread *, struct pathconf_args *); int fpathconf(struct thread *, struct fpathconf_args *); int getrlimit(struct thread *, struct __getrlimit_args *); int setrlimit(struct thread *, struct __setrlimit_args *); int getdirentries(struct thread *, struct getdirentries_args *); int mmap(struct thread *, struct mmap_args *); int lseek(struct thread *, struct lseek_args *); int truncate(struct thread *, struct truncate_args *); int ftruncate(struct thread *, struct ftruncate_args *); int __sysctl(struct thread *, struct sysctl_args *); int mlock(struct thread *, struct mlock_args *); int munlock(struct thread *, struct munlock_args *); int undelete(struct thread *, struct undelete_args *); int futimes(struct thread *, struct futimes_args *); int getpgid(struct thread *, struct getpgid_args *); int poll(struct thread *, struct poll_args *); int lkmnosys(struct thread *, struct nosys_args *); int __semctl(struct thread *, struct __semctl_args *); int semget(struct thread *, struct semget_args *); int semop(struct thread *, struct semop_args *); int msgctl(struct thread *, struct msgctl_args *); int msgget(struct thread *, struct msgget_args *); int msgsnd(struct thread *, struct msgsnd_args *); int msgrcv(struct thread *, struct msgrcv_args *); int shmat(struct thread *, struct shmat_args *); int shmctl(struct thread *, struct shmctl_args *); int shmdt(struct thread *, struct shmdt_args *); int shmget(struct thread *, struct shmget_args *); int clock_gettime(struct thread *, struct clock_gettime_args *); int clock_settime(struct thread *, struct clock_settime_args *); int clock_getres(struct thread *, struct clock_getres_args *); int ktimer_create(struct thread *, struct ktimer_create_args *); int ktimer_delete(struct thread *, struct ktimer_delete_args *); int ktimer_settime(struct thread *, struct ktimer_settime_args *); int ktimer_gettime(struct thread *, struct ktimer_gettime_args *); int ktimer_getoverrun(struct thread *, struct ktimer_getoverrun_args *); int nanosleep(struct thread *, struct nanosleep_args *); int ntp_gettime(struct thread *, struct ntp_gettime_args *); int minherit(struct thread *, struct minherit_args *); int rfork(struct thread *, struct rfork_args *); int openbsd_poll(struct thread *, struct openbsd_poll_args *); int issetugid(struct thread *, struct issetugid_args *); int lchown(struct thread *, struct lchown_args *); int aio_read(struct thread *, struct aio_read_args *); int aio_write(struct thread *, struct aio_write_args *); int lio_listio(struct thread *, struct lio_listio_args *); int getdents(struct thread *, struct getdents_args *); int lchmod(struct thread *, struct lchmod_args *); int lutimes(struct thread *, struct lutimes_args *); int nstat(struct thread *, struct nstat_args *); int nfstat(struct thread *, struct nfstat_args *); int nlstat(struct thread *, struct nlstat_args *); int preadv(struct thread *, struct preadv_args *); int pwritev(struct thread *, struct pwritev_args *); int fhopen(struct thread *, struct fhopen_args *); int fhstat(struct thread *, struct fhstat_args *); int modnext(struct thread *, struct modnext_args *); int modstat(struct thread *, struct modstat_args *); int modfnext(struct thread *, struct modfnext_args *); int modfind(struct thread *, struct modfind_args *); int kldload(struct thread *, struct kldload_args *); int kldunload(struct thread *, struct kldunload_args *); int kldfind(struct thread *, struct kldfind_args *); int kldnext(struct thread *, struct kldnext_args *); int kldstat(struct thread *, struct kldstat_args *); int kldfirstmod(struct thread *, struct kldfirstmod_args *); int getsid(struct thread *, struct getsid_args *); int setresuid(struct thread *, struct setresuid_args *); int setresgid(struct thread *, struct setresgid_args *); int aio_return(struct thread *, struct aio_return_args *); int aio_suspend(struct thread *, struct aio_suspend_args *); int aio_cancel(struct thread *, struct aio_cancel_args *); int aio_error(struct thread *, struct aio_error_args *); int oaio_read(struct thread *, struct oaio_read_args *); int oaio_write(struct thread *, struct oaio_write_args *); int olio_listio(struct thread *, struct olio_listio_args *); int yield(struct thread *, struct yield_args *); int mlockall(struct thread *, struct mlockall_args *); int munlockall(struct thread *, struct munlockall_args *); int __getcwd(struct thread *, struct __getcwd_args *); int sched_setparam(struct thread *, struct sched_setparam_args *); int sched_getparam(struct thread *, struct sched_getparam_args *); int sched_setscheduler(struct thread *, struct sched_setscheduler_args *); int sched_getscheduler(struct thread *, struct sched_getscheduler_args *); int sched_yield(struct thread *, struct sched_yield_args *); int sched_get_priority_max(struct thread *, struct sched_get_priority_max_args *); int sched_get_priority_min(struct thread *, struct sched_get_priority_min_args *); int sched_rr_get_interval(struct thread *, struct sched_rr_get_interval_args *); int utrace(struct thread *, struct utrace_args *); int kldsym(struct thread *, struct kldsym_args *); int jail(struct thread *, struct jail_args *); int sigprocmask(struct thread *, struct sigprocmask_args *); int sigsuspend(struct thread *, struct sigsuspend_args *); int sigpending(struct thread *, struct sigpending_args *); int sigtimedwait(struct thread *, struct sigtimedwait_args *); int sigwaitinfo(struct thread *, struct sigwaitinfo_args *); int __acl_get_file(struct thread *, struct __acl_get_file_args *); int __acl_set_file(struct thread *, struct __acl_set_file_args *); int __acl_get_fd(struct thread *, struct __acl_get_fd_args *); int __acl_set_fd(struct thread *, struct __acl_set_fd_args *); int __acl_delete_file(struct thread *, struct __acl_delete_file_args *); int __acl_delete_fd(struct thread *, struct __acl_delete_fd_args *); int __acl_aclcheck_file(struct thread *, struct __acl_aclcheck_file_args *); int __acl_aclcheck_fd(struct thread *, struct __acl_aclcheck_fd_args *); int extattrctl(struct thread *, struct extattrctl_args *); int extattr_set_file(struct thread *, struct extattr_set_file_args *); int extattr_get_file(struct thread *, struct extattr_get_file_args *); int extattr_delete_file(struct thread *, struct extattr_delete_file_args *); int aio_waitcomplete(struct thread *, struct aio_waitcomplete_args *); int getresuid(struct thread *, struct getresuid_args *); int getresgid(struct thread *, struct getresgid_args *); int kqueue(struct thread *, struct kqueue_args *); int kevent(struct thread *, struct kevent_args *); int lkmressys(struct thread *, struct nosys_args *); int extattr_set_fd(struct thread *, struct extattr_set_fd_args *); int extattr_get_fd(struct thread *, struct extattr_get_fd_args *); int extattr_delete_fd(struct thread *, struct extattr_delete_fd_args *); int __setugid(struct thread *, struct __setugid_args *); int nfsclnt(struct thread *, struct nfsclnt_args *); int eaccess(struct thread *, struct eaccess_args *); int nmount(struct thread *, struct nmount_args *); int kse_exit(struct thread *, struct kse_exit_args *); int kse_wakeup(struct thread *, struct kse_wakeup_args *); int kse_create(struct thread *, struct kse_create_args *); int kse_thr_interrupt(struct thread *, struct kse_thr_interrupt_args *); int kse_release(struct thread *, struct kse_release_args *); int __mac_get_proc(struct thread *, struct __mac_get_proc_args *); int __mac_set_proc(struct thread *, struct __mac_set_proc_args *); int __mac_get_fd(struct thread *, struct __mac_get_fd_args *); int __mac_get_file(struct thread *, struct __mac_get_file_args *); int __mac_set_fd(struct thread *, struct __mac_set_fd_args *); int __mac_set_file(struct thread *, struct __mac_set_file_args *); int kenv(struct thread *, struct kenv_args *); int lchflags(struct thread *, struct lchflags_args *); int uuidgen(struct thread *, struct uuidgen_args *); int sendfile(struct thread *, struct sendfile_args *); int mac_syscall(struct thread *, struct mac_syscall_args *); int getfsstat(struct thread *, struct getfsstat_args *); int statfs(struct thread *, struct statfs_args *); int fstatfs(struct thread *, struct fstatfs_args *); int fhstatfs(struct thread *, struct fhstatfs_args *); int ksem_close(struct thread *, struct ksem_close_args *); int ksem_post(struct thread *, struct ksem_post_args *); int ksem_wait(struct thread *, struct ksem_wait_args *); int ksem_trywait(struct thread *, struct ksem_trywait_args *); int ksem_init(struct thread *, struct ksem_init_args *); int ksem_open(struct thread *, struct ksem_open_args *); int ksem_unlink(struct thread *, struct ksem_unlink_args *); int ksem_getvalue(struct thread *, struct ksem_getvalue_args *); int ksem_destroy(struct thread *, struct ksem_destroy_args *); int __mac_get_pid(struct thread *, struct __mac_get_pid_args *); int __mac_get_link(struct thread *, struct __mac_get_link_args *); int __mac_set_link(struct thread *, struct __mac_set_link_args *); int extattr_set_link(struct thread *, struct extattr_set_link_args *); int extattr_get_link(struct thread *, struct extattr_get_link_args *); int extattr_delete_link(struct thread *, struct extattr_delete_link_args *); int __mac_execve(struct thread *, struct __mac_execve_args *); int sigaction(struct thread *, struct sigaction_args *); int sigreturn(struct thread *, struct sigreturn_args *); int getcontext(struct thread *, struct getcontext_args *); int setcontext(struct thread *, struct setcontext_args *); int swapcontext(struct thread *, struct swapcontext_args *); int swapoff(struct thread *, struct swapoff_args *); int __acl_get_link(struct thread *, struct __acl_get_link_args *); int __acl_set_link(struct thread *, struct __acl_set_link_args *); int __acl_delete_link(struct thread *, struct __acl_delete_link_args *); int __acl_aclcheck_link(struct thread *, struct __acl_aclcheck_link_args *); int sigwait(struct thread *, struct sigwait_args *); int thr_create(struct thread *, struct thr_create_args *); int thr_exit(struct thread *, struct thr_exit_args *); int thr_self(struct thread *, struct thr_self_args *); int thr_kill(struct thread *, struct thr_kill_args *); int _umtx_lock(struct thread *, struct _umtx_lock_args *); int _umtx_unlock(struct thread *, struct _umtx_unlock_args *); int jail_attach(struct thread *, struct jail_attach_args *); int extattr_list_fd(struct thread *, struct extattr_list_fd_args *); int extattr_list_file(struct thread *, struct extattr_list_file_args *); int extattr_list_link(struct thread *, struct extattr_list_link_args *); int kse_switchin(struct thread *, struct kse_switchin_args *); int ksem_timedwait(struct thread *, struct ksem_timedwait_args *); int thr_suspend(struct thread *, struct thr_suspend_args *); int thr_wake(struct thread *, struct thr_wake_args *); int kldunloadf(struct thread *, struct kldunloadf_args *); int audit(struct thread *, struct audit_args *); int auditon(struct thread *, struct auditon_args *); int getauid(struct thread *, struct getauid_args *); int setauid(struct thread *, struct setauid_args *); int getaudit(struct thread *, struct getaudit_args *); int setaudit(struct thread *, struct setaudit_args *); int getaudit_addr(struct thread *, struct getaudit_addr_args *); int setaudit_addr(struct thread *, struct setaudit_addr_args *); int auditctl(struct thread *, struct auditctl_args *); int _umtx_op(struct thread *, struct _umtx_op_args *); int thr_new(struct thread *, struct thr_new_args *); int sigqueue(struct thread *, struct sigqueue_args *); int kmq_open(struct thread *, struct kmq_open_args *); int kmq_setattr(struct thread *, struct kmq_setattr_args *); int kmq_timedreceive(struct thread *, struct kmq_timedreceive_args *); int kmq_timedsend(struct thread *, struct kmq_timedsend_args *); int kmq_notify(struct thread *, struct kmq_notify_args *); int kmq_unlink(struct thread *, struct kmq_unlink_args *); int abort2(struct thread *, struct abort2_args *); int thr_set_name(struct thread *, struct thr_set_name_args *); int aio_fsync(struct thread *, struct aio_fsync_args *); int rtprio_thread(struct thread *, struct rtprio_thread_args *); int sctp_peeloff(struct thread *, struct sctp_peeloff_args *); int sctp_generic_sendmsg(struct thread *, struct sctp_generic_sendmsg_args *); int sctp_generic_sendmsg_iov(struct thread *, struct sctp_generic_sendmsg_iov_args *); int sctp_generic_recvmsg(struct thread *, struct sctp_generic_recvmsg_args *); #ifdef COMPAT_43 struct ocreat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; }; struct olseek_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char offset_l_[PADL_(long)]; long offset; char offset_r_[PADR_(long)]; char whence_l_[PADL_(int)]; int whence; char whence_r_[PADR_(int)]; }; struct ostat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char ub_l_[PADL_(struct ostat *)]; struct ostat * ub; char ub_r_[PADR_(struct ostat *)]; }; struct olstat_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char ub_l_[PADL_(struct ostat *)]; struct ostat * ub; char ub_r_[PADR_(struct ostat *)]; }; struct osigaction_args { char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)]; char nsa_l_[PADL_(struct osigaction *)]; struct osigaction * nsa; char nsa_r_[PADR_(struct osigaction *)]; char osa_l_[PADL_(struct osigaction *)]; struct osigaction * osa; char osa_r_[PADR_(struct osigaction *)]; }; struct osigprocmask_args { char how_l_[PADL_(int)]; int how; char how_r_[PADR_(int)]; char mask_l_[PADL_(osigset_t)]; osigset_t mask; char mask_r_[PADR_(osigset_t)]; }; struct ofstat_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char sb_l_[PADL_(struct ostat *)]; struct ostat * sb; char sb_r_[PADR_(struct ostat *)]; }; struct getkerninfo_args { char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)]; char where_l_[PADL_(char *)]; char * where; char where_r_[PADR_(char *)]; char size_l_[PADL_(size_t *)]; size_t * size; char size_r_[PADR_(size_t *)]; char arg_l_[PADL_(int)]; int arg; char arg_r_[PADR_(int)]; }; struct ommap_args { char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)]; char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)]; char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char pos_l_[PADL_(long)]; long pos; char pos_r_[PADR_(long)]; }; struct gethostname_args { char hostname_l_[PADL_(char *)]; char * hostname; char hostname_r_[PADR_(char *)]; char len_l_[PADL_(u_int)]; u_int len; char len_r_[PADR_(u_int)]; }; struct sethostname_args { char hostname_l_[PADL_(char *)]; char * hostname; char hostname_r_[PADR_(char *)]; char len_l_[PADL_(u_int)]; u_int len; char len_r_[PADR_(u_int)]; }; struct osend_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char buf_l_[PADL_(caddr_t)]; caddr_t buf; char buf_r_[PADR_(caddr_t)]; char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct orecv_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char buf_l_[PADL_(caddr_t)]; caddr_t buf; char buf_r_[PADR_(caddr_t)]; char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct osigreturn_args { char sigcntxp_l_[PADL_(struct osigcontext *)]; struct osigcontext * sigcntxp; char sigcntxp_r_[PADR_(struct osigcontext *)]; }; struct osigvec_args { char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)]; char nsv_l_[PADL_(struct sigvec *)]; struct sigvec * nsv; char nsv_r_[PADR_(struct sigvec *)]; char osv_l_[PADL_(struct sigvec *)]; struct sigvec * osv; char osv_r_[PADR_(struct sigvec *)]; }; struct osigblock_args { char mask_l_[PADL_(int)]; int mask; char mask_r_[PADR_(int)]; }; struct osigsetmask_args { char mask_l_[PADL_(int)]; int mask; char mask_r_[PADR_(int)]; }; struct osigsuspend_args { char mask_l_[PADL_(osigset_t)]; osigset_t mask; char mask_r_[PADR_(osigset_t)]; }; struct osigstack_args { char nss_l_[PADL_(struct sigstack *)]; struct sigstack * nss; char nss_r_[PADR_(struct sigstack *)]; char oss_l_[PADL_(struct sigstack *)]; struct sigstack * oss; char oss_r_[PADR_(struct sigstack *)]; }; struct orecvmsg_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char msg_l_[PADL_(struct omsghdr *)]; struct omsghdr * msg; char msg_r_[PADR_(struct omsghdr *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct osendmsg_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char msg_l_[PADL_(caddr_t)]; caddr_t msg; char msg_r_[PADR_(caddr_t)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct otruncate_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char length_l_[PADL_(long)]; long length; char length_r_[PADR_(long)]; }; struct oftruncate_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char length_l_[PADL_(long)]; long length; char length_r_[PADR_(long)]; }; struct ogetpeername_args { char fdes_l_[PADL_(int)]; int fdes; char fdes_r_[PADR_(int)]; char asa_l_[PADL_(caddr_t)]; caddr_t asa; char asa_r_[PADR_(caddr_t)]; char alen_l_[PADL_(int *)]; int * alen; char alen_r_[PADR_(int *)]; }; struct osethostid_args { char hostid_l_[PADL_(long)]; long hostid; char hostid_r_[PADR_(long)]; }; struct ogetrlimit_args { char which_l_[PADL_(u_int)]; u_int which; char which_r_[PADR_(u_int)]; char rlp_l_[PADL_(struct orlimit *)]; struct orlimit * rlp; char rlp_r_[PADR_(struct orlimit *)]; }; struct osetrlimit_args { char which_l_[PADL_(u_int)]; u_int which; char which_r_[PADR_(u_int)]; char rlp_l_[PADL_(struct orlimit *)]; struct orlimit * rlp; char rlp_r_[PADR_(struct orlimit *)]; }; struct okillpg_args { char pgid_l_[PADL_(int)]; int pgid; char pgid_r_[PADR_(int)]; char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)]; }; struct ogetdirentries_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)]; char count_l_[PADL_(u_int)]; u_int count; char count_r_[PADR_(u_int)]; char basep_l_[PADL_(long *)]; long * basep; char basep_r_[PADR_(long *)]; }; int ocreat(struct thread *, struct ocreat_args *); int olseek(struct thread *, struct olseek_args *); int ostat(struct thread *, struct ostat_args *); int olstat(struct thread *, struct olstat_args *); int osigaction(struct thread *, struct osigaction_args *); int osigprocmask(struct thread *, struct osigprocmask_args *); int osigpending(struct thread *, struct osigpending_args *); int ofstat(struct thread *, struct ofstat_args *); int ogetkerninfo(struct thread *, struct getkerninfo_args *); int ogetpagesize(struct thread *, struct getpagesize_args *); int ommap(struct thread *, struct ommap_args *); int owait(struct thread *, struct owait_args *); int ogethostname(struct thread *, struct gethostname_args *); int osethostname(struct thread *, struct sethostname_args *); int oaccept(struct thread *, struct accept_args *); int osend(struct thread *, struct osend_args *); int orecv(struct thread *, struct orecv_args *); int osigreturn(struct thread *, struct osigreturn_args *); int osigvec(struct thread *, struct osigvec_args *); int osigblock(struct thread *, struct osigblock_args *); int osigsetmask(struct thread *, struct osigsetmask_args *); int osigsuspend(struct thread *, struct osigsuspend_args *); int osigstack(struct thread *, struct osigstack_args *); int orecvmsg(struct thread *, struct orecvmsg_args *); int osendmsg(struct thread *, struct osendmsg_args *); int orecvfrom(struct thread *, struct recvfrom_args *); int otruncate(struct thread *, struct otruncate_args *); int oftruncate(struct thread *, struct oftruncate_args *); int ogetpeername(struct thread *, struct ogetpeername_args *); int ogethostid(struct thread *, struct ogethostid_args *); int osethostid(struct thread *, struct osethostid_args *); int ogetrlimit(struct thread *, struct ogetrlimit_args *); int osetrlimit(struct thread *, struct osetrlimit_args *); int okillpg(struct thread *, struct okillpg_args *); int oquota(struct thread *, struct oquota_args *); int ogetsockname(struct thread *, struct getsockname_args *); int ogetdirentries(struct thread *, struct ogetdirentries_args *); #endif /* COMPAT_43 */ #ifdef COMPAT_FREEBSD4 struct freebsd4_getfsstat_args { char buf_l_[PADL_(struct ostatfs *)]; struct ostatfs * buf; char buf_r_[PADR_(struct ostatfs *)]; char bufsize_l_[PADL_(long)]; long bufsize; char bufsize_r_[PADR_(long)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct freebsd4_statfs_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char buf_l_[PADL_(struct ostatfs *)]; struct ostatfs * buf; char buf_r_[PADR_(struct ostatfs *)]; }; struct freebsd4_fstatfs_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char buf_l_[PADL_(struct ostatfs *)]; struct ostatfs * buf; char buf_r_[PADR_(struct ostatfs *)]; }; struct freebsd4_fhstatfs_args { char u_fhp_l_[PADL_(const struct fhandle *)]; const struct fhandle * u_fhp; char u_fhp_r_[PADR_(const struct fhandle *)]; char buf_l_[PADL_(struct ostatfs *)]; struct ostatfs * buf; char buf_r_[PADR_(struct ostatfs *)]; }; struct freebsd4_sendfile_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char offset_l_[PADL_(off_t)]; off_t offset; char offset_r_[PADR_(off_t)]; char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)]; char hdtr_l_[PADL_(struct sf_hdtr *)]; struct sf_hdtr * hdtr; char hdtr_r_[PADR_(struct sf_hdtr *)]; char sbytes_l_[PADL_(off_t *)]; off_t * sbytes; char sbytes_r_[PADR_(off_t *)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct freebsd4_sigaction_args { char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)]; char act_l_[PADL_(const struct sigaction *)]; const struct sigaction * act; char act_r_[PADR_(const struct sigaction *)]; char oact_l_[PADL_(struct sigaction *)]; struct sigaction * oact; char oact_r_[PADR_(struct sigaction *)]; }; struct freebsd4_sigreturn_args { char sigcntxp_l_[PADL_(const struct ucontext4 *)]; const struct ucontext4 * sigcntxp; char sigcntxp_r_[PADR_(const struct ucontext4 *)]; }; int freebsd4_getfsstat(struct thread *, struct freebsd4_getfsstat_args *); int freebsd4_statfs(struct thread *, struct freebsd4_statfs_args *); int freebsd4_fstatfs(struct thread *, struct freebsd4_fstatfs_args *); int freebsd4_fhstatfs(struct thread *, struct freebsd4_fhstatfs_args *); int freebsd4_sendfile(struct thread *, struct freebsd4_sendfile_args *); int freebsd4_sigaction(struct thread *, struct freebsd4_sigaction_args *); int freebsd4_sigreturn(struct thread *, struct freebsd4_sigreturn_args *); #endif /* COMPAT_FREEBSD4 */ #define SYS_AUE_syscall AUE_NULL #define SYS_AUE_exit AUE_EXIT #define SYS_AUE_fork AUE_FORK #define SYS_AUE_read AUE_NULL #define SYS_AUE_write AUE_NULL #define SYS_AUE_open AUE_OPEN_RWTC #define SYS_AUE_close AUE_CLOSE #define SYS_AUE_wait4 AUE_WAIT4 #define SYS_AUE_link AUE_LINK #define SYS_AUE_unlink AUE_UNLINK #define SYS_AUE_chdir AUE_CHDIR #define SYS_AUE_fchdir AUE_FCHDIR #define SYS_AUE_mknod AUE_MKNOD #define SYS_AUE_chmod AUE_CHMOD #define SYS_AUE_chown AUE_CHOWN #define SYS_AUE_break AUE_NULL #define SYS_AUE_getpid AUE_GETPID #define SYS_AUE_mount AUE_MOUNT #define SYS_AUE_unmount AUE_UMOUNT #define SYS_AUE_setuid AUE_SETUID #define SYS_AUE_getuid AUE_GETUID #define SYS_AUE_geteuid AUE_GETEUID #define SYS_AUE_ptrace AUE_PTRACE #define SYS_AUE_recvmsg AUE_RECVMSG #define SYS_AUE_sendmsg AUE_SENDMSG #define SYS_AUE_recvfrom AUE_RECVFROM #define SYS_AUE_accept AUE_ACCEPT #define SYS_AUE_getpeername AUE_GETPEERNAME #define SYS_AUE_getsockname AUE_GETSOCKNAME #define SYS_AUE_access AUE_ACCESS #define SYS_AUE_chflags AUE_CHFLAGS #define SYS_AUE_fchflags AUE_FCHFLAGS #define SYS_AUE_sync AUE_SYNC #define SYS_AUE_kill AUE_KILL #define SYS_AUE_getppid AUE_GETPPID #define SYS_AUE_dup AUE_DUP #define SYS_AUE_pipe AUE_PIPE #define SYS_AUE_getegid AUE_GETEGID #define SYS_AUE_profil AUE_PROFILE #define SYS_AUE_ktrace AUE_KTRACE #define SYS_AUE_getgid AUE_GETGID #define SYS_AUE_getlogin AUE_GETLOGIN #define SYS_AUE_setlogin AUE_SETLOGIN #define SYS_AUE_acct AUE_ACCT #define SYS_AUE_sigaltstack AUE_SIGALTSTACK #define SYS_AUE_ioctl AUE_IOCTL #define SYS_AUE_reboot AUE_REBOOT #define SYS_AUE_revoke AUE_REVOKE #define SYS_AUE_symlink AUE_SYMLINK #define SYS_AUE_readlink AUE_READLINK #define SYS_AUE_execve AUE_EXECVE #define SYS_AUE_umask AUE_UMASK #define SYS_AUE_chroot AUE_CHROOT #define SYS_AUE_msync AUE_MSYNC #define SYS_AUE_vfork AUE_VFORK #define SYS_AUE_sbrk AUE_SBRK #define SYS_AUE_sstk AUE_SSTK #define SYS_AUE_vadvise AUE_O_VADVISE #define SYS_AUE_munmap AUE_MUNMAP #define SYS_AUE_mprotect AUE_MPROTECT #define SYS_AUE_madvise AUE_MADVISE #define SYS_AUE_mincore AUE_MINCORE #define SYS_AUE_getgroups AUE_GETGROUPS #define SYS_AUE_setgroups AUE_SETGROUPS #define SYS_AUE_getpgrp AUE_GETPGRP #define SYS_AUE_setpgid AUE_SETPGRP #define SYS_AUE_setitimer AUE_SETITIMER #define SYS_AUE_swapon AUE_SWAPON #define SYS_AUE_getitimer AUE_GETITIMER #define SYS_AUE_getdtablesize AUE_GETDTABLESIZE #define SYS_AUE_dup2 AUE_DUP2 #define SYS_AUE_fcntl AUE_FCNTL #define SYS_AUE_select AUE_SELECT #define SYS_AUE_fsync AUE_FSYNC #define SYS_AUE_setpriority AUE_SETPRIORITY #define SYS_AUE_socket AUE_SOCKET #define SYS_AUE_connect AUE_CONNECT #define SYS_AUE_getpriority AUE_GETPRIORITY #define SYS_AUE_bind AUE_BIND #define SYS_AUE_setsockopt AUE_SETSOCKOPT #define SYS_AUE_listen AUE_LISTEN #define SYS_AUE_gettimeofday AUE_GETTIMEOFDAY #define SYS_AUE_getrusage AUE_GETRUSAGE #define SYS_AUE_getsockopt AUE_GETSOCKOPT #define SYS_AUE_readv AUE_READV #define SYS_AUE_writev AUE_WRITEV #define SYS_AUE_settimeofday AUE_SETTIMEOFDAY #define SYS_AUE_fchown AUE_FCHOWN #define SYS_AUE_fchmod AUE_FCHMOD #define SYS_AUE_setreuid AUE_SETREUID #define SYS_AUE_setregid AUE_SETREGID #define SYS_AUE_rename AUE_RENAME #define SYS_AUE_flock AUE_FLOCK #define SYS_AUE_mkfifo AUE_MKFIFO #define SYS_AUE_sendto AUE_SENDTO #define SYS_AUE_shutdown AUE_SHUTDOWN #define SYS_AUE_socketpair AUE_SOCKETPAIR #define SYS_AUE_mkdir AUE_MKDIR #define SYS_AUE_rmdir AUE_RMDIR #define SYS_AUE_utimes AUE_UTIMES #define SYS_AUE_adjtime AUE_ADJTIME #define SYS_AUE_setsid AUE_SETSID #define SYS_AUE_quotactl AUE_QUOTACTL #define SYS_AUE_nfssvc AUE_NFS_SVC #define SYS_AUE_lgetfh AUE_LGETFH #define SYS_AUE_getfh AUE_NFS_GETFH #define SYS_AUE_getdomainname AUE_SYSCTL #define SYS_AUE_setdomainname AUE_SYSCTL #define SYS_AUE_uname AUE_NULL #define SYS_AUE_sysarch AUE_SYSARCH #define SYS_AUE_rtprio AUE_RTPRIO #define SYS_AUE_semsys AUE_SEMSYS #define SYS_AUE_msgsys AUE_MSGSYS #define SYS_AUE_shmsys AUE_SHMSYS #define SYS_AUE_pread AUE_PREAD #define SYS_AUE_pwrite AUE_PWRITE #define SYS_AUE_ntp_adjtime AUE_NTP_ADJTIME #define SYS_AUE_setgid AUE_SETGID #define SYS_AUE_setegid AUE_SETEGID #define SYS_AUE_seteuid AUE_SETEUID #define SYS_AUE_stat AUE_STAT #define SYS_AUE_fstat AUE_FSTAT #define SYS_AUE_lstat AUE_LSTAT #define SYS_AUE_pathconf AUE_PATHCONF #define SYS_AUE_fpathconf AUE_FPATHCONF #define SYS_AUE_getrlimit AUE_GETRLIMIT #define SYS_AUE_setrlimit AUE_SETRLIMIT #define SYS_AUE_getdirentries AUE_GETDIRENTRIES #define SYS_AUE_mmap AUE_MMAP #define SYS_AUE_lseek AUE_LSEEK #define SYS_AUE_truncate AUE_TRUNCATE #define SYS_AUE_ftruncate AUE_FTRUNCATE #define SYS_AUE___sysctl AUE_SYSCTL #define SYS_AUE_mlock AUE_MLOCK #define SYS_AUE_munlock AUE_MUNLOCK #define SYS_AUE_undelete AUE_UNDELETE #define SYS_AUE_futimes AUE_FUTIMES #define SYS_AUE_getpgid AUE_GETPGID #define SYS_AUE_poll AUE_POLL #define SYS_AUE_lkmnosys AUE_NULL #define SYS_AUE___semctl AUE_SEMCTL #define SYS_AUE_semget AUE_SEMGET #define SYS_AUE_semop AUE_SEMOP #define SYS_AUE_msgctl AUE_MSGCTL #define SYS_AUE_msgget AUE_MSGGET #define SYS_AUE_msgsnd AUE_MSGSND #define SYS_AUE_msgrcv AUE_MSGRCV #define SYS_AUE_shmat AUE_SHMAT #define SYS_AUE_shmctl AUE_SHMCTL #define SYS_AUE_shmdt AUE_SHMDT #define SYS_AUE_shmget AUE_SHMGET #define SYS_AUE_clock_gettime AUE_NULL #define SYS_AUE_clock_settime AUE_CLOCK_SETTIME #define SYS_AUE_clock_getres AUE_NULL #define SYS_AUE_ktimer_create AUE_NULL #define SYS_AUE_ktimer_delete AUE_NULL #define SYS_AUE_ktimer_settime AUE_NULL #define SYS_AUE_ktimer_gettime AUE_NULL #define SYS_AUE_ktimer_getoverrun AUE_NULL #define SYS_AUE_nanosleep AUE_NULL #define SYS_AUE_ntp_gettime AUE_NULL #define SYS_AUE_minherit AUE_MINHERIT #define SYS_AUE_rfork AUE_RFORK #define SYS_AUE_openbsd_poll AUE_POLL #define SYS_AUE_issetugid AUE_ISSETUGID #define SYS_AUE_lchown AUE_LCHOWN #define SYS_AUE_aio_read AUE_NULL #define SYS_AUE_aio_write AUE_NULL #define SYS_AUE_lio_listio AUE_NULL #define SYS_AUE_getdents AUE_O_GETDENTS #define SYS_AUE_lchmod AUE_LCHMOD #define SYS_AUE_lutimes AUE_LUTIMES #define SYS_AUE_nstat AUE_STAT #define SYS_AUE_nfstat AUE_FSTAT #define SYS_AUE_nlstat AUE_LSTAT #define SYS_AUE_preadv AUE_PREADV #define SYS_AUE_pwritev AUE_PWRITEV #define SYS_AUE_fhopen AUE_FHOPEN #define SYS_AUE_fhstat AUE_FHSTAT #define SYS_AUE_modnext AUE_NULL #define SYS_AUE_modstat AUE_NULL #define SYS_AUE_modfnext AUE_NULL #define SYS_AUE_modfind AUE_NULL #define SYS_AUE_kldload AUE_MODLOAD #define SYS_AUE_kldunload AUE_MODUNLOAD #define SYS_AUE_kldfind AUE_NULL #define SYS_AUE_kldnext AUE_NULL #define SYS_AUE_kldstat AUE_NULL #define SYS_AUE_kldfirstmod AUE_NULL #define SYS_AUE_getsid AUE_GETSID #define SYS_AUE_setresuid AUE_SETRESUID #define SYS_AUE_setresgid AUE_SETRESGID #define SYS_AUE_aio_return AUE_NULL #define SYS_AUE_aio_suspend AUE_NULL #define SYS_AUE_aio_cancel AUE_NULL #define SYS_AUE_aio_error AUE_NULL #define SYS_AUE_oaio_read AUE_NULL #define SYS_AUE_oaio_write AUE_NULL #define SYS_AUE_olio_listio AUE_NULL #define SYS_AUE_yield AUE_NULL #define SYS_AUE_mlockall AUE_MLOCKALL #define SYS_AUE_munlockall AUE_MUNLOCKALL #define SYS_AUE___getcwd AUE_GETCWD #define SYS_AUE_sched_setparam AUE_NULL #define SYS_AUE_sched_getparam AUE_NULL #define SYS_AUE_sched_setscheduler AUE_NULL #define SYS_AUE_sched_getscheduler AUE_NULL #define SYS_AUE_sched_yield AUE_NULL #define SYS_AUE_sched_get_priority_max AUE_NULL #define SYS_AUE_sched_get_priority_min AUE_NULL #define SYS_AUE_sched_rr_get_interval AUE_NULL #define SYS_AUE_utrace AUE_NULL #define SYS_AUE_kldsym AUE_NULL #define SYS_AUE_jail AUE_JAIL #define SYS_AUE_sigprocmask AUE_SIGPROCMASK #define SYS_AUE_sigsuspend AUE_SIGSUSPEND #define SYS_AUE_sigpending AUE_SIGPENDING #define SYS_AUE_sigtimedwait AUE_SIGWAIT #define SYS_AUE_sigwaitinfo AUE_NULL #define SYS_AUE___acl_get_file AUE_NULL #define SYS_AUE___acl_set_file AUE_NULL #define SYS_AUE___acl_get_fd AUE_NULL #define SYS_AUE___acl_set_fd AUE_NULL #define SYS_AUE___acl_delete_file AUE_NULL #define SYS_AUE___acl_delete_fd AUE_NULL #define SYS_AUE___acl_aclcheck_file AUE_NULL #define SYS_AUE___acl_aclcheck_fd AUE_NULL #define SYS_AUE_extattrctl AUE_EXTATTRCTL #define SYS_AUE_extattr_set_file AUE_EXTATTR_SET_FILE #define SYS_AUE_extattr_get_file AUE_EXTATTR_GET_FILE #define SYS_AUE_extattr_delete_file AUE_EXTATTR_DELETE_FILE #define SYS_AUE_aio_waitcomplete AUE_NULL #define SYS_AUE_getresuid AUE_GETRESUID #define SYS_AUE_getresgid AUE_GETRESGID #define SYS_AUE_kqueue AUE_KQUEUE #define SYS_AUE_kevent AUE_NULL #define SYS_AUE_lkmressys AUE_NULL #define SYS_AUE_extattr_set_fd AUE_EXTATTR_SET_FD #define SYS_AUE_extattr_get_fd AUE_EXTATTR_GET_FD #define SYS_AUE_extattr_delete_fd AUE_EXTATTR_DELETE_FD #define SYS_AUE___setugid AUE_NULL #define SYS_AUE_nfsclnt AUE_NULL #define SYS_AUE_eaccess AUE_EACCESS #define SYS_AUE_nmount AUE_NMOUNT #define SYS_AUE_kse_exit AUE_NULL #define SYS_AUE_kse_wakeup AUE_NULL #define SYS_AUE_kse_create AUE_NULL #define SYS_AUE_kse_thr_interrupt AUE_NULL #define SYS_AUE_kse_release AUE_NULL #define SYS_AUE___mac_get_proc AUE_NULL #define SYS_AUE___mac_set_proc AUE_NULL #define SYS_AUE___mac_get_fd AUE_NULL #define SYS_AUE___mac_get_file AUE_NULL #define SYS_AUE___mac_set_fd AUE_NULL #define SYS_AUE___mac_set_file AUE_NULL #define SYS_AUE_kenv AUE_NULL #define SYS_AUE_lchflags AUE_LCHFLAGS #define SYS_AUE_uuidgen AUE_NULL #define SYS_AUE_sendfile AUE_SENDFILE #define SYS_AUE_mac_syscall AUE_NULL #define SYS_AUE_getfsstat AUE_GETFSSTAT #define SYS_AUE_statfs AUE_STATFS #define SYS_AUE_fstatfs AUE_FSTATFS #define SYS_AUE_fhstatfs AUE_FHSTATFS #define SYS_AUE_ksem_close AUE_NULL #define SYS_AUE_ksem_post AUE_NULL #define SYS_AUE_ksem_wait AUE_NULL #define SYS_AUE_ksem_trywait AUE_NULL #define SYS_AUE_ksem_init AUE_NULL #define SYS_AUE_ksem_open AUE_NULL #define SYS_AUE_ksem_unlink AUE_NULL #define SYS_AUE_ksem_getvalue AUE_NULL #define SYS_AUE_ksem_destroy AUE_NULL #define SYS_AUE___mac_get_pid AUE_NULL #define SYS_AUE___mac_get_link AUE_NULL #define SYS_AUE___mac_set_link AUE_NULL #define SYS_AUE_extattr_set_link AUE_EXTATTR_SET_LINK #define SYS_AUE_extattr_get_link AUE_EXTATTR_GET_LINK #define SYS_AUE_extattr_delete_link AUE_EXTATTR_DELETE_LINK #define SYS_AUE___mac_execve AUE_NULL #define SYS_AUE_sigaction AUE_SIGACTION #define SYS_AUE_sigreturn AUE_SIGRETURN #define SYS_AUE_getcontext AUE_NULL #define SYS_AUE_setcontext AUE_NULL #define SYS_AUE_swapcontext AUE_NULL #define SYS_AUE_swapoff AUE_SWAPOFF #define SYS_AUE___acl_get_link AUE_NULL #define SYS_AUE___acl_set_link AUE_NULL #define SYS_AUE___acl_delete_link AUE_NULL #define SYS_AUE___acl_aclcheck_link AUE_NULL #define SYS_AUE_sigwait AUE_SIGWAIT #define SYS_AUE_thr_create AUE_NULL #define SYS_AUE_thr_exit AUE_NULL #define SYS_AUE_thr_self AUE_NULL #define SYS_AUE_thr_kill AUE_NULL #define SYS_AUE__umtx_lock AUE_NULL #define SYS_AUE__umtx_unlock AUE_NULL #define SYS_AUE_jail_attach AUE_NULL #define SYS_AUE_extattr_list_fd AUE_EXTATTR_LIST_FD #define SYS_AUE_extattr_list_file AUE_EXTATTR_LIST_FILE #define SYS_AUE_extattr_list_link AUE_EXTATTR_LIST_LINK #define SYS_AUE_kse_switchin AUE_NULL #define SYS_AUE_ksem_timedwait AUE_NULL #define SYS_AUE_thr_suspend AUE_NULL #define SYS_AUE_thr_wake AUE_NULL #define SYS_AUE_kldunloadf AUE_MODUNLOAD #define SYS_AUE_audit AUE_AUDIT #define SYS_AUE_auditon AUE_AUDITON #define SYS_AUE_getauid AUE_GETAUID #define SYS_AUE_setauid AUE_SETAUID #define SYS_AUE_getaudit AUE_GETAUDIT #define SYS_AUE_setaudit AUE_SETAUDIT #define SYS_AUE_getaudit_addr AUE_GETAUDIT_ADDR #define SYS_AUE_setaudit_addr AUE_SETAUDIT_ADDR #define SYS_AUE_auditctl AUE_AUDITCTL #define SYS_AUE__umtx_op AUE_NULL #define SYS_AUE_thr_new AUE_NULL #define SYS_AUE_sigqueue AUE_NULL #define SYS_AUE_kmq_open AUE_NULL #define SYS_AUE_kmq_setattr AUE_NULL #define SYS_AUE_kmq_timedreceive AUE_NULL #define SYS_AUE_kmq_timedsend AUE_NULL #define SYS_AUE_kmq_notify AUE_NULL #define SYS_AUE_kmq_unlink AUE_NULL #define SYS_AUE_abort2 AUE_NULL #define SYS_AUE_thr_set_name AUE_NULL #define SYS_AUE_aio_fsync AUE_NULL #define SYS_AUE_rtprio_thread AUE_RTPRIO #define SYS_AUE_sctp_peeloff AUE_NULL #define SYS_AUE_sctp_generic_sendmsg AUE_NULL #define SYS_AUE_sctp_generic_sendmsg_iov AUE_NULL #define SYS_AUE_sctp_generic_recvmsg AUE_NULL #undef PAD_ #undef PADL_ #undef PADR_ #endif /* !_SYS_SYSPROTO_H_ */ Index: head/sys/sys/thr.h =================================================================== --- head/sys/sys/thr.h (revision 164183) +++ head/sys/sys/thr.h (revision 164184) @@ -1,73 +1,73 @@ /*- * Copyright (c) 2003, Jeffrey Roberson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ * */ #ifndef _SYS_THR_H_ #define _SYS_THR_H_ -#include +#include /* Create the thread in the suspended state. */ #define THR_SUSPENDED 0x0001 /* Create the system scope thread. */ #define THR_SYSTEM_SCOPE 0x0002 struct thr_param { void (*start_func)(void *); /* thread entry function. */ void *arg; /* argument for entry function. */ char *stack_base; /* stack base address. */ size_t stack_size; /* stack size. */ char *tls_base; /* tls base address. */ size_t tls_size; /* tls size. */ long *child_tid; /* address to store new TID. */ long *parent_tid; /* parent accesses the new TID here. */ int flags; /* thread flags. */ struct rtprio *rtp; /* Real-time scheduling priority */ void *spare[3]; /* TODO: cpu affinity mask etc. */ }; /* * See pthread_* */ #ifndef _KERNEL int thr_create(ucontext_t *ctx, long *id, int flags); int thr_new(struct thr_param *param, int param_size); int thr_self(long *id); void thr_exit(long *state); int thr_kill(long id, int sig); int thr_suspend(const struct timespec *timeout); int thr_wake(long id); int thr_set_name(long id, const char *name); #else struct thread; int kern_thr_new(struct thread *td, struct thr_param *param); int kern_thr_suspend(struct thread *, struct timespec *); #endif /* !_KERNEL */ #endif /* ! _SYS_THR_H_ */