summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwsalamon <wsalamon@FreeBSD.org>2006-09-01 11:45:40 +0000
committerwsalamon <wsalamon@FreeBSD.org>2006-09-01 11:45:40 +0000
commitc62317c442340f5e4627b6020679dc03d49a3918 (patch)
tree17f9a899743e9577c2e64080d7c7f0a957fbe0f4
parente279989d710de9f19f0e36445d579caea48bf429 (diff)
downloadFreeBSD-src-c62317c442340f5e4627b6020679dc03d49a3918.zip
FreeBSD-src-c62317c442340f5e4627b6020679dc03d49a3918.tar.gz
Audit the argv and env vectors passed in on exec:
Add the argument auditing functions for argv and env. Add kernel-specific versions of the tokenizer functions for the arg and env represented as a char array. Implement the AUDIT_ARGV and AUDIT_ARGE audit policy commands to enable/disable argv/env auditing. Call the argument auditing from the exec system calls. Obtained from: TrustedBSD Project Approved by: rwatson (mentor)
-rw-r--r--sys/bsm/audit_record.h9
-rw-r--r--sys/kern/kern_exec.c9
-rw-r--r--sys/security/audit/audit.c8
-rw-r--r--sys/security/audit/audit.h5
-rw-r--r--sys/security/audit/audit_arg.c42
-rw-r--r--sys/security/audit/audit_bsm.c15
-rw-r--r--sys/security/audit/audit_bsm_token.c64
-rw-r--r--sys/security/audit/audit_private.h6
-rw-r--r--sys/security/audit/audit_syscalls.c9
9 files changed, 155 insertions, 12 deletions
diff --git a/sys/bsm/audit_record.h b/sys/bsm/audit_record.h
index 18235e2..b1c975b 100644
--- a/sys/bsm/audit_record.h
+++ b/sys/bsm/audit_record.h
@@ -319,8 +319,13 @@ token_t *au_to_subject32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid);
token_t *au_to_subject64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid);
-token_t *au_to_exec_args(const char **);
-token_t *au_to_exec_env(const char **);
+#if defined(_KERNEL) || defined(KERNEL)
+token_t *au_to_exec_args(char *args, int argc);
+token_t *au_to_exec_env(char *envs, int envc);
+#else
+token_t *au_to_exec_args(char **argv);
+token_t *au_to_exec_env(char **envp);
+#endif
token_t *au_to_text(char *text);
token_t *au_to_kevent(struct kevent *kev);
token_t *au_to_trailer(int rec_size);
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index d8f196b..9bd3104 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -79,6 +79,8 @@ __FBSDID("$FreeBSD$");
#include <machine/reg.h>
+#include <security/audit/audit.h>
+
MALLOC_DEFINE(M_PARGS, "proc-args", "Process arguments");
static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS);
@@ -239,6 +241,10 @@ kern_execve(td, args, mac_p)
struct proc *p = td->td_proc;
int error;
+ AUDIT_ARG(argv, args->begin_argv, args->argc,
+ args->begin_envv - args->begin_argv);
+ AUDIT_ARG(envv, args->begin_envv, args->envc,
+ args->endp - args->begin_envv);
if (p->p_flag & P_HADTHREADS) {
PROC_LOCK(p);
if (thread_single(SINGLE_BOUNDARY)) {
@@ -351,6 +357,9 @@ do_execve(td, args, mac_p)
/*
* Translate the file name. namei() returns a vnode pointer
* in ni_vp amoung other things.
+ *
+ * XXXAUDIT: It would be desirable to also audit the name of the
+ * interpreter if this is an interpreted binary.
*/
ndp = &nd;
NDINIT(ndp, LOOKUP, ISOPEN | LOCKLEAF | FOLLOW | SAVENAME | MPSAFE |
diff --git a/sys/security/audit/audit.c b/sys/security/audit/audit.c
index 07cf3278..be0d481 100644
--- a/sys/security/audit/audit.c
+++ b/sys/security/audit/audit.c
@@ -92,6 +92,8 @@ int audit_suspended;
*/
int audit_panic_on_write_fail;
int audit_fail_stop;
+int audit_argv;
+int audit_arge;
/*
* Are we currently "failing stop" due to out of disk space?
@@ -204,6 +206,10 @@ audit_record_dtor(void *mem, int size, void *arg)
free(ar->k_ar.ar_arg_text, M_AUDITTEXT);
if (ar->k_udata != NULL)
free(ar->k_udata, M_AUDITDATA);
+ if (ar->k_ar.ar_arg_argv != NULL)
+ free(ar->k_ar.ar_arg_argv, M_AUDITTEXT);
+ if (ar->k_ar.ar_arg_envv != NULL)
+ free(ar->k_ar.ar_arg_envv, M_AUDITTEXT);
}
/*
@@ -221,6 +227,8 @@ audit_init(void)
audit_panic_on_write_fail = 0;
audit_fail_stop = 0;
audit_in_failure = 0;
+ audit_argv = 0;
+ audit_arge = 0;
audit_fstat.af_filesz = 0; /* '0' means unset, unbounded */
audit_fstat.af_currsz = 0;
diff --git a/sys/security/audit/audit.h b/sys/security/audit/audit.h
index 6043236..574f6af 100644
--- a/sys/security/audit/audit.h
+++ b/sys/security/audit/audit.h
@@ -111,6 +111,9 @@ extern int audit_suspended;
#define ARG_MACHPORT1 0x0000100000000000ULL
#define ARG_MACHPORT2 0x0000200000000000ULL
#define ARG_EXIT 0x0000400000000000ULL
+#define ARG_IOVECSTR 0x0000800000000000ULL
+#define ARG_ARGV 0x0001000000000000ULL
+#define ARG_ENVV 0x0002000000000000ULL
#define ARG_NONE 0x0000000000000000ULL
#define ARG_ALL 0xFFFFFFFFFFFFFFFFULL
@@ -165,6 +168,8 @@ void audit_arg_svipc_addr(void *addr);
void audit_arg_posix_ipc_perm(uid_t uid, gid_t gid, mode_t mode);
void audit_arg_auditon(union auditon_udata *udata);
void audit_arg_file(struct proc *p, struct file *fp);
+void audit_arg_argv(char *argv, int argc, int length);
+void audit_arg_envv(char *envv, int envc, int length);
void audit_sysclose(struct thread *td, int fd);
void audit_proc_alloc(struct proc *p);
void audit_proc_kproc0(struct proc *p);
diff --git a/sys/security/audit/audit_arg.c b/sys/security/audit/audit_arg.c
index 5da377f..ea569f7 100644
--- a/sys/security/audit/audit_arg.c
+++ b/sys/security/audit/audit_arg.c
@@ -763,6 +763,48 @@ audit_arg_vnode(struct vnode *vp, u_int64_t flags)
}
/*
+ * Audit the argument strings passed to exec.
+ */
+void
+audit_arg_argv(char *argv, int argc, int length)
+{
+ struct kaudit_record *ar;
+
+ if (audit_argv == 0)
+ return;
+
+ ar = currecord();
+ if (ar == NULL)
+ return;
+
+ ar->k_ar.ar_arg_argv = malloc(length, M_AUDITTEXT, M_WAITOK);
+ bcopy(argv, ar->k_ar.ar_arg_argv, length);
+ ar->k_ar.ar_arg_argc = argc;
+ ARG_SET_VALID(ar, ARG_ARGV);
+}
+
+/*
+ * Audit the environment strings passed to exec.
+ */
+void
+audit_arg_envv(char *envv, int envc, int length)
+{
+ struct kaudit_record *ar;
+
+ if (audit_arge == 0)
+ return;
+
+ ar = currecord();
+ if (ar == NULL)
+ return;
+
+ ar->k_ar.ar_arg_envv = malloc(length, M_AUDITTEXT, M_WAITOK);
+ bcopy(envv, ar->k_ar.ar_arg_envv, length);
+ ar->k_ar.ar_arg_envc = envc;
+ ARG_SET_VALID(ar, ARG_ENVV);
+}
+
+/*
* The close() system call uses it's own audit call to capture the path/vnode
* information because those pieces are not easily obtained within the system
* call itself.
diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c
index 9beb68e..2bfab8a 100644
--- a/sys/security/audit/audit_bsm.c
+++ b/sys/security/audit/audit_bsm.c
@@ -572,7 +572,6 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
case AUE_CHDIR:
case AUE_CHROOT:
case AUE_EACCESS:
- case AUE_EXECVE:
case AUE_GETATTRLIST:
case AUE_NFS_GETFH:
case AUE_LSTAT:
@@ -671,6 +670,20 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
EXTATTR_TOKENS;
break;
+ case AUE_EXECVE:
+ if (ARG_IS_VALID(kar, ARG_ARGV)) {
+ tok = au_to_exec_args(ar->ar_arg_argv,
+ ar->ar_arg_argc);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_ENVV)) {
+ tok = au_to_exec_env(ar->ar_arg_envv,
+ ar->ar_arg_envc);
+ kau_write(rec, tok);
+ }
+ UPATH1_VNODE1_TOKENS;
+ break;
+
case AUE_FCHMOD:
if (ARG_IS_VALID(kar, ARG_MODE)) {
tok = au_to_arg32(2, "new file mode",
diff --git a/sys/security/audit/audit_bsm_token.c b/sys/security/audit/audit_bsm_token.c
index 7b9abe5..a5d404b 100644
--- a/sys/security/audit/audit_bsm_token.c
+++ b/sys/security/audit/audit_bsm_token.c
@@ -1014,13 +1014,60 @@ au_to_me(void)
}
#endif
+#if defined(_KERNEL) || defined(KERNEL)
+static token_t *
+au_to_exec_strings(char *strs, int count, u_char type)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int32_t totlen;
+ int ctr;
+ char *p;
+
+ totlen = 0;
+ ctr = count;
+ p = strs;
+ while (ctr-- > 0) {
+ totlen += strlen(p) + 1;
+ p = strs + totlen;
+ }
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen);
+ ADD_U_CHAR(dptr, type);
+ ADD_U_INT32(dptr, count);
+ ADD_STRING(dptr, strs, totlen);
+
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * count 4 bytes
+ * text count null-terminated strings
+ */
+token_t *
+au_to_exec_args(char *args, int argc)
+{
+ return (au_to_exec_strings(args, argc, AUT_EXEC_ARGS));
+}
+
/*
* token ID 1 byte
* count 4 bytes
* text count null-terminated strings
*/
token_t *
-au_to_exec_args(const char **args)
+au_to_exec_env(char *envs, int envc)
+{
+ return (au_to_exec_strings(envs, envc, AUT_EXEC_ENV));
+}
+#else
+/*
+ * token ID 1 byte
+ * count 4 bytes
+ * text count null-terminated strings
+ */
+token_t *
+au_to_exec_args(char **argv)
{
token_t *t;
u_char *dptr = NULL;
@@ -1028,7 +1075,7 @@ au_to_exec_args(const char **args)
int i, count = 0;
size_t totlen = 0;
- nextarg = *args;
+ nextarg = *argv;
while (nextarg != NULL) {
int nextlen;
@@ -1036,7 +1083,7 @@ au_to_exec_args(const char **args)
nextlen = strlen(nextarg);
totlen += nextlen + 1;
count++;
- nextarg = *(args + count);
+ nextarg = *(argv + count);
}
totlen += count * sizeof(char); /* nul terminations. */
@@ -1046,7 +1093,7 @@ au_to_exec_args(const char **args)
ADD_U_INT32(dptr, count);
for (i = 0; i < count; i++) {
- nextarg = *(args + i);
+ nextarg = *(argv + i);
ADD_MEM(dptr, nextarg, strlen(nextarg) + 1);
}
@@ -1059,7 +1106,7 @@ au_to_exec_args(const char **args)
* text count null-terminated strings
*/
token_t *
-au_to_exec_env(const char **env)
+au_to_exec_env(char **envp)
{
token_t *t;
u_char *dptr = NULL;
@@ -1067,7 +1114,7 @@ au_to_exec_env(const char **env)
size_t totlen = 0;
const char *nextenv;
- nextenv = *env;
+ nextenv = *envp;
while (nextenv != NULL) {
int nextlen;
@@ -1075,7 +1122,7 @@ au_to_exec_env(const char **env)
nextlen = strlen(nextenv);
totlen += nextlen + 1;
count++;
- nextenv = *(env + count);
+ nextenv = *(envp + count);
}
totlen += sizeof(char) * count;
@@ -1085,12 +1132,13 @@ au_to_exec_env(const char **env)
ADD_U_INT32(dptr, count);
for (i = 0; i < count; i++) {
- nextenv = *(env + i);
+ nextenv = *(envp + i);
ADD_MEM(dptr, nextenv, strlen(nextenv) + 1);
}
return (t);
}
+#endif
/*
* token ID 1 byte
diff --git a/sys/security/audit/audit_private.h b/sys/security/audit/audit_private.h
index 2dc61ec..f6cd17a 100644
--- a/sys/security/audit/audit_private.h
+++ b/sys/security/audit/audit_private.h
@@ -74,6 +74,8 @@ extern struct audit_fstat audit_fstat;
extern struct au_mask audit_nae_mask;
extern int audit_panic_on_write_fail;
extern int audit_fail_stop;
+extern int audit_argv;
+extern int audit_arge;
/*
* Success/failure conditions for the conversion of a kernel audit record to
@@ -210,6 +212,10 @@ struct audit_record {
void * ar_arg_svipc_addr;
struct posix_ipc_perm ar_arg_pipc_perm;
union auditon_udata ar_arg_auditon;
+ char *ar_arg_argv;
+ int ar_arg_argc;
+ char *ar_arg_envv;
+ int ar_arg_envc;
int ar_arg_exitstatus;
int ar_arg_exitretval;
};
diff --git a/sys/security/audit/audit_syscalls.c b/sys/security/audit/audit_syscalls.c
index 8bd6ccb..eb18c76 100644
--- a/sys/security/audit/audit_syscalls.c
+++ b/sys/security/audit/audit_syscalls.c
@@ -190,16 +190,23 @@ auditon(struct thread *td, struct auditon_args *uap)
udata.au_policy |= AUDIT_CNT;
if (audit_panic_on_write_fail)
udata.au_policy |= AUDIT_AHLT;
+ if (audit_argv)
+ udata.au_policy |= AUDIT_ARGV;
+ if (audit_arge)
+ udata.au_policy |= AUDIT_ARGE;
break;
case A_SETPOLICY:
- if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT))
+ if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|AUDIT_ARGV|
+ AUDIT_ARGE))
return (EINVAL);
/*
* XXX - Need to wake up waiters if the policy relaxes?
*/
audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0);
audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT);
+ audit_argv = (udata.au_policy & AUDIT_ARGV);
+ audit_arge = (udata.au_policy & AUDIT_ARGE);
break;
case A_GETKMASK:
OpenPOWER on IntegriCloud