[AUDIT] break large execve argument logging into smaller messages

execve arguments can be quite large. There is no limit on the number of
arguments and a 4G limit on the size of an argument.

this patch prints those aruguments in bite sized pieces. a userspace size
limitation of 8k was discovered so this keeps messages around 7.5k

single arguments larger than 7.5k in length are split into multiple records
and can be identified as aX[Y]=

Signed-off-by: Eric Paris <eparis@redhat.com>

authored by

Eric Paris and committed by
Al Viro
de6bbd1d e445deb5

+196 -78
-7
Documentation/filesystems/proc.txt
··· 1134 1134 resume it if we have a value of 3 or more percent; consider information about 1135 1135 the amount of free space valid for 30 seconds 1136 1136 1137 - audit_argv_kb 1138 - ------------- 1139 - 1140 - The file contains a single value denoting the limit on the argv array size 1141 - for execve (in KiB). This limit is only applied when system call auditing for 1142 - execve is enabled, otherwise the value is ignored. 1143 - 1144 1137 ctrl-alt-del 1145 1138 ------------ 1146 1139
+4 -2
include/linux/audit.h
··· 525 525 extern void audit_log_hex(struct audit_buffer *ab, 526 526 const unsigned char *buf, 527 527 size_t len); 528 - extern const char * audit_log_untrustedstring(struct audit_buffer *ab, 528 + extern int audit_string_contains_control(const char *string, 529 + size_t len); 530 + extern void audit_log_untrustedstring(struct audit_buffer *ab, 529 531 const char *string); 530 - extern const char * audit_log_n_untrustedstring(struct audit_buffer *ab, 532 + extern void audit_log_n_untrustedstring(struct audit_buffer *ab, 531 533 size_t n, 532 534 const char *string); 533 535 extern void audit_log_d_path(struct audit_buffer *ab,
+23 -14
kernel/audit.c
··· 1350 1350 } 1351 1351 1352 1352 /** 1353 + * audit_string_contains_control - does a string need to be logged in hex 1354 + * @string - string to be checked 1355 + * @len - max length of the string to check 1356 + */ 1357 + int audit_string_contains_control(const char *string, size_t len) 1358 + { 1359 + const unsigned char *p; 1360 + for (p = string; p < (const unsigned char *)string + len && *p; p++) { 1361 + if (*p == '"' || *p < 0x21 || *p > 0x7f) 1362 + return 1; 1363 + } 1364 + return 0; 1365 + } 1366 + 1367 + /** 1353 1368 * audit_log_n_untrustedstring - log a string that may contain random characters 1354 1369 * @ab: audit_buffer 1355 1370 * @len: lenth of string (not including trailing null) ··· 1378 1363 * The caller specifies the number of characters in the string to log, which may 1379 1364 * or may not be the entire string. 1380 1365 */ 1381 - const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, 1382 - const char *string) 1366 + void audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, 1367 + const char *string) 1383 1368 { 1384 - const unsigned char *p; 1385 - 1386 - for (p = string; p < (const unsigned char *)string + len && *p; p++) { 1387 - if (*p == '"' || *p < 0x21 || *p > 0x7f) { 1388 - audit_log_hex(ab, string, len); 1389 - return string + len + 1; 1390 - } 1391 - } 1392 - audit_log_n_string(ab, len, string); 1393 - return p + 1; 1369 + if (audit_string_contains_control(string, len)) 1370 + audit_log_hex(ab, string, len); 1371 + else 1372 + audit_log_n_string(ab, len, string); 1394 1373 } 1395 1374 1396 1375 /** ··· 1395 1386 * Same as audit_log_n_untrustedstring(), except that strlen is used to 1396 1387 * determine string length. 1397 1388 */ 1398 - const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string) 1389 + void audit_log_untrustedstring(struct audit_buffer *ab, const char *string) 1399 1390 { 1400 - return audit_log_n_untrustedstring(ab, strlen(string), string); 1391 + audit_log_n_untrustedstring(ab, strlen(string), string); 1401 1392 } 1402 1393 1403 1394 /* This is a helper-function to print the escaped d_path */
+169 -44
kernel/auditsc.c
··· 78 78 /* Indicates that audit should log the full pathname. */ 79 79 #define AUDIT_NAME_FULL -1 80 80 81 + /* no execve audit message should be longer than this (userspace limits) */ 82 + #define MAX_EXECVE_AUDIT_LEN 7500 83 + 81 84 /* number of audit rules */ 82 85 int audit_n_rules; 83 86 ··· 968 965 return rc; 969 966 } 970 967 971 - static void audit_log_execve_info(struct audit_buffer *ab, 972 - struct audit_aux_data_execve *axi) 968 + /* 969 + * to_send and len_sent accounting are very loose estimates. We aren't 970 + * really worried about a hard cap to MAX_EXECVE_AUDIT_LEN so much as being 971 + * within about 500 bytes (next page boundry) 972 + * 973 + * why snprintf? an int is up to 12 digits long. if we just assumed when 974 + * logging that a[%d]= was going to be 16 characters long we would be wasting 975 + * space in every audit message. In one 7500 byte message we can log up to 976 + * about 1000 min size arguments. That comes down to about 50% waste of space 977 + * if we didn't do the snprintf to find out how long arg_num_len was. 978 + */ 979 + static int audit_log_single_execve_arg(struct audit_context *context, 980 + struct audit_buffer **ab, 981 + int arg_num, 982 + size_t *len_sent, 983 + const char __user *p, 984 + char *buf) 973 985 { 974 - int i; 975 - long len, ret; 976 - const char __user *p; 977 - char *buf; 986 + char arg_num_len_buf[12]; 987 + const char __user *tmp_p = p; 988 + /* how many digits are in arg_num? 3 is the length of a=\n */ 989 + size_t arg_num_len = snprintf(arg_num_len_buf, 12, "%d", arg_num) + 3; 990 + size_t len, len_left, to_send; 991 + size_t max_execve_audit_len = MAX_EXECVE_AUDIT_LEN; 992 + unsigned int i, has_cntl = 0, too_long = 0; 993 + int ret; 978 994 979 - if (axi->mm != current->mm) 980 - return; /* execve failed, no additional info */ 995 + /* strnlen_user includes the null we don't want to send */ 996 + len_left = len = strnlen_user(p, MAX_ARG_STRLEN) - 1; 981 997 982 - p = (const char __user *)axi->mm->arg_start; 998 + /* 999 + * We just created this mm, if we can't find the strings 1000 + * we just copied into it something is _very_ wrong. Similar 1001 + * for strings that are too long, we should not have created 1002 + * any. 1003 + */ 1004 + if (unlikely((len = -1) || len > MAX_ARG_STRLEN - 1)) { 1005 + WARN_ON(1); 1006 + send_sig(SIGKILL, current, 0); 1007 + } 983 1008 984 - for (i = 0; i < axi->argc; i++, p += len) { 985 - len = strnlen_user(p, MAX_ARG_STRLEN); 986 - /* 987 - * We just created this mm, if we can't find the strings 988 - * we just copied into it something is _very_ wrong. Similar 989 - * for strings that are too long, we should not have created 990 - * any. 991 - */ 992 - if (!len || len > MAX_ARG_STRLEN) { 993 - WARN_ON(1); 994 - send_sig(SIGKILL, current, 0); 995 - } 996 - 997 - buf = kmalloc(len, GFP_KERNEL); 998 - if (!buf) { 999 - audit_panic("out of memory for argv string\n"); 1000 - break; 1001 - } 1002 - 1003 - ret = copy_from_user(buf, p, len); 1009 + /* walk the whole argument looking for non-ascii chars */ 1010 + do { 1011 + if (len_left > MAX_EXECVE_AUDIT_LEN) 1012 + to_send = MAX_EXECVE_AUDIT_LEN; 1013 + else 1014 + to_send = len_left; 1015 + ret = copy_from_user(buf, tmp_p, to_send); 1004 1016 /* 1005 1017 * There is no reason for this copy to be short. We just 1006 1018 * copied them here, and the mm hasn't been exposed to user- ··· 1025 1007 WARN_ON(1); 1026 1008 send_sig(SIGKILL, current, 0); 1027 1009 } 1010 + buf[to_send] = '\0'; 1011 + has_cntl = audit_string_contains_control(buf, to_send); 1012 + if (has_cntl) { 1013 + /* 1014 + * hex messages get logged as 2 bytes, so we can only 1015 + * send half as much in each message 1016 + */ 1017 + max_execve_audit_len = MAX_EXECVE_AUDIT_LEN / 2; 1018 + break; 1019 + } 1020 + len_left -= to_send; 1021 + tmp_p += to_send; 1022 + } while (len_left > 0); 1028 1023 1029 - audit_log_format(ab, "a%d=", i); 1030 - audit_log_untrustedstring(ab, buf); 1031 - audit_log_format(ab, "\n"); 1024 + len_left = len; 1032 1025 1033 - kfree(buf); 1026 + if (len > max_execve_audit_len) 1027 + too_long = 1; 1028 + 1029 + /* rewalk the argument actually logging the message */ 1030 + for (i = 0; len_left > 0; i++) { 1031 + int room_left; 1032 + 1033 + if (len_left > max_execve_audit_len) 1034 + to_send = max_execve_audit_len; 1035 + else 1036 + to_send = len_left; 1037 + 1038 + /* do we have space left to send this argument in this ab? */ 1039 + room_left = MAX_EXECVE_AUDIT_LEN - arg_num_len - *len_sent; 1040 + if (has_cntl) 1041 + room_left -= (to_send * 2); 1042 + else 1043 + room_left -= to_send; 1044 + if (room_left < 0) { 1045 + *len_sent = 0; 1046 + audit_log_end(*ab); 1047 + *ab = audit_log_start(context, GFP_KERNEL, AUDIT_EXECVE); 1048 + if (!*ab) 1049 + return 0; 1050 + } 1051 + 1052 + /* 1053 + * first record needs to say how long the original string was 1054 + * so we can be sure nothing was lost. 1055 + */ 1056 + if ((i == 0) && (too_long)) 1057 + audit_log_format(*ab, "a%d_len=%ld ", arg_num, 1058 + has_cntl ? 2*len : len); 1059 + 1060 + /* 1061 + * normally arguments are small enough to fit and we already 1062 + * filled buf above when we checked for control characters 1063 + * so don't bother with another copy_from_user 1064 + */ 1065 + if (len >= max_execve_audit_len) 1066 + ret = copy_from_user(buf, p, to_send); 1067 + else 1068 + ret = 0; 1069 + if (ret) { 1070 + WARN_ON(1); 1071 + send_sig(SIGKILL, current, 0); 1072 + } 1073 + buf[to_send] = '\0'; 1074 + 1075 + /* actually log it */ 1076 + audit_log_format(*ab, "a%d", arg_num); 1077 + if (too_long) 1078 + audit_log_format(*ab, "[%d]", i); 1079 + audit_log_format(*ab, "="); 1080 + if (has_cntl) 1081 + audit_log_hex(*ab, buf, to_send); 1082 + else 1083 + audit_log_format(*ab, "\"%s\"", buf); 1084 + audit_log_format(*ab, "\n"); 1085 + 1086 + p += to_send; 1087 + len_left -= to_send; 1088 + *len_sent += arg_num_len; 1089 + if (has_cntl) 1090 + *len_sent += to_send * 2; 1091 + else 1092 + *len_sent += to_send; 1034 1093 } 1094 + /* include the null we didn't log */ 1095 + return len + 1; 1096 + } 1097 + 1098 + static void audit_log_execve_info(struct audit_context *context, 1099 + struct audit_buffer **ab, 1100 + struct audit_aux_data_execve *axi) 1101 + { 1102 + int i; 1103 + size_t len, len_sent = 0; 1104 + const char __user *p; 1105 + char *buf; 1106 + 1107 + if (axi->mm != current->mm) 1108 + return; /* execve failed, no additional info */ 1109 + 1110 + p = (const char __user *)axi->mm->arg_start; 1111 + 1112 + audit_log_format(*ab, "argc=%d ", axi->argc); 1113 + 1114 + /* 1115 + * we need some kernel buffer to hold the userspace args. Just 1116 + * allocate one big one rather than allocating one of the right size 1117 + * for every single argument inside audit_log_single_execve_arg() 1118 + * should be <8k allocation so should be pretty safe. 1119 + */ 1120 + buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL); 1121 + if (!buf) { 1122 + audit_panic("out of memory for argv string\n"); 1123 + return; 1124 + } 1125 + 1126 + for (i = 0; i < axi->argc; i++) { 1127 + len = audit_log_single_execve_arg(context, ab, i, 1128 + &len_sent, p, buf); 1129 + if (len <= 0) 1130 + break; 1131 + p += len; 1132 + } 1133 + kfree(buf); 1035 1134 } 1036 1135 1037 1136 static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) ··· 1292 1157 1293 1158 case AUDIT_EXECVE: { 1294 1159 struct audit_aux_data_execve *axi = (void *)aux; 1295 - audit_log_execve_info(ab, axi); 1160 + audit_log_execve_info(context, &ab, axi); 1296 1161 break; } 1297 1162 1298 1163 case AUDIT_SOCKETCALL: { ··· 2229 2094 return 0; 2230 2095 } 2231 2096 2232 - int audit_argv_kb = 32; 2233 - 2234 2097 int audit_bprm(struct linux_binprm *bprm) 2235 2098 { 2236 2099 struct audit_aux_data_execve *ax; ··· 2236 2103 2237 2104 if (likely(!audit_enabled || !context || context->dummy)) 2238 2105 return 0; 2239 - 2240 - /* 2241 - * Even though the stack code doesn't limit the arg+env size any more, 2242 - * the audit code requires that _all_ arguments be logged in a single 2243 - * netlink skb. Hence cap it :-( 2244 - */ 2245 - if (bprm->argv_len > (audit_argv_kb << 10)) 2246 - return -E2BIG; 2247 2106 2248 2107 ax = kmalloc(sizeof(*ax), GFP_KERNEL); 2249 2108 if (!ax)
-11
kernel/sysctl.c
··· 81 81 extern int compat_log; 82 82 extern int maps_protect; 83 83 extern int sysctl_stat_interval; 84 - extern int audit_argv_kb; 85 84 extern int latencytop_enabled; 86 85 87 86 /* Constants used for minimum and maximum */ ··· 389 390 .mode = 0644, 390 391 .proc_handler = &proc_dointvec, 391 392 }, 392 - #ifdef CONFIG_AUDITSYSCALL 393 - { 394 - .ctl_name = CTL_UNNUMBERED, 395 - .procname = "audit_argv_kb", 396 - .data = &audit_argv_kb, 397 - .maxlen = sizeof(int), 398 - .mode = 0644, 399 - .proc_handler = &proc_dointvec, 400 - }, 401 - #endif 402 393 { 403 394 .ctl_name = KERN_CORE_PATTERN, 404 395 .procname = "core_pattern",