Merge "Revert "Delay initial accept() until server initialized""
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 375207b..51d5755 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -22,6 +22,9 @@
"name": "libpackagelistparser_test"
},
{
+ "name": "libcutils_test"
+ },
+ {
"name": "libprocinfo_test"
},
{
diff --git a/adb/SOCKET-ACTIVATION.txt b/adb/SOCKET-ACTIVATION.txt
deleted file mode 100644
index 4ef62ac..0000000
--- a/adb/SOCKET-ACTIVATION.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-adb can be configured to work with systemd-style socket activation,
-allowing the daemon to start automatically when the adb control port
-is forwarded across a network. You need two files, placed in the usual
-systemd service directories (e.g., ~/.config/systemd/user for a user
-service).
-
-adb.service:
-
---- START adb.service CUT HERE ---
-[Unit]
-Description=adb
-After=adb.socket
-Requires=adb.socket
-[Service]
-Type=simple
-# FD 3 is part of the systemd interface
-ExecStart=/path/to/adb server nodaemon -L acceptfd:3
---- END adb.service CUT HERE ---
-
---- START adb.socket CUT HERE ---
-[Unit]
-Description=adb
-PartOf=adb.service
-[Socket]
-ListenStream=127.0.0.1:5037
-Accept=no
-[Install]
-WantedBy=sockets.target
---- END adb.socket CUT HERE ---
-
-After installing the adb service, the adb server will be started
-automatically on any connection to 127.0.0.1:5037 (the default adb
-control port), even after adb kill-server kills the server.
-
-Other "superserver" launcher systems (like macOS launchd) can be
-configured analogously. The important part is that adb be started with
-"server" and "nodaemon" command line arguments and that the listen
-address (passed to -L) name a file descriptor that's ready to
-accept(2) connections and that's already bound to the desired address
-and listening. inetd-style pre-accepted sockets do _not_ work in this
-configuration: the file descriptor passed to acceptfd must be the
-serve socket, not the accepted connection socket.
diff --git a/adb/client/adb_client.cpp b/adb/client/adb_client.cpp
index f724cb5..d91ae35 100644
--- a/adb/client/adb_client.cpp
+++ b/adb/client/adb_client.cpp
@@ -222,7 +222,7 @@
int port;
std::string error;
if (!parse_tcp_socket_spec(__adb_server_socket_spec, nullptr, &port, nullptr, &error)) {
- return {};
+ LOG(FATAL) << "failed to parse server socket spec: " << error;
}
return adb_get_android_dir_path() + OS_PATH_SEPARATOR + "adb." + std::to_string(port);
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 6465ffe..0ffdbc2 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -107,7 +107,6 @@
" localfilesystem:<unix domain socket name>\n"
" dev:<character device name>\n"
" jdwp:<process pid> (remote only)\n"
- " acceptfd:<fd> (listen only)\n"
" forward --remove LOCAL remove specific forward socket connection\n"
" forward --remove-all remove all forward socket connections\n"
" ppp TTY [PARAMETER...] run PPP over USB\n"
diff --git a/adb/client/fastdeploy.cpp b/adb/client/fastdeploy.cpp
index bdc9e56..5fa0edb 100644
--- a/adb/client/fastdeploy.cpp
+++ b/adb/client/fastdeploy.cpp
@@ -101,17 +101,12 @@
static void push_to_device(const void* data, size_t byte_count, const char* dst, bool sync) {
std::vector<const char*> srcs;
- {
- TemporaryFile temp;
- android::base::WriteFully(temp.fd, data, byte_count);
- srcs.push_back(temp.path);
-
- // On Windows, the file needs to be flushed before pushing to device.
- // closing the file flushes its content, but we still need to remove it after push.
- // FileDeleter does exactly that.
- temp.DoNotRemove();
- }
- FileDeleter temp_deleter(srcs.back());
+ TemporaryFile tf;
+ android::base::WriteFully(tf.fd, data, byte_count);
+ srcs.push_back(tf.path);
+ // On Windows, the file needs to be flushed before pushing to device,
+ // but can't be removed until after the push.
+ unix_close(tf.release());
if (!do_sync_push(srcs, dst, sync)) {
error_exit("Failed to push fastdeploy agent to device.");
diff --git a/adb/fastdeploy/deployagent/test/com/android/fastdeploy/FastDeployTest.java b/adb/fastdeploy/deployagent/test/com/android/fastdeploy/FastDeployTest.java
index ef6ccae..4aa2f79 100644
--- a/adb/fastdeploy/deployagent/test/com/android/fastdeploy/FastDeployTest.java
+++ b/adb/fastdeploy/deployagent/test/com/android/fastdeploy/FastDeployTest.java
@@ -20,7 +20,9 @@
import static org.junit.Assert.assertTrue;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -68,17 +70,19 @@
}
private boolean isAppInstalled(String packageName) throws DeviceNotAvailableException {
- final String commandResult = getDevice().executeShellCommand("pm list packages");
+ final String result = getDevice().executeShellCommand("pm list packages");
+ CLog.logAndDisplay(LogLevel.INFO, result);
final int prefixLength = "package:".length();
- return Arrays.stream(commandResult.split("\\r?\\n"))
+ return Arrays.stream(result.split("\\r?\\n"))
.anyMatch(line -> line.substring(prefixLength).equals(packageName));
}
// Mostly copied from PkgInstallSignatureVerificationTest.java.
- private String fastInstallPackage(String apkPath)
+ private void fastInstallPackage(String apkPath)
throws IOException, DeviceNotAvailableException {
- return getDevice().executeAdbCommand("install", "-t", "--fastdeploy", "--force-agent",
+ String result = getDevice().executeAdbCommand("install", "-t", "--fastdeploy", "--force-agent",
apkPath);
+ CLog.logAndDisplay(LogLevel.INFO, result);
}
}
diff --git a/adb/socket_spec.cpp b/adb/socket_spec.cpp
index e5129e6..98468b5 100644
--- a/adb/socket_spec.cpp
+++ b/adb/socket_spec.cpp
@@ -16,7 +16,6 @@
#include "socket_spec.h"
-#include <limits>
#include <string>
#include <string_view>
#include <unordered_map>
@@ -29,12 +28,10 @@
#include <cutils/sockets.h>
#include "adb.h"
-#include "adb_utils.h"
#include "sysdeps.h"
using namespace std::string_literals;
-using android::base::ConsumePrefix;
using android::base::StringPrintf;
#if defined(__linux__)
@@ -134,7 +131,7 @@
return true;
}
}
- return spec.starts_with("tcp:") || spec.starts_with("acceptfd:");
+ return spec.starts_with("tcp:");
}
bool is_local_socket_spec(std::string_view spec) {
@@ -238,9 +235,6 @@
*error = "vsock is only supported on linux";
return false;
#endif // ADB_LINUX
- } else if (address.starts_with("acceptfd:")) {
- *error = "cannot connect to acceptfd";
- return false;
}
for (const auto& it : kLocalSocketTypes) {
@@ -338,46 +332,6 @@
*error = "vsock is only supported on linux";
return -1;
#endif // ADB_LINUX
- } else if (ConsumePrefix(&spec, "acceptfd:")) {
-#if ADB_WINDOWS
- *error = "socket activation not supported under Windows";
- return -1;
-#else
- // We inherited the socket from some kind of launcher. It's already bound and
- // listening. Return a copy of the FD instead of the FD itself so we implement the
- // normal "listen" contract and can succeed more than once.
- unsigned int fd_u;
- if (!ParseUint(&fd_u, spec) || fd_u > std::numeric_limits<int>::max()) {
- *error = "invalid fd";
- return -1;
- }
- int fd = static_cast<int>(fd_u);
- int flags = get_fd_flags(fd);
- if (flags < 0) {
- *error = android::base::StringPrintf("could not get flags of inherited fd %d: '%s'", fd,
- strerror(errno));
- return -1;
- }
- if (flags & O_CLOEXEC) {
- *error = android::base::StringPrintf("fd %d was not inherited from parent", fd);
- return -1;
- }
-
- int dummy_sock_type;
- socklen_t dummy_sock_type_size = sizeof(dummy_sock_type);
- if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &dummy_sock_type, &dummy_sock_type_size)) {
- *error = android::base::StringPrintf("fd %d does not refer to a socket", fd);
- return -1;
- }
-
- int new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
- if (new_fd < 0) {
- *error = android::base::StringPrintf("could not dup inherited fd %d: '%s'", fd,
- strerror(errno));
- return -1;
- }
- return new_fd;
-#endif
}
for (const auto& it : kLocalSocketTypes) {
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 979413a..466c2ce 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -349,15 +349,8 @@
return c == '/';
}
-static __inline__ int get_fd_flags(borrowed_fd fd) {
- return fcntl(fd.get(), F_GETFD);
-}
-
static __inline__ void close_on_exec(borrowed_fd fd) {
- int flags = get_fd_flags(fd);
- if (flags >= 0 && (flags & O_CLOEXEC) == 0) {
- fcntl(fd.get(), F_SETFD, flags | O_CLOEXEC);
- }
+ fcntl(fd.get(), F_SETFD, FD_CLOEXEC);
}
// Open a file and return a file descriptor that may be used with unix_read(),
diff --git a/base/README.md b/base/README.md
new file mode 100644
index 0000000..2ef5c10
--- /dev/null
+++ b/base/README.md
@@ -0,0 +1,42 @@
+# libbase
+
+## Who is this library for?
+
+This library is a collection of convenience functions to make common tasks
+easier and less error-prone.
+
+In this context, "error-prone" covers both "hard to do correctly" and
+"hard to do with good performance", but as a general purpose library,
+libbase's primary focus is on making it easier to do things easily and
+correctly when a compromise has to be made between "simplest API" on the
+one hand and "fastest implementation" on the other. Though obviously
+the ideal is to have both.
+
+## Should my routine be added?
+
+The intention is to cover the 80% use cases, not be all things to all users.
+
+If you have a routine that's really useful in your project,
+congratulations. But that doesn't mean it should be here rather than
+just in your project.
+
+The question for libbase is "should everyone be doing this?"/"does this
+make everyone's code cleaner/safer?". Historically we've considered the
+bar for inclusion to be "are there at least three *unrelated* projects
+that would be cleaned up by doing so".
+
+If your routine is actually something from a future C++ standard (that
+isn't yet in libc++), or it's widely used in another library, that helps
+show that there's precedent. Being able to say "so-and-so has used this
+API for n years" is a good way to reduce concerns about API choices.
+
+## Any other restrictions?
+
+Unlike most Android code, code in libbase has to build for Mac and
+Windows too.
+
+Code here is also expected to have good test coverage.
+
+By its nature, it's difficult to change libbase API. It's often best
+to start using your routine just in your project, and let it "graduate"
+after you're certain that the API is solid.
diff --git a/code_coverage/Android.mk b/code_coverage/Android.mk
new file mode 100644
index 0000000..80ab36b
--- /dev/null
+++ b/code_coverage/Android.mk
@@ -0,0 +1,37 @@
+# policies to allow processes inside minijail to dump code coverage information
+#
+
+LOCAL_PATH := $(call my-dir)
+
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := code_coverage.policy
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MULTILIB := both
+
+ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm arm64))
+LOCAL_MODULE_STEM_32 := code_coverage.arm.policy
+LOCAL_MODULE_STEM_64 := code_coverage.arm64.policy
+endif
+
+ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), x86 x86_64))
+LOCAL_MODULE_STEM_32 := code_coverage.x86.policy
+LOCAL_MODULE_STEM_64 := code_coverage.x86_64.policy
+endif
+
+# different files for different configurations
+ifeq ($(NATIVE_COVERAGE),true)
+LOCAL_SRC_FILES_arm := seccomp_policy/code_coverage.arm.policy
+LOCAL_SRC_FILES_arm64 := seccomp_policy/code_coverage.arm64.policy
+LOCAL_SRC_FILES_x86 := seccomp_policy/code_coverage.x86.policy
+LOCAL_SRC_FILES_x86_64 := seccomp_policy/code_coverage.x86_64.policy
+else
+LOCAL_SRC_FILES_arm := empty_policy/code_coverage.arm.policy
+LOCAL_SRC_FILES_arm64 := empty_policy/code_coverage.arm64.policy
+LOCAL_SRC_FILES_x86 := empty_policy/code_coverage.x86.policy
+LOCAL_SRC_FILES_x86_64 := empty_policy/code_coverage.x86_64.policy
+endif
+
+LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/seccomp_policy
+include $(BUILD_PREBUILT)
diff --git a/code_coverage/empty_policy/code_coverage.arm.policy b/code_coverage/empty_policy/code_coverage.arm.policy
new file mode 100644
index 0000000..4c9132b
--- /dev/null
+++ b/code_coverage/empty_policy/code_coverage.arm.policy
@@ -0,0 +1,2 @@
+# empty unless code_coverage is enabled.
+# code_coverage.arm.policy
diff --git a/code_coverage/empty_policy/code_coverage.arm64.policy b/code_coverage/empty_policy/code_coverage.arm64.policy
new file mode 100644
index 0000000..dc5c35a
--- /dev/null
+++ b/code_coverage/empty_policy/code_coverage.arm64.policy
@@ -0,0 +1,2 @@
+# empty unless code_coverage is enabled.
+# code_coverage.arm64.policy
diff --git a/code_coverage/empty_policy/code_coverage.x86.policy b/code_coverage/empty_policy/code_coverage.x86.policy
new file mode 100644
index 0000000..044f34c
--- /dev/null
+++ b/code_coverage/empty_policy/code_coverage.x86.policy
@@ -0,0 +1,2 @@
+# empty unless code_coverage is enabled.
+# code_coverage.x86.policy
diff --git a/code_coverage/empty_policy/code_coverage.x86_64.policy b/code_coverage/empty_policy/code_coverage.x86_64.policy
new file mode 100644
index 0000000..6dcd22d
--- /dev/null
+++ b/code_coverage/empty_policy/code_coverage.x86_64.policy
@@ -0,0 +1,2 @@
+# empty unless code_coverage is enabled.
+# code_coverage.x86_64.policy
diff --git a/code_coverage/seccomp_policy/code_coverage.arm.policy b/code_coverage/seccomp_policy/code_coverage.arm.policy
new file mode 100644
index 0000000..d6784e3
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.arm.policy
@@ -0,0 +1,14 @@
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+fcntl64: 1
+fstat64: 1
+geteuid32: 1
+_llseek: 1
+mmap2: 1
+sigreturn: 1
+gettimeofday: 1
+prctl: 1
diff --git a/code_coverage/seccomp_policy/code_coverage.arm64.policy b/code_coverage/seccomp_policy/code_coverage.arm64.policy
new file mode 100644
index 0000000..4c3dd26
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.arm64.policy
@@ -0,0 +1,13 @@
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+fcntl: 1
+fstat: 1
+geteuid: 1
+lseek: 1
+mmap: 1
+rt_sigreturn: 1
+prctl: 1
diff --git a/code_coverage/seccomp_policy/code_coverage.policy.def b/code_coverage/seccomp_policy/code_coverage.policy.def
new file mode 100644
index 0000000..f136084
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.policy.def
@@ -0,0 +1,51 @@
+// SECCOMP_MODE_STRICT
+//
+// minijail allowances for code coverage
+// this is processed with generate.sh, so we can use appropriate directives
+// size specific: __LP64__ for 64 bit, else 32 bit
+// arch specific: __arm__, __aarch64__, __i386__, __x86_64__
+
+// includes *all* syscalls used during the coverage dumping
+// no skipping just because they might have been in another policy file.
+
+// coverage tool uses different operations on different passes
+// 1st: uses write() to fill the file
+// 2nd-Nth: uses mmap() to update in place
+
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+
+#if defined(__LP64__)
+fcntl: 1
+fstat: 1
+geteuid: 1
+lseek: 1
+mmap: 1
+rt_sigreturn: 1
+#else
+fcntl64: 1
+fstat64: 1
+geteuid32: 1
+_llseek: 1
+mmap2: 1
+sigreturn: 1
+#endif
+
+#if defined(__arm__)
+gettimeofday: 1
+#endif
+
+#if defined(__i386__)
+madvise: 1
+#endif
+
+#if defined(__arm__)
+prctl: 1
+#elif defined(__aarch64__)
+prctl: 1
+#endif
+
diff --git a/code_coverage/seccomp_policy/code_coverage.x86.policy b/code_coverage/seccomp_policy/code_coverage.x86.policy
new file mode 100644
index 0000000..24ff8b9
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.x86.policy
@@ -0,0 +1,13 @@
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+fcntl64: 1
+fstat64: 1
+geteuid32: 1
+_llseek: 1
+mmap2: 1
+sigreturn: 1
+madvise: 1
diff --git a/code_coverage/seccomp_policy/code_coverage.x86_64.policy b/code_coverage/seccomp_policy/code_coverage.x86_64.policy
new file mode 100644
index 0000000..3081036
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.x86_64.policy
@@ -0,0 +1,12 @@
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+fcntl: 1
+fstat: 1
+geteuid: 1
+lseek: 1
+mmap: 1
+rt_sigreturn: 1
diff --git a/code_coverage/seccomp_policy/generate.sh b/code_coverage/seccomp_policy/generate.sh
new file mode 100755
index 0000000..ae582c6
--- /dev/null
+++ b/code_coverage/seccomp_policy/generate.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# generate the arch-specific files from the generic one
+
+set -ex
+
+cd "$(dirname "$0")"
+CPP='cpp -undef -E -P code_coverage.policy.def'
+$CPP -D__arm__ -o code_coverage.arm.policy
+$CPP -D__aarch64__ -D__LP64__ -o code_coverage.arm64.policy
+$CPP -D__i386__ -o code_coverage.x86.policy
+$CPP -D__x86_64__ -D__LP64__ -o code_coverage.x86_64.policy
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index a8059b7..75ebd94 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1407,9 +1407,8 @@
return -1;
}
} else {
- // TODO(b/135984674): support remounting for ext4.
- LERROR << "Remounting in checkpointing mode is not yet supported for ext4";
- return -1;
+ // STOPSHIP(b/143970043): support remounting for ext4.
+ LWARNING << "Remounting into checkpointing is not supported for ex4. Proceed with caution";
}
return 0;
}
diff --git a/fs_mgr/libsnapshot/snapshot_metadata_updater_test.cpp b/fs_mgr/libsnapshot/snapshot_metadata_updater_test.cpp
index 7d96a67..4fd8759 100644
--- a/fs_mgr/libsnapshot/snapshot_metadata_updater_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_metadata_updater_test.cpp
@@ -325,7 +325,7 @@
EXPECT_TRUE(CheckGroupName("product", "another_group"));
}
-INSTANTIATE_TEST_SUITE_P(, SnapshotMetadataUpdaterTest, testing::Values(0, 1));
+INSTANTIATE_TEST_SUITE_P(Snapshot, SnapshotMetadataUpdaterTest, testing::Values(0, 1));
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 3c3d9a6..af268f9 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -1338,7 +1338,7 @@
ASSERT_TRUE(new_sm->CancelUpdate());
}
-INSTANTIATE_TEST_SUITE_P(, FlashAfterUpdateTest, Combine(Values(0, 1), Bool()),
+INSTANTIATE_TEST_SUITE_P(Snapshot, FlashAfterUpdateTest, Combine(Values(0, 1), Bool()),
[](const TestParamInfo<FlashAfterUpdateTest::ParamType>& info) {
return "Flash"s + (std::get<0>(info.param) ? "New"s : "Old"s) +
"Slot"s + (std::get<1>(info.param) ? "After"s : "Before"s) +
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 9e168e9..bdf4aac 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -73,12 +73,25 @@
return std::nullopt;
}
+static void initHealthInfo(HealthInfo_2_1* health_info_2_1) {
+ *health_info_2_1 = HealthInfo_2_1{};
+
+ // HIDL enum values are zero initialized, so they need to be initialized
+ // properly.
+ health_info_2_1->batteryCapacityLevel = BatteryCapacityLevel::UNKNOWN;
+ auto* props = &health_info_2_1->legacy.legacy;
+ props->batteryStatus = BatteryStatus::UNKNOWN;
+ props->batteryHealth = BatteryHealth::UNKNOWN;
+}
+
BatteryMonitor::BatteryMonitor()
: mHealthdConfig(nullptr),
mBatteryDevicePresent(false),
mBatteryFixedCapacity(0),
mBatteryFixedTemperature(0),
- mHealthInfo(std::make_unique<HealthInfo_2_1>()) {}
+ mHealthInfo(std::make_unique<HealthInfo_2_1>()) {
+ initHealthInfo(mHealthInfo.get());
+}
BatteryMonitor::~BatteryMonitor() {}
@@ -168,7 +181,7 @@
return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
auto ret = mapSysfsString(buf.c_str(), supplyTypeMap);
- if (ret < 0) {
+ if (!ret) {
KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf.c_str());
*ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
}
@@ -198,7 +211,7 @@
}
void BatteryMonitor::updateValues(void) {
- *mHealthInfo = HealthInfo_2_1{};
+ initHealthInfo(mHealthInfo.get());
HealthInfo_1_0& props = mHealthInfo->legacy.legacy;
diff --git a/init/Android.bp b/init/Android.bp
index 776a3a6..d939fcc 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -65,6 +65,7 @@
"libavb",
"libc++fs",
"libcgrouprc_format",
+ "liblmkd_utils",
"libmodprobe",
"libprotobuf-cpp-lite",
"libpropertyinfoserializer",
@@ -118,6 +119,7 @@
"init.cpp",
"interface_utils.cpp",
"keychords.cpp",
+ "lmkd_service.cpp",
"modalias_handler.cpp",
"mount_handler.cpp",
"mount_namespace.cpp",
diff --git a/init/AndroidTest.xml b/init/AndroidTest.xml
index 94a02e6..667911d 100644
--- a/init/AndroidTest.xml
+++ b/init/AndroidTest.xml
@@ -17,7 +17,7 @@
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
- <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
<option name="cleanup" value="true" />
<option name="push" value="CtsInitTestCases->/data/local/tmp/CtsInitTestCases" />
diff --git a/init/README.md b/init/README.md
index cdf3487..e8df4ec 100644
--- a/init/README.md
+++ b/init/README.md
@@ -505,12 +505,23 @@
> Used to mark the point right after /data is mounted. Used to implement the
`class_reset_post_data` and `class_start_post_data` commands.
-`mkdir <path> [mode] [owner] [group]`
+`mkdir <path> [<mode>] [<owner>] [<group>] [encryption=<action>] [key=<key>]`
> Create a directory at _path_, optionally with the given mode, owner, and
group. If not provided, the directory is created with permissions 755 and
owned by the root user and root group. If provided, the mode, owner and group
will be updated if the directory exists already.
+ > _action_ can be one of:
+ * `None`: take no encryption action; directory will be encrypted if parent is.
+ * `Require`: encrypt directory, abort boot process if encryption fails
+ * `Attempt`: try to set an encryption policy, but continue if it fails
+ * `DeleteIfNecessary`: recursively delete directory if necessary to set
+ encryption policy.
+
+ > _key_ can be one of:
+ * `ref`: use the systemwide DE key
+ * `per_boot_ref`: use the key freshly generated on each boot.
+
`mount_all <fstab> [ <path> ]\* [--<option>]`
> Calls fs\_mgr\_mount\_all on the given fs\_mgr-format fstab with optional
options "early" and "late".
diff --git a/init/builtins.cpp b/init/builtins.cpp
index b2c6461..5ee928e 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -364,67 +364,52 @@
return {};
}
-// mkdir <path> [mode] [owner] [group]
+// mkdir <path> [mode] [owner] [group] [<option> ...]
static Result<void> do_mkdir(const BuiltinArguments& args) {
- mode_t mode = 0755;
- Result<uid_t> uid = -1;
- Result<gid_t> gid = -1;
-
- switch (args.size()) {
- case 5:
- gid = DecodeUid(args[4]);
- if (!gid) {
- return Error() << "Unable to decode GID for '" << args[4] << "': " << gid.error();
- }
- FALLTHROUGH_INTENDED;
- case 4:
- uid = DecodeUid(args[3]);
- if (!uid) {
- return Error() << "Unable to decode UID for '" << args[3] << "': " << uid.error();
- }
- FALLTHROUGH_INTENDED;
- case 3:
- mode = std::strtoul(args[2].c_str(), 0, 8);
- FALLTHROUGH_INTENDED;
- case 2:
- break;
- default:
- return Error() << "Unexpected argument count: " << args.size();
+ auto options = ParseMkdir(args.args);
+ if (!options) return options.error();
+ std::string ref_basename;
+ if (options->ref_option == "ref") {
+ ref_basename = fscrypt_key_ref;
+ } else if (options->ref_option == "per_boot_ref") {
+ ref_basename = fscrypt_key_per_boot_ref;
+ } else {
+ return Error() << "Unknown key option: '" << options->ref_option << "'";
}
- std::string target = args[1];
+
struct stat mstat;
- if (lstat(target.c_str(), &mstat) != 0) {
+ if (lstat(options->target.c_str(), &mstat) != 0) {
if (errno != ENOENT) {
- return ErrnoError() << "lstat() failed on " << target;
+ return ErrnoError() << "lstat() failed on " << options->target;
}
- if (!make_dir(target, mode)) {
- return ErrnoErrorIgnoreEnoent() << "mkdir() failed on " << target;
+ if (!make_dir(options->target, options->mode)) {
+ return ErrnoErrorIgnoreEnoent() << "mkdir() failed on " << options->target;
}
- if (lstat(target.c_str(), &mstat) != 0) {
- return ErrnoError() << "lstat() failed on new " << target;
+ if (lstat(options->target.c_str(), &mstat) != 0) {
+ return ErrnoError() << "lstat() failed on new " << options->target;
}
}
if (!S_ISDIR(mstat.st_mode)) {
- return Error() << "Not a directory on " << target;
+ return Error() << "Not a directory on " << options->target;
}
- bool needs_chmod = (mstat.st_mode & ~S_IFMT) != mode;
- if ((*uid != static_cast<uid_t>(-1) && *uid != mstat.st_uid) ||
- (*gid != static_cast<gid_t>(-1) && *gid != mstat.st_gid)) {
- if (lchown(target.c_str(), *uid, *gid) == -1) {
- return ErrnoError() << "lchown failed on " << target;
+ bool needs_chmod = (mstat.st_mode & ~S_IFMT) != options->mode;
+ if ((options->uid != static_cast<uid_t>(-1) && options->uid != mstat.st_uid) ||
+ (options->gid != static_cast<gid_t>(-1) && options->gid != mstat.st_gid)) {
+ if (lchown(options->target.c_str(), options->uid, options->gid) == -1) {
+ return ErrnoError() << "lchown failed on " << options->target;
}
// chown may have cleared S_ISUID and S_ISGID, chmod again
needs_chmod = true;
}
if (needs_chmod) {
- if (fchmodat(AT_FDCWD, target.c_str(), mode, AT_SYMLINK_NOFOLLOW) == -1) {
- return ErrnoError() << "fchmodat() failed on " << target;
+ if (fchmodat(AT_FDCWD, options->target.c_str(), options->mode, AT_SYMLINK_NOFOLLOW) == -1) {
+ return ErrnoError() << "fchmodat() failed on " << options->target;
}
}
if (fscrypt_is_native()) {
- if (fscrypt_set_directory_policy(target)) {
+ if (!FscryptSetDirectoryPolicy(ref_basename, options->fscrypt_action, options->target)) {
return reboot_into_recovery(
- {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + target});
+ {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + options->target});
}
}
return {};
@@ -562,11 +547,25 @@
*
* return code is processed based on input code
*/
-static Result<void> queue_fs_event(int code) {
+static Result<void> queue_fs_event(int code, bool userdata_remount) {
if (code == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
+ if (userdata_remount) {
+ // FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION should only happen on FDE devices. Since we don't
+ // support userdata remount on FDE devices, this should never been triggered. Time to
+ // panic!
+ LOG(ERROR) << "Userdata remount is not supported on FDE devices. How did you get here?";
+ TriggerShutdown("reboot,requested-userdata-remount-on-fde-device");
+ }
ActionManager::GetInstance().QueueEventTrigger("encrypt");
return {};
} else if (code == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
+ if (userdata_remount) {
+ // FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED should only happen on FDE devices. Since we
+ // don't support userdata remount on FDE devices, this should never been triggered.
+ // Time to panic!
+ LOG(ERROR) << "Userdata remount is not supported on FDE devices. How did you get here?";
+ TriggerShutdown("reboot,requested-userdata-remount-on-fde-device");
+ }
property_set("ro.crypto.state", "encrypted");
property_set("ro.crypto.type", "block");
ActionManager::GetInstance().QueueEventTrigger("defaultcrypto");
@@ -589,8 +588,8 @@
return reboot_into_recovery(options);
/* If reboot worked, there is no return. */
} else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) {
- if (fscrypt_install_keyring()) {
- return Error() << "fscrypt_install_keyring() failed";
+ if (!userdata_remount && !FscryptInstallKeyring()) {
+ return Error() << "FscryptInstallKeyring() failed";
}
property_set("ro.crypto.state", "encrypted");
property_set("ro.crypto.type", "file");
@@ -600,8 +599,8 @@
ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
return {};
} else if (code == FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED) {
- if (fscrypt_install_keyring()) {
- return Error() << "fscrypt_install_keyring() failed";
+ if (!userdata_remount && !FscryptInstallKeyring()) {
+ return Error() << "FscryptInstallKeyring() failed";
}
property_set("ro.crypto.state", "encrypted");
property_set("ro.crypto.type", "file");
@@ -611,8 +610,8 @@
ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
return {};
} else if (code == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
- if (fscrypt_install_keyring()) {
- return Error() << "fscrypt_install_keyring() failed";
+ if (!userdata_remount && !FscryptInstallKeyring()) {
+ return Error() << "FscryptInstallKeyring() failed";
}
property_set("ro.crypto.state", "encrypted");
property_set("ro.crypto.type", "file");
@@ -679,7 +678,7 @@
/* queue_fs_event will queue event based on mount_fstab return code
* and return processed return code*/
initial_mount_fstab_return_code = mount_fstab_return_code;
- auto queue_fs_result = queue_fs_event(mount_fstab_return_code);
+ auto queue_fs_result = queue_fs_event(mount_fstab_return_code, false);
if (!queue_fs_result) {
return Error() << "queue_fs_event() failed: " << queue_fs_result.error();
}
@@ -1151,7 +1150,7 @@
if (auto rc = fs_mgr_remount_userdata_into_checkpointing(&fstab); rc < 0) {
TriggerShutdown("reboot,mount-userdata-failed");
}
- if (auto result = queue_fs_event(initial_mount_fstab_return_code); !result) {
+ if (auto result = queue_fs_event(initial_mount_fstab_return_code, true); !result) {
return Error() << "queue_fs_event() failed: " << result.error();
}
return {};
@@ -1257,7 +1256,7 @@
{"load_system_props", {0, 0, {false, do_load_system_props}}},
{"loglevel", {1, 1, {false, do_loglevel}}},
{"mark_post_data", {0, 0, {false, do_mark_post_data}}},
- {"mkdir", {1, 4, {true, do_mkdir}}},
+ {"mkdir", {1, 6, {true, do_mkdir}}},
// TODO: Do mount operations in vendor_init.
// mount_all is currently too complex to run in vendor_init as it queues action triggers,
// imports rc scripts, etc. It should be simplified and run in vendor_init context.
diff --git a/init/check_builtins.cpp b/init/check_builtins.cpp
index 2efaeea..9d23921 100644
--- a/init/check_builtins.cpp
+++ b/init/check_builtins.cpp
@@ -121,22 +121,10 @@
}
Result<void> check_mkdir(const BuiltinArguments& args) {
- if (args.size() >= 4) {
- if (!args[3].empty()) {
- auto uid = DecodeUid(args[3]);
- if (!uid) {
- return Error() << "Unable to decode UID for '" << args[3] << "': " << uid.error();
- }
- }
-
- if (args.size() == 5 && !args[4].empty()) {
- auto gid = DecodeUid(args[4]);
- if (!gid) {
- return Error() << "Unable to decode GID for '" << args[4] << "': " << gid.error();
- }
- }
+ auto options = ParseMkdir(args.args);
+ if (!options) {
+ return options.error();
}
-
return {};
}
diff --git a/init/fscrypt_init_extensions.cpp b/init/fscrypt_init_extensions.cpp
index 5fa07dd..7820f3d 100644
--- a/init/fscrypt_init_extensions.cpp
+++ b/init/fscrypt_init_extensions.cpp
@@ -41,19 +41,15 @@
using namespace android::fscrypt;
-static int set_policy_on(const std::string& ref_basename, const std::string& dir);
-
-int fscrypt_install_keyring() {
+bool FscryptInstallKeyring() {
key_serial_t device_keyring = add_key("keyring", "fscrypt", 0, 0, KEY_SPEC_SESSION_KEYRING);
if (device_keyring == -1) {
PLOG(ERROR) << "Failed to create keyring";
- return -1;
+ return false;
}
-
LOG(INFO) << "Keyring created with id " << device_keyring << " in process " << getpid();
-
- return 0;
+ return true;
}
// TODO(b/139378601): use a single central implementation of this.
@@ -97,102 +93,57 @@
}
}
-int fscrypt_set_directory_policy(const std::string& dir) {
- const std::string prefix = "/data/";
-
- if (!android::base::StartsWith(dir, prefix)) {
- return 0;
- }
-
- // Special-case /data/media/obb per b/64566063
- if (dir == "/data/media/obb") {
- // Try to set policy on this directory, but if it is non-empty this may fail.
- set_policy_on(fscrypt_key_ref, dir);
- return 0;
- }
-
- // Only set policy on first level /data directories
- // To make this less restrictive, consider using a policy file.
- // However this is overkill for as long as the policy is simply
- // to apply a global policy to all /data folders created via makedir
- if (dir.find_first_of('/', prefix.size()) != std::string::npos) {
- return 0;
- }
-
- // Special case various directories that must not be encrypted,
- // often because their subdirectories must be encrypted.
- // This isn't a nice way to do this, see b/26641735
- std::vector<std::string> directories_to_exclude = {
- "lost+found",
- "system_ce", "system_de",
- "misc_ce", "misc_de",
- "vendor_ce", "vendor_de",
- "media",
- "data", "user", "user_de",
- "apex", "preloads", "app-staging",
- "gsi",
- };
- for (const auto& d : directories_to_exclude) {
- if ((prefix + d) == dir) {
- LOG(INFO) << "Not setting policy on " << dir;
- return 0;
- }
- }
- std::vector<std::string> per_boot_directories = {
- "per_boot",
- };
- for (const auto& d : per_boot_directories) {
- if ((prefix + d) == dir) {
- LOG(INFO) << "Setting per_boot key on " << dir;
- return set_policy_on(fscrypt_key_per_boot_ref, dir);
- }
- }
- int err = set_policy_on(fscrypt_key_ref, dir);
- if (err == 0) {
- return 0;
- }
- // Empty these directories if policy setting fails.
- std::vector<std::string> wipe_on_failure = {
- "rollback", "rollback-observer", // b/139193659
- };
- for (const auto& d : wipe_on_failure) {
- if ((prefix + d) == dir) {
- LOG(ERROR) << "Setting policy failed, deleting: " << dir;
- delete_dir_contents(dir);
- err = set_policy_on(fscrypt_key_ref, dir);
- break;
- }
- }
- return err;
-}
-
-// Set an encryption policy on the given directory. The policy (key reference
+// Look up an encryption policy The policy (key reference
// and encryption options) to use is read from files that were written by vold.
-static int set_policy_on(const std::string& ref_basename, const std::string& dir) {
- EncryptionPolicy policy;
+static bool LookupPolicy(const std::string& ref_basename, EncryptionPolicy* policy) {
std::string ref_filename = std::string("/data") + ref_basename;
- if (!android::base::ReadFileToString(ref_filename, &policy.key_raw_ref)) {
- LOG(ERROR) << "Unable to read system policy to set on " << dir;
- return -1;
+ if (!android::base::ReadFileToString(ref_filename, &policy->key_raw_ref)) {
+ LOG(ERROR) << "Unable to read system policy with name " << ref_filename;
+ return false;
}
auto options_filename = std::string("/data") + fscrypt_key_mode;
std::string options_string;
if (!android::base::ReadFileToString(options_filename, &options_string)) {
LOG(ERROR) << "Cannot read encryption options string";
- return -1;
+ return false;
}
- if (!ParseOptions(options_string, &policy.options)) {
+ if (!ParseOptions(options_string, &policy->options)) {
LOG(ERROR) << "Invalid encryption options string: " << options_string;
- return -1;
+ return false;
}
+ return true;
+}
+static bool EnsurePolicyOrLog(const EncryptionPolicy& policy, const std::string& dir) {
if (!EnsurePolicy(policy, dir)) {
std::string ref_hex;
BytesToHex(policy.key_raw_ref, &ref_hex);
LOG(ERROR) << "Setting " << ref_hex << " policy on " << dir << " failed!";
- return -1;
+ return false;
}
+ return true;
+}
- return 0;
+static bool SetPolicyOn(const std::string& ref_basename, const std::string& dir) {
+ EncryptionPolicy policy;
+ if (!LookupPolicy(ref_basename, &policy)) return false;
+ if (!EnsurePolicyOrLog(policy, dir)) return false;
+ return true;
+}
+
+bool FscryptSetDirectoryPolicy(const std::string& ref_basename, FscryptAction action,
+ const std::string& dir) {
+ if (action == FscryptAction::kNone) {
+ return true;
+ }
+ if (SetPolicyOn(ref_basename, dir) || action == FscryptAction::kAttempt) {
+ return true;
+ }
+ if (action == FscryptAction::kDeleteIfNecessary) {
+ LOG(ERROR) << "Setting policy failed, deleting: " << dir;
+ delete_dir_contents(dir);
+ return SetPolicyOn(ref_basename, dir);
+ }
+ return false;
}
diff --git a/init/fscrypt_init_extensions.h b/init/fscrypt_init_extensions.h
index 2163ef6..d357bb2 100644
--- a/init/fscrypt_init_extensions.h
+++ b/init/fscrypt_init_extensions.h
@@ -18,5 +18,13 @@
#include <string>
-int fscrypt_install_keyring();
-int fscrypt_set_directory_policy(const std::string& dir);
+enum class FscryptAction {
+ kNone,
+ kAttempt,
+ kRequire,
+ kDeleteIfNecessary,
+};
+
+bool FscryptInstallKeyring();
+bool FscryptSetDirectoryPolicy(const std::string& ref_basename, FscryptAction action,
+ const std::string& dir);
diff --git a/init/init.cpp b/init/init.cpp
index f775d8f..6ea2d00 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -59,6 +59,7 @@
#include "first_stage_mount.h"
#include "import_parser.h"
#include "keychords.h"
+#include "lmkd_service.h"
#include "mount_handler.h"
#include "mount_namespace.h"
#include "property_service.h"
@@ -684,9 +685,15 @@
InitKernelLogging(argv);
LOG(INFO) << "init second stage started!";
+ // Will handle EPIPE at the time of write by checking the errno
+ signal(SIGPIPE, SIG_IGN);
+
// Set init and its forked children's oom_adj.
- if (auto result = WriteFile("/proc/1/oom_score_adj", "-1000"); !result) {
- LOG(ERROR) << "Unable to write -1000 to /proc/1/oom_score_adj: " << result.error();
+ if (auto result =
+ WriteFile("/proc/1/oom_score_adj", StringPrintf("%d", DEFAULT_OOM_SCORE_ADJUST));
+ !result) {
+ LOG(ERROR) << "Unable to write " << DEFAULT_OOM_SCORE_ADJUST
+ << " to /proc/1/oom_score_adj: " << result.error();
}
// Set up a session keyring that all processes will have access to. It
diff --git a/init/lmkd_service.cpp b/init/lmkd_service.cpp
new file mode 100644
index 0000000..dd1ab4d
--- /dev/null
+++ b/init/lmkd_service.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "lmkd_service.h"
+
+#include <errno.h>
+
+#include <android-base/logging.h>
+#include <liblmkd_utils.h>
+
+#include "service_list.h"
+
+namespace android {
+namespace init {
+
+enum LmkdRegistrationResult {
+ LMKD_REG_SUCCESS,
+ LMKD_CONN_FAILED,
+ LMKD_REG_FAILED,
+};
+
+static int lmkd_socket = -1;
+
+static LmkdRegistrationResult RegisterProcess(uid_t uid, pid_t pid, int oom_score_adjust) {
+ // connect to lmkd if not already connected
+ if (lmkd_socket < 0) {
+ lmkd_socket = lmkd_connect();
+ if (lmkd_socket < 0) {
+ return LMKD_CONN_FAILED;
+ }
+ }
+
+ // register service with lmkd
+ struct lmk_procprio params;
+ params.pid = pid;
+ params.uid = uid;
+ params.oomadj = oom_score_adjust;
+ params.ptype = PROC_TYPE_SERVICE;
+ if (lmkd_register_proc(lmkd_socket, ¶ms) != 0) {
+ // data transfer failed, reset the connection
+ close(lmkd_socket);
+ lmkd_socket = -1;
+ return LMKD_REG_FAILED;
+ }
+
+ return LMKD_REG_SUCCESS;
+}
+
+static bool UnregisterProcess(pid_t pid) {
+ if (lmkd_socket < 0) {
+ // no connection or it was lost, no need to unregister
+ return false;
+ }
+
+ // unregister service
+ struct lmk_procremove params;
+ params.pid = pid;
+ if (lmkd_unregister_proc(lmkd_socket, ¶ms) != 0) {
+ // data transfer failed, reset the connection
+ close(lmkd_socket);
+ lmkd_socket = -1;
+ return false;
+ }
+
+ return true;
+}
+
+static void RegisterServices(pid_t exclude_pid) {
+ for (const auto& service : ServiceList::GetInstance().services()) {
+ auto svc = service.get();
+ if (svc->oom_score_adjust() != DEFAULT_OOM_SCORE_ADJUST) {
+ // skip if process is excluded or not yet forked (pid==0)
+ if (svc->pid() == exclude_pid || svc->pid() == 0) {
+ continue;
+ }
+ if (RegisterProcess(svc->uid(), svc->pid(), svc->oom_score_adjust()) !=
+ LMKD_REG_SUCCESS) {
+ // a failure here resets the connection, will retry during next registration
+ break;
+ }
+ }
+ }
+}
+
+void LmkdRegister(const std::string& name, uid_t uid, pid_t pid, int oom_score_adjust) {
+ bool new_connection = lmkd_socket == -1;
+ LmkdRegistrationResult result;
+
+ result = RegisterProcess(uid, pid, oom_score_adjust);
+ if (result == LMKD_REG_FAILED) {
+ // retry one time if connection to lmkd was lost
+ result = RegisterProcess(uid, pid, oom_score_adjust);
+ new_connection = result == LMKD_REG_SUCCESS;
+ }
+ switch (result) {
+ case LMKD_REG_SUCCESS:
+ // register existing services once new connection is established
+ if (new_connection) {
+ RegisterServices(pid);
+ }
+ break;
+ case LMKD_CONN_FAILED:
+ PLOG(ERROR) << "lmkd connection failed when " << name << " process got started";
+ break;
+ case LMKD_REG_FAILED:
+ PLOG(ERROR) << "lmkd failed to register " << name << " process";
+ break;
+ }
+}
+
+void LmkdUnregister(const std::string& name, pid_t pid) {
+ if (!UnregisterProcess(pid)) {
+ PLOG(ERROR) << "lmkd failed to unregister " << name << " process";
+ }
+}
+
+} // namespace init
+} // namespace android
diff --git a/init/lmkd_service.h b/init/lmkd_service.h
new file mode 100644
index 0000000..5b51d52
--- /dev/null
+++ b/init/lmkd_service.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <sys/types.h>
+
+#include <string>
+
+namespace android {
+namespace init {
+
+static const int MIN_OOM_SCORE_ADJUST = -1000;
+static const int MAX_OOM_SCORE_ADJUST = 1000;
+// service with default score is unkillable
+static const int DEFAULT_OOM_SCORE_ADJUST = MIN_OOM_SCORE_ADJUST;
+
+#if defined(__ANDROID__)
+
+void LmkdRegister(const std::string& name, uid_t uid, pid_t pid, int oom_score_adjust);
+void LmkdUnregister(const std::string& name, pid_t pid);
+
+#else // defined(__ANDROID__)
+
+static inline void LmkdRegister(const std::string&, uid_t, pid_t, int) {}
+static inline void LmkdUnregister(const std::string&, pid_t) {}
+
+#endif // defined(__ANDROID__)
+
+} // namespace init
+} // namespace android
diff --git a/init/reboot.cpp b/init/reboot.cpp
index fc18ecb..4a16969 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -57,6 +57,7 @@
#include "action_manager.h"
#include "builtin_arguments.h"
#include "init.h"
+#include "mount_namespace.h"
#include "property_service.h"
#include "reboot_utils.h"
#include "service.h"
@@ -713,6 +714,18 @@
SendStartSendingMessagesMessage();
}
+static Result<void> UnmountAllApexes() {
+ const char* args[] = {"/system/bin/apexd", "--unmount-all"};
+ int status;
+ if (logwrap_fork_execvp(arraysize(args), args, &status, false, LOG_KLOG, true, nullptr) != 0) {
+ return ErrnoError() << "Failed to call '/system/bin/apexd --unmount-all'";
+ }
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ return {};
+ }
+ return Error() << "'/system/bin/apexd --unmount-all' failed : " << status;
+}
+
static Result<void> DoUserspaceReboot() {
LOG(INFO) << "Userspace reboot initiated";
auto guard = android::base::make_scope_guard([] {
@@ -746,30 +759,20 @@
// TODO(b/135984674): store information about offending services for debugging.
return Error() << r << " post-data services are still running";
}
- // We only really need to restart vold if userdata is ext4 filesystem.
- // TODO(b/135984674): get userdata fs type here, and do nothing in case of f2fs.
- // First shutdown volumes managed by vold. They will be recreated by
- // system_server.
- Service* vold_service = ServiceList::GetInstance().FindService("vold");
- if (vold_service != nullptr && vold_service->IsRunning()) {
- if (auto result = ShutdownVold(); !result) {
- return result;
- }
- LOG(INFO) << "Restarting vold";
- vold_service->Restart();
- }
- // Again, we only need to kill zram backing device in case of ext4 userdata.
- // TODO(b/135984674): get userdata fs type here, and do nothing in case of f2fs.
- if (auto result = KillZramBackingDevice(); !result) {
- return result;
- }
+ // TODO(b/143970043): in case of ext4 we probably we will need to restart vold and kill zram
+ // backing device.
if (int r = StopServicesAndLogViolations(GetDebuggingServices(true /* only_post_data */), 5s,
false /* SIGKILL */);
r > 0) {
// TODO(b/135984674): store information about offending services for debugging.
return Error() << r << " debugging services are still running";
}
- // TODO(b/135984674): deactivate APEX modules and switch back to bootstrap namespace.
+ if (auto result = UnmountAllApexes(); !result) {
+ return result;
+ }
+ if (!SwitchToBootstrapMountNamespaceIfNeeded()) {
+ return Error() << "Failed to switch to bootstrap namespace";
+ }
// Re-enable services
for (const auto& s : were_enabled) {
LOG(INFO) << "Re-enabling service '" << s->name() << "'";
diff --git a/init/selinux.cpp b/init/selinux.cpp
index a15d136..a9cd290 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -514,9 +514,6 @@
} // namespace
-// The files and directories that were created before initial sepolicy load or
-// files on ramdisk need to have their security context restored to the proper
-// value. This must happen before /dev is populated by ueventd.
void SelinuxRestoreContext() {
LOG(INFO) << "Running restorecon...";
selinux_android_restorecon("/dev", 0);
@@ -560,15 +557,12 @@
return 0;
}
-// This function sets up SELinux logging to be written to kmsg, to match init's logging.
void SelinuxSetupKernelLogging() {
selinux_callback cb;
cb.func_log = SelinuxKlogCallback;
selinux_set_callback(SELINUX_CB_LOG, cb);
}
-// This function returns the Android version with which the vendor SEPolicy was compiled.
-// It is used for version checks such as whether or not vendor_init should be used
int SelinuxGetVendorAndroidVersion() {
static int vendor_android_version = [] {
if (!IsSplitPolicyDevice()) {
@@ -594,7 +588,6 @@
return vendor_android_version;
}
-// This function initializes SELinux then execs init to run in the init SELinux context.
int SetupSelinux(char** argv) {
SetStdioToDevNull(argv);
InitKernelLogging(argv);
diff --git a/init/selinux.h b/init/selinux.h
index 63ad470..1a41bfd 100644
--- a/init/selinux.h
+++ b/init/selinux.h
@@ -19,10 +19,19 @@
namespace android {
namespace init {
+// Initialize SELinux, then exec init to run in the init SELinux context.
int SetupSelinux(char** argv);
+
+// Restore the proper security context to files and directories on ramdisk, and
+// those that were created before initial sepolicy load.
+// This must happen before /dev is populated by ueventd.
void SelinuxRestoreContext();
+// Set up SELinux logging to be written to kmsg, to match init's logging.
void SelinuxSetupKernelLogging();
+
+// Return the Android API level with which the vendor SEPolicy was compiled.
+// Used for version checks such as whether or not vendor_init should be used.
int SelinuxGetVendorAndroidVersion();
static constexpr char kEnvSelinuxStartedAt[] = "SELINUX_STARTED_AT";
diff --git a/init/service.cpp b/init/service.cpp
index c8568a0..f8e98a2 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -36,6 +36,7 @@
#include <processgroup/processgroup.h>
#include <selinux/selinux.h>
+#include "lmkd_service.h"
#include "service_list.h"
#include "util.h"
@@ -151,7 +152,7 @@
seclabel_(seclabel),
onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0,
"onrestart", {}),
- oom_score_adjust_(-1000),
+ oom_score_adjust_(DEFAULT_OOM_SCORE_ADJUST),
start_order_(0),
args_(args) {}
@@ -199,6 +200,10 @@
if (r == 0) process_cgroup_empty_ = true;
}
+
+ if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
+ LmkdUnregister(name_, pid_);
+ }
}
void Service::SetProcessAttributesAndCaps() {
@@ -502,7 +507,7 @@
return ErrnoError() << "Failed to fork";
}
- if (oom_score_adjust_ != -1000) {
+ if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
std::string oom_str = std::to_string(oom_score_adjust_);
std::string oom_file = StringPrintf("/proc/%d/oom_score_adj", pid);
if (!WriteStringToFile(oom_str, oom_file)) {
@@ -563,6 +568,10 @@
}
}
+ if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
+ LmkdRegister(name_, proc_attr_.uid, pid_, oom_score_adjust_);
+ }
+
NotifyStateChange("running");
reboot_on_failure.Disable();
return {};
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index e6a341d..154d1dd 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -29,6 +29,7 @@
#include <hidl-util/FQName.h>
#include <system/thread_defs.h>
+#include "lmkd_service.h"
#include "rlimit_parser.h"
#include "service_utils.h"
#include "util.h"
@@ -261,8 +262,10 @@
}
Result<void> ServiceParser::ParseOomScoreAdjust(std::vector<std::string>&& args) {
- if (!ParseInt(args[1], &service_->oom_score_adjust_, -1000, 1000)) {
- return Error() << "oom_score_adjust value must be in range -1000 - +1000";
+ if (!ParseInt(args[1], &service_->oom_score_adjust_, MIN_OOM_SCORE_ADJUST,
+ MAX_OOM_SCORE_ADJUST)) {
+ return Error() << "oom_score_adjust value must be in range " << MIN_OOM_SCORE_ADJUST
+ << " - +" << MAX_OOM_SCORE_ADJUST;
}
return {};
}
diff --git a/init/service_test.cpp b/init/service_test.cpp
index c9cc7bd..c158b0a 100644
--- a/init/service_test.cpp
+++ b/init/service_test.cpp
@@ -23,6 +23,7 @@
#include <gtest/gtest.h>
+#include "lmkd_service.h"
#include "util.h"
namespace android {
@@ -49,7 +50,7 @@
EXPECT_EQ(IoSchedClass_NONE, service_in_old_memory->ioprio_class());
EXPECT_EQ(0, service_in_old_memory->ioprio_pri());
EXPECT_EQ(0, service_in_old_memory->priority());
- EXPECT_EQ(-1000, service_in_old_memory->oom_score_adjust());
+ EXPECT_EQ(DEFAULT_OOM_SCORE_ADJUST, service_in_old_memory->oom_score_adjust());
EXPECT_FALSE(service_in_old_memory->process_cgroup_empty());
for (std::size_t i = 0; i < memory_size; ++i) {
@@ -68,7 +69,7 @@
EXPECT_EQ(IoSchedClass_NONE, service_in_old_memory2->ioprio_class());
EXPECT_EQ(0, service_in_old_memory2->ioprio_pri());
EXPECT_EQ(0, service_in_old_memory2->priority());
- EXPECT_EQ(-1000, service_in_old_memory2->oom_score_adjust());
+ EXPECT_EQ(DEFAULT_OOM_SCORE_ADJUST, service_in_old_memory2->oom_score_adjust());
EXPECT_FALSE(service_in_old_memory->process_cgroup_empty());
}
diff --git a/init/util.cpp b/init/util.cpp
index 40db838..ada9e78 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -434,6 +434,142 @@
return {};
}
+static FscryptAction FscryptInferAction(const std::string& dir) {
+ const std::string prefix = "/data/";
+
+ if (!android::base::StartsWith(dir, prefix)) {
+ return FscryptAction::kNone;
+ }
+
+ // Special-case /data/media/obb per b/64566063
+ if (dir == "/data/media/obb") {
+ // Try to set policy on this directory, but if it is non-empty this may fail.
+ return FscryptAction::kAttempt;
+ }
+
+ // Only set policy on first level /data directories
+ // To make this less restrictive, consider using a policy file.
+ // However this is overkill for as long as the policy is simply
+ // to apply a global policy to all /data folders created via makedir
+ if (dir.find_first_of('/', prefix.size()) != std::string::npos) {
+ return FscryptAction::kNone;
+ }
+
+ // Special case various directories that must not be encrypted,
+ // often because their subdirectories must be encrypted.
+ // This isn't a nice way to do this, see b/26641735
+ std::vector<std::string> directories_to_exclude = {
+ "lost+found", "system_ce", "system_de", "misc_ce", "misc_de",
+ "vendor_ce", "vendor_de", "media", "data", "user",
+ "user_de", "apex", "preloads", "app-staging", "gsi",
+ };
+ for (const auto& d : directories_to_exclude) {
+ if ((prefix + d) == dir) {
+ return FscryptAction::kNone;
+ }
+ }
+ // Empty these directories if policy setting fails.
+ std::vector<std::string> wipe_on_failure = {
+ "rollback", "rollback-observer", // b/139193659
+ };
+ for (const auto& d : wipe_on_failure) {
+ if ((prefix + d) == dir) {
+ return FscryptAction::kDeleteIfNecessary;
+ }
+ }
+ return FscryptAction::kRequire;
+}
+
+Result<MkdirOptions> ParseMkdir(const std::vector<std::string>& args) {
+ mode_t mode = 0755;
+ Result<uid_t> uid = -1;
+ Result<gid_t> gid = -1;
+ FscryptAction fscrypt_inferred_action = FscryptInferAction(args[1]);
+ FscryptAction fscrypt_action = fscrypt_inferred_action;
+ std::string ref_option = "ref";
+ bool set_option_encryption = false;
+ bool set_option_key = false;
+
+ for (size_t i = 2; i < args.size(); i++) {
+ switch (i) {
+ case 2:
+ mode = std::strtoul(args[2].c_str(), 0, 8);
+ break;
+ case 3:
+ uid = DecodeUid(args[3]);
+ if (!uid) {
+ return Error()
+ << "Unable to decode UID for '" << args[3] << "': " << uid.error();
+ }
+ break;
+ case 4:
+ gid = DecodeUid(args[4]);
+ if (!gid) {
+ return Error()
+ << "Unable to decode GID for '" << args[4] << "': " << gid.error();
+ }
+ break;
+ default:
+ auto parts = android::base::Split(args[i], "=");
+ if (parts.size() != 2) {
+ return Error() << "Can't parse option: '" << args[i] << "'";
+ }
+ auto optname = parts[0];
+ auto optval = parts[1];
+ if (optname == "encryption") {
+ if (set_option_encryption) {
+ return Error() << "Duplicated option: '" << optname << "'";
+ }
+ if (optval == "Require") {
+ fscrypt_action = FscryptAction::kRequire;
+ } else if (optval == "None") {
+ fscrypt_action = FscryptAction::kNone;
+ } else if (optval == "Attempt") {
+ fscrypt_action = FscryptAction::kAttempt;
+ } else if (optval == "DeleteIfNecessary") {
+ fscrypt_action = FscryptAction::kDeleteIfNecessary;
+ } else {
+ return Error() << "Unknown encryption option: '" << optval << "'";
+ }
+ set_option_encryption = true;
+ } else if (optname == "key") {
+ if (set_option_key) {
+ return Error() << "Duplicated option: '" << optname << "'";
+ }
+ if (optval == "ref" || optval == "per_boot_ref") {
+ ref_option = optval;
+ } else {
+ return Error() << "Unknown key option: '" << optval << "'";
+ }
+ set_option_key = true;
+ } else {
+ return Error() << "Unknown option: '" << args[i] << "'";
+ }
+ }
+ }
+ if (set_option_key && fscrypt_action == FscryptAction::kNone) {
+ return Error() << "Key option set but encryption action is none";
+ }
+ const std::string prefix = "/data/";
+ if (StartsWith(args[1], prefix) &&
+ args[1].find_first_of('/', prefix.size()) == std::string::npos) {
+ if (!set_option_encryption) {
+ LOG(WARNING) << "Top-level directory needs encryption action, eg mkdir " << args[1]
+ << " <mode> <uid> <gid> encryption=Require";
+ }
+ if (fscrypt_action == FscryptAction::kNone) {
+ LOG(INFO) << "Not setting encryption policy on: " << args[1];
+ }
+ }
+ if (fscrypt_action != fscrypt_inferred_action) {
+ LOG(WARNING) << "Inferred action different from explicit one, expected "
+ << static_cast<int>(fscrypt_inferred_action) << " but got "
+ << static_cast<int>(fscrypt_action);
+ }
+
+ return MkdirOptions{args[1], mode, *uid, *gid, fscrypt_action, ref_option};
+}
+
Result<std::pair<int, std::vector<std::string>>> ParseRestorecon(
const std::vector<std::string>& args) {
struct flag_type {
diff --git a/init/util.h b/init/util.h
index 4cccefe..3d81d72 100644
--- a/init/util.h
+++ b/init/util.h
@@ -25,6 +25,7 @@
#include <android-base/chrono_utils.h>
+#include "fscrypt_init_extensions.h"
#include "result.h"
using android::base::boot_clock;
@@ -60,6 +61,17 @@
bool IsLegalPropertyName(const std::string& name);
Result<void> IsLegalPropertyValue(const std::string& name, const std::string& value);
+struct MkdirOptions {
+ std::string target;
+ mode_t mode;
+ uid_t uid;
+ gid_t gid;
+ FscryptAction fscrypt_action;
+ std::string ref_option;
+};
+
+Result<MkdirOptions> ParseMkdir(const std::vector<std::string>& args);
+
Result<std::pair<int, std::vector<std::string>>> ParseRestorecon(
const std::vector<std::string>& args);
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index b9420d4..88e1bdb 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -244,6 +244,7 @@
defaults: ["libcutils_test_default"],
host_supported: true,
shared_libs: test_libraries,
+ require_root: true,
}
cc_test {
@@ -255,6 +256,7 @@
"libcgrouprc_format",
] + test_libraries,
stl: "libc++_static",
+ require_root: true,
target: {
android: {
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 5fb11a5..2b39ca6 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -85,6 +85,7 @@
{ 00755, AID_ROOT, AID_SHELL, 0, "system/vendor" },
{ 00751, AID_ROOT, AID_SHELL, 0, "system/xbin" },
{ 00751, AID_ROOT, AID_SHELL, 0, "system/apex/*/bin" },
+ { 00751, AID_ROOT, AID_SHELL, 0, "system_ext/bin" },
{ 00751, AID_ROOT, AID_SHELL, 0, "vendor/bin" },
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor" },
{ 00755, AID_ROOT, AID_ROOT, 0, 0 },
@@ -207,6 +208,7 @@
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/apex/*/bin/*" },
+ { 00755, AID_ROOT, AID_SHELL, 0, "system_ext/bin/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor/bin/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor/xbin/*" },
{ 00644, AID_ROOT, AID_ROOT, 0, 0 },
diff --git a/libcutils/fs_config_test.cpp b/libcutils/fs_config_test.cpp
index 9627152..c6684b4 100644
--- a/libcutils/fs_config_test.cpp
+++ b/libcutils/fs_config_test.cpp
@@ -46,7 +46,7 @@
// clang-format off
{ true, "system/lib", "system/lib/hw", true },
{ true, "vendor/lib", "system/vendor/lib/hw", true },
- { true, "system/vendor/lib", "vendor/lib/hw", true },
+ { true, "system/vendor/lib", "vendor/lib/hw", false },
{ true, "system/vendor/lib", "system/vendor/lib/hw", true },
{ true, "foo/*/bar/*", "foo/1/bar/2", true },
{ true, "foo/*/bar/*", "foo/1/bar", true },
@@ -56,13 +56,14 @@
{ false, "vendor/bin/wifi", "system/vendor/bin/wifi", true },
{ false, "vendor/bin/wifi", "system/vendor/bin/wifi2", false },
{ false, "system/vendor/bin/wifi", "system/vendor/bin/wifi", true, },
- { false, "odm/bin/wifi", "system/odm/bin/wifi", true },
- { false, "oem/bin/wifi", "system/oem/bin/wifi", true },
+ { false, "odm/bin/wifi", "system/odm/bin/wifi", false },
+ { false, "odm/bin/wifi", "vendor/odm/bin/wifi", true },
+ { false, "oem/bin/wifi", "system/oem/bin/wifi", false },
{ false, "data/bin/wifi", "system/data/bin/wifi", false },
{ false, "system/bin/*", "system/bin/wifi", true },
{ false, "vendor/bin/*", "system/vendor/bin/wifi", true },
{ false, "system/bin/*", "system/bin", false },
- { false, "system/vendor/bin/*", "vendor/bin/wifi", true },
+ { false, "system/vendor/bin/*", "vendor/bin/wifi", false },
{ false, "foo/*/bar/*", "foo/1/bar/2", true },
{ false, "foo/*/bar/*", "foo/1/bar", false },
{ false, "foo/*/bar/*", "foo/1/bar/2/3", true },
diff --git a/libcutils/include/cutils/sockets.h b/libcutils/include/cutils/sockets.h
index 285f150..be21a8f 100644
--- a/libcutils/include/cutils/sockets.h
+++ b/libcutils/include/cutils/sockets.h
@@ -103,14 +103,6 @@
int socket_close(cutils_socket_t sock);
/*
- * Sets socket receive timeout using SO_RCVTIMEO. Setting |timeout_ms| to 0
- * disables receive timeouts.
- *
- * Return 0 on success.
- */
-int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms);
-
-/*
* Returns the local port the socket is bound to or -1 on error.
*/
int socket_get_local_port(cutils_socket_t sock);
diff --git a/libcutils/sockets_test.cpp b/libcutils/sockets_test.cpp
index b762ac1..1fa40bc 100644
--- a/libcutils/sockets_test.cpp
+++ b/libcutils/sockets_test.cpp
@@ -73,25 +73,6 @@
EXPECT_EQ(0, socket_close(client));
}
-// Tests receive timeout. The timing verification logic must be very coarse to
-// make sure different systems can all pass these tests.
-void TestReceiveTimeout(cutils_socket_t sock) {
- time_t start_time;
- char buffer[32];
-
- // Make sure a 20ms timeout completes in 1 second or less.
- EXPECT_EQ(0, socket_set_receive_timeout(sock, 20));
- start_time = time(nullptr);
- EXPECT_EQ(-1, recv(sock, buffer, sizeof(buffer), 0));
- EXPECT_LE(difftime(time(nullptr), start_time), 1.0);
-
- // Make sure a 1250ms timeout takes 1 second or more.
- EXPECT_EQ(0, socket_set_receive_timeout(sock, 1250));
- start_time = time(nullptr);
- EXPECT_EQ(-1, recv(sock, buffer, sizeof(buffer), 0));
- EXPECT_LE(1.0, difftime(time(nullptr), start_time));
-}
-
// Tests socket_get_local_port().
TEST(SocketsTest, TestGetLocalPort) {
cutils_socket_t server;
@@ -157,32 +138,6 @@
TestConnectedSockets(handler, client, SOCK_STREAM);
}
-// Tests setting a receive timeout for UDP sockets.
-TEST(SocketsTest, TestUdpReceiveTimeout) {
- cutils_socket_t sock = socket_inaddr_any_server(0, SOCK_DGRAM);
- ASSERT_NE(INVALID_SOCKET, sock);
-
- TestReceiveTimeout(sock);
-
- EXPECT_EQ(0, socket_close(sock));
-}
-
-// Tests setting a receive timeout for TCP sockets.
-TEST(SocketsTest, TestTcpReceiveTimeout) {
- cutils_socket_t server = socket_inaddr_any_server(0, SOCK_STREAM);
- ASSERT_NE(INVALID_SOCKET, server);
-
- cutils_socket_t client = socket_network_client(
- "localhost", socket_get_local_port(server), SOCK_STREAM);
- cutils_socket_t handler = accept(server, nullptr, nullptr);
- EXPECT_EQ(0, socket_close(server));
-
- TestReceiveTimeout(handler);
-
- EXPECT_EQ(0, socket_close(client));
- EXPECT_EQ(0, socket_close(handler));
-}
-
// Tests socket_send_buffers() failure.
TEST(SocketsTest, TestSocketSendBuffersFailure) {
EXPECT_EQ(-1, socket_send_buffers(INVALID_SOCKET, nullptr, 0));
diff --git a/libcutils/sockets_unix.cpp b/libcutils/sockets_unix.cpp
index 6acdcd8..84663e6 100644
--- a/libcutils/sockets_unix.cpp
+++ b/libcutils/sockets_unix.cpp
@@ -31,13 +31,6 @@
return close(sock);
}
-int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms) {
- timeval tv;
- tv.tv_sec = timeout_ms / 1000;
- tv.tv_usec = (timeout_ms % 1000) * 1000;
- return setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
-}
-
ssize_t socket_send_buffers(cutils_socket_t sock,
const cutils_socket_buffer_t* buffers,
size_t num_buffers) {
diff --git a/libcutils/sockets_windows.cpp b/libcutils/sockets_windows.cpp
index df14712..4adb796 100644
--- a/libcutils/sockets_windows.cpp
+++ b/libcutils/sockets_windows.cpp
@@ -54,11 +54,6 @@
return closesocket(sock);
}
-int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms) {
- return setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
- reinterpret_cast<char*>(&timeout_ms), sizeof(timeout_ms));
-}
-
ssize_t socket_send_buffers(cutils_socket_t sock,
const cutils_socket_buffer_t* buffers,
size_t num_buffers) {
diff --git a/libgrallocusage/Android.bp b/libgrallocusage/Android.bp
index d27feb9..ce0c3c8 100644
--- a/libgrallocusage/Android.bp
+++ b/libgrallocusage/Android.bp
@@ -20,12 +20,7 @@
"-Werror",
],
cppflags: [
- "-Weverything",
- "-Wno-c++98-compat-pedantic",
- // Hide errors in headers we include
- "-Wno-global-constructors",
- "-Wno-exit-time-destructors",
- "-Wno-padded",
+ "-Wextra",
],
srcs: ["GrallocUsageConversion.cpp"],
export_include_dirs: ["include"],
diff --git a/libprocessgroup/profiles/test.cpp b/libprocessgroup/profiles/test.cpp
index bc9aade..b37e3e6 100644
--- a/libprocessgroup/profiles/test.cpp
+++ b/libprocessgroup/profiles/test.cpp
@@ -33,14 +33,14 @@
}
// Test suite instantiations
-INSTANTIATE_TEST_SUITE_P(, JsonSchemaTest,
+INSTANTIATE_TEST_SUITE_P(Cgroups, JsonSchemaTest,
::testing::Values(MakeTestParam<Cgroups>("/cgroups.json"),
MakeTestParam<Cgroups>("/cgroups.recovery.json"),
MakeTestParam<TaskProfiles>("/task_profiles.json")));
-INSTANTIATE_TEST_SUITE_P(, CgroupsTest,
+INSTANTIATE_TEST_SUITE_P(Cgroups, CgroupsTest,
::testing::Values(MakeTestParam<Cgroups>("/cgroups.json"),
MakeTestParam<Cgroups>("/cgroups.recovery.json")));
-INSTANTIATE_TEST_SUITE_P(, TaskProfilesTest,
+INSTANTIATE_TEST_SUITE_P(TaskProfiles, TaskProfilesTest,
::testing::Values(MakeTestParam<TaskProfiles>("/task_profiles.json")));
} // namespace profiles
diff --git a/libunwindstack/tests/ArmExidxDecodeTest.cpp b/libunwindstack/tests/ArmExidxDecodeTest.cpp
index 7b1dd92..69a7816 100644
--- a/libunwindstack/tests/ArmExidxDecodeTest.cpp
+++ b/libunwindstack/tests/ArmExidxDecodeTest.cpp
@@ -1662,7 +1662,7 @@
ASSERT_EQ(0x10U, (*exidx_->regs())[15]);
}
-INSTANTIATE_TEST_SUITE_P(, ArmExidxDecodeTest,
+INSTANTIATE_TEST_SUITE_P(Unwindstack, ArmExidxDecodeTest,
::testing::Values("logging", "register_logging", "no_logging"));
} // namespace unwindstack
diff --git a/libutils/include/utils/Trace.h b/libutils/include/utils/Trace.h
index fec0ffa..9986bf5 100644
--- a/libutils/include/utils/Trace.h
+++ b/libutils/include/utils/Trace.h
@@ -33,7 +33,7 @@
// ATRACE_NAME traces from its location until the end of its enclosing scope.
#define _PASTE(x, y) x ## y
#define PASTE(x, y) _PASTE(x,y)
-#define ATRACE_NAME(name) android::ScopedTrace PASTE(___tracer, __LINE__) (ATRACE_TAG, name)
+#define ATRACE_NAME(name) ::android::ScopedTrace PASTE(___tracer, __LINE__)(ATRACE_TAG, name)
// ATRACE_CALL is an ATRACE_NAME that uses the current function name.
#define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 667bddc..e3bb2ab 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -196,4 +196,5 @@
srcs: ["libziparchive_fuzzer.cpp"],
static_libs: ["libziparchive", "libbase", "libz", "liblog"],
host_supported: true,
+ corpus: ["testdata/*"],
}
diff --git a/lmkd/Android.bp b/lmkd/Android.bp
index e8e125b..deebb8e 100644
--- a/lmkd/Android.bp
+++ b/lmkd/Android.bp
@@ -48,6 +48,7 @@
cc_library_static {
name: "liblmkd_utils",
srcs: ["liblmkd_utils.c"],
+ recovery_available: true,
shared_libs: [
"libcutils",
],
diff --git a/lmkd/include/liblmkd_utils.h b/lmkd/include/liblmkd_utils.h
index 72e3f4a..92e4d41 100644
--- a/lmkd/include/liblmkd_utils.h
+++ b/lmkd/include/liblmkd_utils.h
@@ -40,6 +40,14 @@
int lmkd_register_proc(int sock, struct lmk_procprio *params);
/*
+ * Unregisters a process previously registered with lmkd.
+ * On success returns 0.
+ * On error, -1 is returned.
+ * In the case of error errno is set appropriately.
+ */
+int lmkd_unregister_proc(int sock, struct lmk_procremove *params);
+
+/*
* Creates memcg directory for given process.
* On success returns 0.
* -1 is returned if path creation failed.
diff --git a/lmkd/include/lmkd.h b/lmkd/include/lmkd.h
index 59377dd..bd9b80e 100644
--- a/lmkd/include/lmkd.h
+++ b/lmkd/include/lmkd.h
@@ -87,21 +87,33 @@
return idx * sizeof(int);
}
+/* Process types for lmk_procprio.ptype */
+enum proc_type {
+ PROC_TYPE_FIRST,
+ PROC_TYPE_APP = PROC_TYPE_FIRST,
+ PROC_TYPE_SERVICE,
+ PROC_TYPE_COUNT,
+};
+
/* LMK_PROCPRIO packet payload */
struct lmk_procprio {
pid_t pid;
uid_t uid;
int oomadj;
+ enum proc_type ptype;
};
/*
* For LMK_PROCPRIO packet get its payload.
* Warning: no checks performed, caller should ensure valid parameters.
*/
-static inline void lmkd_pack_get_procprio(LMKD_CTRL_PACKET packet, struct lmk_procprio* params) {
+static inline void lmkd_pack_get_procprio(LMKD_CTRL_PACKET packet, int field_count,
+ struct lmk_procprio* params) {
params->pid = (pid_t)ntohl(packet[1]);
params->uid = (uid_t)ntohl(packet[2]);
params->oomadj = ntohl(packet[3]);
+ /* if field is missing assume PROC_TYPE_APP for backward compatibility */
+ params->ptype = field_count > 3 ? (enum proc_type)ntohl(packet[4]) : PROC_TYPE_APP;
}
/*
@@ -113,7 +125,8 @@
packet[1] = htonl(params->pid);
packet[2] = htonl(params->uid);
packet[3] = htonl(params->oomadj);
- return 4 * sizeof(int);
+ packet[4] = htonl((int)params->ptype);
+ return 5 * sizeof(int);
}
/* LMK_PROCREMOVE packet payload */
@@ -135,7 +148,7 @@
* Warning: no checks performed, caller should ensure valid parameters.
*/
static inline size_t lmkd_pack_set_procremove(LMKD_CTRL_PACKET packet,
- struct lmk_procprio* params) {
+ struct lmk_procremove* params) {
packet[0] = htonl(LMK_PROCREMOVE);
packet[1] = htonl(params->pid);
return 2 * sizeof(int);
diff --git a/lmkd/liblmkd_utils.c b/lmkd/liblmkd_utils.c
index fa3b7a9..280c149 100644
--- a/lmkd/liblmkd_utils.c
+++ b/lmkd/liblmkd_utils.c
@@ -28,7 +28,7 @@
int lmkd_connect() {
return socket_local_client("lmkd",
ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_SEQPACKET);
+ SOCK_SEQPACKET | SOCK_CLOEXEC);
}
int lmkd_register_proc(int sock, struct lmk_procprio *params) {
@@ -42,6 +42,17 @@
return (ret < 0) ? -1 : 0;
}
+int lmkd_unregister_proc(int sock, struct lmk_procremove *params) {
+ LMKD_CTRL_PACKET packet;
+ size_t size;
+ int ret;
+
+ size = lmkd_pack_set_procremove(packet, params);
+ ret = TEMP_FAILURE_RETRY(write(sock, packet, size));
+
+ return (ret < 0) ? -1 : 0;
+}
+
int create_memcg(uid_t uid, pid_t pid) {
char buf[256];
int tasks_file;
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 9de7ff7..4352498 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -45,6 +45,7 @@
#include <log/log.h>
#include <log/log_event_list.h>
#include <log/log_time.h>
+#include <private/android_filesystem_config.h>
#include <psi/psi.h>
#include <system/thread_defs.h>
@@ -240,11 +241,12 @@
/* data required to handle socket events */
struct sock_event_handler_info {
int sock;
+ pid_t pid;
struct event_handler_info handler_info;
};
-/* max supported number of data connections */
-#define MAX_DATA_CONN 2
+/* max supported number of data connections (AMS, init, tests) */
+#define MAX_DATA_CONN 3
/* socket event handler data */
static struct sock_event_handler_info ctrl_sock;
@@ -254,7 +256,7 @@
static struct event_handler_info vmpressure_hinfo[VMPRESS_LEVEL_COUNT];
/*
- * 1 ctrl listen socket, 2 ctrl data socket, 3 memory pressure levels,
+ * 1 ctrl listen socket, 3 ctrl data socket, 3 memory pressure levels,
* 1 lmk events + 1 fd to wait for process death
*/
#define MAX_EPOLL_EVENTS (1 + MAX_DATA_CONN + VMPRESS_LEVEL_COUNT + 1 + 1)
@@ -490,6 +492,7 @@
int pidfd;
uid_t uid;
int oomadj;
+ pid_t reg_pid; /* PID of the process that registered this record */
struct proc *pidhash_next;
};
@@ -845,7 +848,35 @@
return buf;
}
-static void cmd_procprio(LMKD_CTRL_PACKET packet) {
+static bool claim_record(struct proc *procp, pid_t pid) {
+ if (procp->reg_pid == pid) {
+ /* Record already belongs to the registrant */
+ return true;
+ }
+ if (procp->reg_pid == 0) {
+ /* Old registrant is gone, claim the record */
+ procp->reg_pid = pid;
+ return true;
+ }
+ /* The record is owned by another registrant */
+ return false;
+}
+
+static void remove_claims(pid_t pid) {
+ int i;
+
+ for (i = 0; i < PIDHASH_SZ; i++) {
+ struct proc *procp = pidhash[i];
+ while (procp) {
+ if (procp->reg_pid == pid) {
+ procp->reg_pid = 0;
+ }
+ procp = procp->pidhash_next;
+ }
+ }
+}
+
+static void cmd_procprio(LMKD_CTRL_PACKET packet, int field_count, struct ucred *cred) {
struct proc *procp;
char path[LINE_MAX];
char val[20];
@@ -855,7 +886,7 @@
struct passwd *pwdrec;
int tgid;
- lmkd_pack_get_procprio(packet, ¶ms);
+ lmkd_pack_get_procprio(packet, field_count, ¶ms);
if (params.oomadj < OOM_SCORE_ADJ_MIN ||
params.oomadj > OOM_SCORE_ADJ_MAX) {
@@ -863,6 +894,11 @@
return;
}
+ if (params.ptype < PROC_TYPE_FIRST || params.ptype >= PROC_TYPE_COUNT) {
+ ALOGE("Invalid PROCPRIO process type argument %d", params.ptype);
+ return;
+ }
+
/* Check if registered process is a thread group leader */
tgid = proc_get_tgid(params.pid);
if (tgid >= 0 && tgid != params.pid) {
@@ -889,7 +925,8 @@
return;
}
- if (per_app_memcg) {
+ /* lmkd should not change soft limits for services */
+ if (params.ptype == PROC_TYPE_APP && per_app_memcg) {
if (params.oomadj >= 900) {
soft_limit_mult = 0;
} else if (params.oomadj >= 800) {
@@ -954,24 +991,47 @@
procp->pid = params.pid;
procp->pidfd = pidfd;
procp->uid = params.uid;
+ procp->reg_pid = cred->pid;
procp->oomadj = params.oomadj;
proc_insert(procp);
} else {
+ if (!claim_record(procp, cred->pid)) {
+ char buf[LINE_MAX];
+ /* Only registrant of the record can remove it */
+ ALOGE("%s (%d, %d) attempts to modify a process registered by another client",
+ proc_get_name(cred->pid, buf, sizeof(buf)), cred->uid, cred->pid);
+ return;
+ }
proc_unslot(procp);
procp->oomadj = params.oomadj;
proc_slot(procp);
}
}
-static void cmd_procremove(LMKD_CTRL_PACKET packet) {
+static void cmd_procremove(LMKD_CTRL_PACKET packet, struct ucred *cred) {
struct lmk_procremove params;
+ struct proc *procp;
lmkd_pack_get_procremove(packet, ¶ms);
+
if (use_inkernel_interface) {
stats_remove_taskname(params.pid, kpoll_info.poll_fd);
return;
}
+ procp = pid_lookup(params.pid);
+ if (!procp) {
+ return;
+ }
+
+ if (!claim_record(procp, cred->pid)) {
+ char buf[LINE_MAX];
+ /* Only registrant of the record can remove it */
+ ALOGE("%s (%d, %d) attempts to unregister a process registered by another client",
+ proc_get_name(cred->pid, buf, sizeof(buf)), cred->uid, cred->pid);
+ return;
+ }
+
/*
* WARNING: After pid_remove() procp is freed and can't be used!
* Therefore placed at the end of the function.
@@ -979,7 +1039,7 @@
pid_remove(params.pid);
}
-static void cmd_procpurge() {
+static void cmd_procpurge(struct ucred *cred) {
int i;
struct proc *procp;
struct proc *next;
@@ -989,20 +1049,17 @@
return;
}
- for (i = 0; i <= ADJTOSLOT(OOM_SCORE_ADJ_MAX); i++) {
- procadjslot_list[i].next = &procadjslot_list[i];
- procadjslot_list[i].prev = &procadjslot_list[i];
- }
-
for (i = 0; i < PIDHASH_SZ; i++) {
procp = pidhash[i];
while (procp) {
next = procp->pidhash_next;
- free(procp);
+ /* Purge only records created by the requestor */
+ if (claim_record(procp, cred->pid)) {
+ pid_remove(procp->pid);
+ }
procp = next;
}
}
- memset(&pidhash[0], 0, sizeof(pidhash));
}
static void inc_killcnt(int oomadj) {
@@ -1153,19 +1210,50 @@
close(data_sock[dsock_idx].sock);
data_sock[dsock_idx].sock = -1;
+
+ /* Mark all records of the old registrant as unclaimed */
+ remove_claims(data_sock[dsock_idx].pid);
}
-static int ctrl_data_read(int dsock_idx, char *buf, size_t bufsz) {
- int ret = 0;
+static ssize_t ctrl_data_read(int dsock_idx, char *buf, size_t bufsz, struct ucred *sender_cred) {
+ struct iovec iov = { buf, bufsz };
+ char control[CMSG_SPACE(sizeof(struct ucred))];
+ struct msghdr hdr = {
+ NULL, 0, &iov, 1, control, sizeof(control), 0,
+ };
+ ssize_t ret;
- ret = TEMP_FAILURE_RETRY(read(data_sock[dsock_idx].sock, buf, bufsz));
-
+ ret = TEMP_FAILURE_RETRY(recvmsg(data_sock[dsock_idx].sock, &hdr, 0));
if (ret == -1) {
- ALOGE("control data socket read failed; errno=%d", errno);
- } else if (ret == 0) {
- ALOGE("Got EOF on control data socket");
- ret = -1;
+ ALOGE("control data socket read failed; %s", strerror(errno));
+ return -1;
}
+ if (ret == 0) {
+ ALOGE("Got EOF on control data socket");
+ return -1;
+ }
+
+ struct ucred* cred = NULL;
+ struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);
+ while (cmsg != NULL) {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) {
+ cred = (struct ucred*)CMSG_DATA(cmsg);
+ break;
+ }
+ cmsg = CMSG_NXTHDR(&hdr, cmsg);
+ }
+
+ if (cred == NULL) {
+ ALOGE("Failed to retrieve sender credentials");
+ /* Close the connection */
+ ctrl_data_close(dsock_idx);
+ return -1;
+ }
+
+ memcpy(sender_cred, cred, sizeof(struct ucred));
+
+ /* Store PID of the peer */
+ data_sock[dsock_idx].pid = cred->pid;
return ret;
}
@@ -1187,13 +1275,14 @@
static void ctrl_command_handler(int dsock_idx) {
LMKD_CTRL_PACKET packet;
+ struct ucred cred;
int len;
enum lmk_cmd cmd;
int nargs;
int targets;
int kill_cnt;
- len = ctrl_data_read(dsock_idx, (char *)packet, CTRL_PACKET_MAX_SIZE);
+ len = ctrl_data_read(dsock_idx, (char *)packet, CTRL_PACKET_MAX_SIZE, &cred);
if (len <= 0)
return;
@@ -1215,19 +1304,20 @@
cmd_target(targets, packet);
break;
case LMK_PROCPRIO:
- if (nargs != 3)
+ /* process type field is optional for backward compatibility */
+ if (nargs < 3 || nargs > 4)
goto wronglen;
- cmd_procprio(packet);
+ cmd_procprio(packet, nargs, &cred);
break;
case LMK_PROCREMOVE:
if (nargs != 1)
goto wronglen;
- cmd_procremove(packet);
+ cmd_procremove(packet, &cred);
break;
case LMK_PROCPURGE:
if (nargs != 0)
goto wronglen;
- cmd_procpurge();
+ cmd_procpurge(&cred);
break;
case LMK_GETKILLCNT:
if (nargs != 2)
diff --git a/lmkd/lmkd.rc b/lmkd/lmkd.rc
index 76b6055..982a188 100644
--- a/lmkd/lmkd.rc
+++ b/lmkd/lmkd.rc
@@ -4,5 +4,5 @@
group lmkd system readproc
capabilities DAC_OVERRIDE KILL IPC_LOCK SYS_NICE SYS_RESOURCE
critical
- socket lmkd seqpacket 0660 system system
+ socket lmkd seqpacket+passcred 0660 system system
writepid /dev/cpuset/system-background/tasks
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index eac3f06..19f117f 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -294,27 +294,6 @@
include $(BUILD_PREBUILT)
#######################################
-# {llndk,vndkcore,vndksp,vndkprivate,vndkcorevariant}.libraries.txt
-vndk_libraries_files := \
- llndk.libraries.txt:$(SOONG_LLNDK_LIBRARIES_FILE)\
- vndkcore.libraries.txt:$(SOONG_VNDKCORE_LIBRARIES_FILE)\
- vndksp.libraries.txt:$(SOONG_VNDKSP_LIBRARIES_FILE)\
- vndkprivate.libraries.txt:$(SOONG_VNDKPRIVATE_LIBRARIES_FILE)\
- vndkcorevariant.libraries.txt:$(SOONG_VNDKCOREVARIANT_LIBRARIES_FILE)
-
-$(foreach pair,$(vndk_libraries_files),\
- $(eval _filename := $(call word-colon,1,$(pair)))\
- $(eval _prebuilt := $(call word-colon,2,$(pair)))\
- $(eval include $(CLEAR_VARS))\
- $(eval LOCAL_MODULE := $(_filename))\
- $(eval LOCAL_MODULE_CLASS := ETC)\
- $(eval LOCAL_PREBUILT_MODULE_FILE := $(_prebuilt))\
- $(eval LOCAL_MODULE_PATH := $(TARGET_OUT_ETC))\
- $(eval LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE)))\
- $(eval include $(BUILD_PREBUILT)))
-vndk_libraries_files :=
-
-#######################################
# sanitizer.libraries.txt
include $(CLEAR_VARS)
LOCAL_MODULE := sanitizer.libraries.txt
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 66d60fa..0827247 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -347,6 +347,8 @@
# Start logd before any other services run to ensure we capture all of their logs.
start logd
+ # Start lmkd before any other services run so that it can register them
+ start lmkd
# Start essential services.
start servicemanager
@@ -486,26 +488,26 @@
# Start bootcharting as soon as possible after the data partition is
# mounted to collect more data.
- mkdir /data/bootchart 0755 shell shell
+ mkdir /data/bootchart 0755 shell shell encryption=Require
bootchart start
# Make sure that apexd is started in the default namespace
enter_default_mount_ns
# /data/apex is now available. Start apexd to scan and activate APEXes.
- mkdir /data/apex 0750 root system
+ mkdir /data/apex 0750 root system encryption=None
mkdir /data/apex/active 0750 root system
mkdir /data/apex/backup 0700 root system
mkdir /data/apex/hashtree 0700 root system
mkdir /data/apex/sessions 0700 root system
- mkdir /data/app-staging 0750 system system
+ mkdir /data/app-staging 0750 system system encryption=None
start apexd
# Avoid predictable entropy pool. Carry over entropy from previous boot.
copy /data/system/entropy.dat /dev/urandom
# create basic filesystem structure
- mkdir /data/misc 01771 system misc
+ mkdir /data/misc 01771 system misc encryption=Require
mkdir /data/misc/recovery 0770 system log
copy /data/misc/recovery/ro.build.fingerprint /data/misc/recovery/ro.build.fingerprint.1
chmod 0440 /data/misc/recovery/ro.build.fingerprint.1
@@ -548,7 +550,7 @@
mkdir /data/misc/user 0771 root root
# give system access to wpa_supplicant.conf for backup and restore
chmod 0660 /data/misc/wifi/wpa_supplicant.conf
- mkdir /data/local 0751 root root
+ mkdir /data/local 0751 root root encryption=Require
mkdir /data/misc/media 0700 media media
mkdir /data/misc/audioserver 0700 audioserver audioserver
mkdir /data/misc/cameraserver 0700 cameraserver cameraserver
@@ -567,89 +569,91 @@
mkdir /data/misc/gcov 0770 root root
mkdir /data/misc/installd 0700 root root
- mkdir /data/preloads 0775 system system
+ mkdir /data/preloads 0775 system system encryption=None
- mkdir /data/vendor 0771 root root
- mkdir /data/vendor_ce 0771 root root
- mkdir /data/vendor_de 0771 root root
+ mkdir /data/vendor 0771 root root encryption=Require
+ mkdir /data/vendor_ce 0771 root root encryption=None
+ mkdir /data/vendor_de 0771 root root encryption=None
mkdir /data/vendor/hardware 0771 root root
# For security reasons, /data/local/tmp should always be empty.
# Do not place files or directories in /data/local/tmp
mkdir /data/local/tmp 0771 shell shell
mkdir /data/local/traces 0777 shell shell
- mkdir /data/data 0771 system system
- mkdir /data/app-private 0771 system system
- mkdir /data/app-ephemeral 0771 system system
- mkdir /data/app-asec 0700 root root
- mkdir /data/app-lib 0771 system system
- mkdir /data/app 0771 system system
- mkdir /data/property 0700 root root
- mkdir /data/tombstones 0771 system system
+ mkdir /data/data 0771 system system encryption=None
+ mkdir /data/app-private 0771 system system encryption=Require
+ mkdir /data/app-ephemeral 0771 system system encryption=Require
+ mkdir /data/app-asec 0700 root root encryption=Require
+ mkdir /data/app-lib 0771 system system encryption=Require
+ mkdir /data/app 0771 system system encryption=Require
+ mkdir /data/property 0700 root root encryption=Require
+ mkdir /data/tombstones 0771 system system encryption=Require
mkdir /data/vendor/tombstones 0771 root root
mkdir /data/vendor/tombstones/wifi 0771 wifi wifi
# create dalvik-cache, so as to enforce our permissions
- mkdir /data/dalvik-cache 0771 root root
+ mkdir /data/dalvik-cache 0771 root root encryption=Require
# create the A/B OTA directory, so as to enforce our permissions
- mkdir /data/ota 0771 root root
+ mkdir /data/ota 0771 root root encryption=Require
# create the OTA package directory. It will be accessed by GmsCore (cache
# group), update_engine and update_verifier.
- mkdir /data/ota_package 0770 system cache
+ mkdir /data/ota_package 0770 system cache encryption=Require
# create resource-cache and double-check the perms
- mkdir /data/resource-cache 0771 system system
+ mkdir /data/resource-cache 0771 system system encryption=Require
chown system system /data/resource-cache
chmod 0771 /data/resource-cache
# create the lost+found directories, so as to enforce our permissions
- mkdir /data/lost+found 0770 root root
+ mkdir /data/lost+found 0770 root root encryption=None
# create directory for DRM plug-ins - give drm the read/write access to
# the following directory.
- mkdir /data/drm 0770 drm drm
+ mkdir /data/drm 0770 drm drm encryption=Require
# create directory for MediaDrm plug-ins - give drm the read/write access to
# the following directory.
- mkdir /data/mediadrm 0770 mediadrm mediadrm
+ mkdir /data/mediadrm 0770 mediadrm mediadrm encryption=Require
- mkdir /data/anr 0775 system system
+ mkdir /data/anr 0775 system system encryption=Require
# NFC: create data/nfc for nv storage
- mkdir /data/nfc 0770 nfc nfc
+ mkdir /data/nfc 0770 nfc nfc encryption=Require
mkdir /data/nfc/param 0770 nfc nfc
# Create all remaining /data root dirs so that they are made through init
# and get proper encryption policy installed
- mkdir /data/backup 0700 system system
- mkdir /data/ss 0700 system system
+ mkdir /data/backup 0700 system system encryption=Require
+ mkdir /data/ss 0700 system system encryption=Require
- mkdir /data/system 0775 system system
+ mkdir /data/system 0775 system system encryption=Require
mkdir /data/system/dropbox 0700 system system
mkdir /data/system/heapdump 0700 system system
mkdir /data/system/users 0775 system system
- mkdir /data/system_de 0770 system system
- mkdir /data/system_ce 0770 system system
+ mkdir /data/system_de 0770 system system encryption=None
+ mkdir /data/system_ce 0770 system system encryption=None
- mkdir /data/misc_de 01771 system misc
- mkdir /data/misc_ce 01771 system misc
+ mkdir /data/misc_de 01771 system misc encryption=None
+ mkdir /data/misc_ce 01771 system misc encryption=None
- mkdir /data/user 0711 system system
- mkdir /data/user_de 0711 system system
+ mkdir /data/user 0711 system system encryption=None
+ mkdir /data/user_de 0711 system system encryption=None
symlink /data/data /data/user/0
- mkdir /data/media 0770 media_rw media_rw
- mkdir /data/media/obb 0770 media_rw media_rw
+ # Special-case /data/media/obb per b/64566063
+ mkdir /data/media 0770 media_rw media_rw encryption=None
+ mkdir /data/media/obb 0770 media_rw media_rw encryption=Attempt
- mkdir /data/cache 0770 system cache
+ mkdir /data/cache 0770 system cache encryption=Require
mkdir /data/cache/recovery 0770 system cache
mkdir /data/cache/backup_stage 0700 system system
mkdir /data/cache/backup 0700 system system
- mkdir /data/rollback 0700 system system
- mkdir /data/rollback-observer 0700 system system
+ # Delete these if need be, per b/139193659
+ mkdir /data/rollback 0700 system system encryption=DeleteIfNecessary
+ mkdir /data/rollback-observer 0700 system system encryption=DeleteIfNecessary
# Wait for apexd to finish activating APEXes before starting more processes.
wait_for_prop apexd.status ready
@@ -867,7 +871,7 @@
bootchart stop
# Setup per_boot directory so other .rc could start to use it on boot_completed
exec - system system -- /bin/rm -rf /data/per_boot
- mkdir /data/per_boot 0700 system system
+ mkdir /data/per_boot 0700 system system encryption=Require key=per_boot_ref
# system server cannot write to /proc/sys files,
# and chown/chmod does not work for /proc/sys/ entries.
@@ -924,7 +928,7 @@
setprop sys.init.userspace_reboot_in_progress 1
setprop sys.boot_completed 0
setprop sys.init.updatable_crashing 0
- setprop apexd.status 0
+ setprop apexd.status ""
on userspace-reboot-fs-remount
# Make sure that vold is running.
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index 688d9ad..a1888fc 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -9,7 +9,7 @@
chown system system /sys/class/android_usb/android0/f_rndis/ethaddr
chmod 0660 /sys/class/android_usb/android0/f_rndis/ethaddr
mkdir /data/misc/adb 02750 system shell
- mkdir /data/adb 0700 root root
+ mkdir /data/adb 0700 root root encryption=Require
# adbd is controlled via property triggers in init.<platform>.usb.rc
service adbd /system/bin/adbd --root_seclabel=u:r:su:s0