diff options
Diffstat (limited to 'kernel/auditsc.c')
| -rw-r--r-- | kernel/auditsc.c | 205 |
1 files changed, 165 insertions, 40 deletions
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; |
