• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/core


Commit MetaInfo

修訂ac3ca99b77c4944333649dda4670d509f9facc05 (tree)
時間2019-04-10 12:54:47
作者Nick Kralevich <nnk@goog...>
CommiterNick Kralevich

Log Message

introduce auditctl and use it to configure SELinux throttling

In an effort to ensure that our development community does not
introduce new code without corresponding SELinux changes, Android
closely monitors the number of SELinux denials which occur during
boot. This monitoring occurs both in treehugger, as well as various
dashboards. If SELinux denials are dropped during early boot, this
could result in non-determinism for the various SELinux treehugger
tests.

Introduce /system/bin/auditctl. This tool, model after
https://linux.die.net/man/8/auditctl , allows for configuring the
throttling rate for the kernel auditing system.

Remove any throttling from early boot. This will hopefully reduce
treehugger flakiness by making denial generation more predictible
during early boot.

Reapply the throttling at boot complete, to avoid denial of service
attacks against the auditing subsystem.

Delete pre-existing unittests for logd / SELinux integration. It's
intended that all throttling decisions be made in the kernel, and
shouldn't be a concern of logd.

Bug: 118815957
Test: Perform an operation which generates lots of SELinux denials,

and count how many occur before and after the time period.

(cherry picked from commit be5e44679146d333c20e28bf99c52d168f422626)

Change-Id: I283cd56151d199cd66f0d217b49115460c4a01e5

Change Summary

差異

--- a/logd/Android.bp
+++ b/logd/Android.bp
@@ -80,6 +80,24 @@ cc_binary {
8080 cflags: ["-Werror"],
8181 }
8282
83+cc_binary {
84+ name: "auditctl",
85+
86+ srcs: ["auditctl.cpp"],
87+
88+ static_libs: [
89+ "liblogd",
90+ ],
91+
92+ shared_libs: ["libbase"],
93+
94+ cflags: [
95+ "-Wall",
96+ "-Wextra",
97+ "-Werror",
98+ "-Wconversion"
99+ ],
100+}
83101
84102 prebuilt_etc {
85103 name: "logtagd.rc",
--- /dev/null
+++ b/logd/auditctl.cpp
@@ -0,0 +1,74 @@
1+/*
2+ * Copyright (C) 2019 The Android Open Source Project
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+#include <android-base/parseint.h>
18+#include <error.h>
19+#include <stdio.h>
20+#include <stdlib.h>
21+#include <unistd.h>
22+#include "libaudit.h"
23+
24+static void usage(const char* cmdline) {
25+ fprintf(stderr, "Usage: %s [-r rate]\n", cmdline);
26+}
27+
28+static void do_update_rate(uint32_t rate) {
29+ int fd = audit_open();
30+ if (fd == -1) {
31+ error(EXIT_FAILURE, errno, "Unable to open audit socket");
32+ }
33+ int result = audit_rate_limit(fd, rate);
34+ close(fd);
35+ if (result < 0) {
36+ fprintf(stderr, "Can't update audit rate limit: %d\n", result);
37+ exit(EXIT_FAILURE);
38+ }
39+}
40+
41+int main(int argc, char* argv[]) {
42+ uint32_t rate = 0;
43+ bool update_rate = false;
44+ int opt;
45+
46+ while ((opt = getopt(argc, argv, "r:")) != -1) {
47+ switch (opt) {
48+ case 'r':
49+ if (!android::base::ParseUint<uint32_t>(optarg, &rate)) {
50+ error(EXIT_FAILURE, errno, "Invalid Rate");
51+ }
52+ update_rate = true;
53+ break;
54+ default: /* '?' */
55+ usage(argv[0]);
56+ exit(EXIT_FAILURE);
57+ }
58+ }
59+
60+ // In the future, we may add other options to auditctl
61+ // so this if statement will expand.
62+ // if (!update_rate && !update_backlog && !update_whatever) ...
63+ if (!update_rate) {
64+ fprintf(stderr, "Nothing to do\n");
65+ usage(argv[0]);
66+ exit(EXIT_FAILURE);
67+ }
68+
69+ if (update_rate) {
70+ do_update_rate(rate);
71+ }
72+
73+ return 0;
74+}
--- a/logd/libaudit.c
+++ b/logd/libaudit.c
@@ -160,8 +160,7 @@ int audit_setup(int fd, pid_t pid) {
160160 * and the the mask set to AUDIT_STATUS_PID
161161 */
162162 status.pid = pid;
163- status.mask = AUDIT_STATUS_PID | AUDIT_STATUS_RATE_LIMIT;
164- status.rate_limit = AUDIT_RATE_LIMIT; /* audit entries per second */
163+ status.mask = AUDIT_STATUS_PID;
165164
166165 /* Let the kernel know this pid will be registering for audit events */
167166 rc = audit_send(fd, AUDIT_SET, &status, sizeof(status));
@@ -188,6 +187,14 @@ int audit_open() {
188187 return socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_AUDIT);
189188 }
190189
190+int audit_rate_limit(int fd, uint32_t limit) {
191+ struct audit_status status;
192+ memset(&status, 0, sizeof(status));
193+ status.mask = AUDIT_STATUS_RATE_LIMIT;
194+ status.rate_limit = limit; /* audit entries per second */
195+ return audit_send(fd, AUDIT_SET, &status, sizeof(status));
196+}
197+
191198 int audit_get_reply(int fd, struct audit_message* rep, reply_t block, int peek) {
192199 ssize_t len;
193200 int flags;
--- a/logd/libaudit.h
+++ b/logd/libaudit.h
@@ -89,8 +89,17 @@ extern int audit_get_reply(int fd, struct audit_message* rep, reply_t block,
8989 */
9090 extern int audit_setup(int fd, pid_t pid);
9191
92-/* Max audit messages per second */
93-#define AUDIT_RATE_LIMIT 5
92+/**
93+ * Throttle kernel messages at the provided rate
94+ * @param fd
95+ * The fd returned by a call to audit_open()
96+ * @param rate
97+ * The rate, in messages per second, above which the kernel
98+ * should drop audit messages.
99+ * @return
100+ * This function returns 0 on success, -errno on error.
101+ */
102+extern int audit_rate_limit(int fd, uint32_t limit);
94103
95104 __END_DECLS
96105
--- a/logd/logd.rc
+++ b/logd/logd.rc
@@ -16,8 +16,19 @@ service logd-reinit /system/bin/logd --reinit
1616 group logd
1717 writepid /dev/cpuset/system-background/tasks
1818
19+# Limit SELinux denial generation to 5/second
20+service logd-auditctl /system/bin/auditctl -r 5
21+ oneshot
22+ disabled
23+ user logd
24+ group logd
25+ capabilities AUDIT_CONTROL
26+
1927 on fs
2028 write /dev/event-log-tags "# content owned by logd
2129 "
2230 chown logd logd /dev/event-log-tags
2331 chmod 0644 /dev/event-log-tags
32+
33+on property:sys.boot_completed=1
34+ start logd-auditctl
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -39,7 +39,6 @@
3939 #endif
4040
4141 #include "../LogReader.h" // pickup LOGD_SNDTIMEO
42-#include "../libaudit.h" // pickup AUDIT_RATE_LIMIT_*
4342
4443 #ifdef __ANDROID__
4544 static void send_to_control(char* buf, size_t len) {
@@ -1065,145 +1064,3 @@ TEST(logd, multiple_test_3) {
10651064 TEST(logd, multiple_test_10) {
10661065 __android_log_btwrite_multiple__helper(10);
10671066 }
1068-
1069-#ifdef __ANDROID__
1070-// returns violating pid
1071-static pid_t sepolicy_rate(unsigned rate, unsigned num) {
1072- pid_t pid = fork();
1073-
1074- if (pid) {
1075- siginfo_t info = {};
1076- if (TEMP_FAILURE_RETRY(waitid(P_PID, pid, &info, WEXITED))) return -1;
1077- if (info.si_status) return -1;
1078- return pid;
1079- }
1080-
1081- // We may have DAC, but let's not have MAC
1082- if ((setcon("u:object_r:shell:s0") < 0) && (setcon("u:r:shell:s0") < 0)) {
1083- int save_errno = errno;
1084- security_context_t context;
1085- getcon(&context);
1086- if (strcmp(context, "u:r:shell:s0")) {
1087- fprintf(stderr, "setcon(\"u:r:shell:s0\") failed @\"%s\" %s\n",
1088- context, strerror(save_errno));
1089- freecon(context);
1090- _exit(-1);
1091- // NOTREACHED
1092- return -1;
1093- }
1094- }
1095-
1096- // The key here is we are root, but we are in u:r:shell:s0,
1097- // and the directory does not provide us DAC access
1098- // (eg: 0700 system system) so we trigger the pair dac_override
1099- // and dac_read_search on every try to get past the message
1100- // de-duper. We will also rotate the file name in the directory
1101- // as another measure.
1102- static const char file[] = "/data/drm/cannot_access_directory_%u";
1103- static const unsigned avc_requests_per_access = 2;
1104-
1105- rate /= avc_requests_per_access;
1106- useconds_t usec;
1107- if (rate == 0) {
1108- rate = 1;
1109- usec = 2000000;
1110- } else {
1111- usec = (1000000 + (rate / 2)) / rate;
1112- }
1113- num = (num + (avc_requests_per_access / 2)) / avc_requests_per_access;
1114-
1115- if (usec < 2) usec = 2;
1116-
1117- while (num > 0) {
1118- if (access(android::base::StringPrintf(file, num).c_str(), F_OK) == 0) {
1119- _exit(-1);
1120- // NOTREACHED
1121- return -1;
1122- }
1123- usleep(usec);
1124- --num;
1125- }
1126- _exit(0);
1127- // NOTREACHED
1128- return -1;
1129-}
1130-
1131-static constexpr int background_period = 10;
1132-
1133-static int count_avc(pid_t pid) {
1134- int count = 0;
1135-
1136- // pid=-1 skip as pid is in error
1137- if (pid == (pid_t)-1) return count;
1138-
1139- // pid=0 means we want to report the background count of avc: activities
1140- struct logger_list* logger_list =
1141- pid ? android_logger_list_alloc(
1142- ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, pid)
1143- : android_logger_list_alloc_time(
1144- ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
1145- log_time(android_log_clockid()) -
1146- log_time(background_period, 0),
1147- 0);
1148- if (!logger_list) return count;
1149- struct logger* logger = android_logger_open(logger_list, LOG_ID_EVENTS);
1150- if (!logger) {
1151- android_logger_list_close(logger_list);
1152- return count;
1153- }
1154- for (;;) {
1155- log_msg log_msg;
1156-
1157- if (android_logger_list_read(logger_list, &log_msg) <= 0) break;
1158-
1159- if ((log_msg.entry.pid != pid) || (log_msg.entry.len < (4 + 1 + 8)) ||
1160- (log_msg.id() != LOG_ID_EVENTS))
1161- continue;
1162-
1163- char* eventData = log_msg.msg();
1164- if (!eventData) continue;
1165-
1166- uint32_t tag = get4LE(eventData);
1167- if (tag != AUDITD_LOG_TAG) continue;
1168-
1169- if (eventData[4] != EVENT_TYPE_STRING) continue;
1170-
1171- // int len = get4LE(eventData + 4 + 1);
1172- log_msg.buf[LOGGER_ENTRY_MAX_LEN] = '\0';
1173- const char* cp = strstr(eventData + 4 + 1 + 4, "): avc: denied");
1174- if (!cp) continue;
1175-
1176- ++count;
1177- }
1178-
1179- android_logger_list_close(logger_list);
1180-
1181- return count;
1182-}
1183-#endif
1184-
1185-TEST(logd, sepolicy_rate_limiter) {
1186-#ifdef __ANDROID__
1187- int background_selinux_activity_too_high = count_avc(0);
1188- if (background_selinux_activity_too_high > 2) {
1189- GTEST_LOG_(ERROR) << "Too much background selinux activity "
1190- << background_selinux_activity_too_high * 60 /
1191- background_period
1192- << "/minute on the device, this test\n"
1193- << "can not measure the functionality of the "
1194- << "sepolicy rate limiter. Expect test to\n"
1195- << "fail as this device is in a bad state, "
1196- << "but is not strictly a unit test failure.";
1197- }
1198-
1199- static const int rate = AUDIT_RATE_LIMIT;
1200- static const int duration = 2;
1201- // Two seconds of sustained denials. Depending on the overlap in the time
1202- // window that the kernel is considering vs what this test is considering,
1203- // allow some additional denials to prevent a flaky test.
1204- EXPECT_LE(count_avc(sepolicy_rate(rate, rate * duration)),
1205- rate * duration + rate);
1206-#else
1207- GTEST_LOG_(INFO) << "This test does nothing.\n";
1208-#endif
1209-}
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -10,6 +10,7 @@ phony {
1010 phony {
1111 name: "shell_and_utilities_system",
1212 required: [
13+ "auditctl",
1314 "awk",
1415 "bzip2",
1516 "grep",