[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 resume it if we have a value of 3 or more percent; consider information about 1135 the amount of free space valid for 30 seconds 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 ctrl-alt-del 1145 ------------ 1146
··· 1134 resume it if we have a value of 3 or more percent; consider information about 1135 the amount of free space valid for 30 seconds 1136 1137 ctrl-alt-del 1138 ------------ 1139
+4 -2
include/linux/audit.h
··· 525 extern void audit_log_hex(struct audit_buffer *ab, 526 const unsigned char *buf, 527 size_t len); 528 - extern const char * audit_log_untrustedstring(struct audit_buffer *ab, 529 const char *string); 530 - extern const char * audit_log_n_untrustedstring(struct audit_buffer *ab, 531 size_t n, 532 const char *string); 533 extern void audit_log_d_path(struct audit_buffer *ab,
··· 525 extern void audit_log_hex(struct audit_buffer *ab, 526 const unsigned char *buf, 527 size_t len); 528 + extern int audit_string_contains_control(const char *string, 529 + size_t len); 530 + extern void audit_log_untrustedstring(struct audit_buffer *ab, 531 const char *string); 532 + extern void audit_log_n_untrustedstring(struct audit_buffer *ab, 533 size_t n, 534 const char *string); 535 extern void audit_log_d_path(struct audit_buffer *ab,
+23 -14
kernel/audit.c
··· 1350 } 1351 1352 /** 1353 * audit_log_n_untrustedstring - log a string that may contain random characters 1354 * @ab: audit_buffer 1355 * @len: lenth of string (not including trailing null) ··· 1378 * The caller specifies the number of characters in the string to log, which may 1379 * or may not be the entire string. 1380 */ 1381 - const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, 1382 - const char *string) 1383 { 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; 1394 } 1395 1396 /** ··· 1395 * Same as audit_log_n_untrustedstring(), except that strlen is used to 1396 * determine string length. 1397 */ 1398 - const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string) 1399 { 1400 - return audit_log_n_untrustedstring(ab, strlen(string), string); 1401 } 1402 1403 /* This is a helper-function to print the escaped d_path */
··· 1350 } 1351 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 + /** 1368 * audit_log_n_untrustedstring - log a string that may contain random characters 1369 * @ab: audit_buffer 1370 * @len: lenth of string (not including trailing null) ··· 1363 * The caller specifies the number of characters in the string to log, which may 1364 * or may not be the entire string. 1365 */ 1366 + void audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, 1367 + const char *string) 1368 { 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); 1373 } 1374 1375 /** ··· 1386 * Same as audit_log_n_untrustedstring(), except that strlen is used to 1387 * determine string length. 1388 */ 1389 + void audit_log_untrustedstring(struct audit_buffer *ab, const char *string) 1390 { 1391 + audit_log_n_untrustedstring(ab, strlen(string), string); 1392 } 1393 1394 /* This is a helper-function to print the escaped d_path */
+169 -44
kernel/auditsc.c
··· 78 /* Indicates that audit should log the full pathname. */ 79 #define AUDIT_NAME_FULL -1 80 81 /* number of audit rules */ 82 int audit_n_rules; 83 ··· 968 return rc; 969 } 970 971 - static void audit_log_execve_info(struct audit_buffer *ab, 972 - struct audit_aux_data_execve *axi) 973 { 974 - int i; 975 - long len, ret; 976 - const char __user *p; 977 - char *buf; 978 979 - if (axi->mm != current->mm) 980 - return; /* execve failed, no additional info */ 981 982 - p = (const char __user *)axi->mm->arg_start; 983 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); 1004 /* 1005 * There is no reason for this copy to be short. We just 1006 * copied them here, and the mm hasn't been exposed to user- ··· 1025 WARN_ON(1); 1026 send_sig(SIGKILL, current, 0); 1027 } 1028 1029 - audit_log_format(ab, "a%d=", i); 1030 - audit_log_untrustedstring(ab, buf); 1031 - audit_log_format(ab, "\n"); 1032 1033 - kfree(buf); 1034 } 1035 } 1036 1037 static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) ··· 1292 1293 case AUDIT_EXECVE: { 1294 struct audit_aux_data_execve *axi = (void *)aux; 1295 - audit_log_execve_info(ab, axi); 1296 break; } 1297 1298 case AUDIT_SOCKETCALL: { ··· 2229 return 0; 2230 } 2231 2232 - int audit_argv_kb = 32; 2233 - 2234 int audit_bprm(struct linux_binprm *bprm) 2235 { 2236 struct audit_aux_data_execve *ax; ··· 2236 2237 if (likely(!audit_enabled || !context || context->dummy)) 2238 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 2248 ax = kmalloc(sizeof(*ax), GFP_KERNEL); 2249 if (!ax)
··· 78 /* Indicates that audit should log the full pathname. */ 79 #define AUDIT_NAME_FULL -1 80 81 + /* no execve audit message should be longer than this (userspace limits) */ 82 + #define MAX_EXECVE_AUDIT_LEN 7500 83 + 84 /* number of audit rules */ 85 int audit_n_rules; 86 ··· 965 return rc; 966 } 967 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) 985 { 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; 994 995 + /* strnlen_user includes the null we don't want to send */ 996 + len_left = len = strnlen_user(p, MAX_ARG_STRLEN) - 1; 997 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 + } 1008 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); 1016 /* 1017 * There is no reason for this copy to be short. We just 1018 * copied them here, and the mm hasn't been exposed to user- ··· 1007 WARN_ON(1); 1008 send_sig(SIGKILL, current, 0); 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); 1023 1024 + len_left = len; 1025 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; 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); 1134 } 1135 1136 static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) ··· 1157 1158 case AUDIT_EXECVE: { 1159 struct audit_aux_data_execve *axi = (void *)aux; 1160 + audit_log_execve_info(context, &ab, axi); 1161 break; } 1162 1163 case AUDIT_SOCKETCALL: { ··· 2094 return 0; 2095 } 2096 2097 int audit_bprm(struct linux_binprm *bprm) 2098 { 2099 struct audit_aux_data_execve *ax; ··· 2103 2104 if (likely(!audit_enabled || !context || context->dummy)) 2105 return 0; 2106 2107 ax = kmalloc(sizeof(*ax), GFP_KERNEL); 2108 if (!ax)
-11
kernel/sysctl.c
··· 81 extern int compat_log; 82 extern int maps_protect; 83 extern int sysctl_stat_interval; 84 - extern int audit_argv_kb; 85 extern int latencytop_enabled; 86 87 /* Constants used for minimum and maximum */ ··· 389 .mode = 0644, 390 .proc_handler = &proc_dointvec, 391 }, 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 { 403 .ctl_name = KERN_CORE_PATTERN, 404 .procname = "core_pattern",
··· 81 extern int compat_log; 82 extern int maps_protect; 83 extern int sysctl_stat_interval; 84 extern int latencytop_enabled; 85 86 /* Constants used for minimum and maximum */ ··· 390 .mode = 0644, 391 .proc_handler = &proc_dointvec, 392 }, 393 { 394 .ctl_name = KERN_CORE_PATTERN, 395 .procname = "core_pattern",