Index: head/lib/libc/stdlib/realpath.c =================================================================== --- head/lib/libc/stdlib/realpath.c (revision 358171) +++ head/lib/libc/stdlib/realpath.c (revision 358172) @@ -1,230 +1,239 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2003 Constantin S. Svintsoff * * 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. * 3. The names of the authors 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 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. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)realpath.c 8.1 (Berkeley) 2/16/94"; #endif /* LIBC_SCCS and not lint */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include #include +#include #include "un-namespace.h" +#include "libc_private.h" +extern int __realpathat(int fd, const char *path, char *buf, size_t size, + int flags); + /* * Find the real name of path, by removing all ".", ".." and symlink * components. Returns (resolved) on success, or (NULL) on failure, * in which case the path which caused trouble is left in (resolved). */ -static char * +static char * __noinline realpath1(const char *path, char *resolved) { struct stat sb; char *p, *q; size_t left_len, resolved_len, next_token_len; unsigned symlinks; ssize_t slen; char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; symlinks = 0; if (path[0] == '/') { resolved[0] = '/'; resolved[1] = '\0'; if (path[1] == '\0') return (resolved); resolved_len = 1; left_len = strlcpy(left, path + 1, sizeof(left)); } else { if (getcwd(resolved, PATH_MAX) == NULL) { resolved[0] = '.'; resolved[1] = '\0'; return (NULL); } resolved_len = strlen(resolved); left_len = strlcpy(left, path, sizeof(left)); } if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { errno = ENAMETOOLONG; return (NULL); } /* * Iterate over path components in `left'. */ while (left_len != 0) { /* * Extract the next path component and adjust `left' * and its length. */ p = strchr(left, '/'); next_token_len = p != NULL ? (size_t)(p - left) : left_len; memcpy(next_token, left, next_token_len); next_token[next_token_len] = '\0'; if (p != NULL) { left_len -= next_token_len + 1; memmove(left, p + 1, left_len + 1); } else { left[0] = '\0'; left_len = 0; } if (resolved[resolved_len - 1] != '/') { if (resolved_len + 1 >= PATH_MAX) { errno = ENAMETOOLONG; return (NULL); } resolved[resolved_len++] = '/'; resolved[resolved_len] = '\0'; } if (next_token[0] == '\0') { /* Handle consequential slashes. */ continue; } else if (strcmp(next_token, ".") == 0) { continue; } else if (strcmp(next_token, "..") == 0) { /* * Strip the last path component except when we have * single "/" */ if (resolved_len > 1) { resolved[resolved_len - 1] = '\0'; q = strrchr(resolved, '/') + 1; *q = '\0'; resolved_len = q - resolved; } continue; } /* * Append the next path component and lstat() it. */ resolved_len = strlcat(resolved, next_token, PATH_MAX); if (resolved_len >= PATH_MAX) { errno = ENAMETOOLONG; return (NULL); } if (lstat(resolved, &sb) != 0) return (NULL); if (S_ISLNK(sb.st_mode)) { if (symlinks++ > MAXSYMLINKS) { errno = ELOOP; return (NULL); } slen = readlink(resolved, symlink, sizeof(symlink)); if (slen <= 0 || slen >= (ssize_t)sizeof(symlink)) { if (slen < 0) ; /* keep errno from readlink(2) call */ else if (slen == 0) errno = ENOENT; else errno = ENAMETOOLONG; return (NULL); } symlink[slen] = '\0'; if (symlink[0] == '/') { resolved[1] = 0; resolved_len = 1; } else { /* Strip the last path component. */ q = strrchr(resolved, '/') + 1; *q = '\0'; resolved_len = q - resolved; } /* * If there are any path components left, then * append them to symlink. The result is placed * in `left'. */ if (p != NULL) { if (symlink[slen - 1] != '/') { if (slen + 1 >= (ssize_t)sizeof(symlink)) { errno = ENAMETOOLONG; return (NULL); } symlink[slen] = '/'; symlink[slen + 1] = 0; } left_len = strlcat(symlink, left, sizeof(symlink)); if (left_len >= sizeof(symlink)) { errno = ENAMETOOLONG; return (NULL); } } left_len = strlcpy(left, symlink, sizeof(left)); } else if (!S_ISDIR(sb.st_mode) && p != NULL) { errno = ENOTDIR; return (NULL); } } /* * Remove trailing slash except when the resolved pathname * is a single "/". */ if (resolved_len > 1 && resolved[resolved_len - 1] == '/') resolved[resolved_len - 1] = '\0'; return (resolved); } char * realpath(const char * __restrict path, char * __restrict resolved) { char *m, *res; if (path == NULL) { errno = EINVAL; return (NULL); } if (path[0] == '\0') { errno = ENOENT; return (NULL); } if (resolved != NULL) { m = NULL; } else { m = resolved = malloc(PATH_MAX); if (resolved == NULL) return (NULL); + } + if (__getosreldate() >= 1300080) { + if (__realpathat(AT_FDCWD, path, resolved, PATH_MAX, 0) == 0) + return (resolved); } res = realpath1(path, resolved); if (res == NULL) free(m); return (res); } Index: head/libexec/rtld-elf/rtld-libc/Makefile.inc =================================================================== --- head/libexec/rtld-elf/rtld-libc/Makefile.inc (revision 358171) +++ head/libexec/rtld-elf/rtld-libc/Makefile.inc (revision 358172) @@ -1,102 +1,102 @@ # $FreeBSD$ # This makefiles adds the necessary libc dependencies for RTLD without pulling # in all of the complex libc bits such as locales, etc. .include LIBC_SRCTOP=${SRCTOP}/lib/libc .if exists(${LIBC_SRCTOP}/${MACHINE_ARCH}) LIBC_ARCH=${MACHINE_ARCH} .else LIBC_ARCH=${MACHINE_CPUARCH} .endif CFLAGS+= -I${SRCTOP}/libexec/rtld-elf/rtld-libc # Build all the libc files that use interposed symbols or pthreads again for # RTLD. We compile with a different libc_private.h and namespace.h that # redirects all calls to interposed functions to use the non-interposed version # instead. .PATH: ${LIBC_SRCTOP}/gen SRCS+= opendir.c closedir.c readdir.c telldir.c # Avoid further dependencies by providing simple implementations of libc # functions such as __error(), etc. .PATH: ${SRCTOP}/libexec/rtld-elf/rtld-libc SRCS+= rtld_libc.c # Now build the remaining files from libc: .PATH: ${LIBC_SRCTOP}/stdlib SRCS+= reallocf.c realpath.c getenv.c merge.c reallocarray.c # TODO: fix merge.c to build with WARNS=6 .if ${COMPILER_TYPE} == "clang" CFLAGS.merge.c+=-Wno-error=null-pointer-arithmetic .endif .PATH: ${LIBC_SRCTOP}/gen SRCS+= errlst.c getcwd.c getprogname.c raise.c sigsetops.c sysctlnametomib.c \ __xuname.c # errlst.c needs the errlst.h header from libc: CFLAGS.errlst.c+=-I${LIBC_SRCTOP}/include # Use the string and memory .o files from libc instead of rebuilding them (they # might be using optimized assembly and duplicating that logic here is awkward). _libc_string_objects= bcmp bcopy bzero memset memchr memcmp memcpy memmove \ stpncpy strcat strchr strcmp stpcpy strcpy strcspn strdup strlcat strlcpy \ strlen strncmp strncpy strrchr strsep strspn strstr strtok # Also use all the syscall .o files from libc_nossp_pic: _libc_other_objects= sigsetjmp lstat stat fstat fstatat fstatfs syscall \ cerror geteuid getegid sigfastblock munmap mprotect \ sysarch __sysctl issetugid __getcwd utrace \ thr_self thr_kill pread mmap lseek _exit _fstat _fstatat _fstatfs \ getdirentries _getdirentries _close _fcntl _open _openat _read \ - _sigprocmask _write readlink _setjmp setjmp setjmperr + _sigprocmask _write readlink __realpathat _setjmp setjmp setjmperr # Finally add additional architecture-dependent libc dependencies .if ${LIBC_ARCH} == "arm" # ARM needs aeabi_unwind_cpp for _setjmp _libc_other_objects+=aeabi_unwind_cpp .elif ${LIBC_ARCH} == "i386" # __udivdi3 is needed by kvprintf() in rtld_printf.c # i386 also needs i386_set_gsbase for allocate_initial_tls() _libc_other_objects+=umoddi3 udivdi3 qdivrem i386_set_gsbase .elif ${LIBC_ARCH} == "powerpc" || ${LIBC_ARCH} == "powerpcspe" # ppc needs __syncicache for reloc.c and __umoddi3+__udivdi3 for rtld_printf.c _libc_other_objects+=syncicache umoddi3 udivdi3 qdivrem # for some reason there is also a reference to abs() _libc_other_objects+=abs .elif ${LIBC_ARCH} == "powerpc64" # ppc64 needs __syncicache for reloc.c _libc_other_objects+=syncicache .elif ${LIBC_ARCH} == "mips" # 32-bit MIPS needs __umoddi3+__udivdi3 for rtld_printf.c .if ${MACHINE_ARCH:Mmipsn32*} == "" && ${MACHINE_ARCH:Mmips64*} == "" _libc_other_objects+=umoddi3 udivdi3 qdivrem .endif .elif ${LIBC_ARCH} == "sparc64" # reloc.c uses __sparc_utrap which needs a lot of other object files _libc_other_objects+=__sparc_utrap __sparc_utrap_fp_disabled __sparc_utrap_gen \ __sparc_utrap_setup __sparc_utrap_align __sparc_utrap_emul kill getpid \ fpu fpu_explode fpu_div fpu_reg fpu_sqrt fpu_implode fpu_subr fpu_add \ fpu_compare fpu_mul .endif # Extract all the .o files from libc_nossp_pic.a. This ensures that # we don't accidentally pull in the interposing table or similar by linking # directly against libc_nossp_pic.a _rtld_libc_objs= .for _obj in ${_libc_other_objects} ${_libc_string_objects} _rtld_libc_objs+=${_obj}.nossppico CLEANFILES+=${_obj}.nossppico # LDFLAGS+= -Wl,--trace-symbol=${_obj} .endfor # LDFLAGS+= -Wl,--trace # We insert all the .o files from libc_nossp_pic.a into a new rtld_libc.a file # to ensure that only .o files that are actually used end up being included. rtld_libc.a: ${LIBC_NOSSP_PIC} ${SRCTOP}/libexec/rtld-elf/rtld-libc/Makefile.inc ${AR} x ${LIBC_NOSSP_PIC} ${_rtld_libc_objs} ${AR} cr ${.OBJDIR}/${.TARGET} ${_rtld_libc_objs} CLEANFILES+=rtld_libc.a LDADD+=${.OBJDIR}/rtld_libc.a beforelinking: rtld_libc.a Index: head/sys/bsm/audit_kevents.h =================================================================== --- head/sys/bsm/audit_kevents.h (revision 358171) +++ head/sys/bsm/audit_kevents.h (revision 358172) @@ -1,846 +1,847 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2005-2009 Apple Inc. * 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. * 3. Neither the name of Apple Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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$ */ #ifndef _BSM_AUDIT_KEVENTS_H_ #define _BSM_AUDIT_KEVENTS_H_ /* * The reserved event numbers for kernel events are 1...2047 and 43001..44999. */ #define AUE_IS_A_KEVENT(e) (((e) > 0 && (e) < 2048) || \ ((e) > 43000 && (e) < 45000)) /* * Values marked as AUE_NULL are not required to be audited as per CAPP. * * Some conflicts exist in the assignment of name to event number mappings * between BSM implementations. In general, we prefer the OpenSolaris * definition as we consider Solaris BSM to be authoritative. _DARWIN_ has * been inserted for the Darwin variants. If necessary, other tags will be * added in the future. */ #define AUE_NULL 0 #define AUE_EXIT 1 #define AUE_FORK 2 #define AUE_FORKALL AUE_FORK /* Solaris-specific. */ #define AUE_OPEN 3 #define AUE_CREAT 4 #define AUE_LINK 5 #define AUE_UNLINK 6 #define AUE_DELETE AUE_UNLINK /* Darwin-specific. */ #define AUE_EXEC 7 #define AUE_CHDIR 8 #define AUE_MKNOD 9 #define AUE_CHMOD 10 #define AUE_CHOWN 11 #define AUE_UMOUNT 12 #define AUE_JUNK 13 /* Solaris-specific. */ #define AUE_ACCESS 14 #define AUE_KILL 15 #define AUE_STAT 16 #define AUE_LSTAT 17 #define AUE_ACCT 18 #define AUE_MCTL 19 /* Solaris-specific. */ #define AUE_REBOOT 20 /* XXX: Darwin conflict. */ #define AUE_SYMLINK 21 #define AUE_READLINK 22 #define AUE_EXECVE 23 #define AUE_CHROOT 24 #define AUE_VFORK 25 #define AUE_SETGROUPS 26 #define AUE_SETPGRP 27 #define AUE_SWAPON 28 #define AUE_SETHOSTNAME 29 /* XXX: Darwin conflict. */ #define AUE_FCNTL 30 #define AUE_SETPRIORITY 31 /* XXX: Darwin conflict. */ #define AUE_CONNECT 32 #define AUE_ACCEPT 33 #define AUE_BIND 34 #define AUE_SETSOCKOPT 35 #define AUE_VTRACE 36 /* Solaris-specific. */ #define AUE_SETTIMEOFDAY 37 /* XXX: Darwin conflict. */ #define AUE_FCHOWN 38 #define AUE_FCHMOD 39 #define AUE_SETREUID 40 #define AUE_SETREGID 41 #define AUE_RENAME 42 #define AUE_TRUNCATE 43 /* XXX: Darwin conflict. */ #define AUE_FTRUNCATE 44 /* XXX: Darwin conflict. */ #define AUE_FLOCK 45 /* XXX: Darwin conflict. */ #define AUE_SHUTDOWN 46 #define AUE_MKDIR 47 #define AUE_RMDIR 48 #define AUE_UTIMES 49 #define AUE_ADJTIME 50 #define AUE_SETRLIMIT 51 #define AUE_KILLPG 52 #define AUE_NFS_SVC 53 /* XXX: Darwin conflict. */ #define AUE_STATFS 54 #define AUE_FSTATFS 55 #define AUE_UNMOUNT 56 /* XXX: Darwin conflict. */ #define AUE_ASYNC_DAEMON 57 #define AUE_NFS_GETFH 58 /* XXX: Darwin conflict. */ #define AUE_SETDOMAINNAME 59 #define AUE_QUOTACTL 60 /* XXX: Darwin conflict. */ #define AUE_EXPORTFS 61 #define AUE_MOUNT 62 #define AUE_SEMSYS 63 #define AUE_MSGSYS 64 #define AUE_SHMSYS 65 #define AUE_BSMSYS 66 /* Solaris-specific. */ #define AUE_RFSSYS 67 /* Solaris-specific. */ #define AUE_FCHDIR 68 #define AUE_FCHROOT 69 #define AUE_VPIXSYS 70 /* Solaris-specific. */ #define AUE_PATHCONF 71 #define AUE_OPEN_R 72 #define AUE_OPEN_RC 73 #define AUE_OPEN_RT 74 #define AUE_OPEN_RTC 75 #define AUE_OPEN_W 76 #define AUE_OPEN_WC 77 #define AUE_OPEN_WT 78 #define AUE_OPEN_WTC 79 #define AUE_OPEN_RW 80 #define AUE_OPEN_RWC 81 #define AUE_OPEN_RWT 82 #define AUE_OPEN_RWTC 83 #define AUE_MSGCTL 84 #define AUE_MSGCTL_RMID 85 #define AUE_MSGCTL_SET 86 #define AUE_MSGCTL_STAT 87 #define AUE_MSGGET 88 #define AUE_MSGRCV 89 #define AUE_MSGSND 90 #define AUE_SHMCTL 91 #define AUE_SHMCTL_RMID 92 #define AUE_SHMCTL_SET 93 #define AUE_SHMCTL_STAT 94 #define AUE_SHMGET 95 #define AUE_SHMAT 96 #define AUE_SHMDT 97 #define AUE_SEMCTL 98 #define AUE_SEMCTL_RMID 99 #define AUE_SEMCTL_SET 100 #define AUE_SEMCTL_STAT 101 #define AUE_SEMCTL_GETNCNT 102 #define AUE_SEMCTL_GETPID 103 #define AUE_SEMCTL_GETVAL 104 #define AUE_SEMCTL_GETALL 105 #define AUE_SEMCTL_GETZCNT 106 #define AUE_SEMCTL_SETVAL 107 #define AUE_SEMCTL_SETALL 108 #define AUE_SEMGET 109 #define AUE_SEMOP 110 #define AUE_CORE 111 /* Solaris-specific, currently. */ #define AUE_CLOSE 112 #define AUE_SYSTEMBOOT 113 /* Solaris-specific. */ #define AUE_ASYNC_DAEMON_EXIT 114 /* Solaris-specific. */ #define AUE_NFSSVC_EXIT 115 /* Solaris-specific. */ #define AUE_WRITEL 128 /* Solaris-specific. */ #define AUE_WRITEVL 129 /* Solaris-specific. */ #define AUE_GETAUID 130 #define AUE_SETAUID 131 #define AUE_GETAUDIT 132 #define AUE_SETAUDIT 133 #define AUE_GETUSERAUDIT 134 /* Solaris-specific. */ #define AUE_SETUSERAUDIT 135 /* Solaris-specific. */ #define AUE_AUDITSVC 136 /* Solaris-specific. */ #define AUE_AUDITUSER 137 /* Solaris-specific. */ #define AUE_AUDITON 138 #define AUE_AUDITON_GTERMID 139 /* Solaris-specific. */ #define AUE_AUDITON_STERMID 140 /* Solaris-specific. */ #define AUE_AUDITON_GPOLICY 141 #define AUE_AUDITON_SPOLICY 142 #define AUE_AUDITON_GQCTRL 145 #define AUE_AUDITON_SQCTRL 146 #define AUE_GETKERNSTATE 147 /* Solaris-specific. */ #define AUE_SETKERNSTATE 148 /* Solaris-specific. */ #define AUE_GETPORTAUDIT 149 /* Solaris-specific. */ #define AUE_AUDITSTAT 150 /* Solaris-specific. */ #define AUE_REVOKE 151 #define AUE_MAC 152 /* Solaris-specific. */ #define AUE_ENTERPROM 153 /* Solaris-specific. */ #define AUE_EXITPROM 154 /* Solaris-specific. */ #define AUE_IFLOAT 155 /* Solaris-specific. */ #define AUE_PFLOAT 156 /* Solaris-specific. */ #define AUE_UPRIV 157 /* Solaris-specific. */ #define AUE_IOCTL 158 #define AUE_SOCKET 183 #define AUE_SENDTO 184 #define AUE_PIPE 185 #define AUE_SOCKETPAIR 186 /* XXX: Darwin conflict. */ #define AUE_SEND 187 #define AUE_SENDMSG 188 #define AUE_RECV 189 #define AUE_RECVMSG 190 #define AUE_RECVFROM 191 #define AUE_READ 192 #define AUE_GETDENTS 193 #define AUE_LSEEK 194 #define AUE_WRITE 195 #define AUE_WRITEV 196 #define AUE_NFS 197 /* Solaris-specific. */ #define AUE_READV 198 #define AUE_OSTAT 199 /* Solaris-specific. */ #define AUE_SETUID 200 /* XXXRW: Solaris old setuid? */ #define AUE_STIME 201 /* XXXRW: Solaris old stime? */ #define AUE_UTIME 202 /* XXXRW: Solaris old utime? */ #define AUE_NICE 203 /* XXXRW: Solaris old nice? */ #define AUE_OSETPGRP 204 /* Solaris-specific. */ #define AUE_SETGID 205 #define AUE_READL 206 /* Solaris-specific. */ #define AUE_READVL 207 /* Solaris-specific. */ #define AUE_FSTAT 208 #define AUE_DUP2 209 #define AUE_MMAP 210 #define AUE_AUDIT 211 #define AUE_PRIOCNTLSYS 212 /* Solaris-specific. */ #define AUE_MUNMAP 213 #define AUE_SETEGID 214 #define AUE_SETEUID 215 #define AUE_PUTMSG 216 /* Solaris-specific. */ #define AUE_GETMSG 217 /* Solaris-specific. */ #define AUE_PUTPMSG 218 /* Solaris-specific. */ #define AUE_GETPMSG 219 /* Solaris-specific. */ #define AUE_AUDITSYS 220 /* Solaris-specific. */ #define AUE_AUDITON_GETKMASK 221 #define AUE_AUDITON_SETKMASK 222 #define AUE_AUDITON_GETCWD 223 #define AUE_AUDITON_GETCAR 224 #define AUE_AUDITON_GETSTAT 225 #define AUE_AUDITON_SETSTAT 226 #define AUE_AUDITON_SETUMASK 227 #define AUE_AUDITON_SETSMASK 228 #define AUE_AUDITON_GETCOND 229 #define AUE_AUDITON_SETCOND 230 #define AUE_AUDITON_GETCLASS 231 #define AUE_AUDITON_SETCLASS 232 #define AUE_FUSERS 233 /* Solaris-specific; also UTSSYS? */ #define AUE_STATVFS 234 #define AUE_XSTAT 235 /* Solaris-specific. */ #define AUE_LXSTAT 236 /* Solaris-specific. */ #define AUE_LCHOWN 237 #define AUE_MEMCNTL 238 /* Solaris-specific. */ #define AUE_SYSINFO 239 /* Solaris-specific. */ #define AUE_XMKNOD 240 /* Solaris-specific. */ #define AUE_FORK1 241 #define AUE_MODCTL 242 /* Solaris-specific. */ #define AUE_MODLOAD 243 #define AUE_MODUNLOAD 244 #define AUE_MODCONFIG 245 /* Solaris-specific. */ #define AUE_MODADDMAJ 246 /* Solaris-specific. */ #define AUE_SOCKACCEPT 247 /* Solaris-specific. */ #define AUE_SOCKCONNECT 248 /* Solaris-specific. */ #define AUE_SOCKSEND 249 /* Solaris-specific. */ #define AUE_SOCKRECEIVE 250 /* Solaris-specific. */ #define AUE_ACLSET 251 #define AUE_FACLSET 252 #define AUE_DOORFS 253 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_CALL 254 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_RETURN 255 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_CREATE 256 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_REVOKE 257 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_INFO 258 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_CRED 259 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_BIND 260 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_UNBIND 261 /* Solaris-specific. */ #define AUE_P_ONLINE 262 /* Solaris-specific. */ #define AUE_PROCESSOR_BIND 263 /* Solaris-specific. */ #define AUE_INST_SYNC 264 /* Solaris-specific. */ #define AUE_SOCKCONFIG 265 /* Solaris-specific. */ #define AUE_SETAUDIT_ADDR 266 #define AUE_GETAUDIT_ADDR 267 #define AUE_UMOUNT2 268 /* Solaris-specific. */ #define AUE_FSAT 269 /* Solaris-specific. */ #define AUE_OPENAT_R 270 #define AUE_OPENAT_RC 271 #define AUE_OPENAT_RT 272 #define AUE_OPENAT_RTC 273 #define AUE_OPENAT_W 274 #define AUE_OPENAT_WC 275 #define AUE_OPENAT_WT 276 #define AUE_OPENAT_WTC 277 #define AUE_OPENAT_RW 278 #define AUE_OPENAT_RWC 279 #define AUE_OPENAT_RWT 280 #define AUE_OPENAT_RWTC 281 #define AUE_RENAMEAT 282 #define AUE_FSTATAT 283 #define AUE_FCHOWNAT 284 #define AUE_FUTIMESAT 285 #define AUE_UNLINKAT 286 #define AUE_CLOCK_SETTIME 287 #define AUE_NTP_ADJTIME 288 #define AUE_SETPPRIV 289 /* Solaris-specific. */ #define AUE_MODDEVPLCY 290 /* Solaris-specific. */ #define AUE_MODADDPRIV 291 /* Solaris-specific. */ #define AUE_CRYPTOADM 292 /* Solaris-specific. */ #define AUE_CONFIGKSSL 293 /* Solaris-specific. */ #define AUE_BRANDSYS 294 /* Solaris-specific. */ #define AUE_PF_POLICY_ADDRULE 295 /* Solaris-specific. */ #define AUE_PF_POLICY_DELRULE 296 /* Solaris-specific. */ #define AUE_PF_POLICY_CLONE 297 /* Solaris-specific. */ #define AUE_PF_POLICY_FLIP 298 /* Solaris-specific. */ #define AUE_PF_POLICY_FLUSH 299 /* Solaris-specific. */ #define AUE_PF_POLICY_ALGS 300 /* Solaris-specific. */ #define AUE_PORTFS 301 /* Solaris-specific. */ /* * Events added for Apple Darwin that potentially collide with future Solaris * BSM events. These are assigned AUE_DARWIN prefixes, and are deprecated in * new trails. Systems generating these events should switch to the new * identifiers that avoid colliding with the Solaris identifier space. */ #define AUE_DARWIN_GETFSSTAT 301 #define AUE_DARWIN_PTRACE 302 #define AUE_DARWIN_CHFLAGS 303 #define AUE_DARWIN_FCHFLAGS 304 #define AUE_DARWIN_PROFILE 305 #define AUE_DARWIN_KTRACE 306 #define AUE_DARWIN_SETLOGIN 307 #define AUE_DARWIN_REBOOT 308 #define AUE_DARWIN_REVOKE 309 #define AUE_DARWIN_UMASK 310 #define AUE_DARWIN_MPROTECT 311 #define AUE_DARWIN_SETPRIORITY 312 #define AUE_DARWIN_SETTIMEOFDAY 313 #define AUE_DARWIN_FLOCK 314 #define AUE_DARWIN_MKFIFO 315 #define AUE_DARWIN_POLL 316 #define AUE_DARWIN_SOCKETPAIR 317 #define AUE_DARWIN_FUTIMES 318 #define AUE_DARWIN_SETSID 319 #define AUE_DARWIN_SETPRIVEXEC 320 /* Darwin-specific. */ #define AUE_DARWIN_NFSSVC 321 #define AUE_DARWIN_GETFH 322 #define AUE_DARWIN_QUOTACTL 323 #define AUE_DARWIN_ADDPROFILE 324 /* Darwin-specific. */ #define AUE_DARWIN_KDEBUGTRACE 325 /* Darwin-specific. */ #define AUE_DARWIN_KDBUGTRACE AUE_KDEBUGTRACE #define AUE_DARWIN_FSTAT 326 #define AUE_DARWIN_FPATHCONF 327 #define AUE_DARWIN_GETDIRENTRIES 328 #define AUE_DARWIN_TRUNCATE 329 #define AUE_DARWIN_FTRUNCATE 330 #define AUE_DARWIN_SYSCTL 331 #define AUE_DARWIN_MLOCK 332 #define AUE_DARWIN_MUNLOCK 333 #define AUE_DARWIN_UNDELETE 334 #define AUE_DARWIN_GETATTRLIST 335 /* Darwin-specific. */ #define AUE_DARWIN_SETATTRLIST 336 /* Darwin-specific. */ #define AUE_DARWIN_GETDIRENTRIESATTR 337 /* Darwin-specific. */ #define AUE_DARWIN_EXCHANGEDATA 338 /* Darwin-specific. */ #define AUE_DARWIN_SEARCHFS 339 /* Darwin-specific. */ #define AUE_DARWIN_MINHERIT 340 #define AUE_DARWIN_SEMCONFIG 341 #define AUE_DARWIN_SEMOPEN 342 #define AUE_DARWIN_SEMCLOSE 343 #define AUE_DARWIN_SEMUNLINK 344 #define AUE_DARWIN_SHMOPEN 345 #define AUE_DARWIN_SHMUNLINK 346 #define AUE_DARWIN_LOADSHFILE 347 /* Darwin-specific. */ #define AUE_DARWIN_RESETSHFILE 348 /* Darwin-specific. */ #define AUE_DARWIN_NEWSYSTEMSHREG 349 /* Darwin-specific. */ #define AUE_DARWIN_PTHREADKILL 350 /* Darwin-specific. */ #define AUE_DARWIN_PTHREADSIGMASK 351 /* Darwin-specific. */ #define AUE_DARWIN_AUDITCTL 352 #define AUE_DARWIN_RFORK 353 #define AUE_DARWIN_LCHMOD 354 #define AUE_DARWIN_SWAPOFF 355 #define AUE_DARWIN_INITPROCESS 356 /* Darwin-specific. */ #define AUE_DARWIN_MAPFD 357 /* Darwin-specific. */ #define AUE_DARWIN_TASKFORPID 358 /* Darwin-specific. */ #define AUE_DARWIN_PIDFORTASK 359 /* Darwin-specific. */ #define AUE_DARWIN_SYSCTL_NONADMIN 360 #define AUE_DARWIN_COPYFILE 361 /* Darwin-specific. */ /* * Audit event identifiers added as part of OpenBSM, generally corresponding * to events in FreeBSD, Darwin, and Linux that were not present in Solaris. * These often duplicate events added to the Solaris set by Darwin, but use * event identifiers in a higher range in order to avoid colliding with * future Solaris additions. * * If an event in this section is later added to Solaris, we prefer the * Solaris event identifier, and add _OPENBSM_ to the OpenBSM-specific * identifier so that old trails can still be processed, but new trails use * the Solaris identifier. */ #define AUE_GETFSSTAT 43001 #define AUE_PTRACE 43002 #define AUE_CHFLAGS 43003 #define AUE_FCHFLAGS 43004 #define AUE_PROFILE 43005 #define AUE_KTRACE 43006 #define AUE_SETLOGIN 43007 #define AUE_OPENBSM_REVOKE 43008 /* Solaris event now preferred. */ #define AUE_UMASK 43009 #define AUE_MPROTECT 43010 #define AUE_MKFIFO 43011 #define AUE_POLL 43012 #define AUE_FUTIMES 43013 #define AUE_SETSID 43014 #define AUE_SETPRIVEXEC 43015 /* Darwin-specific. */ #define AUE_ADDPROFILE 43016 /* Darwin-specific. */ #define AUE_KDEBUGTRACE 43017 /* Darwin-specific. */ #define AUE_KDBUGTRACE AUE_KDEBUGTRACE #define AUE_OPENBSM_FSTAT 43018 /* Solaris event now preferred. */ #define AUE_FPATHCONF 43019 #define AUE_GETDIRENTRIES 43020 #define AUE_SYSCTL 43021 #define AUE_MLOCK 43022 #define AUE_MUNLOCK 43023 #define AUE_UNDELETE 43024 #define AUE_GETATTRLIST 43025 /* Darwin-specific. */ #define AUE_SETATTRLIST 43026 /* Darwin-specific. */ #define AUE_GETDIRENTRIESATTR 43027 /* Darwin-specific. */ #define AUE_EXCHANGEDATA 43028 /* Darwin-specific. */ #define AUE_SEARCHFS 43029 /* Darwin-specific. */ #define AUE_MINHERIT 43030 #define AUE_SEMCONFIG 43031 #define AUE_SEMOPEN 43032 #define AUE_SEMCLOSE 43033 #define AUE_SEMUNLINK 43034 #define AUE_SHMOPEN 43035 #define AUE_SHMUNLINK 43036 #define AUE_LOADSHFILE 43037 /* Darwin-specific. */ #define AUE_RESETSHFILE 43038 /* Darwin-specific. */ #define AUE_NEWSYSTEMSHREG 43039 /* Darwin-specific. */ #define AUE_PTHREADKILL 43040 /* Darwin-specific. */ #define AUE_PTHREADSIGMASK 43041 /* Darwin-specific. */ #define AUE_AUDITCTL 43042 #define AUE_RFORK 43043 #define AUE_LCHMOD 43044 #define AUE_SWAPOFF 43045 #define AUE_INITPROCESS 43046 /* Darwin-specific. */ #define AUE_MAPFD 43047 /* Darwin-specific. */ #define AUE_TASKFORPID 43048 /* Darwin-specific. */ #define AUE_PIDFORTASK 43049 /* Darwin-specific. */ #define AUE_SYSCTL_NONADMIN 43050 #define AUE_COPYFILE 43051 /* Darwin-specific. */ /* * Events added to OpenBSM for FreeBSD and Linux; may also be used by Darwin * in the future. */ #define AUE_LUTIMES 43052 #define AUE_LCHFLAGS 43053 /* FreeBSD-specific. */ #define AUE_SENDFILE 43054 /* BSD/Linux-specific. */ #define AUE_USELIB 43055 /* Linux-specific. */ #define AUE_GETRESUID 43056 #define AUE_SETRESUID 43057 #define AUE_GETRESGID 43058 #define AUE_SETRESGID 43059 #define AUE_WAIT4 43060 /* FreeBSD-specific. */ #define AUE_LGETFH 43061 /* FreeBSD-specific. */ #define AUE_FHSTATFS 43062 /* FreeBSD-specific. */ #define AUE_FHOPEN 43063 /* FreeBSD-specific. */ #define AUE_FHSTAT 43064 /* FreeBSD-specific. */ #define AUE_JAIL 43065 /* FreeBSD-specific. */ #define AUE_EACCESS 43066 /* FreeBSD-specific. */ #define AUE_KQUEUE 43067 /* FreeBSD-specific. */ #define AUE_KEVENT 43068 /* FreeBSD-specific. */ #define AUE_FSYNC 43069 #define AUE_NMOUNT 43070 /* FreeBSD-specific. */ #define AUE_BDFLUSH 43071 /* Linux-specific. */ #define AUE_SETFSUID 43072 /* Linux-specific. */ #define AUE_SETFSGID 43073 /* Linux-specific. */ #define AUE_PERSONALITY 43074 /* Linux-specific. */ #define AUE_SCHED_GETSCHEDULER 43075 /* POSIX.1b. */ #define AUE_SCHED_SETSCHEDULER 43076 /* POSIX.1b. */ #define AUE_PRCTL 43077 /* Linux-specific. */ #define AUE_GETCWD 43078 /* FreeBSD/Linux-specific. */ #define AUE_CAPGET 43079 /* Linux-specific. */ #define AUE_CAPSET 43080 /* Linux-specific. */ #define AUE_PIVOT_ROOT 43081 /* Linux-specific. */ #define AUE_RTPRIO 43082 /* FreeBSD-specific. */ #define AUE_SCHED_GETPARAM 43083 /* POSIX.1b. */ #define AUE_SCHED_SETPARAM 43084 /* POSIX.1b. */ #define AUE_SCHED_GET_PRIORITY_MAX 43085 /* POSIX.1b. */ #define AUE_SCHED_GET_PRIORITY_MIN 43086 /* POSIX.1b. */ #define AUE_SCHED_RR_GET_INTERVAL 43087 /* POSIX.1b. */ #define AUE_ACL_GET_FILE 43088 /* FreeBSD. */ #define AUE_ACL_SET_FILE 43089 /* FreeBSD. */ #define AUE_ACL_GET_FD 43090 /* FreeBSD. */ #define AUE_ACL_SET_FD 43091 /* FreeBSD. */ #define AUE_ACL_DELETE_FILE 43092 /* FreeBSD. */ #define AUE_ACL_DELETE_FD 43093 /* FreeBSD. */ #define AUE_ACL_CHECK_FILE 43094 /* FreeBSD. */ #define AUE_ACL_CHECK_FD 43095 /* FreeBSD. */ #define AUE_ACL_GET_LINK 43096 /* FreeBSD. */ #define AUE_ACL_SET_LINK 43097 /* FreeBSD. */ #define AUE_ACL_DELETE_LINK 43098 /* FreeBSD. */ #define AUE_ACL_CHECK_LINK 43099 /* FreeBSD. */ #define AUE_SYSARCH 43100 /* FreeBSD. */ #define AUE_EXTATTRCTL 43101 /* FreeBSD. */ #define AUE_EXTATTR_GET_FILE 43102 /* FreeBSD. */ #define AUE_EXTATTR_SET_FILE 43103 /* FreeBSD. */ #define AUE_EXTATTR_LIST_FILE 43104 /* FreeBSD. */ #define AUE_EXTATTR_DELETE_FILE 43105 /* FreeBSD. */ #define AUE_EXTATTR_GET_FD 43106 /* FreeBSD. */ #define AUE_EXTATTR_SET_FD 43107 /* FreeBSD. */ #define AUE_EXTATTR_LIST_FD 43108 /* FreeBSD. */ #define AUE_EXTATTR_DELETE_FD 43109 /* FreeBSD. */ #define AUE_EXTATTR_GET_LINK 43110 /* FreeBSD. */ #define AUE_EXTATTR_SET_LINK 43111 /* FreeBSD. */ #define AUE_EXTATTR_LIST_LINK 43112 /* FreeBSD. */ #define AUE_EXTATTR_DELETE_LINK 43113 /* FreeBSD. */ #define AUE_KENV 43114 /* FreeBSD. */ #define AUE_JAIL_ATTACH 43115 /* FreeBSD. */ #define AUE_SYSCTL_WRITE 43116 /* FreeBSD. */ #define AUE_IOPERM 43117 /* Linux. */ #define AUE_READDIR 43118 /* Linux. */ #define AUE_IOPL 43119 /* Linux. */ #define AUE_VM86 43120 /* Linux. */ #define AUE_MAC_GET_PROC 43121 /* FreeBSD/Darwin. */ #define AUE_MAC_SET_PROC 43122 /* FreeBSD/Darwin. */ #define AUE_MAC_GET_FD 43123 /* FreeBSD/Darwin. */ #define AUE_MAC_GET_FILE 43124 /* FreeBSD/Darwin. */ #define AUE_MAC_SET_FD 43125 /* FreeBSD/Darwin. */ #define AUE_MAC_SET_FILE 43126 /* FreeBSD/Darwin. */ #define AUE_MAC_SYSCALL 43127 /* FreeBSD. */ #define AUE_MAC_GET_PID 43128 /* FreeBSD/Darwin. */ #define AUE_MAC_GET_LINK 43129 /* FreeBSD/Darwin. */ #define AUE_MAC_SET_LINK 43130 /* FreeBSD/Darwin. */ #define AUE_MAC_EXECVE 43131 /* FreeBSD/Darwin. */ #define AUE_GETPATH_FROMFD 43132 /* FreeBSD. */ #define AUE_GETPATH_FROMADDR 43133 /* FreeBSD. */ #define AUE_MQ_OPEN 43134 /* FreeBSD. */ #define AUE_MQ_SETATTR 43135 /* FreeBSD. */ #define AUE_MQ_TIMEDRECEIVE 43136 /* FreeBSD. */ #define AUE_MQ_TIMEDSEND 43137 /* FreeBSD. */ #define AUE_MQ_NOTIFY 43138 /* FreeBSD. */ #define AUE_MQ_UNLINK 43139 /* FreeBSD. */ #define AUE_LISTEN 43140 /* FreeBSD/Darwin/Linux. */ #define AUE_MLOCKALL 43141 /* FreeBSD. */ #define AUE_MUNLOCKALL 43142 /* FreeBSD. */ #define AUE_CLOSEFROM 43143 /* FreeBSD. */ #define AUE_FEXECVE 43144 /* FreeBSD. */ #define AUE_FACCESSAT 43145 /* FreeBSD. */ #define AUE_FCHMODAT 43146 /* FreeBSD. */ #define AUE_LINKAT 43147 /* FreeBSD. */ #define AUE_MKDIRAT 43148 /* FreeBSD. */ #define AUE_MKFIFOAT 43149 /* FreeBSD. */ #define AUE_MKNODAT 43150 /* FreeBSD. */ #define AUE_READLINKAT 43151 /* FreeBSD. */ #define AUE_SYMLINKAT 43152 /* FreeBSD. */ #define AUE_MAC_GETFSSTAT 43153 /* Darwin. */ #define AUE_MAC_GET_MOUNT 43154 /* Darwin. */ #define AUE_MAC_GET_LCID 43155 /* Darwin. */ #define AUE_MAC_GET_LCTX 43156 /* Darwin. */ #define AUE_MAC_SET_LCTX 43157 /* Darwin. */ #define AUE_MAC_MOUNT 43158 /* Darwin. */ #define AUE_GETLCID 43159 /* Darwin. */ #define AUE_SETLCID 43160 /* Darwin. */ #define AUE_TASKNAMEFORPID 43161 /* Darwin. */ #define AUE_ACCESS_EXTENDED 43162 /* Darwin. */ #define AUE_CHMOD_EXTENDED 43163 /* Darwin. */ #define AUE_FCHMOD_EXTENDED 43164 /* Darwin. */ #define AUE_FSTAT_EXTENDED 43165 /* Darwin. */ #define AUE_LSTAT_EXTENDED 43166 /* Darwin. */ #define AUE_MKDIR_EXTENDED 43167 /* Darwin. */ #define AUE_MKFIFO_EXTENDED 43168 /* Darwin. */ #define AUE_OPEN_EXTENDED 43169 /* Darwin. */ #define AUE_OPEN_EXTENDED_R 43170 /* Darwin. */ #define AUE_OPEN_EXTENDED_RC 43171 /* Darwin. */ #define AUE_OPEN_EXTENDED_RT 43172 /* Darwin. */ #define AUE_OPEN_EXTENDED_RTC 43173 /* Darwin. */ #define AUE_OPEN_EXTENDED_W 43174 /* Darwin. */ #define AUE_OPEN_EXTENDED_WC 43175 /* Darwin. */ #define AUE_OPEN_EXTENDED_WT 43176 /* Darwin. */ #define AUE_OPEN_EXTENDED_WTC 43177 /* Darwin. */ #define AUE_OPEN_EXTENDED_RW 43178 /* Darwin. */ #define AUE_OPEN_EXTENDED_RWC 43179 /* Darwin. */ #define AUE_OPEN_EXTENDED_RWT 43180 /* Darwin. */ #define AUE_OPEN_EXTENDED_RWTC 43181 /* Darwin. */ #define AUE_STAT_EXTENDED 43182 /* Darwin. */ #define AUE_UMASK_EXTENDED 43183 /* Darwin. */ #define AUE_OPENAT 43184 /* FreeBSD. */ #define AUE_POSIX_OPENPT 43185 /* FreeBSD. */ #define AUE_CAP_NEW 43186 /* TrustedBSD. */ #define AUE_CAP_RIGHTS_GET 43187 /* TrustedBSD. */ #define AUE_CAP_GETRIGHTS AUE_CAP_RIGHTS_GET #define AUE_CAP_ENTER 43188 /* TrustedBSD. */ #define AUE_CAP_GETMODE 43189 /* TrustedBSD. */ #define AUE_POSIX_SPAWN 43190 /* Darwin. */ #define AUE_FSGETPATH 43191 /* Darwin. */ #define AUE_PREAD 43192 /* Darwin/FreeBSD. */ #define AUE_PWRITE 43193 /* Darwin/FreeBSD. */ #define AUE_FSCTL 43194 /* Darwin. */ #define AUE_FFSCTL 43195 /* Darwin. */ #define AUE_LPATHCONF 43196 /* FreeBSD. */ #define AUE_PDFORK 43197 /* FreeBSD. */ #define AUE_PDKILL 43198 /* FreeBSD. */ #define AUE_PDGETPID 43199 /* FreeBSD. */ #define AUE_PDWAIT 43200 /* FreeBSD. */ #define AUE_WAIT6 43201 /* FreeBSD. */ #define AUE_CAP_RIGHTS_LIMIT 43202 /* TrustedBSD. */ #define AUE_CAP_IOCTLS_LIMIT 43203 /* TrustedBSD. */ #define AUE_CAP_IOCTLS_GET 43204 /* TrustedBSD. */ #define AUE_CAP_FCNTLS_LIMIT 43205 /* TrustedBSD. */ #define AUE_CAP_FCNTLS_GET 43206 /* TrustedBSD. */ #define AUE_BINDAT 43207 /* TrustedBSD. */ #define AUE_CONNECTAT 43208 /* TrustedBSD. */ #define AUE_CHFLAGSAT 43209 /* FreeBSD-specific. */ #define AUE_PREADV 43210 /* FreeBSD-specific. */ #define AUE_PWRITEV 43211 /* FreeBSD-specific. */ #define AUE_POSIX_FALLOCATE 43212 /* FreeBSD-specific. */ #define AUE_AIO_MLOCK 43213 /* FreeBSD-specific. */ #define AUE_PROCCTL 43214 /* FreeBSD-specific. */ #define AUE_AIO_READ 43215 /* FreeBSD-specific. */ #define AUE_AIO_WRITE 43216 /* FreeBSD-specific. */ #define AUE_AIO_RETURN 43217 /* FreeBSD-specific. */ #define AUE_AIO_SUSPEND 43218 /* FreeBSD-specific. */ #define AUE_AIO_CANCEL 43219 /* FreeBSD-specific. */ #define AUE_AIO_ERROR 43220 /* FreeBSD-specific. */ #define AUE_AIO_WAITCOMPLETE 43221 /* FreeBSD-specific. */ #define AUE_AIO_FSYNC 43222 /* FreeBSD-specific. */ #define AUE_THR_CREATE 43223 /* FreeBSD-specific. */ #define AUE_THR_NEW 43224 /* FreeBSD-specific. */ #define AUE_THR_EXIT 43225 /* FreeBSD-specific. */ #define AUE_THR_KILL 43226 /* FreeBSD-specific. */ #define AUE_THR_KILL2 43227 /* FreeBSD-specific. */ #define AUE_SETFIB 43228 /* FreeBSD-specific. */ #define AUE_LIO_LISTIO 43229 /* FreeBSD-specific. */ #define AUE_SETUGID 43230 /* FreeBSD-specific. */ #define AUE_SCTP_PEELOFF 43231 /* FreeBSD-specific. */ #define AUE_SCTP_GENERIC_SENDMSG 43232 /* FreeBSD-specific. */ #define AUE_SCTP_GENERIC_RECVMSG 43233 /* FreeBSD-specific. */ #define AUE_JAIL_GET 43234 /* FreeBSD-specific. */ #define AUE_JAIL_SET 43235 /* FreeBSD-specific. */ #define AUE_JAIL_REMOVE 43236 /* FreeBSD-specific. */ #define AUE_GETLOGINCLASS 43237 /* FreeBSD-specific. */ #define AUE_SETLOGINCLASS 43238 /* FreeBSD-specific. */ #define AUE_POSIX_FADVISE 43239 /* FreeBSD-specific. */ #define AUE_SCTP_GENERIC_SENDMSG_IOV 43240 /* FreeBSD-specific. */ #define AUE_ABORT2 43241 /* FreeBSD-specific. */ #define AUE_SEMTIMEDWAIT 43242 /* FreeBSD-specific. */ #define AUE_SEMDESTROY 43243 /* FreeBSD-specific. */ #define AUE_SEMGETVALUE 43244 /* FreeBSD-specific. */ #define AUE_SEMINIT 43245 /* FreeBSD-specific. */ #define AUE_SEMPOST 43246 /* FreeBSD-specific. */ #define AUE_SEMTRYWAIT 43247 /* FreeBSD-specific. */ #define AUE_SEMWAIT 43258 /* FreeBSD-specific. */ #define AUE_FGETUUID 43259 /* CADETS. */ #define AUE_GETUUID 43260 /* CADETS. */ #define AUE_LGETUUID 43261 /* CADETS. */ #define AUE_EXECVEAT 43262 /* FreeBSD/Linux. */ #define AUE_SHMRENAME 43263 /* FreeBSD-specific. */ +#define AUE_REALPATHAT 43264 /* FreeBSD-specific. */ /* * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the * normal Solaris BSM identifiers. _O_ refers to it being an old, or compat * interface. In most cases, Darwin has never implemented these system calls * but picked up the fields in their system call table from their FreeBSD * import. Happily, these have different names than the AUE_O* definitions * in Solaris BSM. */ #define AUE_O_CREAT AUE_OPEN_RWTC /* Darwin */ #define AUE_O_EXECVE AUE_NULL /* Darwin */ #define AUE_O_SBREAK AUE_NULL /* Darwin */ #define AUE_O_LSEEK AUE_NULL /* Darwin */ #define AUE_O_MOUNT AUE_NULL /* Darwin */ #define AUE_O_UMOUNT AUE_NULL /* Darwin */ #define AUE_O_STAT AUE_STAT /* Darwin */ #define AUE_O_LSTAT AUE_LSTAT /* Darwin */ #define AUE_O_FSTAT AUE_FSTAT /* Darwin */ #define AUE_O_GETPAGESIZE AUE_NULL /* Darwin */ #define AUE_O_VREAD AUE_NULL /* Darwin */ #define AUE_O_VWRITE AUE_NULL /* Darwin */ #define AUE_O_MMAP AUE_MMAP /* Darwin */ #define AUE_O_VADVISE AUE_NULL /* Darwin */ #define AUE_O_VHANGUP AUE_NULL /* Darwin */ #define AUE_O_VLIMIT AUE_NULL /* Darwin */ #define AUE_O_WAIT AUE_NULL /* Darwin */ #define AUE_O_GETHOSTNAME AUE_NULL /* Darwin */ #define AUE_O_SETHOSTNAME AUE_SYSCTL /* Darwin */ #define AUE_O_GETDOPT AUE_NULL /* Darwin */ #define AUE_O_SETDOPT AUE_NULL /* Darwin */ #define AUE_O_ACCEPT AUE_NULL /* Darwin */ #define AUE_O_SEND AUE_SENDMSG /* Darwin */ #define AUE_O_RECV AUE_RECVMSG /* Darwin */ #define AUE_O_VTIMES AUE_NULL /* Darwin */ #define AUE_O_SIGVEC AUE_NULL /* Darwin */ #define AUE_O_SIGBLOCK AUE_NULL /* Darwin */ #define AUE_O_SIGSETMASK AUE_NULL /* Darwin */ #define AUE_O_SIGSTACK AUE_NULL /* Darwin */ #define AUE_O_RECVMSG AUE_RECVMSG /* Darwin */ #define AUE_O_SENDMSG AUE_SENDMSG /* Darwin */ #define AUE_O_VTRACE AUE_NULL /* Darwin */ #define AUE_O_RESUBA AUE_NULL /* Darwin */ #define AUE_O_RECVFROM AUE_RECVFROM /* Darwin */ #define AUE_O_SETREUID AUE_SETREUID /* Darwin */ #define AUE_O_SETREGID AUE_SETREGID /* Darwin */ #define AUE_O_GETDIRENTRIES AUE_GETDIRENTRIES /* Darwin */ #define AUE_O_TRUNCATE AUE_TRUNCATE /* Darwin */ #define AUE_O_FTRUNCATE AUE_FTRUNCATE /* Darwin */ #define AUE_O_GETPEERNAME AUE_NULL /* Darwin */ #define AUE_O_GETHOSTID AUE_NULL /* Darwin */ #define AUE_O_SETHOSTID AUE_NULL /* Darwin */ #define AUE_O_GETRLIMIT AUE_NULL /* Darwin */ #define AUE_O_SETRLIMIT AUE_SETRLIMIT /* Darwin */ #define AUE_O_KILLPG AUE_KILL /* Darwin */ #define AUE_O_SETQUOTA AUE_NULL /* Darwin */ #define AUE_O_QUOTA AUE_NULL /* Darwin */ #define AUE_O_GETSOCKNAME AUE_NULL /* Darwin */ #define AUE_O_GETDIREENTRIES AUE_GETDIREENTRIES /* Darwin */ #define AUE_O_ASYNCDAEMON AUE_NULL /* Darwin */ #define AUE_O_GETDOMAINNAME AUE_NULL /* Darwin */ #define AUE_O_SETDOMAINNAME AUE_SYSCTL /* Darwin */ #define AUE_O_PCFS_MOUNT AUE_NULL /* Darwin */ #define AUE_O_EXPORTFS AUE_NULL /* Darwin */ #define AUE_O_USTATE AUE_NULL /* Darwin */ #define AUE_O_WAIT3 AUE_NULL /* Darwin */ #define AUE_O_RPAUSE AUE_NULL /* Darwin */ #define AUE_O_GETDENTS AUE_NULL /* Darwin */ /* * Possible desired future values based on review of BSD/Darwin system calls. */ #define AUE_ATGETMSG AUE_NULL #define AUE_ATPUTMSG AUE_NULL #define AUE_ATSOCKET AUE_NULL #define AUE_ATPGETREQ AUE_NULL #define AUE_ATPGETRSP AUE_NULL #define AUE_ATPSNDREQ AUE_NULL #define AUE_ATPSNDRSP AUE_NULL #define AUE_BSDTHREADCREATE AUE_NULL #define AUE_BSDTHREADTERMINATE AUE_NULL #define AUE_BSDTHREADREGISTER AUE_NULL #define AUE_CHUD AUE_NULL #define AUE_CSOPS AUE_NULL #define AUE_DUP AUE_NULL #define AUE_FDATASYNC AUE_NULL #define AUE_FGETATTRLIST AUE_NULL #define AUE_FGETXATTR AUE_NULL #define AUE_FLISTXATTR AUE_NULL #define AUE_FREMOVEXATTR AUE_NULL #define AUE_FSETATTRLIST AUE_NULL #define AUE_FSETXATTR AUE_NULL #define AUE_FSTATFS64 AUE_NULL #define AUE_FSTATV AUE_NULL #define AUE_FSTAT64 AUE_NULL #define AUE_FSTAT64_EXTENDED AUE_NULL #define AUE_GCCONTROL AUE_NULL #define AUE_GETDIRENTRIES64 AUE_NULL #define AUE_GETDTABLESIZE AUE_NULL #define AUE_GETEGID AUE_NULL #define AUE_GETEUID AUE_NULL #define AUE_GETFSSTAT64 AUE_NULL #define AUE_GETGID AUE_NULL #define AUE_GETGROUPS AUE_NULL #define AUE_GETITIMER AUE_NULL #define AUE_GETLOGIN AUE_NULL #define AUE_GETPEERNAME AUE_NULL #define AUE_GETPGID AUE_NULL #define AUE_GETPGRP AUE_NULL #define AUE_GETPID AUE_NULL #define AUE_GETPPID AUE_NULL #define AUE_GETPRIORITY AUE_NULL #define AUE_GETRLIMIT AUE_NULL #define AUE_GETRUSAGE AUE_NULL #define AUE_GETSGROUPS AUE_NULL #define AUE_GETSID AUE_NULL #define AUE_GETSOCKNAME AUE_NULL #define AUE_GETTIMEOFDAY AUE_NULL #define AUE_GETTID AUE_NULL #define AUE_GETUID AUE_NULL #define AUE_GETSOCKOPT AUE_NULL #define AUE_GETWGROUPS AUE_NULL #define AUE_GETXATTR AUE_NULL #define AUE_IDENTITYSVC AUE_NULL #define AUE_INITGROUPS AUE_NULL #define AUE_IOPOLICYSYS AUE_NULL #define AUE_ISSETUGID AUE_NULL #define AUE_LIOLISTIO AUE_NULL #define AUE_LISTXATTR AUE_NULL #define AUE_LSTATV AUE_NULL #define AUE_LSTAT64 AUE_NULL #define AUE_LSTAT64_EXTENDED AUE_NULL #define AUE_MADVISE AUE_NULL #define AUE_MINCORE AUE_NULL #define AUE_MKCOMPLEX AUE_NULL #define AUE_MODWATCH AUE_NULL #define AUE_MSGCL AUE_NULL #define AUE_MSYNC AUE_NULL #define AUE_PROCINFO AUE_NULL #define AUE_PTHREADCANCELED AUE_NULL #define AUE_PTHREADCHDIR AUE_NULL #define AUE_PTHREADCONDBROADCAST AUE_NULL #define AUE_PTHREADCONDDESTORY AUE_NULL #define AUE_PTHREADCONDINIT AUE_NULL #define AUE_PTHREADCONDSIGNAL AUE_NULL #define AUE_PTHREADCONDWAIT AUE_NULL #define AUE_PTHREADFCHDIR AUE_NULL #define AUE_PTHREADMARK AUE_NULL #define AUE_PTHREADMUTEXDESTROY AUE_NULL #define AUE_PTHREADMUTEXINIT AUE_NULL #define AUE_PTHREADMUTEXTRYLOCK AUE_NULL #define AUE_PTHREADMUTEXUNLOCK AUE_NULL #define AUE_REMOVEXATTR AUE_NULL #define AUE_SBRK AUE_NULL #define AUE_SELECT AUE_NULL #define AUE_SEMWAITSIGNAL AUE_NULL #define AUE_SETITIMER AUE_NULL #define AUE_SETSGROUPS AUE_NULL #define AUE_SETTID AUE_NULL #define AUE_SETTIDWITHPID AUE_NULL #define AUE_SETWGROUPS AUE_NULL #define AUE_SETXATTR AUE_NULL #define AUE_SHAREDREGIONCHECK AUE_NULL #define AUE_SHAREDREGIONMAP AUE_NULL #define AUE_SIGACTION AUE_NULL #define AUE_SIGALTSTACK AUE_NULL #define AUE_SIGPENDING AUE_NULL #define AUE_SIGPROCMASK AUE_NULL #define AUE_SIGRETURN AUE_NULL #define AUE_SIGSUSPEND AUE_NULL #define AUE_SIGWAIT AUE_NULL #define AUE_SSTK AUE_NULL #define AUE_STACKSNAPSHOT AUE_NULL #define AUE_STATFS64 AUE_NULL #define AUE_STATV AUE_NULL #define AUE_STAT64 AUE_NULL #define AUE_STAT64_EXTENDED AUE_NULL #define AUE_SYNC AUE_NULL #define AUE_SYSCALL AUE_NULL #define AUE_TABLE AUE_NULL #define AUE_VMPRESSUREMONITOR AUE_NULL #define AUE_WAITEVENT AUE_NULL #define AUE_WAITID AUE_NULL #define AUE_WATCHEVENT AUE_NULL #define AUE_WORKQOPEN AUE_NULL #define AUE_WORKQOPS AUE_NULL #endif /* !_BSM_AUDIT_KEVENTS_H_ */ Index: head/sys/compat/freebsd32/syscalls.master =================================================================== --- head/sys/compat/freebsd32/syscalls.master (revision 358171) +++ head/sys/compat/freebsd32/syscalls.master (revision 358172) @@ -1,1164 +1,1166 @@ $FreeBSD$ ; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94 ; from: src/sys/kern/syscalls.master 1.107 ; ; System call name/number master file. ; Processed to created init_sysent.c, syscalls.c and syscall.h. ; Columns: number audit type name alt{name,tag,rtyp}/comments ; number system call number, must be in order ; audit the audit event associated with the system call ; A value of AUE_NULL means no auditing, but it also means that ; there is no audit event for the call at this time. For the ; case where the event exists, but we don't want auditing, the ; event should be #defined to AUE_NULL in audit_kevents.h. ; type one of STD, OBSOL, UNIMPL, COMPAT, COMPAT4, COMPAT6, ; COMPAT7, COMPAT11, COMPAT12, NODEF, NOARGS, NOPROTO, NOSTD ; The COMPAT* options may be combined with one or more NO* ; options separated by '|' with no spaces (e.g. COMPAT|NOARGS) ; name pseudo-prototype of syscall routine ; If one of the following alts is different, then all appear: ; altname name of system call if different ; alttag name of args struct tag if different from [o]`name'"_args" ; altrtyp return type if not int (bogus - syscalls always return int) ; for UNIMPL/OBSOL, name continues with comments ; types: ; STD always included ; COMPAT included on COMPAT #ifdef ; COMPAT4 included on COMPAT_FREEBSD4 #ifdef (FreeBSD 4 compat) ; COMPAT6 included on COMPAT_FREEBSD6 #ifdef (FreeBSD 6 compat) ; COMPAT7 included on COMPAT_FREEBSD7 #ifdef (FreeBSD 7 compat) ; COMPAT10 included on COMPAT_FREEBSD10 #ifdef (FreeBSD 10 compat) ; COMPAT11 included on COMPAT_FREEBSD11 #ifdef (FreeBSD 11 compat) ; COMPAT12 included on COMPAT_FREEBSD12 #ifdef (FreeBSD 12 compat) ; OBSOL obsolete, not included in system, only specifies name ; UNIMPL not implemented, placeholder only ; NOSTD implemented but as a lkm that can be statically ; compiled in; sysent entry will be filled with lkmressys ; so the SYSCALL_MODULE macro works ; NOARGS same as STD except do not create structure in sys/sysproto.h ; NODEF same as STD except only have the entry in the syscall table ; added. Meaning - do not create structure or function ; prototype in sys/sysproto.h ; NOPROTO same as STD except do not create structure or ; function prototype in sys/sysproto.h. Does add a ; definition to syscall.h besides adding a sysent. ; #ifdef's, etc. may be included, and are copied to the output files. #include #include #include #include #include #include #include #if !defined(PAD64_REQUIRED) && !defined(__amd64__) #define PAD64_REQUIRED #endif ; Reserved/unimplemented system calls in the range 0-150 inclusive ; are reserved for use in future Berkeley releases. ; Additional system calls implemented in vendor and other ; redistributions should be placed in the reserved range at the end ; of the current calls. 0 AUE_NULL NOPROTO { int nosys(void); } syscall nosys_args int 1 AUE_EXIT NOPROTO { void sys_exit(int rval); } exit \ sys_exit_args void 2 AUE_FORK NOPROTO { int fork(void); } 3 AUE_READ NOPROTO { ssize_t read(int fd, void *buf, \ size_t nbyte); } 4 AUE_WRITE NOPROTO { ssize_t write(int fd, const void *buf, \ size_t nbyte); } 5 AUE_OPEN_RWTC NOPROTO { int open(const char *path, int flags, \ mode_t mode); } 6 AUE_CLOSE NOPROTO { int close(int fd); } 7 AUE_WAIT4 STD { int freebsd32_wait4(int pid, int *status, \ int options, struct rusage32 *rusage); } 8 AUE_CREAT OBSOL old creat 9 AUE_LINK NOPROTO { int link(const char *path, \ const char *link); } 10 AUE_UNLINK NOPROTO { int unlink(const char *path); } 11 AUE_NULL OBSOL execv 12 AUE_CHDIR NOPROTO { int chdir(const char *path); } 13 AUE_FCHDIR NOPROTO { int fchdir(int fd); } 14 AUE_MKNOD COMPAT11|NOPROTO { int mknod(const char *path, \ int mode, uint32_t dev); } 15 AUE_CHMOD NOPROTO { int chmod(const char *path, mode_t mode); } 16 AUE_CHOWN NOPROTO { int chown(const char *path, int uid, int gid); } 17 AUE_NULL NOPROTO { void *break(char *nsize); } 18 AUE_GETFSSTAT COMPAT4 { int freebsd32_getfsstat( \ struct statfs32 *buf, long bufsize, \ int mode); } 19 AUE_LSEEK COMPAT { int freebsd32_lseek(int fd, int offset, \ int whence); } 20 AUE_GETPID NOPROTO { pid_t getpid(void); } 21 AUE_MOUNT NOPROTO { int mount(const char *type, \ const char *path, \ int flags, void *data); } 22 AUE_UMOUNT NOPROTO { int unmount(const char *path, int flags); } 23 AUE_SETUID NOPROTO { int setuid(uid_t uid); } 24 AUE_GETUID NOPROTO { uid_t getuid(void); } 25 AUE_GETEUID NOPROTO { uid_t geteuid(void); } 26 AUE_PTRACE NOPROTO { int ptrace(int req, pid_t pid, \ caddr_t addr, int data); } 27 AUE_RECVMSG STD { int freebsd32_recvmsg(int s, struct msghdr32 *msg, \ int flags); } 28 AUE_SENDMSG STD { int freebsd32_sendmsg(int s, struct msghdr32 *msg, \ int flags); } 29 AUE_RECVFROM STD { int freebsd32_recvfrom(int s, void *buf, \ uint32_t len, int flags, \ struct sockaddr *from, \ uint32_t fromlenaddr); } 30 AUE_ACCEPT NOPROTO { int accept(int s, struct sockaddr *name, \ int *anamelen); } 31 AUE_GETPEERNAME NOPROTO { int getpeername(int fdes, \ struct sockaddr *asa, \ int *alen); } 32 AUE_GETSOCKNAME NOPROTO { int getsockname(int fdes, \ struct sockaddr *asa, \ int *alen); } 33 AUE_ACCESS NOPROTO { int access(const char *path, int amode); } 34 AUE_CHFLAGS NOPROTO { int chflags(const char *path, u_long flags); } 35 AUE_FCHFLAGS NOPROTO { int fchflags(int fd, u_long flags); } 36 AUE_SYNC NOPROTO { int sync(void); } 37 AUE_KILL NOPROTO { int kill(int pid, int signum); } 38 AUE_STAT COMPAT { int freebsd32_stat(const char *path, \ struct ostat32 *ub); } 39 AUE_GETPPID NOPROTO { pid_t getppid(void); } 40 AUE_LSTAT COMPAT { int freebsd32_lstat(const char *path, \ struct ostat *ub); } 41 AUE_DUP NOPROTO { int dup(u_int fd); } 42 AUE_PIPE COMPAT10 { int freebsd32_pipe(void); } 43 AUE_GETEGID NOPROTO { gid_t getegid(void); } 44 AUE_PROFILE NOPROTO { int profil(char *samples, size_t size, \ size_t offset, u_int scale); } 45 AUE_KTRACE NOPROTO { int ktrace(const char *fname, int ops, \ int facs, int pid); } 46 AUE_SIGACTION COMPAT { int freebsd32_sigaction( int signum, \ struct osigaction32 *nsa, \ struct osigaction32 *osa); } 47 AUE_GETGID NOPROTO { gid_t getgid(void); } 48 AUE_SIGPROCMASK COMPAT { int freebsd32_sigprocmask(int how, \ osigset_t mask); } 49 AUE_GETLOGIN NOPROTO { int getlogin(char *namebuf, \ u_int namelen); } 50 AUE_SETLOGIN NOPROTO { int setlogin(const char *namebuf); } 51 AUE_ACCT NOPROTO { int acct(const char *path); } 52 AUE_SIGPENDING COMPAT { int freebsd32_sigpending(void); } 53 AUE_SIGALTSTACK STD { int freebsd32_sigaltstack( \ struct sigaltstack32 *ss, \ struct sigaltstack32 *oss); } 54 AUE_IOCTL STD { int freebsd32_ioctl(int fd, uint32_t com, \ struct md_ioctl32 *data); } 55 AUE_REBOOT NOPROTO { int reboot(int opt); } 56 AUE_REVOKE NOPROTO { int revoke(const char *path); } 57 AUE_SYMLINK NOPROTO { int symlink(const char *path, \ const char *link); } 58 AUE_READLINK NOPROTO { ssize_t readlink(const char *path, char *buf, \ size_t count); } 59 AUE_EXECVE STD { int freebsd32_execve(const char *fname, \ uint32_t *argv, uint32_t *envv); } 60 AUE_UMASK NOPROTO { int umask(mode_t newmask); } 61 AUE_CHROOT NOPROTO { int chroot(const char *path); } 62 AUE_FSTAT COMPAT { int freebsd32_fstat(int fd, \ struct ostat32 *ub); } 63 AUE_NULL OBSOL ogetkerninfo 64 AUE_NULL COMPAT { int freebsd32_getpagesize( \ int32_t dummy); } 65 AUE_MSYNC NOPROTO { int msync(void *addr, size_t len, \ int flags); } 66 AUE_VFORK NOPROTO { int vfork(void); } 67 AUE_NULL OBSOL vread 68 AUE_NULL OBSOL vwrite 69 AUE_SBRK NOPROTO { int sbrk(int incr); } 70 AUE_SSTK NOPROTO { int sstk(int incr); } 71 AUE_MMAP COMPAT|NOPROTO { void *mmap(void *addr, int len, \ int prot, int flags, int fd, int pos); } 72 AUE_O_VADVISE COMPAT11|NOPROTO { int vadvise(int anom); } 73 AUE_MUNMAP NOPROTO { int munmap(void *addr, size_t len); } 74 AUE_MPROTECT STD { int freebsd32_mprotect(void *addr, \ size_t len, int prot); } 75 AUE_MADVISE NOPROTO { int madvise(void *addr, size_t len, \ int behav); } 76 AUE_NULL OBSOL vhangup 77 AUE_NULL OBSOL vlimit 78 AUE_MINCORE NOPROTO { int mincore(const void *addr, size_t len, \ char *vec); } 79 AUE_GETGROUPS NOPROTO { int getgroups(u_int gidsetsize, \ gid_t *gidset); } 80 AUE_SETGROUPS NOPROTO { int setgroups(u_int gidsetsize, \ gid_t *gidset); } 81 AUE_GETPGRP NOPROTO { int getpgrp(void); } 82 AUE_SETPGRP NOPROTO { int setpgid(int pid, int pgid); } 83 AUE_SETITIMER STD { int freebsd32_setitimer(u_int which, \ struct itimerval32 *itv, \ struct itimerval32 *oitv); } 84 AUE_NULL OBSOL owait ; XXX implement 85 AUE_SWAPON NOPROTO { int swapon(const char *name); } 86 AUE_GETITIMER STD { int freebsd32_getitimer(u_int which, \ struct itimerval32 *itv); } 87 AUE_O_GETHOSTNAME OBSOL ogethostname 88 AUE_O_SETHOSTNAME OBSOL osethostname 89 AUE_GETDTABLESIZE NOPROTO { int getdtablesize(void); } 90 AUE_DUP2 NOPROTO { int dup2(u_int from, u_int to); } 91 AUE_NULL UNIMPL getdopt 92 AUE_FCNTL STD { int freebsd32_fcntl(int fd, int cmd, \ int arg); } 93 AUE_SELECT STD { int freebsd32_select(int nd, fd_set *in, \ fd_set *ou, fd_set *ex, \ struct timeval32 *tv); } 94 AUE_NULL UNIMPL setdopt 95 AUE_FSYNC NOPROTO { int fsync(int fd); } 96 AUE_SETPRIORITY NOPROTO { int setpriority(int which, int who, \ int prio); } 97 AUE_SOCKET NOPROTO { int socket(int domain, int type, \ int protocol); } 98 AUE_CONNECT NOPROTO { int connect(int s, \ const struct sockaddr *name, \ int namelen); } 99 AUE_NULL OBSOL oaccept 100 AUE_GETPRIORITY NOPROTO { int getpriority(int which, int who); } 101 AUE_NULL OBSOL osend 102 AUE_NULL OBSOL orecv 103 AUE_SIGRETURN COMPAT { int freebsd32_sigreturn( \ struct ia32_sigcontext3 *sigcntxp); } 104 AUE_BIND NOPROTO { int bind(int s, const struct sockaddr *name, \ int namelen); } 105 AUE_SETSOCKOPT NOPROTO { int setsockopt(int s, int level, \ int name, const void *val, int valsize); } 106 AUE_LISTEN NOPROTO { int listen(int s, int backlog); } 107 AUE_NULL OBSOL vtimes 108 AUE_O_SIGVEC COMPAT { int freebsd32_sigvec(int signum, \ struct sigvec32 *nsv, \ struct sigvec32 *osv); } 109 AUE_O_SIGBLOCK COMPAT { int freebsd32_sigblock(int mask); } 110 AUE_O_SIGSETMASK COMPAT { int freebsd32_sigsetmask( int mask); } 111 AUE_SIGSUSPEND COMPAT { int freebsd32_sigsuspend( int mask); } 112 AUE_O_SIGSTACK COMPAT { int freebsd32_sigstack( \ struct sigstack32 *nss, \ struct sigstack32 *oss); } 113 AUE_NULL OBSOL orecvmsg 114 AUE_NULL OBSOL osendmsg 115 AUE_NULL OBSOL vtrace 116 AUE_GETTIMEOFDAY STD { int freebsd32_gettimeofday( \ struct timeval32 *tp, \ struct timezone *tzp); } 117 AUE_GETRUSAGE STD { int freebsd32_getrusage(int who, \ struct rusage32 *rusage); } 118 AUE_GETSOCKOPT NOPROTO { int getsockopt(int s, int level, \ int name, void *val, int *avalsize); } 119 AUE_NULL UNIMPL resuba (BSD/OS 2.x) 120 AUE_READV STD { int freebsd32_readv(int fd, \ struct iovec32 *iovp, u_int iovcnt); } 121 AUE_WRITEV STD { int freebsd32_writev(int fd, \ struct iovec32 *iovp, u_int iovcnt); } 122 AUE_SETTIMEOFDAY STD { int freebsd32_settimeofday( \ struct timeval32 *tv, \ struct timezone *tzp); } 123 AUE_FCHOWN NOPROTO { int fchown(int fd, int uid, int gid); } 124 AUE_FCHMOD NOPROTO { int fchmod(int fd, mode_t mode); } 125 AUE_RECVFROM OBSOL orecvfrom 126 AUE_SETREUID NOPROTO { int setreuid(int ruid, int euid); } 127 AUE_SETREGID NOPROTO { int setregid(int rgid, int egid); } 128 AUE_RENAME NOPROTO { int rename(const char *from, \ const char *to); } 129 AUE_TRUNCATE COMPAT|NOPROTO { int truncate(const char *path, \ int length); } 130 AUE_FTRUNCATE COMPAT|NOPROTO { int ftruncate(int fd, int length); } 131 AUE_FLOCK NOPROTO { int flock(int fd, int how); } 132 AUE_MKFIFO NOPROTO { int mkfifo(const char *path, mode_t mode); } 133 AUE_SENDTO NOPROTO { int sendto(int s, const void *buf, \ size_t len, int flags, \ const struct sockaddr *to, \ int tolen); } 134 AUE_SHUTDOWN NOPROTO { int shutdown(int s, int how); } 135 AUE_SOCKETPAIR NOPROTO { int socketpair(int domain, int type, \ int protocol, int *rsv); } 136 AUE_MKDIR NOPROTO { int mkdir(const char *path, mode_t mode); } 137 AUE_RMDIR NOPROTO { int rmdir(const char *path); } 138 AUE_UTIMES STD { int freebsd32_utimes(const char *path, \ struct timeval32 *tptr); } 139 AUE_NULL OBSOL 4.2 sigreturn 140 AUE_ADJTIME STD { int freebsd32_adjtime( \ struct timeval32 *delta, \ struct timeval32 *olddelta); } 141 AUE_GETPEERNAME OBSOL ogetpeername 142 AUE_SYSCTL OBSOL ogethostid 143 AUE_SYSCTL OBSOL sethostid 144 AUE_GETRLIMIT OBSOL getrlimit 145 AUE_SETRLIMIT OBSOL setrlimit 146 AUE_KILLPG OBSOL killpg 147 AUE_SETSID NOPROTO { int setsid(void); } 148 AUE_QUOTACTL NOPROTO { int quotactl(const char *path, int cmd, \ int uid, void *arg); } 149 AUE_O_QUOTA OBSOL oquota 150 AUE_GETSOCKNAME OBSOL ogetsockname ; Syscalls 151-180 inclusive are reserved for vendor-specific ; system calls. (This includes various calls added for compatibity ; with other Unix variants.) ; Some of these calls are now supported by BSD... 151 AUE_NULL UNIMPL sem_lock (BSD/OS 2.x) 152 AUE_NULL UNIMPL sem_wakeup (BSD/OS 2.x) 153 AUE_NULL UNIMPL asyncdaemon (BSD/OS 2.x) ; 154 is initialised by the NLM code, if present. 154 AUE_NULL UNIMPL nlm_syscall ; 155 is initialized by the NFS code, if present. ; XXX this is a problem!!! 155 AUE_NFS_SVC UNIMPL nfssvc 156 AUE_GETDIRENTRIES COMPAT { int freebsd32_getdirentries(int fd, \ char *buf, u_int count, uint32_t *basep); } 157 AUE_STATFS COMPAT4 { int freebsd32_statfs(const char *path, \ struct statfs32 *buf); } 158 AUE_FSTATFS COMPAT4 { int freebsd32_fstatfs(int fd, \ struct statfs32 *buf); } 159 AUE_NULL UNIMPL nosys 160 AUE_LGETFH UNIMPL lgetfh 161 AUE_NFS_GETFH NOPROTO { int getfh(const char *fname, \ struct fhandle *fhp); } 162 AUE_SYSCTL OBSOL getdomainname 163 AUE_SYSCTL OBSOL setdomainname 164 AUE_NULL OBSOL uname 165 AUE_SYSARCH STD { int freebsd32_sysarch(int op, char *parms); } 166 AUE_RTPRIO NOPROTO { int rtprio(int function, pid_t pid, \ struct rtprio *rtp); } 167 AUE_NULL UNIMPL nosys 168 AUE_NULL UNIMPL nosys 169 AUE_SEMSYS NOSTD { int freebsd32_semsys(int which, int a2, \ int a3, int a4, int a5); } 170 AUE_MSGSYS NOSTD { int freebsd32_msgsys(int which, int a2, \ int a3, int a4, int a5, int a6); } 171 AUE_SHMSYS NOSTD { int freebsd32_shmsys(uint32_t which, uint32_t a2, \ uint32_t a3, uint32_t a4); } 172 AUE_NULL UNIMPL nosys 173 AUE_PREAD COMPAT6 { ssize_t freebsd32_pread(int fd, void *buf, \ size_t nbyte, int pad, \ uint32_t offset1, uint32_t offset2); } 174 AUE_PWRITE COMPAT6 { ssize_t freebsd32_pwrite(int fd, \ const void *buf, size_t nbyte, int pad, \ uint32_t offset1, uint32_t offset2); } 175 AUE_NULL UNIMPL nosys 176 AUE_NTP_ADJTIME NOPROTO { int ntp_adjtime(struct timex *tp); } 177 AUE_NULL UNIMPL sfork (BSD/OS 2.x) 178 AUE_NULL UNIMPL getdescriptor (BSD/OS 2.x) 179 AUE_NULL UNIMPL setdescriptor (BSD/OS 2.x) 180 AUE_NULL UNIMPL nosys ; Syscalls 181-199 are used by/reserved for BSD 181 AUE_SETGID NOPROTO { int setgid(gid_t gid); } 182 AUE_SETEGID NOPROTO { int setegid(gid_t egid); } 183 AUE_SETEUID NOPROTO { int seteuid(uid_t euid); } 184 AUE_NULL OBSOL lfs_bmapv 185 AUE_NULL OBSOL lfs_markv 186 AUE_NULL OBSOL lfs_segclean 187 AUE_NULL OBSOL lfs_segwait 188 AUE_STAT COMPAT11 { int freebsd32_stat(const char *path, \ struct freebsd11_stat32 *ub); } 189 AUE_FSTAT COMPAT11 { int freebsd32_fstat(int fd, \ struct freebsd11_stat32 *ub); } 190 AUE_LSTAT COMPAT11 { int freebsd32_lstat(const char *path, \ struct freebsd11_stat32 *ub); } 191 AUE_PATHCONF NOPROTO { int pathconf(const char *path, int name); } 192 AUE_FPATHCONF NOPROTO { int fpathconf(int fd, int name); } 193 AUE_NULL UNIMPL nosys 194 AUE_GETRLIMIT NOPROTO { int getrlimit(u_int which, \ struct rlimit *rlp); } getrlimit \ __getrlimit_args int 195 AUE_SETRLIMIT NOPROTO { int setrlimit(u_int which, \ struct rlimit *rlp); } setrlimit \ __setrlimit_args int 196 AUE_GETDIRENTRIES COMPAT11 { int freebsd32_getdirentries(int fd, \ char *buf, u_int count, int32_t *basep); } 197 AUE_MMAP COMPAT6 { void *freebsd32_mmap(void *addr, \ size_t len, int prot, int flags, int fd, \ int pad, uint32_t pos1, uint32_t pos2); } 198 AUE_NULL NOPROTO { int nosys(void); } __syscall \ __syscall_args int 199 AUE_LSEEK COMPAT6 { off_t freebsd32_lseek(int fd, int pad, \ uint32_t offset1, uint32_t offset2, \ int whence); } 200 AUE_TRUNCATE COMPAT6 { int freebsd32_truncate(const char *path, \ int pad, uint32_t length1, \ uint32_t length2); } 201 AUE_FTRUNCATE COMPAT6 { int freebsd32_ftruncate(int fd, int pad, \ uint32_t length1, uint32_t length2); } 202 AUE_SYSCTL STD { int freebsd32___sysctl(int *name, \ u_int namelen, void *old, \ uint32_t *oldlenp, const void *new, \ uint32_t newlen); } 203 AUE_MLOCK NOPROTO { int mlock(const void *addr, \ size_t len); } 204 AUE_MUNLOCK NOPROTO { int munlock(const void *addr, \ size_t len); } 205 AUE_UNDELETE NOPROTO { int undelete(const char *path); } 206 AUE_FUTIMES STD { int freebsd32_futimes(int fd, \ struct timeval32 *tptr); } 207 AUE_GETPGID NOPROTO { int getpgid(pid_t pid); } 208 AUE_NULL UNIMPL nosys 209 AUE_POLL NOPROTO { int poll(struct pollfd *fds, u_int nfds, \ int timeout); } ; ; The following are reserved for loadable syscalls ; 210 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 211 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 212 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 213 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 214 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 215 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 216 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 217 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 218 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 219 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 220 AUE_SEMCTL COMPAT7|NOSTD { int freebsd32_semctl( \ int semid, int semnum, \ int cmd, union semun32 *arg); } 221 AUE_SEMGET NOSTD|NOPROTO { int semget(key_t key, int nsems, \ int semflg); } 222 AUE_SEMOP NOSTD|NOPROTO { int semop(int semid, \ struct sembuf *sops, u_int nsops); } 223 AUE_NULL OBSOL semconfig 224 AUE_MSGCTL COMPAT7|NOSTD { int freebsd32_msgctl( \ int msqid, int cmd, \ struct msqid_ds32_old *buf); } 225 AUE_MSGGET NOSTD|NOPROTO { int msgget(key_t key, int msgflg); } 226 AUE_MSGSND NOSTD { int freebsd32_msgsnd(int msqid, void *msgp, \ size_t msgsz, int msgflg); } 227 AUE_MSGRCV NOSTD { int freebsd32_msgrcv(int msqid, void *msgp, \ size_t msgsz, long msgtyp, int msgflg); } 228 AUE_SHMAT NOSTD|NOPROTO { void *shmat(int shmid, void *shmaddr, \ int shmflg); } 229 AUE_SHMCTL COMPAT7|NOSTD { int freebsd32_shmctl( \ int shmid, int cmd, \ struct shmid_ds32_old *buf); } 230 AUE_SHMDT NOSTD|NOPROTO { int shmdt(void *shmaddr); } 231 AUE_SHMGET NOSTD|NOPROTO { int shmget(key_t key, int size, \ int shmflg); } ; 232 AUE_NULL STD { int freebsd32_clock_gettime(clockid_t clock_id, \ struct timespec32 *tp); } 233 AUE_CLOCK_SETTIME STD { int freebsd32_clock_settime(clockid_t clock_id, \ const struct timespec32 *tp); } 234 AUE_NULL STD { int freebsd32_clock_getres(clockid_t clock_id, \ struct timespec32 *tp); } 235 AUE_NULL STD { int freebsd32_ktimer_create(\ clockid_t clock_id, \ struct sigevent32 *evp, int *timerid); } 236 AUE_NULL NOPROTO { int ktimer_delete(int timerid); } 237 AUE_NULL STD { int freebsd32_ktimer_settime(int timerid,\ int flags, \ const struct itimerspec32 *value, \ struct itimerspec32 *ovalue); } 238 AUE_NULL STD { int freebsd32_ktimer_gettime(int timerid,\ struct itimerspec32 *value); } 239 AUE_NULL NOPROTO { int ktimer_getoverrun(int timerid); } 240 AUE_NULL STD { int freebsd32_nanosleep( \ const struct timespec32 *rqtp, \ struct timespec32 *rmtp); } 241 AUE_NULL NOPROTO { int ffclock_getcounter(ffcounter *ffcount); } 242 AUE_NULL NOPROTO { int ffclock_setestimate( \ struct ffclock_estimate *cest); } 243 AUE_NULL NOPROTO { int ffclock_getestimate( \ struct ffclock_estimate *cest); } 244 AUE_NULL STD { int freebsd32_clock_nanosleep( \ clockid_t clock_id, int flags, \ const struct timespec32 *rqtp, \ struct timespec32 *rmtp); } 245 AUE_NULL UNIMPL nosys 246 AUE_NULL UNIMPL nosys 247 AUE_NULL STD { int freebsd32_clock_getcpuclockid2(\ uint32_t id1, uint32_t id2,\ int which, clockid_t *clock_id); } 248 AUE_NULL UNIMPL ntp_gettime 249 AUE_NULL UNIMPL nosys 250 AUE_MINHERIT NOPROTO { int minherit(void *addr, size_t len, \ int inherit); } 251 AUE_RFORK NOPROTO { int rfork(int flags); } 252 AUE_POLL OBSOL openbsd_poll 253 AUE_ISSETUGID NOPROTO { int issetugid(void); } 254 AUE_LCHOWN NOPROTO { int lchown(const char *path, int uid, \ int gid); } 255 AUE_AIO_READ STD { int freebsd32_aio_read( \ struct aiocb32 *aiocbp); } 256 AUE_AIO_WRITE STD { int freebsd32_aio_write( \ struct aiocb32 *aiocbp); } 257 AUE_LIO_LISTIO STD { int freebsd32_lio_listio(int mode, \ struct aiocb32 * const *acb_list, \ int nent, struct sigevent32 *sig); } 258 AUE_NULL UNIMPL nosys 259 AUE_NULL UNIMPL nosys 260 AUE_NULL UNIMPL nosys 261 AUE_NULL UNIMPL nosys 262 AUE_NULL UNIMPL nosys 263 AUE_NULL UNIMPL nosys 264 AUE_NULL UNIMPL nosys 265 AUE_NULL UNIMPL nosys 266 AUE_NULL UNIMPL nosys 267 AUE_NULL UNIMPL nosys 268 AUE_NULL UNIMPL nosys 269 AUE_NULL UNIMPL nosys 270 AUE_NULL UNIMPL nosys 271 AUE_NULL UNIMPL nosys 272 AUE_O_GETDENTS COMPAT11 { int freebsd32_getdents(int fd, char *buf, \ int count); } 273 AUE_NULL UNIMPL nosys 274 AUE_LCHMOD NOPROTO { int lchmod(const char *path, mode_t mode); } 275 AUE_NULL OBSOL netbsd_lchown 276 AUE_LUTIMES STD { int freebsd32_lutimes(const char *path, \ struct timeval32 *tptr); } 277 AUE_NULL OBSOL netbsd_msync 278 AUE_STAT COMPAT11|NOPROTO { int nstat(const char *path, \ struct nstat *ub); } 279 AUE_FSTAT COMPAT11|NOPROTO { int nfstat(int fd, struct nstat *sb); } 280 AUE_LSTAT COMPAT11|NOPROTO { int nlstat(const char *path, \ struct nstat *ub); } 281 AUE_NULL UNIMPL nosys 282 AUE_NULL UNIMPL nosys 283 AUE_NULL UNIMPL nosys 284 AUE_NULL UNIMPL nosys 285 AUE_NULL UNIMPL nosys 286 AUE_NULL UNIMPL nosys 287 AUE_NULL UNIMPL nosys 288 AUE_NULL UNIMPL nosys 289 AUE_PREADV STD { ssize_t freebsd32_preadv(int fd, \ struct iovec32 *iovp, \ u_int iovcnt, \ uint32_t offset1, uint32_t offset2); } 290 AUE_PWRITEV STD { ssize_t freebsd32_pwritev(int fd, \ struct iovec32 *iovp, \ u_int iovcnt, \ uint32_t offset1, uint32_t offset2); } 291 AUE_NULL UNIMPL nosys 292 AUE_NULL UNIMPL nosys 293 AUE_NULL UNIMPL nosys 294 AUE_NULL UNIMPL nosys 295 AUE_NULL UNIMPL nosys 296 AUE_NULL UNIMPL nosys 297 AUE_FHSTATFS COMPAT4 { int freebsd32_fhstatfs( \ const struct fhandle *u_fhp, \ struct statfs32 *buf); } 298 AUE_FHOPEN NOPROTO { int fhopen(const struct fhandle *u_fhp, \ int flags); } 299 AUE_FHSTAT COMPAT11 { int freebsd32_fhstat( \ const struct fhandle *u_fhp, \ struct freebsd11_stat32 *sb); } ; syscall numbers for FreeBSD 300 AUE_NULL NOPROTO { int modnext(int modid); } 301 AUE_NULL STD { int freebsd32_modstat(int modid, \ struct module_stat32 *stat); } 302 AUE_NULL NOPROTO { int modfnext(int modid); } 303 AUE_NULL NOPROTO { int modfind(const char *name); } 304 AUE_MODLOAD NOPROTO { int kldload(const char *file); } 305 AUE_MODUNLOAD NOPROTO { int kldunload(int fileid); } 306 AUE_NULL NOPROTO { int kldfind(const char *file); } 307 AUE_NULL NOPROTO { int kldnext(int fileid); } 308 AUE_NULL STD { int freebsd32_kldstat(int fileid, \ struct kld32_file_stat *stat); } 309 AUE_NULL NOPROTO { int kldfirstmod(int fileid); } 310 AUE_GETSID NOPROTO { int getsid(pid_t pid); } 311 AUE_SETRESUID NOPROTO { int setresuid(uid_t ruid, uid_t euid, \ uid_t suid); } 312 AUE_SETRESGID NOPROTO { int setresgid(gid_t rgid, gid_t egid, \ gid_t sgid); } 313 AUE_NULL OBSOL signanosleep 314 AUE_AIO_RETURN STD { int freebsd32_aio_return( \ struct aiocb32 *aiocbp); } 315 AUE_AIO_SUSPEND STD { int freebsd32_aio_suspend( \ struct aiocb32 * const * aiocbp, int nent, \ const struct timespec32 *timeout); } 316 AUE_AIO_CANCEL NOPROTO { int aio_cancel(int fd, \ struct aiocb *aiocbp); } 317 AUE_AIO_ERROR STD { int freebsd32_aio_error( \ struct aiocb32 *aiocbp); } 318 AUE_AIO_READ COMPAT6 { int freebsd32_aio_read( \ struct oaiocb32 *aiocbp); } 319 AUE_AIO_WRITE COMPAT6 { int freebsd32_aio_write( \ struct oaiocb32 *aiocbp); } 320 AUE_LIO_LISTIO COMPAT6 { int freebsd32_lio_listio(int mode, \ struct oaiocb32 * const *acb_list, \ int nent, struct osigevent32 *sig); } 321 AUE_NULL NOPROTO { int yield(void); } 322 AUE_NULL OBSOL thr_sleep 323 AUE_NULL OBSOL thr_wakeup 324 AUE_MLOCKALL NOPROTO { int mlockall(int how); } 325 AUE_MUNLOCKALL NOPROTO { int munlockall(void); } 326 AUE_GETCWD NOPROTO { int __getcwd(char *buf, size_t buflen); } 327 AUE_NULL NOPROTO { int sched_setparam (pid_t pid, \ const struct sched_param *param); } 328 AUE_NULL NOPROTO { int sched_getparam (pid_t pid, \ struct sched_param *param); } 329 AUE_NULL NOPROTO { int sched_setscheduler (pid_t pid, \ int policy, \ const struct sched_param *param); } 330 AUE_NULL NOPROTO { int sched_getscheduler (pid_t pid); } 331 AUE_NULL NOPROTO { int sched_yield (void); } 332 AUE_NULL NOPROTO { int sched_get_priority_max (int policy); } 333 AUE_NULL NOPROTO { int sched_get_priority_min (int policy); } 334 AUE_NULL STD { int freebsd32_sched_rr_get_interval ( \ pid_t pid, \ struct timespec32 *interval); } 335 AUE_NULL NOPROTO { int utrace(const void *addr, size_t len); } 336 AUE_SENDFILE COMPAT4 { int freebsd32_sendfile(int fd, int s, \ uint32_t offset1, uint32_t offset2, \ size_t nbytes, struct sf_hdtr32 *hdtr, \ off_t *sbytes, int flags); } 337 AUE_NULL NOPROTO { int kldsym(int fileid, int cmd, \ void *data); } 338 AUE_JAIL STD { int freebsd32_jail(struct jail32 *jail); } 339 AUE_NULL UNIMPL pioctl 340 AUE_SIGPROCMASK NOPROTO { int sigprocmask(int how, \ const sigset_t *set, sigset_t *oset); } 341 AUE_SIGSUSPEND NOPROTO { int sigsuspend(const sigset_t *sigmask); } 342 AUE_SIGACTION COMPAT4 { int freebsd32_sigaction(int sig, \ struct sigaction32 *act, \ struct sigaction32 *oact); } 343 AUE_SIGPENDING NOPROTO { int sigpending(sigset_t *set); } 344 AUE_SIGRETURN COMPAT4 { int freebsd32_sigreturn( \ const struct freebsd4_freebsd32_ucontext *sigcntxp); } 345 AUE_SIGWAIT STD { int freebsd32_sigtimedwait(const sigset_t *set, \ siginfo_t *info, \ const struct timespec *timeout); } 346 AUE_NULL STD { int freebsd32_sigwaitinfo(const sigset_t *set, \ siginfo_t *info); } 347 AUE_ACL_GET_FILE NOPROTO { int __acl_get_file(const char *path, \ acl_type_t type, struct acl *aclp); } 348 AUE_ACL_SET_FILE NOPROTO { int __acl_set_file(const char *path, \ acl_type_t type, struct acl *aclp); } 349 AUE_ACL_GET_FD NOPROTO { int __acl_get_fd(int filedes, \ acl_type_t type, struct acl *aclp); } 350 AUE_ACL_SET_FD NOPROTO { int __acl_set_fd(int filedes, \ acl_type_t type, struct acl *aclp); } 351 AUE_ACL_DELETE_FILE NOPROTO { int __acl_delete_file(const char *path, \ acl_type_t type); } 352 AUE_ACL_DELETE_FD NOPROTO { int __acl_delete_fd(int filedes, \ acl_type_t type); } 353 AUE_ACL_CHECK_FILE NOPROTO { int __acl_aclcheck_file(const char *path, \ acl_type_t type, struct acl *aclp); } 354 AUE_ACL_CHECK_FD NOPROTO { int __acl_aclcheck_fd(int filedes, \ acl_type_t type, struct acl *aclp); } 355 AUE_EXTATTRCTL NOPROTO { int extattrctl(const char *path, int cmd, \ const char *filename, int attrnamespace, \ const char *attrname); } 356 AUE_EXTATTR_SET_FILE NOPROTO { ssize_t extattr_set_file( \ const char *path, int attrnamespace, \ const char *attrname, void *data, \ size_t nbytes); } 357 AUE_EXTATTR_GET_FILE NOPROTO { ssize_t extattr_get_file( \ const char *path, int attrnamespace, \ const char *attrname, void *data, \ size_t nbytes); } 358 AUE_EXTATTR_DELETE_FILE NOPROTO { int extattr_delete_file( \ const char *path, int attrnamespace, \ const char *attrname); } 359 AUE_AIO_WAITCOMPLETE STD { int freebsd32_aio_waitcomplete( \ struct aiocb32 **aiocbp, \ struct timespec32 *timeout); } 360 AUE_GETRESUID NOPROTO { int getresuid(uid_t *ruid, uid_t *euid, \ uid_t *suid); } 361 AUE_GETRESGID NOPROTO { int getresgid(gid_t *rgid, gid_t *egid, \ gid_t *sgid); } 362 AUE_KQUEUE NOPROTO { int kqueue(void); } 363 AUE_KEVENT COMPAT11 { int freebsd32_kevent(int fd, \ const struct kevent32_freebsd11 * \ changelist, \ int nchanges, \ struct kevent32_freebsd11 *eventlist, \ int nevents, \ const struct timespec32 *timeout); } 364 AUE_NULL OBSOL __cap_get_proc 365 AUE_NULL OBSOL __cap_set_proc 366 AUE_NULL OBSOL __cap_get_fd 367 AUE_NULL OBSOL __cap_get_file 368 AUE_NULL OBSOL __cap_set_fd 369 AUE_NULL OBSOL __cap_set_file 370 AUE_NULL UNIMPL nosys 371 AUE_EXTATTR_SET_FD NOPROTO { ssize_t extattr_set_fd(int fd, \ int attrnamespace, const char *attrname, \ void *data, size_t nbytes); } 372 AUE_EXTATTR_GET_FD NOPROTO { ssize_t extattr_get_fd(int fd, \ int attrnamespace, const char *attrname, \ void *data, size_t nbytes); } 373 AUE_EXTATTR_DELETE_FD NOPROTO { int extattr_delete_fd(int fd, \ int attrnamespace, \ const char *attrname); } 374 AUE_SETUGID NOPROTO { int __setugid(int flag); } 375 AUE_NULL OBSOL nfsclnt 376 AUE_EACCESS NOPROTO { int eaccess(const char *path, int amode); } 377 AUE_NULL UNIMPL afs_syscall 378 AUE_NMOUNT STD { int freebsd32_nmount(struct iovec32 *iovp, \ unsigned int iovcnt, int flags); } 379 AUE_NULL OBSOL kse_exit 380 AUE_NULL OBSOL kse_wakeup 381 AUE_NULL OBSOL kse_create 382 AUE_NULL OBSOL kse_thr_interrupt 383 AUE_NULL OBSOL kse_release 384 AUE_NULL UNIMPL __mac_get_proc 385 AUE_NULL UNIMPL __mac_set_proc 386 AUE_NULL UNIMPL __mac_get_fd 387 AUE_NULL UNIMPL __mac_get_file 388 AUE_NULL UNIMPL __mac_set_fd 389 AUE_NULL UNIMPL __mac_set_file 390 AUE_NULL NOPROTO { int kenv(int what, const char *name, \ char *value, int len); } 391 AUE_LCHFLAGS NOPROTO { int lchflags(const char *path, \ u_long flags); } 392 AUE_NULL NOPROTO { int uuidgen(struct uuid *store, \ int count); } 393 AUE_SENDFILE STD { int freebsd32_sendfile(int fd, int s, \ uint32_t offset1, uint32_t offset2, \ size_t nbytes, struct sf_hdtr32 *hdtr, \ off_t *sbytes, int flags); } 394 AUE_NULL UNIMPL mac_syscall 395 AUE_GETFSSTAT COMPAT11|NOPROTO { int getfsstat( \ struct freebsd11_statfs *buf, \ long bufsize, int mode); } 396 AUE_STATFS COMPAT11|NOPROTO { int statfs(const char *path, \ struct statfs *buf); } 397 AUE_FSTATFS COMPAT11|NOPROTO { int fstatfs(int fd, \ struct freebsd11_statfs *buf); } 398 AUE_FHSTATFS COMPAT11|NOPROTO { int fhstatfs( \ const struct fhandle *u_fhp, \ struct freebsd11_statfs *buf); } 399 AUE_NULL UNIMPL nosys 400 AUE_SEMCLOSE NOSTD|NOPROTO { int ksem_close(semid_t id); } 401 AUE_SEMPOST NOSTD|NOPROTO { int ksem_post(semid_t id); } 402 AUE_SEMWAIT NOSTD|NOPROTO { int ksem_wait(semid_t id); } 403 AUE_SEMTRYWAIT NOSTD|NOPROTO { int ksem_trywait(semid_t id); } 404 AUE_SEMINIT NOSTD { int freebsd32_ksem_init(semid_t *idp, \ unsigned int value); } 405 AUE_SEMOPEN NOSTD { int freebsd32_ksem_open(semid_t *idp, \ const char *name, int oflag, \ mode_t mode, unsigned int value); } 406 AUE_SEMUNLINK NOSTD|NOPROTO { int ksem_unlink(const char *name); } 407 AUE_SEMGETVALUE NOSTD|NOPROTO { int ksem_getvalue(semid_t id, \ int *val); } 408 AUE_SEMDESTROY NOSTD|NOPROTO { int ksem_destroy(semid_t id); } 409 AUE_NULL UNIMPL __mac_get_pid 410 AUE_NULL UNIMPL __mac_get_link 411 AUE_NULL UNIMPL __mac_set_link 412 AUE_EXTATTR_SET_LINK NOPROTO { ssize_t extattr_set_link( \ const char *path, int attrnamespace, \ const char *attrname, void *data, \ size_t nbytes); } 413 AUE_EXTATTR_GET_LINK NOPROTO { ssize_t extattr_get_link( \ const char *path, int attrnamespace, \ const char *attrname, void *data, \ size_t nbytes); } 414 AUE_EXTATTR_DELETE_LINK NOPROTO { int extattr_delete_link( \ const char *path, int attrnamespace, \ const char *attrname); } 415 AUE_NULL UNIMPL __mac_execve 416 AUE_SIGACTION STD { int freebsd32_sigaction(int sig, \ struct sigaction32 *act, \ struct sigaction32 *oact); } 417 AUE_SIGRETURN STD { int freebsd32_sigreturn( \ const struct freebsd32_ucontext *sigcntxp); } 418 AUE_NULL UNIMPL __xstat 419 AUE_NULL UNIMPL __xfstat 420 AUE_NULL UNIMPL __xlstat 421 AUE_NULL STD { int freebsd32_getcontext( \ struct freebsd32_ucontext *ucp); } 422 AUE_NULL STD { int freebsd32_setcontext( \ const struct freebsd32_ucontext *ucp); } 423 AUE_NULL STD { int freebsd32_swapcontext( \ struct freebsd32_ucontext *oucp, \ const struct freebsd32_ucontext *ucp); } 424 AUE_SWAPOFF UNIMPL swapoff 425 AUE_ACL_GET_LINK NOPROTO { int __acl_get_link(const char *path, \ acl_type_t type, struct acl *aclp); } 426 AUE_ACL_SET_LINK NOPROTO { int __acl_set_link(const char *path, \ acl_type_t type, struct acl *aclp); } 427 AUE_ACL_DELETE_LINK NOPROTO { int __acl_delete_link(const char *path, \ acl_type_t type); } 428 AUE_ACL_CHECK_LINK NOPROTO { int __acl_aclcheck_link(const char *path, \ acl_type_t type, struct acl *aclp); } 429 AUE_SIGWAIT NOPROTO { int sigwait(const sigset_t *set, \ int *sig); } 430 AUE_THR_CREATE UNIMPL thr_create; 431 AUE_THR_EXIT NOPROTO { void thr_exit(long *state); } 432 AUE_NULL NOPROTO { int thr_self(long *id); } 433 AUE_THR_KILL NOPROTO { int thr_kill(long id, int sig); } 434 AUE_NULL UNIMPL nosys 435 AUE_NULL UNIMPL nosys 436 AUE_JAIL_ATTACH NOPROTO { int jail_attach(int jid); } 437 AUE_EXTATTR_LIST_FD NOPROTO { ssize_t extattr_list_fd(int fd, \ int attrnamespace, void *data, \ size_t nbytes); } 438 AUE_EXTATTR_LIST_FILE NOPROTO { ssize_t extattr_list_file( \ const char *path, int attrnamespace, \ void *data, size_t nbytes); } 439 AUE_EXTATTR_LIST_LINK NOPROTO { ssize_t extattr_list_link( \ const char *path, int attrnamespace, \ void *data, size_t nbytes); } 440 AUE_NULL OBSOL kse_switchin 441 AUE_SEMWAIT NOSTD { int freebsd32_ksem_timedwait(semid_t id, \ const struct timespec32 *abstime); } 442 AUE_NULL STD { int freebsd32_thr_suspend( \ const struct timespec32 *timeout); } 443 AUE_NULL NOPROTO { int thr_wake(long id); } 444 AUE_MODUNLOAD NOPROTO { int kldunloadf(int fileid, int flags); } 445 AUE_AUDIT NOPROTO { int audit(const void *record, \ u_int length); } 446 AUE_AUDITON NOPROTO { int auditon(int cmd, void *data, \ u_int length); } 447 AUE_GETAUID NOPROTO { int getauid(uid_t *auid); } 448 AUE_SETAUID NOPROTO { int setauid(uid_t *auid); } 449 AUE_GETAUDIT NOPROTO { int getaudit(struct auditinfo *auditinfo); } 450 AUE_SETAUDIT NOPROTO { int setaudit(struct auditinfo *auditinfo); } 451 AUE_GETAUDIT_ADDR NOPROTO { int getaudit_addr( \ struct auditinfo_addr *auditinfo_addr, \ u_int length); } 452 AUE_SETAUDIT_ADDR NOPROTO { int setaudit_addr( \ struct auditinfo_addr *auditinfo_addr, \ u_int length); } 453 AUE_AUDITCTL NOPROTO { int auditctl(const char *path); } 454 AUE_NULL STD { int freebsd32__umtx_op(void *obj, int op,\ u_long val, void *uaddr, \ void *uaddr2); } 455 AUE_THR_NEW STD { int freebsd32_thr_new( \ struct thr_param32 *param, \ int param_size); } 456 AUE_NULL STD { int freebsd32_sigqueue(pid_t pid, \ int signum, int value); } 457 AUE_MQ_OPEN NOSTD { int freebsd32_kmq_open( \ const char *path, int flags, mode_t mode, \ const struct mq_attr32 *attr); } 458 AUE_MQ_SETATTR NOSTD { int freebsd32_kmq_setattr(int mqd, \ const struct mq_attr32 *attr, \ struct mq_attr32 *oattr); } 459 AUE_MQ_TIMEDRECEIVE NOSTD { int freebsd32_kmq_timedreceive(int mqd, \ char *msg_ptr, size_t msg_len, \ unsigned *msg_prio, \ const struct timespec32 *abs_timeout); } 460 AUE_MQ_TIMEDSEND NOSTD { int freebsd32_kmq_timedsend(int mqd, \ const char *msg_ptr, size_t msg_len,\ unsigned msg_prio, \ const struct timespec32 *abs_timeout);} 461 AUE_MQ_NOTIFY NOSTD { int freebsd32_kmq_notify(int mqd, \ const struct sigevent32 *sigev); } 462 AUE_MQ_UNLINK NOPROTO|NOSTD { int kmq_unlink(const char *path); } 463 AUE_NULL NOPROTO { int abort2(const char *why, int nargs, void **args); } 464 AUE_NULL NOPROTO { int thr_set_name(long id, const char *name); } 465 AUE_AIO_FSYNC STD { int freebsd32_aio_fsync(int op, \ struct aiocb32 *aiocbp); } 466 AUE_RTPRIO NOPROTO { int rtprio_thread(int function, \ lwpid_t lwpid, struct rtprio *rtp); } 467 AUE_NULL UNIMPL nosys 468 AUE_NULL UNIMPL nosys 469 AUE_NULL UNIMPL __getpath_fromfd 470 AUE_NULL UNIMPL __getpath_fromaddr 471 AUE_SCTP_PEELOFF NOPROTO|NOSTD { int sctp_peeloff(int sd, uint32_t name); } 472 AUE_SCTP_GENERIC_SENDMSG NOPROTO|NOSTD { int sctp_generic_sendmsg( \ int sd, void *msg, int mlen, \ struct sockaddr *to, __socklen_t tolen, \ struct sctp_sndrcvinfo *sinfo, int flags); } 473 AUE_SCTP_GENERIC_SENDMSG_IOV NOPROTO|NOSTD { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, \ struct sockaddr *to, __socklen_t tolen, \ struct sctp_sndrcvinfo *sinfo, int flags); } 474 AUE_SCTP_GENERIC_RECVMSG NOPROTO|NOSTD { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \ struct sockaddr * from, __socklen_t *fromlenaddr, \ struct sctp_sndrcvinfo *sinfo, int *msg_flags); } #ifdef PAD64_REQUIRED 475 AUE_PREAD STD { ssize_t freebsd32_pread(int fd, \ void *buf,size_t nbyte, \ int pad, \ uint32_t offset1, uint32_t offset2); } 476 AUE_PWRITE STD { ssize_t freebsd32_pwrite(int fd, \ const void *buf, size_t nbyte, \ int pad, \ uint32_t offset1, uint32_t offset2); } 477 AUE_MMAP STD { void *freebsd32_mmap(void *addr, \ size_t len, int prot, int flags, int fd, \ int pad, \ uint32_t pos1, uint32_t pos2); } 478 AUE_LSEEK STD { off_t freebsd32_lseek(int fd, \ int pad, \ uint32_t offset1, uint32_t offset2, \ int whence); } 479 AUE_TRUNCATE STD { int freebsd32_truncate(const char *path, \ int pad, \ uint32_t length1, uint32_t length2); } 480 AUE_FTRUNCATE STD { int freebsd32_ftruncate(int fd, \ int pad, \ uint32_t length1, uint32_t length2); } #else 475 AUE_PREAD STD { ssize_t freebsd32_pread(int fd, \ void *buf,size_t nbyte, \ uint32_t offset1, uint32_t offset2); } 476 AUE_PWRITE STD { ssize_t freebsd32_pwrite(int fd, \ const void *buf, size_t nbyte, \ uint32_t offset1, uint32_t offset2); } 477 AUE_MMAP STD { void *freebsd32_mmap(void *addr, \ size_t len, int prot, int flags, int fd, \ uint32_t pos1, uint32_t pos2); } 478 AUE_LSEEK STD { off_t freebsd32_lseek(int fd, \ uint32_t offset1, uint32_t offset2, \ int whence); } 479 AUE_TRUNCATE STD { int freebsd32_truncate(const char *path, \ uint32_t length1, uint32_t length2); } 480 AUE_FTRUNCATE STD { int freebsd32_ftruncate(int fd, \ uint32_t length1, uint32_t length2); } #endif 481 AUE_THR_KILL2 NOPROTO { int thr_kill2(pid_t pid, long id, int sig); } 482 AUE_SHMOPEN COMPAT12|NOPROTO { int shm_open( \ const char *path, int flags, mode_t mode); } 483 AUE_SHMUNLINK NOPROTO { int shm_unlink(const char *path); } 484 AUE_NULL NOPROTO { int cpuset(cpusetid_t *setid); } #ifdef PAD64_REQUIRED 485 AUE_NULL STD { int freebsd32_cpuset_setid(cpuwhich_t which, \ int pad, \ uint32_t id1, uint32_t id2, \ cpusetid_t setid); } #else 485 AUE_NULL STD { int freebsd32_cpuset_setid(cpuwhich_t which, \ uint32_t id1, uint32_t id2, \ cpusetid_t setid); } #endif 486 AUE_NULL STD { int freebsd32_cpuset_getid(cpulevel_t level, \ cpuwhich_t which, \ uint32_t id1, uint32_t id2, \ cpusetid_t *setid); } 487 AUE_NULL STD { int freebsd32_cpuset_getaffinity( \ cpulevel_t level, cpuwhich_t which, \ uint32_t id1, uint32_t id2, \ size_t cpusetsize, \ cpuset_t *mask); } 488 AUE_NULL STD { int freebsd32_cpuset_setaffinity( \ cpulevel_t level, cpuwhich_t which, \ uint32_t id1, uint32_t id2, \ size_t cpusetsize, \ const cpuset_t *mask); } 489 AUE_FACCESSAT NOPROTO { int faccessat(int fd, const char *path, \ int amode, int flag); } 490 AUE_FCHMODAT NOPROTO { int fchmodat(int fd, const char *path, \ mode_t mode, int flag); } 491 AUE_FCHOWNAT NOPROTO { int fchownat(int fd, const char *path, \ uid_t uid, gid_t gid, int flag); } 492 AUE_FEXECVE STD { int freebsd32_fexecve(int fd, \ uint32_t *argv, uint32_t *envv); } 493 AUE_FSTATAT COMPAT11 { int freebsd32_fstatat(int fd, \ const char *path, \ struct freebsd11_stat32 *buf, \ int flag); } 494 AUE_FUTIMESAT STD { int freebsd32_futimesat(int fd, \ const char *path, \ struct timeval *times); } 495 AUE_LINKAT NOPROTO { int linkat(int fd1, const char *path1, \ int fd2, const char *path2, int flag); } 496 AUE_MKDIRAT NOPROTO { int mkdirat(int fd, const char *path, \ mode_t mode); } 497 AUE_MKFIFOAT NOPROTO { int mkfifoat(int fd, const char *path, \ mode_t mode); } 498 AUE_MKNODAT COMPAT11|NOPROTO { int mknodat(int fd, \ const char *path, mode_t mode, \ uint32_t dev); } 499 AUE_OPENAT_RWTC NOPROTO { int openat(int fd, const char *path, \ int flag, mode_t mode); } 500 AUE_READLINKAT NOPROTO { ssize_t readlinkat(int fd, const char *path, \ char *buf, size_t bufsize); } 501 AUE_RENAMEAT NOPROTO { int renameat(int oldfd, const char *old, \ int newfd, const char *new); } 502 AUE_SYMLINKAT NOPROTO { int symlinkat(const char *path1, int fd, \ const char *path2); } 503 AUE_UNLINKAT NOPROTO { int unlinkat(int fd, const char *path, \ int flag); } 504 AUE_POSIX_OPENPT NOPROTO { int posix_openpt(int flags); } ; 505 is initialised by the kgssapi code, if present. 505 AUE_NULL UNIMPL gssd_syscall 506 AUE_JAIL_GET STD { int freebsd32_jail_get(struct iovec32 *iovp, \ unsigned int iovcnt, int flags); } 507 AUE_JAIL_SET STD { int freebsd32_jail_set(struct iovec32 *iovp, \ unsigned int iovcnt, int flags); } 508 AUE_JAIL_REMOVE NOPROTO { int jail_remove(int jid); } 509 AUE_CLOSEFROM NOPROTO { int closefrom(int lowfd); } 510 AUE_SEMCTL NOSTD { int freebsd32_semctl(int semid, int semnum, \ int cmd, union semun32 *arg); } 511 AUE_MSGCTL NOSTD { int freebsd32_msgctl(int msqid, int cmd, \ struct msqid_ds32 *buf); } 512 AUE_SHMCTL NOSTD { int freebsd32_shmctl(int shmid, int cmd, \ struct shmid_ds32 *buf); } 513 AUE_LPATHCONF NOPROTO { int lpathconf(const char *path, int name); } 514 AUE_NULL OBSOL cap_new 515 AUE_CAP_RIGHTS_GET NOPROTO { int __cap_rights_get(int version, \ int fd, cap_rights_t *rightsp); } 516 AUE_CAP_ENTER NOPROTO { int cap_enter(void); } 517 AUE_CAP_GETMODE NOPROTO { int cap_getmode(u_int *modep); } 518 AUE_PDFORK NOPROTO { int pdfork(int *fdp, int flags); } 519 AUE_PDKILL NOPROTO { int pdkill(int fd, int signum); } 520 AUE_PDGETPID NOPROTO { int pdgetpid(int fd, pid_t *pidp); } 521 AUE_PDWAIT UNIMPL pdwait4 522 AUE_SELECT STD { int freebsd32_pselect(int nd, fd_set *in, \ fd_set *ou, fd_set *ex, \ const struct timespec32 *ts, \ const sigset_t *sm); } 523 AUE_GETLOGINCLASS NOPROTO { int getloginclass(char *namebuf, \ size_t namelen); } 524 AUE_SETLOGINCLASS NOPROTO { int setloginclass(const char *namebuf); } 525 AUE_NULL NOPROTO { int rctl_get_racct(const void *inbufp, \ size_t inbuflen, void *outbufp, \ size_t outbuflen); } 526 AUE_NULL NOPROTO { int rctl_get_rules(const void *inbufp, \ size_t inbuflen, void *outbufp, \ size_t outbuflen); } 527 AUE_NULL NOPROTO { int rctl_get_limits(const void *inbufp, \ size_t inbuflen, void *outbufp, \ size_t outbuflen); } 528 AUE_NULL NOPROTO { int rctl_add_rule(const void *inbufp, \ size_t inbuflen, void *outbufp, \ size_t outbuflen); } 529 AUE_NULL NOPROTO { int rctl_remove_rule(const void *inbufp, \ size_t inbuflen, void *outbufp, \ size_t outbuflen); } #ifdef PAD64_REQUIRED 530 AUE_POSIX_FALLOCATE STD { int freebsd32_posix_fallocate(int fd, \ int pad, \ uint32_t offset1, uint32_t offset2,\ uint32_t len1, uint32_t len2); } 531 AUE_POSIX_FADVISE STD { int freebsd32_posix_fadvise(int fd, \ int pad, \ uint32_t offset1, uint32_t offset2,\ uint32_t len1, uint32_t len2, \ int advice); } 532 AUE_WAIT6 STD { int freebsd32_wait6(int idtype, int pad, \ uint32_t id1, uint32_t id2, \ int *status, int options, \ struct wrusage32 *wrusage, \ siginfo_t *info); } #else 530 AUE_POSIX_FALLOCATE STD { int freebsd32_posix_fallocate(int fd,\ uint32_t offset1, uint32_t offset2,\ uint32_t len1, uint32_t len2); } 531 AUE_POSIX_FADVISE STD { int freebsd32_posix_fadvise(int fd, \ uint32_t offset1, uint32_t offset2,\ uint32_t len1, uint32_t len2, \ int advice); } 532 AUE_WAIT6 STD { int freebsd32_wait6(int idtype, \ uint32_t id1, uint32_t id2, \ int *status, int options, \ struct wrusage32 *wrusage, \ siginfo_t *info); } #endif 533 AUE_CAP_RIGHTS_LIMIT NOPROTO { \ int cap_rights_limit(int fd, \ cap_rights_t *rightsp); } 534 AUE_CAP_IOCTLS_LIMIT STD { \ int freebsd32_cap_ioctls_limit(int fd, \ const uint32_t *cmds, size_t ncmds); } 535 AUE_CAP_IOCTLS_GET STD { \ ssize_t freebsd32_cap_ioctls_get(int fd, \ uint32_t *cmds, size_t maxcmds); } 536 AUE_CAP_FCNTLS_LIMIT NOPROTO { int cap_fcntls_limit(int fd, \ uint32_t fcntlrights); } 537 AUE_CAP_FCNTLS_GET NOPROTO { int cap_fcntls_get(int fd, \ uint32_t *fcntlrightsp); } 538 AUE_BINDAT NOPROTO { int bindat(int fd, int s, \ const struct sockaddr *name, \ int namelen); } 539 AUE_CONNECTAT NOPROTO { int connectat(int fd, int s, \ const struct sockaddr *name, \ int namelen); } 540 AUE_CHFLAGSAT NOPROTO { int chflagsat(int fd, const char *path, \ u_long flags, int atflag); } 541 AUE_ACCEPT NOPROTO { int accept4(int s, \ struct sockaddr *name, \ __socklen_t *anamelen, \ int flags); } 542 AUE_PIPE NOPROTO { int pipe2(int *fildes, int flags); } 543 AUE_AIO_MLOCK STD { int freebsd32_aio_mlock( \ struct aiocb32 *aiocbp); } #ifdef PAD64_REQUIRED 544 AUE_PROCCTL STD { int freebsd32_procctl(int idtype, int pad, \ uint32_t id1, uint32_t id2, int com, \ void *data); } #else 544 AUE_PROCCTL STD { int freebsd32_procctl(int idtype, \ uint32_t id1, uint32_t id2, int com, \ void *data); } #endif 545 AUE_POLL STD { int freebsd32_ppoll(struct pollfd *fds, \ u_int nfds, const struct timespec32 *ts, \ const sigset_t *set); } 546 AUE_FUTIMES STD { int freebsd32_futimens(int fd, \ struct timespec *times); } 547 AUE_FUTIMESAT STD { int freebsd32_utimensat(int fd, \ const char *path, \ struct timespec *times, int flag); } 548 AUE_NULL OBSOL numa_getaffinity 549 AUE_NULL OBSOL numa_setaffinity 550 AUE_FSYNC NOPROTO { int fdatasync(int fd); } 551 AUE_FSTAT STD { int freebsd32_fstat(int fd, \ struct stat32 *ub); } 552 AUE_FSTATAT STD { int freebsd32_fstatat(int fd, \ const char *path, struct stat32 *buf, \ int flag); } 553 AUE_FHSTAT STD { int freebsd32_fhstat( \ const struct fhandle *u_fhp, \ struct stat32 *sb); } 554 AUE_GETDIRENTRIES NOPROTO { ssize_t getdirentries( \ int fd, char *buf, size_t count, \ off_t *basep); } 555 AUE_STATFS NOPROTO { int statfs(const char *path, \ struct statfs32 *buf); } 556 AUE_FSTATFS NOPROTO { int fstatfs(int fd, struct statfs32 *buf); } 557 AUE_GETFSSTAT NOPROTO { int getfsstat(struct statfs32 *buf, \ long bufsize, int mode); } 558 AUE_FHSTATFS NOPROTO { int fhstatfs(const struct fhandle *u_fhp, \ struct statfs32 *buf); } #ifdef PAD64_REQUIRED 559 AUE_MKNODAT STD { int freebsd32_mknodat(int fd, \ const char *path, mode_t mode, \ int pad, uint32_t dev1, uint32_t dev2); } #else 559 AUE_MKNODAT STD { int freebsd32_mknodat(int fd, \ const char *path, mode_t mode, \ uint32_t dev1, uint32_t dev2); } #endif 560 AUE_KEVENT STD { int freebsd32_kevent(int fd, \ const struct kevent32 *changelist, \ int nchanges, \ struct kevent32 *eventlist, \ int nevents, \ const struct timespec32 *timeout); } 561 AUE_NULL STD { int freebsd32_cpuset_getdomain(cpulevel_t level, \ cpuwhich_t which, uint32_t id1, uint32_t id2, \ size_t domainsetsize, domainset_t *mask, \ int *policy); } 562 AUE_NULL STD { int freebsd32_cpuset_setdomain(cpulevel_t level, \ cpuwhich_t which, uint32_t id1, uint32_t id2, \ size_t domainsetsize, domainset_t *mask, \ int policy); } 563 AUE_NULL NOPROTO { int getrandom(void *buf, size_t buflen, \ unsigned int flags); } 564 AUE_NULL NOPROTO { int getfhat( int fd, char *path, \ struct fhandle *fhp, int flags); } 565 AUE_NULL NOPROTO { int fhlink( struct fhandle *fhp, const char *to ); } 566 AUE_NULL NOPROTO { int fhlinkat( struct fhandle *fhp, int tofd, \ const char *to); } 567 AUE_NULL NOPROTO { int fhreadlink( struct fhandle *fhp, char *buf, \ size_t bufsize); } 568 AUE_UNLINKAT NOPROTO { int funlinkat(int dfd, const char *path, int fd, \ int flag); } 569 AUE_NULL NOPROTO { ssize_t copy_file_range(int infd, \ off_t *inoffp, int outfd, off_t *outoffp, \ size_t len, unsigned int flags); } 570 AUE_SYSCTL STD { int freebsd32___sysctlbyname(const char *name, \ size_t namelen, void *old, uint32_t *oldlenp, \ void *new, size_t newlen); } 571 AUE_SHMOPEN NOPROTO { int shm_open2( \ const char *path, int flags, mode_t mode, \ int shmflags, const char *name); } 572 AUE_SHMRENAME NOPROTO { int shm_rename(const char *path_from, \ const char *path_to, int flags); } 573 AUE_NULL NOPROTO { int sigfastblock(int cmd, uint32_t *ptr); } +574 AUE_REALPATHAT NOPROTO { int __realpathat(int fd, const char *path, \ + char *buf, size_t size, int flags); } ; vim: syntax=off Index: head/sys/kern/syscalls.master =================================================================== --- head/sys/kern/syscalls.master (revision 358171) +++ head/sys/kern/syscalls.master (revision 358172) @@ -1,3224 +1,3233 @@ $FreeBSD$ ; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94 ; ; System call name/number master file. ; Processed to created init_sysent.c, syscalls.c and syscall.h. ; Columns: number audit type name alt{name,tag,rtyp}/comments ; number system call number, must be in order ; audit the audit event associated with the system call ; A value of AUE_NULL means no auditing, but it also means that ; there is no audit event for the call at this time. For the ; case where the event exists, but we don't want auditing, the ; event should be #defined to AUE_NULL in audit_kevents.h. ; type one of STD, OBSOL, UNIMPL, COMPAT, COMPAT4, COMPAT6, ; COMPAT7, COMPAT11, COMPAT12, NODEF, NOARGS, NOPROTO, NOSTD ; The COMPAT* options may be combined with one or more NO* ; options separated by '|' with no spaces (e.g. COMPAT|NOARGS) ; name pseudo-prototype of syscall routine ; If one of the following alts is different, then all appear: ; altname name of system call if different ; alttag name of args struct tag if different from [o]`name'"_args" ; altrtyp return type if not int (bogus - syscalls always return int) ; for UNIMPL/OBSOL, name continues with comments ; types: ; STD always included ; COMPAT included on COMPAT #ifdef ; COMPAT4 included on COMPAT_FREEBSD4 #ifdef (FreeBSD 4 compat) ; COMPAT6 included on COMPAT_FREEBSD6 #ifdef (FreeBSD 6 compat) ; COMPAT7 included on COMPAT_FREEBSD7 #ifdef (FreeBSD 7 compat) ; COMPAT10 included on COMPAT_FREEBSD10 #ifdef (FreeBSD 10 compat) ; COMPAT11 included on COMPAT_FREEBSD11 #ifdef (FreeBSD 11 compat) ; COMPAT12 included on COMPAT_FREEBSD12 #ifdef (FreeBSD 12 compat) ; OBSOL obsolete, not included in system, only specifies name ; UNIMPL not implemented, placeholder only ; NOSTD implemented but as a lkm that can be statically ; compiled in; sysent entry will be filled with lkmressys ; so the SYSCALL_MODULE macro works ; NOARGS same as STD except do not create structure in sys/sysproto.h ; NODEF same as STD except only have the entry in the syscall table ; added. Meaning - do not create structure or function ; prototype in sys/sysproto.h ; NOPROTO same as STD except do not create structure or ; function prototype in sys/sysproto.h. Does add a ; definition to syscall.h besides adding a sysent. ; NOTSTATIC syscall is loadable ; annotations: ; SAL 2.0 annotations are used to specify how system calls treat ; arguments that are passed using pointers. There are three basic ; annotations. ; ; _In_ Object pointed to will be read and not modified. ; _Out_ Object pointed to will be written and not read. ; _Inout_ Object pointed to will be written and read. ; ; These annotations are used alone when the pointer refers to a single ; object i.e. scalar types, structs, and pointers, and not NULL. Adding ; the _opt_ suffix, e.g. _In_opt_, implies that the pointer may also ; refer to NULL. ; ; For pointers to arrays, additional suffixes are added: ; ; _In_z_, _Out_z_, _Inout_z_: ; for a NUL terminated array e.g. a string. ; _In_reads_z_(n),_Out_writes_z_(n), _Inout_updates_z_(n): ; for a NUL terminated array e.g. a string, of known length n bytes. ; _In_reads_(n),_Out_writes_(n),_Inout_updates_(n): ; for an array of n elements. ; _In_reads_bytes_(n), _Out_writes_bytes_(n), _Inout_updates_bytes(n): ; for a buffer of n-bytes. ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master ; #ifdef's, etc. may be included, and are copied to the output files. #include #include #include ; Reserved/unimplemented system calls in the range 0-150 inclusive ; are reserved for use in future Berkeley releases. ; Additional system calls implemented in vendor and other ; redistributions should be placed in the reserved range at the end ; of the current calls. 0 AUE_NULL STD { int nosys(void); } syscall nosys_args int 1 AUE_EXIT STD { void sys_exit( int rval ); } exit sys_exit_args void 2 AUE_FORK STD { int fork(void); } 3 AUE_READ STD { ssize_t read( int fd, _Out_writes_bytes_(nbyte) void *buf, size_t nbyte ); } 4 AUE_WRITE STD { ssize_t write( int fd, _In_reads_bytes_(nbyte) const void *buf, size_t nbyte ); } 5 AUE_OPEN_RWTC STD { int open( _In_z_ const char *path, int flags, mode_t mode ); } ; XXX should be { int open(const char *path, int flags, ...); } ; but we're not ready for varargs. 6 AUE_CLOSE STD { int close( int fd ); } 7 AUE_WAIT4 STD { int wait4( int pid, _Out_opt_ int *status, int options, _Out_opt_ struct rusage *rusage ); } 8 AUE_CREAT COMPAT { int creat( _In_z_ const char *path, int mode ); } 9 AUE_LINK STD { int link( _In_z_ const char *path, _In_z_ const char *link ); } 10 AUE_UNLINK STD { int unlink( _In_z_ const char *path ); } 11 AUE_NULL OBSOL execv 12 AUE_CHDIR STD { int chdir( _In_z_ const char *path ); } 13 AUE_FCHDIR STD { int fchdir( int fd ); } 14 AUE_MKNOD COMPAT11 { int mknod( _In_z_ const char *path, int mode, uint32_t dev ); } 15 AUE_CHMOD STD { int chmod( _In_z_ const char *path, mode_t mode ); } 16 AUE_CHOWN STD { int chown( _In_z_ const char *path, int uid, int gid ); } 17 AUE_NULL STD { void *break( _In_ char *nsize ); } 18 AUE_GETFSSTAT COMPAT4 { int getfsstat( _Out_writes_bytes_opt_(bufsize) struct ostatfs *buf, long bufsize, int mode ); } 19 AUE_LSEEK COMPAT { long lseek( int fd, long offset, int whence ); } 20 AUE_GETPID STD { pid_t getpid(void); } 21 AUE_MOUNT STD { int mount( _In_z_ const char *type, _In_z_ const char *path, int flags, _In_opt_ void *data ); } 22 AUE_UMOUNT STD { int unmount( _In_z_ const char *path, int flags ); } 23 AUE_SETUID STD { int setuid( uid_t uid ); } 24 AUE_GETUID STD { uid_t getuid(void); } 25 AUE_GETEUID STD { uid_t geteuid(void); } 26 AUE_PTRACE STD { int ptrace( int req, pid_t pid, _Inout_opt_ caddr_t addr, int data ); } 27 AUE_RECVMSG STD { int recvmsg( int s, _Inout_ struct msghdr *msg, int flags ); } 28 AUE_SENDMSG STD { int sendmsg( int s, _In_ struct msghdr *msg, int flags ); } 29 AUE_RECVFROM STD { int recvfrom( int s, _Out_writes_bytes_(len) void *buf, size_t len, int flags, _Out_writes_bytes_opt_(*fromlenaddr) struct sockaddr *from, _Inout_opt_ __socklen_t *fromlenaddr ); } 30 AUE_ACCEPT STD { int accept( int s, _Out_writes_bytes_opt_(*anamelen) struct sockaddr *name, _Inout_opt_ __socklen_t *anamelen ); } 31 AUE_GETPEERNAME STD { int getpeername( int fdes, _Out_writes_bytes_(*alen) struct sockaddr *asa, _Inout_opt_ __socklen_t *alen ); } 32 AUE_GETSOCKNAME STD { int getsockname( int fdes, _Out_writes_bytes_(*alen) struct sockaddr *asa, _Inout_ __socklen_t *alen ); } 33 AUE_ACCESS STD { int access( _In_z_ const char *path, int amode ); } 34 AUE_CHFLAGS STD { int chflags( _In_z_ const char *path, u_long flags ); } 35 AUE_FCHFLAGS STD { int fchflags( int fd, u_long flags ); } 36 AUE_SYNC STD { int sync(void); } 37 AUE_KILL STD { int kill( int pid, int signum ); } 38 AUE_STAT COMPAT { int stat( _In_z_ const char *path, _Out_ struct ostat *ub ); } 39 AUE_GETPPID STD { pid_t getppid(void); } 40 AUE_LSTAT COMPAT { int lstat( _In_z_ const char *path, _Out_ struct ostat *ub ); } 41 AUE_DUP STD { int dup( u_int fd ); } 42 AUE_PIPE COMPAT10 { int pipe(void); } 43 AUE_GETEGID STD { gid_t getegid(void); } 44 AUE_PROFILE STD { int profil( _Out_writes_bytes_(size) char *samples, size_t size, size_t offset, u_int scale ); } 45 AUE_KTRACE STD { int ktrace( _In_z_ const char *fname, int ops, int facs, int pid ); } 46 AUE_SIGACTION COMPAT { int sigaction( int signum, _In_opt_ struct osigaction *nsa, _Out_opt_ struct osigaction *osa ); } 47 AUE_GETGID STD { gid_t getgid(void); } 48 AUE_SIGPROCMASK COMPAT { int sigprocmask( int how, osigset_t mask ); } ; XXX note nonstandard (bogus) calling convention - the libc stub passes ; us the mask, not a pointer to it, and we return the old mask as the ; (int) return value. 49 AUE_GETLOGIN STD { int getlogin( _Out_writes_z_(namelen) char *namebuf, u_int namelen ); } 50 AUE_SETLOGIN STD { int setlogin( _In_z_ const char *namebuf ); } 51 AUE_ACCT STD { int acct( _In_z_ const char *path ); } 52 AUE_SIGPENDING COMPAT { int sigpending(void); } 53 AUE_SIGALTSTACK STD { int sigaltstack( _In_opt_ stack_t *ss, _Out_opt_ stack_t *oss ); } 54 AUE_IOCTL STD { int ioctl( int fd, u_long com, _Inout_opt_ char *data ); } 55 AUE_REBOOT STD { int reboot( int opt ); } 56 AUE_REVOKE STD { int revoke( _In_z_ const char *path ); } 57 AUE_SYMLINK STD { int symlink( _In_z_ const char *path, _In_z_ const char *link ); } 58 AUE_READLINK STD { ssize_t readlink( _In_z_ const char *path, _Out_writes_z_(count) char *buf, size_t count ); } 59 AUE_EXECVE STD { int execve( _In_z_ const char *fname, _In_z_ char **argv, _In_z_ char **envv ); } 60 AUE_UMASK STD { int umask( mode_t newmask ); } 61 AUE_CHROOT STD { int chroot( _In_z_ const char *path ); } 62 AUE_FSTAT COMPAT { int fstat( int fd, _Out_ struct ostat *sb ); } 63 AUE_NULL COMPAT { int getkerninfo( int op, _Out_writes_bytes_opt( *size) char *where, _Inout_opt_ size_t *size, int arg ); } 64 AUE_NULL COMPAT { int getpagesize(void); } 65 AUE_MSYNC STD { int msync( _In_ void *addr, size_t len, int flags ); } 66 AUE_VFORK STD { int vfork(void); } 67 AUE_NULL OBSOL vread 68 AUE_NULL OBSOL vwrite 69 AUE_SBRK STD { int sbrk( int incr ); } 70 AUE_SSTK STD { int sstk( int incr ); } 71 AUE_MMAP COMPAT { void *mmap( _In_ void *addr, int len, int prot, int flags, int fd, long pos ); } 72 AUE_O_VADVISE COMPAT11 { int vadvise( int anom ); } 73 AUE_MUNMAP STD { int munmap( _In_ void *addr, size_t len ); } 74 AUE_MPROTECT STD { int mprotect( _In_ void *addr, size_t len, int prot ); } 75 AUE_MADVISE STD { int madvise( _In_ void *addr, size_t len, int behav ); } 76 AUE_NULL OBSOL vhangup 77 AUE_NULL OBSOL vlimit 78 AUE_MINCORE STD { int mincore( _In_ const void *addr, size_t len, _Out_writes_bytes_(len/PAGE_SIZE) char *vec ); } 79 AUE_GETGROUPS STD { int getgroups( u_int gidsetsize, _Out_writes_opt_(gidsetsize) gid_t *gidset ); } 80 AUE_SETGROUPS STD { int setgroups( u_int gidsetsize, _In_reads_(gidsetsize) gid_t *gidset ); } 81 AUE_GETPGRP STD { int getpgrp(void); } 82 AUE_SETPGRP STD { int setpgid( int pid, int pgid ); } 83 AUE_SETITIMER STD { int setitimer( u_int which, _In_ struct itimerval *itv, _Out_opt_ struct itimerval *oitv ); } 84 AUE_WAIT4 COMPAT { int wait(void); } 85 AUE_SWAPON STD { int swapon( _In_z_ const char *name ); } 86 AUE_GETITIMER STD { int getitimer( u_int which, _Out_ struct itimerval *itv ); } 87 AUE_SYSCTL COMPAT { int gethostname( _Out_writes_z_(len) char *hostname, u_int len ); } 88 AUE_SYSCTL COMPAT { int sethostname( _In_reads_z_(len) char *hostname, u_int len ); } 89 AUE_GETDTABLESIZE STD { int getdtablesize(void); } 90 AUE_DUP2 STD { int dup2( u_int from, u_int to ); } 91 AUE_NULL UNIMPL getdopt 92 AUE_FCNTL STD { int fcntl( int fd, int cmd, long arg ); } ; XXX should be { int fcntl(int fd, int cmd, ...); } ; but we're not ready for varargs. 93 AUE_SELECT STD { int select( int nd, _Inout_opt_ fd_set *in, _Inout_opt_ fd_set *ou, _Inout_opt_ fd_set *ex, _In_opt_ struct timeval *tv ); } 94 AUE_NULL UNIMPL setdopt 95 AUE_FSYNC STD { int fsync( int fd ); } 96 AUE_SETPRIORITY STD { int setpriority( int which, int who, int prio ); } 97 AUE_SOCKET STD { int socket( int domain, int type, int protocol ); } 98 AUE_CONNECT STD { int connect( int s, _In_reads_bytes_(namelen) const struct sockaddr *name, int namelen ); } 99 AUE_ACCEPT COMPAT { int accept( int s, _Out_writes_bytes_opt_(*anamelen) struct sockaddr *name, int *anamelen ); } 100 AUE_GETPRIORITY STD { int getpriority( int which, int who ); } 101 AUE_SEND COMPAT { int send( int s, _In_reads_bytes_(len) const void *buf, int len, int flags ); } 102 AUE_RECV COMPAT { int recv( int s, _Out_writes_bytes_(len) void *buf, int len, int flags ); } 103 AUE_SIGRETURN COMPAT { int sigreturn( _In_ struct osigcontext *sigcntxp ); } 104 AUE_BIND STD { int bind( int s, _In_reads_bytes_(namelen) const struct sockaddr *name, int namelen ); } 105 AUE_SETSOCKOPT STD { int setsockopt( int s, int level, int name, _In_reads_bytes_opt_(valsize) const void *val, int valsize ); } 106 AUE_LISTEN STD { int listen( int s, int backlog ); } 107 AUE_NULL OBSOL vtimes 108 AUE_NULL COMPAT { int sigvec( int signum, _In_opt_ struct sigvec *nsv, _Out_opt_ struct sigvec *osv ); } 109 AUE_NULL COMPAT { int sigblock( int mask ); } 110 AUE_NULL COMPAT { int sigsetmask( int mask ); } 111 AUE_NULL COMPAT { int sigsuspend( osigset_t mask ); } ; XXX note nonstandard (bogus) calling convention - the libc stub passes ; us the mask, not a pointer to it. 112 AUE_NULL COMPAT { int sigstack( _In_opt_ struct sigstack *nss, _Out_opt_ struct sigstack *oss ); } 113 AUE_RECVMSG COMPAT { int recvmsg( int s, _Inout_ struct omsghdr *msg, int flags ); } 114 AUE_SENDMSG COMPAT { int sendmsg( int s, _In_ const void *msg, int flags ); } 115 AUE_NULL OBSOL vtrace 116 AUE_GETTIMEOFDAY STD { int gettimeofday( _Out_ struct timeval *tp, _Out_opt_ struct timezone *tzp ); } 117 AUE_GETRUSAGE STD { int getrusage( int who, _Out_ struct rusage *rusage ); } 118 AUE_GETSOCKOPT STD { int getsockopt( int s, int level, int name, _Out_writes_bytes_opt_(*avalsize) void *val, _Inout_ int *avalsize ); } 119 AUE_NULL UNIMPL resuba (BSD/OS 2.x) 120 AUE_READV STD { int readv( int fd, _Inout_updates_(iovcnt) struct iovec *iovp, u_int iovcnt ); } 121 AUE_WRITEV STD { int writev( int fd, _In_reads_opt_(iovcnt) struct iovec *iovp, u_int iovcnt ); } 122 AUE_SETTIMEOFDAY STD { int settimeofday( _In_ struct timeval *tv, _In_opt_ struct timezone *tzp ); } 123 AUE_FCHOWN STD { int fchown( int fd, int uid, int gid ); } 124 AUE_FCHMOD STD { int fchmod( int fd, mode_t mode ); } 125 AUE_RECVFROM COMPAT|NOARGS { int recvfrom( int s, _Out_writes_(len) void *buf, size_t len, int flags, _Out_writes_bytes_(*fromlenaddr) struct sockaddr *from, _Inout_ int *fromlenaddr ); } recvfrom recvfrom_args int 126 AUE_SETREUID STD { int setreuid( int ruid, int euid ); } 127 AUE_SETREGID STD { int setregid( int rgid, int egid ); } 128 AUE_RENAME STD { int rename( _In_z_ const char *from, _In_z_ const char *to ); } 129 AUE_TRUNCATE COMPAT { int truncate( _In_z_ const char *path, long length ); } 130 AUE_FTRUNCATE COMPAT { int ftruncate( int fd, long length ); } 131 AUE_FLOCK STD { int flock( int fd, int how ); } 132 AUE_MKFIFO STD { int mkfifo( _In_z_ const char *path, mode_t mode ); } 133 AUE_SENDTO STD { int sendto( int s, _In_reads_bytes_(len) const void *buf, size_t len, int flags, _In_reads_bytes_opt_(tolen) const struct sockaddr *to, int tolen ); } 134 AUE_SHUTDOWN STD { int shutdown( int s, int how ); } 135 AUE_SOCKETPAIR STD { int socketpair( int domain, int type, int protocol, _Out_writes_(2) int *rsv ); } 136 AUE_MKDIR STD { int mkdir( _In_z_ const char *path, mode_t mode ); } 137 AUE_RMDIR STD { int rmdir( _In_z_ const char *path ); } 138 AUE_UTIMES STD { int utimes( _In_z_ const char *path, _In_ struct timeval *tptr ); } 139 AUE_NULL OBSOL 4.2 sigreturn 140 AUE_ADJTIME STD { int adjtime( _In_ struct timeval *delta, _Out_opt_ struct timeval *olddelta ); } 141 AUE_GETPEERNAME COMPAT { int getpeername( int fdes, _Out_writes_bytes_(*alen) struct sockaddr *asa, _Inout_opt_ int *alen ); } 142 AUE_SYSCTL COMPAT { long gethostid(void); } 143 AUE_SYSCTL COMPAT { int sethostid( long hostid ); } 144 AUE_GETRLIMIT COMPAT { int getrlimit( u_int which, _Out_ struct orlimit *rlp ); } 145 AUE_SETRLIMIT COMPAT { int setrlimit( u_int which, _Out_ struct orlimit *rlp ); } 146 AUE_KILLPG COMPAT { int killpg( int pgid, int signum ); } 147 AUE_SETSID STD { int setsid(void); } 148 AUE_QUOTACTL STD { int quotactl( _In_z_ const char *path, int cmd, int uid, _In_ void *arg ); } 149 AUE_O_QUOTA COMPAT { int quota(void); } 150 AUE_GETSOCKNAME COMPAT|NOARGS { int getsockname( int fdec, _Out_writes_bytes_(*alen) struct sockaddr *asa, _Inout_ int *alen ); } getsockname getsockname_args int ; Syscalls 151-180 inclusive are reserved for vendor-specific ; system calls. (This includes various calls added for compatibity ; with other Unix variants.) ; Some of these calls are now supported by BSD. 151 AUE_NULL UNIMPL sem_lock (BSD/OS 2.x) 152 AUE_NULL UNIMPL sem_wakeup (BSD/OS 2.x) 153 AUE_NULL UNIMPL asyncdaemon (BSD/OS 2.x) ; 154 is initialised by the NLM code, if present. 154 AUE_NULL NOSTD { int nlm_syscall( int debug_level, int grace_period, int addr_count, _In_reads_(addr_count) char **addrs ); } ; 155 is initialized by the NFS code, if present. 155 AUE_NFS_SVC NOSTD { int nfssvc( int flag, _In_ void *argp ); } 156 AUE_GETDIRENTRIES COMPAT { int getdirentries( int fd, _Out_writes_bytes_(count) char *buf, u_int count, _Out_ long *basep ); } 157 AUE_STATFS COMPAT4 { int statfs( _In_z_ const char *path, _Out_ struct ostatfs *buf ); } 158 AUE_FSTATFS COMPAT4 { int fstatfs( int fd, _Out_ struct ostatfs *buf ); } 159 AUE_NULL UNIMPL nosys 160 AUE_LGETFH STD { int lgetfh( _In_z_ const char *fname, _Out_ struct fhandle *fhp ); } 161 AUE_NFS_GETFH STD { int getfh( _In_z_ const char *fname, _Out_ struct fhandle *fhp ); } 162 AUE_SYSCTL COMPAT4 { int getdomainname( _Out_writes_z_(len) char *domainname, int len ); } 163 AUE_SYSCTL COMPAT4 { int setdomainname( _In_reads_z_(len) char *domainname, int len ); } 164 AUE_NULL COMPAT4 { int uname( _Out_ struct utsname *name ); } 165 AUE_SYSARCH STD { int sysarch( int op, _In_z_ char *parms ); } 166 AUE_RTPRIO STD { int rtprio( int function, pid_t pid, _Inout_ struct rtprio *rtp ); } 167 AUE_NULL UNIMPL nosys 168 AUE_NULL UNIMPL nosys 169 AUE_SEMSYS NOSTD { int semsys( int which, int a2, int a3, int a4, int a5 ); } ; XXX should be { int semsys(int which, ...); } 170 AUE_MSGSYS NOSTD { int msgsys( int which, int a2, int a3, int a4, int a5, int a6 ); } ; XXX should be { int msgsys(int which, ...); } 171 AUE_SHMSYS NOSTD { int shmsys( int which, int a2, int a3, int a4 ); } ; XXX should be { int shmsys(int which, ...); } 172 AUE_NULL UNIMPL nosys 173 AUE_PREAD COMPAT6 { ssize_t pread( int fd, _Out_writes_bytes_(nbyte) void *buf, size_t nbyte, int pad, off_t offset ); } 174 AUE_PWRITE COMPAT6 { ssize_t pwrite( int fd, _In_reads_bytes_(nbyte) const void *buf, size_t nbyte, int pad, off_t offset ); } 175 AUE_SETFIB STD { int setfib( int fibnum ); } 176 AUE_NTP_ADJTIME STD { int ntp_adjtime( _Inout_ struct timex *tp ); } 177 AUE_NULL UNIMPL sfork (BSD/OS 2.x) 178 AUE_NULL UNIMPL getdescriptor (BSD/OS 2.x) 179 AUE_NULL UNIMPL setdescriptor (BSD/OS 2.x) 180 AUE_NULL UNIMPL nosys ; Syscalls 181-199 are used by/reserved for BSD 181 AUE_SETGID STD { int setgid( gid_t gid ); } 182 AUE_SETEGID STD { int setegid( gid_t egid ); } 183 AUE_SETEUID STD { int seteuid( uid_t euid ); } 184 AUE_NULL OBSOL lfs_bmapv 185 AUE_NULL OBSOL lfs_markv 186 AUE_NULL OBSOL lfs_segclean 187 AUE_NULL OBSOL lfs_segwait 188 AUE_STAT COMPAT11 { int stat( _In_z_ const char *path, _Out_ struct freebsd11_stat *ub ); } 189 AUE_FSTAT COMPAT11 { int fstat( int fd, _Out_ struct freebsd11_stat *sb ); } 190 AUE_LSTAT COMPAT11 { int lstat( _In_z_ const char *path, _Out_ struct freebsd11_stat *ub ); } 191 AUE_PATHCONF STD { int pathconf( _In_z_ const char *path, int name ); } 192 AUE_FPATHCONF STD { int fpathconf( int fd, int name ); } 193 AUE_NULL UNIMPL nosys 194 AUE_GETRLIMIT STD { int getrlimit( u_int which, _Out_ struct rlimit *rlp ); } getrlimit __getrlimit_args int 195 AUE_SETRLIMIT STD { int setrlimit( u_int which, _In_ struct rlimit *rlp ); } setrlimit __setrlimit_args int 196 AUE_GETDIRENTRIES COMPAT11 { int getdirentries( int fd, _Out_writes_bytes_(count) char *buf, u_int count, _Out_ long *basep ); } 197 AUE_MMAP COMPAT6 { void *mmap( _In_ void *addr, size_t len, int prot, int flags, int fd, int pad, off_t pos ); } 198 AUE_NULL NOPROTO { int nosys(void); } __syscall __syscall_args int 199 AUE_LSEEK COMPAT6 { off_t lseek( int fd, int pad, off_t offset, int whence ); } 200 AUE_TRUNCATE COMPAT6 { int truncate( _In_z_ const char *path, int pad, off_t length ); } 201 AUE_FTRUNCATE COMPAT6 { int ftruncate( int fd, int pad, off_t length ); } 202 AUE_SYSCTL STD { int __sysctl( _In_reads_(namelen) int *name, u_int namelen, _Out_writes_bytes_opt_(*oldlenp) void *old, _Inout_opt_ size_t *oldlenp, _In_reads_bytes_opt_(newlen) const void *new, size_t newlen ); } __sysctl sysctl_args int 203 AUE_MLOCK STD { int mlock( _In_ const void *addr, size_t len ); } 204 AUE_MUNLOCK STD { int munlock( _In_ const void *addr, size_t len ); } 205 AUE_UNDELETE STD { int undelete( _In_z_ const char *path ); } 206 AUE_FUTIMES STD { int futimes( int fd, _In_reads_(2) struct timeval *tptr ); } 207 AUE_GETPGID STD { int getpgid( pid_t pid ); } 208 AUE_NULL UNIMPL nosys 209 AUE_POLL STD { int poll( _Inout_updates_(nfds) struct pollfd *fds, u_int nfds, int timeout ); } ; ; The following are reserved for loadable syscalls ; 210 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 211 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 212 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 213 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 214 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 215 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 216 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 217 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 218 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 219 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int 220 AUE_SEMCTL COMPAT7|NOSTD { int __semctl( int semid, int semnum, int cmd, union semun_old *arg ); } 221 AUE_SEMGET NOSTD { int semget( key_t key, int nsems, int semflg ); } 222 AUE_SEMOP NOSTD { int semop( int semid, _In_reads_(nsops) struct sembuf *sops, size_t nsops ); } 223 AUE_NULL OBSOL semconfig 224 AUE_MSGCTL COMPAT7|NOSTD { int msgctl( int msqid, int cmd, struct msqid_ds_old *buf ); } 225 AUE_MSGGET NOSTD { int msgget( key_t key, int msgflg ); } 226 AUE_MSGSND NOSTD { int msgsnd( int msqid, _In_reads_bytes_(msgsz) const void *msgp, size_t msgsz, int msgflg ); } 227 AUE_MSGRCV NOSTD { ssize_t msgrcv( int msqid, _Out_writes_bytes_(msgsz) void *msgp, size_t msgsz, long msgtyp, int msgflg ); } 228 AUE_SHMAT NOSTD { void *shmat( int shmid, _In_ const void *shmaddr, int shmflg ); } 229 AUE_SHMCTL COMPAT7|NOSTD { int shmctl( int shmid, int cmd, struct shmid_ds_old *buf ); } 230 AUE_SHMDT NOSTD { int shmdt( _In_ const void *shmaddr ); } 231 AUE_SHMGET NOSTD { int shmget( key_t key, size_t size, int shmflg ); } 232 AUE_NULL STD { int clock_gettime( clockid_t clock_id, _Out_ struct timespec *tp ); } 233 AUE_CLOCK_SETTIME STD { int clock_settime( clockid_t clock_id, _In_ const struct timespec *tp ); } 234 AUE_NULL STD { int clock_getres( clockid_t clock_id, _Out_ struct timespec *tp ); } 235 AUE_NULL STD { int ktimer_create( clockid_t clock_id, _In_ struct sigevent *evp, _Out_ int *timerid ); } 236 AUE_NULL STD { int ktimer_delete( int timerid ); } 237 AUE_NULL STD { int ktimer_settime( int timerid, int flags, _In_ const struct itimerspec *value, _Out_opt_ struct itimerspec *ovalue ); } 238 AUE_NULL STD { int ktimer_gettime( int timerid, _Out_ struct itimerspec *value ); } 239 AUE_NULL STD { int ktimer_getoverrun( int timerid ); } 240 AUE_NULL STD { int nanosleep( _In_ const struct timespec *rqtp, _Out_opt_ struct timespec *rmtp ); } 241 AUE_NULL STD { int ffclock_getcounter( _Out_ ffcounter *ffcount ); } 242 AUE_NULL STD { int ffclock_setestimate( _In_ struct ffclock_estimate *cest ); } 243 AUE_NULL STD { int ffclock_getestimate( _Out_ struct ffclock_estimate *cest ); } 244 AUE_NULL STD { int clock_nanosleep( clockid_t clock_id, int flags, _In_ const struct timespec *rqtp, _Out_opt_ struct timespec *rmtp ); } 245-246 AUE_NULL UNIMPL nosys 247 AUE_NULL STD { int clock_getcpuclockid2( id_t id, int which, _Out_ clockid_t *clock_id ); } 248 AUE_NULL STD { int ntp_gettime( _Out_ struct ntptimeval *ntvp ); } 249 AUE_NULL UNIMPL nosys ; syscall numbers initially used in OpenBSD 250 AUE_MINHERIT STD { int minherit( _In_ void *addr, size_t len, int inherit ); } 251 AUE_RFORK STD { int rfork( int flags ); } 252 AUE_POLL OBSOL openbsd_poll 253 AUE_ISSETUGID STD { int issetugid(void); } 254 AUE_LCHOWN STD { int lchown( _In_z_ const char *path, int uid, int gid ); } 255 AUE_AIO_READ STD { int aio_read( _Inout_ struct aiocb *aiocbp ); } 256 AUE_AIO_WRITE STD { int aio_write( _Inout_ struct aiocb *aiocbp ); } 257 AUE_LIO_LISTIO STD { int lio_listio( int mode, _Inout_updates_(nent) struct aiocb * const *acb_list, int nent, _In_opt_ struct sigevent *sig ); } 258-271 AUE_NULL UNIMPL nosys 272 AUE_O_GETDENTS COMPAT11 { int getdents( int fd, _Out_writes_bytes_(count) char *buf, size_t count ); } 273 AUE_NULL UNIMPL nosys 274 AUE_LCHMOD STD { int lchmod( _In_z_ const char *path, mode_t mode ); } 275 AUE_NULL OBSOL netbsd_lchown 276 AUE_LUTIMES STD { int lutimes( _In_z_ const char *path, _In_ struct timeval *tptr ); } 277 AUE_NULL OBSOL netbsd_msync 278 AUE_STAT COMPAT11 { int nstat( _In_z_ const char *path, _Out_ struct nstat *ub ); } 279 AUE_FSTAT COMPAT11 { int nfstat( int fd, _Out_ struct nstat *sb ); } 280 AUE_LSTAT COMPAT11 { int nlstat( _In_z_ const char *path, _Out_ struct nstat *ub ); } 281-288 AUE_NULL UNIMPL nosys 289 AUE_PREADV STD { ssize_t preadv( int fd, _In_reads_(iovcnt) struct iovec *iovp, u_int iovcnt, off_t offset ); } 290 AUE_PWRITEV STD { ssize_t pwritev( int fd, _In_reads_(iovcnt) struct iovec *iovp, u_int iovcnt, off_t offset ); } 291-296 AUE_NULL UNIMPL nosys 297 AUE_FHSTATFS COMPAT4 { int fhstatfs( _In_ const struct fhandle *u_fhp, _Out_ struct ostatfs *buf ); } 298 AUE_FHOPEN STD { int fhopen( _In_ const struct fhandle *u_fhp, int flags ); } 299 AUE_FHSTAT COMPAT11 { int fhstat( _In_ const struct fhandle *u_fhp, _Out_ struct freebsd11_stat *sb ); } 300 AUE_NULL STD { int modnext( int modid ); } 301 AUE_NULL STD { int modstat( int modid, _Out_ struct module_stat *stat ); } 302 AUE_NULL STD { int modfnext( int modid ); } 303 AUE_NULL STD { int modfind( _In_z_ const char *name ); } 304 AUE_MODLOAD STD { int kldload( _In_z_ const char *file ); } 305 AUE_MODUNLOAD STD { int kldunload( int fileid ); } 306 AUE_NULL STD { int kldfind( _In_z_ const char *file ); } 307 AUE_NULL STD { int kldnext( int fileid ); } 308 AUE_NULL STD { int kldstat( int fileid, _Out_ struct kld_file_stat *stat ); } 309 AUE_NULL STD { int kldfirstmod( int fileid ); } 310 AUE_GETSID STD { int getsid( pid_t pid ); } 311 AUE_SETRESUID STD { int setresuid( uid_t ruid, uid_t euid, uid_t suid ); } 312 AUE_SETRESGID STD { int setresgid( gid_t rgid, gid_t egid, gid_t sgid ); } 313 AUE_NULL OBSOL signanosleep 314 AUE_AIO_RETURN STD { ssize_t aio_return( _Inout_ struct aiocb *aiocbp ); } 315 AUE_AIO_SUSPEND STD { int aio_suspend( _Inout_updates_(nent) struct aiocb * const * aiocbp, int nent, _In_opt_ const struct timespec *timeout ); } 316 AUE_AIO_CANCEL STD { int aio_cancel( int fd, _In_opt_ struct aiocb *aiocbp ); } 317 AUE_AIO_ERROR STD { int aio_error( _In_ struct aiocb *aiocbp ); } 318 AUE_AIO_READ COMPAT6 { int aio_read( _Inout_ struct oaiocb *aiocbp ); } 319 AUE_AIO_WRITE COMPAT6 { int aio_write( _Inout_ struct oaiocb *aiocbp ); } 320 AUE_LIO_LISTIO COMPAT6 { int lio_listio( int mode, _Inout_updates_(nent) struct oaiocb * const *acb_list, int nent, _In_opt_ struct osigevent *sig ); } 321 AUE_NULL STD { int yield(void); } 322 AUE_NULL OBSOL thr_sleep 323 AUE_NULL OBSOL thr_wakeup 324 AUE_MLOCKALL STD { int mlockall( int how ); } 325 AUE_MUNLOCKALL STD { int munlockall(void); } 326 AUE_GETCWD STD { int __getcwd( _Out_writes_z_(buflen) char *buf, size_t buflen ); } 327 AUE_NULL STD { int sched_setparam( pid_t pid, _In_ const struct sched_param *param ); } 328 AUE_NULL STD { int sched_getparam( pid_t pid, _Out_ struct sched_param *param ); } 329 AUE_NULL STD { int sched_setscheduler( pid_t pid, int policy, _In_ const struct sched_param *param ); } 330 AUE_NULL STD { int sched_getscheduler( pid_t pid ); } 331 AUE_NULL STD { int sched_yield(void); } 332 AUE_NULL STD { int sched_get_priority_max( int policy ); } 333 AUE_NULL STD { int sched_get_priority_min( int policy ); } 334 AUE_NULL STD { int sched_rr_get_interval( pid_t pid, _Out_ struct timespec *interval ); } 335 AUE_NULL STD { int utrace( _In_reads_bytes_(len) const void *addr, size_t len ); } 336 AUE_SENDFILE COMPAT4 { int sendfile( int fd, int s, off_t offset, size_t nbytes, _In_opt_ struct sf_hdtr *hdtr, _Out_opt_ off_t *sbytes, int flags ); } 337 AUE_NULL STD { int kldsym( int fileid, int cmd, _In_ void *data ); } 338 AUE_JAIL STD { int jail( _In_ struct jail *jail ); } 339 AUE_NULL NOSTD|NOTSTATIC { int nnpfs_syscall( int operation, char *a_pathP, int a_opcode, void *a_paramsP, int a_followSymlinks ); } 340 AUE_SIGPROCMASK STD { int sigprocmask( int how, _In_opt_ const sigset_t *set, _Out_opt_ sigset_t *oset ); } 341 AUE_SIGSUSPEND STD { int sigsuspend( _In_ const sigset_t *sigmask ); } 342 AUE_SIGACTION COMPAT4 { int sigaction( int sig, _In_opt_ const struct sigaction *act, _Out_opt_ struct sigaction *oact ); } 343 AUE_SIGPENDING STD { int sigpending( _In_ sigset_t *set ); } 344 AUE_SIGRETURN COMPAT4 { int sigreturn( _In_ const struct ucontext4 *sigcntxp ); } 345 AUE_SIGWAIT STD { int sigtimedwait( _In_ const sigset_t *set, _Out_opt_ siginfo_t *info, _In_opt_ const struct timespec *timeout ); } 346 AUE_NULL STD { int sigwaitinfo( _In_ const sigset_t *set, _Out_opt_ siginfo_t *info ); } 347 AUE_ACL_GET_FILE STD { int __acl_get_file( _In_z_ const char *path, acl_type_t type, _Out_ struct acl *aclp ); } 348 AUE_ACL_SET_FILE STD { int __acl_set_file( _In_z_ const char *path, acl_type_t type, _In_ struct acl *aclp ); } 349 AUE_ACL_GET_FD STD { int __acl_get_fd( int filedes, acl_type_t type, _Out_ struct acl *aclp ); } 350 AUE_ACL_SET_FD STD { int __acl_set_fd( int filedes, acl_type_t type, _In_ struct acl *aclp ); } 351 AUE_ACL_DELETE_FILE STD { int __acl_delete_file( _In_z_ const char *path, acl_type_t type ); } 352 AUE_ACL_DELETE_FD STD { int __acl_delete_fd( int filedes, acl_type_t type ); } 353 AUE_ACL_CHECK_FILE STD { int __acl_aclcheck_file( _In_z_ const char *path, acl_type_t type, _In_ struct acl *aclp ); } 354 AUE_ACL_CHECK_FD STD { int __acl_aclcheck_fd( int filedes, acl_type_t type, _In_ struct acl *aclp ); } 355 AUE_EXTATTRCTL STD { int extattrctl( _In_z_ const char *path, int cmd, _In_z_opt_ const char *filename, int attrnamespace, _In_z_ const char *attrname ); } 356 AUE_EXTATTR_SET_FILE STD { ssize_t extattr_set_file( _In_z_ const char *path, int attrnamespace, _In_z_ const char *attrname, _In_reads_bytes_(nbytes) void *data, size_t nbytes ); } 357 AUE_EXTATTR_GET_FILE STD { ssize_t extattr_get_file( _In_z_ const char *path, int attrnamespace, _In_z_ const char *attrname, _Out_writes_bytes_(nbytes) void *data, size_t nbytes ); } 358 AUE_EXTATTR_DELETE_FILE STD { int extattr_delete_file( _In_z_ const char *path, int attrnamespace, _In_z_ const char *attrname ); } 359 AUE_AIO_WAITCOMPLETE STD { ssize_t aio_waitcomplete( _Outptr_result_maybenull_ struct aiocb **aiocbp, _In_opt_ struct timespec *timeout ); } 360 AUE_GETRESUID STD { int getresuid( _Out_opt_ uid_t *ruid, _Out_opt_ uid_t *euid, _Out_opt_ uid_t *suid ); } 361 AUE_GETRESGID STD { int getresgid( _Out_opt_ gid_t *rgid, _Out_opt_ gid_t *egid, _Out_opt_ gid_t *sgid ); } 362 AUE_KQUEUE STD { int kqueue(void); } 363 AUE_KEVENT COMPAT11 { int kevent( int fd, _In_reads_opt_(nchanges) struct kevent_freebsd11 *changelist, int nchanges, _Out_writes_opt_(nevents) struct kevent_freebsd11 *eventlist, int nevents, _In_opt_ const struct timespec *timeout ); } 364 AUE_NULL OBSOL __cap_get_proc 365 AUE_NULL OBSOL __cap_set_proc 366 AUE_NULL OBSOL __cap_get_fd 367 AUE_NULL OBSOL __cap_get_file 368 AUE_NULL OBSOL __cap_set_fd 369 AUE_NULL OBSOL __cap_set_file 370 AUE_NULL UNIMPL nosys 371 AUE_EXTATTR_SET_FD STD { ssize_t extattr_set_fd( int fd, int attrnamespace, _In_z_ const char *attrname, _In_reads_bytes_(nbytes) void *data, size_t nbytes ); } 372 AUE_EXTATTR_GET_FD STD { ssize_t extattr_get_fd( int fd, int attrnamespace, _In_z_ const char *attrname, _Out_writes_bytes_(nbytes) void *data, size_t nbytes ); } 373 AUE_EXTATTR_DELETE_FD STD { int extattr_delete_fd( int fd, int attrnamespace, _In_z_ const char *attrname ); } 374 AUE_SETUGID STD { int __setugid( int flag ); } 375 AUE_NULL OBSOL nfsclnt 376 AUE_EACCESS STD { int eaccess( _In_z_ const char *path, int amode ); } 377 AUE_NULL NOSTD|NOTSTATIC { int afs3_syscall( long syscall, long parm1, long parm2, long parm3, long parm4, long parm5, long parm6 ); } 378 AUE_NMOUNT STD { int nmount( _In_reads_(iovcnt) struct iovec *iovp, unsigned int iovcnt, int flags ); } 379 AUE_NULL OBSOL kse_exit 380 AUE_NULL OBSOL kse_wakeup 381 AUE_NULL OBSOL kse_create 382 AUE_NULL OBSOL kse_thr_interrupt 383 AUE_NULL OBSOL kse_release 384 AUE_NULL STD { int __mac_get_proc( _In_ struct mac *mac_p ); } 385 AUE_NULL STD { int __mac_set_proc( _In_ struct mac *mac_p ); } 386 AUE_NULL STD { int __mac_get_fd( int fd, _In_ struct mac *mac_p ); } 387 AUE_NULL STD { int __mac_get_file( _In_z_ const char *path_p, _In_ struct mac *mac_p ); } 388 AUE_NULL STD { int __mac_set_fd( int fd, _In_ struct mac *mac_p ); } 389 AUE_NULL STD { int __mac_set_file( _In_z_ const char *path_p, _In_ struct mac *mac_p ); } 390 AUE_NULL STD { int kenv( int what, _In_z_opt_ const char *name, _Inout_updates_opt_(len) char *value, int len ); } 391 AUE_LCHFLAGS STD { int lchflags( _In_z_ const char *path, u_long flags ); } 392 AUE_NULL STD { int uuidgen( _Out_writes_(count) struct uuid *store, int count ); } 393 AUE_SENDFILE STD { int sendfile( int fd, int s, off_t offset, size_t nbytes, _In_opt_ struct sf_hdtr *hdtr, _Out_opt_ off_t *sbytes, int flags ); } 394 AUE_NULL STD { int mac_syscall( _In_z_ const char *policy, int call, _In_opt_ void *arg ); } 395 AUE_GETFSSTAT COMPAT11 { int getfsstat( _Out_writes_bytes_opt_(bufsize) struct freebsd11_statfs *buf, long bufsize, int mode ); } 396 AUE_STATFS COMPAT11 { int statfs( _In_z_ const char *path, _Out_ struct freebsd11_statfs *buf ); } 397 AUE_FSTATFS COMPAT11 { int fstatfs( int fd, _Out_ struct freebsd11_statfs *buf ); } 398 AUE_FHSTATFS COMPAT11 { int fhstatfs( _In_ const struct fhandle *u_fhp, _Out_ struct freebsd11_statfs *buf ); } 399 AUE_NULL UNIMPL nosys 400 AUE_SEMCLOSE NOSTD { int ksem_close( semid_t id ); } 401 AUE_SEMPOST NOSTD { int ksem_post( semid_t id ); } 402 AUE_SEMWAIT NOSTD { int ksem_wait( semid_t id ); } 403 AUE_SEMTRYWAIT NOSTD { int ksem_trywait( semid_t id ); } 404 AUE_SEMINIT NOSTD { int ksem_init( _Out_ semid_t *idp, unsigned int value ); } 405 AUE_SEMOPEN NOSTD { int ksem_open( _Out_ semid_t *idp, _In_z_ const char *name, int oflag, mode_t mode, unsigned int value ); } 406 AUE_SEMUNLINK NOSTD { int ksem_unlink( _In_z_ const char *name ); } 407 AUE_SEMGETVALUE NOSTD { int ksem_getvalue( semid_t id, _Out_ int *val ); } 408 AUE_SEMDESTROY NOSTD { int ksem_destroy( semid_t id ); } 409 AUE_NULL STD { int __mac_get_pid( pid_t pid, _In_ struct mac *mac_p ); } 410 AUE_NULL STD { int __mac_get_link( _In_z_ const char *path_p, _In_ struct mac *mac_p ); } 411 AUE_NULL STD { int __mac_set_link( _In_z_ const char *path_p, _In_ struct mac *mac_p ); } 412 AUE_EXTATTR_SET_LINK STD { ssize_t extattr_set_link( _In_z_ const char *path, int attrnamespace, _In_z_ const char *attrname, _In_reads_bytes_(nbytes) void *data, size_t nbytes ); } 413 AUE_EXTATTR_GET_LINK STD { ssize_t extattr_get_link( _In_z_ const char *path, int attrnamespace, _In_z_ const char *attrname, _Out_writes_bytes_(nbytes) void *data, size_t nbytes ); } 414 AUE_EXTATTR_DELETE_LINK STD { int extattr_delete_link( _In_z_ const char *path, int attrnamespace, _In_z_ const char *attrname ); } 415 AUE_NULL STD { int __mac_execve( _In_z_ const char *fname, _In_ char **argv, _In_ char **envv, _In_ struct mac *mac_p ); } 416 AUE_SIGACTION STD { int sigaction( int sig, _In_opt_ const struct sigaction *act, _Out_opt_ struct sigaction *oact ); } 417 AUE_SIGRETURN STD { int sigreturn( _In_ const struct __ucontext *sigcntxp ); } 418 AUE_NULL UNIMPL __xstat 419 AUE_NULL UNIMPL __xfstat 420 AUE_NULL UNIMPL __xlstat 421 AUE_NULL STD { int getcontext( _Out_ struct __ucontext *ucp ); } 422 AUE_NULL STD { int setcontext( _In_ const struct __ucontext *ucp ); } 423 AUE_NULL STD { int swapcontext( _Out_ struct __ucontext *oucp, _In_ const struct __ucontext *ucp ); } 424 AUE_SWAPOFF STD { int swapoff( _In_z_ const char *name ); } 425 AUE_ACL_GET_LINK STD { int __acl_get_link( _In_z_ const char *path, acl_type_t type, _Out_ struct acl *aclp ); } 426 AUE_ACL_SET_LINK STD { int __acl_set_link( _In_z_ const char *path, acl_type_t type, _In_ struct acl *aclp ); } 427 AUE_ACL_DELETE_LINK STD { int __acl_delete_link( _In_z_ const char *path, acl_type_t type ); } 428 AUE_ACL_CHECK_LINK STD { int __acl_aclcheck_link( _In_z_ const char *path, acl_type_t type, _In_ struct acl *aclp ); } 429 AUE_SIGWAIT STD { int sigwait( _In_ const sigset_t *set, _Out_ int *sig ); } 430 AUE_THR_CREATE STD { int thr_create( _In_ ucontext_t *ctx, _Out_ long *id, int flags ); } 431 AUE_THR_EXIT STD { void thr_exit( _Out_opt_ long *state ); } 432 AUE_NULL STD { int thr_self( _Out_ long *id ); } 433 AUE_THR_KILL STD { int thr_kill( long id, int sig ); } 434-435 AUE_NULL UNIMPL nosys 436 AUE_JAIL_ATTACH STD { int jail_attach( int jid ); } 437 AUE_EXTATTR_LIST_FD STD { ssize_t extattr_list_fd( int fd, int attrnamespace, _Out_writes_bytes_opt_(nbytes) void *data, size_t nbytes ); } 438 AUE_EXTATTR_LIST_FILE STD { ssize_t extattr_list_file( _In_z_ const char *path, int attrnamespace, _Out_writes_bytes_opt_(nbytes) void *data, size_t nbytes ); } 439 AUE_EXTATTR_LIST_LINK STD { ssize_t extattr_list_link( _In_z_ const char *path, int attrnamespace, _Out_writes_bytes_opt_(nbytes) void *data, size_t nbytes ); } 440 AUE_NULL OBSOL kse_switchin 441 AUE_SEMWAIT NOSTD { int ksem_timedwait( semid_t id, _In_opt_ const struct timespec *abstime ); } 442 AUE_NULL STD { int thr_suspend( _In_opt_ const struct timespec *timeout ); } 443 AUE_NULL STD { int thr_wake( long id ); } 444 AUE_MODUNLOAD STD { int kldunloadf( int fileid, int flags ); } 445 AUE_AUDIT STD { int audit( _In_reads_bytes_(length) const void *record, u_int length ); } 446 AUE_AUDITON STD { int auditon( int cmd, _In_opt_ void *data, u_int length ); } 447 AUE_GETAUID STD { int getauid( _Out_ uid_t *auid ); } 448 AUE_SETAUID STD { int setauid( _In_ uid_t *auid ); } 449 AUE_GETAUDIT STD { int getaudit( _Out_ struct auditinfo *auditinfo ); } 450 AUE_SETAUDIT STD { int setaudit( _In_ struct auditinfo *auditinfo ); } 451 AUE_GETAUDIT_ADDR STD { int getaudit_addr( _Out_writes_bytes_(length) struct auditinfo_addr *auditinfo_addr, u_int length ); } 452 AUE_SETAUDIT_ADDR STD { int setaudit_addr( _In_reads_bytes_(length) struct auditinfo_addr *auditinfo_addr, u_int length ); } 453 AUE_AUDITCTL STD { int auditctl( _In_z_ const char *path ); } 454 AUE_NULL STD { int _umtx_op( _Inout_ void *obj, int op, u_long val, _In_ void *uaddr1, _In_ void *uaddr2 ); } 455 AUE_THR_NEW STD { int thr_new( _In_ struct thr_param *param, int param_size ); } 456 AUE_NULL STD { int sigqueue( pid_t pid, int signum, _In_ void *value ); } 457 AUE_MQ_OPEN NOSTD { int kmq_open( _In_z_ const char *path, int flags, mode_t mode, _In_opt_ const struct mq_attr *attr ); } 458 AUE_MQ_SETATTR NOSTD { int kmq_setattr( int mqd, _In_opt_ const struct mq_attr *attr, _Out_opt_ struct mq_attr *oattr ); } 459 AUE_MQ_TIMEDRECEIVE NOSTD { int kmq_timedreceive( int mqd, _Out_writes_bytes_(msg_len) char *msg_ptr, size_t msg_len, _Out_opt_ unsigned *msg_prio, _In_opt_ const struct timespec *abs_timeout ); } 460 AUE_MQ_TIMEDSEND NOSTD { int kmq_timedsend( int mqd, _In_reads_bytes_(msg_len) const char *msg_ptr, size_t msg_len, unsigned msg_prio, _In_opt_ const struct timespec *abs_timeout ); } 461 AUE_MQ_NOTIFY NOSTD { int kmq_notify( int mqd, _In_opt_ const struct sigevent *sigev ); } 462 AUE_MQ_UNLINK NOSTD { int kmq_unlink( _In_z_ const char *path ); } 463 AUE_NULL STD { int abort2( _In_z_ const char *why, int nargs, _In_reads_(nargs) void **args ); } 464 AUE_NULL STD { int thr_set_name( long id, _In_z_ const char *name ); } 465 AUE_AIO_FSYNC STD { int aio_fsync( int op, _In_ struct aiocb *aiocbp ); } 466 AUE_RTPRIO STD { int rtprio_thread( int function, lwpid_t lwpid, _Inout_ struct rtprio *rtp ); } 467-468 AUE_NULL UNIMPL nosys 469 AUE_NULL UNIMPL __getpath_fromfd 470 AUE_NULL UNIMPL __getpath_fromaddr 471 AUE_SCTP_PEELOFF NOSTD { int sctp_peeloff( int sd, uint32_t name ); } 472 AUE_SCTP_GENERIC_SENDMSG NOSTD { int sctp_generic_sendmsg( int sd, _In_reads_bytes_(mlen) void *msg, int mlen, _In_reads_bytes_(tolen) struct sockaddr *to, __socklen_t tolen, _In_opt_ struct sctp_sndrcvinfo *sinfo, int flags ); } 473 AUE_SCTP_GENERIC_SENDMSG_IOV NOSTD { int sctp_generic_sendmsg_iov( int sd, _In_reads_(iovlen) struct iovec *iov, int iovlen, _In_reads_bytes_(tolen) struct sockaddr *to, __socklen_t tolen, _In_opt_ struct sctp_sndrcvinfo *sinfo, int flags ); } 474 AUE_SCTP_GENERIC_RECVMSG NOSTD { int sctp_generic_recvmsg( int sd, _In_reads_(iovlen) struct iovec *iov, int iovlen, _Out_writes_bytes_(*fromlenaddr) struct sockaddr *from, _Out_ __socklen_t *fromlenaddr, _In_opt_ struct sctp_sndrcvinfo *sinfo, _Out_opt_ int *msg_flags ); } 475 AUE_PREAD STD { ssize_t pread( int fd, _Out_writes_bytes_(nbyte) void *buf, size_t nbyte, off_t offset ); } 476 AUE_PWRITE STD { ssize_t pwrite( int fd, _In_reads_bytes_(nbyte) const void *buf, size_t nbyte, off_t offset ); } 477 AUE_MMAP STD { void *mmap( _In_ void *addr, size_t len, int prot, int flags, int fd, off_t pos ); } 478 AUE_LSEEK STD { off_t lseek( int fd, off_t offset, int whence ); } 479 AUE_TRUNCATE STD { int truncate( _In_z_ const char *path, off_t length ); } 480 AUE_FTRUNCATE STD { int ftruncate( int fd, off_t length ); } 481 AUE_THR_KILL2 STD { int thr_kill2( pid_t pid, long id, int sig ); } 482 AUE_SHMOPEN COMPAT12 { int shm_open( _In_z_ const char *path, int flags, mode_t mode ); } 483 AUE_SHMUNLINK STD { int shm_unlink( _In_z_ const char *path ); } 484 AUE_NULL STD { int cpuset( _Out_ cpusetid_t *setid ); } 485 AUE_NULL STD { int cpuset_setid( cpuwhich_t which, id_t id, cpusetid_t setid ); } 486 AUE_NULL STD { int cpuset_getid( cpulevel_t level, cpuwhich_t which, id_t id, _Out_ cpusetid_t *setid ); } 487 AUE_NULL STD { int cpuset_getaffinity( cpulevel_t level, cpuwhich_t which, id_t id, size_t cpusetsize, _Out_ cpuset_t *mask ); } 488 AUE_NULL STD { int cpuset_setaffinity( cpulevel_t level, cpuwhich_t which, id_t id, size_t cpusetsize, _Out_ const cpuset_t *mask ); } 489 AUE_FACCESSAT STD { int faccessat( int fd, _In_z_ const char *path, int amode, int flag ); } 490 AUE_FCHMODAT STD { int fchmodat( int fd, _In_z_ const char *path, mode_t mode, int flag ); } 491 AUE_FCHOWNAT STD { int fchownat( int fd, _In_z_ const char *path, uid_t uid, gid_t gid, int flag ); } 492 AUE_FEXECVE STD { int fexecve( int fd, _In_ char **argv, _In_ char **envv ); } 493 AUE_FSTATAT COMPAT11 { int fstatat( int fd, _In_z_ const char *path, _Out_ struct freebsd11_stat *buf, int flag ); } 494 AUE_FUTIMESAT STD { int futimesat( int fd, _In_z_ const char *path, _In_reads_(2) struct timeval *times ); } 495 AUE_LINKAT STD { int linkat( int fd1, _In_z_ const char *path1, int fd2, _In_z_ const char *path2, int flag ); } 496 AUE_MKDIRAT STD { int mkdirat( int fd, _In_z_ const char *path, mode_t mode ); } 497 AUE_MKFIFOAT STD { int mkfifoat( int fd, _In_z_ const char *path, mode_t mode ); } 498 AUE_MKNODAT COMPAT11 { int mknodat( int fd, _In_z_ const char *path, mode_t mode, uint32_t dev ); } ; XXX: see the comment for open 499 AUE_OPENAT_RWTC STD { int openat( int fd, _In_z_ const char *path, int flag, mode_t mode ); } 500 AUE_READLINKAT STD { ssize_t readlinkat( int fd, _In_z_ const char *path, _Out_writes_bytes_(bufsize) char *buf, size_t bufsize ); } 501 AUE_RENAMEAT STD { int renameat( int oldfd, _In_z_ const char *old, int newfd, _In_z_ const char *new ); } 502 AUE_SYMLINKAT STD { int symlinkat( _In_z_ const char *path1, int fd, _In_z_ const char *path2 ); } 503 AUE_UNLINKAT STD { int unlinkat( int fd, _In_z_ const char *path, int flag ); } 504 AUE_POSIX_OPENPT STD { int posix_openpt( int flags ); } ; 505 is initialised by the kgssapi code, if present. 505 AUE_NULL NOSTD { int gssd_syscall( _In_z_ const char *path ); } 506 AUE_JAIL_GET STD { int jail_get( _In_reads_(iovcnt) struct iovec *iovp, unsigned int iovcnt, int flags ); } 507 AUE_JAIL_SET STD { int jail_set( _In_reads_(iovcnt) struct iovec *iovp, unsigned int iovcnt, int flags ); } 508 AUE_JAIL_REMOVE STD { int jail_remove( int jid ); } 509 AUE_CLOSEFROM STD { int closefrom( int lowfd ); } 510 AUE_SEMCTL NOSTD { int __semctl( int semid, int semnum, int cmd, _Inout_ union semun *arg ); } 511 AUE_MSGCTL NOSTD { int msgctl( int msqid, int cmd, _Inout_opt_ struct msqid_ds *buf ); } 512 AUE_SHMCTL NOSTD { int shmctl( int shmid, int cmd, _Inout_opt_ struct shmid_ds *buf ); } 513 AUE_LPATHCONF STD { int lpathconf( _In_z_ const char *path, int name ); } 514 AUE_NULL OBSOL cap_new 515 AUE_CAP_RIGHTS_GET STD { int __cap_rights_get( int version, int fd, _Out_ cap_rights_t *rightsp ); } 516 AUE_CAP_ENTER STD { int cap_enter(void); } 517 AUE_CAP_GETMODE STD { int cap_getmode( _Out_ u_int *modep ); } 518 AUE_PDFORK STD { int pdfork( _Out_ int *fdp, int flags ); } 519 AUE_PDKILL STD { int pdkill( int fd, int signum ); } 520 AUE_PDGETPID STD { int pdgetpid( int fd, _Out_ pid_t *pidp ); } 521 AUE_PDWAIT UNIMPL pdwait4 522 AUE_SELECT STD { int pselect( int nd, _Inout_opt_ fd_set *in, _Inout_opt_ fd_set *ou, _Inout_opt_ fd_set *ex, _In_opt_ const struct timespec *ts, _In_opt_ const sigset_t *sm ); } 523 AUE_GETLOGINCLASS STD { int getloginclass( _Out_writes_z_(namelen) char *namebuf, size_t namelen ); } 524 AUE_SETLOGINCLASS STD { int setloginclass( _In_z_ const char *namebuf ); } 525 AUE_NULL STD { int rctl_get_racct( _In_reads_bytes_(inbuflen) const void *inbufp, size_t inbuflen, _Out_writes_bytes_(outbuflen) void *outbufp, size_t outbuflen ); } 526 AUE_NULL STD { int rctl_get_rules( _In_reads_bytes_(inbuflen) const void *inbufp, size_t inbuflen, _Out_writes_bytes_(outbuflen) void *outbufp, size_t outbuflen ); } 527 AUE_NULL STD { int rctl_get_limits( _In_reads_bytes_(inbuflen) const void *inbufp, size_t inbuflen, _Out_writes_bytes_(outbuflen) void *outbufp, size_t outbuflen ); } 528 AUE_NULL STD { int rctl_add_rule( _In_reads_bytes_(inbuflen) const void *inbufp, size_t inbuflen, _Out_writes_bytes_(outbuflen) void *outbufp, size_t outbuflen ); } 529 AUE_NULL STD { int rctl_remove_rule( _In_reads_bytes_(inbuflen) const void *inbufp, size_t inbuflen, _Out_writes_bytes_(outbuflen) void *outbufp, size_t outbuflen ); } 530 AUE_POSIX_FALLOCATE STD { int posix_fallocate( int fd, off_t offset, off_t len ); } 531 AUE_POSIX_FADVISE STD { int posix_fadvise( int fd, off_t offset, off_t len, int advice ); } 532 AUE_WAIT6 STD { int wait6( idtype_t idtype, id_t id, _Out_opt_ int *status, int options, _Out_opt_ struct __wrusage *wrusage, _Out_opt_ siginfo_t *info ); } 533 AUE_CAP_RIGHTS_LIMIT STD { int cap_rights_limit( int fd, _In_ cap_rights_t *rightsp ); } 534 AUE_CAP_IOCTLS_LIMIT STD { int cap_ioctls_limit( int fd, _In_reads_(ncmds) const u_long *cmds, size_t ncmds ); } 535 AUE_CAP_IOCTLS_GET STD { ssize_t cap_ioctls_get( int fd, _Out_writes_(maxcmds) u_long *cmds, size_t maxcmds ); } 536 AUE_CAP_FCNTLS_LIMIT STD { int cap_fcntls_limit( int fd, uint32_t fcntlrights ); } 537 AUE_CAP_FCNTLS_GET STD { int cap_fcntls_get( int fd, _Out_ uint32_t *fcntlrightsp ); } 538 AUE_BINDAT STD { int bindat( int fd, int s, _In_reads_bytes_(namelen) const struct sockaddr *name, int namelen ); } 539 AUE_CONNECTAT STD { int connectat( int fd, int s, _In_reads_bytes_(namelen) const struct sockaddr *name, int namelen ); } 540 AUE_CHFLAGSAT STD { int chflagsat( int fd, _In_z_ const char *path, u_long flags, int atflag ); } 541 AUE_ACCEPT STD { int accept4( int s, _Out_writes_bytes_opt_(*anamelen) struct sockaddr *name, _Inout_opt_ __socklen_t *anamelen, int flags ); } 542 AUE_PIPE STD { int pipe2( _Out_writes_(2) int *fildes, int flags ); } 543 AUE_AIO_MLOCK STD { int aio_mlock( _In_ struct aiocb *aiocbp ); } 544 AUE_PROCCTL STD { int procctl( idtype_t idtype, id_t id, int com, _In_opt_ void *data ); } 545 AUE_POLL STD { int ppoll( _Inout_updates_(nfds) struct pollfd *fds, u_int nfds, _In_opt_ const struct timespec *ts, _In_opt_ const sigset_t *set ); } 546 AUE_FUTIMES STD { int futimens( int fd, _In_reads_(2) struct timespec *times ); } 547 AUE_FUTIMESAT STD { int utimensat( int fd, _In_z_ const char *path, _In_reads_(2) struct timespec *times, int flag ); } 548 AUE_NULL OBSOL numa_getaffinity 549 AUE_NULL OBSOL numa_setaffinity 550 AUE_FSYNC STD { int fdatasync( int fd ); } 551 AUE_FSTAT STD { int fstat( int fd, _Out_ struct stat *sb ); } 552 AUE_FSTATAT STD { int fstatat( int fd, _In_z_ const char *path, _Out_ struct stat *buf, int flag ); } 553 AUE_FHSTAT STD { int fhstat( _In_ const struct fhandle *u_fhp, _Out_ struct stat *sb ); } 554 AUE_GETDIRENTRIES STD { ssize_t getdirentries( int fd, _Out_writes_bytes_(count) char *buf, size_t count, _Out_ off_t *basep ); } 555 AUE_STATFS STD { int statfs( _In_z_ const char *path, _Out_ struct statfs *buf ); } 556 AUE_FSTATFS STD { int fstatfs( int fd, _Out_ struct statfs *buf ); } 557 AUE_GETFSSTAT STD { int getfsstat( _Out_writes_bytes_opt_(bufsize) struct statfs *buf, long bufsize, int mode ); } 558 AUE_FHSTATFS STD { int fhstatfs( _In_ const struct fhandle *u_fhp, _Out_ struct statfs *buf ); } 559 AUE_MKNODAT STD { int mknodat( int fd, _In_z_ const char *path, mode_t mode, dev_t dev ); } 560 AUE_KEVENT STD { int kevent( int fd, _In_reads_opt_(nchanges) struct kevent *changelist, int nchanges, _Out_writes_opt_(nevents) struct kevent *eventlist, int nevents, _In_opt_ const struct timespec *timeout ); } 561 AUE_NULL STD { int cpuset_getdomain( cpulevel_t level, cpuwhich_t which, id_t id, size_t domainsetsize, _Out_writes_bytes_(domainsetsize) domainset_t *mask, _Out_ int *policy ); } 562 AUE_NULL STD { int cpuset_setdomain( cpulevel_t level, cpuwhich_t which, id_t id, size_t domainsetsize, _In_ domainset_t *mask, int policy ); } 563 AUE_NULL STD { int getrandom( _Out_writes_bytes_(buflen) void *buf, size_t buflen, unsigned int flags ); } 564 AUE_NULL STD { int getfhat( int fd, _In_z_ char *path, _Out_ struct fhandle *fhp, int flags ); } 565 AUE_NULL STD { int fhlink( _In_ struct fhandle *fhp, _In_z_ const char *to ); } 566 AUE_NULL STD { int fhlinkat( _In_ struct fhandle *fhp, int tofd, _In_z_ const char *to, ); } 567 AUE_NULL STD { int fhreadlink( _In_ struct fhandle *fhp, _Out_writes_(bufsize) char *buf, size_t bufsize ); } 568 AUE_UNLINKAT STD { int funlinkat( int dfd, _In_z_ const char *path, int fd, int flag ); } 569 AUE_NULL STD { ssize_t copy_file_range( int infd, _Inout_opt_ off_t *inoffp, int outfd, _Inout_opt_ off_t *outoffp, size_t len, unsigned int flags ); } 570 AUE_SYSCTL STD { int __sysctlbyname( _In_reads_(namelen) const char *name, size_t namelen, _Out_writes_bytes_opt_(*oldlenp) void *old, _Inout_opt_ size_t *oldlenp, _In_reads_bytes_opt_(newlen) void *new, size_t newlen ); } 571 AUE_SHMOPEN STD { int shm_open2( _In_z_ const char *path, int flags, mode_t mode, int shmflags, _In_z_ const char *name ); } 572 AUE_SHMRENAME STD { int shm_rename( _In_z_ const char *path_from, _In_z_ const char *path_to, int flags ); } 573 AUE_NULL STD { int sigfastblock( int cmd, _Inout_opt_ uint32_t *ptr ); } +574 AUE_REALPATHAT STD { + int __realpathat( + int fd, + _In_z_ const char *path, + _Out_writes_z_(size) char *buf, + size_t size, + int flags + ); + } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master ; vim: syntax=off Index: head/sys/kern/vfs_cache.c =================================================================== --- head/sys/kern/vfs_cache.c (revision 358171) +++ head/sys/kern/vfs_cache.c (revision 358172) @@ -1,2606 +1,2758 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1989, 1993, 1995 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Poul-Henning Kamp of the FreeBSD Project. * * 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. * 3. 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. * * @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95 */ #include __FBSDID("$FreeBSD$"); #include "opt_ddb.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 #ifdef KTRACE #include #endif #ifdef DDB #include #endif #include SDT_PROVIDER_DECLARE(vfs); SDT_PROBE_DEFINE3(vfs, namecache, enter, done, "struct vnode *", "char *", "struct vnode *"); SDT_PROBE_DEFINE2(vfs, namecache, enter_negative, done, "struct vnode *", "char *"); SDT_PROBE_DEFINE1(vfs, namecache, fullpath, entry, "struct vnode *"); SDT_PROBE_DEFINE3(vfs, namecache, fullpath, hit, "struct vnode *", "char *", "struct vnode *"); SDT_PROBE_DEFINE1(vfs, namecache, fullpath, miss, "struct vnode *"); SDT_PROBE_DEFINE3(vfs, namecache, fullpath, return, "int", "struct vnode *", "char *"); SDT_PROBE_DEFINE3(vfs, namecache, lookup, hit, "struct vnode *", "char *", "struct vnode *"); SDT_PROBE_DEFINE2(vfs, namecache, lookup, hit__negative, "struct vnode *", "char *"); SDT_PROBE_DEFINE2(vfs, namecache, lookup, miss, "struct vnode *", "char *"); SDT_PROBE_DEFINE1(vfs, namecache, purge, done, "struct vnode *"); SDT_PROBE_DEFINE1(vfs, namecache, purge_negative, done, "struct vnode *"); SDT_PROBE_DEFINE1(vfs, namecache, purgevfs, done, "struct mount *"); SDT_PROBE_DEFINE3(vfs, namecache, zap, done, "struct vnode *", "char *", "struct vnode *"); SDT_PROBE_DEFINE2(vfs, namecache, zap_negative, done, "struct vnode *", "char *"); SDT_PROBE_DEFINE2(vfs, namecache, shrink_negative, done, "struct vnode *", "char *"); /* * This structure describes the elements in the cache of recent * names looked up by namei. */ struct namecache { LIST_ENTRY(namecache) nc_hash; /* hash chain */ LIST_ENTRY(namecache) nc_src; /* source vnode list */ TAILQ_ENTRY(namecache) nc_dst; /* destination vnode list */ struct vnode *nc_dvp; /* vnode of parent of name */ union { struct vnode *nu_vp; /* vnode the name refers to */ } n_un; u_char nc_flag; /* flag bits */ u_char nc_nlen; /* length of name */ char nc_name[0]; /* segment name + nul */ }; /* * struct namecache_ts repeats struct namecache layout up to the * nc_nlen member. * struct namecache_ts is used in place of struct namecache when time(s) need * to be stored. The nc_dotdottime field is used when a cache entry is mapping * both a non-dotdot directory name plus dotdot for the directory's * parent. */ struct namecache_ts { struct timespec nc_time; /* timespec provided by fs */ struct timespec nc_dotdottime; /* dotdot timespec provided by fs */ int nc_ticks; /* ticks value when entry was added */ struct namecache nc_nc; }; #define nc_vp n_un.nu_vp /* * Flags in namecache.nc_flag */ #define NCF_WHITE 0x01 #define NCF_ISDOTDOT 0x02 #define NCF_TS 0x04 #define NCF_DTS 0x08 #define NCF_DVDROP 0x10 #define NCF_NEGATIVE 0x20 #define NCF_HOTNEGATIVE 0x40 /* * Name caching works as follows: * * Names found by directory scans are retained in a cache * for future reference. It is managed LRU, so frequently * used names will hang around. Cache is indexed by hash value * obtained from (dvp, name) where dvp refers to the directory * containing name. * * If it is a "negative" entry, (i.e. for a name that is known NOT to * exist) the vnode pointer will be NULL. * * Upon reaching the last segment of a path, if the reference * is for DELETE, or NOCACHE is set (rewrite), and the * name is located in the cache, it will be dropped. * * These locks are used (in the order in which they can be taken): * NAME TYPE ROLE * vnodelock mtx vnode lists and v_cache_dd field protection * bucketlock rwlock for access to given set of hash buckets * neglist mtx negative entry LRU management * * Additionally, ncneg_shrink_lock mtx is used to have at most one thread * shrinking the LRU list. * * It is legal to take multiple vnodelock and bucketlock locks. The locking * order is lower address first. Both are recursive. * * "." lookups are lockless. * * ".." and vnode -> name lookups require vnodelock. * * name -> vnode lookup requires the relevant bucketlock to be held for reading. * * Insertions and removals of entries require involved vnodes and bucketlocks * to be write-locked to prevent other threads from seeing the entry. * * Some lookups result in removal of the found entry (e.g. getting rid of a * negative entry with the intent to create a positive one), which poses a * problem when multiple threads reach the state. Similarly, two different * threads can purge two different vnodes and try to remove the same name. * * If the already held vnode lock is lower than the second required lock, we * can just take the other lock. However, in the opposite case, this could * deadlock. As such, this is resolved by trylocking and if that fails unlocking * the first node, locking everything in order and revalidating the state. */ /* * Structures associated with name caching. */ #define NCHHASH(hash) \ (&nchashtbl[(hash) & nchash]) static __read_mostly LIST_HEAD(nchashhead, namecache) *nchashtbl;/* Hash Table */ static u_long __read_mostly nchash; /* size of hash table */ SYSCTL_ULONG(_debug, OID_AUTO, nchash, CTLFLAG_RD, &nchash, 0, "Size of namecache hash table"); static u_long __read_mostly ncnegfactor = 5; /* ratio of negative entries */ SYSCTL_ULONG(_vfs, OID_AUTO, ncnegfactor, CTLFLAG_RW, &ncnegfactor, 0, "Ratio of negative namecache entries"); static u_long __exclusive_cache_line numneg; /* number of negative entries allocated */ static u_long __exclusive_cache_line numcache;/* number of cache entries allocated */ u_int ncsizefactor = 2; SYSCTL_UINT(_vfs, OID_AUTO, ncsizefactor, CTLFLAG_RW, &ncsizefactor, 0, "Size factor for namecache"); static u_int __read_mostly ncpurgeminvnodes; SYSCTL_UINT(_vfs, OID_AUTO, ncpurgeminvnodes, CTLFLAG_RW, &ncpurgeminvnodes, 0, "Number of vnodes below which purgevfs ignores the request"); static u_int __read_mostly ncsize; /* the size as computed on creation or resizing */ struct nchstats nchstats; /* cache effectiveness statistics */ static struct mtx __exclusive_cache_line ncneg_shrink_lock; static int shrink_list_turn; struct neglist { struct mtx nl_lock; TAILQ_HEAD(, namecache) nl_list; } __aligned(CACHE_LINE_SIZE); static struct neglist __read_mostly *neglists; static struct neglist ncneg_hot; static u_long numhotneg; #define numneglists (ncneghash + 1) static u_int __read_mostly ncneghash; static inline struct neglist * NCP2NEGLIST(struct namecache *ncp) { return (&neglists[(((uintptr_t)(ncp) >> 8) & ncneghash)]); } #define numbucketlocks (ncbuckethash + 1) static u_int __read_mostly ncbuckethash; static struct rwlock_padalign __read_mostly *bucketlocks; #define HASH2BUCKETLOCK(hash) \ ((struct rwlock *)(&bucketlocks[((hash) & ncbuckethash)])) #define numvnodelocks (ncvnodehash + 1) static u_int __read_mostly ncvnodehash; static struct mtx __read_mostly *vnodelocks; static inline struct mtx * VP2VNODELOCK(struct vnode *vp) { return (&vnodelocks[(((uintptr_t)(vp) >> 8) & ncvnodehash)]); } /* * UMA zones for the VFS cache. * * The small cache is used for entries with short names, which are the * most common. The large cache is used for entries which are too big to * fit in the small cache. */ static uma_zone_t __read_mostly cache_zone_small; static uma_zone_t __read_mostly cache_zone_small_ts; static uma_zone_t __read_mostly cache_zone_large; static uma_zone_t __read_mostly cache_zone_large_ts; #define CACHE_PATH_CUTOFF 35 static struct namecache * cache_alloc(int len, int ts) { struct namecache_ts *ncp_ts; struct namecache *ncp; if (__predict_false(ts)) { if (len <= CACHE_PATH_CUTOFF) ncp_ts = uma_zalloc(cache_zone_small_ts, M_WAITOK); else ncp_ts = uma_zalloc(cache_zone_large_ts, M_WAITOK); ncp = &ncp_ts->nc_nc; } else { if (len <= CACHE_PATH_CUTOFF) ncp = uma_zalloc(cache_zone_small, M_WAITOK); else ncp = uma_zalloc(cache_zone_large, M_WAITOK); } return (ncp); } static void cache_free(struct namecache *ncp) { struct namecache_ts *ncp_ts; if (ncp == NULL) return; if ((ncp->nc_flag & NCF_DVDROP) != 0) vdrop(ncp->nc_dvp); if (__predict_false(ncp->nc_flag & NCF_TS)) { ncp_ts = __containerof(ncp, struct namecache_ts, nc_nc); if (ncp->nc_nlen <= CACHE_PATH_CUTOFF) uma_zfree(cache_zone_small_ts, ncp_ts); else uma_zfree(cache_zone_large_ts, ncp_ts); } else { if (ncp->nc_nlen <= CACHE_PATH_CUTOFF) uma_zfree(cache_zone_small, ncp); else uma_zfree(cache_zone_large, ncp); } } static void cache_out_ts(struct namecache *ncp, struct timespec *tsp, int *ticksp) { struct namecache_ts *ncp_ts; KASSERT((ncp->nc_flag & NCF_TS) != 0 || (tsp == NULL && ticksp == NULL), ("No NCF_TS")); if (tsp == NULL && ticksp == NULL) return; ncp_ts = __containerof(ncp, struct namecache_ts, nc_nc); if (tsp != NULL) *tsp = ncp_ts->nc_time; if (ticksp != NULL) *ticksp = ncp_ts->nc_ticks; } #ifdef DEBUG_CACHE static int __read_mostly doingcache = 1; /* 1 => enable the cache */ SYSCTL_INT(_debug, OID_AUTO, vfscache, CTLFLAG_RW, &doingcache, 0, "VFS namecache enabled"); #endif /* Export size information to userland */ SYSCTL_INT(_debug_sizeof, OID_AUTO, namecache, CTLFLAG_RD, SYSCTL_NULL_INT_PTR, sizeof(struct namecache), "sizeof(struct namecache)"); /* * The new name cache statistics */ static SYSCTL_NODE(_vfs, OID_AUTO, cache, CTLFLAG_RW, 0, "Name cache statistics"); #define STATNODE_ULONG(name, descr) \ SYSCTL_ULONG(_vfs_cache, OID_AUTO, name, CTLFLAG_RD, &name, 0, descr); #define STATNODE_COUNTER(name, descr) \ static counter_u64_t __read_mostly name; \ SYSCTL_COUNTER_U64(_vfs_cache, OID_AUTO, name, CTLFLAG_RD, &name, descr); STATNODE_ULONG(numneg, "Number of negative cache entries"); STATNODE_ULONG(numcache, "Number of cache entries"); STATNODE_COUNTER(numcachehv, "Number of namecache entries with vnodes held"); STATNODE_COUNTER(numcalls, "Number of cache lookups"); STATNODE_COUNTER(dothits, "Number of '.' hits"); STATNODE_COUNTER(dotdothits, "Number of '..' hits"); STATNODE_COUNTER(numchecks, "Number of checks in lookup"); STATNODE_COUNTER(nummiss, "Number of cache misses"); STATNODE_COUNTER(nummisszap, "Number of cache misses we do not want to cache"); STATNODE_COUNTER(numposzaps, "Number of cache hits (positive) we do not want to cache"); STATNODE_COUNTER(numposhits, "Number of cache hits (positive)"); STATNODE_COUNTER(numnegzaps, "Number of cache hits (negative) we do not want to cache"); STATNODE_COUNTER(numneghits, "Number of cache hits (negative)"); /* These count for vn_getcwd(), too. */ STATNODE_COUNTER(numfullpathcalls, "Number of fullpath search calls"); STATNODE_COUNTER(numfullpathfail1, "Number of fullpath search errors (ENOTDIR)"); STATNODE_COUNTER(numfullpathfail2, "Number of fullpath search errors (VOP_VPTOCNP failures)"); STATNODE_COUNTER(numfullpathfail4, "Number of fullpath search errors (ENOMEM)"); STATNODE_COUNTER(numfullpathfound, "Number of successful fullpath calls"); STATNODE_COUNTER(zap_and_exit_bucket_relock_success, "Number of successful removals after relocking"); static long zap_and_exit_bucket_fail; STATNODE_ULONG(zap_and_exit_bucket_fail, "Number of times zap_and_exit failed to lock"); static long zap_and_exit_bucket_fail2; STATNODE_ULONG(zap_and_exit_bucket_fail2, "Number of times zap_and_exit failed to lock"); static long cache_lock_vnodes_cel_3_failures; STATNODE_ULONG(cache_lock_vnodes_cel_3_failures, "Number of times 3-way vnode locking failed"); STATNODE_ULONG(numhotneg, "Number of hot negative entries"); STATNODE_COUNTER(numneg_evicted, "Number of negative entries evicted when adding a new entry"); STATNODE_COUNTER(shrinking_skipped, "Number of times shrinking was already in progress"); static void cache_zap_locked(struct namecache *ncp, bool neg_locked); -static int vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir, +static int vn_fullpath_hardlink(struct thread *td, struct nameidata *ndp, char **retbuf, + char **freebuf, size_t *buflen); +static int vn_fullpath_any(struct thread *td, struct vnode *vp, struct vnode *rdir, char *buf, char **retbuf, size_t *buflen); +static int vn_fullpath_dir(struct thread *td, struct vnode *vp, struct vnode *rdir, + char *buf, char **retbuf, size_t *len, bool slash_prefixed, size_t addend); static MALLOC_DEFINE(M_VFSCACHE, "vfscache", "VFS name cache entries"); static int cache_yield; SYSCTL_INT(_vfs_cache, OID_AUTO, yield, CTLFLAG_RD, &cache_yield, 0, "Number of times cache called yield"); static void __noinline cache_maybe_yield(void) { if (should_yield()) { cache_yield++; kern_yield(PRI_USER); } } static inline void cache_assert_vlp_locked(struct mtx *vlp) { if (vlp != NULL) mtx_assert(vlp, MA_OWNED); } static inline void cache_assert_vnode_locked(struct vnode *vp) { struct mtx *vlp; vlp = VP2VNODELOCK(vp); cache_assert_vlp_locked(vlp); } static uint32_t cache_get_hash(char *name, u_char len, struct vnode *dvp) { uint32_t hash; hash = fnv_32_buf(name, len, FNV1_32_INIT); hash = fnv_32_buf(&dvp, sizeof(dvp), hash); return (hash); } static inline struct rwlock * NCP2BUCKETLOCK(struct namecache *ncp) { uint32_t hash; hash = cache_get_hash(ncp->nc_name, ncp->nc_nlen, ncp->nc_dvp); return (HASH2BUCKETLOCK(hash)); } #ifdef INVARIANTS static void cache_assert_bucket_locked(struct namecache *ncp, int mode) { struct rwlock *blp; blp = NCP2BUCKETLOCK(ncp); rw_assert(blp, mode); } #else #define cache_assert_bucket_locked(x, y) do { } while (0) #endif #define cache_sort_vnodes(x, y) _cache_sort_vnodes((void **)(x), (void **)(y)) static void _cache_sort_vnodes(void **p1, void **p2) { void *tmp; MPASS(*p1 != NULL || *p2 != NULL); if (*p1 > *p2) { tmp = *p2; *p2 = *p1; *p1 = tmp; } } static void cache_lock_all_buckets(void) { u_int i; for (i = 0; i < numbucketlocks; i++) rw_wlock(&bucketlocks[i]); } static void cache_unlock_all_buckets(void) { u_int i; for (i = 0; i < numbucketlocks; i++) rw_wunlock(&bucketlocks[i]); } static void cache_lock_all_vnodes(void) { u_int i; for (i = 0; i < numvnodelocks; i++) mtx_lock(&vnodelocks[i]); } static void cache_unlock_all_vnodes(void) { u_int i; for (i = 0; i < numvnodelocks; i++) mtx_unlock(&vnodelocks[i]); } static int cache_trylock_vnodes(struct mtx *vlp1, struct mtx *vlp2) { cache_sort_vnodes(&vlp1, &vlp2); if (vlp1 != NULL) { if (!mtx_trylock(vlp1)) return (EAGAIN); } if (!mtx_trylock(vlp2)) { if (vlp1 != NULL) mtx_unlock(vlp1); return (EAGAIN); } return (0); } static void cache_lock_vnodes(struct mtx *vlp1, struct mtx *vlp2) { MPASS(vlp1 != NULL || vlp2 != NULL); MPASS(vlp1 <= vlp2); if (vlp1 != NULL) mtx_lock(vlp1); if (vlp2 != NULL) mtx_lock(vlp2); } static void cache_unlock_vnodes(struct mtx *vlp1, struct mtx *vlp2) { MPASS(vlp1 != NULL || vlp2 != NULL); if (vlp1 != NULL) mtx_unlock(vlp1); if (vlp2 != NULL) mtx_unlock(vlp2); } static int sysctl_nchstats(SYSCTL_HANDLER_ARGS) { struct nchstats snap; if (req->oldptr == NULL) return (SYSCTL_OUT(req, 0, sizeof(snap))); snap = nchstats; snap.ncs_goodhits = counter_u64_fetch(numposhits); snap.ncs_neghits = counter_u64_fetch(numneghits); snap.ncs_badhits = counter_u64_fetch(numposzaps) + counter_u64_fetch(numnegzaps); snap.ncs_miss = counter_u64_fetch(nummisszap) + counter_u64_fetch(nummiss); return (SYSCTL_OUT(req, &snap, sizeof(snap))); } SYSCTL_PROC(_vfs_cache, OID_AUTO, nchstats, CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 0, sysctl_nchstats, "LU", "VFS cache effectiveness statistics"); #ifdef DIAGNOSTIC /* * Grab an atomic snapshot of the name cache hash chain lengths */ static SYSCTL_NODE(_debug, OID_AUTO, hashstat, CTLFLAG_RW, NULL, "hash table stats"); static int sysctl_debug_hashstat_rawnchash(SYSCTL_HANDLER_ARGS) { struct nchashhead *ncpp; struct namecache *ncp; int i, error, n_nchash, *cntbuf; retry: n_nchash = nchash + 1; /* nchash is max index, not count */ if (req->oldptr == NULL) return SYSCTL_OUT(req, 0, n_nchash * sizeof(int)); cntbuf = malloc(n_nchash * sizeof(int), M_TEMP, M_ZERO | M_WAITOK); cache_lock_all_buckets(); if (n_nchash != nchash + 1) { cache_unlock_all_buckets(); free(cntbuf, M_TEMP); goto retry; } /* Scan hash tables counting entries */ for (ncpp = nchashtbl, i = 0; i < n_nchash; ncpp++, i++) LIST_FOREACH(ncp, ncpp, nc_hash) cntbuf[i]++; cache_unlock_all_buckets(); for (error = 0, i = 0; i < n_nchash; i++) if ((error = SYSCTL_OUT(req, &cntbuf[i], sizeof(int))) != 0) break; free(cntbuf, M_TEMP); return (error); } SYSCTL_PROC(_debug_hashstat, OID_AUTO, rawnchash, CTLTYPE_INT|CTLFLAG_RD| CTLFLAG_MPSAFE, 0, 0, sysctl_debug_hashstat_rawnchash, "S,int", "nchash chain lengths"); static int sysctl_debug_hashstat_nchash(SYSCTL_HANDLER_ARGS) { int error; struct nchashhead *ncpp; struct namecache *ncp; int n_nchash; int count, maxlength, used, pct; if (!req->oldptr) return SYSCTL_OUT(req, 0, 4 * sizeof(int)); cache_lock_all_buckets(); n_nchash = nchash + 1; /* nchash is max index, not count */ used = 0; maxlength = 0; /* Scan hash tables for applicable entries */ for (ncpp = nchashtbl; n_nchash > 0; n_nchash--, ncpp++) { count = 0; LIST_FOREACH(ncp, ncpp, nc_hash) { count++; } if (count) used++; if (maxlength < count) maxlength = count; } n_nchash = nchash + 1; cache_unlock_all_buckets(); pct = (used * 100) / (n_nchash / 100); error = SYSCTL_OUT(req, &n_nchash, sizeof(n_nchash)); if (error) return (error); error = SYSCTL_OUT(req, &used, sizeof(used)); if (error) return (error); error = SYSCTL_OUT(req, &maxlength, sizeof(maxlength)); if (error) return (error); error = SYSCTL_OUT(req, &pct, sizeof(pct)); if (error) return (error); return (0); } SYSCTL_PROC(_debug_hashstat, OID_AUTO, nchash, CTLTYPE_INT|CTLFLAG_RD| CTLFLAG_MPSAFE, 0, 0, sysctl_debug_hashstat_nchash, "I", "nchash statistics (number of total/used buckets, maximum chain length, usage percentage)"); #endif /* * Negative entries management * * A variation of LRU scheme is used. New entries are hashed into one of * numneglists cold lists. Entries get promoted to the hot list on first hit. * * The shrinker will demote hot list head and evict from the cold list in a * round-robin manner. */ static void cache_negative_hit(struct namecache *ncp) { struct neglist *neglist; MPASS(ncp->nc_flag & NCF_NEGATIVE); if (ncp->nc_flag & NCF_HOTNEGATIVE) return; neglist = NCP2NEGLIST(ncp); mtx_lock(&ncneg_hot.nl_lock); mtx_lock(&neglist->nl_lock); if (!(ncp->nc_flag & NCF_HOTNEGATIVE)) { numhotneg++; TAILQ_REMOVE(&neglist->nl_list, ncp, nc_dst); TAILQ_INSERT_TAIL(&ncneg_hot.nl_list, ncp, nc_dst); ncp->nc_flag |= NCF_HOTNEGATIVE; } mtx_unlock(&neglist->nl_lock); mtx_unlock(&ncneg_hot.nl_lock); } static void cache_negative_insert(struct namecache *ncp, bool neg_locked) { struct neglist *neglist; MPASS(ncp->nc_flag & NCF_NEGATIVE); cache_assert_bucket_locked(ncp, RA_WLOCKED); neglist = NCP2NEGLIST(ncp); if (!neg_locked) { mtx_lock(&neglist->nl_lock); } else { mtx_assert(&neglist->nl_lock, MA_OWNED); } TAILQ_INSERT_TAIL(&neglist->nl_list, ncp, nc_dst); if (!neg_locked) mtx_unlock(&neglist->nl_lock); atomic_add_rel_long(&numneg, 1); } static void cache_negative_remove(struct namecache *ncp, bool neg_locked) { struct neglist *neglist; bool hot_locked = false; bool list_locked = false; MPASS(ncp->nc_flag & NCF_NEGATIVE); cache_assert_bucket_locked(ncp, RA_WLOCKED); neglist = NCP2NEGLIST(ncp); if (!neg_locked) { if (ncp->nc_flag & NCF_HOTNEGATIVE) { hot_locked = true; mtx_lock(&ncneg_hot.nl_lock); if (!(ncp->nc_flag & NCF_HOTNEGATIVE)) { list_locked = true; mtx_lock(&neglist->nl_lock); } } else { list_locked = true; mtx_lock(&neglist->nl_lock); } } if (ncp->nc_flag & NCF_HOTNEGATIVE) { mtx_assert(&ncneg_hot.nl_lock, MA_OWNED); TAILQ_REMOVE(&ncneg_hot.nl_list, ncp, nc_dst); numhotneg--; } else { mtx_assert(&neglist->nl_lock, MA_OWNED); TAILQ_REMOVE(&neglist->nl_list, ncp, nc_dst); } if (list_locked) mtx_unlock(&neglist->nl_lock); if (hot_locked) mtx_unlock(&ncneg_hot.nl_lock); atomic_subtract_rel_long(&numneg, 1); } static void cache_negative_shrink_select(int start, struct namecache **ncpp, struct neglist **neglistpp) { struct neglist *neglist; struct namecache *ncp; int i; *ncpp = ncp = NULL; neglist = NULL; for (i = start; i < numneglists; i++) { neglist = &neglists[i]; if (TAILQ_FIRST(&neglist->nl_list) == NULL) continue; mtx_lock(&neglist->nl_lock); ncp = TAILQ_FIRST(&neglist->nl_list); if (ncp != NULL) break; mtx_unlock(&neglist->nl_lock); } *neglistpp = neglist; *ncpp = ncp; } static void cache_negative_zap_one(void) { struct namecache *ncp, *ncp2; struct neglist *neglist; struct mtx *dvlp; struct rwlock *blp; if (mtx_owner(&ncneg_shrink_lock) != NULL || !mtx_trylock(&ncneg_shrink_lock)) { counter_u64_add(shrinking_skipped, 1); return; } mtx_lock(&ncneg_hot.nl_lock); ncp = TAILQ_FIRST(&ncneg_hot.nl_list); if (ncp != NULL) { neglist = NCP2NEGLIST(ncp); mtx_lock(&neglist->nl_lock); TAILQ_REMOVE(&ncneg_hot.nl_list, ncp, nc_dst); TAILQ_INSERT_TAIL(&neglist->nl_list, ncp, nc_dst); ncp->nc_flag &= ~NCF_HOTNEGATIVE; numhotneg--; mtx_unlock(&neglist->nl_lock); } mtx_unlock(&ncneg_hot.nl_lock); cache_negative_shrink_select(shrink_list_turn, &ncp, &neglist); shrink_list_turn++; if (shrink_list_turn == numneglists) shrink_list_turn = 0; if (ncp == NULL && shrink_list_turn == 0) cache_negative_shrink_select(shrink_list_turn, &ncp, &neglist); mtx_unlock(&ncneg_shrink_lock); if (ncp == NULL) return; MPASS(ncp->nc_flag & NCF_NEGATIVE); dvlp = VP2VNODELOCK(ncp->nc_dvp); blp = NCP2BUCKETLOCK(ncp); mtx_unlock(&neglist->nl_lock); mtx_lock(dvlp); rw_wlock(blp); mtx_lock(&neglist->nl_lock); ncp2 = TAILQ_FIRST(&neglist->nl_list); if (ncp != ncp2 || dvlp != VP2VNODELOCK(ncp2->nc_dvp) || blp != NCP2BUCKETLOCK(ncp2) || !(ncp2->nc_flag & NCF_NEGATIVE)) { ncp = NULL; } else { SDT_PROBE2(vfs, namecache, shrink_negative, done, ncp->nc_dvp, ncp->nc_name); cache_zap_locked(ncp, true); counter_u64_add(numneg_evicted, 1); } mtx_unlock(&neglist->nl_lock); rw_wunlock(blp); mtx_unlock(dvlp); cache_free(ncp); } /* * cache_zap_locked(): * * Removes a namecache entry from cache, whether it contains an actual * pointer to a vnode or if it is just a negative cache entry. */ static void cache_zap_locked(struct namecache *ncp, bool neg_locked) { if (!(ncp->nc_flag & NCF_NEGATIVE)) cache_assert_vnode_locked(ncp->nc_vp); cache_assert_vnode_locked(ncp->nc_dvp); cache_assert_bucket_locked(ncp, RA_WLOCKED); CTR2(KTR_VFS, "cache_zap(%p) vp %p", ncp, (ncp->nc_flag & NCF_NEGATIVE) ? NULL : ncp->nc_vp); LIST_REMOVE(ncp, nc_hash); if (!(ncp->nc_flag & NCF_NEGATIVE)) { SDT_PROBE3(vfs, namecache, zap, done, ncp->nc_dvp, ncp->nc_name, ncp->nc_vp); TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst, ncp, nc_dst); if (ncp == ncp->nc_vp->v_cache_dd) ncp->nc_vp->v_cache_dd = NULL; } else { SDT_PROBE2(vfs, namecache, zap_negative, done, ncp->nc_dvp, ncp->nc_name); cache_negative_remove(ncp, neg_locked); } if (ncp->nc_flag & NCF_ISDOTDOT) { if (ncp == ncp->nc_dvp->v_cache_dd) ncp->nc_dvp->v_cache_dd = NULL; } else { LIST_REMOVE(ncp, nc_src); if (LIST_EMPTY(&ncp->nc_dvp->v_cache_src)) { ncp->nc_flag |= NCF_DVDROP; counter_u64_add(numcachehv, -1); } } atomic_subtract_rel_long(&numcache, 1); } static void cache_zap_negative_locked_vnode_kl(struct namecache *ncp, struct vnode *vp) { struct rwlock *blp; MPASS(ncp->nc_dvp == vp); MPASS(ncp->nc_flag & NCF_NEGATIVE); cache_assert_vnode_locked(vp); blp = NCP2BUCKETLOCK(ncp); rw_wlock(blp); cache_zap_locked(ncp, false); rw_wunlock(blp); } static bool cache_zap_locked_vnode_kl2(struct namecache *ncp, struct vnode *vp, struct mtx **vlpp) { struct mtx *pvlp, *vlp1, *vlp2, *to_unlock; struct rwlock *blp; MPASS(vp == ncp->nc_dvp || vp == ncp->nc_vp); cache_assert_vnode_locked(vp); if (ncp->nc_flag & NCF_NEGATIVE) { if (*vlpp != NULL) { mtx_unlock(*vlpp); *vlpp = NULL; } cache_zap_negative_locked_vnode_kl(ncp, vp); return (true); } pvlp = VP2VNODELOCK(vp); blp = NCP2BUCKETLOCK(ncp); vlp1 = VP2VNODELOCK(ncp->nc_dvp); vlp2 = VP2VNODELOCK(ncp->nc_vp); if (*vlpp == vlp1 || *vlpp == vlp2) { to_unlock = *vlpp; *vlpp = NULL; } else { if (*vlpp != NULL) { mtx_unlock(*vlpp); *vlpp = NULL; } cache_sort_vnodes(&vlp1, &vlp2); if (vlp1 == pvlp) { mtx_lock(vlp2); to_unlock = vlp2; } else { if (!mtx_trylock(vlp1)) goto out_relock; to_unlock = vlp1; } } rw_wlock(blp); cache_zap_locked(ncp, false); rw_wunlock(blp); if (to_unlock != NULL) mtx_unlock(to_unlock); return (true); out_relock: mtx_unlock(vlp2); mtx_lock(vlp1); mtx_lock(vlp2); MPASS(*vlpp == NULL); *vlpp = vlp1; return (false); } static int __noinline cache_zap_locked_vnode(struct namecache *ncp, struct vnode *vp) { struct mtx *pvlp, *vlp1, *vlp2, *to_unlock; struct rwlock *blp; int error = 0; MPASS(vp == ncp->nc_dvp || vp == ncp->nc_vp); cache_assert_vnode_locked(vp); pvlp = VP2VNODELOCK(vp); if (ncp->nc_flag & NCF_NEGATIVE) { cache_zap_negative_locked_vnode_kl(ncp, vp); goto out; } blp = NCP2BUCKETLOCK(ncp); vlp1 = VP2VNODELOCK(ncp->nc_dvp); vlp2 = VP2VNODELOCK(ncp->nc_vp); cache_sort_vnodes(&vlp1, &vlp2); if (vlp1 == pvlp) { mtx_lock(vlp2); to_unlock = vlp2; } else { if (!mtx_trylock(vlp1)) { error = EAGAIN; goto out; } to_unlock = vlp1; } rw_wlock(blp); cache_zap_locked(ncp, false); rw_wunlock(blp); mtx_unlock(to_unlock); out: mtx_unlock(pvlp); return (error); } /* * If trylocking failed we can get here. We know enough to take all needed locks * in the right order and re-lookup the entry. */ static int cache_zap_unlocked_bucket(struct namecache *ncp, struct componentname *cnp, struct vnode *dvp, struct mtx *dvlp, struct mtx *vlp, uint32_t hash, struct rwlock *blp) { struct namecache *rncp; cache_assert_bucket_locked(ncp, RA_UNLOCKED); cache_sort_vnodes(&dvlp, &vlp); cache_lock_vnodes(dvlp, vlp); rw_wlock(blp); LIST_FOREACH(rncp, (NCHHASH(hash)), nc_hash) { if (rncp == ncp && rncp->nc_dvp == dvp && rncp->nc_nlen == cnp->cn_namelen && !bcmp(rncp->nc_name, cnp->cn_nameptr, rncp->nc_nlen)) break; } if (rncp != NULL) { cache_zap_locked(rncp, false); rw_wunlock(blp); cache_unlock_vnodes(dvlp, vlp); counter_u64_add(zap_and_exit_bucket_relock_success, 1); return (0); } rw_wunlock(blp); cache_unlock_vnodes(dvlp, vlp); return (EAGAIN); } static int __noinline cache_zap_wlocked_bucket(struct namecache *ncp, struct componentname *cnp, uint32_t hash, struct rwlock *blp) { struct mtx *dvlp, *vlp; struct vnode *dvp; cache_assert_bucket_locked(ncp, RA_WLOCKED); dvlp = VP2VNODELOCK(ncp->nc_dvp); vlp = NULL; if (!(ncp->nc_flag & NCF_NEGATIVE)) vlp = VP2VNODELOCK(ncp->nc_vp); if (cache_trylock_vnodes(dvlp, vlp) == 0) { cache_zap_locked(ncp, false); rw_wunlock(blp); cache_unlock_vnodes(dvlp, vlp); return (0); } dvp = ncp->nc_dvp; rw_wunlock(blp); return (cache_zap_unlocked_bucket(ncp, cnp, dvp, dvlp, vlp, hash, blp)); } static int __noinline cache_zap_rlocked_bucket(struct namecache *ncp, struct componentname *cnp, uint32_t hash, struct rwlock *blp) { struct mtx *dvlp, *vlp; struct vnode *dvp; cache_assert_bucket_locked(ncp, RA_RLOCKED); dvlp = VP2VNODELOCK(ncp->nc_dvp); vlp = NULL; if (!(ncp->nc_flag & NCF_NEGATIVE)) vlp = VP2VNODELOCK(ncp->nc_vp); if (cache_trylock_vnodes(dvlp, vlp) == 0) { rw_runlock(blp); rw_wlock(blp); cache_zap_locked(ncp, false); rw_wunlock(blp); cache_unlock_vnodes(dvlp, vlp); return (0); } dvp = ncp->nc_dvp; rw_runlock(blp); return (cache_zap_unlocked_bucket(ncp, cnp, dvp, dvlp, vlp, hash, blp)); } static int cache_zap_wlocked_bucket_kl(struct namecache *ncp, struct rwlock *blp, struct mtx **vlpp1, struct mtx **vlpp2) { struct mtx *dvlp, *vlp; cache_assert_bucket_locked(ncp, RA_WLOCKED); dvlp = VP2VNODELOCK(ncp->nc_dvp); vlp = NULL; if (!(ncp->nc_flag & NCF_NEGATIVE)) vlp = VP2VNODELOCK(ncp->nc_vp); cache_sort_vnodes(&dvlp, &vlp); if (*vlpp1 == dvlp && *vlpp2 == vlp) { cache_zap_locked(ncp, false); cache_unlock_vnodes(dvlp, vlp); *vlpp1 = NULL; *vlpp2 = NULL; return (0); } if (*vlpp1 != NULL) mtx_unlock(*vlpp1); if (*vlpp2 != NULL) mtx_unlock(*vlpp2); *vlpp1 = NULL; *vlpp2 = NULL; if (cache_trylock_vnodes(dvlp, vlp) == 0) { cache_zap_locked(ncp, false); cache_unlock_vnodes(dvlp, vlp); return (0); } rw_wunlock(blp); *vlpp1 = dvlp; *vlpp2 = vlp; if (*vlpp1 != NULL) mtx_lock(*vlpp1); mtx_lock(*vlpp2); rw_wlock(blp); return (EAGAIN); } static void cache_lookup_unlock(struct rwlock *blp, struct mtx *vlp) { if (blp != NULL) { rw_runlock(blp); } else { mtx_unlock(vlp); } } static int __noinline cache_lookup_dot(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct timespec *tsp, int *ticksp) { int ltype; *vpp = dvp; CTR2(KTR_VFS, "cache_lookup(%p, %s) found via .", dvp, cnp->cn_nameptr); counter_u64_add(dothits, 1); SDT_PROBE3(vfs, namecache, lookup, hit, dvp, ".", *vpp); if (tsp != NULL) timespecclear(tsp); if (ticksp != NULL) *ticksp = ticks; vrefact(*vpp); /* * When we lookup "." we still can be asked to lock it * differently... */ ltype = cnp->cn_lkflags & LK_TYPE_MASK; if (ltype != VOP_ISLOCKED(*vpp)) { if (ltype == LK_EXCLUSIVE) { vn_lock(*vpp, LK_UPGRADE | LK_RETRY); if (VN_IS_DOOMED((*vpp))) { /* forced unmount */ vrele(*vpp); *vpp = NULL; return (ENOENT); } } else vn_lock(*vpp, LK_DOWNGRADE | LK_RETRY); } return (-1); } static __noinline int cache_lookup_nomakeentry(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct timespec *tsp, int *ticksp) { struct namecache *ncp; struct rwlock *blp; struct mtx *dvlp, *dvlp2; uint32_t hash; int error; if (cnp->cn_namelen == 2 && cnp->cn_nameptr[0] == '.' && cnp->cn_nameptr[1] == '.') { counter_u64_add(dotdothits, 1); dvlp = VP2VNODELOCK(dvp); dvlp2 = NULL; mtx_lock(dvlp); retry_dotdot: ncp = dvp->v_cache_dd; if (ncp == NULL) { SDT_PROBE3(vfs, namecache, lookup, miss, dvp, "..", NULL); mtx_unlock(dvlp); if (dvlp2 != NULL) mtx_unlock(dvlp2); return (0); } if ((ncp->nc_flag & NCF_ISDOTDOT) != 0) { if (ncp->nc_dvp != dvp) panic("dvp %p v_cache_dd %p\n", dvp, ncp); if (!cache_zap_locked_vnode_kl2(ncp, dvp, &dvlp2)) goto retry_dotdot; MPASS(dvp->v_cache_dd == NULL); mtx_unlock(dvlp); if (dvlp2 != NULL) mtx_unlock(dvlp2); cache_free(ncp); } else { dvp->v_cache_dd = NULL; mtx_unlock(dvlp); if (dvlp2 != NULL) mtx_unlock(dvlp2); } return (0); } hash = cache_get_hash(cnp->cn_nameptr, cnp->cn_namelen, dvp); blp = HASH2BUCKETLOCK(hash); retry: if (LIST_EMPTY(NCHHASH(hash))) goto out_no_entry; rw_wlock(blp); LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) { counter_u64_add(numchecks, 1); if (ncp->nc_dvp == dvp && ncp->nc_nlen == cnp->cn_namelen && !bcmp(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen)) break; } /* We failed to find an entry */ if (ncp == NULL) { rw_wunlock(blp); goto out_no_entry; } error = cache_zap_wlocked_bucket(ncp, cnp, hash, blp); if (__predict_false(error != 0)) { zap_and_exit_bucket_fail++; cache_maybe_yield(); goto retry; } counter_u64_add(numposzaps, 1); cache_free(ncp); return (0); out_no_entry: SDT_PROBE3(vfs, namecache, lookup, miss, dvp, cnp->cn_nameptr, NULL); counter_u64_add(nummisszap, 1); return (0); } /** * Lookup a name in the name cache * * # Arguments * * - dvp: Parent directory in which to search. * - vpp: Return argument. Will contain desired vnode on cache hit. * - cnp: Parameters of the name search. The most interesting bits of * the cn_flags field have the following meanings: * - MAKEENTRY: If clear, free an entry from the cache rather than look * it up. * - ISDOTDOT: Must be set if and only if cn_nameptr == ".." * - tsp: Return storage for cache timestamp. On a successful (positive * or negative) lookup, tsp will be filled with any timespec that * was stored when this cache entry was created. However, it will * be clear for "." entries. * - ticks: Return storage for alternate cache timestamp. On a successful * (positive or negative) lookup, it will contain the ticks value * that was current when the cache entry was created, unless cnp * was ".". * * # Returns * * - -1: A positive cache hit. vpp will contain the desired vnode. * - ENOENT: A negative cache hit, or dvp was recycled out from under us due * to a forced unmount. vpp will not be modified. If the entry * is a whiteout, then the ISWHITEOUT flag will be set in * cnp->cn_flags. * - 0: A cache miss. vpp will not be modified. * * # Locking * * On a cache hit, vpp will be returned locked and ref'd. If we're looking up * .., dvp is unlocked. If we're looking up . an extra ref is taken, but the * lock is not recursively acquired. */ int cache_lookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct timespec *tsp, int *ticksp) { struct namecache_ts *ncp_ts; struct namecache *ncp; struct rwlock *blp; struct mtx *dvlp; uint32_t hash; enum vgetstate vs; int error, ltype; #ifdef DEBUG_CACHE if (__predict_false(!doingcache)) { cnp->cn_flags &= ~MAKEENTRY; return (0); } #endif counter_u64_add(numcalls, 1); if (__predict_false(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.')) return (cache_lookup_dot(dvp, vpp, cnp, tsp, ticksp)); if ((cnp->cn_flags & MAKEENTRY) == 0) return (cache_lookup_nomakeentry(dvp, vpp, cnp, tsp, ticksp)); retry: blp = NULL; dvlp = NULL; error = 0; if (cnp->cn_namelen == 2 && cnp->cn_nameptr[0] == '.' && cnp->cn_nameptr[1] == '.') { counter_u64_add(dotdothits, 1); dvlp = VP2VNODELOCK(dvp); mtx_lock(dvlp); ncp = dvp->v_cache_dd; if (ncp == NULL) { SDT_PROBE3(vfs, namecache, lookup, miss, dvp, "..", NULL); mtx_unlock(dvlp); return (0); } if ((ncp->nc_flag & NCF_ISDOTDOT) != 0) { if (ncp->nc_flag & NCF_NEGATIVE) *vpp = NULL; else *vpp = ncp->nc_vp; } else *vpp = ncp->nc_dvp; /* Return failure if negative entry was found. */ if (*vpp == NULL) goto negative_success; CTR3(KTR_VFS, "cache_lookup(%p, %s) found %p via ..", dvp, cnp->cn_nameptr, *vpp); SDT_PROBE3(vfs, namecache, lookup, hit, dvp, "..", *vpp); cache_out_ts(ncp, tsp, ticksp); if ((ncp->nc_flag & (NCF_ISDOTDOT | NCF_DTS)) == NCF_DTS && tsp != NULL) { ncp_ts = __containerof(ncp, struct namecache_ts, nc_nc); *tsp = ncp_ts->nc_dotdottime; } goto success; } hash = cache_get_hash(cnp->cn_nameptr, cnp->cn_namelen, dvp); blp = HASH2BUCKETLOCK(hash); rw_rlock(blp); LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) { counter_u64_add(numchecks, 1); if (ncp->nc_dvp == dvp && ncp->nc_nlen == cnp->cn_namelen && !bcmp(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen)) break; } /* We failed to find an entry */ if (__predict_false(ncp == NULL)) { rw_runlock(blp); SDT_PROBE3(vfs, namecache, lookup, miss, dvp, cnp->cn_nameptr, NULL); counter_u64_add(nummiss, 1); return (0); } if (ncp->nc_flag & NCF_NEGATIVE) goto negative_success; /* We found a "positive" match, return the vnode */ counter_u64_add(numposhits, 1); *vpp = ncp->nc_vp; CTR4(KTR_VFS, "cache_lookup(%p, %s) found %p via ncp %p", dvp, cnp->cn_nameptr, *vpp, ncp); SDT_PROBE3(vfs, namecache, lookup, hit, dvp, ncp->nc_name, *vpp); cache_out_ts(ncp, tsp, ticksp); success: /* * On success we return a locked and ref'd vnode as per the lookup * protocol. */ MPASS(dvp != *vpp); ltype = 0; /* silence gcc warning */ if (cnp->cn_flags & ISDOTDOT) { ltype = VOP_ISLOCKED(dvp); VOP_UNLOCK(dvp); } vs = vget_prep(*vpp); cache_lookup_unlock(blp, dvlp); error = vget_finish(*vpp, cnp->cn_lkflags, vs); if (cnp->cn_flags & ISDOTDOT) { vn_lock(dvp, ltype | LK_RETRY); if (VN_IS_DOOMED(dvp)) { if (error == 0) vput(*vpp); *vpp = NULL; return (ENOENT); } } if (error) { *vpp = NULL; goto retry; } if ((cnp->cn_flags & ISLASTCN) && (cnp->cn_lkflags & LK_TYPE_MASK) == LK_EXCLUSIVE) { ASSERT_VOP_ELOCKED(*vpp, "cache_lookup"); } return (-1); negative_success: /* We found a negative match, and want to create it, so purge */ if (cnp->cn_nameiop == CREATE) { counter_u64_add(numnegzaps, 1); goto zap_and_exit; } counter_u64_add(numneghits, 1); cache_negative_hit(ncp); if (ncp->nc_flag & NCF_WHITE) cnp->cn_flags |= ISWHITEOUT; SDT_PROBE2(vfs, namecache, lookup, hit__negative, dvp, ncp->nc_name); cache_out_ts(ncp, tsp, ticksp); cache_lookup_unlock(blp, dvlp); return (ENOENT); zap_and_exit: if (blp != NULL) error = cache_zap_rlocked_bucket(ncp, cnp, hash, blp); else error = cache_zap_locked_vnode(ncp, dvp); if (__predict_false(error != 0)) { zap_and_exit_bucket_fail2++; cache_maybe_yield(); goto retry; } cache_free(ncp); return (0); } struct celockstate { struct mtx *vlp[3]; struct rwlock *blp[2]; }; CTASSERT((nitems(((struct celockstate *)0)->vlp) == 3)); CTASSERT((nitems(((struct celockstate *)0)->blp) == 2)); static inline void cache_celockstate_init(struct celockstate *cel) { bzero(cel, sizeof(*cel)); } static void cache_lock_vnodes_cel(struct celockstate *cel, struct vnode *vp, struct vnode *dvp) { struct mtx *vlp1, *vlp2; MPASS(cel->vlp[0] == NULL); MPASS(cel->vlp[1] == NULL); MPASS(cel->vlp[2] == NULL); MPASS(vp != NULL || dvp != NULL); vlp1 = VP2VNODELOCK(vp); vlp2 = VP2VNODELOCK(dvp); cache_sort_vnodes(&vlp1, &vlp2); if (vlp1 != NULL) { mtx_lock(vlp1); cel->vlp[0] = vlp1; } mtx_lock(vlp2); cel->vlp[1] = vlp2; } static void cache_unlock_vnodes_cel(struct celockstate *cel) { MPASS(cel->vlp[0] != NULL || cel->vlp[1] != NULL); if (cel->vlp[0] != NULL) mtx_unlock(cel->vlp[0]); if (cel->vlp[1] != NULL) mtx_unlock(cel->vlp[1]); if (cel->vlp[2] != NULL) mtx_unlock(cel->vlp[2]); } static bool cache_lock_vnodes_cel_3(struct celockstate *cel, struct vnode *vp) { struct mtx *vlp; bool ret; cache_assert_vlp_locked(cel->vlp[0]); cache_assert_vlp_locked(cel->vlp[1]); MPASS(cel->vlp[2] == NULL); MPASS(vp != NULL); vlp = VP2VNODELOCK(vp); ret = true; if (vlp >= cel->vlp[1]) { mtx_lock(vlp); } else { if (mtx_trylock(vlp)) goto out; cache_lock_vnodes_cel_3_failures++; cache_unlock_vnodes_cel(cel); if (vlp < cel->vlp[0]) { mtx_lock(vlp); mtx_lock(cel->vlp[0]); mtx_lock(cel->vlp[1]); } else { if (cel->vlp[0] != NULL) mtx_lock(cel->vlp[0]); mtx_lock(vlp); mtx_lock(cel->vlp[1]); } ret = false; } out: cel->vlp[2] = vlp; return (ret); } static void cache_lock_buckets_cel(struct celockstate *cel, struct rwlock *blp1, struct rwlock *blp2) { MPASS(cel->blp[0] == NULL); MPASS(cel->blp[1] == NULL); cache_sort_vnodes(&blp1, &blp2); if (blp1 != NULL) { rw_wlock(blp1); cel->blp[0] = blp1; } rw_wlock(blp2); cel->blp[1] = blp2; } static void cache_unlock_buckets_cel(struct celockstate *cel) { if (cel->blp[0] != NULL) rw_wunlock(cel->blp[0]); rw_wunlock(cel->blp[1]); } /* * Lock part of the cache affected by the insertion. * * This means vnodelocks for dvp, vp and the relevant bucketlock. * However, insertion can result in removal of an old entry. In this * case we have an additional vnode and bucketlock pair to lock. If the * entry is negative, ncelock is locked instead of the vnode. * * That is, in the worst case we have to lock 3 vnodes and 2 bucketlocks, while * preserving the locking order (smaller address first). */ static void cache_enter_lock(struct celockstate *cel, struct vnode *dvp, struct vnode *vp, uint32_t hash) { struct namecache *ncp; struct rwlock *blps[2]; blps[0] = HASH2BUCKETLOCK(hash); for (;;) { blps[1] = NULL; cache_lock_vnodes_cel(cel, dvp, vp); if (vp == NULL || vp->v_type != VDIR) break; ncp = vp->v_cache_dd; if (ncp == NULL) break; if ((ncp->nc_flag & NCF_ISDOTDOT) == 0) break; MPASS(ncp->nc_dvp == vp); blps[1] = NCP2BUCKETLOCK(ncp); if (ncp->nc_flag & NCF_NEGATIVE) break; if (cache_lock_vnodes_cel_3(cel, ncp->nc_vp)) break; /* * All vnodes got re-locked. Re-validate the state and if * nothing changed we are done. Otherwise restart. */ if (ncp == vp->v_cache_dd && (ncp->nc_flag & NCF_ISDOTDOT) != 0 && blps[1] == NCP2BUCKETLOCK(ncp) && VP2VNODELOCK(ncp->nc_vp) == cel->vlp[2]) break; cache_unlock_vnodes_cel(cel); cel->vlp[0] = NULL; cel->vlp[1] = NULL; cel->vlp[2] = NULL; } cache_lock_buckets_cel(cel, blps[0], blps[1]); } static void cache_enter_lock_dd(struct celockstate *cel, struct vnode *dvp, struct vnode *vp, uint32_t hash) { struct namecache *ncp; struct rwlock *blps[2]; blps[0] = HASH2BUCKETLOCK(hash); for (;;) { blps[1] = NULL; cache_lock_vnodes_cel(cel, dvp, vp); ncp = dvp->v_cache_dd; if (ncp == NULL) break; if ((ncp->nc_flag & NCF_ISDOTDOT) == 0) break; MPASS(ncp->nc_dvp == dvp); blps[1] = NCP2BUCKETLOCK(ncp); if (ncp->nc_flag & NCF_NEGATIVE) break; if (cache_lock_vnodes_cel_3(cel, ncp->nc_vp)) break; if (ncp == dvp->v_cache_dd && (ncp->nc_flag & NCF_ISDOTDOT) != 0 && blps[1] == NCP2BUCKETLOCK(ncp) && VP2VNODELOCK(ncp->nc_vp) == cel->vlp[2]) break; cache_unlock_vnodes_cel(cel); cel->vlp[0] = NULL; cel->vlp[1] = NULL; cel->vlp[2] = NULL; } cache_lock_buckets_cel(cel, blps[0], blps[1]); } static void cache_enter_unlock(struct celockstate *cel) { cache_unlock_buckets_cel(cel); cache_unlock_vnodes_cel(cel); } static void __noinline cache_enter_dotdot_prep(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { struct celockstate cel; struct namecache *ncp; uint32_t hash; int len; if (dvp->v_cache_dd == NULL) return; len = cnp->cn_namelen; cache_celockstate_init(&cel); hash = cache_get_hash(cnp->cn_nameptr, len, dvp); cache_enter_lock_dd(&cel, dvp, vp, hash); ncp = dvp->v_cache_dd; if (ncp != NULL && (ncp->nc_flag & NCF_ISDOTDOT)) { KASSERT(ncp->nc_dvp == dvp, ("wrong isdotdot parent")); cache_zap_locked(ncp, false); } else { ncp = NULL; } dvp->v_cache_dd = NULL; cache_enter_unlock(&cel); cache_free(ncp); } /* * Add an entry to the cache. */ void cache_enter_time(struct vnode *dvp, struct vnode *vp, struct componentname *cnp, struct timespec *tsp, struct timespec *dtsp) { struct celockstate cel; struct namecache *ncp, *n2, *ndd; struct namecache_ts *ncp_ts, *n2_ts; struct nchashhead *ncpp; uint32_t hash; int flag; int len; u_long lnumcache; CTR3(KTR_VFS, "cache_enter(%p, %p, %s)", dvp, vp, cnp->cn_nameptr); VNASSERT(vp == NULL || !VN_IS_DOOMED(vp), vp, ("cache_enter: Adding a doomed vnode")); VNASSERT(dvp == NULL || !VN_IS_DOOMED(dvp), dvp, ("cache_enter: Doomed vnode used as src")); #ifdef DEBUG_CACHE if (__predict_false(!doingcache)) return; #endif flag = 0; if (__predict_false(cnp->cn_nameptr[0] == '.')) { if (cnp->cn_namelen == 1) return; if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') { cache_enter_dotdot_prep(dvp, vp, cnp); flag = NCF_ISDOTDOT; } } /* * Avoid blowout in namecache entries. */ lnumcache = atomic_fetchadd_long(&numcache, 1) + 1; if (__predict_false(lnumcache >= ncsize)) { atomic_add_long(&numcache, -1); return; } cache_celockstate_init(&cel); ndd = NULL; ncp_ts = NULL; /* * Calculate the hash key and setup as much of the new * namecache entry as possible before acquiring the lock. */ ncp = cache_alloc(cnp->cn_namelen, tsp != NULL); ncp->nc_flag = flag; ncp->nc_vp = vp; if (vp == NULL) ncp->nc_flag |= NCF_NEGATIVE; ncp->nc_dvp = dvp; if (tsp != NULL) { ncp_ts = __containerof(ncp, struct namecache_ts, nc_nc); ncp_ts->nc_time = *tsp; ncp_ts->nc_ticks = ticks; ncp_ts->nc_nc.nc_flag |= NCF_TS; if (dtsp != NULL) { ncp_ts->nc_dotdottime = *dtsp; ncp_ts->nc_nc.nc_flag |= NCF_DTS; } } len = ncp->nc_nlen = cnp->cn_namelen; hash = cache_get_hash(cnp->cn_nameptr, len, dvp); strlcpy(ncp->nc_name, cnp->cn_nameptr, len + 1); cache_enter_lock(&cel, dvp, vp, hash); /* * See if this vnode or negative entry is already in the cache * with this name. This can happen with concurrent lookups of * the same path name. */ ncpp = NCHHASH(hash); LIST_FOREACH(n2, ncpp, nc_hash) { if (n2->nc_dvp == dvp && n2->nc_nlen == cnp->cn_namelen && !bcmp(n2->nc_name, cnp->cn_nameptr, n2->nc_nlen)) { if (tsp != NULL) { KASSERT((n2->nc_flag & NCF_TS) != 0, ("no NCF_TS")); n2_ts = __containerof(n2, struct namecache_ts, nc_nc); n2_ts->nc_time = ncp_ts->nc_time; n2_ts->nc_ticks = ncp_ts->nc_ticks; if (dtsp != NULL) { n2_ts->nc_dotdottime = ncp_ts->nc_dotdottime; if (ncp->nc_flag & NCF_NEGATIVE) mtx_lock(&ncneg_hot.nl_lock); n2_ts->nc_nc.nc_flag |= NCF_DTS; if (ncp->nc_flag & NCF_NEGATIVE) mtx_unlock(&ncneg_hot.nl_lock); } } goto out_unlock_free; } } if (flag == NCF_ISDOTDOT) { /* * See if we are trying to add .. entry, but some other lookup * has populated v_cache_dd pointer already. */ if (dvp->v_cache_dd != NULL) goto out_unlock_free; KASSERT(vp == NULL || vp->v_type == VDIR, ("wrong vnode type %p", vp)); dvp->v_cache_dd = ncp; } if (vp != NULL) { if (vp->v_type == VDIR) { if (flag != NCF_ISDOTDOT) { /* * For this case, the cache entry maps both the * directory name in it and the name ".." for the * directory's parent. */ if ((ndd = vp->v_cache_dd) != NULL) { if ((ndd->nc_flag & NCF_ISDOTDOT) != 0) cache_zap_locked(ndd, false); else ndd = NULL; } vp->v_cache_dd = ncp; } } else { vp->v_cache_dd = NULL; } } if (flag != NCF_ISDOTDOT) { if (LIST_EMPTY(&dvp->v_cache_src)) { vhold(dvp); counter_u64_add(numcachehv, 1); } LIST_INSERT_HEAD(&dvp->v_cache_src, ncp, nc_src); } /* * Insert the new namecache entry into the appropriate chain * within the cache entries table. */ LIST_INSERT_HEAD(ncpp, ncp, nc_hash); /* * If the entry is "negative", we place it into the * "negative" cache queue, otherwise, we place it into the * destination vnode's cache entries queue. */ if (vp != NULL) { TAILQ_INSERT_HEAD(&vp->v_cache_dst, ncp, nc_dst); SDT_PROBE3(vfs, namecache, enter, done, dvp, ncp->nc_name, vp); } else { if (cnp->cn_flags & ISWHITEOUT) ncp->nc_flag |= NCF_WHITE; cache_negative_insert(ncp, false); SDT_PROBE2(vfs, namecache, enter_negative, done, dvp, ncp->nc_name); } cache_enter_unlock(&cel); if (numneg * ncnegfactor > lnumcache) cache_negative_zap_one(); cache_free(ndd); return; out_unlock_free: cache_enter_unlock(&cel); cache_free(ncp); return; } static u_int cache_roundup_2(u_int val) { u_int res; for (res = 1; res <= val; res <<= 1) continue; return (res); } /* * Name cache initialization, from vfs_init() when we are booting */ static void nchinit(void *dummy __unused) { u_int i; cache_zone_small = uma_zcreate("S VFS Cache", sizeof(struct namecache) + CACHE_PATH_CUTOFF + 1, NULL, NULL, NULL, NULL, UMA_ALIGNOF(struct namecache), UMA_ZONE_ZINIT); cache_zone_small_ts = uma_zcreate("STS VFS Cache", sizeof(struct namecache_ts) + CACHE_PATH_CUTOFF + 1, NULL, NULL, NULL, NULL, UMA_ALIGNOF(struct namecache_ts), UMA_ZONE_ZINIT); cache_zone_large = uma_zcreate("L VFS Cache", sizeof(struct namecache) + NAME_MAX + 1, NULL, NULL, NULL, NULL, UMA_ALIGNOF(struct namecache), UMA_ZONE_ZINIT); cache_zone_large_ts = uma_zcreate("LTS VFS Cache", sizeof(struct namecache_ts) + NAME_MAX + 1, NULL, NULL, NULL, NULL, UMA_ALIGNOF(struct namecache_ts), UMA_ZONE_ZINIT); ncsize = desiredvnodes * ncsizefactor; nchashtbl = hashinit(desiredvnodes * 2, M_VFSCACHE, &nchash); ncbuckethash = cache_roundup_2(mp_ncpus * mp_ncpus) - 1; if (ncbuckethash < 7) /* arbitrarily chosen to avoid having one lock */ ncbuckethash = 7; if (ncbuckethash > nchash) ncbuckethash = nchash; bucketlocks = malloc(sizeof(*bucketlocks) * numbucketlocks, M_VFSCACHE, M_WAITOK | M_ZERO); for (i = 0; i < numbucketlocks; i++) rw_init_flags(&bucketlocks[i], "ncbuc", RW_DUPOK | RW_RECURSE); ncvnodehash = ncbuckethash; vnodelocks = malloc(sizeof(*vnodelocks) * numvnodelocks, M_VFSCACHE, M_WAITOK | M_ZERO); for (i = 0; i < numvnodelocks; i++) mtx_init(&vnodelocks[i], "ncvn", NULL, MTX_DUPOK | MTX_RECURSE); ncpurgeminvnodes = numbucketlocks * 2; ncneghash = 3; neglists = malloc(sizeof(*neglists) * numneglists, M_VFSCACHE, M_WAITOK | M_ZERO); for (i = 0; i < numneglists; i++) { mtx_init(&neglists[i].nl_lock, "ncnegl", NULL, MTX_DEF); TAILQ_INIT(&neglists[i].nl_list); } mtx_init(&ncneg_hot.nl_lock, "ncneglh", NULL, MTX_DEF); TAILQ_INIT(&ncneg_hot.nl_list); mtx_init(&ncneg_shrink_lock, "ncnegs", NULL, MTX_DEF); numcachehv = counter_u64_alloc(M_WAITOK); numcalls = counter_u64_alloc(M_WAITOK); dothits = counter_u64_alloc(M_WAITOK); dotdothits = counter_u64_alloc(M_WAITOK); numchecks = counter_u64_alloc(M_WAITOK); nummiss = counter_u64_alloc(M_WAITOK); nummisszap = counter_u64_alloc(M_WAITOK); numposzaps = counter_u64_alloc(M_WAITOK); numposhits = counter_u64_alloc(M_WAITOK); numnegzaps = counter_u64_alloc(M_WAITOK); numneghits = counter_u64_alloc(M_WAITOK); numfullpathcalls = counter_u64_alloc(M_WAITOK); numfullpathfail1 = counter_u64_alloc(M_WAITOK); numfullpathfail2 = counter_u64_alloc(M_WAITOK); numfullpathfail4 = counter_u64_alloc(M_WAITOK); numfullpathfound = counter_u64_alloc(M_WAITOK); zap_and_exit_bucket_relock_success = counter_u64_alloc(M_WAITOK); numneg_evicted = counter_u64_alloc(M_WAITOK); shrinking_skipped = counter_u64_alloc(M_WAITOK); } SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_SECOND, nchinit, NULL); void cache_changesize(u_long newmaxvnodes) { struct nchashhead *new_nchashtbl, *old_nchashtbl; u_long new_nchash, old_nchash; struct namecache *ncp; uint32_t hash; u_long newncsize; int i; newncsize = newmaxvnodes * ncsizefactor; newmaxvnodes = cache_roundup_2(newmaxvnodes * 2); if (newmaxvnodes < numbucketlocks) newmaxvnodes = numbucketlocks; new_nchashtbl = hashinit(newmaxvnodes, M_VFSCACHE, &new_nchash); /* If same hash table size, nothing to do */ if (nchash == new_nchash) { free(new_nchashtbl, M_VFSCACHE); return; } /* * Move everything from the old hash table to the new table. * None of the namecache entries in the table can be removed * because to do so, they have to be removed from the hash table. */ cache_lock_all_vnodes(); cache_lock_all_buckets(); old_nchashtbl = nchashtbl; old_nchash = nchash; nchashtbl = new_nchashtbl; nchash = new_nchash; for (i = 0; i <= old_nchash; i++) { while ((ncp = LIST_FIRST(&old_nchashtbl[i])) != NULL) { hash = cache_get_hash(ncp->nc_name, ncp->nc_nlen, ncp->nc_dvp); LIST_REMOVE(ncp, nc_hash); LIST_INSERT_HEAD(NCHHASH(hash), ncp, nc_hash); } } ncsize = newncsize; cache_unlock_all_buckets(); cache_unlock_all_vnodes(); free(old_nchashtbl, M_VFSCACHE); } /* * Invalidate all entries from and to a particular vnode. */ void cache_purge(struct vnode *vp) { TAILQ_HEAD(, namecache) ncps; struct namecache *ncp, *nnp; struct mtx *vlp, *vlp2; CTR1(KTR_VFS, "cache_purge(%p)", vp); SDT_PROBE1(vfs, namecache, purge, done, vp); if (LIST_EMPTY(&vp->v_cache_src) && TAILQ_EMPTY(&vp->v_cache_dst) && vp->v_cache_dd == NULL) return; TAILQ_INIT(&ncps); vlp = VP2VNODELOCK(vp); vlp2 = NULL; mtx_lock(vlp); retry: while (!LIST_EMPTY(&vp->v_cache_src)) { ncp = LIST_FIRST(&vp->v_cache_src); if (!cache_zap_locked_vnode_kl2(ncp, vp, &vlp2)) goto retry; TAILQ_INSERT_TAIL(&ncps, ncp, nc_dst); } while (!TAILQ_EMPTY(&vp->v_cache_dst)) { ncp = TAILQ_FIRST(&vp->v_cache_dst); if (!cache_zap_locked_vnode_kl2(ncp, vp, &vlp2)) goto retry; TAILQ_INSERT_TAIL(&ncps, ncp, nc_dst); } ncp = vp->v_cache_dd; if (ncp != NULL) { KASSERT(ncp->nc_flag & NCF_ISDOTDOT, ("lost dotdot link")); if (!cache_zap_locked_vnode_kl2(ncp, vp, &vlp2)) goto retry; TAILQ_INSERT_TAIL(&ncps, ncp, nc_dst); } KASSERT(vp->v_cache_dd == NULL, ("incomplete purge")); mtx_unlock(vlp); if (vlp2 != NULL) mtx_unlock(vlp2); TAILQ_FOREACH_SAFE(ncp, &ncps, nc_dst, nnp) { cache_free(ncp); } } /* * Invalidate all negative entries for a particular directory vnode. */ void cache_purge_negative(struct vnode *vp) { TAILQ_HEAD(, namecache) ncps; struct namecache *ncp, *nnp; struct mtx *vlp; CTR1(KTR_VFS, "cache_purge_negative(%p)", vp); SDT_PROBE1(vfs, namecache, purge_negative, done, vp); if (LIST_EMPTY(&vp->v_cache_src)) return; TAILQ_INIT(&ncps); vlp = VP2VNODELOCK(vp); mtx_lock(vlp); LIST_FOREACH_SAFE(ncp, &vp->v_cache_src, nc_src, nnp) { if (!(ncp->nc_flag & NCF_NEGATIVE)) continue; cache_zap_negative_locked_vnode_kl(ncp, vp); TAILQ_INSERT_TAIL(&ncps, ncp, nc_dst); } mtx_unlock(vlp); TAILQ_FOREACH_SAFE(ncp, &ncps, nc_dst, nnp) { cache_free(ncp); } } /* * Flush all entries referencing a particular filesystem. */ void cache_purgevfs(struct mount *mp, bool force) { TAILQ_HEAD(, namecache) ncps; struct mtx *vlp1, *vlp2; struct rwlock *blp; struct nchashhead *bucket; struct namecache *ncp, *nnp; u_long i, j, n_nchash; int error; /* Scan hash tables for applicable entries */ SDT_PROBE1(vfs, namecache, purgevfs, done, mp); if (!force && mp->mnt_nvnodelistsize <= ncpurgeminvnodes) return; TAILQ_INIT(&ncps); n_nchash = nchash + 1; vlp1 = vlp2 = NULL; for (i = 0; i < numbucketlocks; i++) { blp = (struct rwlock *)&bucketlocks[i]; rw_wlock(blp); for (j = i; j < n_nchash; j += numbucketlocks) { retry: bucket = &nchashtbl[j]; LIST_FOREACH_SAFE(ncp, bucket, nc_hash, nnp) { cache_assert_bucket_locked(ncp, RA_WLOCKED); if (ncp->nc_dvp->v_mount != mp) continue; error = cache_zap_wlocked_bucket_kl(ncp, blp, &vlp1, &vlp2); if (error != 0) goto retry; TAILQ_INSERT_HEAD(&ncps, ncp, nc_dst); } } rw_wunlock(blp); if (vlp1 == NULL && vlp2 == NULL) cache_maybe_yield(); } if (vlp1 != NULL) mtx_unlock(vlp1); if (vlp2 != NULL) mtx_unlock(vlp2); TAILQ_FOREACH_SAFE(ncp, &ncps, nc_dst, nnp) { cache_free(ncp); } } /* * Perform canonical checks and cache lookup and pass on to filesystem * through the vop_cachedlookup only if needed. */ int vfs_cache_lookup(struct vop_lookup_args *ap) { struct vnode *dvp; int error; struct vnode **vpp = ap->a_vpp; struct componentname *cnp = ap->a_cnp; int flags = cnp->cn_flags; *vpp = NULL; dvp = ap->a_dvp; if (dvp->v_type != VDIR) return (ENOTDIR); if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) return (EROFS); error = vn_dir_check_exec(dvp, cnp); if (error != 0) return (error); error = cache_lookup(dvp, vpp, cnp, NULL, NULL); if (error == 0) return (VOP_CACHEDLOOKUP(dvp, vpp, cnp)); if (error == -1) return (0); return (error); } /* Implementation of the getcwd syscall. */ int sys___getcwd(struct thread *td, struct __getcwd_args *uap) { char *buf, *retbuf; size_t buflen; int error; buflen = uap->buflen; if (__predict_false(buflen < 2)) return (EINVAL); if (buflen > MAXPATHLEN) buflen = MAXPATHLEN; buf = malloc(buflen, M_TEMP, M_WAITOK); error = vn_getcwd(td, buf, &retbuf, &buflen); if (error == 0) error = copyout(retbuf, uap->buf, buflen); free(buf, M_TEMP); return (error); } int vn_getcwd(struct thread *td, char *buf, char **retbuf, size_t *buflen) { struct filedesc *fdp; struct vnode *cdir, *rdir; int error; fdp = td->td_proc->p_fd; FILEDESC_SLOCK(fdp); cdir = fdp->fd_cdir; vrefact(cdir); rdir = fdp->fd_rdir; vrefact(rdir); FILEDESC_SUNLOCK(fdp); - error = vn_fullpath1(td, cdir, rdir, buf, retbuf, buflen); + error = vn_fullpath_any(td, cdir, rdir, buf, retbuf, buflen); vrele(rdir); vrele(cdir); #ifdef KTRACE if (KTRPOINT(curthread, KTR_NAMEI) && error == 0) ktrnamei(*retbuf); #endif return (error); } +static int +kern___realpathat(struct thread *td, int fd, const char *path, char *buf, + size_t size, int flags, enum uio_seg pathseg) +{ + struct nameidata nd; + char *retbuf, *freebuf; + int error; + + if (flags != 0) + return (EINVAL); + NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | SAVENAME | WANTPARENT | AUDITVNODE1, + pathseg, path, fd, &cap_fstat_rights, td); + if ((error = namei(&nd)) != 0) + return (error); + error = vn_fullpath_hardlink(td, &nd, &retbuf, &freebuf, &size); + if (error == 0) { + error = copyout(retbuf, buf, size); + free(freebuf, M_TEMP); + } + NDFREE(&nd, 0); + return (error); +} + +int +sys___realpathat(struct thread *td, struct __realpathat_args *uap) +{ + + return (kern___realpathat(td, uap->fd, uap->path, uap->buf, uap->size, + uap->flags, UIO_USERSPACE)); +} + /* * Retrieve the full filesystem path that correspond to a vnode from the name * cache (if available) */ int vn_fullpath(struct thread *td, struct vnode *vn, char **retbuf, char **freebuf) { char *buf; struct filedesc *fdp; struct vnode *rdir; size_t buflen; int error; if (__predict_false(vn == NULL)) return (EINVAL); buflen = MAXPATHLEN; buf = malloc(buflen, M_TEMP, M_WAITOK); fdp = td->td_proc->p_fd; FILEDESC_SLOCK(fdp); rdir = fdp->fd_rdir; vrefact(rdir); FILEDESC_SUNLOCK(fdp); - error = vn_fullpath1(td, vn, rdir, buf, retbuf, &buflen); + error = vn_fullpath_any(td, vn, rdir, buf, retbuf, &buflen); vrele(rdir); if (!error) *freebuf = buf; else free(buf, M_TEMP); return (error); } /* * This function is similar to vn_fullpath, but it attempts to lookup the * pathname relative to the global root mount point. This is required for the * auditing sub-system, as audited pathnames must be absolute, relative to the * global root mount point. */ int vn_fullpath_global(struct thread *td, struct vnode *vn, char **retbuf, char **freebuf) { char *buf; size_t buflen; int error; if (__predict_false(vn == NULL)) return (EINVAL); buflen = MAXPATHLEN; buf = malloc(buflen, M_TEMP, M_WAITOK); - error = vn_fullpath1(td, vn, rootvnode, buf, retbuf, &buflen); + error = vn_fullpath_any(td, vn, rootvnode, buf, retbuf, &buflen); if (!error) *freebuf = buf; else free(buf, M_TEMP); return (error); } int vn_vptocnp(struct vnode **vp, struct ucred *cred, char *buf, size_t *buflen) { struct vnode *dvp; struct namecache *ncp; struct mtx *vlp; int error; vlp = VP2VNODELOCK(*vp); mtx_lock(vlp); TAILQ_FOREACH(ncp, &((*vp)->v_cache_dst), nc_dst) { if ((ncp->nc_flag & NCF_ISDOTDOT) == 0) break; } if (ncp != NULL) { if (*buflen < ncp->nc_nlen) { mtx_unlock(vlp); vrele(*vp); counter_u64_add(numfullpathfail4, 1); error = ENOMEM; SDT_PROBE3(vfs, namecache, fullpath, return, error, vp, NULL); return (error); } *buflen -= ncp->nc_nlen; memcpy(buf + *buflen, ncp->nc_name, ncp->nc_nlen); SDT_PROBE3(vfs, namecache, fullpath, hit, ncp->nc_dvp, ncp->nc_name, vp); dvp = *vp; *vp = ncp->nc_dvp; vref(*vp); mtx_unlock(vlp); vrele(dvp); return (0); } SDT_PROBE1(vfs, namecache, fullpath, miss, vp); mtx_unlock(vlp); vn_lock(*vp, LK_SHARED | LK_RETRY); error = VOP_VPTOCNP(*vp, &dvp, cred, buf, buflen); vput(*vp); if (error) { counter_u64_add(numfullpathfail2, 1); SDT_PROBE3(vfs, namecache, fullpath, return, error, vp, NULL); return (error); } *vp = dvp; if (VN_IS_DOOMED(dvp)) { /* forced unmount */ vrele(dvp); error = ENOENT; SDT_PROBE3(vfs, namecache, fullpath, return, error, vp, NULL); return (error); } /* * *vp has its use count incremented still. */ return (0); } /* - * The magic behind vn_getcwd() and vn_fullpath(). + * Resolve a directory to a pathname. + * + * The name of the directory can always be found in the namecache or fetched + * from the filesystem. There is also guaranteed to be only one parent, meaning + * we can just follow vnodes up until we find the root. + * + * The vnode must be referenced. */ static int -vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir, - char *buf, char **retbuf, size_t *len) +vn_fullpath_dir(struct thread *td, struct vnode *vp, struct vnode *rdir, + char *buf, char **retbuf, size_t *len, bool slash_prefixed, size_t addend) { - int error, slash_prefixed; #ifdef KDTRACE_HOOKS struct vnode *startvp = vp; #endif struct vnode *vp1; size_t buflen; + int error; + VNPASS(vp->v_type == VDIR || VN_IS_DOOMED(vp), vp); + VNPASS(vp->v_usecount > 0, vp); + buflen = *len; - buflen--; - buf[buflen] = '\0'; + if (!slash_prefixed) { + MPASS(*len >= 2); + buflen--; + buf[buflen] = '\0'; + } + error = 0; - slash_prefixed = 0; SDT_PROBE1(vfs, namecache, fullpath, entry, vp); counter_u64_add(numfullpathcalls, 1); - vref(vp); - if (vp->v_type != VDIR) { - error = vn_vptocnp(&vp, td->td_ucred, buf, &buflen); - if (error) - return (error); - if (buflen == 0) { - vrele(vp); - return (ENOMEM); - } - buf[--buflen] = '/'; - slash_prefixed = 1; - } while (vp != rdir && vp != rootvnode) { /* * The vp vnode must be already fully constructed, * since it is either found in namecache or obtained * from VOP_VPTOCNP(). We may test for VV_ROOT safely * without obtaining the vnode lock. */ if ((vp->v_vflag & VV_ROOT) != 0) { vn_lock(vp, LK_RETRY | LK_SHARED); /* * With the vnode locked, check for races with * unmount, forced or not. Note that we * already verified that vp is not equal to * the root vnode, which means that * mnt_vnodecovered can be NULL only for the * case of unmount. */ if (VN_IS_DOOMED(vp) || (vp1 = vp->v_mount->mnt_vnodecovered) == NULL || vp1->v_mountedhere != vp->v_mount) { vput(vp); error = ENOENT; SDT_PROBE3(vfs, namecache, fullpath, return, error, vp, NULL); break; } vref(vp1); vput(vp); vp = vp1; continue; } if (vp->v_type != VDIR) { vrele(vp); counter_u64_add(numfullpathfail1, 1); error = ENOTDIR; SDT_PROBE3(vfs, namecache, fullpath, return, error, vp, NULL); break; } error = vn_vptocnp(&vp, td->td_ucred, buf, &buflen); if (error) break; if (buflen == 0) { vrele(vp); error = ENOMEM; SDT_PROBE3(vfs, namecache, fullpath, return, error, startvp, NULL); break; } buf[--buflen] = '/'; - slash_prefixed = 1; + slash_prefixed = true; } if (error) return (error); if (!slash_prefixed) { if (buflen == 0) { vrele(vp); counter_u64_add(numfullpathfail4, 1); SDT_PROBE3(vfs, namecache, fullpath, return, ENOMEM, startvp, NULL); return (ENOMEM); } buf[--buflen] = '/'; } counter_u64_add(numfullpathfound, 1); vrele(vp); - SDT_PROBE3(vfs, namecache, fullpath, return, 0, startvp, buf + buflen); *retbuf = buf + buflen; + SDT_PROBE3(vfs, namecache, fullpath, return, 0, startvp, *retbuf); *len -= buflen; + *len += addend; return (0); +} + +/* + * Resolve an arbitrary vnode to a pathname. + * + * Note 2 caveats: + * - hardlinks are not tracked, thus if the vnode is not a directory this can + * resolve to a different path than the one used to find it + * - namecache is not mandatory, meaning names are not guaranteed to be added + * (in which case resolving fails) + */ +static int +vn_fullpath_any(struct thread *td, struct vnode *vp, struct vnode *rdir, + char *buf, char **retbuf, size_t *buflen) +{ + size_t orig_buflen; + bool slash_prefixed; + int error; + + if (*buflen < 2) + return (EINVAL); + + orig_buflen = *buflen; + + vref(vp); + slash_prefixed = false; + if (vp->v_type != VDIR) { + *buflen -= 1; + buf[*buflen] = '\0'; + error = vn_vptocnp(&vp, td->td_ucred, buf, buflen); + if (error) + return (error); + if (*buflen == 0) { + vrele(vp); + return (ENOMEM); + } + *buflen -= 1; + buf[*buflen] = '/'; + slash_prefixed = true; + } + + return (vn_fullpath_dir(td, vp, rdir, buf, retbuf, buflen, slash_prefixed, + orig_buflen - *buflen)); +} + +/* + * Resolve an arbitrary vnode to a pathname (taking care of hardlinks). + * + * Since the namecache does not track handlings, the caller is expected to first + * look up the target vnode with SAVENAME | WANTPARENT flags passed to namei. + * + * Then we have 2 cases: + * - if the found vnode is a directory, the path can be constructed just by + * fullowing names up the chain + * - otherwise we populate the buffer with the saved name and start resolving + * from the parent + */ +static int +vn_fullpath_hardlink(struct thread *td, struct nameidata *ndp, char **retbuf, + char **freebuf, size_t *buflen) +{ + char *buf, *tmpbuf; + struct filedesc *fdp; + struct vnode *rdir; + struct componentname *cnp; + struct vnode *vp; + size_t addend; + int error; + bool slash_prefixed; + + if (*buflen < 2) + return (EINVAL); + if (*buflen > MAXPATHLEN) + *buflen = MAXPATHLEN; + + slash_prefixed = false; + + buf = malloc(*buflen, M_TEMP, M_WAITOK); + fdp = td->td_proc->p_fd; + FILEDESC_SLOCK(fdp); + rdir = fdp->fd_rdir; + vrefact(rdir); + FILEDESC_SUNLOCK(fdp); + + addend = 0; + vp = ndp->ni_vp; + if (vp->v_type != VDIR) { + cnp = &ndp->ni_cnd; + addend = cnp->cn_namelen + 2; + if (*buflen < addend) { + error = ENOMEM; + goto out_bad; + } + *buflen -= addend; + tmpbuf = buf + *buflen; + tmpbuf[0] = '/'; + memcpy(&tmpbuf[1], cnp->cn_nameptr, cnp->cn_namelen); + tmpbuf[addend - 1] = '\0'; + slash_prefixed = true; + vp = ndp->ni_dvp; + } + + vref(vp); + error = vn_fullpath_dir(td, vp, rdir, buf, retbuf, buflen, slash_prefixed, addend); + if (error != 0) + goto out_bad; + + vrele(rdir); + *freebuf = buf; + + return (0); +out_bad: + vrele(rdir); + free(buf, M_TEMP); + return (error); } struct vnode * vn_dir_dd_ino(struct vnode *vp) { struct namecache *ncp; struct vnode *ddvp; struct mtx *vlp; enum vgetstate vs; ASSERT_VOP_LOCKED(vp, "vn_dir_dd_ino"); vlp = VP2VNODELOCK(vp); mtx_lock(vlp); TAILQ_FOREACH(ncp, &(vp->v_cache_dst), nc_dst) { if ((ncp->nc_flag & NCF_ISDOTDOT) != 0) continue; ddvp = ncp->nc_dvp; vs = vget_prep(ddvp); mtx_unlock(vlp); if (vget_finish(ddvp, LK_SHARED | LK_NOWAIT, vs)) return (NULL); return (ddvp); } mtx_unlock(vlp); return (NULL); } int vn_commname(struct vnode *vp, char *buf, u_int buflen) { struct namecache *ncp; struct mtx *vlp; int l; vlp = VP2VNODELOCK(vp); mtx_lock(vlp); TAILQ_FOREACH(ncp, &vp->v_cache_dst, nc_dst) if ((ncp->nc_flag & NCF_ISDOTDOT) == 0) break; if (ncp == NULL) { mtx_unlock(vlp); return (ENOENT); } l = min(ncp->nc_nlen, buflen - 1); memcpy(buf, ncp->nc_name, l); mtx_unlock(vlp); buf[l] = '\0'; return (0); } /* * This function updates path string to vnode's full global path * and checks the size of the new path string against the pathlen argument. * * Requires a locked, referenced vnode. * Vnode is re-locked on success or ENODEV, otherwise unlocked. * * If vp is a directory, the call to vn_fullpath_global() always succeeds * because it falls back to the ".." lookup if the namecache lookup fails. */ int vn_path_to_global_path(struct thread *td, struct vnode *vp, char *path, u_int pathlen) { struct nameidata nd; struct vnode *vp1; char *rpath, *fbuf; int error; ASSERT_VOP_ELOCKED(vp, __func__); /* Construct global filesystem path from vp. */ VOP_UNLOCK(vp); error = vn_fullpath_global(td, vp, &rpath, &fbuf); if (error != 0) { vrele(vp); return (error); } if (strlen(rpath) >= pathlen) { vrele(vp); error = ENAMETOOLONG; goto out; } /* * Re-lookup the vnode by path to detect a possible rename. * As a side effect, the vnode is relocked. * If vnode was renamed, return ENOENT. */ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_SYSSPACE, path, td); error = namei(&nd); if (error != 0) { vrele(vp); goto out; } NDFREE(&nd, NDF_ONLY_PNBUF); vp1 = nd.ni_vp; vrele(vp); if (vp1 == vp) strcpy(path, rpath); else { vput(vp1); error = ENOENT; } out: free(fbuf, M_TEMP); return (error); } #ifdef DDB static void db_print_vpath(struct vnode *vp) { while (vp != NULL) { db_printf("%p: ", vp); if (vp == rootvnode) { db_printf("/"); vp = NULL; } else { if (vp->v_vflag & VV_ROOT) { db_printf(""); vp = vp->v_mount->mnt_vnodecovered; } else { struct namecache *ncp; char *ncn; int i; ncp = TAILQ_FIRST(&vp->v_cache_dst); if (ncp != NULL) { ncn = ncp->nc_name; for (i = 0; i < ncp->nc_nlen; i++) db_printf("%c", *ncn++); vp = ncp->nc_dvp; } else { vp = NULL; } } } db_printf("\n"); } return; } DB_SHOW_COMMAND(vpath, db_show_vpath) { struct vnode *vp; if (!have_addr) { db_printf("usage: show vpath \n"); return; } vp = (struct vnode *)addr; db_print_vpath(vp); } #endif Index: head/sys/security/audit/audit_bsm.c =================================================================== --- head/sys/security/audit/audit_bsm.c (revision 358171) +++ head/sys/security/audit/audit_bsm.c (revision 358172) @@ -1,1779 +1,1780 @@ /* * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1999-2009 Apple Inc. * Copyright (c) 2016-2017 Robert N. M. Watson * All rights reserved. * * Portions of this software were developed by BAE Systems, the University of * Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL * contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent * Computing (TC) 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. * 3. Neither the name of Apple Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MALLOC_DEFINE(M_AUDITBSM, "audit_bsm", "Audit BSM data"); static void audit_sys_auditon(struct audit_record *ar, struct au_record *rec); /* * Initialize the BSM auditing subsystem. */ void kau_init(void) { au_evclassmap_init(); au_evnamemap_init(); } /* * This call reserves memory for the audit record. Memory must be guaranteed * before any auditable event can be generated. The au_record structure * maintains a reference to the memory allocated above and also the list of * tokens associated with this record. */ static struct au_record * kau_open(void) { struct au_record *rec; rec = malloc(sizeof(*rec), M_AUDITBSM, M_WAITOK); rec->data = NULL; TAILQ_INIT(&rec->token_q); rec->len = 0; rec->used = 1; return (rec); } /* * Store the token with the record descriptor. */ static void kau_write(struct au_record *rec, struct au_token *tok) { KASSERT(tok != NULL, ("kau_write: tok == NULL")); TAILQ_INSERT_TAIL(&rec->token_q, tok, tokens); rec->len += tok->len; } /* * Close out the audit record by adding the header token, identifying any * missing tokens. Write out the tokens to the record memory. */ static void kau_close(struct au_record *rec, struct timespec *ctime, short event) { u_char *dptr; size_t tot_rec_size; token_t *cur, *hdr, *trail; struct timeval tm; size_t hdrsize; struct auditinfo_addr ak; struct in6_addr *ap; audit_get_kinfo(&ak); hdrsize = 0; switch (ak.ai_termid.at_type) { case AU_IPv4: hdrsize = (ak.ai_termid.at_addr[0] == INADDR_ANY) ? AUDIT_HEADER_SIZE : AUDIT_HEADER_EX_SIZE(&ak); break; case AU_IPv6: ap = (struct in6_addr *)&ak.ai_termid.at_addr[0]; hdrsize = (IN6_IS_ADDR_UNSPECIFIED(ap)) ? AUDIT_HEADER_SIZE : AUDIT_HEADER_EX_SIZE(&ak); break; default: panic("kau_close: invalid address family"); } tot_rec_size = rec->len + hdrsize + AUDIT_TRAILER_SIZE; rec->data = malloc(tot_rec_size, M_AUDITBSM, M_WAITOK | M_ZERO); tm.tv_usec = ctime->tv_nsec / 1000; tm.tv_sec = ctime->tv_sec; if (hdrsize != AUDIT_HEADER_SIZE) hdr = au_to_header32_ex_tm(tot_rec_size, event, 0, tm, &ak); else hdr = au_to_header32_tm(tot_rec_size, event, 0, tm); TAILQ_INSERT_HEAD(&rec->token_q, hdr, tokens); trail = au_to_trailer(tot_rec_size); TAILQ_INSERT_TAIL(&rec->token_q, trail, tokens); rec->len = tot_rec_size; dptr = rec->data; TAILQ_FOREACH(cur, &rec->token_q, tokens) { memcpy(dptr, cur->t_data, cur->len); dptr += cur->len; } } /* * Free a BSM audit record by releasing all the tokens and clearing the audit * record information. */ void kau_free(struct au_record *rec) { struct au_token *tok; /* Free the token list. */ while ((tok = TAILQ_FIRST(&rec->token_q))) { TAILQ_REMOVE(&rec->token_q, tok, tokens); free(tok->t_data, M_AUDITBSM); free(tok, M_AUDITBSM); } rec->used = 0; rec->len = 0; free(rec->data, M_AUDITBSM); free(rec, M_AUDITBSM); } /* * XXX: May want turn some (or all) of these macros into functions in order * to reduce the generated code size. * * XXXAUDIT: These macros assume that 'kar', 'ar', 'rec', and 'tok' in the * caller are OK with this. */ #define ATFD1_TOKENS(argnum) do { \ if (ARG_IS_VALID(kar, ARG_ATFD1)) { \ tok = au_to_arg32(argnum, "at fd 1", ar->ar_arg_atfd1); \ kau_write(rec, tok); \ } \ } while (0) #define ATFD2_TOKENS(argnum) do { \ if (ARG_IS_VALID(kar, ARG_ATFD2)) { \ tok = au_to_arg32(argnum, "at fd 2", ar->ar_arg_atfd2); \ kau_write(rec, tok); \ } \ } while (0) #define UPATH1_TOKENS do { \ if (ARG_IS_VALID(kar, ARG_UPATH1)) { \ tok = au_to_path(ar->ar_arg_upath1); \ kau_write(rec, tok); \ } \ } while (0) #define UPATH2_TOKENS do { \ if (ARG_IS_VALID(kar, ARG_UPATH2)) { \ tok = au_to_path(ar->ar_arg_upath2); \ kau_write(rec, tok); \ } \ } while (0) #define VNODE1_TOKENS do { \ if (ARG_IS_VALID(kar, ARG_ATFD)) { \ tok = au_to_arg32(1, "at fd", ar->ar_arg_atfd); \ kau_write(rec, tok); \ } \ if (ARG_IS_VALID(kar, ARG_VNODE1)) { \ tok = au_to_attr32(&ar->ar_arg_vnode1); \ kau_write(rec, tok); \ } \ } while (0) #define UPATH1_VNODE1_TOKENS do { \ UPATH1_TOKENS; \ if (ARG_IS_VALID(kar, ARG_VNODE1)) { \ tok = au_to_attr32(&ar->ar_arg_vnode1); \ kau_write(rec, tok); \ } \ } while (0) #define VNODE2_TOKENS do { \ if (ARG_IS_VALID(kar, ARG_VNODE2)) { \ tok = au_to_attr32(&ar->ar_arg_vnode2); \ kau_write(rec, tok); \ } \ } while (0) #define FD_VNODE1_TOKENS do { \ if (ARG_IS_VALID(kar, ARG_VNODE1)) { \ if (ARG_IS_VALID(kar, ARG_FD)) { \ tok = au_to_arg32(1, "fd", ar->ar_arg_fd); \ kau_write(rec, tok); \ } \ tok = au_to_attr32(&ar->ar_arg_vnode1); \ kau_write(rec, tok); \ } else { \ if (ARG_IS_VALID(kar, ARG_FD)) { \ tok = au_to_arg32(1, "non-file: fd", \ ar->ar_arg_fd); \ kau_write(rec, tok); \ } \ } \ } while (0) #define PROCESS_PID_TOKENS(argn) do { \ if ((ar->ar_arg_pid > 0) /* Reference a single process */ \ && (ARG_IS_VALID(kar, ARG_PROCESS))) { \ tok = au_to_process32_ex(ar->ar_arg_auid, \ ar->ar_arg_euid, ar->ar_arg_egid, \ ar->ar_arg_ruid, ar->ar_arg_rgid, \ ar->ar_arg_pid, ar->ar_arg_asid, \ &ar->ar_arg_termid_addr); \ kau_write(rec, tok); \ } else if (ARG_IS_VALID(kar, ARG_PID)) { \ tok = au_to_arg32(argn, "process", ar->ar_arg_pid); \ kau_write(rec, tok); \ } \ } while (0) #define EXTATTR_TOKENS(namespace_argnum) do { \ if (ARG_IS_VALID(kar, ARG_VALUE)) { \ switch (ar->ar_arg_value) { \ case EXTATTR_NAMESPACE_USER: \ tok = au_to_text(EXTATTR_NAMESPACE_USER_STRING);\ break; \ case EXTATTR_NAMESPACE_SYSTEM: \ tok = au_to_text(EXTATTR_NAMESPACE_SYSTEM_STRING);\ break; \ default: \ tok = au_to_arg32((namespace_argnum), \ "attrnamespace", ar->ar_arg_value); \ break; \ } \ kau_write(rec, tok); \ } \ /* attrname is in the text field */ \ if (ARG_IS_VALID(kar, ARG_TEXT)) { \ tok = au_to_text(ar->ar_arg_text); \ kau_write(rec, tok); \ } \ } while (0) /* * Not all pointer arguments to system calls are of interest, but in some * cases they reflect delegation of rights, such as mmap(2) followed by * minherit(2) before execve(2), so do the best we can. */ #define ADDR_TOKEN(argnum, argname) do { \ if (ARG_IS_VALID(kar, ARG_ADDR)) { \ if (sizeof(void *) == sizeof(uint32_t)) \ tok = au_to_arg32((argnum), (argname), \ (uint32_t)(uintptr_t)ar->ar_arg_addr); \ else \ tok = au_to_arg64((argnum), (argname), \ (uint64_t)(uintptr_t)ar->ar_arg_addr); \ kau_write(rec, tok); \ } \ } while (0) /* * Implement auditing for the auditon() system call. The audit tokens that * are generated depend on the command that was sent into the auditon() * system call. */ static void audit_sys_auditon(struct audit_record *ar, struct au_record *rec) { struct au_token *tok; tok = au_to_arg32(3, "length", ar->ar_arg_len); kau_write(rec, tok); switch (ar->ar_arg_cmd) { case A_OLDSETPOLICY: if ((size_t)ar->ar_arg_len == sizeof(int64_t)) { tok = au_to_arg64(2, "policy", ar->ar_arg_auditon.au_policy64); kau_write(rec, tok); break; } /* FALLTHROUGH */ case A_SETPOLICY: tok = au_to_arg32(2, "policy", ar->ar_arg_auditon.au_policy); kau_write(rec, tok); break; case A_SETKMASK: tok = au_to_arg32(2, "setkmask:as_success", ar->ar_arg_auditon.au_mask.am_success); kau_write(rec, tok); tok = au_to_arg32(2, "setkmask:as_failure", ar->ar_arg_auditon.au_mask.am_failure); kau_write(rec, tok); break; case A_OLDSETQCTRL: if ((size_t)ar->ar_arg_len == sizeof(au_qctrl64_t)) { tok = au_to_arg64(2, "setqctrl:aq_hiwater", ar->ar_arg_auditon.au_qctrl64.aq64_hiwater); kau_write(rec, tok); tok = au_to_arg64(2, "setqctrl:aq_lowater", ar->ar_arg_auditon.au_qctrl64.aq64_lowater); kau_write(rec, tok); tok = au_to_arg64(2, "setqctrl:aq_bufsz", ar->ar_arg_auditon.au_qctrl64.aq64_bufsz); kau_write(rec, tok); tok = au_to_arg64(2, "setqctrl:aq_delay", ar->ar_arg_auditon.au_qctrl64.aq64_delay); kau_write(rec, tok); tok = au_to_arg64(2, "setqctrl:aq_minfree", ar->ar_arg_auditon.au_qctrl64.aq64_minfree); kau_write(rec, tok); break; } /* FALLTHROUGH */ case A_SETQCTRL: tok = au_to_arg32(2, "setqctrl:aq_hiwater", ar->ar_arg_auditon.au_qctrl.aq_hiwater); kau_write(rec, tok); tok = au_to_arg32(2, "setqctrl:aq_lowater", ar->ar_arg_auditon.au_qctrl.aq_lowater); kau_write(rec, tok); tok = au_to_arg32(2, "setqctrl:aq_bufsz", ar->ar_arg_auditon.au_qctrl.aq_bufsz); kau_write(rec, tok); tok = au_to_arg32(2, "setqctrl:aq_delay", ar->ar_arg_auditon.au_qctrl.aq_delay); kau_write(rec, tok); tok = au_to_arg32(2, "setqctrl:aq_minfree", ar->ar_arg_auditon.au_qctrl.aq_minfree); kau_write(rec, tok); break; case A_SETUMASK: tok = au_to_arg32(2, "setumask:as_success", ar->ar_arg_auditon.au_auinfo.ai_mask.am_success); kau_write(rec, tok); tok = au_to_arg32(2, "setumask:as_failure", ar->ar_arg_auditon.au_auinfo.ai_mask.am_failure); kau_write(rec, tok); break; case A_SETSMASK: tok = au_to_arg32(2, "setsmask:as_success", ar->ar_arg_auditon.au_auinfo.ai_mask.am_success); kau_write(rec, tok); tok = au_to_arg32(2, "setsmask:as_failure", ar->ar_arg_auditon.au_auinfo.ai_mask.am_failure); kau_write(rec, tok); break; case A_OLDSETCOND: if ((size_t)ar->ar_arg_len == sizeof(int64_t)) { tok = au_to_arg64(2, "setcond", ar->ar_arg_auditon.au_cond64); kau_write(rec, tok); break; } /* FALLTHROUGH */ case A_SETCOND: tok = au_to_arg32(2, "setcond", ar->ar_arg_auditon.au_cond); kau_write(rec, tok); break; case A_SETCLASS: tok = au_to_arg32(2, "setclass:ec_event", ar->ar_arg_auditon.au_evclass.ec_number); kau_write(rec, tok); tok = au_to_arg32(2, "setclass:ec_class", ar->ar_arg_auditon.au_evclass.ec_class); kau_write(rec, tok); break; case A_SETPMASK: tok = au_to_arg32(2, "setpmask:as_success", ar->ar_arg_auditon.au_aupinfo.ap_mask.am_success); kau_write(rec, tok); tok = au_to_arg32(2, "setpmask:as_failure", ar->ar_arg_auditon.au_aupinfo.ap_mask.am_failure); kau_write(rec, tok); break; case A_SETFSIZE: tok = au_to_arg32(2, "setfsize:filesize", ar->ar_arg_auditon.au_fstat.af_filesz); kau_write(rec, tok); break; default: break; } } /* * Convert an internal kernel audit record to a BSM record and return a * success/failure indicator. The BSM record is passed as an out parameter to * this function. * * Return conditions: * BSM_SUCCESS: The BSM record is valid * BSM_FAILURE: Failure; the BSM record is NULL. * BSM_NOAUDIT: The event is not auditable for BSM; the BSM record is NULL. */ int kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau) { struct au_token *tok, *subj_tok, *jail_tok; struct au_record *rec; au_tid_t tid; struct audit_record *ar; int ctr; KASSERT(kar != NULL, ("kaudit_to_bsm: kar == NULL")); *pau = NULL; ar = &kar->k_ar; rec = kau_open(); /* * Create the subject token. If this credential was jailed be sure to * generate a zonename token. */ if (ar->ar_jailname[0] != '\0') jail_tok = au_to_zonename(ar->ar_jailname); else jail_tok = NULL; switch (ar->ar_subj_term_addr.at_type) { case AU_IPv4: tid.port = ar->ar_subj_term_addr.at_port; tid.machine = ar->ar_subj_term_addr.at_addr[0]; subj_tok = au_to_subject32(ar->ar_subj_auid, /* audit ID */ ar->ar_subj_cred.cr_uid, /* eff uid */ ar->ar_subj_egid, /* eff group id */ ar->ar_subj_ruid, /* real uid */ ar->ar_subj_rgid, /* real group id */ ar->ar_subj_pid, /* process id */ ar->ar_subj_asid, /* session ID */ &tid); break; case AU_IPv6: subj_tok = au_to_subject32_ex(ar->ar_subj_auid, ar->ar_subj_cred.cr_uid, ar->ar_subj_egid, ar->ar_subj_ruid, ar->ar_subj_rgid, ar->ar_subj_pid, ar->ar_subj_asid, &ar->ar_subj_term_addr); break; default: bzero(&tid, sizeof(tid)); subj_tok = au_to_subject32(ar->ar_subj_auid, ar->ar_subj_cred.cr_uid, ar->ar_subj_egid, ar->ar_subj_ruid, ar->ar_subj_rgid, ar->ar_subj_pid, ar->ar_subj_asid, &tid); } /* * The logic inside each case fills in the tokens required for the * event, except for the header, trailer, and return tokens. The * header and trailer tokens are added by the kau_close() function. * The return token is added outside of the switch statement. */ switch(ar->ar_event) { case AUE_ACCEPT: if (ARG_IS_VALID(kar, ARG_FD)) { tok = au_to_arg32(1, "fd", ar->ar_arg_fd); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_SADDRINET)) { tok = au_to_sock_inet((struct sockaddr_in *) &ar->ar_arg_sockaddr); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_SADDRUNIX)) { tok = au_to_sock_unix((struct sockaddr_un *) &ar->ar_arg_sockaddr); kau_write(rec, tok); UPATH1_TOKENS; } break; case AUE_BIND: case AUE_LISTEN: case AUE_CONNECT: case AUE_RECV: case AUE_RECVFROM: case AUE_RECVMSG: case AUE_SEND: case AUE_SENDMSG: case AUE_SENDTO: /* * Socket-related events. */ if (ARG_IS_VALID(kar, ARG_FD)) { tok = au_to_arg32(1, "fd", ar->ar_arg_fd); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_SADDRINET)) { tok = au_to_sock_inet((struct sockaddr_in *) &ar->ar_arg_sockaddr); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_SADDRUNIX)) { tok = au_to_sock_unix((struct sockaddr_un *) &ar->ar_arg_sockaddr); kau_write(rec, tok); UPATH1_TOKENS; } /* XXX Need to handle ARG_SADDRINET6 */ break; case AUE_BINDAT: case AUE_CONNECTAT: ATFD1_TOKENS(1); if (ARG_IS_VALID(kar, ARG_FD)) { tok = au_to_arg32(2, "fd", ar->ar_arg_fd); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_SADDRUNIX)) { tok = au_to_sock_unix((struct sockaddr_un *) &ar->ar_arg_sockaddr); kau_write(rec, tok); UPATH1_TOKENS; } break; case AUE_SENDFILE: FD_VNODE1_TOKENS; if (ARG_IS_VALID(kar, ARG_SADDRINET)) { tok = au_to_sock_inet((struct sockaddr_in *) &ar->ar_arg_sockaddr); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_SADDRUNIX)) { tok = au_to_sock_unix((struct sockaddr_un *) &ar->ar_arg_sockaddr); kau_write(rec, tok); UPATH1_TOKENS; } /* XXX Need to handle ARG_SADDRINET6 */ break; case AUE_SOCKET: case AUE_SOCKETPAIR: if (ARG_IS_VALID(kar, ARG_SOCKINFO)) { tok = au_to_arg32(1, "domain", ar->ar_arg_sockinfo.so_domain); kau_write(rec, tok); tok = au_to_arg32(2, "type", ar->ar_arg_sockinfo.so_type); kau_write(rec, tok); tok = au_to_arg32(3, "protocol", ar->ar_arg_sockinfo.so_protocol); kau_write(rec, tok); } break; case AUE_SETSOCKOPT: case AUE_SHUTDOWN: if (ARG_IS_VALID(kar, ARG_FD)) { tok = au_to_arg32(1, "fd", ar->ar_arg_fd); kau_write(rec, tok); } break; case AUE_ACCT: if (ARG_IS_VALID(kar, ARG_UPATH1)) { UPATH1_VNODE1_TOKENS; } else { tok = au_to_arg32(1, "accounting off", 0); kau_write(rec, tok); } break; case AUE_SETAUID: if (ARG_IS_VALID(kar, ARG_AUID)) { tok = au_to_arg32(2, "setauid", ar->ar_arg_auid); kau_write(rec, tok); } break; case AUE_SETAUDIT: if (ARG_IS_VALID(kar, ARG_AUID) && ARG_IS_VALID(kar, ARG_ASID) && ARG_IS_VALID(kar, ARG_AMASK) && ARG_IS_VALID(kar, ARG_TERMID)) { tok = au_to_arg32(1, "setaudit:auid", ar->ar_arg_auid); kau_write(rec, tok); tok = au_to_arg32(1, "setaudit:port", ar->ar_arg_termid.port); kau_write(rec, tok); tok = au_to_arg32(1, "setaudit:machine", ar->ar_arg_termid.machine); kau_write(rec, tok); tok = au_to_arg32(1, "setaudit:as_success", ar->ar_arg_amask.am_success); kau_write(rec, tok); tok = au_to_arg32(1, "setaudit:as_failure", ar->ar_arg_amask.am_failure); kau_write(rec, tok); tok = au_to_arg32(1, "setaudit:asid", ar->ar_arg_asid); kau_write(rec, tok); } break; case AUE_SETAUDIT_ADDR: if (ARG_IS_VALID(kar, ARG_AUID) && ARG_IS_VALID(kar, ARG_ASID) && ARG_IS_VALID(kar, ARG_AMASK) && ARG_IS_VALID(kar, ARG_TERMID_ADDR)) { tok = au_to_arg32(1, "setaudit_addr:auid", ar->ar_arg_auid); kau_write(rec, tok); tok = au_to_arg32(1, "setaudit_addr:as_success", ar->ar_arg_amask.am_success); kau_write(rec, tok); tok = au_to_arg32(1, "setaudit_addr:as_failure", ar->ar_arg_amask.am_failure); kau_write(rec, tok); tok = au_to_arg32(1, "setaudit_addr:asid", ar->ar_arg_asid); kau_write(rec, tok); tok = au_to_arg32(1, "setaudit_addr:type", ar->ar_arg_termid_addr.at_type); kau_write(rec, tok); tok = au_to_arg32(1, "setaudit_addr:port", ar->ar_arg_termid_addr.at_port); kau_write(rec, tok); if (ar->ar_arg_termid_addr.at_type == AU_IPv6) tok = au_to_in_addr_ex((struct in6_addr *) &ar->ar_arg_termid_addr.at_addr[0]); if (ar->ar_arg_termid_addr.at_type == AU_IPv4) tok = au_to_in_addr((struct in_addr *) &ar->ar_arg_termid_addr.at_addr[0]); kau_write(rec, tok); } break; case AUE_AUDITON: /* * For AUDITON commands without own event, audit the cmd. */ if (ARG_IS_VALID(kar, ARG_CMD)) { tok = au_to_arg32(1, "cmd", ar->ar_arg_cmd); kau_write(rec, tok); } /* FALLTHROUGH */ case AUE_AUDITON_GETCAR: case AUE_AUDITON_GETCLASS: case AUE_AUDITON_GETCOND: case AUE_AUDITON_GETCWD: case AUE_AUDITON_GETKMASK: case AUE_AUDITON_GETSTAT: case AUE_AUDITON_GPOLICY: case AUE_AUDITON_GQCTRL: case AUE_AUDITON_SETCLASS: case AUE_AUDITON_SETCOND: case AUE_AUDITON_SETKMASK: case AUE_AUDITON_SETSMASK: case AUE_AUDITON_SETSTAT: case AUE_AUDITON_SETUMASK: case AUE_AUDITON_SPOLICY: case AUE_AUDITON_SQCTRL: if (ARG_IS_VALID(kar, ARG_AUDITON)) audit_sys_auditon(ar, rec); break; case AUE_AUDITCTL: UPATH1_VNODE1_TOKENS; break; case AUE_EXIT: if (ARG_IS_VALID(kar, ARG_EXIT)) { tok = au_to_exit(ar->ar_arg_exitretval, ar->ar_arg_exitstatus); kau_write(rec, tok); } break; case AUE_ADJTIME: case AUE_CLOCK_SETTIME: case AUE_AUDIT: case AUE_DUP2: case AUE_GETAUDIT: case AUE_GETAUDIT_ADDR: case AUE_GETAUID: case AUE_GETCWD: case AUE_GETFSSTAT: case AUE_GETRESUID: case AUE_GETRESGID: case AUE_KQUEUE: case AUE_MODLOAD: case AUE_MODUNLOAD: case AUE_MSGSYS: case AUE_NTP_ADJTIME: case AUE_PIPE: case AUE_POSIX_OPENPT: case AUE_PROFILE: case AUE_RTPRIO: case AUE_SEMSYS: case AUE_SETFIB: case AUE_SHMSYS: case AUE_SETPGRP: case AUE_SETRLIMIT: case AUE_SETSID: case AUE_SETTIMEOFDAY: case AUE_SYSARCH: /* * Header, subject, and return tokens added at end. */ break; case AUE_ACL_DELETE_FD: case AUE_ACL_DELETE_FILE: case AUE_ACL_CHECK_FD: case AUE_ACL_CHECK_FILE: case AUE_ACL_CHECK_LINK: case AUE_ACL_DELETE_LINK: case AUE_ACL_GET_FD: case AUE_ACL_GET_FILE: case AUE_ACL_GET_LINK: case AUE_ACL_SET_FD: case AUE_ACL_SET_FILE: case AUE_ACL_SET_LINK: if (ARG_IS_VALID(kar, ARG_VALUE)) { tok = au_to_arg32(1, "type", ar->ar_arg_value); kau_write(rec, tok); } ATFD1_TOKENS(1); UPATH1_VNODE1_TOKENS; break; case AUE_CHDIR: case AUE_CHROOT: case AUE_FSTATAT: case AUE_FUTIMESAT: case AUE_GETATTRLIST: case AUE_JAIL: case AUE_LUTIMES: case AUE_NFS_GETFH: case AUE_LGETFH: case AUE_LSTAT: case AUE_LPATHCONF: case AUE_PATHCONF: case AUE_READLINK: case AUE_READLINKAT: case AUE_REVOKE: case AUE_RMDIR: case AUE_SEARCHFS: case AUE_SETATTRLIST: case AUE_STAT: case AUE_STATFS: case AUE_SWAPON: case AUE_SWAPOFF: case AUE_TRUNCATE: case AUE_UNDELETE: case AUE_UNLINK: case AUE_UNLINKAT: case AUE_UTIMES: + case AUE_REALPATHAT: ATFD1_TOKENS(1); UPATH1_VNODE1_TOKENS; break; case AUE_ACCESS: case AUE_EACCESS: case AUE_FACCESSAT: ATFD1_TOKENS(1); UPATH1_VNODE1_TOKENS; if (ARG_IS_VALID(kar, ARG_VALUE)) { tok = au_to_arg32(2, "mode", ar->ar_arg_value); kau_write(rec, tok); } break; case AUE_FHSTATFS: case AUE_FHOPEN: case AUE_FHSTAT: /* XXXRW: Need to audit vnode argument. */ break; case AUE_CHFLAGS: case AUE_LCHFLAGS: case AUE_CHFLAGSAT: if (ARG_IS_VALID(kar, ARG_FFLAGS)) { tok = au_to_arg32(2, "flags", ar->ar_arg_fflags); kau_write(rec, tok); } UPATH1_VNODE1_TOKENS; break; case AUE_CHMOD: case AUE_LCHMOD: if (ARG_IS_VALID(kar, ARG_MODE)) { tok = au_to_arg32(2, "new file mode", ar->ar_arg_mode); kau_write(rec, tok); } UPATH1_VNODE1_TOKENS; break; case AUE_FCHMODAT: ATFD1_TOKENS(1); if (ARG_IS_VALID(kar, ARG_MODE)) { tok = au_to_arg32(3, "new file mode", ar->ar_arg_mode); kau_write(rec, tok); } UPATH1_VNODE1_TOKENS; break; case AUE_CHOWN: case AUE_LCHOWN: if (ARG_IS_VALID(kar, ARG_UID)) { tok = au_to_arg32(2, "new file uid", ar->ar_arg_uid); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_GID)) { tok = au_to_arg32(3, "new file gid", ar->ar_arg_gid); kau_write(rec, tok); } UPATH1_VNODE1_TOKENS; break; case AUE_FCHOWNAT: ATFD1_TOKENS(1); if (ARG_IS_VALID(kar, ARG_UID)) { tok = au_to_arg32(3, "new file uid", ar->ar_arg_uid); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_GID)) { tok = au_to_arg32(4, "new file gid", ar->ar_arg_gid); kau_write(rec, tok); } UPATH1_VNODE1_TOKENS; break; case AUE_EXCHANGEDATA: UPATH1_VNODE1_TOKENS; UPATH2_TOKENS; break; case AUE_CLOSE: if (ARG_IS_VALID(kar, ARG_FD)) { tok = au_to_arg32(1, "fd", ar->ar_arg_fd); kau_write(rec, tok); } UPATH1_VNODE1_TOKENS; break; case AUE_CLOSEFROM: if (ARG_IS_VALID(kar, ARG_FD)) { tok = au_to_arg32(1, "fd", ar->ar_arg_fd); kau_write(rec, tok); } break; case AUE_CORE: if (ARG_IS_VALID(kar, ARG_SIGNUM)) { tok = au_to_arg32(1, "signal", ar->ar_arg_signum); kau_write(rec, tok); } UPATH1_VNODE1_TOKENS; break; case AUE_EXTATTRCTL: UPATH1_VNODE1_TOKENS; if (ARG_IS_VALID(kar, ARG_CMD)) { tok = au_to_arg32(2, "cmd", ar->ar_arg_cmd); kau_write(rec, tok); } /* extattrctl(2) filename parameter is in upath2/vnode2 */ UPATH2_TOKENS; VNODE2_TOKENS; EXTATTR_TOKENS(4); break; case AUE_EXTATTR_GET_FILE: case AUE_EXTATTR_SET_FILE: case AUE_EXTATTR_LIST_FILE: case AUE_EXTATTR_DELETE_FILE: case AUE_EXTATTR_GET_LINK: case AUE_EXTATTR_SET_LINK: case AUE_EXTATTR_LIST_LINK: case AUE_EXTATTR_DELETE_LINK: UPATH1_VNODE1_TOKENS; EXTATTR_TOKENS(2); break; case AUE_EXTATTR_GET_FD: case AUE_EXTATTR_SET_FD: case AUE_EXTATTR_LIST_FD: case AUE_EXTATTR_DELETE_FD: if (ARG_IS_VALID(kar, ARG_FD)) { tok = au_to_arg32(2, "fd", ar->ar_arg_fd); kau_write(rec, tok); } EXTATTR_TOKENS(2); break; case AUE_FEXECVE: if (ARG_IS_VALID(kar, ARG_FD)) { tok = au_to_arg32(1, "fd", ar->ar_arg_fd); kau_write(rec, tok); } /* FALLTHROUGH */ case AUE_EXECVE: case AUE_MAC_EXECVE: if (ARG_IS_VALID(kar, ARG_ARGV)) { tok = au_to_exec_args(ar->ar_arg_argv, ar->ar_arg_argc); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_ENVV)) { tok = au_to_exec_env(ar->ar_arg_envv, ar->ar_arg_envc); kau_write(rec, tok); } UPATH1_VNODE1_TOKENS; break; case AUE_FCHMOD: if (ARG_IS_VALID(kar, ARG_MODE)) { tok = au_to_arg32(2, "new file mode", ar->ar_arg_mode); kau_write(rec, tok); } FD_VNODE1_TOKENS; break; /* * XXXRW: Some of these need to handle non-vnode cases as well. */ case AUE_FCHDIR: case AUE_FPATHCONF: case AUE_FSTAT: case AUE_FSTATFS: case AUE_FSYNC: case AUE_FTRUNCATE: case AUE_FUTIMES: case AUE_GETDIRENTRIES: case AUE_GETDIRENTRIESATTR: case AUE_LSEEK: case AUE_POLL: case AUE_POSIX_FALLOCATE: case AUE_PREAD: case AUE_PWRITE: case AUE_READ: case AUE_READV: case AUE_WRITE: case AUE_WRITEV: FD_VNODE1_TOKENS; break; case AUE_FCHOWN: if (ARG_IS_VALID(kar, ARG_UID)) { tok = au_to_arg32(2, "new file uid", ar->ar_arg_uid); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_GID)) { tok = au_to_arg32(3, "new file gid", ar->ar_arg_gid); kau_write(rec, tok); } FD_VNODE1_TOKENS; break; case AUE_FCNTL: if (ARG_IS_VALID(kar, ARG_CMD)) { tok = au_to_arg32(2, "cmd", au_fcntl_cmd_to_bsm(ar->ar_arg_cmd)); kau_write(rec, tok); } FD_VNODE1_TOKENS; break; case AUE_FCHFLAGS: if (ARG_IS_VALID(kar, ARG_FFLAGS)) { tok = au_to_arg32(2, "flags", ar->ar_arg_fflags); kau_write(rec, tok); } FD_VNODE1_TOKENS; break; case AUE_FLOCK: if (ARG_IS_VALID(kar, ARG_CMD)) { tok = au_to_arg32(2, "operation", ar->ar_arg_cmd); kau_write(rec, tok); } FD_VNODE1_TOKENS; break; case AUE_RFORK: if (ARG_IS_VALID(kar, ARG_FFLAGS)) { tok = au_to_arg32(1, "flags", ar->ar_arg_fflags); kau_write(rec, tok); } /* FALLTHROUGH */ case AUE_FORK: case AUE_VFORK: if (ARG_IS_VALID(kar, ARG_PID)) { tok = au_to_arg32(0, "child PID", ar->ar_arg_pid); kau_write(rec, tok); } break; case AUE_IOCTL: if (ARG_IS_VALID(kar, ARG_CMD)) { tok = au_to_arg32(2, "cmd", ar->ar_arg_cmd); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_VNODE1)) FD_VNODE1_TOKENS; else { if (ARG_IS_VALID(kar, ARG_SOCKINFO)) { tok = kau_to_socket(&ar->ar_arg_sockinfo); kau_write(rec, tok); } else { if (ARG_IS_VALID(kar, ARG_FD)) { tok = au_to_arg32(1, "fd", ar->ar_arg_fd); kau_write(rec, tok); } } } break; case AUE_KILL: case AUE_KILLPG: if (ARG_IS_VALID(kar, ARG_SIGNUM)) { tok = au_to_arg32(2, "signal", ar->ar_arg_signum); kau_write(rec, tok); } PROCESS_PID_TOKENS(1); break; case AUE_KTRACE: if (ARG_IS_VALID(kar, ARG_CMD)) { tok = au_to_arg32(2, "ops", ar->ar_arg_cmd); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_VALUE)) { tok = au_to_arg32(3, "trpoints", ar->ar_arg_value); kau_write(rec, tok); } PROCESS_PID_TOKENS(4); UPATH1_VNODE1_TOKENS; break; case AUE_LINK: case AUE_LINKAT: case AUE_RENAME: case AUE_RENAMEAT: ATFD1_TOKENS(1); UPATH1_VNODE1_TOKENS; ATFD2_TOKENS(3); UPATH2_TOKENS; break; case AUE_LOADSHFILE: ADDR_TOKEN(4, "base addr"); UPATH1_VNODE1_TOKENS; break; case AUE_MKDIR: case AUE_MKDIRAT: case AUE_MKFIFO: case AUE_MKFIFOAT: ATFD1_TOKENS(1); if (ARG_IS_VALID(kar, ARG_MODE)) { tok = au_to_arg32(2, "mode", ar->ar_arg_mode); kau_write(rec, tok); } UPATH1_VNODE1_TOKENS; break; case AUE_MKNOD: case AUE_MKNODAT: ATFD1_TOKENS(1); if (ARG_IS_VALID(kar, ARG_MODE)) { tok = au_to_arg32(2, "mode", ar->ar_arg_mode); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_DEV)) { tok = au_to_arg32(3, "dev", ar->ar_arg_dev); kau_write(rec, tok); } UPATH1_VNODE1_TOKENS; break; case AUE_MMAP: case AUE_MUNMAP: case AUE_MPROTECT: case AUE_MLOCK: case AUE_MUNLOCK: case AUE_MINHERIT: ADDR_TOKEN(1, "addr"); if (ARG_IS_VALID(kar, ARG_LEN)) { tok = au_to_arg32(2, "len", ar->ar_arg_len); kau_write(rec, tok); } if (ar->ar_event == AUE_MMAP) FD_VNODE1_TOKENS; if (ar->ar_event == AUE_MPROTECT) { if (ARG_IS_VALID(kar, ARG_VALUE)) { tok = au_to_arg32(3, "protection", ar->ar_arg_value); kau_write(rec, tok); } } if (ar->ar_event == AUE_MINHERIT) { if (ARG_IS_VALID(kar, ARG_VALUE)) { tok = au_to_arg32(3, "inherit", ar->ar_arg_value); kau_write(rec, tok); } } break; case AUE_MOUNT: case AUE_NMOUNT: /* XXX Need to handle NFS mounts */ if (ARG_IS_VALID(kar, ARG_FFLAGS)) { tok = au_to_arg32(3, "flags", ar->ar_arg_fflags); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_TEXT)) { tok = au_to_text(ar->ar_arg_text); kau_write(rec, tok); } /* FALLTHROUGH */ case AUE_NFS_SVC: if (ARG_IS_VALID(kar, ARG_CMD)) { tok = au_to_arg32(1, "flags", ar->ar_arg_cmd); kau_write(rec, tok); } break; case AUE_UMOUNT: if (ARG_IS_VALID(kar, ARG_VALUE)) { tok = au_to_arg32(2, "flags", ar->ar_arg_value); kau_write(rec, tok); } UPATH1_VNODE1_TOKENS; if (ARG_IS_VALID(kar, ARG_TEXT)) { tok = au_to_text(ar->ar_arg_text); kau_write(rec, tok); } break; case AUE_MSGCTL: ar->ar_event = audit_msgctl_to_event(ar->ar_arg_svipc_cmd); /* Fall through */ case AUE_MSGRCV: case AUE_MSGSND: tok = au_to_arg32(1, "msg ID", ar->ar_arg_svipc_id); kau_write(rec, tok); if (ar->ar_errno != EINVAL) { tok = au_to_ipc(AT_IPC_MSG, ar->ar_arg_svipc_id); kau_write(rec, tok); } break; case AUE_MSGGET: if (ar->ar_errno == 0) { if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) { tok = au_to_ipc(AT_IPC_MSG, ar->ar_arg_svipc_id); kau_write(rec, tok); } } break; case AUE_RESETSHFILE: ADDR_TOKEN(1, "base addr"); break; case AUE_OPEN_RC: case AUE_OPEN_RTC: case AUE_OPEN_RWC: case AUE_OPEN_RWTC: case AUE_OPEN_WC: case AUE_OPEN_WTC: case AUE_CREAT: if (ARG_IS_VALID(kar, ARG_MODE)) { tok = au_to_arg32(3, "mode", ar->ar_arg_mode); kau_write(rec, tok); } /* FALLTHROUGH */ case AUE_OPEN_R: case AUE_OPEN_RT: case AUE_OPEN_RW: case AUE_OPEN_RWT: case AUE_OPEN_W: case AUE_OPEN_WT: if (ARG_IS_VALID(kar, ARG_FFLAGS)) { tok = au_to_arg32(2, "flags", ar->ar_arg_fflags); kau_write(rec, tok); } UPATH1_VNODE1_TOKENS; break; case AUE_OPENAT_RC: case AUE_OPENAT_RTC: case AUE_OPENAT_RWC: case AUE_OPENAT_RWTC: case AUE_OPENAT_WC: case AUE_OPENAT_WTC: if (ARG_IS_VALID(kar, ARG_MODE)) { tok = au_to_arg32(3, "mode", ar->ar_arg_mode); kau_write(rec, tok); } /* FALLTHROUGH */ case AUE_OPENAT_R: case AUE_OPENAT_RT: case AUE_OPENAT_RW: case AUE_OPENAT_RWT: case AUE_OPENAT_W: case AUE_OPENAT_WT: if (ARG_IS_VALID(kar, ARG_FFLAGS)) { tok = au_to_arg32(2, "flags", ar->ar_arg_fflags); kau_write(rec, tok); } ATFD1_TOKENS(1); UPATH1_VNODE1_TOKENS; break; case AUE_PROCCTL: if (ARG_IS_VALID(kar, ARG_VALUE)) { tok = au_to_arg32(1, "idtype", ar->ar_arg_value); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_CMD)) { tok = au_to_arg32(2, "com", ar->ar_arg_cmd); kau_write(rec, tok); } PROCESS_PID_TOKENS(3); break; case AUE_PTRACE: if (ARG_IS_VALID(kar, ARG_CMD)) { tok = au_to_arg32(1, "request", ar->ar_arg_cmd); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_VALUE)) { tok = au_to_arg32(4, "data", ar->ar_arg_value); kau_write(rec, tok); } PROCESS_PID_TOKENS(2); break; case AUE_QUOTACTL: if (ARG_IS_VALID(kar, ARG_CMD)) { tok = au_to_arg32(2, "command", ar->ar_arg_cmd); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_UID)) { tok = au_to_arg32(3, "uid", ar->ar_arg_uid); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_GID)) { tok = au_to_arg32(3, "gid", ar->ar_arg_gid); kau_write(rec, tok); } UPATH1_VNODE1_TOKENS; break; case AUE_REBOOT: if (ARG_IS_VALID(kar, ARG_CMD)) { tok = au_to_arg32(1, "howto", ar->ar_arg_cmd); kau_write(rec, tok); } break; case AUE_SEMCTL: ar->ar_event = audit_semctl_to_event(ar->ar_arg_svipc_cmd); /* Fall through */ case AUE_SEMOP: if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) { tok = au_to_arg32(1, "sem ID", ar->ar_arg_svipc_id); kau_write(rec, tok); if (ar->ar_errno != EINVAL) { tok = au_to_ipc(AT_IPC_SEM, ar->ar_arg_svipc_id); kau_write(rec, tok); } } break; case AUE_SEMGET: if (ar->ar_errno == 0) { if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) { tok = au_to_ipc(AT_IPC_SEM, ar->ar_arg_svipc_id); kau_write(rec, tok); } } break; case AUE_SETEGID: if (ARG_IS_VALID(kar, ARG_EGID)) { tok = au_to_arg32(1, "egid", ar->ar_arg_egid); kau_write(rec, tok); } break; case AUE_SETEUID: if (ARG_IS_VALID(kar, ARG_EUID)) { tok = au_to_arg32(1, "euid", ar->ar_arg_euid); kau_write(rec, tok); } break; case AUE_SETREGID: if (ARG_IS_VALID(kar, ARG_RGID)) { tok = au_to_arg32(1, "rgid", ar->ar_arg_rgid); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_EGID)) { tok = au_to_arg32(2, "egid", ar->ar_arg_egid); kau_write(rec, tok); } break; case AUE_SETREUID: if (ARG_IS_VALID(kar, ARG_RUID)) { tok = au_to_arg32(1, "ruid", ar->ar_arg_ruid); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_EUID)) { tok = au_to_arg32(2, "euid", ar->ar_arg_euid); kau_write(rec, tok); } break; case AUE_SETRESGID: if (ARG_IS_VALID(kar, ARG_RGID)) { tok = au_to_arg32(1, "rgid", ar->ar_arg_rgid); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_EGID)) { tok = au_to_arg32(2, "egid", ar->ar_arg_egid); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_SGID)) { tok = au_to_arg32(3, "sgid", ar->ar_arg_sgid); kau_write(rec, tok); } break; case AUE_SETRESUID: if (ARG_IS_VALID(kar, ARG_RUID)) { tok = au_to_arg32(1, "ruid", ar->ar_arg_ruid); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_EUID)) { tok = au_to_arg32(2, "euid", ar->ar_arg_euid); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_SUID)) { tok = au_to_arg32(3, "suid", ar->ar_arg_suid); kau_write(rec, tok); } break; case AUE_SETGID: if (ARG_IS_VALID(kar, ARG_GID)) { tok = au_to_arg32(1, "gid", ar->ar_arg_gid); kau_write(rec, tok); } break; case AUE_SETUID: if (ARG_IS_VALID(kar, ARG_UID)) { tok = au_to_arg32(1, "uid", ar->ar_arg_uid); kau_write(rec, tok); } break; case AUE_SETGROUPS: if (ARG_IS_VALID(kar, ARG_GROUPSET)) { for(ctr = 0; ctr < ar->ar_arg_groups.gidset_size; ctr++) { tok = au_to_arg32(1, "setgroups", ar->ar_arg_groups.gidset[ctr]); kau_write(rec, tok); } } break; case AUE_SETLOGIN: if (ARG_IS_VALID(kar, ARG_LOGIN)) { tok = au_to_text(ar->ar_arg_login); kau_write(rec, tok); } break; case AUE_SETPRIORITY: if (ARG_IS_VALID(kar, ARG_CMD)) { tok = au_to_arg32(1, "which", ar->ar_arg_cmd); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_UID)) { tok = au_to_arg32(2, "who", ar->ar_arg_uid); kau_write(rec, tok); } PROCESS_PID_TOKENS(2); if (ARG_IS_VALID(kar, ARG_VALUE)) { tok = au_to_arg32(3, "priority", ar->ar_arg_value); kau_write(rec, tok); } break; case AUE_SETPRIVEXEC: if (ARG_IS_VALID(kar, ARG_VALUE)) { tok = au_to_arg32(1, "flag", ar->ar_arg_value); kau_write(rec, tok); } break; /* AUE_SHMAT, AUE_SHMCTL, AUE_SHMDT and AUE_SHMGET are SysV IPC */ case AUE_SHMAT: if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) { tok = au_to_arg32(1, "shmid", ar->ar_arg_svipc_id); kau_write(rec, tok); /* XXXAUDIT: Does having the ipc token make sense? */ tok = au_to_ipc(AT_IPC_SHM, ar->ar_arg_svipc_id); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_SVIPC_ADDR)) { tok = au_to_arg32(2, "shmaddr", (int)(uintptr_t)ar->ar_arg_svipc_addr); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_SVIPC_PERM)) { tok = au_to_ipc_perm(&ar->ar_arg_svipc_perm); kau_write(rec, tok); } break; case AUE_SHMCTL: if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) { tok = au_to_arg32(1, "shmid", ar->ar_arg_svipc_id); kau_write(rec, tok); /* XXXAUDIT: Does having the ipc token make sense? */ tok = au_to_ipc(AT_IPC_SHM, ar->ar_arg_svipc_id); kau_write(rec, tok); } switch (ar->ar_arg_svipc_cmd) { case IPC_STAT: ar->ar_event = AUE_SHMCTL_STAT; break; case IPC_RMID: ar->ar_event = AUE_SHMCTL_RMID; break; case IPC_SET: ar->ar_event = AUE_SHMCTL_SET; if (ARG_IS_VALID(kar, ARG_SVIPC_PERM)) { tok = au_to_ipc_perm(&ar->ar_arg_svipc_perm); kau_write(rec, tok); } break; default: break; /* We will audit a bad command */ } break; case AUE_SHMDT: if (ARG_IS_VALID(kar, ARG_SVIPC_ADDR)) { tok = au_to_arg32(1, "shmaddr", (int)(uintptr_t)ar->ar_arg_svipc_addr); kau_write(rec, tok); } break; case AUE_SHMGET: /* This is unusual; the return value is in an argument token */ if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) { tok = au_to_arg32(0, "shmid", ar->ar_arg_svipc_id); kau_write(rec, tok); tok = au_to_ipc(AT_IPC_SHM, ar->ar_arg_svipc_id); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_SVIPC_PERM)) { tok = au_to_ipc_perm(&ar->ar_arg_svipc_perm); kau_write(rec, tok); } break; /* shm_rename is a non-Posix extension to the Posix shm implementation */ case AUE_SHMRENAME: UPATH1_TOKENS; UPATH2_TOKENS; if (ARG_IS_VALID(kar, ARG_FFLAGS)) { tok = au_to_arg32(2, "flags", ar->ar_arg_fflags); kau_write(rec, tok); } break; /* AUE_SHMOPEN, AUE_SHMUNLINK, AUE_SEMOPEN, AUE_SEMCLOSE * and AUE_SEMUNLINK are Posix IPC */ case AUE_SHMOPEN: if (ARG_IS_VALID(kar, ARG_FFLAGS)) { tok = au_to_arg32(2, "flags", ar->ar_arg_fflags); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_MODE)) { tok = au_to_arg32(3, "mode", ar->ar_arg_mode); kau_write(rec, tok); } /* FALLTHROUGH */ case AUE_SHMUNLINK: UPATH1_TOKENS; if (ARG_IS_VALID(kar, ARG_POSIX_IPC_PERM)) { struct ipc_perm perm; perm.uid = ar->ar_arg_pipc_perm.pipc_uid; perm.gid = ar->ar_arg_pipc_perm.pipc_gid; perm.cuid = ar->ar_arg_pipc_perm.pipc_uid; perm.cgid = ar->ar_arg_pipc_perm.pipc_gid; perm.mode = ar->ar_arg_pipc_perm.pipc_mode; perm.seq = 0; perm.key = 0; tok = au_to_ipc_perm(&perm); kau_write(rec, tok); } break; case AUE_SEMOPEN: if (ARG_IS_VALID(kar, ARG_FFLAGS)) { tok = au_to_arg32(2, "flags", ar->ar_arg_fflags); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_MODE)) { tok = au_to_arg32(3, "mode", ar->ar_arg_mode); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_VALUE)) { tok = au_to_arg32(4, "value", ar->ar_arg_value); kau_write(rec, tok); } /* FALLTHROUGH */ case AUE_SEMUNLINK: if (ARG_IS_VALID(kar, ARG_TEXT)) { tok = au_to_text(ar->ar_arg_text); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_POSIX_IPC_PERM)) { struct ipc_perm perm; perm.uid = ar->ar_arg_pipc_perm.pipc_uid; perm.gid = ar->ar_arg_pipc_perm.pipc_gid; perm.cuid = ar->ar_arg_pipc_perm.pipc_uid; perm.cgid = ar->ar_arg_pipc_perm.pipc_gid; perm.mode = ar->ar_arg_pipc_perm.pipc_mode; perm.seq = 0; perm.key = 0; tok = au_to_ipc_perm(&perm); kau_write(rec, tok); } break; case AUE_SEMCLOSE: if (ARG_IS_VALID(kar, ARG_FD)) { tok = au_to_arg32(1, "sem", ar->ar_arg_fd); kau_write(rec, tok); } break; case AUE_SYMLINK: case AUE_SYMLINKAT: if (ARG_IS_VALID(kar, ARG_TEXT)) { tok = au_to_text(ar->ar_arg_text); kau_write(rec, tok); } ATFD1_TOKENS(1); UPATH1_VNODE1_TOKENS; break; case AUE_SYSCTL: case AUE_SYSCTL_NONADMIN: if (ARG_IS_VALID(kar, ARG_CTLNAME | ARG_LEN)) { for (ctr = 0; ctr < ar->ar_arg_len; ctr++) { tok = au_to_arg32(1, "name", ar->ar_arg_ctlname[ctr]); kau_write(rec, tok); } } if (ARG_IS_VALID(kar, ARG_VALUE)) { tok = au_to_arg32(5, "newval", ar->ar_arg_value); kau_write(rec, tok); } if (ARG_IS_VALID(kar, ARG_TEXT)) { tok = au_to_text(ar->ar_arg_text); kau_write(rec, tok); } break; case AUE_UMASK: if (ARG_IS_VALID(kar, ARG_MASK)) { tok = au_to_arg32(1, "new mask", ar->ar_arg_mask); kau_write(rec, tok); } tok = au_to_arg32(0, "prev mask", ar->ar_retval); kau_write(rec, tok); break; case AUE_WAIT4: case AUE_WAIT6: PROCESS_PID_TOKENS(1); if (ARG_IS_VALID(kar, ARG_VALUE)) { tok = au_to_arg32(3, "options", ar->ar_arg_value); kau_write(rec, tok); } break; case AUE_CAP_RIGHTS_LIMIT: /* * XXXRW/XXXJA: Would be nice to audit socket/etc information. */ FD_VNODE1_TOKENS; if (ARG_IS_VALID(kar, ARG_RIGHTS)) { tok = au_to_rights(&ar->ar_arg_rights); kau_write(rec, tok); } break; case AUE_CAP_FCNTLS_GET: case AUE_CAP_IOCTLS_GET: case AUE_CAP_IOCTLS_LIMIT: case AUE_CAP_RIGHTS_GET: if (ARG_IS_VALID(kar, ARG_FD)) { tok = au_to_arg32(1, "fd", ar->ar_arg_fd); kau_write(rec, tok); } break; case AUE_CAP_FCNTLS_LIMIT: FD_VNODE1_TOKENS; if (ARG_IS_VALID(kar, ARG_FCNTL_RIGHTS)) { tok = au_to_arg32(2, "fcntlrights", ar->ar_arg_fcntl_rights); kau_write(rec, tok); } break; case AUE_CAP_ENTER: case AUE_CAP_GETMODE: break; case AUE_NULL: default: printf("BSM conversion requested for unknown event %d\n", ar->ar_event); /* * Write the subject token so it is properly freed here. */ if (jail_tok != NULL) kau_write(rec, jail_tok); kau_write(rec, subj_tok); kau_free(rec); return (BSM_NOAUDIT); } if (jail_tok != NULL) kau_write(rec, jail_tok); kau_write(rec, subj_tok); tok = au_to_return32(au_errno_to_bsm(ar->ar_errno), ar->ar_retval); kau_write(rec, tok); /* Every record gets a return token */ kau_close(rec, &ar->ar_endtime, ar->ar_event); *pau = rec; return (BSM_SUCCESS); } /* * Verify that a record is a valid BSM record. This verification is simple * now, but may be expanded on sometime in the future. Return 1 if the * record is good, 0 otherwise. */ int bsm_rec_verify(void *rec) { char c = *(char *)rec; /* * Check the token ID of the first token; it has to be a header * token. * * XXXAUDIT There needs to be a token structure to map a token. * XXXAUDIT 'Shouldn't be simply looking at the first char. */ if ((c != AUT_HEADER32) && (c != AUT_HEADER32_EX) && (c != AUT_HEADER64) && (c != AUT_HEADER64_EX)) return (0); return (1); } Index: head/sys/sys/param.h =================================================================== --- head/sys/sys/param.h (revision 358171) +++ head/sys/sys/param.h (revision 358172) @@ -1,368 +1,368 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1982, 1986, 1989, 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. * 3. 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. * * @(#)param.h 8.3 (Berkeley) 4/4/95 * $FreeBSD$ */ #ifndef _SYS_PARAM_H_ #define _SYS_PARAM_H_ #include #define BSD 199506 /* System version (year & month). */ #define BSD4_3 1 #define BSD4_4 1 /* * __FreeBSD_version numbers are documented in the Porter's Handbook. * If you bump the version for any reason, you should update the documentation * there. * Currently this lives here in the doc/ repository: * * head/en_US.ISO8859-1/books/porters-handbook/versions/chapter.xml * * scheme is: Rxx * 'R' is in the range 0 to 4 if this is a release branch or * X.0-CURRENT before releng/X.0 is created, otherwise 'R' is * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1300079 /* Master, propagated to newvers */ +#define __FreeBSD_version 1300080 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, * which by definition is always true on FreeBSD. This macro is also defined * on other systems that use the kernel of FreeBSD, such as GNU/kFreeBSD. * * It is tempting to use this macro in userland code when we want to enable * kernel-specific routines, and in fact it's fine to do this in code that * is part of FreeBSD itself. However, be aware that as presence of this * macro is still not widespread (e.g. older FreeBSD versions, 3rd party * compilers, etc), it is STRONGLY DISCOURAGED to check for this macro in * external applications without also checking for __FreeBSD__ as an * alternative. */ #undef __FreeBSD_kernel__ #define __FreeBSD_kernel__ #if defined(_KERNEL) || defined(IN_RTLD) #define P_OSREL_SIGWAIT 700000 #define P_OSREL_SIGSEGV 700004 #define P_OSREL_MAP_ANON 800104 #define P_OSREL_MAP_FSTRICT 1100036 #define P_OSREL_SHUTDOWN_ENOTCONN 1100077 #define P_OSREL_MAP_GUARD 1200035 #define P_OSREL_WRFSBASE 1200041 #define P_OSREL_CK_CYLGRP 1200046 #define P_OSREL_VMTOTAL64 1200054 #define P_OSREL_CK_SUPERBLOCK 1300000 #define P_OSREL_CK_INODE 1300005 #define P_OSREL_POWERPC_NEW_AUX_ARGS 1300070 #define P_OSREL_MAJOR(x) ((x) / 100000) #endif #ifndef LOCORE #include #endif /* * Machine-independent constants (some used in following include files). * Redefined constants are from POSIX 1003.1 limits file. * * MAXCOMLEN should be >= sizeof(ac_comm) (see ) */ #include #define MAXCOMLEN 19 /* max command name remembered */ #define MAXINTERP PATH_MAX /* max interpreter file name length */ #define MAXLOGNAME 33 /* max login name length (incl. NUL) */ #define MAXUPRC CHILD_MAX /* max simultaneous processes */ #define NCARGS ARG_MAX /* max bytes for an exec function */ #define NGROUPS (NGROUPS_MAX+1) /* max number groups */ #define NOFILE OPEN_MAX /* max open files per process */ #define NOGROUP 65535 /* marker for empty group set member */ #define MAXHOSTNAMELEN 256 /* max hostname size */ #define SPECNAMELEN 255 /* max length of devicename */ /* More types and definitions used throughout the kernel. */ #ifdef _KERNEL #include #include #ifndef LOCORE #include #include #endif #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #endif #ifndef _KERNEL /* Signals. */ #include #endif /* Machine type dependent parameters. */ #include #ifndef _KERNEL #include #endif #ifndef DEV_BSHIFT #define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */ #endif #define DEV_BSIZE (1<>PAGE_SHIFT) #endif /* * btodb() is messy and perhaps slow because `bytes' may be an off_t. We * want to shift an unsigned type to avoid sign extension and we don't * want to widen `bytes' unnecessarily. Assume that the result fits in * a daddr_t. */ #ifndef btodb #define btodb(bytes) /* calculates (bytes / DEV_BSIZE) */ \ (sizeof (bytes) > sizeof(long) \ ? (daddr_t)((unsigned long long)(bytes) >> DEV_BSHIFT) \ : (daddr_t)((unsigned long)(bytes) >> DEV_BSHIFT)) #endif #ifndef dbtob #define dbtob(db) /* calculates (db * DEV_BSIZE) */ \ ((off_t)(db) << DEV_BSHIFT) #endif #define PRIMASK 0x0ff #define PCATCH 0x100 /* OR'd with pri for tsleep to check signals */ #define PDROP 0x200 /* OR'd with pri to stop re-entry of interlock mutex */ #define NZERO 0 /* default "nice" */ #define NBBY 8 /* number of bits in a byte */ #define NBPW sizeof(int) /* number of bytes per word (integer) */ #define CMASK 022 /* default file mask: S_IWGRP|S_IWOTH */ #define NODEV (dev_t)(-1) /* non-existent device */ /* * File system parameters and macros. * * MAXBSIZE - Filesystems are made out of blocks of at most MAXBSIZE bytes * per block. MAXBSIZE may be made larger without effecting * any existing filesystems as long as it does not exceed MAXPHYS, * and may be made smaller at the risk of not being able to use * filesystems which require a block size exceeding MAXBSIZE. * * MAXBCACHEBUF - Maximum size of a buffer in the buffer cache. This must * be >= MAXBSIZE and can be set differently for different * architectures by defining it in . * Making this larger allows NFS to do larger reads/writes. * * BKVASIZE - Nominal buffer space per buffer, in bytes. BKVASIZE is the * minimum KVM memory reservation the kernel is willing to make. * Filesystems can of course request smaller chunks. Actual * backing memory uses a chunk size of a page (PAGE_SIZE). * The default value here can be overridden on a per-architecture * basis by defining it in . * * If you make BKVASIZE too small you risk seriously fragmenting * the buffer KVM map which may slow things down a bit. If you * make it too big the kernel will not be able to optimally use * the KVM memory reserved for the buffer cache and will wind * up with too-few buffers. * * The default is 16384, roughly 2x the block size used by a * normal UFS filesystem. */ #define MAXBSIZE 65536 /* must be power of 2 */ #ifndef MAXBCACHEBUF #define MAXBCACHEBUF MAXBSIZE /* must be a power of 2 >= MAXBSIZE */ #endif #ifndef BKVASIZE #define BKVASIZE 16384 /* must be power of 2 */ #endif #define BKVAMASK (BKVASIZE-1) /* * MAXPATHLEN defines the longest permissible path length after expanding * symbolic links. It is used to allocate a temporary buffer from the buffer * pool in which to do the name expansion, hence should be a power of two, * and must be less than or equal to MAXBSIZE. MAXSYMLINKS defines the * maximum number of symbolic links that may be expanded in a path name. * It should be set high enough to allow all legitimate uses, but halt * infinite loops reasonably quickly. */ #define MAXPATHLEN PATH_MAX #define MAXSYMLINKS 32 /* Bit map related macros. */ #define setbit(a,i) (((unsigned char *)(a))[(i)/NBBY] |= 1<<((i)%NBBY)) #define clrbit(a,i) (((unsigned char *)(a))[(i)/NBBY] &= ~(1<<((i)%NBBY))) #define isset(a,i) \ (((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY))) #define isclr(a,i) \ ((((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY))) == 0) /* Macros for counting and rounding. */ #ifndef howmany #define howmany(x, y) (((x)+((y)-1))/(y)) #endif #define nitems(x) (sizeof((x)) / sizeof((x)[0])) #define rounddown(x, y) (((x)/(y))*(y)) #define rounddown2(x, y) ((x)&(~((y)-1))) /* if y is power of two */ #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */ #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ #define powerof2(x) ((((x)-1)&(x))==0) /* Macros for min/max. */ #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) #ifdef _KERNEL /* * Basic byte order function prototypes for non-inline functions. */ #ifndef LOCORE #ifndef _BYTEORDER_PROTOTYPED #define _BYTEORDER_PROTOTYPED __BEGIN_DECLS __uint32_t htonl(__uint32_t); __uint16_t htons(__uint16_t); __uint32_t ntohl(__uint32_t); __uint16_t ntohs(__uint16_t); __END_DECLS #endif #endif #ifndef _BYTEORDER_FUNC_DEFINED #define _BYTEORDER_FUNC_DEFINED #define htonl(x) __htonl(x) #define htons(x) __htons(x) #define ntohl(x) __ntohl(x) #define ntohs(x) __ntohs(x) #endif /* !_BYTEORDER_FUNC_DEFINED */ #endif /* _KERNEL */ /* * Scale factor for scaled integers used to count %cpu time and load avgs. * * The number of CPU `tick's that map to a unique `%age' can be expressed * by the formula (1 / (2 ^ (FSHIFT - 11))). The maximum load average that * can be calculated (assuming 32 bits) can be closely approximated using * the formula (2 ^ (2 * (16 - FSHIFT))) for (FSHIFT < 15). * * For the scheduler to maintain a 1:1 mapping of CPU `tick' to `%age', * FSHIFT must be at least 11; this gives us a maximum load avg of ~1024. */ #define FSHIFT 11 /* bits to right of fixed binary point */ #define FSCALE (1<> (PAGE_SHIFT - DEV_BSHIFT)) #define ctodb(db) /* calculates pages to devblks */ \ ((db) << (PAGE_SHIFT - DEV_BSHIFT)) /* * Old spelling of __containerof(). */ #define member2struct(s, m, x) \ ((struct s *)(void *)((char *)(x) - offsetof(struct s, m))) /* * Access a variable length array that has been declared as a fixed * length array. */ #define __PAST_END(array, offset) (((__typeof__(*(array)) *)(array))[offset]) #endif /* _SYS_PARAM_H_ */ Index: head/usr.bin/truss/syscalls.c =================================================================== --- head/usr.bin/truss/syscalls.c (revision 358171) +++ head/usr.bin/truss/syscalls.c (revision 358172) @@ -1,2807 +1,2810 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright 1997 Sean Eric Fagan * * 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Sean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote * products derived from this software without specific prior written * permission. * * 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$"); /* * This file has routines used to print out system calls and their * arguments. */ #include #include #define _WANT_FREEBSD11_KEVENT #include #include #include #include #include #include #include #define _WANT_FREEBSD11_STAT #include #include #include #include #include #include #include #include #include #include #include #define _WANT_KERNEL_ERRNO #include #include #include #include #include #include #include #include #include #include #include #include #include #include "truss.h" #include "extern.h" #include "syscall.h" /* * This should probably be in its own file, sorted alphabetically. */ static struct syscall decoded_syscalls[] = { /* Native ABI */ { .name = "__acl_aclcheck_fd", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } }, { .name = "__acl_aclcheck_file", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } }, { .name = "__acl_aclcheck_link", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } }, { .name = "__acl_delete_fd", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Acltype, 1 } } }, { .name = "__acl_delete_file", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Acltype, 1 } } }, { .name = "__acl_delete_link", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Acltype, 1 } } }, { .name = "__acl_get_fd", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } }, { .name = "__acl_get_file", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } }, { .name = "__acl_get_link", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } }, { .name = "__acl_set_fd", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } }, { .name = "__acl_set_file", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } }, { .name = "__acl_set_link", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } }, { .name = "__cap_rights_get", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Int, 1 }, { CapRights | OUT, 2 } } }, { .name = "__getcwd", .ret_type = 1, .nargs = 2, .args = { { Name | OUT, 0 }, { Int, 1 } } }, + { .name = "__realpathat", .ret_type = 1, .nargs = 5, + .args = { { Atfd, 0 }, { Name | IN, 1 }, { Name | OUT, 2 }, + { Sizet, 3 }, { Int, 4} } }, { .name = "_umtx_op", .ret_type = 1, .nargs = 5, .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 }, { Ptr, 4 } } }, { .name = "accept", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, { .name = "access", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Accessmode, 1 } } }, { .name = "bind", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } }, { .name = "bindat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 }, { Int, 3 } } }, { .name = "break", .ret_type = 1, .nargs = 1, .args = { { Ptr, 0 } } }, { .name = "cap_fcntls_get", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { CapFcntlRights | OUT, 1 } } }, { .name = "cap_fcntls_limit", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { CapFcntlRights, 1 } } }, { .name = "cap_getmode", .ret_type = 1, .nargs = 1, .args = { { PUInt | OUT, 0 } } }, { .name = "cap_rights_limit", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { CapRights, 1 } } }, { .name = "chdir", .ret_type = 1, .nargs = 1, .args = { { Name, 0 } } }, { .name = "chflags", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { FileFlags, 1 } } }, { .name = "chflagsat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name | IN, 1 }, { FileFlags, 2 }, { Atflags, 3 } } }, { .name = "chmod", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Octal, 1 } } }, { .name = "chown", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } }, { .name = "chroot", .ret_type = 1, .nargs = 1, .args = { { Name, 0 } } }, { .name = "clock_gettime", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Timespec | OUT, 1 } } }, { .name = "close", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "compat11.fstat", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Stat11 | OUT, 1 } } }, { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 }, { Atflags, 3 } } }, { .name = "compat11.kevent", .ret_type = 1, .nargs = 6, .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 }, { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } }, { .name = "compat11.lstat", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } }, { .name = "compat11.stat", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } }, { .name = "connect", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } }, { .name = "connectat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 }, { Int, 3 } } }, { .name = "dup", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "dup2", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Int, 1 } } }, { .name = "eaccess", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Accessmode, 1 } } }, { .name = "execve", .ret_type = 1, .nargs = 3, .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 }, { ExecEnv | IN, 2 } } }, { .name = "exit", .ret_type = 0, .nargs = 1, .args = { { Hex, 0 } } }, { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } }, { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } }, { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } }, { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5, .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 }, { BinString | OUT, 3 }, { Sizet, 4 } } }, { .name = "extattr_get_file", .ret_type = 1, .nargs = 5, .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 }, { BinString | OUT, 3 }, { Sizet, 4 } } }, { .name = "extattr_get_link", .ret_type = 1, .nargs = 5, .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 }, { BinString | OUT, 3 }, { Sizet, 4 } } }, { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 }, { Sizet, 3 } } }, { .name = "extattr_list_file", .ret_type = 1, .nargs = 4, .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 }, { Sizet, 3 } } }, { .name = "extattr_list_link", .ret_type = 1, .nargs = 4, .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 }, { Sizet, 3 } } }, { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5, .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 }, { BinString | IN, 3 }, { Sizet, 4 } } }, { .name = "extattr_set_file", .ret_type = 1, .nargs = 5, .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 }, { BinString | IN, 3 }, { Sizet, 4 } } }, { .name = "extattr_set_link", .ret_type = 1, .nargs = 5, .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 }, { BinString | IN, 3 }, { Sizet, 4 } } }, { .name = "extattrctl", .ret_type = 1, .nargs = 5, .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 }, { Extattrnamespace, 3 }, { Name, 4 } } }, { .name = "faccessat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 }, { Atflags, 3 } } }, { .name = "fchflags", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { FileFlags, 1 } } }, { .name = "fchmod", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Octal, 1 } } }, { .name = "fchmodat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } }, { .name = "fchown", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } }, { .name = "fchownat", .ret_type = 1, .nargs = 5, .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 }, { Atflags, 4 } } }, { .name = "fcntl", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } }, { .name = "fdatasync", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "flock", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Flockop, 1 } } }, { .name = "fstat", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Stat | OUT, 1 } } }, { .name = "fstatat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 }, { Atflags, 3 } } }, { .name = "fstatfs", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { StatFs | OUT, 1 } } }, { .name = "fsync", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "ftruncate", .ret_type = 1, .nargs = 2, .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } }, { .name = "futimens", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Timespec2 | IN, 1 } } }, { .name = "futimes", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Timeval2 | IN, 1 } } }, { .name = "futimesat", .ret_type = 1, .nargs = 3, .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } }, { .name = "getdirentries", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 }, { PQuadHex | OUT, 3 } } }, { .name = "getfsstat", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } }, { .name = "getitimer", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Itimerval | OUT, 2 } } }, { .name = "getpeername", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, { .name = "getpgid", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "getpriority", .ret_type = 1, .nargs = 2, .args = { { Priowhich, 0 }, { Int, 1 } } }, { .name = "getrandom", .ret_type = 1, .nargs = 3, .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } }, { .name = "getrlimit", .ret_type = 1, .nargs = 2, .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } }, { .name = "getrusage", .ret_type = 1, .nargs = 2, .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } }, { .name = "getsid", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "getsockname", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, { .name = "getsockopt", .ret_type = 1, .nargs = 5, .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 }, { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } }, { .name = "gettimeofday", .ret_type = 1, .nargs = 2, .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } }, { .name = "ioctl", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } }, { .name = "kevent", .ret_type = 1, .nargs = 6, .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } }, { .name = "kill", .ret_type = 1, .nargs = 2, .args = { { Int | IN, 0 }, { Signal | IN, 1 } } }, { .name = "kldfind", .ret_type = 1, .nargs = 1, .args = { { Name | IN, 0 } } }, { .name = "kldfirstmod", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "kldload", .ret_type = 1, .nargs = 1, .args = { { Name | IN, 0 } } }, { .name = "kldnext", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "kldstat", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Ptr, 1 } } }, { .name = "kldsym", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } }, { .name = "kldunload", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "kldunloadf", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Kldunloadflags, 1 } } }, { .name = "kse_release", .ret_type = 0, .nargs = 1, .args = { { Timespec, 0 } } }, { .name = "lchflags", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { FileFlags, 1 } } }, { .name = "lchmod", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Octal, 1 } } }, { .name = "lchown", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } }, { .name = "link", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Name, 1 } } }, { .name = "linkat", .ret_type = 1, .nargs = 5, .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 }, { Atflags, 4 } } }, { .name = "listen", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Int, 1 } } }, { .name = "lseek", .ret_type = 2, .nargs = 3, .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } }, { .name = "lstat", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } }, { .name = "lutimes", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } }, { .name = "madvise", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } }, { .name = "minherit", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } }, { .name = "mkdir", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Octal, 1 } } }, { .name = "mkdirat", .ret_type = 1, .nargs = 3, .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } }, { .name = "mkfifo", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Octal, 1 } } }, { .name = "mkfifoat", .ret_type = 1, .nargs = 3, .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } }, { .name = "mknod", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } }, { .name = "mknodat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } }, { .name = "mlock", .ret_type = 1, .nargs = 2, .args = { { Ptr, 0 }, { Sizet, 1 } } }, { .name = "mlockall", .ret_type = 1, .nargs = 1, .args = { { Mlockall, 0 } } }, { .name = "mmap", .ret_type = 1, .nargs = 6, .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 }, { Int, 4 }, { QuadHex, 5 } } }, { .name = "modfind", .ret_type = 1, .nargs = 1, .args = { { Name | IN, 0 } } }, { .name = "mount", .ret_type = 1, .nargs = 4, .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } }, { .name = "mprotect", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } }, { .name = "msync", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } }, { .name = "munlock", .ret_type = 1, .nargs = 2, .args = { { Ptr, 0 }, { Sizet, 1 } } }, { .name = "munmap", .ret_type = 1, .nargs = 2, .args = { { Ptr, 0 }, { Sizet, 1 } } }, { .name = "nanosleep", .ret_type = 1, .nargs = 1, .args = { { Timespec, 0 } } }, { .name = "nmount", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } }, { .name = "open", .ret_type = 1, .nargs = 3, .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } }, { .name = "openat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 }, { Octal, 3 } } }, { .name = "pathconf", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Pathconf, 1 } } }, { .name = "pipe", .ret_type = 1, .nargs = 1, .args = { { PipeFds | OUT, 0 } } }, { .name = "pipe2", .ret_type = 1, .nargs = 2, .args = { { Ptr, 0 }, { Pipe2, 1 } } }, { .name = "poll", .ret_type = 1, .nargs = 3, .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } }, { .name = "posix_fadvise", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 }, { Fadvice, 3 } } }, { .name = "posix_openpt", .ret_type = 1, .nargs = 1, .args = { { Open, 0 } } }, { .name = "pread", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 }, { QuadHex, 3 } } }, { .name = "procctl", .ret_type = 1, .nargs = 4, .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } }, { .name = "ptrace", .ret_type = 1, .nargs = 4, .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } }, { .name = "pwrite", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 }, { QuadHex, 3 } } }, { .name = "quotactl", .ret_type = 1, .nargs = 4, .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } }, { .name = "read", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } }, { .name = "readlink", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } }, { .name = "readlinkat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 }, { Sizet, 3 } } }, { .name = "readv", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } }, { .name = "reboot", .ret_type = 1, .nargs = 1, .args = { { Reboothowto, 0 } } }, { .name = "recvfrom", .ret_type = 1, .nargs = 6, .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 }, { Msgflags, 3 }, { Sockaddr | OUT, 4 }, { Ptr | OUT, 5 } } }, { .name = "recvmsg", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } }, { .name = "rename", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Name, 1 } } }, { .name = "renameat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } }, { .name = "rfork", .ret_type = 1, .nargs = 1, .args = { { Rforkflags, 0 } } }, { .name = "rmdir", .ret_type = 1, .nargs = 1, .args = { { Name, 0 } } }, { .name = "rtprio", .ret_type = 1, .nargs = 3, .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } }, { .name = "rtprio_thread", .ret_type = 1, .nargs = 3, .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } }, { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1, .args = { { Schedpolicy, 0 } } }, { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1, .args = { { Schedpolicy, 0 } } }, { .name = "sched_getparam", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Schedparam | OUT, 1 } } }, { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Timespec | OUT, 1 } } }, { .name = "sched_setparam", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Schedparam, 1 } } }, { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } }, { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7, .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 }, { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 }, { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } }, { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7, .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { Sockaddr | IN, 3 }, { Socklent, 4 }, { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } }, { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7, .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 }, { Sockaddr | IN, 3 }, { Socklent, 4 }, { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } }, { .name = "select", .ret_type = 1, .nargs = 5, .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 }, { Timeval, 4 } } }, { .name = "sendmsg", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } }, { .name = "sendto", .ret_type = 1, .nargs = 6, .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 }, { Msgflags, 3 }, { Sockaddr | IN, 4 }, { Socklent | IN, 5 } } }, { .name = "setitimer", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } }, { .name = "setpriority", .ret_type = 1, .nargs = 3, .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } }, { .name = "setrlimit", .ret_type = 1, .nargs = 2, .args = { { Resource, 0 }, { Rlimit | IN, 1 } } }, { .name = "setsockopt", .ret_type = 1, .nargs = 5, .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 }, { Ptr | IN, 3 }, { Socklent, 4 } } }, { .name = "shm_open", .ret_type = 1, .nargs = 3, .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 } } }, { .name = "shm_open2", .ret_type = 1, .nargs = 5, .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 }, { ShmFlags, 3 }, { Name | IN, 4 } } }, { .name = "shm_rename", .ret_type = 1, .nargs = 3, .args = { { Name | IN, 0 }, { Name | IN, 1 }, { Hex, 2 } } }, { .name = "shm_unlink", .ret_type = 1, .nargs = 1, .args = { { Name | IN, 0 } } }, { .name = "shutdown", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Shutdown, 1 } } }, { .name = "sigaction", .ret_type = 1, .nargs = 3, .args = { { Signal, 0 }, { Sigaction | IN, 1 }, { Sigaction | OUT, 2 } } }, { .name = "sigpending", .ret_type = 1, .nargs = 1, .args = { { Sigset | OUT, 0 } } }, { .name = "sigprocmask", .ret_type = 1, .nargs = 3, .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } }, { .name = "sigqueue", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } }, { .name = "sigreturn", .ret_type = 1, .nargs = 1, .args = { { Ptr, 0 } } }, { .name = "sigsuspend", .ret_type = 1, .nargs = 1, .args = { { Sigset | IN, 0 } } }, { .name = "sigtimedwait", .ret_type = 1, .nargs = 3, .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 }, { Timespec | IN, 2 } } }, { .name = "sigwait", .ret_type = 1, .nargs = 2, .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } }, { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2, .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } }, { .name = "socket", .ret_type = 1, .nargs = 3, .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } }, { .name = "stat", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } }, { .name = "statfs", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } }, { .name = "symlink", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Name, 1 } } }, { .name = "symlinkat", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } }, { .name = "sysarch", .ret_type = 1, .nargs = 2, .args = { { Sysarch, 0 }, { Ptr, 1 } } }, { .name = "__sysctl", .ret_type = 1, .nargs = 6, .args = { { Sysctl, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 }, { Ptr, 4 }, { Sizet, 5 } } }, { .name = "__sysctlbyname", .ret_type = 1, .nargs = 6, .args = { { Name, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 }, { Ptr, 4}, { Sizet, 5 } } }, { .name = "thr_kill", .ret_type = 1, .nargs = 2, .args = { { Long, 0 }, { Signal, 1 } } }, { .name = "thr_self", .ret_type = 1, .nargs = 1, .args = { { Ptr, 0 } } }, { .name = "thr_set_name", .ret_type = 1, .nargs = 2, .args = { { Long, 0 }, { Name, 1 } } }, { .name = "truncate", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } }, #if 0 /* Does not exist */ { .name = "umount", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Int, 2 } } }, #endif { .name = "unlink", .ret_type = 1, .nargs = 1, .args = { { Name, 0 } } }, { .name = "unlinkat", .ret_type = 1, .nargs = 3, .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } }, { .name = "unmount", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Mountflags, 1 } } }, { .name = "utimensat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 }, { Atflags, 3 } } }, { .name = "utimes", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } }, { .name = "utrace", .ret_type = 1, .nargs = 1, .args = { { Utrace, 0 } } }, { .name = "wait4", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 }, { Rusage | OUT, 3 } } }, { .name = "wait6", .ret_type = 1, .nargs = 6, .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 }, { Waitoptions, 3 }, { Rusage | OUT, 4 }, { Siginfo | OUT, 5 } } }, { .name = "write", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } }, { .name = "writev", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } }, /* Linux ABI */ { .name = "linux_access", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Accessmode, 1 } } }, { .name = "linux_execve", .ret_type = 1, .nargs = 3, .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 }, { ExecEnv | IN, 2 } } }, { .name = "linux_lseek", .ret_type = 2, .nargs = 3, .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } }, { .name = "linux_mkdir", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Int, 1 } } }, { .name = "linux_newfstat", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Ptr | OUT, 1 } } }, { .name = "linux_newstat", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } }, { .name = "linux_open", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } }, { .name = "linux_readlink", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } }, { .name = "linux_socketcall", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { LinuxSockArgs, 1 } } }, { .name = "linux_stat64", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } }, /* CloudABI system calls. */ { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1, .args = { { CloudABIClockID, 0 } } }, { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2, .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } }, { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } }, { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1, .args = { { CloudABIFileType, 0 } } }, { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2, .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } }, { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Int, 1 } } }, { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } }, { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } }, { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 }, { CloudABIFDSFlags, 2 } } }, { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { Int, 1 }, { Int, 2 }, { CloudABIAdvice, 3 } } }, { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } }, { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { BinString | IN, 1 }, { CloudABIFileType, 3 } } }, { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4, .args = { { CloudABILookup, 0 }, { BinString | IN, 1 }, { Int, 3 }, { BinString | IN, 4 } } }, { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { BinString | IN, 1 }, { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } }, { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 }, { Int, 3 } } }, { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { BinString | IN, 1 }, { BinString | OUT, 3 }, { Int, 4 } } }, { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 3 }, { BinString | IN, 4 } } }, { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } }, { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 }, { CloudABIFSFlags, 2 } } }, { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3, .args = { { CloudABILookup, 0 }, { BinString | IN, 1 }, { CloudABIFileStat | OUT, 3 } } }, { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4, .args = { { CloudABILookup, 0 }, { BinString | IN, 1 }, { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } }, { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3, .args = { { BinString | IN, 0 }, { Int, 2 }, { BinString | IN, 3 } } }, { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { BinString | IN, 1 }, { CloudABIULFlags, 3 } } }, { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2, .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } }, { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } }, { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6, .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 }, { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } }, { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } }, { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } }, { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2, .args = { { Ptr, 0 }, { Int, 1 } } }, { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5, .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { IntArray, 3 }, { Int, 4 } } }, { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 }, { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1, .args = { { CloudABISignal, 0 } } }, { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2, .args = { { BinString | OUT, 0 }, { Int, 1 } } }, { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { CloudABISDFlags, 1 } } }, { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2, .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } }, { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 }, { .name = 0 }, }; static STAILQ_HEAD(, syscall) syscalls; /* Xlat idea taken from strace */ struct xlat { int val; const char *str; }; #define X(a) { a, #a }, #define XEND { 0, NULL } static struct xlat poll_flags[] = { X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR) X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND) X(POLLWRBAND) X(POLLINIGNEOF) XEND }; static struct xlat sigaction_flags[] = { X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP) X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND }; static struct xlat linux_socketcall_ops[] = { X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN) X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME) X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO) X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT) X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG) XEND }; #undef X #define X(a) { CLOUDABI_##a, #a }, static struct xlat cloudabi_advice[] = { X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL) X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED) XEND }; static struct xlat cloudabi_clockid[] = { X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID) X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID) XEND }; static struct xlat cloudabi_fdflags[] = { X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK) X(FDFLAG_RSYNC) X(FDFLAG_SYNC) XEND }; static struct xlat cloudabi_fdsflags[] = { X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS) XEND }; static struct xlat cloudabi_filetype[] = { X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE) X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY) X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE) X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM) X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK) XEND }; static struct xlat cloudabi_fsflags[] = { X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM) X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE) XEND }; static struct xlat cloudabi_mflags[] = { X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED) XEND }; static struct xlat cloudabi_mprot[] = { X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ) XEND }; static struct xlat cloudabi_msflags[] = { X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC) XEND }; static struct xlat cloudabi_oflags[] = { X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC) XEND }; static struct xlat cloudabi_sdflags[] = { X(SHUT_RD) X(SHUT_WR) XEND }; static struct xlat cloudabi_signal[] = { X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE) X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT) X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP) X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2) X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ) XEND }; static struct xlat cloudabi_ulflags[] = { X(UNLINK_REMOVEDIR) XEND }; static struct xlat cloudabi_whence[] = { X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET) XEND }; #undef X #undef XEND /* * Searches an xlat array for a value, and returns it if found. Otherwise * return a string representation. */ static const char * lookup(struct xlat *xlat, int val, int base) { static char tmp[16]; for (; xlat->str != NULL; xlat++) if (xlat->val == val) return (xlat->str); switch (base) { case 8: sprintf(tmp, "0%o", val); break; case 16: sprintf(tmp, "0x%x", val); break; case 10: sprintf(tmp, "%u", val); break; default: errx(1,"Unknown lookup base"); break; } return (tmp); } static const char * xlookup(struct xlat *xlat, int val) { return (lookup(xlat, val, 16)); } /* * Searches an xlat array containing bitfield values. Remaining bits * set after removing the known ones are printed at the end: * IN|0x400. */ static char * xlookup_bits(struct xlat *xlat, int val) { int len, rem; static char str[512]; len = 0; rem = val; for (; xlat->str != NULL; xlat++) { if ((xlat->val & rem) == xlat->val) { /* * Don't print the "all-bits-zero" string unless all * bits are really zero. */ if (xlat->val == 0 && val != 0) continue; len += sprintf(str + len, "%s|", xlat->str); rem &= ~(xlat->val); } } /* * If we have leftover bits or didn't match anything, print * the remainder. */ if (rem || len == 0) len += sprintf(str + len, "0x%x", rem); if (len && str[len - 1] == '|') len--; str[len] = 0; return (str); } static void print_integer_arg(const char *(*decoder)(int), FILE *fp, int value) { const char *str; str = decoder(value); if (str != NULL) fputs(str, fp); else fprintf(fp, "%d", value); } static void print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value) { int rem; if (!decoder(fp, value, &rem)) fprintf(fp, "0x%x", rem); else if (rem != 0) fprintf(fp, "|0x%x", rem); } static void print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp, uint32_t value) { uint32_t rem; if (!decoder(fp, value, &rem)) fprintf(fp, "0x%x", rem); else if (rem != 0) fprintf(fp, "|0x%x", rem); } #ifndef __LP64__ /* * Add argument padding to subsequent system calls after Quad * syscall arguments as needed. This used to be done by hand in the * decoded_syscalls table which was ugly and error prone. It is * simpler to do the fixup of offsets at initialization time than when * decoding arguments. */ static void quad_fixup(struct syscall *sc) { int offset, prev; u_int i; offset = 0; prev = -1; for (i = 0; i < sc->nargs; i++) { /* This arg type is a dummy that doesn't use offset. */ if ((sc->args[i].type & ARG_MASK) == PipeFds) continue; assert(prev < sc->args[i].offset); prev = sc->args[i].offset; sc->args[i].offset += offset; switch (sc->args[i].type & ARG_MASK) { case Quad: case QuadHex: #ifdef __powerpc__ /* * 64-bit arguments on 32-bit powerpc must be * 64-bit aligned. If the current offset is * not aligned, the calling convention inserts * a 32-bit pad argument that should be skipped. */ if (sc->args[i].offset % 2 == 1) { sc->args[i].offset++; offset++; } #endif offset++; default: break; } } } #endif void init_syscalls(void) { struct syscall *sc; STAILQ_INIT(&syscalls); for (sc = decoded_syscalls; sc->name != NULL; sc++) { #ifndef __LP64__ quad_fixup(sc); #endif STAILQ_INSERT_HEAD(&syscalls, sc, entries); } } static struct syscall * find_syscall(struct procabi *abi, u_int number) { struct extra_syscall *es; if (number < nitems(abi->syscalls)) return (abi->syscalls[number]); STAILQ_FOREACH(es, &abi->extra_syscalls, entries) { if (es->number == number) return (es->sc); } return (NULL); } static void add_syscall(struct procabi *abi, u_int number, struct syscall *sc) { struct extra_syscall *es; if (number < nitems(abi->syscalls)) { assert(abi->syscalls[number] == NULL); abi->syscalls[number] = sc; } else { es = malloc(sizeof(*es)); es->sc = sc; es->number = number; STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries); } } /* * If/when the list gets big, it might be desirable to do it * as a hash table or binary search. */ struct syscall * get_syscall(struct threadinfo *t, u_int number, u_int nargs) { struct syscall *sc; const char *name; char *new_name; u_int i; sc = find_syscall(t->proc->abi, number); if (sc != NULL) return (sc); name = sysdecode_syscallname(t->proc->abi->abi, number); if (name == NULL) { asprintf(&new_name, "#%d", number); name = new_name; } else new_name = NULL; STAILQ_FOREACH(sc, &syscalls, entries) { if (strcmp(name, sc->name) == 0) { add_syscall(t->proc->abi, number, sc); free(new_name); return (sc); } } /* It is unknown. Add it into the list. */ #if DEBUG fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name, nargs); #endif sc = calloc(1, sizeof(struct syscall)); sc->name = name; if (new_name != NULL) sc->unknown = true; sc->ret_type = 1; sc->nargs = nargs; for (i = 0; i < nargs; i++) { sc->args[i].offset = i; /* Treat all unknown arguments as LongHex. */ sc->args[i].type = LongHex; } STAILQ_INSERT_HEAD(&syscalls, sc, entries); add_syscall(t->proc->abi, number, sc); return (sc); } /* * Copy a fixed amount of bytes from the process. */ static int get_struct(pid_t pid, uintptr_t offset, void *buf, int len) { struct ptrace_io_desc iorequest; iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = (void *)offset; iorequest.piod_addr = buf; iorequest.piod_len = len; if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) return (-1); return (0); } #define MAXSIZE 4096 /* * Copy a string from the process. Note that it is * expected to be a C string, but if max is set, it will * only get that much. */ static char * get_string(pid_t pid, uintptr_t addr, int max) { struct ptrace_io_desc iorequest; char *buf, *nbuf; size_t offset, size, totalsize; offset = 0; if (max) size = max + 1; else { /* Read up to the end of the current page. */ size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE); if (size > MAXSIZE) size = MAXSIZE; } totalsize = size; buf = malloc(totalsize); if (buf == NULL) return (NULL); for (;;) { iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = (void *)(addr + offset); iorequest.piod_addr = buf + offset; iorequest.piod_len = size; if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) { free(buf); return (NULL); } if (memchr(buf + offset, '\0', size) != NULL) return (buf); offset += size; if (totalsize < MAXSIZE && max == 0) { size = MAXSIZE - totalsize; if (size > PAGE_SIZE) size = PAGE_SIZE; nbuf = realloc(buf, totalsize + size); if (nbuf == NULL) { buf[totalsize - 1] = '\0'; return (buf); } buf = nbuf; totalsize += size; } else { buf[totalsize - 1] = '\0'; return (buf); } } } static const char * strsig2(int sig) { static char tmp[32]; const char *signame; signame = sysdecode_signal(sig); if (signame == NULL) { snprintf(tmp, sizeof(tmp), "%d", sig); signame = tmp; } return (signame); } static void print_kevent(FILE *fp, struct kevent *ke) { switch (ke->filter) { case EVFILT_READ: case EVFILT_WRITE: case EVFILT_VNODE: case EVFILT_PROC: case EVFILT_TIMER: case EVFILT_PROCDESC: case EVFILT_EMPTY: fprintf(fp, "%ju", (uintmax_t)ke->ident); break; case EVFILT_SIGNAL: fputs(strsig2(ke->ident), fp); break; default: fprintf(fp, "%p", (void *)ke->ident); } fprintf(fp, ","); print_integer_arg(sysdecode_kevent_filter, fp, ke->filter); fprintf(fp, ","); print_mask_arg(sysdecode_kevent_flags, fp, ke->flags); fprintf(fp, ","); sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16); fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata); } static void print_utrace(FILE *fp, void *utrace_addr, size_t len) { unsigned char *utrace_buffer; fprintf(fp, "{ "); if (sysdecode_utrace(fp, utrace_addr, len)) { fprintf(fp, " }"); return; } utrace_buffer = utrace_addr; fprintf(fp, "%zu:", len); while (len--) fprintf(fp, " %02x", *utrace_buffer++); fprintf(fp, " }"); } static void print_pointer(FILE *fp, uintptr_t arg) { fprintf(fp, "%p", (void *)arg); } static void print_sockaddr(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg, socklen_t len) { char addr[64]; struct sockaddr_in *lsin; struct sockaddr_in6 *lsin6; struct sockaddr_un *sun; struct sockaddr *sa; u_char *q; pid_t pid = trussinfo->curthread->proc->pid; if (arg == 0) { fputs("NULL", fp); return; } /* If the length is too small, just bail. */ if (len < sizeof(*sa)) { print_pointer(fp, arg); return; } sa = calloc(1, len); if (get_struct(pid, arg, sa, len) == -1) { free(sa); print_pointer(fp, arg); return; } switch (sa->sa_family) { case AF_INET: if (len < sizeof(*lsin)) goto sockaddr_short; lsin = (struct sockaddr_in *)(void *)sa; inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr)); fprintf(fp, "{ AF_INET %s:%d }", addr, htons(lsin->sin_port)); break; case AF_INET6: if (len < sizeof(*lsin6)) goto sockaddr_short; lsin6 = (struct sockaddr_in6 *)(void *)sa; inet_ntop(AF_INET6, &lsin6->sin6_addr, addr, sizeof(addr)); fprintf(fp, "{ AF_INET6 [%s]:%d }", addr, htons(lsin6->sin6_port)); break; case AF_UNIX: sun = (struct sockaddr_un *)sa; fprintf(fp, "{ AF_UNIX \"%.*s\" }", (int)(len - offsetof(struct sockaddr_un, sun_path)), sun->sun_path); break; default: sockaddr_short: fprintf(fp, "{ sa_len = %d, sa_family = %d, sa_data = {", (int)sa->sa_len, (int)sa->sa_family); for (q = (u_char *)sa->sa_data; q < (u_char *)sa + len; q++) fprintf(fp, "%s 0x%02x", q == (u_char *)sa->sa_data ? "" : ",", *q); fputs(" } }", fp); } free(sa); } #define IOV_LIMIT 16 static void print_iovec(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg, int iovcnt) { struct iovec iov[IOV_LIMIT]; size_t max_string = trussinfo->strsize; char tmp2[max_string + 1], *tmp3; size_t len; pid_t pid = trussinfo->curthread->proc->pid; int i; bool buf_truncated, iov_truncated; if (iovcnt <= 0) { print_pointer(fp, arg); return; } if (iovcnt > IOV_LIMIT) { iovcnt = IOV_LIMIT; iov_truncated = true; } else { iov_truncated = false; } if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) { print_pointer(fp, arg); return; } fputs("[", fp); for (i = 0; i < iovcnt; i++) { len = iov[i].iov_len; if (len > max_string) { len = max_string; buf_truncated = true; } else { buf_truncated = false; } fprintf(fp, "%s{", (i > 0) ? "," : ""); if (len && get_struct(pid, (uintptr_t)iov[i].iov_base, &tmp2, len) != -1) { tmp3 = malloc(len * 4 + 1); while (len) { if (strvisx(tmp3, tmp2, len, VIS_CSTYLE|VIS_TAB|VIS_NL) <= (int)max_string) break; len--; buf_truncated = true; } fprintf(fp, "\"%s\"%s", tmp3, buf_truncated ? "..." : ""); free(tmp3); } else { print_pointer(fp, (uintptr_t)iov[i].iov_base); } fprintf(fp, ",%zu}", iov[i].iov_len); } fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]"); } static void print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr) { u_char *q; fputs("{", fp); for (q = CMSG_DATA(cmsghdr); q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) { fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q); } fputs("}", fp); } static void print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init) { fprintf(fp, "{out=%u,", init->sinit_num_ostreams); fprintf(fp, "in=%u,", init->sinit_max_instreams); fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts); fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo); } static void print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info) { fprintf(fp, "{sid=%u,", info->sinfo_stream); if (receive) { fprintf(fp, "ssn=%u,", info->sinfo_ssn); } fputs("flgs=", fp); sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags); fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid)); if (!receive) { fprintf(fp, "ctx=%u,", info->sinfo_context); fprintf(fp, "ttl=%u,", info->sinfo_timetolive); } if (receive) { fprintf(fp, "tsn=%u,", info->sinfo_tsn); fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn); } fprintf(fp, "id=%u}", info->sinfo_assoc_id); } static void print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info) { fprintf(fp, "{sid=%u,", info->snd_sid); fputs("flgs=", fp); print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags); fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid)); fprintf(fp, "ctx=%u,", info->snd_context); fprintf(fp, "id=%u}", info->snd_assoc_id); } static void print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info) { fprintf(fp, "{sid=%u,", info->rcv_sid); fprintf(fp, "ssn=%u,", info->rcv_ssn); fputs("flgs=", fp); print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags); fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid)); fprintf(fp, "tsn=%u,", info->rcv_tsn); fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn); fprintf(fp, "ctx=%u,", info->rcv_context); fprintf(fp, "id=%u}", info->rcv_assoc_id); } static void print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info) { fprintf(fp, "{sid=%u,", info->nxt_sid); fputs("flgs=", fp); print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags); fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid)); fprintf(fp, "len=%u,", info->nxt_length); fprintf(fp, "id=%u}", info->nxt_assoc_id); } static void print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info) { fputs("{pol=", fp); print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy); fprintf(fp, ",val=%u}", info->pr_value); } static void print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info) { fprintf(fp, "{num=%u}", info->auth_keynumber); } static void print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr) { char buf[INET_ADDRSTRLEN]; const char *s; s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN); if (s != NULL) fprintf(fp, "{addr=%s}", s); else fputs("{addr=???}", fp); } static void print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr) { char buf[INET6_ADDRSTRLEN]; const char *s; s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN); if (s != NULL) fprintf(fp, "{addr=%s}", s); else fputs("{addr=???}", fp); } static void print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr) { void *data; socklen_t len; len = cmsghdr->cmsg_len; data = CMSG_DATA(cmsghdr); switch (cmsghdr->cmsg_type) { case SCTP_INIT: if (len == CMSG_LEN(sizeof(struct sctp_initmsg))) print_sctp_initmsg(fp, (struct sctp_initmsg *)data); else print_gen_cmsg(fp, cmsghdr); break; case SCTP_SNDRCV: if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo))) print_sctp_sndrcvinfo(fp, receive, (struct sctp_sndrcvinfo *)data); else print_gen_cmsg(fp, cmsghdr); break; #if 0 case SCTP_EXTRCV: if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo))) print_sctp_extrcvinfo(fp, (struct sctp_extrcvinfo *)data); else print_gen_cmsg(fp, cmsghdr); break; #endif case SCTP_SNDINFO: if (len == CMSG_LEN(sizeof(struct sctp_sndinfo))) print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data); else print_gen_cmsg(fp, cmsghdr); break; case SCTP_RCVINFO: if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo))) print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data); else print_gen_cmsg(fp, cmsghdr); break; case SCTP_NXTINFO: if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo))) print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data); else print_gen_cmsg(fp, cmsghdr); break; case SCTP_PRINFO: if (len == CMSG_LEN(sizeof(struct sctp_prinfo))) print_sctp_prinfo(fp, (struct sctp_prinfo *)data); else print_gen_cmsg(fp, cmsghdr); break; case SCTP_AUTHINFO: if (len == CMSG_LEN(sizeof(struct sctp_authinfo))) print_sctp_authinfo(fp, (struct sctp_authinfo *)data); else print_gen_cmsg(fp, cmsghdr); break; case SCTP_DSTADDRV4: if (len == CMSG_LEN(sizeof(struct in_addr))) print_sctp_ipv4_addr(fp, (struct in_addr *)data); else print_gen_cmsg(fp, cmsghdr); break; case SCTP_DSTADDRV6: if (len == CMSG_LEN(sizeof(struct in6_addr))) print_sctp_ipv6_addr(fp, (struct in6_addr *)data); else print_gen_cmsg(fp, cmsghdr); break; default: print_gen_cmsg(fp, cmsghdr); } } static void print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr) { struct cmsghdr *cmsghdr; char *cmsgbuf; const char *temp; socklen_t len; int level, type; bool first; len = msghdr->msg_controllen; if (len == 0) { fputs("{}", fp); return; } cmsgbuf = calloc(1, len); if (get_struct(pid, (uintptr_t)msghdr->msg_control, cmsgbuf, len) == -1) { print_pointer(fp, (uintptr_t)msghdr->msg_control); free(cmsgbuf); return; } msghdr->msg_control = cmsgbuf; first = true; fputs("{", fp); for (cmsghdr = CMSG_FIRSTHDR(msghdr); cmsghdr != NULL; cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) { level = cmsghdr->cmsg_level; type = cmsghdr->cmsg_type; len = cmsghdr->cmsg_len; fprintf(fp, "%s{level=", first ? "" : ","); print_integer_arg(sysdecode_sockopt_level, fp, level); fputs(",type=", fp); temp = sysdecode_cmsg_type(level, type); if (temp) { fputs(temp, fp); } else { fprintf(fp, "%d", type); } fputs(",data=", fp); switch (level) { case IPPROTO_SCTP: print_sctp_cmsg(fp, receive, cmsghdr); break; default: print_gen_cmsg(fp, cmsghdr); break; } fputs("}", fp); first = false; } fputs("}", fp); free(cmsgbuf); } static void print_sysctl_oid(FILE *fp, int *oid, int len) { int i; for (i = 0; i < len; i++) fprintf(fp, ".%d", oid[i]); } /* * Converts a syscall argument into a string. Said string is * allocated via malloc(), so needs to be free()'d. sc is * a pointer to the syscall description (see above); args is * an array of all of the system call arguments. */ char * print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval, struct trussinfo *trussinfo) { FILE *fp; char *tmp; size_t tmplen; pid_t pid; fp = open_memstream(&tmp, &tmplen); pid = trussinfo->curthread->proc->pid; switch (sc->type & ARG_MASK) { case Hex: fprintf(fp, "0x%x", (int)args[sc->offset]); break; case Octal: fprintf(fp, "0%o", (int)args[sc->offset]); break; case Int: fprintf(fp, "%d", (int)args[sc->offset]); break; case UInt: fprintf(fp, "%u", (unsigned int)args[sc->offset]); break; case PUInt: { unsigned int val; if (get_struct(pid, args[sc->offset], &val, sizeof(val)) == 0) fprintf(fp, "{ %u }", val); else print_pointer(fp, args[sc->offset]); break; } case LongHex: fprintf(fp, "0x%lx", args[sc->offset]); break; case Long: fprintf(fp, "%ld", args[sc->offset]); break; case Sizet: fprintf(fp, "%zu", (size_t)args[sc->offset]); break; case ShmName: /* Handle special SHM_ANON value. */ if ((char *)args[sc->offset] == SHM_ANON) { fprintf(fp, "SHM_ANON"); break; } /* FALLTHROUGH */ case Name: { /* NULL-terminated string. */ char *tmp2; tmp2 = get_string(pid, args[sc->offset], 0); fprintf(fp, "\"%s\"", tmp2); free(tmp2); break; } case BinString: { /* * Binary block of data that might have printable characters. * XXX If type|OUT, assume that the length is the syscall's * return value. Otherwise, assume that the length of the block * is in the next syscall argument. */ int max_string = trussinfo->strsize; char tmp2[max_string + 1], *tmp3; int len; int truncated = 0; if (sc->type & OUT) len = retval[0]; else len = args[sc->offset + 1]; /* * Don't print more than max_string characters, to avoid word * wrap. If we have to truncate put some ... after the string. */ if (len > max_string) { len = max_string; truncated = 1; } if (len && get_struct(pid, args[sc->offset], &tmp2, len) != -1) { tmp3 = malloc(len * 4 + 1); while (len) { if (strvisx(tmp3, tmp2, len, VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string) break; len--; truncated = 1; } fprintf(fp, "\"%s\"%s", tmp3, truncated ? "..." : ""); free(tmp3); } else { print_pointer(fp, args[sc->offset]); } break; } case ExecArgs: case ExecEnv: case StringArray: { uintptr_t addr; union { char *strarray[0]; char buf[PAGE_SIZE]; } u; char *string; size_t len; u_int first, i; /* * Only parse argv[] and environment arrays from exec calls * if requested. */ if (((sc->type & ARG_MASK) == ExecArgs && (trussinfo->flags & EXECVEARGS) == 0) || ((sc->type & ARG_MASK) == ExecEnv && (trussinfo->flags & EXECVEENVS) == 0)) { print_pointer(fp, args[sc->offset]); break; } /* * Read a page of pointers at a time. Punt if the top-level * pointer is not aligned. Note that the first read is of * a partial page. */ addr = args[sc->offset]; if (addr % sizeof(char *) != 0) { print_pointer(fp, args[sc->offset]); break; } len = PAGE_SIZE - (addr & PAGE_MASK); if (get_struct(pid, addr, u.buf, len) == -1) { print_pointer(fp, args[sc->offset]); break; } fputc('[', fp); first = 1; i = 0; while (u.strarray[i] != NULL) { string = get_string(pid, (uintptr_t)u.strarray[i], 0); fprintf(fp, "%s \"%s\"", first ? "" : ",", string); free(string); first = 0; i++; if (i == len / sizeof(char *)) { addr += len; len = PAGE_SIZE; if (get_struct(pid, addr, u.buf, len) == -1) { fprintf(fp, ", "); break; } i = 0; } } fputs(" ]", fp); break; } #ifdef __LP64__ case Quad: fprintf(fp, "%ld", args[sc->offset]); break; case QuadHex: fprintf(fp, "0x%lx", args[sc->offset]); break; #else case Quad: case QuadHex: { unsigned long long ll; #if _BYTE_ORDER == _LITTLE_ENDIAN ll = (unsigned long long)args[sc->offset + 1] << 32 | args[sc->offset]; #else ll = (unsigned long long)args[sc->offset] << 32 | args[sc->offset + 1]; #endif if ((sc->type & ARG_MASK) == Quad) fprintf(fp, "%lld", ll); else fprintf(fp, "0x%llx", ll); break; } #endif case PQuadHex: { uint64_t val; if (get_struct(pid, args[sc->offset], &val, sizeof(val)) == 0) fprintf(fp, "{ 0x%jx }", (uintmax_t)val); else print_pointer(fp, args[sc->offset]); break; } case Ptr: print_pointer(fp, args[sc->offset]); break; case Readlinkres: { char *tmp2; if (retval[0] == -1) break; tmp2 = get_string(pid, args[sc->offset], retval[0]); fprintf(fp, "\"%s\"", tmp2); free(tmp2); break; } case Ioctl: { const char *temp; unsigned long cmd; cmd = args[sc->offset]; temp = sysdecode_ioctlname(cmd); if (temp) fputs(temp, fp); else { fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }", cmd, cmd & IOC_OUT ? "R" : "", cmd & IOC_IN ? "W" : "", IOCGROUP(cmd), isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?', cmd & 0xFF, IOCPARM_LEN(cmd)); } break; } case Timespec: { struct timespec ts; if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1) fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec, ts.tv_nsec); else print_pointer(fp, args[sc->offset]); break; } case Timespec2: { struct timespec ts[2]; const char *sep; unsigned int i; if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1) { fputs("{ ", fp); sep = ""; for (i = 0; i < nitems(ts); i++) { fputs(sep, fp); sep = ", "; switch (ts[i].tv_nsec) { case UTIME_NOW: fprintf(fp, "UTIME_NOW"); break; case UTIME_OMIT: fprintf(fp, "UTIME_OMIT"); break; default: fprintf(fp, "%jd.%09ld", (intmax_t)ts[i].tv_sec, ts[i].tv_nsec); break; } } fputs(" }", fp); } else print_pointer(fp, args[sc->offset]); break; } case Timeval: { struct timeval tv; if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1) fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec, tv.tv_usec); else print_pointer(fp, args[sc->offset]); break; } case Timeval2: { struct timeval tv[2]; if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1) fprintf(fp, "{ %jd.%06ld, %jd.%06ld }", (intmax_t)tv[0].tv_sec, tv[0].tv_usec, (intmax_t)tv[1].tv_sec, tv[1].tv_usec); else print_pointer(fp, args[sc->offset]); break; } case Itimerval: { struct itimerval itv; if (get_struct(pid, args[sc->offset], &itv, sizeof(itv)) != -1) fprintf(fp, "{ %jd.%06ld, %jd.%06ld }", (intmax_t)itv.it_interval.tv_sec, itv.it_interval.tv_usec, (intmax_t)itv.it_value.tv_sec, itv.it_value.tv_usec); else print_pointer(fp, args[sc->offset]); break; } case LinuxSockArgs: { struct linux_socketcall_args largs; if (get_struct(pid, args[sc->offset], (void *)&largs, sizeof(largs)) != -1) fprintf(fp, "{ %s, 0x%lx }", lookup(linux_socketcall_ops, largs.what, 10), (long unsigned int)largs.args); else print_pointer(fp, args[sc->offset]); break; } case Pollfd: { /* * XXX: A Pollfd argument expects the /next/ syscall argument * to be the number of fds in the array. This matches the poll * syscall. */ struct pollfd *pfd; int numfds = args[sc->offset + 1]; size_t bytes = sizeof(struct pollfd) * numfds; int i; if ((pfd = malloc(bytes)) == NULL) err(1, "Cannot malloc %zu bytes for pollfd array", bytes); if (get_struct(pid, args[sc->offset], pfd, bytes) != -1) { fputs("{", fp); for (i = 0; i < numfds; i++) { fprintf(fp, " %d/%s", pfd[i].fd, xlookup_bits(poll_flags, pfd[i].events)); } fputs(" }", fp); } else { print_pointer(fp, args[sc->offset]); } free(pfd); break; } case Fd_set: { /* * XXX: A Fd_set argument expects the /first/ syscall argument * to be the number of fds in the array. This matches the * select syscall. */ fd_set *fds; int numfds = args[0]; size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS; int i; if ((fds = malloc(bytes)) == NULL) err(1, "Cannot malloc %zu bytes for fd_set array", bytes); if (get_struct(pid, args[sc->offset], fds, bytes) != -1) { fputs("{", fp); for (i = 0; i < numfds; i++) { if (FD_ISSET(i, fds)) fprintf(fp, " %d", i); } fputs(" }", fp); } else print_pointer(fp, args[sc->offset]); free(fds); break; } case Signal: fputs(strsig2(args[sc->offset]), fp); break; case Sigset: { long sig; sigset_t ss; int i, first; sig = args[sc->offset]; if (get_struct(pid, args[sc->offset], (void *)&ss, sizeof(ss)) == -1) { print_pointer(fp, args[sc->offset]); break; } fputs("{ ", fp); first = 1; for (i = 1; i < sys_nsig; i++) { if (sigismember(&ss, i)) { fprintf(fp, "%s%s", !first ? "|" : "", strsig2(i)); first = 0; } } if (!first) fputc(' ', fp); fputc('}', fp); break; } case Sigprocmask: print_integer_arg(sysdecode_sigprocmask_how, fp, args[sc->offset]); break; case Fcntlflag: /* XXX: Output depends on the value of the previous argument. */ if (sysdecode_fcntl_arg_p(args[sc->offset - 1])) sysdecode_fcntl_arg(fp, args[sc->offset - 1], args[sc->offset], 16); break; case Open: print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]); break; case Fcntl: print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]); break; case Mprot: print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]); break; case Mmapflags: print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]); break; case Whence: print_integer_arg(sysdecode_whence, fp, args[sc->offset]); break; case ShmFlags: print_mask_arg(sysdecode_shmflags, fp, args[sc->offset]); break; case Sockdomain: print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]); break; case Socktype: print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]); break; case Shutdown: print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]); break; case Resource: print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]); break; case RusageWho: print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]); break; case Pathconf: print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]); break; case Rforkflags: print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]); break; case Sockaddr: { socklen_t len; if (args[sc->offset] == 0) { fputs("NULL", fp); break; } /* * Extract the address length from the next argument. If * this is an output sockaddr (OUT is set), then the * next argument is a pointer to a socklen_t. Otherwise * the next argument contains a socklen_t by value. */ if (sc->type & OUT) { if (get_struct(pid, args[sc->offset + 1], &len, sizeof(len)) == -1) { print_pointer(fp, args[sc->offset]); break; } } else len = args[sc->offset + 1]; print_sockaddr(fp, trussinfo, args[sc->offset], len); break; } case Sigaction: { struct sigaction sa; if (get_struct(pid, args[sc->offset], &sa, sizeof(sa)) != -1) { fputs("{ ", fp); if (sa.sa_handler == SIG_DFL) fputs("SIG_DFL", fp); else if (sa.sa_handler == SIG_IGN) fputs("SIG_IGN", fp); else fprintf(fp, "%p", sa.sa_handler); fprintf(fp, " %s ss_t }", xlookup_bits(sigaction_flags, sa.sa_flags)); } else print_pointer(fp, args[sc->offset]); break; } case Kevent: { /* * XXX XXX: The size of the array is determined by either the * next syscall argument, or by the syscall return value, * depending on which argument number we are. This matches the * kevent syscall, but luckily that's the only syscall that uses * them. */ struct kevent *ke; int numevents = -1; size_t bytes; int i; if (sc->offset == 1) numevents = args[sc->offset+1]; else if (sc->offset == 3 && retval[0] != -1) numevents = retval[0]; if (numevents >= 0) { bytes = sizeof(struct kevent) * numevents; if ((ke = malloc(bytes)) == NULL) err(1, "Cannot malloc %zu bytes for kevent array", bytes); } else ke = NULL; if (numevents >= 0 && get_struct(pid, args[sc->offset], ke, bytes) != -1) { fputc('{', fp); for (i = 0; i < numevents; i++) { fputc(' ', fp); print_kevent(fp, &ke[i]); } fputs(" }", fp); } else { print_pointer(fp, args[sc->offset]); } free(ke); break; } case Kevent11: { struct kevent_freebsd11 *ke11; struct kevent ke; int numevents = -1; size_t bytes; int i; if (sc->offset == 1) numevents = args[sc->offset+1]; else if (sc->offset == 3 && retval[0] != -1) numevents = retval[0]; if (numevents >= 0) { bytes = sizeof(struct kevent_freebsd11) * numevents; if ((ke11 = malloc(bytes)) == NULL) err(1, "Cannot malloc %zu bytes for kevent array", bytes); } else ke11 = NULL; memset(&ke, 0, sizeof(ke)); if (numevents >= 0 && get_struct(pid, args[sc->offset], ke11, bytes) != -1) { fputc('{', fp); for (i = 0; i < numevents; i++) { fputc(' ', fp); ke.ident = ke11[i].ident; ke.filter = ke11[i].filter; ke.flags = ke11[i].flags; ke.fflags = ke11[i].fflags; ke.data = ke11[i].data; ke.udata = ke11[i].udata; print_kevent(fp, &ke); } fputs(" }", fp); } else { print_pointer(fp, args[sc->offset]); } free(ke11); break; } case Stat: { struct stat st; if (get_struct(pid, args[sc->offset], &st, sizeof(st)) != -1) { char mode[12]; strmode(st.st_mode, mode); fprintf(fp, "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode, (uintmax_t)st.st_ino, (intmax_t)st.st_size, (long)st.st_blksize); } else { print_pointer(fp, args[sc->offset]); } break; } case Stat11: { struct freebsd11_stat st; if (get_struct(pid, args[sc->offset], &st, sizeof(st)) != -1) { char mode[12]; strmode(st.st_mode, mode); fprintf(fp, "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode, (uintmax_t)st.st_ino, (intmax_t)st.st_size, (long)st.st_blksize); } else { print_pointer(fp, args[sc->offset]); } break; } case StatFs: { unsigned int i; struct statfs buf; if (get_struct(pid, args[sc->offset], &buf, sizeof(buf)) != -1) { char fsid[17]; bzero(fsid, sizeof(fsid)); if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) { for (i = 0; i < sizeof(buf.f_fsid); i++) snprintf(&fsid[i*2], sizeof(fsid) - (i*2), "%02x", ((u_char *)&buf.f_fsid)[i]); } fprintf(fp, "{ fstypename=%s,mntonname=%s,mntfromname=%s," "fsid=%s }", buf.f_fstypename, buf.f_mntonname, buf.f_mntfromname, fsid); } else print_pointer(fp, args[sc->offset]); break; } case Rusage: { struct rusage ru; if (get_struct(pid, args[sc->offset], &ru, sizeof(ru)) != -1) { fprintf(fp, "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }", (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec, (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec, ru.ru_inblock, ru.ru_oublock); } else print_pointer(fp, args[sc->offset]); break; } case Rlimit: { struct rlimit rl; if (get_struct(pid, args[sc->offset], &rl, sizeof(rl)) != -1) { fprintf(fp, "{ cur=%ju,max=%ju }", rl.rlim_cur, rl.rlim_max); } else print_pointer(fp, args[sc->offset]); break; } case ExitStatus: { int status; if (get_struct(pid, args[sc->offset], &status, sizeof(status)) != -1) { fputs("{ ", fp); if (WIFCONTINUED(status)) fputs("CONTINUED", fp); else if (WIFEXITED(status)) fprintf(fp, "EXITED,val=%d", WEXITSTATUS(status)); else if (WIFSIGNALED(status)) fprintf(fp, "SIGNALED,sig=%s%s", strsig2(WTERMSIG(status)), WCOREDUMP(status) ? ",cored" : ""); else fprintf(fp, "STOPPED,sig=%s", strsig2(WTERMSIG(status))); fputs(" }", fp); } else print_pointer(fp, args[sc->offset]); break; } case Waitoptions: print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]); break; case Idtype: print_integer_arg(sysdecode_idtype, fp, args[sc->offset]); break; case Procctl: print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]); break; case Umtxop: print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]); break; case Atfd: print_integer_arg(sysdecode_atfd, fp, args[sc->offset]); break; case Atflags: print_mask_arg(sysdecode_atflags, fp, args[sc->offset]); break; case Accessmode: print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]); break; case Sysarch: print_integer_arg(sysdecode_sysarch_number, fp, args[sc->offset]); break; case Sysctl: { char name[BUFSIZ]; int oid[CTL_MAXNAME + 2], qoid[CTL_MAXNAME + 2]; size_t i; int len; memset(name, 0, sizeof(name)); len = args[sc->offset + 1]; if (get_struct(pid, args[sc->offset], oid, len * sizeof(oid[0])) != -1) { fprintf(fp, "\""); if (oid[0] == CTL_SYSCTL) { fprintf(fp, "sysctl."); switch (oid[1]) { case CTL_SYSCTL_DEBUG: fprintf(fp, "debug"); break; case CTL_SYSCTL_NAME: fprintf(fp, "name"); print_sysctl_oid(fp, oid + 2, len - 2); break; case CTL_SYSCTL_NEXT: fprintf(fp, "next"); break; case CTL_SYSCTL_NAME2OID: fprintf(fp, "name2oid"); break; case CTL_SYSCTL_OIDFMT: fprintf(fp, "oidfmt"); print_sysctl_oid(fp, oid + 2, len - 2); break; case CTL_SYSCTL_OIDDESCR: fprintf(fp, "oiddescr"); print_sysctl_oid(fp, oid + 2, len - 2); break; case CTL_SYSCTL_OIDLABEL: fprintf(fp, "oidlabel"); print_sysctl_oid(fp, oid + 2, len - 2); break; default: print_sysctl_oid(fp, oid + 1, len - 1); } } else { qoid[0] = CTL_SYSCTL; qoid[1] = CTL_SYSCTL_NAME; memcpy(qoid + 2, oid, len * sizeof(int)); i = sizeof(name); if (sysctl(qoid, len + 2, name, &i, 0, 0) == -1) print_sysctl_oid(fp, qoid + 2, len); else fprintf(fp, "%s", name); } fprintf(fp, "\""); } break; } case PipeFds: /* * The pipe() system call in the kernel returns its * two file descriptors via return values. However, * the interface exposed by libc is that pipe() * accepts a pointer to an array of descriptors. * Format the output to match the libc API by printing * the returned file descriptors as a fake argument. * * Overwrite the first retval to signal a successful * return as well. */ fprintf(fp, "{ %d, %d }", (int)retval[0], (int)retval[1]); retval[0] = 0; break; case Utrace: { size_t len; void *utrace_addr; len = args[sc->offset + 1]; utrace_addr = calloc(1, len); if (get_struct(pid, args[sc->offset], (void *)utrace_addr, len) != -1) print_utrace(fp, utrace_addr, len); else print_pointer(fp, args[sc->offset]); free(utrace_addr); break; } case IntArray: { int descriptors[16]; unsigned long i, ndescriptors; bool truncated; ndescriptors = args[sc->offset + 1]; truncated = false; if (ndescriptors > nitems(descriptors)) { ndescriptors = nitems(descriptors); truncated = true; } if (get_struct(pid, args[sc->offset], descriptors, ndescriptors * sizeof(descriptors[0])) != -1) { fprintf(fp, "{"); for (i = 0; i < ndescriptors; i++) fprintf(fp, i == 0 ? " %d" : ", %d", descriptors[i]); fprintf(fp, truncated ? ", ... }" : " }"); } else print_pointer(fp, args[sc->offset]); break; } case Pipe2: print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]); break; case CapFcntlRights: { uint32_t rights; if (sc->type & OUT) { if (get_struct(pid, args[sc->offset], &rights, sizeof(rights)) == -1) { print_pointer(fp, args[sc->offset]); break; } } else rights = args[sc->offset]; print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights); break; } case Fadvice: print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]); break; case FileFlags: { fflags_t rem; if (!sysdecode_fileflags(fp, args[sc->offset], &rem)) fprintf(fp, "0x%x", rem); else if (rem != 0) fprintf(fp, "|0x%x", rem); break; } case Flockop: print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]); break; case Getfsstatmode: print_integer_arg(sysdecode_getfsstat_mode, fp, args[sc->offset]); break; case Kldsymcmd: print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]); break; case Kldunloadflags: print_integer_arg(sysdecode_kldunload_flags, fp, args[sc->offset]); break; case Madvice: print_integer_arg(sysdecode_madvice, fp, args[sc->offset]); break; case Socklent: fprintf(fp, "%u", (socklen_t)args[sc->offset]); break; case Sockprotocol: { const char *temp; int domain, protocol; domain = args[sc->offset - 2]; protocol = args[sc->offset]; if (protocol == 0) { fputs("0", fp); } else { temp = sysdecode_socket_protocol(domain, protocol); if (temp) { fputs(temp, fp); } else { fprintf(fp, "%d", protocol); } } break; } case Sockoptlevel: print_integer_arg(sysdecode_sockopt_level, fp, args[sc->offset]); break; case Sockoptname: { const char *temp; int level, name; level = args[sc->offset - 1]; name = args[sc->offset]; temp = sysdecode_sockopt_name(level, name); if (temp) { fputs(temp, fp); } else { fprintf(fp, "%d", name); } break; } case Msgflags: print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]); break; case CapRights: { cap_rights_t rights; if (get_struct(pid, args[sc->offset], &rights, sizeof(rights)) != -1) { fputs("{ ", fp); sysdecode_cap_rights(fp, &rights); fputs(" }", fp); } else print_pointer(fp, args[sc->offset]); break; } case Acltype: print_integer_arg(sysdecode_acltype, fp, args[sc->offset]); break; case Extattrnamespace: print_integer_arg(sysdecode_extattrnamespace, fp, args[sc->offset]); break; case Minherit: print_integer_arg(sysdecode_minherit_inherit, fp, args[sc->offset]); break; case Mlockall: print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]); break; case Mountflags: print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]); break; case Msync: print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]); break; case Priowhich: print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]); break; case Ptraceop: print_integer_arg(sysdecode_ptrace_request, fp, args[sc->offset]); break; case Quotactlcmd: if (!sysdecode_quotactl_cmd(fp, args[sc->offset])) fprintf(fp, "%#x", (int)args[sc->offset]); break; case Reboothowto: print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]); break; case Rtpriofunc: print_integer_arg(sysdecode_rtprio_function, fp, args[sc->offset]); break; case Schedpolicy: print_integer_arg(sysdecode_scheduler_policy, fp, args[sc->offset]); break; case Schedparam: { struct sched_param sp; if (get_struct(pid, args[sc->offset], &sp, sizeof(sp)) != -1) fprintf(fp, "{ %d }", sp.sched_priority); else print_pointer(fp, args[sc->offset]); break; } case PSig: { int sig; if (get_struct(pid, args[sc->offset], &sig, sizeof(sig)) == 0) fprintf(fp, "{ %s }", strsig2(sig)); else print_pointer(fp, args[sc->offset]); break; } case Siginfo: { siginfo_t si; if (get_struct(pid, args[sc->offset], &si, sizeof(si)) != -1) { fprintf(fp, "{ signo=%s", strsig2(si.si_signo)); decode_siginfo(fp, &si); fprintf(fp, " }"); } else print_pointer(fp, args[sc->offset]); break; } case Iovec: /* * Print argument as an array of struct iovec, where the next * syscall argument is the number of elements of the array. */ print_iovec(fp, trussinfo, args[sc->offset], (int)args[sc->offset + 1]); break; case Sctpsndrcvinfo: { struct sctp_sndrcvinfo info; if (get_struct(pid, args[sc->offset], &info, sizeof(struct sctp_sndrcvinfo)) == -1) { print_pointer(fp, args[sc->offset]); break; } print_sctp_sndrcvinfo(fp, sc->type & OUT, &info); break; } case Msghdr: { struct msghdr msghdr; if (get_struct(pid, args[sc->offset], &msghdr, sizeof(struct msghdr)) == -1) { print_pointer(fp, args[sc->offset]); break; } fputs("{", fp); print_sockaddr(fp, trussinfo, (uintptr_t)msghdr.msg_name, msghdr.msg_namelen); fprintf(fp, ",%d,", msghdr.msg_namelen); print_iovec(fp, trussinfo, (uintptr_t)msghdr.msg_iov, msghdr.msg_iovlen); fprintf(fp, ",%d,", msghdr.msg_iovlen); print_cmsgs(fp, pid, sc->type & OUT, &msghdr); fprintf(fp, ",%u,", msghdr.msg_controllen); print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags); fputs("}", fp); break; } case CloudABIAdvice: fputs(xlookup(cloudabi_advice, args[sc->offset]), fp); break; case CloudABIClockID: fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp); break; case CloudABIFDSFlags: fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp); break; case CloudABIFDStat: { cloudabi_fdstat_t fds; if (get_struct(pid, args[sc->offset], &fds, sizeof(fds)) != -1) { fprintf(fp, "{ %s, ", xlookup(cloudabi_filetype, fds.fs_filetype)); fprintf(fp, "%s, ... }", xlookup_bits(cloudabi_fdflags, fds.fs_flags)); } else print_pointer(fp, args[sc->offset]); break; } case CloudABIFileStat: { cloudabi_filestat_t fsb; if (get_struct(pid, args[sc->offset], &fsb, sizeof(fsb)) != -1) fprintf(fp, "{ %s, %ju }", xlookup(cloudabi_filetype, fsb.st_filetype), (uintmax_t)fsb.st_size); else print_pointer(fp, args[sc->offset]); break; } case CloudABIFileType: fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp); break; case CloudABIFSFlags: fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp); break; case CloudABILookup: if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0) fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW", (int)args[sc->offset]); else fprintf(fp, "%d", (int)args[sc->offset]); break; case CloudABIMFlags: fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp); break; case CloudABIMProt: fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp); break; case CloudABIMSFlags: fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp); break; case CloudABIOFlags: fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp); break; case CloudABISDFlags: fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp); break; case CloudABISignal: fputs(xlookup(cloudabi_signal, args[sc->offset]), fp); break; case CloudABITimestamp: fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000, args[sc->offset] % 1000000000); break; case CloudABIULFlags: fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp); break; case CloudABIWhence: fputs(xlookup(cloudabi_whence, args[sc->offset]), fp); break; default: errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK); } fclose(fp); return (tmp); } /* * Print (to outfile) the system call and its arguments. */ void print_syscall(struct trussinfo *trussinfo) { struct threadinfo *t; const char *name; char **s_args; int i, len, nargs; t = trussinfo->curthread; name = t->cs.sc->name; nargs = t->cs.nargs; s_args = t->cs.s_args; len = print_line_prefix(trussinfo); len += fprintf(trussinfo->outfile, "%s(", name); for (i = 0; i < nargs; i++) { if (s_args[i] != NULL) len += fprintf(trussinfo->outfile, "%s", s_args[i]); else len += fprintf(trussinfo->outfile, ""); len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ? "," : ""); } len += fprintf(trussinfo->outfile, ")"); for (i = 0; i < 6 - (len / 8); i++) fprintf(trussinfo->outfile, "\t"); } void print_syscall_ret(struct trussinfo *trussinfo, int error, register_t *retval) { struct timespec timediff; struct threadinfo *t; struct syscall *sc; t = trussinfo->curthread; sc = t->cs.sc; if (trussinfo->flags & COUNTONLY) { timespecsub(&t->after, &t->before, &timediff); timespecadd(&sc->time, &timediff, &sc->time); sc->ncalls++; if (error != 0) sc->nerror++; return; } print_syscall(trussinfo); fflush(trussinfo->outfile); if (retval == NULL) { /* * This system call resulted in the current thread's exit, * so there is no return value or error to display. */ fprintf(trussinfo->outfile, "\n"); return; } if (error == ERESTART) fprintf(trussinfo->outfile, " ERESTART\n"); else if (error == EJUSTRETURN) fprintf(trussinfo->outfile, " EJUSTRETURN\n"); else if (error != 0) { fprintf(trussinfo->outfile, " ERR#%d '%s'\n", sysdecode_freebsd_to_abi_errno(t->proc->abi->abi, error), strerror(error)); } #ifndef __LP64__ else if (sc->ret_type == 2) { off_t off; #if _BYTE_ORDER == _LITTLE_ENDIAN off = (off_t)retval[1] << 32 | retval[0]; #else off = (off_t)retval[0] << 32 | retval[1]; #endif fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off, (intmax_t)off); } #endif else fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)retval[0], (intmax_t)retval[0]); } void print_summary(struct trussinfo *trussinfo) { struct timespec total = {0, 0}; struct syscall *sc; int ncall, nerror; fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n", "syscall", "seconds", "calls", "errors"); ncall = nerror = 0; STAILQ_FOREACH(sc, &syscalls, entries) if (sc->ncalls) { fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n", sc->name, (intmax_t)sc->time.tv_sec, sc->time.tv_nsec, sc->ncalls, sc->nerror); timespecadd(&total, &sc->time, &total); ncall += sc->ncalls; nerror += sc->nerror; } fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n", "", "-------------", "-------", "-------"); fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n", "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror); }