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", |
