18ac5aef8SEnji Cooper /*
28ac5aef8SEnji Cooper * Minimal portability layer for system call differences between
38ac5aef8SEnji Cooper * Capsicum OSes.
48ac5aef8SEnji Cooper */
58ac5aef8SEnji Cooper #ifndef __SYSCALLS_H__
68ac5aef8SEnji Cooper #define __SYSCALLS_H__
78ac5aef8SEnji Cooper
88ac5aef8SEnji Cooper /************************************************************
98ac5aef8SEnji Cooper * FreeBSD
108ac5aef8SEnji Cooper ************************************************************/
118ac5aef8SEnji Cooper #ifdef __FreeBSD__
128ac5aef8SEnji Cooper
138ac5aef8SEnji Cooper /* Map umount2 (Linux) syscall to unmount (FreeBSD) syscall */
148ac5aef8SEnji Cooper #define umount2(T, F) unmount(T, F)
158ac5aef8SEnji Cooper
168ac5aef8SEnji Cooper /* Map sighandler_y (Linux) to sig_t (FreeBSD) */
178ac5aef8SEnji Cooper #define sighandler_t sig_t
188ac5aef8SEnji Cooper
198ac5aef8SEnji Cooper /* profil(2) has a first argument of char* */
208ac5aef8SEnji Cooper #define profil_arg1_t char
218ac5aef8SEnji Cooper
228ac5aef8SEnji Cooper /* FreeBSD has getdents(2) available */
238ac5aef8SEnji Cooper #include <sys/types.h>
248ac5aef8SEnji Cooper #include <dirent.h>
getdents_(unsigned int fd,void * dirp,unsigned int count)258ac5aef8SEnji Cooper inline int getdents_(unsigned int fd, void *dirp, unsigned int count) {
268ac5aef8SEnji Cooper return getdents(fd, (char*)dirp, count);
278ac5aef8SEnji Cooper }
288ac5aef8SEnji Cooper #include <sys/mman.h>
mincore_(void * addr,size_t length,unsigned char * vec)298ac5aef8SEnji Cooper inline int mincore_(void *addr, size_t length, unsigned char *vec) {
308ac5aef8SEnji Cooper return mincore(addr, length, (char*)vec);
318ac5aef8SEnji Cooper }
328ac5aef8SEnji Cooper #define getpid_ getpid
338ac5aef8SEnji Cooper
348ac5aef8SEnji Cooper /* Map Linux-style sendfile to FreeBSD sendfile */
358ac5aef8SEnji Cooper #include <sys/socket.h>
368ac5aef8SEnji Cooper #include <sys/uio.h>
sendfile_(int out_fd,int in_fd,off_t * offset,size_t count)378ac5aef8SEnji Cooper inline ssize_t sendfile_(int out_fd, int in_fd, off_t *offset, size_t count) {
388ac5aef8SEnji Cooper return sendfile(in_fd, out_fd, *offset, count, NULL, offset, 0);
398ac5aef8SEnji Cooper }
408ac5aef8SEnji Cooper
418ac5aef8SEnji Cooper /* A sample mount(2) call */
428ac5aef8SEnji Cooper #include <sys/param.h>
438ac5aef8SEnji Cooper #include <sys/mount.h>
bogus_mount_()448ac5aef8SEnji Cooper inline int bogus_mount_() {
458ac5aef8SEnji Cooper return mount("procfs", "/not_mounted", 0, NULL);
468ac5aef8SEnji Cooper }
478ac5aef8SEnji Cooper
488ac5aef8SEnji Cooper /* Mappings for extended attribute functions */
498ac5aef8SEnji Cooper #include <sys/extattr.h>
50*4ee9db7aSEd Maste #include <errno.h>
fbsd_extattr_skip_prefix(const char * p)51*4ee9db7aSEd Maste static const char *fbsd_extattr_skip_prefix(const char *p) {
52*4ee9db7aSEd Maste if (*p++ == 'u' && *p++ == 's' && *p++ == 'e' && *p++ == 'r' && *p++ == '.')
53*4ee9db7aSEd Maste return p;
54*4ee9db7aSEd Maste errno = EINVAL;
55*4ee9db7aSEd Maste return NULL;
56*4ee9db7aSEd Maste }
flistxattr_(int fd,char * list,size_t size)578ac5aef8SEnji Cooper inline ssize_t flistxattr_(int fd, char *list, size_t size) {
588ac5aef8SEnji Cooper return extattr_list_fd(fd, EXTATTR_NAMESPACE_USER, list, size);
598ac5aef8SEnji Cooper }
fgetxattr_(int fd,const char * name,void * value,size_t size)608ac5aef8SEnji Cooper inline ssize_t fgetxattr_(int fd, const char *name, void *value, size_t size) {
61*4ee9db7aSEd Maste if (!(name = fbsd_extattr_skip_prefix(name)))
62*4ee9db7aSEd Maste return -1;
638ac5aef8SEnji Cooper return extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, name, value, size);
648ac5aef8SEnji Cooper }
fsetxattr_(int fd,const char * name,const void * value,size_t size,int)658ac5aef8SEnji Cooper inline int fsetxattr_(int fd, const char *name, const void *value, size_t size, int) {
66*4ee9db7aSEd Maste if (!(name = fbsd_extattr_skip_prefix(name)))
67*4ee9db7aSEd Maste return -1;
688ac5aef8SEnji Cooper return extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, name, value, size);
698ac5aef8SEnji Cooper }
fremovexattr_(int fd,const char * name)708ac5aef8SEnji Cooper inline int fremovexattr_(int fd, const char *name) {
71*4ee9db7aSEd Maste if (!(name = fbsd_extattr_skip_prefix(name)))
72*4ee9db7aSEd Maste return -1;
738ac5aef8SEnji Cooper return extattr_delete_fd(fd, EXTATTR_NAMESPACE_USER, name);
748ac5aef8SEnji Cooper }
758ac5aef8SEnji Cooper
768ac5aef8SEnji Cooper /* mq_* functions are wrappers in FreeBSD so go through to underlying syscalls */
778ac5aef8SEnji Cooper #include <sys/syscall.h>
788ac5aef8SEnji Cooper extern "C" {
798ac5aef8SEnji Cooper extern int __sys_kmq_notify(int, const struct sigevent *);
808ac5aef8SEnji Cooper extern int __sys_kmq_open(const char *, int, mode_t, const struct mq_attr *);
818ac5aef8SEnji Cooper extern int __sys_kmq_setattr(int, const struct mq_attr *__restrict, struct mq_attr *__restrict);
828ac5aef8SEnji Cooper extern ssize_t __sys_kmq_timedreceive(int, char *__restrict, size_t,
838ac5aef8SEnji Cooper unsigned *__restrict, const struct timespec *__restrict);
848ac5aef8SEnji Cooper extern int __sys_kmq_timedsend(int, const char *, size_t, unsigned,
858ac5aef8SEnji Cooper const struct timespec *);
868ac5aef8SEnji Cooper extern int __sys_kmq_unlink(const char *);
878ac5aef8SEnji Cooper }
888ac5aef8SEnji Cooper #define mq_notify_ __sys_kmq_notify
898ac5aef8SEnji Cooper #define mq_open_ __sys_kmq_open
908ac5aef8SEnji Cooper #define mq_setattr_ __sys_kmq_setattr
918ac5aef8SEnji Cooper #define mq_getattr_(A, B) __sys_kmq_setattr(A, NULL, B)
928ac5aef8SEnji Cooper #define mq_timedreceive_ __sys_kmq_timedreceive
938ac5aef8SEnji Cooper #define mq_timedsend_ __sys_kmq_timedsend
948ac5aef8SEnji Cooper #define mq_unlink_ __sys_kmq_unlink
958ac5aef8SEnji Cooper #define mq_close_ close
968ac5aef8SEnji Cooper #include <sys/ptrace.h>
ptrace_(int request,pid_t pid,void * addr,void * data)978ac5aef8SEnji Cooper inline long ptrace_(int request, pid_t pid, void *addr, void *data) {
988ac5aef8SEnji Cooper return ptrace(request, pid, (caddr_t)addr, static_cast<int>((long)data));
998ac5aef8SEnji Cooper }
1008ac5aef8SEnji Cooper #define PTRACE_PEEKDATA_ PT_READ_D
1018ac5aef8SEnji Cooper #define getegid_ getegid
1028ac5aef8SEnji Cooper #define getgid_ getgid
1038ac5aef8SEnji Cooper #define geteuid_ geteuid
1048ac5aef8SEnji Cooper #define getuid_ getuid
1058ac5aef8SEnji Cooper #define getgroups_ getgroups
1068ac5aef8SEnji Cooper #define getrlimit_ getrlimit
1078ac5aef8SEnji Cooper #define bind_ bind
1088ac5aef8SEnji Cooper #define connect_ connect
1098ac5aef8SEnji Cooper
1108ac5aef8SEnji Cooper /* Features available */
1118ac5aef8SEnji Cooper #if __FreeBSD_version >= 1000000
1128ac5aef8SEnji Cooper #define HAVE_CHFLAGSAT
1138ac5aef8SEnji Cooper #define HAVE_BINDAT
1148ac5aef8SEnji Cooper #define HAVE_CONNECTAT
1158ac5aef8SEnji Cooper #endif
1168ac5aef8SEnji Cooper #define HAVE_CHFLAGS
1178ac5aef8SEnji Cooper #define HAVE_GETFSSTAT
1188ac5aef8SEnji Cooper #define HAVE_REVOKE
1198ac5aef8SEnji Cooper #define HAVE_GETLOGIN
1208ac5aef8SEnji Cooper #define HAVE_MKFIFOAT
1218ac5aef8SEnji Cooper #define HAVE_SYSARCH
1228ac5aef8SEnji Cooper #include <machine/sysarch.h>
1238ac5aef8SEnji Cooper #define HAVE_STAT_BIRTHTIME
1248ac5aef8SEnji Cooper #define HAVE_SYSCTL
1258ac5aef8SEnji Cooper #define HAVE_FPATHCONF
1268ac5aef8SEnji Cooper #define HAVE_F_DUP2FD
1278ac5aef8SEnji Cooper #define HAVE_PSELECT
1288ac5aef8SEnji Cooper #define HAVE_SCTP
1298ac5aef8SEnji Cooper
1308ac5aef8SEnji Cooper /* FreeBSD only allows root to call mlock[all]/munlock[all] */
1318ac5aef8SEnji Cooper #define MLOCK_REQUIRES_ROOT 1
1328ac5aef8SEnji Cooper /* FreeBSD effectively only allows root to call sched_setscheduler */
1338ac5aef8SEnji Cooper #define SCHED_SETSCHEDULER_REQUIRES_ROOT 1
1348ac5aef8SEnji Cooper
1358ac5aef8SEnji Cooper #endif /* FreeBSD */
1368ac5aef8SEnji Cooper
1378ac5aef8SEnji Cooper /************************************************************
1388ac5aef8SEnji Cooper * Linux
1398ac5aef8SEnji Cooper ************************************************************/
1408ac5aef8SEnji Cooper #ifdef __linux__
1418ac5aef8SEnji Cooper #include <fcntl.h>
1428ac5aef8SEnji Cooper #include <unistd.h>
1438ac5aef8SEnji Cooper #include <sys/prctl.h>
1448ac5aef8SEnji Cooper #include <sys/syscall.h>
1458ac5aef8SEnji Cooper #include <sys/types.h>
1468ac5aef8SEnji Cooper #include <sys/time.h>
1478ac5aef8SEnji Cooper #include <sys/resource.h>
1488ac5aef8SEnji Cooper #include <sys/wait.h>
1498ac5aef8SEnji Cooper #include <sys/sendfile.h>
1508ac5aef8SEnji Cooper #include <sys/statfs.h>
1518ac5aef8SEnji Cooper #include <sys/xattr.h>
1528ac5aef8SEnji Cooper #include <sys/mount.h>
1538ac5aef8SEnji Cooper #include <linux/net.h>
1548ac5aef8SEnji Cooper
1558ac5aef8SEnji Cooper /* profil(2) has a first argument of unsigned short* */
1568ac5aef8SEnji Cooper #define profil_arg1_t unsigned short
1578ac5aef8SEnji Cooper
getdents_(unsigned int fd,void * dirp,unsigned int count)1588ac5aef8SEnji Cooper static inline int getdents_(unsigned int fd, void *dirp, unsigned int count) {
1598ac5aef8SEnji Cooper return syscall(__NR_getdents, fd, dirp, count);
1608ac5aef8SEnji Cooper }
1618ac5aef8SEnji Cooper /* A sample mount(2) call */
bogus_mount_()1628ac5aef8SEnji Cooper static inline int bogus_mount_() {
1638ac5aef8SEnji Cooper return mount("/dev/bogus", "/bogus", "debugfs", MS_RDONLY, "");
1648ac5aef8SEnji Cooper }
1658ac5aef8SEnji Cooper
1668ac5aef8SEnji Cooper /* libc's getpid() wrapper caches the pid value, and doesn't invalidate
1678ac5aef8SEnji Cooper * the cached value on pdfork(), so directly syscall. */
getpid_()1688ac5aef8SEnji Cooper static inline pid_t getpid_() {
1698ac5aef8SEnji Cooper return syscall(__NR_getpid);
1708ac5aef8SEnji Cooper }
execveat(int fd,const char * path,char * const argv[],char * const envp[],int flags)1718ac5aef8SEnji Cooper static inline int execveat(int fd, const char *path,
1728ac5aef8SEnji Cooper char *const argv[], char *const envp[], int flags) {
1738ac5aef8SEnji Cooper return syscall(__NR_execveat, fd, path, argv, envp, flags);
1748ac5aef8SEnji Cooper }
1758ac5aef8SEnji Cooper
1768ac5aef8SEnji Cooper /*
1778ac5aef8SEnji Cooper * Linux glibc includes an fexecve() function, implemented via the /proc
1788ac5aef8SEnji Cooper * filesystem. Bypass this and go directly to the execveat(2) syscall.
1798ac5aef8SEnji Cooper */
fexecve_(int fd,char * const argv[],char * const envp[])1808ac5aef8SEnji Cooper static inline int fexecve_(int fd, char *const argv[], char *const envp[]) {
1818ac5aef8SEnji Cooper return execveat(fd, "", argv, envp, AT_EMPTY_PATH);
1828ac5aef8SEnji Cooper }
1838ac5aef8SEnji Cooper /*
1848ac5aef8SEnji Cooper * Linux glibc attempts to be clever and intercepts various uid/gid functions.
1858ac5aef8SEnji Cooper * Bypass by calling the syscalls directly.
1868ac5aef8SEnji Cooper */
getegid_(void)1878ac5aef8SEnji Cooper static inline gid_t getegid_(void) { return syscall(__NR_getegid); }
getgid_(void)1888ac5aef8SEnji Cooper static inline gid_t getgid_(void) { return syscall(__NR_getgid); }
geteuid_(void)1898ac5aef8SEnji Cooper static inline uid_t geteuid_(void) { return syscall(__NR_geteuid); }
getuid_(void)1908ac5aef8SEnji Cooper static inline uid_t getuid_(void) { return syscall(__NR_getuid); }
getgroups_(int size,gid_t list[])1918ac5aef8SEnji Cooper static inline int getgroups_(int size, gid_t list[]) { return syscall(__NR_getgroups, size, list); }
getrlimit_(int resource,struct rlimit * rlim)1928ac5aef8SEnji Cooper static inline int getrlimit_(int resource, struct rlimit *rlim) {
1938ac5aef8SEnji Cooper return syscall(__NR_getrlimit, resource, rlim);
1948ac5aef8SEnji Cooper }
1958ac5aef8SEnji Cooper
1968ac5aef8SEnji Cooper /*
1978ac5aef8SEnji Cooper * Linux glibc for i386 consumes the errno returned from the raw socketcall(2) operation,
1988ac5aef8SEnji Cooper * so use the raw syscall for those operations that are disallowed in capability mode.
1998ac5aef8SEnji Cooper */
2008ac5aef8SEnji Cooper #ifdef __NR_bind
2018ac5aef8SEnji Cooper #define bind_ bind
2028ac5aef8SEnji Cooper #else
bind_(int sockfd,const struct sockaddr * addr,socklen_t addrlen)2038ac5aef8SEnji Cooper static inline int bind_(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
2048ac5aef8SEnji Cooper unsigned long args[3] = {(unsigned long)sockfd, (unsigned long)(intptr_t)addr, (unsigned long)addrlen};
2058ac5aef8SEnji Cooper return syscall(__NR_socketcall, SYS_BIND, args);
2068ac5aef8SEnji Cooper }
2078ac5aef8SEnji Cooper #endif
2088ac5aef8SEnji Cooper #ifdef __NR_connect
2098ac5aef8SEnji Cooper #define connect_ connect
2108ac5aef8SEnji Cooper #else
connect_(int sockfd,const struct sockaddr * addr,socklen_t addrlen)2118ac5aef8SEnji Cooper static inline int connect_(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
2128ac5aef8SEnji Cooper unsigned long args[3] = {(unsigned long)sockfd, (unsigned long)(intptr_t)addr, (unsigned long)addrlen};
2138ac5aef8SEnji Cooper return syscall(__NR_socketcall, SYS_CONNECT, args);
2148ac5aef8SEnji Cooper }
2158ac5aef8SEnji Cooper #endif
2168ac5aef8SEnji Cooper
2178ac5aef8SEnji Cooper #define mincore_ mincore
2188ac5aef8SEnji Cooper #define sendfile_ sendfile
2198ac5aef8SEnji Cooper #define flistxattr_ flistxattr
2208ac5aef8SEnji Cooper #define fgetxattr_ fgetxattr
2218ac5aef8SEnji Cooper #define fsetxattr_ fsetxattr
2228ac5aef8SEnji Cooper #define fremovexattr_ fremovexattr
2238ac5aef8SEnji Cooper #define mq_notify_ mq_notify
2248ac5aef8SEnji Cooper #define mq_open_ mq_open
2258ac5aef8SEnji Cooper #define mq_setattr_ mq_setattr
2268ac5aef8SEnji Cooper #define mq_getattr_ mq_getattr
2278ac5aef8SEnji Cooper #define mq_timedreceive_ mq_timedreceive
2288ac5aef8SEnji Cooper #define mq_timedsend_ mq_timedsend
2298ac5aef8SEnji Cooper #define mq_unlink_ mq_unlink
2308ac5aef8SEnji Cooper #define mq_close_ mq_close
2318ac5aef8SEnji Cooper #define ptrace_ ptrace
2328ac5aef8SEnji Cooper #define PTRACE_PEEKDATA_ PTRACE_PEEKDATA
2338ac5aef8SEnji Cooper
2348ac5aef8SEnji Cooper /* Features available */
2358ac5aef8SEnji Cooper #define HAVE_DUP3
2368ac5aef8SEnji Cooper #define HAVE_PIPE2
2378ac5aef8SEnji Cooper #include <sys/fsuid.h> /* for setfsgid()/setfsuid() */
2388ac5aef8SEnji Cooper #define HAVE_SETFSUID
2398ac5aef8SEnji Cooper #define HAVE_SETFSGID
2408ac5aef8SEnji Cooper #define HAVE_READAHEAD
2418ac5aef8SEnji Cooper #define HAVE_SEND_RECV_MMSG
2428ac5aef8SEnji Cooper #define HAVE_SYNCFS
2438ac5aef8SEnji Cooper #define HAVE_SYNC_FILE_RANGE
2448ac5aef8SEnji Cooper #include <sys/uio.h> /* for vmsplice */
2458ac5aef8SEnji Cooper #define HAVE_TEE
2468ac5aef8SEnji Cooper #define HAVE_SPLICE
2478ac5aef8SEnji Cooper #define HAVE_VMSPLICE
2488ac5aef8SEnji Cooper #define HAVE_PSELECT
2498ac5aef8SEnji Cooper #define HAVE_PPOLL
2508ac5aef8SEnji Cooper #define HAVE_EXECVEAT
2518ac5aef8SEnji Cooper #define HAVE_SYSCALL
2528ac5aef8SEnji Cooper #define HAVE_MKNOD_REG
2538ac5aef8SEnji Cooper #define HAVE_MKNOD_SOCKET
2548ac5aef8SEnji Cooper /*
2558ac5aef8SEnji Cooper * O_BENEATH is arch-specific, via <asm/fcntl.h>; however we cannot include both that file
2568ac5aef8SEnji Cooper * and the normal <fcntl.h> as they have some clashing definitions. Bypass by directly
2578ac5aef8SEnji Cooper * defining O_BENEATH, using the current proposed x86 value. (This will therefore not
2588ac5aef8SEnji Cooper * work for non-x86, and may need changing in future if a different value gets merged.)
2598ac5aef8SEnji Cooper */
2608ac5aef8SEnji Cooper #ifndef O_BENEATH
2618ac5aef8SEnji Cooper #define O_BENEATH 040000000 /* no / or .. in openat path */
2628ac5aef8SEnji Cooper #endif
2638ac5aef8SEnji Cooper
2648ac5aef8SEnji Cooper
2658ac5aef8SEnji Cooper /* Linux allows anyone to call mlock[all]/munlock[all] */
2668ac5aef8SEnji Cooper #define MLOCK_REQUIRES_ROOT 0
2678ac5aef8SEnji Cooper /* Linux allows anyone to call sched_setscheduler */
2688ac5aef8SEnji Cooper #define SCHED_SETSCHEDULER_REQUIRES_ROOT 1
2698ac5aef8SEnji Cooper
2708ac5aef8SEnji Cooper #endif /* Linux */
2718ac5aef8SEnji Cooper
2728ac5aef8SEnji Cooper #endif /*__SYSCALLS_H__*/
273