summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Dempsky <matthew@cvs.openbsd.org>2011-09-18 23:24:15 +0000
committerMatthew Dempsky <matthew@cvs.openbsd.org>2011-09-18 23:24:15 +0000
commit01828fa1f01fd1c82399b056e2c7250d308c56df (patch)
tree3748a26e81c4f2f6851f7a751eb44d6502ab2b97
parent7fbcb0d21f1e3057dc3a3c665ca09626fbed9de4 (diff)
Add support for *at(2) system calls to systrace(1).
ok deraadt@, sthen@, jasper@
-rw-r--r--bin/systrace/intercept-translate.c78
-rw-r--r--bin/systrace/intercept.c18
-rw-r--r--bin/systrace/intercept.h12
-rw-r--r--bin/systrace/openbsd-syscalls.c11
-rw-r--r--bin/systrace/register.c77
-rw-r--r--sys/dev/systrace.c30
-rw-r--r--sys/dev/systrace.h9
7 files changed, 214 insertions, 21 deletions
diff --git a/bin/systrace/intercept-translate.c b/bin/systrace/intercept-translate.c
index b2bf3acfa66..0a0b12ec522 100644
--- a/bin/systrace/intercept-translate.c
+++ b/bin/systrace/intercept-translate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: intercept-translate.c,v 1.13 2006/06/10 07:19:13 sturm Exp $ */
+/* $OpenBSD: intercept-translate.c,v 1.14 2011/09/18 23:24:14 matthew Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -33,6 +33,7 @@
#include <sys/param.h>
#include <sys/tree.h>
#include <sys/socket.h>
+#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
@@ -75,7 +76,7 @@ int
intercept_translate(struct intercept_translate *trans,
int fd, pid_t pid, int off, void *args, int argsize)
{
- void *addr, *addr2;
+ void *addr, *addr2, *addrend;
ic_trans_free(trans);
@@ -87,6 +88,12 @@ intercept_translate(struct intercept_translate *trans,
return (-1);
trans->trans_addr2 = addr2;
}
+ if (trans->offend) {
+ if (intercept.getarg(argsize + trans->offend,
+ args, argsize, &addrend) == -1)
+ return (-1);
+ trans->trans_addrend = addrend;
+ }
trans->trans_valid = 1;
trans->trans_addr = addr;
@@ -221,6 +228,43 @@ ic_get_unlinkname(struct intercept_translate *trans, int fd, pid_t pid,
}
static int
+ic_get_filenameat(struct intercept_translate *trans, int fd, pid_t pid,
+ void *addr)
+{
+ char *name;
+ size_t len;
+ int atfd = (intptr_t)trans->trans_addr2;
+ int follow = (intptr_t)trans->user;
+ int userp;
+
+ if (trans->offend) {
+ int flag = (intptr_t)trans->trans_addrend;
+ if ((flag & ~(AT_SYMLINK_FOLLOW | AT_SYMLINK_NOFOLLOW)) != 0)
+ return (-1);
+ if ((flag & follow) != 0)
+ return (-1);
+ if (flag != 0)
+ follow = flag;
+ }
+
+ userp = (follow == AT_SYMLINK_FOLLOW) ? ICLINK_ALL : ICLINK_NOLAST;
+ name = intercept_filenameat(fd, pid, atfd, addr, userp, NULL);
+ if (name == NULL)
+ return (-1);
+
+ len = strlen(name) + 1;
+ trans->trans_data = malloc(len);
+ if (trans->trans_data == NULL)
+ return (-1);
+
+ trans->trans_size = len;
+ memcpy(trans->trans_data, name, len);
+ trans->trans_flags = ICTRANS_NOLINKS;
+
+ return (0);
+}
+
+static int
ic_get_sockaddr(struct intercept_translate *trans, int fd, pid_t pid,
void *addr)
{
@@ -359,6 +403,36 @@ struct intercept_translate ic_translate_unlinkname = {
ic_get_unlinkname, ic_print_filename,
};
+struct intercept_translate ic_translate_filenameat = {
+ "filename",
+ ic_get_filenameat, ic_print_filename,
+ .off2 = -1,
+ .user = (void *)AT_SYMLINK_FOLLOW,
+};
+
+struct intercept_translate ic_translate_unlinknameat = {
+ "filename",
+ ic_get_filenameat, ic_print_filename,
+ .off2 = -1,
+ .user = (void *)AT_SYMLINK_NOFOLLOW,
+};
+
+struct intercept_translate ic_translate_filenameatflag = {
+ "filename",
+ ic_get_filenameat, ic_print_filename,
+ .off2 = -1,
+ .offend = -1,
+ .user = (void *)AT_SYMLINK_FOLLOW,
+};
+
+struct intercept_translate ic_translate_unlinknameatflag = {
+ "filename",
+ ic_get_filenameat, ic_print_filename,
+ .off2 = -1,
+ .offend = -1,
+ .user = (void *)AT_SYMLINK_NOFOLLOW,
+};
+
struct intercept_translate ic_translate_connect = {
"sockaddr",
ic_get_sockaddr, ic_print_sockaddr,
diff --git a/bin/systrace/intercept.c b/bin/systrace/intercept.c
index dee54f3bd6d..6059df4e959 100644
--- a/bin/systrace/intercept.c
+++ b/bin/systrace/intercept.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: intercept.c,v 1.56 2010/04/20 21:56:52 tedu Exp $ */
+/* $OpenBSD: intercept.c,v 1.57 2011/09/18 23:24:14 matthew Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -589,6 +589,12 @@ intercept_get_string(int fd, pid_t pid, void *addr)
char *
intercept_filename(int fd, pid_t pid, void *addr, int userp, char *before)
{
+ return (intercept_filenameat(fd, pid, AT_FDCWD, addr, userp, before));
+}
+
+char *
+intercept_filenameat(int fd, pid_t pid, int atfd, void *addr, int userp, char *before)
+{
char *name;
if ((name = intercept_get_string(fd, pid, addr)) == NULL)
@@ -597,7 +603,7 @@ intercept_filename(int fd, pid_t pid, void *addr, int userp, char *before)
if (before != NULL)
strlcpy(before, name, MAXPATHLEN);
- if ((name = normalize_filename(fd, pid, name, userp)) == NULL)
+ if ((name = normalize_filenameat(fd, pid, atfd, name, userp)) == NULL)
goto abort;
return (name);
@@ -615,6 +621,12 @@ intercept_filename(int fd, pid_t pid, void *addr, int userp, char *before)
char *
normalize_filename(int fd, pid_t pid, char *name, int userp)
{
+ return (normalize_filenameat(fd, pid, AT_FDCWD, name, userp));
+}
+
+char *
+normalize_filenameat(int fd, pid_t pid, int atfd, char *name, int userp)
+{
static char cwd[2*MAXPATHLEN];
int havecwd = 0;
@@ -625,7 +637,7 @@ normalize_filename(int fd, pid_t pid, char *name, int userp)
if (strcmp(name, "") == 0)
return (name);
- if (fd != -1 && intercept.setcwd(fd, pid) == -1) {
+ if (fd != -1 && intercept.setcwd(fd, pid, atfd) == -1) {
if (errno == EBUSY)
return (NULL);
getcwderr:
diff --git a/bin/systrace/intercept.h b/bin/systrace/intercept.h
index d371dfb9e31..9a2f23b50ed 100644
--- a/bin/systrace/intercept.h
+++ b/bin/systrace/intercept.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intercept.h,v 1.24 2006/07/02 12:34:15 sturm Exp $ */
+/* $OpenBSD: intercept.h,v 1.25 2011/09/18 23:24:14 matthew Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -47,7 +47,7 @@ struct intercept_system {
int (*report)(int, pid_t);
int (*read)(int);
int (*getsyscallnumber)(const char *, const char *);
- int (*setcwd)(int, pid_t);
+ int (*setcwd)(int, pid_t, int);
int (*restcwd)(int);
int (*io)(int, pid_t, int, void *, u_char *, size_t);
int (*getarg)(int, void *, int, void **);
@@ -118,10 +118,12 @@ struct intercept_translate {
int (*translate)(struct intercept_translate *, int, pid_t, void *);
int (*print)(char *, size_t, struct intercept_translate *);
int off2;
+ int offend;
int off;
u_char trans_valid;
void *trans_addr;
void *trans_addr2;
+ void *trans_addrend;
void *trans_data;
size_t trans_size;
char *trans_print;
@@ -184,6 +186,10 @@ extern struct intercept_translate ic_translate_string;
extern struct intercept_translate ic_translate_filename;
extern struct intercept_translate ic_translate_linkname;
extern struct intercept_translate ic_translate_unlinkname;
+extern struct intercept_translate ic_translate_filenameat;
+extern struct intercept_translate ic_translate_unlinknameat;
+extern struct intercept_translate ic_translate_filenameatflag;
+extern struct intercept_translate ic_translate_unlinknameatflag;
extern struct intercept_translate ic_translate_connect;
extern struct intercept_translate ic_translate_sendmsg;
@@ -194,7 +200,9 @@ int intercept_existpids(void);
char *intercept_get_string(int, pid_t, void *);
char *normalize_filename(int, pid_t, char *, int);
+char *normalize_filenameat(int, pid_t, int, char *, int);
char *intercept_filename(int, pid_t, void *, int, char *);
+char *intercept_filenameat(int, pid_t, int, void *, int, char *);
void intercept_syscall(int, pid_t, u_int16_t, int, const char *, int,
const char *, void *, int);
void intercept_syscall_result(int, pid_t, u_int16_t, int, const char *, int,
diff --git a/bin/systrace/openbsd-syscalls.c b/bin/systrace/openbsd-syscalls.c
index b78ad3eebbd..a8f2fc5652b 100644
--- a/bin/systrace/openbsd-syscalls.c
+++ b/bin/systrace/openbsd-syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: openbsd-syscalls.c,v 1.40 2011/07/04 22:59:42 tedu Exp $ */
+/* $OpenBSD: openbsd-syscalls.c,v 1.41 2011/09/18 23:24:14 matthew Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -110,7 +110,7 @@ static int obsd_assignpolicy(int, pid_t, int);
static int obsd_modifypolicy(int, int, int, short);
static int obsd_replace(int, pid_t, u_int16_t, struct intercept_replace *);
static int obsd_io(int, pid_t, int, void *, u_char *, size_t);
-static int obsd_setcwd(int, pid_t);
+static int obsd_setcwd(int, pid_t, int);
static int obsd_restcwd(int);
static int obsd_argument(int, void *, int, void **);
static int obsd_read(int);
@@ -488,9 +488,12 @@ obsd_io(int fd, pid_t pid, int op, void *addr, u_char *buf, size_t size)
}
static int
-obsd_setcwd(int fd, pid_t pid)
+obsd_setcwd(int fd, pid_t pid, int atfd)
{
- return (ioctl(fd, STRIOCGETCWD, &pid));
+ struct systrace_getcwd gd;
+ gd.strgd_pid = pid;
+ gd.strgd_atfd = atfd;
+ return (ioctl(fd, STRIOCGETCWD, &gd));
}
static int
diff --git a/bin/systrace/register.c b/bin/systrace/register.c
index 83731601a7b..1d68d06c513 100644
--- a/bin/systrace/register.c
+++ b/bin/systrace/register.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: register.c,v 1.22 2006/08/14 07:24:55 ray Exp $ */
+/* $OpenBSD: register.c,v 1.23 2011/09/18 23:24:14 matthew Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -189,6 +189,81 @@ systrace_initcb(void)
X(intercept_register_sccb("native", "mprotect", trans_cb, NULL));
intercept_register_translation("native", "mprotect", 2, &ic_memprot);
+ X(intercept_register_sccb("native", "openat", trans_cb, NULL));
+ tl = intercept_register_translation("native", "openat", 1,
+ &ic_translate_filenameat);
+ intercept_register_translation("native", "openat", 2, &ic_oflags);
+ alias = systrace_new_alias("native", "openat", "native", "fswrite");
+ systrace_alias_add_trans(alias, tl);
+
+ X(intercept_register_sccb("native", "mkdirat", trans_cb, NULL));
+ tl = intercept_register_translation("native", "mkdirat", 1,
+ &ic_translate_unlinknameat);
+ alias = systrace_new_alias("native", "mkdirat", "native", "fswrite");
+ systrace_alias_add_trans(alias, tl);
+
+ X(intercept_register_sccb("native", "mkfifoat", trans_cb, NULL));
+ tl = intercept_register_translation("native", "mkfifoat", 1,
+ &ic_translate_unlinknameat);
+ intercept_register_translation("native", "mkfifoat", 2, &ic_modeflags);
+ alias = systrace_new_alias("native", "mkfifoat", "native", "fswrite");
+ systrace_alias_add_trans(alias, tl);
+
+ X(intercept_register_sccb("native", "mknodat", trans_cb, NULL));
+ intercept_register_translation("native", "mknodat", 1,
+ &ic_translate_unlinknameat);
+ intercept_register_translation("native", "mknodat", 2, &ic_modeflags);
+
+ X(intercept_register_sccb("native", "symlinkat", trans_cb, NULL));
+ intercept_register_transstring("native", "symlinkat", 0);
+ intercept_register_translation("native", "symlinkat", 2,
+ &ic_translate_unlinknameat);
+
+ X(intercept_register_sccb("native", "faccessat", trans_cb, NULL));
+ tl = intercept_register_translation("native", "faccessat", 1,
+ &ic_translate_filenameat);
+ alias = systrace_new_alias("native", "faccessat", "native", "fsread");
+ systrace_alias_add_trans(alias, tl);
+
+ X(intercept_register_sccb("native", "unlinkat", trans_cb, NULL));
+ tl = intercept_register_translation("native", "unlinkat", 1,
+ &ic_translate_unlinknameat);
+ alias = systrace_new_alias("native", "unlinkat", "native", "fswrite");
+ systrace_alias_add_trans(alias, tl);
+
+ X(intercept_register_sccb("native", "readlinkat", trans_cb, NULL));
+ tl = intercept_register_translation("native", "readlinkat", 1,
+ &ic_translate_unlinknameat);
+ alias = systrace_new_alias("native", "readlinkat", "native", "fsread");
+ systrace_alias_add_trans(alias, tl);
+
+ X(intercept_register_sccb("native", "renameat", trans_cb, NULL));
+ intercept_register_translation("native", "renameat", 1,
+ &ic_translate_unlinknameat);
+ intercept_register_translation("native", "renameat", 3,
+ &ic_translate_unlinknameat);
+
+ X(intercept_register_sccb("native", "fchownat", trans_cb, NULL));
+ intercept_register_translation("native", "fchownat", 1,
+ &ic_translate_filenameatflag);
+ intercept_register_translation("native", "fchownat", 2, &ic_uidt);
+ intercept_register_translation("native", "fchownat", 3, &ic_gidt);
+ X(intercept_register_sccb("native", "fchmodat", trans_cb, NULL));
+ intercept_register_translation("native", "fchmodat", 1,
+ &ic_translate_filenameatflag);
+ intercept_register_translation("native", "fchmodat", 2, &ic_modeflags);
+ X(intercept_register_sccb("native", "fstatat", trans_cb, NULL));
+ tl = intercept_register_translation("native", "fstatat", 1,
+ &ic_translate_filenameatflag);
+ alias = systrace_new_alias("native", "fstatat", "native", "fsread");
+ systrace_alias_add_trans(alias, tl);
+
+ X(intercept_register_sccb("native", "linkat", trans_cb, NULL));
+ intercept_register_translation("native", "linkat", 1,
+ &ic_translate_unlinknameatflag);
+ intercept_register_translation("native", "linkat", 3,
+ &ic_translate_unlinknameat);
+
X(intercept_register_sccb("linux", "open", trans_cb, NULL));
tl = intercept_register_translink("linux", "open", 0);
intercept_register_translation("linux", "open", 1, &ic_linux_oflags);
diff --git a/sys/dev/systrace.c b/sys/dev/systrace.c
index 1f47f233f40..09147c791a8 100644
--- a/sys/dev/systrace.c
+++ b/sys/dev/systrace.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: systrace.c,v 1.59 2011/07/11 15:40:47 guenther Exp $ */
+/* $OpenBSD: systrace.c,v 1.60 2011/09/18 23:24:14 matthew Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -158,7 +158,7 @@ int systrace_io(struct str_process *, struct systrace_io *);
int systrace_policy(struct fsystrace *, struct systrace_policy *);
int systrace_preprepl(struct str_process *, struct systrace_replace *);
int systrace_replace(struct str_process *, size_t, register_t []);
-int systrace_getcwd(struct fsystrace *, struct str_process *);
+int systrace_getcwd(struct fsystrace *, struct str_process *, int);
int systrace_fname(struct str_process *, caddr_t, size_t);
void systrace_replacefree(struct str_process *);
@@ -267,6 +267,7 @@ systracef_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
struct filedesc *fdp;
struct str_process *strp;
pid_t pid = 0;
+ int atfd = -1;
switch (cmd) {
case FIONBIO:
@@ -299,11 +300,14 @@ systracef_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
if (!pid)
ret = EINVAL;
break;
- case STRIOCGETCWD:
- pid = *(pid_t *)data;
+ case STRIOCGETCWD: {
+ struct systrace_getcwd *gd = (struct systrace_getcwd *)data;
+ pid = gd->strgd_pid;
if (!pid)
ret = EINVAL;
+ atfd = gd->strgd_atfd;
break;
+ }
case STRIOCATTACH:
case STRIOCRESCWD:
case STRIOCPOLICY:
@@ -386,7 +390,7 @@ systracef_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
fst->fd_cdir = fst->fd_rdir = NULL;
break;
case STRIOCGETCWD:
- ret = systrace_getcwd(fst, strp);
+ ret = systrace_getcwd(fst, strp, atfd);
break;
default:
ret = ENOTTY;
@@ -1107,9 +1111,10 @@ systrace_processready(struct str_process *strp)
}
int
-systrace_getcwd(struct fsystrace *fst, struct str_process *strp)
+systrace_getcwd(struct fsystrace *fst, struct str_process *strp, int atfd)
{
struct filedesc *myfdp, *fdp;
+ struct vnode *dvp;
int error;
DPRINTF(("%s: %d\n", __func__, strp->pid));
@@ -1123,12 +1128,23 @@ systrace_getcwd(struct fsystrace *fst, struct str_process *strp)
if (myfdp == NULL || fdp == NULL)
return (EINVAL);
+ if (atfd == AT_FDCWD)
+ dvp = fdp->fd_cdir;
+ else {
+ struct file *fp = fd_getfile(fdp, atfd);
+ if (fp == NULL || fp->f_type != DTYPE_VNODE)
+ return (EINVAL);
+ dvp = (struct vnode *)fp->f_data;
+ if (dvp->v_type != VDIR)
+ return (EINVAL);
+ }
+
/* Store our current values */
fst->fd_pid = strp->pid;
fst->fd_cdir = myfdp->fd_cdir;
fst->fd_rdir = myfdp->fd_rdir;
- if ((myfdp->fd_cdir = fdp->fd_cdir) != NULL)
+ if ((myfdp->fd_cdir = dvp) != NULL)
vref(myfdp->fd_cdir);
if ((myfdp->fd_rdir = fdp->fd_rdir) != NULL)
vref(myfdp->fd_rdir);
diff --git a/sys/dev/systrace.h b/sys/dev/systrace.h
index 9af22c05cf8..18a9b9e0429 100644
--- a/sys/dev/systrace.h
+++ b/sys/dev/systrace.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: systrace.h,v 1.22 2011/06/22 01:32:16 djm Exp $ */
+/* $OpenBSD: systrace.h,v 1.23 2011/09/18 23:24:14 matthew Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -167,6 +167,11 @@ struct systrace_inject {
pid_t stri_pid;
};
+struct systrace_getcwd {
+ pid_t strgd_pid;
+ int strgd_atfd;
+};
+
#define STRIOCCLONE _IOR('s', 100, int)
#define SYSTR_CLONE STRIOCCLONE
#define STRIOCATTACH _IOW('s', 101, pid_t)
@@ -174,7 +179,7 @@ struct systrace_inject {
#define STRIOCANSWER _IOW('s', 103, struct systrace_answer)
#define STRIOCIO _IOWR('s', 104, struct systrace_io)
#define STRIOCPOLICY _IOWR('s', 105, struct systrace_policy)
-#define STRIOCGETCWD _IOW('s', 106, pid_t)
+#define STRIOCGETCWD _IOW('s', 106, struct systrace_getcwd)
#define STRIOCRESCWD _IO('s', 107)
#define STRIOCREPORT _IOW('s', 108, pid_t)
#define STRIOCREPLACE _IOW('s', 109, struct systrace_replace)