Commit de6bbd1d30e5912620d25dd15e3f180ac7f9fcef

Authored by Eric Paris
Committed by Al Viro
1 parent e445deb593

[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>

Showing 5 changed files with 192 additions and 74 deletions Side-by-side Diff

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