aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Seebach <seebs@eee12.(none)>2010-03-26 15:06:43 -0500
committerPeter Seebach <seebs@eee12.(none)>2010-03-26 15:06:43 -0500
commit8231f7c636183ec0beda5beae8a342bb89b3c774 (patch)
treeb93659df7a0fd5cb51f256cbfe1376109c5a0959
parent80259da816b82c5bdfbf9515935823a157f5d0e9 (diff)
downloadpseudo-8231f7c636183ec0beda5beae8a342bb89b3c774.tar.gz
pseudo-8231f7c636183ec0beda5beae8a342bb89b3c774.tar.bz2
pseudo-8231f7c636183ec0beda5beae8a342bb89b3c774.zip
Add support for intercepting execve()
This allows us to track execution, although the tracking for it requires some additional thought -- the basic assumption is that we don't want to canonicalize names into the chroot() directory, but since all the filename canonicalization assumes that we want this, that will take some sneaking. It's a little useful as is, though, so I'm running with it.
-rw-r--r--guts/README1
-rw-r--r--guts/execve.c17
-rw-r--r--pseudo.c1
-rw-r--r--pseudo.h4
-rw-r--r--pseudo_client.c3
-rw-r--r--pseudo_db.c1
-rw-r--r--pseudo_table.c1
-rw-r--r--pseudo_util.c4
-rw-r--r--pseudolog.15
-rw-r--r--pseudolog.c5
-rw-r--r--wrapfuncs.in1
11 files changed, 40 insertions, 3 deletions
diff --git a/guts/README b/guts/README
index 277f712..e933349 100644
--- a/guts/README
+++ b/guts/README
@@ -83,6 +83,7 @@ wrappers:
close
dup
dup2
+ execve (note that all other exec* functions redirect here)
fclose
fopen
fopen64
diff --git a/guts/execve.c b/guts/execve.c
new file mode 100644
index 0000000..e202575
--- /dev/null
+++ b/guts/execve.c
@@ -0,0 +1,17 @@
+/*
+ * static int
+ * wrap_execve(const char *filename, char *const *argv, char *const *envp) {
+ * int rc = -1;
+ */
+ /* note: we don't canonicalize this, because we are intentionally
+ * NOT redirecting execs into the chroot environment. If you try
+ * to execute /bin/sh, you get the actual /bin/sh, not
+ * <CHROOT>/bin/sh. This allows use of basic utilities. This
+ * design will likely be revisited.
+ */
+ pseudo_client_op(OP_EXEC, PSA_EXEC, 0, 0, filename, 0);
+ rc = real_execve(filename, argv, envp);
+
+/* return rc;
+ * }
+ */
diff --git a/pseudo.c b/pseudo.c
index e6e6a39..583adb1 100644
--- a/pseudo.c
+++ b/pseudo.c
@@ -481,6 +481,7 @@ pseudo_op(pseudo_msg_t *msg, const char *tag) {
* as of this writing, but might be logged by accident: */
pseudo_diag("error: op %s sent to server.\n", pseudo_op_name(msg->op));
break;
+ case OP_EXEC:
case OP_OPEN:
/* nothing to do -- just sent in case we're logging */
break;
diff --git a/pseudo.h b/pseudo.h
index aec6f60..93f3e89 100644
--- a/pseudo.h
+++ b/pseudo.h
@@ -40,7 +40,11 @@ typedef enum {
OP_RENAME,
OP_STAT,
OP_UNLINK,
+ /* added after the original release, so they have to go out of order
+ * to avoid breaking the operation numbers in old logs.
+ */
OP_SYMLINK,
+ OP_EXEC,
OP_MAX
} op_id_t;
extern char *pseudo_op_name(op_id_t id);
diff --git a/pseudo_client.c b/pseudo_client.c
index 3066570..e144456 100644
--- a/pseudo_client.c
+++ b/pseudo_client.c
@@ -835,10 +835,11 @@ pseudo_client_op(op_id_t op, int access, int fd, int dirfd, const char *path, co
* (operations which can create should be CREAT or MKNOD
* or MKDIR)
*/
- case OP_LINK:
+ case OP_EXEC:
case OP_CHOWN:
case OP_FCHOWN:
case OP_FSTAT:
+ case OP_LINK:
case OP_RENAME:
case OP_STAT:
case OP_UNLINK:
diff --git a/pseudo_db.c b/pseudo_db.c
index 84a9103..04eb412 100644
--- a/pseudo_db.c
+++ b/pseudo_db.c
@@ -63,6 +63,7 @@ id_row op_rows[] = {
OP_ROW(OP_CLOSE, "close"),
OP_ROW(OP_CREAT, "creat"),
OP_ROW(OP_DUP, "dup"),
+ OP_ROW(OP_EXEC, "exec"),
OP_ROW(OP_FCHMOD, "fchmod"),
OP_ROW(OP_FCHOWN, "fchown"),
OP_ROW(OP_FSTAT, "fstat"),
diff --git a/pseudo_table.c b/pseudo_table.c
index 171ba7b..7225422 100644
--- a/pseudo_table.c
+++ b/pseudo_table.c
@@ -43,6 +43,7 @@ static char *operation_names[] = {
"stat",
"unlink",
"symlink",
+ "exec",
NULL
};
diff --git a/pseudo_util.c b/pseudo_util.c
index 55e0488..bb60edb 100644
--- a/pseudo_util.c
+++ b/pseudo_util.c
@@ -604,6 +604,10 @@ pseudo_access_fopen(const char *mode) {
if (mode[1] == '+' || (mode[1] == 'b' && mode[2] == '+'))
access |= PSA_READ;
break;
+ /* special case */
+ case 'x':
+ access |= PSA_EXEC;
+ break;
default:
access = -1;
break;
diff --git a/pseudolog.1 b/pseudolog.1
index 8aaf9c8..b7c9bbb 100644
--- a/pseudolog.1
+++ b/pseudolog.1
@@ -185,7 +185,10 @@ such as "r+" to indicate read/write access. Note that specifying
.B \&a
as an access mode will include non-append writes, as the "a" mode
implies write and append both. This feature is slightly experimental
-and may not correctly identify the access type of every access.
+and may not correctly identify the access type of every access. The
+string
+.B x
+may be specified to indicate execute access.
.TP 8
.B c
Client ID (the PID of a client).
diff --git a/pseudolog.c b/pseudolog.c
index 4d189b6..877a643 100644
--- a/pseudolog.c
+++ b/pseudolog.c
@@ -382,7 +382,7 @@ plog_trait(int opt, char *string) {
case PSQF_ACCESS:
new_trait->data.ivalue = pseudo_access_fopen(string);
if (new_trait->data.ivalue == (unsigned long long) -1) {
- pseudo_diag("access flags should be specified like fopen(3) mode strings.\n");
+ pseudo_diag("access flags should be specified like fopen(3) mode strings (or x for exec).\n");
free(new_trait);
return 0;
}
@@ -646,6 +646,7 @@ format_one(log_entry *e, char *format) {
switch (*s) {
case 'a': /* PSQF_ACCESS */
+ *scratch = '\0';
if (e->access == -1) {
strcpy(scratch, "invalid");
} else if (e->access != 0) {
@@ -661,6 +662,8 @@ format_one(log_entry *e, char *format) {
}
if (e->access & PSA_READ)
strcat(scratch, "+");
+ } else if (e->access & PSA_EXEC) {
+ strcpy(scratch, "x");
}
/* this should be impossible... should. */
if (e->access & PSA_APPEND && !(e->access & PSA_WRITE)) {
diff --git a/wrapfuncs.in b/wrapfuncs.in
index 2eabd5d..22510dc 100644
--- a/wrapfuncs.in
+++ b/wrapfuncs.in
@@ -88,3 +88,4 @@ char *tmpnam(char *s);
int truncate(const char *path, off_t length);
int utime(const char *path, const struct utimbuf *buf);
int utimes(const char *path, const struct timeval *times);
+int execve(const char *filename, char *const *argv, char *const *envp);