xref: /freebsd/tests/sys/capsicum/syscalls.h (revision 670b568ec1c36464c6d55e400382c290b0391ccf)
1*670b568eSEd Maste /*
2*670b568eSEd Maste  * Minimal portability layer for system call differences between
3*670b568eSEd Maste  * Capsicum OSes.
4*670b568eSEd Maste  */
5*670b568eSEd Maste #ifndef __SYSCALLS_H__
6*670b568eSEd Maste #define __SYSCALLS_H__
7*670b568eSEd Maste 
8*670b568eSEd Maste /************************************************************
9*670b568eSEd Maste  * FreeBSD
10*670b568eSEd Maste  ************************************************************/
11*670b568eSEd Maste #ifdef __FreeBSD__
12*670b568eSEd Maste 
13*670b568eSEd Maste /* Map umount2 (Linux) syscall to unmount (FreeBSD) syscall */
14*670b568eSEd Maste #define umount2(T, F) unmount(T, F)
15*670b568eSEd Maste 
16*670b568eSEd Maste /* Map sighandler_y (Linux) to sig_t (FreeBSD) */
17*670b568eSEd Maste #define sighandler_t sig_t
18*670b568eSEd Maste 
19*670b568eSEd Maste /* profil(2) has a first argument of char* */
20*670b568eSEd Maste #define profil_arg1_t char
21*670b568eSEd Maste 
22*670b568eSEd Maste /* FreeBSD has getdents(2) available */
23*670b568eSEd Maste #include <sys/types.h>
24*670b568eSEd Maste #include <dirent.h>
getdents_(unsigned int fd,void * dirp,unsigned int count)25*670b568eSEd Maste inline int getdents_(unsigned int fd, void *dirp, unsigned int count) {
26*670b568eSEd Maste   return getdents(fd, (char*)dirp, count);
27*670b568eSEd Maste }
28*670b568eSEd Maste #include <sys/mman.h>
mincore_(void * addr,size_t length,unsigned char * vec)29*670b568eSEd Maste inline int mincore_(void *addr, size_t length, unsigned char *vec) {
30*670b568eSEd Maste   return mincore(addr, length, (char*)vec);
31*670b568eSEd Maste }
32*670b568eSEd Maste #define getpid_ getpid
33*670b568eSEd Maste 
34*670b568eSEd Maste /* Map Linux-style sendfile to FreeBSD sendfile */
35*670b568eSEd Maste #include <sys/socket.h>
36*670b568eSEd Maste #include <sys/uio.h>
sendfile_(int out_fd,int in_fd,off_t * offset,size_t count)37*670b568eSEd Maste inline ssize_t sendfile_(int out_fd, int in_fd, off_t *offset, size_t count) {
38*670b568eSEd Maste   return sendfile(in_fd, out_fd, *offset, count, NULL, offset, 0);
39*670b568eSEd Maste }
40*670b568eSEd Maste 
41*670b568eSEd Maste /* A sample mount(2) call */
42*670b568eSEd Maste #include <sys/param.h>
43*670b568eSEd Maste #include <sys/mount.h>
bogus_mount_()44*670b568eSEd Maste inline int bogus_mount_() {
45*670b568eSEd Maste   return mount("procfs", "/not_mounted", 0, NULL);
46*670b568eSEd Maste }
47*670b568eSEd Maste 
48*670b568eSEd Maste /* Mappings for extended attribute functions */
49*670b568eSEd Maste #include <sys/extattr.h>
50*670b568eSEd Maste #include <errno.h>
fbsd_extattr_skip_prefix(const char * p)51*670b568eSEd Maste static const char *fbsd_extattr_skip_prefix(const char *p) {
52*670b568eSEd Maste   if (*p++ == 'u' && *p++ == 's' && *p++ == 'e' && *p++ == 'r' && *p++ == '.')
53*670b568eSEd Maste     return p;
54*670b568eSEd Maste   errno = EINVAL;
55*670b568eSEd Maste   return NULL;
56*670b568eSEd Maste }
flistxattr_(int fd,char * list,size_t size)57*670b568eSEd Maste inline ssize_t flistxattr_(int fd, char *list, size_t size) {
58*670b568eSEd Maste   return extattr_list_fd(fd, EXTATTR_NAMESPACE_USER, list, size);
59*670b568eSEd Maste }
fgetxattr_(int fd,const char * name,void * value,size_t size)60*670b568eSEd Maste inline ssize_t fgetxattr_(int fd, const char *name, void *value, size_t size) {
61*670b568eSEd Maste   if (!(name = fbsd_extattr_skip_prefix(name)))
62*670b568eSEd Maste     return -1;
63*670b568eSEd Maste   return extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, name, value, size);
64*670b568eSEd Maste }
fsetxattr_(int fd,const char * name,const void * value,size_t size,int)65*670b568eSEd Maste inline int fsetxattr_(int fd, const char *name, const void *value, size_t size, int) {
66*670b568eSEd Maste   if (!(name = fbsd_extattr_skip_prefix(name)))
67*670b568eSEd Maste     return -1;
68*670b568eSEd Maste   return extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, name, value, size);
69*670b568eSEd Maste }
fremovexattr_(int fd,const char * name)70*670b568eSEd Maste inline int fremovexattr_(int fd, const char *name) {
71*670b568eSEd Maste   if (!(name = fbsd_extattr_skip_prefix(name)))
72*670b568eSEd Maste     return -1;
73*670b568eSEd Maste   return extattr_delete_fd(fd, EXTATTR_NAMESPACE_USER, name);
74*670b568eSEd Maste }
75*670b568eSEd Maste 
76*670b568eSEd Maste /* mq_* functions are wrappers in FreeBSD so go through to underlying syscalls */
77*670b568eSEd Maste #include <sys/syscall.h>
78*670b568eSEd Maste extern "C" {
79*670b568eSEd Maste extern int __sys_kmq_notify(int, const struct sigevent *);
80*670b568eSEd Maste extern int __sys_kmq_open(const char *, int, mode_t, const struct mq_attr *);
81*670b568eSEd Maste extern int __sys_kmq_setattr(int, const struct mq_attr *__restrict, struct mq_attr *__restrict);
82*670b568eSEd Maste extern ssize_t __sys_kmq_timedreceive(int, char *__restrict, size_t,
83*670b568eSEd Maste                                       unsigned *__restrict, const struct timespec *__restrict);
84*670b568eSEd Maste extern int __sys_kmq_timedsend(int, const char *, size_t, unsigned,
85*670b568eSEd Maste                                const struct timespec *);
86*670b568eSEd Maste extern int  __sys_kmq_unlink(const char *);
87*670b568eSEd Maste }
88*670b568eSEd Maste #define mq_notify_ __sys_kmq_notify
89*670b568eSEd Maste #define mq_open_ __sys_kmq_open
90*670b568eSEd Maste #define mq_setattr_ __sys_kmq_setattr
91*670b568eSEd Maste #define mq_getattr_(A, B) __sys_kmq_setattr(A, NULL, B)
92*670b568eSEd Maste #define mq_timedreceive_ __sys_kmq_timedreceive
93*670b568eSEd Maste #define mq_timedsend_ __sys_kmq_timedsend
94*670b568eSEd Maste #define mq_unlink_ __sys_kmq_unlink
95*670b568eSEd Maste #define mq_close_ close
96*670b568eSEd Maste #include <sys/ptrace.h>
ptrace_(int request,pid_t pid,void * addr,void * data)97*670b568eSEd Maste inline long ptrace_(int request, pid_t pid, void *addr, void *data) {
98*670b568eSEd Maste   return ptrace(request, pid, (caddr_t)addr, static_cast<int>((long)data));
99*670b568eSEd Maste }
100*670b568eSEd Maste #define PTRACE_PEEKDATA_ PT_READ_D
101*670b568eSEd Maste #define getegid_ getegid
102*670b568eSEd Maste #define getgid_ getgid
103*670b568eSEd Maste #define geteuid_ geteuid
104*670b568eSEd Maste #define getuid_ getuid
105*670b568eSEd Maste #define getgroups_ getgroups
106*670b568eSEd Maste #define getrlimit_ getrlimit
107*670b568eSEd Maste #define bind_ bind
108*670b568eSEd Maste #define connect_ connect
109*670b568eSEd Maste 
110*670b568eSEd Maste /* Features available */
111*670b568eSEd Maste #if __FreeBSD_version >= 1000000
112*670b568eSEd Maste #define HAVE_CHFLAGSAT
113*670b568eSEd Maste #define HAVE_BINDAT
114*670b568eSEd Maste #define HAVE_CONNECTAT
115*670b568eSEd Maste #endif
116*670b568eSEd Maste #define HAVE_CHFLAGS
117*670b568eSEd Maste #define HAVE_GETFSSTAT
118*670b568eSEd Maste #define HAVE_REVOKE
119*670b568eSEd Maste #define HAVE_GETLOGIN
120*670b568eSEd Maste #define HAVE_MKFIFOAT
121*670b568eSEd Maste #define HAVE_SYSARCH
122*670b568eSEd Maste #include <machine/sysarch.h>
123*670b568eSEd Maste #define HAVE_STAT_BIRTHTIME
124*670b568eSEd Maste #define HAVE_SYSCTL
125*670b568eSEd Maste #define HAVE_FPATHCONF
126*670b568eSEd Maste #define HAVE_F_DUP2FD
127*670b568eSEd Maste #define HAVE_PSELECT
128*670b568eSEd Maste #define HAVE_SCTP
129*670b568eSEd Maste 
130*670b568eSEd Maste /* FreeBSD only allows root to call mlock[all]/munlock[all] */
131*670b568eSEd Maste #define MLOCK_REQUIRES_ROOT 1
132*670b568eSEd Maste /* FreeBSD effectively only allows root to call sched_setscheduler */
133*670b568eSEd Maste #define SCHED_SETSCHEDULER_REQUIRES_ROOT 1
134*670b568eSEd Maste 
135*670b568eSEd Maste #endif  /* FreeBSD */
136*670b568eSEd Maste 
137*670b568eSEd Maste /************************************************************
138*670b568eSEd Maste  * Linux
139*670b568eSEd Maste  ************************************************************/
140*670b568eSEd Maste #ifdef __linux__
141*670b568eSEd Maste #include <fcntl.h>
142*670b568eSEd Maste #include <unistd.h>
143*670b568eSEd Maste #include <sys/prctl.h>
144*670b568eSEd Maste #include <sys/syscall.h>
145*670b568eSEd Maste #include <sys/types.h>
146*670b568eSEd Maste #include <sys/time.h>
147*670b568eSEd Maste #include <sys/resource.h>
148*670b568eSEd Maste #include <sys/wait.h>
149*670b568eSEd Maste #include <sys/sendfile.h>
150*670b568eSEd Maste #include <sys/statfs.h>
151*670b568eSEd Maste #include <sys/xattr.h>
152*670b568eSEd Maste #include <sys/mount.h>
153*670b568eSEd Maste #include <linux/net.h>
154*670b568eSEd Maste 
155*670b568eSEd Maste /* profil(2) has a first argument of unsigned short* */
156*670b568eSEd Maste #define profil_arg1_t unsigned short
157*670b568eSEd Maste 
getdents_(unsigned int fd,void * dirp,unsigned int count)158*670b568eSEd Maste static inline int getdents_(unsigned int fd, void *dirp, unsigned int count) {
159*670b568eSEd Maste   return syscall(__NR_getdents, fd, dirp, count);
160*670b568eSEd Maste }
161*670b568eSEd Maste /* A sample mount(2) call */
bogus_mount_()162*670b568eSEd Maste static inline int bogus_mount_() {
163*670b568eSEd Maste   return mount("/dev/bogus", "/bogus", "debugfs", MS_RDONLY, "");
164*670b568eSEd Maste }
165*670b568eSEd Maste 
166*670b568eSEd Maste /* libc's getpid() wrapper caches the pid value, and doesn't invalidate
167*670b568eSEd Maste  * the cached value on pdfork(), so directly syscall. */
getpid_()168*670b568eSEd Maste static inline pid_t getpid_() {
169*670b568eSEd Maste   return syscall(__NR_getpid);
170*670b568eSEd Maste }
execveat(int fd,const char * path,char * const argv[],char * const envp[],int flags)171*670b568eSEd Maste static inline int execveat(int fd, const char *path,
172*670b568eSEd Maste                            char *const argv[], char *const envp[], int flags) {
173*670b568eSEd Maste   return syscall(__NR_execveat, fd, path, argv, envp, flags);
174*670b568eSEd Maste }
175*670b568eSEd Maste 
176*670b568eSEd Maste /*
177*670b568eSEd Maste  * Linux glibc includes an fexecve() function, implemented via the /proc
178*670b568eSEd Maste  * filesystem.  Bypass this and go directly to the execveat(2) syscall.
179*670b568eSEd Maste  */
fexecve_(int fd,char * const argv[],char * const envp[])180*670b568eSEd Maste static inline int fexecve_(int fd, char *const argv[], char *const envp[]) {
181*670b568eSEd Maste   return execveat(fd, "", argv, envp, AT_EMPTY_PATH);
182*670b568eSEd Maste }
183*670b568eSEd Maste /*
184*670b568eSEd Maste  * Linux glibc attempts to be clever and intercepts various uid/gid functions.
185*670b568eSEd Maste  * Bypass by calling the syscalls directly.
186*670b568eSEd Maste  */
getegid_(void)187*670b568eSEd Maste static inline gid_t getegid_(void) { return syscall(__NR_getegid); }
getgid_(void)188*670b568eSEd Maste static inline gid_t getgid_(void) { return syscall(__NR_getgid); }
geteuid_(void)189*670b568eSEd Maste static inline uid_t geteuid_(void) { return syscall(__NR_geteuid); }
getuid_(void)190*670b568eSEd Maste static inline uid_t getuid_(void) { return syscall(__NR_getuid); }
getgroups_(int size,gid_t list[])191*670b568eSEd Maste static inline int getgroups_(int size, gid_t list[]) { return syscall(__NR_getgroups, size, list); }
getrlimit_(int resource,struct rlimit * rlim)192*670b568eSEd Maste static inline int getrlimit_(int resource, struct rlimit *rlim) {
193*670b568eSEd Maste   return syscall(__NR_getrlimit, resource, rlim);
194*670b568eSEd Maste }
195*670b568eSEd Maste 
196*670b568eSEd Maste /*
197*670b568eSEd Maste  * Linux glibc for i386 consumes the errno returned from the raw socketcall(2) operation,
198*670b568eSEd Maste  * so use the raw syscall for those operations that are disallowed in capability mode.
199*670b568eSEd Maste  */
200*670b568eSEd Maste #ifdef __NR_bind
201*670b568eSEd Maste #define bind_ bind
202*670b568eSEd Maste #else
bind_(int sockfd,const struct sockaddr * addr,socklen_t addrlen)203*670b568eSEd Maste static inline int bind_(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
204*670b568eSEd Maste   unsigned long args[3] = {(unsigned long)sockfd, (unsigned long)(intptr_t)addr, (unsigned long)addrlen};
205*670b568eSEd Maste   return syscall(__NR_socketcall, SYS_BIND, args);
206*670b568eSEd Maste }
207*670b568eSEd Maste #endif
208*670b568eSEd Maste #ifdef __NR_connect
209*670b568eSEd Maste #define connect_ connect
210*670b568eSEd Maste #else
connect_(int sockfd,const struct sockaddr * addr,socklen_t addrlen)211*670b568eSEd Maste static inline int connect_(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
212*670b568eSEd Maste   unsigned long args[3] = {(unsigned long)sockfd, (unsigned long)(intptr_t)addr, (unsigned long)addrlen};
213*670b568eSEd Maste   return syscall(__NR_socketcall, SYS_CONNECT, args);
214*670b568eSEd Maste }
215*670b568eSEd Maste #endif
216*670b568eSEd Maste 
217*670b568eSEd Maste #define mincore_ mincore
218*670b568eSEd Maste #define sendfile_ sendfile
219*670b568eSEd Maste #define flistxattr_ flistxattr
220*670b568eSEd Maste #define fgetxattr_ fgetxattr
221*670b568eSEd Maste #define fsetxattr_ fsetxattr
222*670b568eSEd Maste #define fremovexattr_ fremovexattr
223*670b568eSEd Maste #define mq_notify_ mq_notify
224*670b568eSEd Maste #define mq_open_ mq_open
225*670b568eSEd Maste #define mq_setattr_ mq_setattr
226*670b568eSEd Maste #define mq_getattr_ mq_getattr
227*670b568eSEd Maste #define mq_timedreceive_ mq_timedreceive
228*670b568eSEd Maste #define mq_timedsend_ mq_timedsend
229*670b568eSEd Maste #define mq_unlink_ mq_unlink
230*670b568eSEd Maste #define mq_close_ mq_close
231*670b568eSEd Maste #define ptrace_ ptrace
232*670b568eSEd Maste #define PTRACE_PEEKDATA_ PTRACE_PEEKDATA
233*670b568eSEd Maste 
234*670b568eSEd Maste /* Features available */
235*670b568eSEd Maste #define HAVE_DUP3
236*670b568eSEd Maste #define HAVE_PIPE2
237*670b568eSEd Maste #include <sys/fsuid.h>  /* for setfsgid()/setfsuid() */
238*670b568eSEd Maste #define HAVE_SETFSUID
239*670b568eSEd Maste #define HAVE_SETFSGID
240*670b568eSEd Maste #define HAVE_READAHEAD
241*670b568eSEd Maste #define HAVE_SEND_RECV_MMSG
242*670b568eSEd Maste #define HAVE_SYNCFS
243*670b568eSEd Maste #define HAVE_SYNC_FILE_RANGE
244*670b568eSEd Maste #include <sys/uio.h>  /* for vmsplice */
245*670b568eSEd Maste #define HAVE_TEE
246*670b568eSEd Maste #define HAVE_SPLICE
247*670b568eSEd Maste #define HAVE_VMSPLICE
248*670b568eSEd Maste #define HAVE_PSELECT
249*670b568eSEd Maste #define HAVE_PPOLL
250*670b568eSEd Maste #define HAVE_EXECVEAT
251*670b568eSEd Maste #define HAVE_SYSCALL
252*670b568eSEd Maste #define HAVE_MKNOD_REG
253*670b568eSEd Maste #define HAVE_MKNOD_SOCKET
254*670b568eSEd Maste /*
255*670b568eSEd Maste  * O_BENEATH is arch-specific, via <asm/fcntl.h>; however we cannot include both that file
256*670b568eSEd Maste  * and the normal <fcntl.h> as they have some clashing definitions.  Bypass by directly
257*670b568eSEd Maste  * defining O_BENEATH, using the current proposed x86 value.  (This will therefore not
258*670b568eSEd Maste  * work for non-x86, and may need changing in future if a different value gets merged.)
259*670b568eSEd Maste  */
260*670b568eSEd Maste #ifndef O_BENEATH
261*670b568eSEd Maste #define O_BENEATH	040000000	/* no / or .. in openat path */
262*670b568eSEd Maste #endif
263*670b568eSEd Maste 
264*670b568eSEd Maste 
265*670b568eSEd Maste /* Linux allows anyone to call mlock[all]/munlock[all] */
266*670b568eSEd Maste #define MLOCK_REQUIRES_ROOT 0
267*670b568eSEd Maste /* Linux allows anyone to call sched_setscheduler */
268*670b568eSEd Maste #define SCHED_SETSCHEDULER_REQUIRES_ROOT 1
269*670b568eSEd Maste 
270*670b568eSEd Maste #endif  /* Linux */
271*670b568eSEd Maste 
272*670b568eSEd Maste #endif /*__SYSCALLS_H__*/
273