diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/audit.c | 37 | ||||
-rw-r--r-- | kernel/auditsc.c | 205 | ||||
-rw-r--r-- | kernel/sysctl.c | 11 |
3 files changed, 188 insertions, 65 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index cf6698289426..26ff925e13f2 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -1350,6 +1350,21 @@ static void audit_log_n_string(struct audit_buffer *ab, size_t slen, | |||
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 | * audit_log_n_untrustedstring - log a string that may contain random characters | 1368 | * audit_log_n_untrustedstring - log a string that may contain random characters |
1354 | * @ab: audit_buffer | 1369 | * @ab: audit_buffer |
1355 | * @len: lenth of string (not including trailing null) | 1370 | * @len: lenth of string (not including trailing null) |
@@ -1363,19 +1378,13 @@ static void audit_log_n_string(struct audit_buffer *ab, size_t slen, | |||
1363 | * The caller specifies the number of characters in the string to log, which may | 1378 | * The caller specifies the number of characters in the string to log, which may |
1364 | * or may not be the entire string. | 1379 | * or may not be the entire string. |
1365 | */ | 1380 | */ |
1366 | const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, | 1381 | void audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, |
1367 | const char *string) | 1382 | const char *string) |
1368 | { | 1383 | { |
1369 | const unsigned char *p; | 1384 | if (audit_string_contains_control(string, len)) |
1370 | 1385 | audit_log_hex(ab, string, len); | |
1371 | for (p = string; p < (const unsigned char *)string + len && *p; p++) { | 1386 | else |
1372 | if (*p == '"' || *p < 0x21 || *p > 0x7f) { | 1387 | audit_log_n_string(ab, len, string); |
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; | ||
1379 | } | 1388 | } |
1380 | 1389 | ||
1381 | /** | 1390 | /** |
@@ -1386,9 +1395,9 @@ const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, | |||
1386 | * Same as audit_log_n_untrustedstring(), except that strlen is used to | 1395 | * Same as audit_log_n_untrustedstring(), except that strlen is used to |
1387 | * determine string length. | 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 | /* This is a helper-function to print the escaped d_path */ | 1403 | /* This is a helper-function to print the escaped d_path */ |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index aaaca8a13bbe..6e03322e155b 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -78,6 +78,9 @@ extern struct list_head audit_filter_list[]; | |||
78 | /* Indicates that audit should log the full pathname. */ | 78 | /* Indicates that audit should log the full pathname. */ |
79 | #define AUDIT_NAME_FULL -1 | 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 | /* number of audit rules */ | 84 | /* number of audit rules */ |
82 | int audit_n_rules; | 85 | int audit_n_rules; |
83 | 86 | ||
@@ -965,55 +968,187 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid, | |||
965 | return rc; | 968 | return rc; |
966 | } | 969 | } |
967 | 970 | ||
968 | static void audit_log_execve_info(struct audit_buffer *ab, | 971 | /* |
969 | struct audit_aux_data_execve *axi) | 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; | 989 | char arg_num_len_buf[12]; |
972 | long len, ret; | 990 | const char __user *tmp_p = p; |
973 | const char __user *p; | 991 | /* how many digits are in arg_num? 3 is the length of a=\n */ |
974 | char *buf; | 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; | ||
997 | |||
998 | /* strnlen_user includes the null we don't want to send */ | ||
999 | len_left = len = strnlen_user(p, MAX_ARG_STRLEN) - 1; | ||
975 | 1000 | ||
976 | if (axi->mm != current->mm) | 1001 | /* |
977 | return; /* execve failed, no additional info */ | 1002 | * We just created this mm, if we can't find the strings |
978 | 1003 | * we just copied into it something is _very_ wrong. Similar | |
979 | p = (const char __user *)axi->mm->arg_start; | 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) { | 1012 | /* walk the whole argument looking for non-ascii chars */ |
982 | len = strnlen_user(p, MAX_ARG_STRLEN); | 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 | 1020 | * There is no reason for this copy to be short. We just |
985 | * we just copied into it something is _very_ wrong. Similar | 1021 | * copied them here, and the mm hasn't been exposed to user- |
986 | * for strings that are too long, we should not have created | 1022 | * space yet. |
987 | * any. | ||
988 | */ | 1023 | */ |
989 | if (!len || len > MAX_ARG_STRLEN) { | 1024 | if (ret) { |
990 | WARN_ON(1); | 1025 | WARN_ON(1); |
991 | send_sig(SIGKILL, current, 0); | 1026 | send_sig(SIGKILL, current, 0); |
992 | } | 1027 | } |
993 | 1028 | buf[to_send] = '\0'; | |
994 | buf = kmalloc(len, GFP_KERNEL); | 1029 | has_cntl = audit_string_contains_control(buf, to_send); |
995 | if (!buf) { | 1030 | if (has_cntl) { |
996 | audit_panic("out of memory for argv string\n"); | 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 | break; | 1036 | break; |
998 | } | 1037 | } |
1038 | len_left -= to_send; | ||
1039 | tmp_p += to_send; | ||
1040 | } while (len_left > 0); | ||
1041 | |||
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 | } | ||
999 | 1069 | ||
1000 | ret = copy_from_user(buf, p, len); | ||
1001 | /* | 1070 | /* |
1002 | * There is no reason for this copy to be short. We just | 1071 | * first record needs to say how long the original string was |
1003 | * copied them here, and the mm hasn't been exposed to user- | 1072 | * so we can be sure nothing was lost. |
1004 | * space yet. | 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 | ||
1005 | */ | 1082 | */ |
1083 | if (len >= max_execve_audit_len) | ||
1084 | ret = copy_from_user(buf, p, to_send); | ||
1085 | else | ||
1086 | ret = 0; | ||
1006 | if (ret) { | 1087 | if (ret) { |
1007 | WARN_ON(1); | 1088 | WARN_ON(1); |
1008 | send_sig(SIGKILL, current, 0); | 1089 | send_sig(SIGKILL, current, 0); |
1009 | } | 1090 | } |
1091 | buf[to_send] = '\0'; | ||
1092 | |||
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"); | ||
1103 | |||
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; | ||
1111 | } | ||
1112 | /* include the null we didn't log */ | ||
1113 | return len + 1; | ||
1114 | } | ||
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; | ||
1010 | 1124 | ||
1011 | audit_log_format(ab, "a%d=", i); | 1125 | if (axi->mm != current->mm) |
1012 | audit_log_untrustedstring(ab, buf); | 1126 | return; /* execve failed, no additional info */ |
1013 | audit_log_format(ab, "\n"); | 1127 | |
1128 | p = (const char __user *)axi->mm->arg_start; | ||
1014 | 1129 | ||
1015 | kfree(buf); | 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; | ||
1016 | } | 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); | ||
1017 | } | 1152 | } |
1018 | 1153 | ||
1019 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) | 1154 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) |
@@ -1157,7 +1292,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
1157 | 1292 | ||
1158 | case AUDIT_EXECVE: { | 1293 | case AUDIT_EXECVE: { |
1159 | struct audit_aux_data_execve *axi = (void *)aux; | 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 | break; } | 1296 | break; } |
1162 | 1297 | ||
1163 | case AUDIT_SOCKETCALL: { | 1298 | case AUDIT_SOCKETCALL: { |
@@ -2094,8 +2229,6 @@ int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode | |||
2094 | return 0; | 2229 | return 0; |
2095 | } | 2230 | } |
2096 | 2231 | ||
2097 | int audit_argv_kb = 32; | ||
2098 | |||
2099 | int audit_bprm(struct linux_binprm *bprm) | 2232 | int audit_bprm(struct linux_binprm *bprm) |
2100 | { | 2233 | { |
2101 | struct audit_aux_data_execve *ax; | 2234 | struct audit_aux_data_execve *ax; |
@@ -2104,14 +2237,6 @@ int audit_bprm(struct linux_binprm *bprm) | |||
2104 | if (likely(!audit_enabled || !context || context->dummy)) | 2237 | if (likely(!audit_enabled || !context || context->dummy)) |
2105 | return 0; | 2238 | return 0; |
2106 | 2239 | ||
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 | |||
2115 | ax = kmalloc(sizeof(*ax), GFP_KERNEL); | 2240 | ax = kmalloc(sizeof(*ax), GFP_KERNEL); |
2116 | if (!ax) | 2241 | if (!ax) |
2117 | return -ENOMEM; | 2242 | return -ENOMEM; |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 357b68ba23ec..7cb1ac3e6fff 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -81,7 +81,6 @@ extern int percpu_pagelist_fraction; | |||
81 | extern int compat_log; | 81 | extern int compat_log; |
82 | extern int maps_protect; | 82 | extern int maps_protect; |
83 | extern int sysctl_stat_interval; | 83 | extern int sysctl_stat_interval; |
84 | extern int audit_argv_kb; | ||
85 | extern int latencytop_enabled; | 84 | extern int latencytop_enabled; |
86 | 85 | ||
87 | /* Constants used for minimum and maximum */ | 86 | /* Constants used for minimum and maximum */ |
@@ -390,16 +389,6 @@ static struct ctl_table kern_table[] = { | |||
390 | .mode = 0644, | 389 | .mode = 0644, |
391 | .proc_handler = &proc_dointvec, | 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 | .ctl_name = KERN_CORE_PATTERN, | 393 | .ctl_name = KERN_CORE_PATTERN, |
405 | .procname = "core_pattern", | 394 | .procname = "core_pattern", |