diff options
author | Niels Provos <provos@cvs.openbsd.org> | 2002-06-04 17:20:05 +0000 |
---|---|---|
committer | Niels Provos <provos@cvs.openbsd.org> | 2002-06-04 17:20:05 +0000 |
commit | 46a8c64495ad8a9d221a6c0fa12e7d77b6e2420b (patch) | |
tree | 9c7200a8a35c2bee11d017386d12aab0d8bca720 /bin/systrace/openbsd-syscalls.c | |
parent | 72975dabb915c98862a98d34d585bdc781702b4d (diff) |
initial import of systrace. don't touch this, more stuff coming in a while
Diffstat (limited to 'bin/systrace/openbsd-syscalls.c')
-rw-r--r-- | bin/systrace/openbsd-syscalls.c | 510 |
1 files changed, 510 insertions, 0 deletions
diff --git a/bin/systrace/openbsd-syscalls.c b/bin/systrace/openbsd-syscalls.c new file mode 100644 index 00000000000..d6bab1b8596 --- /dev/null +++ b/bin/systrace/openbsd-syscalls.c @@ -0,0 +1,510 @@ +/* $OpenBSD: openbsd-syscalls.c,v 1.1 2002/06/04 17:20:04 provos Exp $ */ +/* + * Copyright 2002 Niels Provos <provos@citi.umich.edu> + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/types.h> +#include <sys/param.h> + +#include <sys/syscall.h> + +#include "/sys/compat/bsdos/bsdos_syscall.h" +#include "/sys/compat/freebsd/freebsd_syscall.h" +#include "/sys/compat/netbsd/netbsd_syscall.h" +#include "/sys/compat/hpux/hpux_syscall.h" +#include "/sys/compat/ibcs2/ibcs2_syscall.h" +#include "/sys/compat/linux/linux_syscall.h" +#include "/sys/compat/osf1/osf1_syscall.h" +#include "/sys/compat/sunos/sunos_syscall.h" +#include "/sys/compat/svr4/svr4_syscall.h" +#include "/sys/compat/ultrix/ultrix_syscall.h" + +#define KTRACE +#define NFSCLIENT +#define NFSSERVER +#define SYSVSEM +#define SYSVMSG +#define SYSVSHM +#define LFS +#define NTP +#include "/sys/kern/syscalls.c" + +#include "/sys/compat/bsdos/bsdos_syscalls.c" +#include "/sys/compat/freebsd/freebsd_syscalls.c" +#include "/sys/compat/netbsd/netbsd_syscalls.c" +#include "/sys/compat/hpux/hpux_syscalls.c" +#include "/sys/compat/ibcs2/ibcs2_syscalls.c" +#include "/sys/compat/linux/linux_syscalls.c" +#include "/sys/compat/osf1/osf1_syscalls.c" +#include "/sys/compat/sunos/sunos_syscalls.c" +#include "/sys/compat/svr4/svr4_syscalls.c" +#include "/sys/compat/ultrix/ultrix_syscalls.c" +#undef KTRACE +#undef NFSCLIENT +#undef NFSSERVER +#undef SYSVSEM +#undef SYSVMSG +#undef SYSVSHM +#undef LFS +#undef NTP + +#include <sys/ioctl.h> +#include <sys/tree.h> +#include <dev/systrace.h> + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <err.h> + +#include "intercept.h" + +/* Callback into main library */ +void intercept_child_info(pid_t, pid_t); +void intercept_syscall(int, pid_t, int, char *, int, char *, void *, int); +void intercept_syscall_result(int, pid_t, int, char *, int, char *, void *, + int, int, void *); + +struct emulation { + char *name; /* Emulation name */ + char **sysnames; /* Array of system call names */ + int nsysnames; /* Number of */ +}; + +static struct emulation emulations[] = { + { "native", syscallnames, SYS_MAXSYSCALL }, + { "hpux", hpux_syscallnames, HPUX_SYS_MAXSYSCALL }, + { "ibcs2", ibcs2_syscallnames, IBCS2_SYS_MAXSYSCALL }, + { "linux", linux_syscallnames, LINUX_SYS_MAXSYSCALL }, + { "osf1", osf1_syscallnames, OSF1_SYS_MAXSYSCALL }, + { "sunos", sunos_syscallnames, SUNOS_SYS_MAXSYSCALL }, + { "svr4", svr4_syscallnames, SVR4_SYS_MAXSYSCALL }, + { "ultrix", ultrix_syscallnames, ULTRIX_SYS_MAXSYSCALL }, + { "bsdos", bsdos_syscallnames, BSDOS_SYS_MAXSYSCALL }, + { "freebsd", freebsd_syscallnames, FREEBSD_SYS_MAXSYSCALL }, + { "netbsd", netbsd_syscallnames, NETBSD_SYS_MAXSYSCALL }, + { NULL, NULL, NULL } +}; + +struct obsd_data { + struct emulation *current; + struct emulation *commit; +}; + +int +obsd_init(void) +{ + return (0); +} + +int +obsd_attach(int fd, pid_t pid) +{ + if (ioctl(fd, STRIOCATTACH, &pid) == -1) + return (-1); + + return (0); +} + +int +obsd_detach(int fd, pid_t pid) +{ + if (ioctl(fd, STRIOCDETACH, &pid) == -1) + return (-1); + + return (0); +} + +int +obsd_open(void) +{ + char *path = "/dev/systrace"; + int fd, cfd = -1; + + fd = open(path, O_RDONLY, 0); + if (fd == -1) { + warn("open: %s", path); + return (-1); + } + + if (ioctl(fd, SYSTR_CLONE, &cfd) == -1) { + warn("ioctl(SYSTR_CLONE)"); + goto out; + } + + if (fcntl(cfd, F_SETFD, 1) == -1) + warn("fcntl(F_SETFD)"); + + out: + close (fd); + return (cfd); +} + +struct intercept_pid * +obsd_getpid(pid_t pid) +{ + struct intercept_pid *icpid; + struct obsd_data *data; + + icpid = intercept_getpid(pid); + if (icpid == NULL) + return (NULL); + if (icpid->data != NULL) + return (icpid); + + if ((icpid->data = malloc(sizeof(struct obsd_data))) == NULL) + err(1, "%s:%d: malloc", __FUNCTION__, __LINE__); + + data = icpid->data; + data->current = &emulations[0]; + data->commit = NULL; + + return (icpid); +} + +void +obsd_freepid(struct intercept_pid *ipid) +{ + if (ipid->data != NULL) + free(ipid->data); +} + +void +obsd_clonepid(struct intercept_pid *opid, struct intercept_pid *npid) +{ + if (opid->data == NULL) { + npid->data = NULL; + return; + } + + if ((npid->data = malloc(sizeof(struct obsd_data))) == NULL) + err(1, "%s:%d: malloc", __FUNCTION__, __LINE__); + memcpy(npid->data, opid->data, sizeof(struct obsd_data)); +} + +struct emulation * +obsd_find_emulation(char *name) +{ + struct emulation *tmp; + + tmp = emulations; + while (tmp->name) { + if (!strcmp(tmp->name, name)) + break; + tmp++; + } + + if (!tmp->name) + return (NULL); + + return (tmp); +} + +int +obsd_set_emulation(pid_t pidnr, char *name) +{ + struct emulation *tmp; + struct intercept_pid *pid; + struct obsd_data *data; + + if ((tmp = obsd_find_emulation(name)) == NULL) + return (-1); + + pid = intercept_getpid(pidnr); + if (pid == NULL) + return (-1); + data = pid->data; + + data->commit = tmp; + + return (0); +} + +char * +obsd_syscall_name(pid_t pidnr, int number) +{ + struct intercept_pid *pid; + struct emulation *current; + + pid = obsd_getpid(pidnr); + if (pid == NULL) + return (NULL); + current = ((struct obsd_data *)pid->data)->current; + + if (number < 0 || number >= current->nsysnames) + return (NULL); + + return (current->sysnames[number]); +} + +int +obsd_syscall_number(char *emulation, char *name) +{ + struct emulation *current; + int i; + + current = obsd_find_emulation(emulation); + if (current == NULL) + return (-1); + + for (i = 0; i < current->nsysnames; i++) + if (!strcmp(name, current->sysnames[i])) + return (i); + + return (-1); +} + +short +obsd_translate_policy(short policy) +{ + switch (policy) { + case ICPOLICY_ASK: + return (SYSTR_POLICY_ASK); + case ICPOLICY_PERMIT: + return (SYSTR_POLICY_PERMIT); + case ICPOLICY_NEVER: + default: + return (SYSTR_POLICY_NEVER); + } +} + +short +obsd_translate_flags(short flags) +{ + switch (flags) { + case ICFLAGS_RESULT: + return (SYSTR_FLAGS_RESULT); + default: + return (0); + } +} + +int +obsd_translate_errno(int errno) +{ + return (errno); +} + +int +obsd_answer(int fd, pid_t pid, short policy, int errno, short flags) +{ + struct systrace_answer ans; + + ans.stra_pid = pid; + ans.stra_policy = obsd_translate_policy(policy); + ans.stra_flags = obsd_translate_flags(flags); + ans.stra_error = obsd_translate_errno(errno); + + if (ioctl(fd, STRIOCANSWER, &ans) == -1) + return (-1); + + return (0); +} + +int +obsd_newpolicy(int fd) +{ + struct systrace_policy pol; + + pol.strp_op = SYSTR_POLICY_NEW; + pol.strp_num = -1; + pol.strp_maxents = 512; + + if (ioctl(fd, STRIOCPOLICY, &pol) == -1) + return (-1); + + return (pol.strp_num); +} + +int +obsd_assignpolicy(int fd, pid_t pid, int num) +{ + struct systrace_policy pol; + + pol.strp_op = SYSTR_POLICY_ASSIGN; + pol.strp_num = num; + pol.strp_pid = pid; + + if (ioctl(fd, STRIOCPOLICY, &pol) == -1) + return (-1); + + return (0); +} + +int +obsd_modifypolicy(int fd, int num, int code, short policy) +{ + struct systrace_policy pol; + + pol.strp_op = SYSTR_POLICY_MODIFY; + pol.strp_num = num; + pol.strp_code = code; + pol.strp_policy = obsd_translate_policy(policy); + + if (ioctl(fd, STRIOCPOLICY, &pol) == -1) + return (-1); + + return (0); +} + +int +obsd_io(int fd, pid_t pid, int op, void *addr, u_char *buf, size_t size) +{ + struct systrace_io io; + + memset(&io, 0, sizeof(io)); + io.strio_pid = pid; + io.strio_addr = buf; + io.strio_len = size; + io.strio_offs = addr; + io.strio_op = (op == INTERCEPT_READ ? SYSTR_READ : SYSTR_WRITE); + if (ioctl(fd, STRIOCIO, &io) == -1) + return (-1); + + return (0); +} + +char * +obsd_getcwd(int fd, pid_t pid, char *buf, size_t size) +{ + char *path; + + if (ioctl(fd, STRIOCGETCWD, &pid) == -1) + return (NULL); + + path = getcwd(buf, size); + + if (ioctl(fd, STRIOCRESCWD, 0) == -1) + warn("%s: ioctl", __FUNCTION__); /* XXX */ + + return (path); +} + +int +obsd_argument(int off, void *pargs, int argsize, void **pres) +{ + register_t *args = (register_t *)pargs; + + if (off >= argsize / sizeof(register_t)) + return (-1); + + *pres = (void *)args[off]; + + return (0); +} + +int +obsd_read(int fd) +{ + struct str_message msg; + struct intercept_pid *icpid; + struct obsd_data *data; + struct emulation *current; + + char name[SYSTR_EMULEN+1], *sysname; + int code; + + if (read(fd, &msg, sizeof(msg)) != sizeof(msg)) + return (-1); + + icpid = obsd_getpid(msg.msg_pid); + if (icpid == NULL) + return (-1); + data = icpid->data; + + current = data->current; + + switch(msg.msg_type) { + case SYSTR_MSG_ASK: + code = msg.msg_data.msg_ask.code; + sysname = obsd_syscall_name(msg.msg_pid, code); + + intercept_syscall(fd, msg.msg_pid, msg.msg_policy, + sysname, code, current->name, + (void *)msg.msg_data.msg_ask.args, + msg.msg_data.msg_ask.argsize); + break; + + case SYSTR_MSG_RES: + code = msg.msg_data.msg_ask.code; + sysname = obsd_syscall_name(msg.msg_pid, code); + + /* Switch emulation around at the right time */ + if (data->commit != NULL) { + current = data->current = data->commit; + data->commit = NULL; + } + + intercept_syscall_result(fd, msg.msg_pid, msg.msg_policy, + sysname, code, current->name, + (void *)msg.msg_data.msg_ask.args, + msg.msg_data.msg_ask.argsize, + msg.msg_data.msg_ask.result, + msg.msg_data.msg_ask.rval); + break; + + case SYSTR_MSG_EMUL: + memcpy(name, msg.msg_data.msg_emul.emul, SYSTR_EMULEN); + name[SYSTR_EMULEN] = '\0'; + + if (obsd_set_emulation(msg.msg_pid, name) == -1) + errx(1, "%s:%d: set_emulation(%s)", + __FUNCTION__, __LINE__, name); + + if (obsd_answer(fd, msg.msg_pid, 0, 0, 0) == -1) + err(1, "%s:%d: answer", __FUNCTION__, __LINE__); + break; + + case SYSTR_MSG_CHILD: + intercept_child_info(msg.msg_pid, + msg.msg_data.msg_child.new_pid); + break; + } + return (0); +} + +struct intercept_system intercept = { + "openbsd", + obsd_init, + obsd_open, + obsd_attach, + obsd_detach, + obsd_read, + obsd_syscall_number, + obsd_getcwd, + obsd_io, + obsd_argument, + obsd_answer, + obsd_newpolicy, + obsd_assignpolicy, + obsd_modifypolicy, + obsd_clonepid, + obsd_freepid, +}; |