diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-29 20:54:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-29 20:54:17 -0400 |
commit | 797cee982eef9195736afc5e7f3b8f613c41d19a (patch) | |
tree | 2baf2ada982bb1c2cbe058b1378e38272cbda5d3 | |
parent | 7a1e8b80fb1e8ead4cec15d1fc494ed290e4d2e9 (diff) | |
parent | 43761473c254b45883a64441dd0bc85a42f3645c (diff) |
Merge branch 'stable-4.8' of git://git.infradead.org/users/pcmoore/audit
Pull audit updates from Paul Moore:
"Six audit patches for 4.8.
There are a couple of style and minor whitespace tweaks for the logs,
as well as a minor fixup to catch errors on user filter rules, however
the major improvements are a fix to the s390 syscall argument masking
code (reviewed by the nice s390 folks), some consolidation around the
exclude filtering (less code, always a win), and a double-fetch fix
for recording the execve arguments"
* 'stable-4.8' of git://git.infradead.org/users/pcmoore/audit:
audit: fix a double fetch in audit_log_single_execve_arg()
audit: fix whitespace in CWD record
audit: add fields to exclude filter by reusing user filter
s390: ensure that syscall arguments are properly masked on s390
audit: fix some horrible switch statement style crimes
audit: fixup: log on errors from filter user rules
-rw-r--r-- | arch/s390/kernel/ptrace.c | 11 | ||||
-rw-r--r-- | include/linux/audit.h | 2 | ||||
-rw-r--r-- | kernel/audit.c | 4 | ||||
-rw-r--r-- | kernel/audit.h | 2 | ||||
-rw-r--r-- | kernel/auditfilter.c | 147 | ||||
-rw-r--r-- | kernel/auditsc.c | 342 |
6 files changed, 236 insertions, 272 deletions
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index cea17010448f..9336e824e2db 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -821,6 +821,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
821 | 821 | ||
822 | asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) | 822 | asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) |
823 | { | 823 | { |
824 | unsigned long mask = -1UL; | ||
825 | |||
824 | /* | 826 | /* |
825 | * The sysc_tracesys code in entry.S stored the system | 827 | * The sysc_tracesys code in entry.S stored the system |
826 | * call number to gprs[2]. | 828 | * call number to gprs[2]. |
@@ -846,9 +848,12 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) | |||
846 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) | 848 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) |
847 | trace_sys_enter(regs, regs->gprs[2]); | 849 | trace_sys_enter(regs, regs->gprs[2]); |
848 | 850 | ||
849 | audit_syscall_entry(regs->gprs[2], regs->orig_gpr2, | 851 | if (is_compat_task()) |
850 | regs->gprs[3], regs->gprs[4], | 852 | mask = 0xffffffff; |
851 | regs->gprs[5]); | 853 | |
854 | audit_syscall_entry(regs->gprs[2], regs->orig_gpr2 & mask, | ||
855 | regs->gprs[3] &mask, regs->gprs[4] &mask, | ||
856 | regs->gprs[5] &mask); | ||
852 | 857 | ||
853 | return regs->gprs[2]; | 858 | return regs->gprs[2]; |
854 | } | 859 | } |
diff --git a/include/linux/audit.h b/include/linux/audit.h index e38e3fc13ea8..9d4443f93db6 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -163,8 +163,6 @@ extern void audit_log_task_info(struct audit_buffer *ab, | |||
163 | extern int audit_update_lsm_rules(void); | 163 | extern int audit_update_lsm_rules(void); |
164 | 164 | ||
165 | /* Private API (for audit.c only) */ | 165 | /* Private API (for audit.c only) */ |
166 | extern int audit_filter_user(int type); | ||
167 | extern int audit_filter_type(int type); | ||
168 | extern int audit_rule_change(int type, __u32 portid, int seq, | 166 | extern int audit_rule_change(int type, __u32 portid, int seq, |
169 | void *data, size_t datasz); | 167 | void *data, size_t datasz); |
170 | extern int audit_list_rules_send(struct sk_buff *request_skb, int seq); | 168 | extern int audit_list_rules_send(struct sk_buff *request_skb, int seq); |
diff --git a/kernel/audit.c b/kernel/audit.c index 8d528f9930da..a8a91bd2b2a9 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -932,7 +932,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
932 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) | 932 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) |
933 | return 0; | 933 | return 0; |
934 | 934 | ||
935 | err = audit_filter_user(msg_type); | 935 | err = audit_filter(msg_type, AUDIT_FILTER_USER); |
936 | if (err == 1) { /* match or error */ | 936 | if (err == 1) { /* match or error */ |
937 | err = 0; | 937 | err = 0; |
938 | if (msg_type == AUDIT_USER_TTY) { | 938 | if (msg_type == AUDIT_USER_TTY) { |
@@ -1379,7 +1379,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, | |||
1379 | if (audit_initialized != AUDIT_INITIALIZED) | 1379 | if (audit_initialized != AUDIT_INITIALIZED) |
1380 | return NULL; | 1380 | return NULL; |
1381 | 1381 | ||
1382 | if (unlikely(audit_filter_type(type))) | 1382 | if (unlikely(!audit_filter(type, AUDIT_FILTER_TYPE))) |
1383 | return NULL; | 1383 | return NULL; |
1384 | 1384 | ||
1385 | if (gfp_mask & __GFP_DIRECT_RECLAIM) { | 1385 | if (gfp_mask & __GFP_DIRECT_RECLAIM) { |
diff --git a/kernel/audit.h b/kernel/audit.h index a492f4c4e710..431444c3708b 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
@@ -331,6 +331,8 @@ extern pid_t audit_sig_pid; | |||
331 | extern kuid_t audit_sig_uid; | 331 | extern kuid_t audit_sig_uid; |
332 | extern u32 audit_sig_sid; | 332 | extern u32 audit_sig_sid; |
333 | 333 | ||
334 | extern int audit_filter(int msgtype, unsigned int listtype); | ||
335 | |||
334 | #ifdef CONFIG_AUDITSYSCALL | 336 | #ifdef CONFIG_AUDITSYSCALL |
335 | extern int __audit_signal_info(int sig, struct task_struct *t); | 337 | extern int __audit_signal_info(int sig, struct task_struct *t); |
336 | static inline int audit_signal_info(int sig, struct task_struct *t) | 338 | static inline int audit_signal_info(int sig, struct task_struct *t) |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 94ca7b1e5e7e..85d9cac497e4 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
@@ -1290,113 +1290,72 @@ int audit_compare_dname_path(const char *dname, const char *path, int parentlen) | |||
1290 | return strncmp(p, dname, dlen); | 1290 | return strncmp(p, dname, dlen); |
1291 | } | 1291 | } |
1292 | 1292 | ||
1293 | static int audit_filter_user_rules(struct audit_krule *rule, int type, | 1293 | int audit_filter(int msgtype, unsigned int listtype) |
1294 | enum audit_state *state) | ||
1295 | { | 1294 | { |
1296 | int i; | ||
1297 | |||
1298 | for (i = 0; i < rule->field_count; i++) { | ||
1299 | struct audit_field *f = &rule->fields[i]; | ||
1300 | pid_t pid; | ||
1301 | int result = 0; | ||
1302 | u32 sid; | ||
1303 | |||
1304 | switch (f->type) { | ||
1305 | case AUDIT_PID: | ||
1306 | pid = task_pid_nr(current); | ||
1307 | result = audit_comparator(pid, f->op, f->val); | ||
1308 | break; | ||
1309 | case AUDIT_UID: | ||
1310 | result = audit_uid_comparator(current_uid(), f->op, f->uid); | ||
1311 | break; | ||
1312 | case AUDIT_GID: | ||
1313 | result = audit_gid_comparator(current_gid(), f->op, f->gid); | ||
1314 | break; | ||
1315 | case AUDIT_LOGINUID: | ||
1316 | result = audit_uid_comparator(audit_get_loginuid(current), | ||
1317 | f->op, f->uid); | ||
1318 | break; | ||
1319 | case AUDIT_LOGINUID_SET: | ||
1320 | result = audit_comparator(audit_loginuid_set(current), | ||
1321 | f->op, f->val); | ||
1322 | break; | ||
1323 | case AUDIT_MSGTYPE: | ||
1324 | result = audit_comparator(type, f->op, f->val); | ||
1325 | break; | ||
1326 | case AUDIT_SUBJ_USER: | ||
1327 | case AUDIT_SUBJ_ROLE: | ||
1328 | case AUDIT_SUBJ_TYPE: | ||
1329 | case AUDIT_SUBJ_SEN: | ||
1330 | case AUDIT_SUBJ_CLR: | ||
1331 | if (f->lsm_rule) { | ||
1332 | security_task_getsecid(current, &sid); | ||
1333 | result = security_audit_rule_match(sid, | ||
1334 | f->type, | ||
1335 | f->op, | ||
1336 | f->lsm_rule, | ||
1337 | NULL); | ||
1338 | } | ||
1339 | break; | ||
1340 | } | ||
1341 | |||
1342 | if (!result) | ||
1343 | return 0; | ||
1344 | } | ||
1345 | switch (rule->action) { | ||
1346 | case AUDIT_NEVER: *state = AUDIT_DISABLED; break; | ||
1347 | case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; | ||
1348 | } | ||
1349 | return 1; | ||
1350 | } | ||
1351 | |||
1352 | int audit_filter_user(int type) | ||
1353 | { | ||
1354 | enum audit_state state = AUDIT_DISABLED; | ||
1355 | struct audit_entry *e; | 1295 | struct audit_entry *e; |
1356 | int rc, ret; | 1296 | int ret = 1; /* Audit by default */ |
1357 | |||
1358 | ret = 1; /* Audit by default */ | ||
1359 | |||
1360 | rcu_read_lock(); | ||
1361 | list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { | ||
1362 | rc = audit_filter_user_rules(&e->rule, type, &state); | ||
1363 | if (rc) { | ||
1364 | if (rc > 0 && state == AUDIT_DISABLED) | ||
1365 | ret = 0; | ||
1366 | break; | ||
1367 | } | ||
1368 | } | ||
1369 | rcu_read_unlock(); | ||
1370 | |||
1371 | return ret; | ||
1372 | } | ||
1373 | |||
1374 | int audit_filter_type(int type) | ||
1375 | { | ||
1376 | struct audit_entry *e; | ||
1377 | int result = 0; | ||
1378 | 1297 | ||
1379 | rcu_read_lock(); | 1298 | rcu_read_lock(); |
1380 | if (list_empty(&audit_filter_list[AUDIT_FILTER_TYPE])) | 1299 | if (list_empty(&audit_filter_list[listtype])) |
1381 | goto unlock_and_return; | 1300 | goto unlock_and_return; |
1301 | list_for_each_entry_rcu(e, &audit_filter_list[listtype], list) { | ||
1302 | int i, result = 0; | ||
1382 | 1303 | ||
1383 | list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE], | ||
1384 | list) { | ||
1385 | int i; | ||
1386 | for (i = 0; i < e->rule.field_count; i++) { | 1304 | for (i = 0; i < e->rule.field_count; i++) { |
1387 | struct audit_field *f = &e->rule.fields[i]; | 1305 | struct audit_field *f = &e->rule.fields[i]; |
1388 | if (f->type == AUDIT_MSGTYPE) { | 1306 | pid_t pid; |
1389 | result = audit_comparator(type, f->op, f->val); | 1307 | u32 sid; |
1390 | if (!result) | 1308 | |
1391 | break; | 1309 | switch (f->type) { |
1310 | case AUDIT_PID: | ||
1311 | pid = task_pid_nr(current); | ||
1312 | result = audit_comparator(pid, f->op, f->val); | ||
1313 | break; | ||
1314 | case AUDIT_UID: | ||
1315 | result = audit_uid_comparator(current_uid(), f->op, f->uid); | ||
1316 | break; | ||
1317 | case AUDIT_GID: | ||
1318 | result = audit_gid_comparator(current_gid(), f->op, f->gid); | ||
1319 | break; | ||
1320 | case AUDIT_LOGINUID: | ||
1321 | result = audit_uid_comparator(audit_get_loginuid(current), | ||
1322 | f->op, f->uid); | ||
1323 | break; | ||
1324 | case AUDIT_LOGINUID_SET: | ||
1325 | result = audit_comparator(audit_loginuid_set(current), | ||
1326 | f->op, f->val); | ||
1327 | break; | ||
1328 | case AUDIT_MSGTYPE: | ||
1329 | result = audit_comparator(msgtype, f->op, f->val); | ||
1330 | break; | ||
1331 | case AUDIT_SUBJ_USER: | ||
1332 | case AUDIT_SUBJ_ROLE: | ||
1333 | case AUDIT_SUBJ_TYPE: | ||
1334 | case AUDIT_SUBJ_SEN: | ||
1335 | case AUDIT_SUBJ_CLR: | ||
1336 | if (f->lsm_rule) { | ||
1337 | security_task_getsecid(current, &sid); | ||
1338 | result = security_audit_rule_match(sid, | ||
1339 | f->type, f->op, f->lsm_rule, NULL); | ||
1340 | } | ||
1341 | break; | ||
1342 | default: | ||
1343 | goto unlock_and_return; | ||
1392 | } | 1344 | } |
1345 | if (result < 0) /* error */ | ||
1346 | goto unlock_and_return; | ||
1347 | if (!result) | ||
1348 | break; | ||
1349 | } | ||
1350 | if (result > 0) { | ||
1351 | if (e->rule.action == AUDIT_NEVER || listtype == AUDIT_FILTER_TYPE) | ||
1352 | ret = 0; | ||
1353 | break; | ||
1393 | } | 1354 | } |
1394 | if (result) | ||
1395 | goto unlock_and_return; | ||
1396 | } | 1355 | } |
1397 | unlock_and_return: | 1356 | unlock_and_return: |
1398 | rcu_read_unlock(); | 1357 | rcu_read_unlock(); |
1399 | return result; | 1358 | return ret; |
1400 | } | 1359 | } |
1401 | 1360 | ||
1402 | static int update_lsm_rule(struct audit_krule *r) | 1361 | static int update_lsm_rule(struct audit_krule *r) |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 2672d105cffc..5abf1dc1f91c 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -72,6 +72,7 @@ | |||
72 | #include <linux/compat.h> | 72 | #include <linux/compat.h> |
73 | #include <linux/ctype.h> | 73 | #include <linux/ctype.h> |
74 | #include <linux/string.h> | 74 | #include <linux/string.h> |
75 | #include <linux/uaccess.h> | ||
75 | #include <uapi/linux/limits.h> | 76 | #include <uapi/linux/limits.h> |
76 | 77 | ||
77 | #include "audit.h" | 78 | #include "audit.h" |
@@ -81,7 +82,8 @@ | |||
81 | #define AUDITSC_SUCCESS 1 | 82 | #define AUDITSC_SUCCESS 1 |
82 | #define AUDITSC_FAILURE 2 | 83 | #define AUDITSC_FAILURE 2 |
83 | 84 | ||
84 | /* no execve audit message should be longer than this (userspace limits) */ | 85 | /* no execve audit message should be longer than this (userspace limits), |
86 | * see the note near the top of audit_log_execve_info() about this value */ | ||
85 | #define MAX_EXECVE_AUDIT_LEN 7500 | 87 | #define MAX_EXECVE_AUDIT_LEN 7500 |
86 | 88 | ||
87 | /* max length to print of cmdline/proctitle value during audit */ | 89 | /* max length to print of cmdline/proctitle value during audit */ |
@@ -694,8 +696,12 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
694 | ctx->prio = rule->prio; | 696 | ctx->prio = rule->prio; |
695 | } | 697 | } |
696 | switch (rule->action) { | 698 | switch (rule->action) { |
697 | case AUDIT_NEVER: *state = AUDIT_DISABLED; break; | 699 | case AUDIT_NEVER: |
698 | case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; | 700 | *state = AUDIT_DISABLED; |
701 | break; | ||
702 | case AUDIT_ALWAYS: | ||
703 | *state = AUDIT_RECORD_CONTEXT; | ||
704 | break; | ||
699 | } | 705 | } |
700 | return 1; | 706 | return 1; |
701 | } | 707 | } |
@@ -987,184 +993,178 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid, | |||
987 | return rc; | 993 | return rc; |
988 | } | 994 | } |
989 | 995 | ||
990 | /* | 996 | static void audit_log_execve_info(struct audit_context *context, |
991 | * to_send and len_sent accounting are very loose estimates. We aren't | 997 | struct audit_buffer **ab) |
992 | * really worried about a hard cap to MAX_EXECVE_AUDIT_LEN so much as being | ||
993 | * within about 500 bytes (next page boundary) | ||
994 | * | ||
995 | * why snprintf? an int is up to 12 digits long. if we just assumed when | ||
996 | * logging that a[%d]= was going to be 16 characters long we would be wasting | ||
997 | * space in every audit message. In one 7500 byte message we can log up to | ||
998 | * about 1000 min size arguments. That comes down to about 50% waste of space | ||
999 | * if we didn't do the snprintf to find out how long arg_num_len was. | ||
1000 | */ | ||
1001 | static int audit_log_single_execve_arg(struct audit_context *context, | ||
1002 | struct audit_buffer **ab, | ||
1003 | int arg_num, | ||
1004 | size_t *len_sent, | ||
1005 | const char __user *p, | ||
1006 | char *buf) | ||
1007 | { | 998 | { |
1008 | char arg_num_len_buf[12]; | 999 | long len_max; |
1009 | const char __user *tmp_p = p; | 1000 | long len_rem; |
1010 | /* how many digits are in arg_num? 5 is the length of ' a=""' */ | 1001 | long len_full; |
1011 | size_t arg_num_len = snprintf(arg_num_len_buf, 12, "%d", arg_num) + 5; | 1002 | long len_buf; |
1012 | size_t len, len_left, to_send; | 1003 | long len_abuf; |
1013 | size_t max_execve_audit_len = MAX_EXECVE_AUDIT_LEN; | 1004 | long len_tmp; |
1014 | unsigned int i, has_cntl = 0, too_long = 0; | 1005 | bool require_data; |
1015 | int ret; | 1006 | bool encode; |
1016 | 1007 | unsigned int iter; | |
1017 | /* strnlen_user includes the null we don't want to send */ | 1008 | unsigned int arg; |
1018 | len_left = len = strnlen_user(p, MAX_ARG_STRLEN) - 1; | 1009 | char *buf_head; |
1019 | 1010 | char *buf; | |
1020 | /* | 1011 | const char __user *p = (const char __user *)current->mm->arg_start; |
1021 | * We just created this mm, if we can't find the strings | 1012 | |
1022 | * we just copied into it something is _very_ wrong. Similar | 1013 | /* NOTE: this buffer needs to be large enough to hold all the non-arg |
1023 | * for strings that are too long, we should not have created | 1014 | * data we put in the audit record for this argument (see the |
1024 | * any. | 1015 | * code below) ... at this point in time 96 is plenty */ |
1025 | */ | 1016 | char abuf[96]; |
1026 | if (WARN_ON_ONCE(len < 0 || len > MAX_ARG_STRLEN - 1)) { | 1017 | |
1027 | send_sig(SIGKILL, current, 0); | 1018 | /* NOTE: we set MAX_EXECVE_AUDIT_LEN to a rather arbitrary limit, the |
1028 | return -1; | 1019 | * current value of 7500 is not as important as the fact that it |
1020 | * is less than 8k, a setting of 7500 gives us plenty of wiggle | ||
1021 | * room if we go over a little bit in the logging below */ | ||
1022 | WARN_ON_ONCE(MAX_EXECVE_AUDIT_LEN > 7500); | ||
1023 | len_max = MAX_EXECVE_AUDIT_LEN; | ||
1024 | |||
1025 | /* scratch buffer to hold the userspace args */ | ||
1026 | buf_head = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL); | ||
1027 | if (!buf_head) { | ||
1028 | audit_panic("out of memory for argv string"); | ||
1029 | return; | ||
1029 | } | 1030 | } |
1031 | buf = buf_head; | ||
1030 | 1032 | ||
1031 | /* walk the whole argument looking for non-ascii chars */ | 1033 | audit_log_format(*ab, "argc=%d", context->execve.argc); |
1034 | |||
1035 | len_rem = len_max; | ||
1036 | len_buf = 0; | ||
1037 | len_full = 0; | ||
1038 | require_data = true; | ||
1039 | encode = false; | ||
1040 | iter = 0; | ||
1041 | arg = 0; | ||
1032 | do { | 1042 | do { |
1033 | if (len_left > MAX_EXECVE_AUDIT_LEN) | 1043 | /* NOTE: we don't ever want to trust this value for anything |
1034 | to_send = MAX_EXECVE_AUDIT_LEN; | 1044 | * serious, but the audit record format insists we |
1035 | else | 1045 | * provide an argument length for really long arguments, |
1036 | to_send = len_left; | 1046 | * e.g. > MAX_EXECVE_AUDIT_LEN, so we have no choice but |
1037 | ret = copy_from_user(buf, tmp_p, to_send); | 1047 | * to use strncpy_from_user() to obtain this value for |
1038 | /* | 1048 | * recording in the log, although we don't use it |
1039 | * There is no reason for this copy to be short. We just | 1049 | * anywhere here to avoid a double-fetch problem */ |
1040 | * copied them here, and the mm hasn't been exposed to user- | 1050 | if (len_full == 0) |
1041 | * space yet. | 1051 | len_full = strnlen_user(p, MAX_ARG_STRLEN) - 1; |
1042 | */ | 1052 | |
1043 | if (ret) { | 1053 | /* read more data from userspace */ |
1044 | WARN_ON(1); | 1054 | if (require_data) { |
1045 | send_sig(SIGKILL, current, 0); | 1055 | /* can we make more room in the buffer? */ |
1046 | return -1; | 1056 | if (buf != buf_head) { |
1047 | } | 1057 | memmove(buf_head, buf, len_buf); |
1048 | buf[to_send] = '\0'; | 1058 | buf = buf_head; |
1049 | has_cntl = audit_string_contains_control(buf, to_send); | 1059 | } |
1050 | if (has_cntl) { | 1060 | |
1051 | /* | 1061 | /* fetch as much as we can of the argument */ |
1052 | * hex messages get logged as 2 bytes, so we can only | 1062 | len_tmp = strncpy_from_user(&buf_head[len_buf], p, |
1053 | * send half as much in each message | 1063 | len_max - len_buf); |
1054 | */ | 1064 | if (len_tmp == -EFAULT) { |
1055 | max_execve_audit_len = MAX_EXECVE_AUDIT_LEN / 2; | 1065 | /* unable to copy from userspace */ |
1056 | break; | 1066 | send_sig(SIGKILL, current, 0); |
1057 | } | 1067 | goto out; |
1058 | len_left -= to_send; | 1068 | } else if (len_tmp == (len_max - len_buf)) { |
1059 | tmp_p += to_send; | 1069 | /* buffer is not large enough */ |
1060 | } while (len_left > 0); | 1070 | require_data = true; |
1061 | 1071 | /* NOTE: if we are going to span multiple | |
1062 | len_left = len; | 1072 | * buffers force the encoding so we stand |
1063 | 1073 | * a chance at a sane len_full value and | |
1064 | if (len > max_execve_audit_len) | 1074 | * consistent record encoding */ |
1065 | too_long = 1; | 1075 | encode = true; |
1066 | 1076 | len_full = len_full * 2; | |
1067 | /* rewalk the argument actually logging the message */ | 1077 | p += len_tmp; |
1068 | for (i = 0; len_left > 0; i++) { | 1078 | } else { |
1069 | int room_left; | 1079 | require_data = false; |
1070 | 1080 | if (!encode) | |
1071 | if (len_left > max_execve_audit_len) | 1081 | encode = audit_string_contains_control( |
1072 | to_send = max_execve_audit_len; | 1082 | buf, len_tmp); |
1073 | else | 1083 | /* try to use a trusted value for len_full */ |
1074 | to_send = len_left; | 1084 | if (len_full < len_max) |
1075 | 1085 | len_full = (encode ? | |
1076 | /* do we have space left to send this argument in this ab? */ | 1086 | len_tmp * 2 : len_tmp); |
1077 | room_left = MAX_EXECVE_AUDIT_LEN - arg_num_len - *len_sent; | 1087 | p += len_tmp + 1; |
1078 | if (has_cntl) | 1088 | } |
1079 | room_left -= (to_send * 2); | 1089 | len_buf += len_tmp; |
1080 | else | 1090 | buf_head[len_buf] = '\0'; |
1081 | room_left -= to_send; | ||
1082 | if (room_left < 0) { | ||
1083 | *len_sent = 0; | ||
1084 | audit_log_end(*ab); | ||
1085 | *ab = audit_log_start(context, GFP_KERNEL, AUDIT_EXECVE); | ||
1086 | if (!*ab) | ||
1087 | return 0; | ||
1088 | } | ||
1089 | 1091 | ||
1090 | /* | 1092 | /* length of the buffer in the audit record? */ |
1091 | * first record needs to say how long the original string was | 1093 | len_abuf = (encode ? len_buf * 2 : len_buf + 2); |
1092 | * so we can be sure nothing was lost. | ||
1093 | */ | ||
1094 | if ((i == 0) && (too_long)) | ||
1095 | audit_log_format(*ab, " a%d_len=%zu", arg_num, | ||
1096 | has_cntl ? 2*len : len); | ||
1097 | |||
1098 | /* | ||
1099 | * normally arguments are small enough to fit and we already | ||
1100 | * filled buf above when we checked for control characters | ||
1101 | * so don't bother with another copy_from_user | ||
1102 | */ | ||
1103 | if (len >= max_execve_audit_len) | ||
1104 | ret = copy_from_user(buf, p, to_send); | ||
1105 | else | ||
1106 | ret = 0; | ||
1107 | if (ret) { | ||
1108 | WARN_ON(1); | ||
1109 | send_sig(SIGKILL, current, 0); | ||
1110 | return -1; | ||
1111 | } | 1094 | } |
1112 | buf[to_send] = '\0'; | ||
1113 | |||
1114 | /* actually log it */ | ||
1115 | audit_log_format(*ab, " a%d", arg_num); | ||
1116 | if (too_long) | ||
1117 | audit_log_format(*ab, "[%d]", i); | ||
1118 | audit_log_format(*ab, "="); | ||
1119 | if (has_cntl) | ||
1120 | audit_log_n_hex(*ab, buf, to_send); | ||
1121 | else | ||
1122 | audit_log_string(*ab, buf); | ||
1123 | |||
1124 | p += to_send; | ||
1125 | len_left -= to_send; | ||
1126 | *len_sent += arg_num_len; | ||
1127 | if (has_cntl) | ||
1128 | *len_sent += to_send * 2; | ||
1129 | else | ||
1130 | *len_sent += to_send; | ||
1131 | } | ||
1132 | /* include the null we didn't log */ | ||
1133 | return len + 1; | ||
1134 | } | ||
1135 | 1095 | ||
1136 | static void audit_log_execve_info(struct audit_context *context, | 1096 | /* write as much as we can to the audit log */ |
1137 | struct audit_buffer **ab) | 1097 | if (len_buf > 0) { |
1138 | { | 1098 | /* NOTE: some magic numbers here - basically if we |
1139 | int i, len; | 1099 | * can't fit a reasonable amount of data into the |
1140 | size_t len_sent = 0; | 1100 | * existing audit buffer, flush it and start with |
1141 | const char __user *p; | 1101 | * a new buffer */ |
1142 | char *buf; | 1102 | if ((sizeof(abuf) + 8) > len_rem) { |
1103 | len_rem = len_max; | ||
1104 | audit_log_end(*ab); | ||
1105 | *ab = audit_log_start(context, | ||
1106 | GFP_KERNEL, AUDIT_EXECVE); | ||
1107 | if (!*ab) | ||
1108 | goto out; | ||
1109 | } | ||
1143 | 1110 | ||
1144 | p = (const char __user *)current->mm->arg_start; | 1111 | /* create the non-arg portion of the arg record */ |
1112 | len_tmp = 0; | ||
1113 | if (require_data || (iter > 0) || | ||
1114 | ((len_abuf + sizeof(abuf)) > len_rem)) { | ||
1115 | if (iter == 0) { | ||
1116 | len_tmp += snprintf(&abuf[len_tmp], | ||
1117 | sizeof(abuf) - len_tmp, | ||
1118 | " a%d_len=%lu", | ||
1119 | arg, len_full); | ||
1120 | } | ||
1121 | len_tmp += snprintf(&abuf[len_tmp], | ||
1122 | sizeof(abuf) - len_tmp, | ||
1123 | " a%d[%d]=", arg, iter++); | ||
1124 | } else | ||
1125 | len_tmp += snprintf(&abuf[len_tmp], | ||
1126 | sizeof(abuf) - len_tmp, | ||
1127 | " a%d=", arg); | ||
1128 | WARN_ON(len_tmp >= sizeof(abuf)); | ||
1129 | abuf[sizeof(abuf) - 1] = '\0'; | ||
1130 | |||
1131 | /* log the arg in the audit record */ | ||
1132 | audit_log_format(*ab, "%s", abuf); | ||
1133 | len_rem -= len_tmp; | ||
1134 | len_tmp = len_buf; | ||
1135 | if (encode) { | ||
1136 | if (len_abuf > len_rem) | ||
1137 | len_tmp = len_rem / 2; /* encoding */ | ||
1138 | audit_log_n_hex(*ab, buf, len_tmp); | ||
1139 | len_rem -= len_tmp * 2; | ||
1140 | len_abuf -= len_tmp * 2; | ||
1141 | } else { | ||
1142 | if (len_abuf > len_rem) | ||
1143 | len_tmp = len_rem - 2; /* quotes */ | ||
1144 | audit_log_n_string(*ab, buf, len_tmp); | ||
1145 | len_rem -= len_tmp + 2; | ||
1146 | /* don't subtract the "2" because we still need | ||
1147 | * to add quotes to the remaining string */ | ||
1148 | len_abuf -= len_tmp; | ||
1149 | } | ||
1150 | len_buf -= len_tmp; | ||
1151 | buf += len_tmp; | ||
1152 | } | ||
1145 | 1153 | ||
1146 | audit_log_format(*ab, "argc=%d", context->execve.argc); | 1154 | /* ready to move to the next argument? */ |
1155 | if ((len_buf == 0) && !require_data) { | ||
1156 | arg++; | ||
1157 | iter = 0; | ||
1158 | len_full = 0; | ||
1159 | require_data = true; | ||
1160 | encode = false; | ||
1161 | } | ||
1162 | } while (arg < context->execve.argc); | ||
1147 | 1163 | ||
1148 | /* | 1164 | /* NOTE: the caller handles the final audit_log_end() call */ |
1149 | * we need some kernel buffer to hold the userspace args. Just | ||
1150 | * allocate one big one rather than allocating one of the right size | ||
1151 | * for every single argument inside audit_log_single_execve_arg() | ||
1152 | * should be <8k allocation so should be pretty safe. | ||
1153 | */ | ||
1154 | buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL); | ||
1155 | if (!buf) { | ||
1156 | audit_panic("out of memory for argv string"); | ||
1157 | return; | ||
1158 | } | ||
1159 | 1165 | ||
1160 | for (i = 0; i < context->execve.argc; i++) { | 1166 | out: |
1161 | len = audit_log_single_execve_arg(context, ab, i, | 1167 | kfree(buf_head); |
1162 | &len_sent, p, buf); | ||
1163 | if (len <= 0) | ||
1164 | break; | ||
1165 | p += len; | ||
1166 | } | ||
1167 | kfree(buf); | ||
1168 | } | 1168 | } |
1169 | 1169 | ||
1170 | static void show_special(struct audit_context *context, int *call_panic) | 1170 | static void show_special(struct audit_context *context, int *call_panic) |
@@ -1425,7 +1425,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
1425 | if (context->pwd.dentry && context->pwd.mnt) { | 1425 | if (context->pwd.dentry && context->pwd.mnt) { |
1426 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD); | 1426 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD); |
1427 | if (ab) { | 1427 | if (ab) { |
1428 | audit_log_d_path(ab, " cwd=", &context->pwd); | 1428 | audit_log_d_path(ab, "cwd=", &context->pwd); |
1429 | audit_log_end(ab); | 1429 | audit_log_end(ab); |
1430 | } | 1430 | } |
1431 | } | 1431 | } |