Create /dev/selinux folder if it was not created by first-stage-init
The /dev/selinux folder is normally created by first-stage-init
https://cs.android.com/android/platform/superproject/+/master:system/core/init/first_stage_init.cpp;l=299-300;drc=07c86bace1e7a7cc4dd975f10b077d21c3743749
However, in some cases the first-stage-init comes from a GKI prebuilt
boot.img and doess not create the required folder (see for example
b/217677967), resulting in bugs like b/244793900.
I modified the selinux.cpp code to create the /dev/selinux folder if it
does not exist already, as a safety measure.
To verify these changes for b/244793900, follow gpaste/4922166775644160
Bug: 243923977
Test: atest SeamendcHostTest, manual verification
Change-Id: I8fe798643b1aeab2b4caac837055348febf70b94
diff --git a/init/selinux.cpp b/init/selinux.cpp
index be8c554..6137988 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -237,9 +237,9 @@
// If there is an odm partition, precompiled_sepolicy will be in
// odm/etc/selinux. Otherwise it will be in vendor/etc/selinux.
static constexpr const char vendor_precompiled_sepolicy[] =
- "/vendor/etc/selinux/precompiled_sepolicy";
+ "/vendor/etc/selinux/precompiled_sepolicy";
static constexpr const char odm_precompiled_sepolicy[] =
- "/odm/etc/selinux/precompiled_sepolicy";
+ "/odm/etc/selinux/precompiled_sepolicy";
if (access(odm_precompiled_sepolicy, R_OK) == 0) {
precompiled_sepolicy = odm_precompiled_sepolicy;
} else if (access(vendor_precompiled_sepolicy, R_OK) == 0) {
@@ -525,6 +525,31 @@
"apex_service_contexts", "apex_seapp_contexts",
"apex_test"};
+Result<void> CreateTmpfsDirIfNeeded() {
+ mode_t mode = 0744;
+ struct stat stat_data;
+ if (stat(kTmpfsDir.c_str(), &stat_data) != 0) {
+ if (errno != ENOENT) {
+ return ErrnoError() << "Could not stat " << kTmpfsDir;
+ }
+ if (mkdir(kTmpfsDir.c_str(), mode) != 0) {
+ return ErrnoError() << "Could not mkdir " << kTmpfsDir;
+ }
+ } else {
+ if (!S_ISDIR(stat_data.st_mode)) {
+ return Error() << kTmpfsDir << " exists and is not a directory.";
+ }
+ }
+
+ // Need to manually call chmod because mkdir will create a folder with
+ // permissions mode & ~umask.
+ if (chmod(kTmpfsDir.c_str(), mode) != 0) {
+ return ErrnoError() << "Could not chmod " << kTmpfsDir;
+ }
+
+ return {};
+}
+
Result<void> PutFileInTmpfs(ZipArchiveHandle archive, const std::string& fileName) {
ZipEntry entry;
std::string dstPath = kTmpfsDir + fileName;
@@ -538,7 +563,7 @@
unique_fd fd(TEMP_FAILURE_RETRY(
open(dstPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, S_IRUSR | S_IWUSR)));
if (fd == -1) {
- return Error() << "Failed to open " << dstPath;
+ return ErrnoError() << "Failed to open " << dstPath;
}
ret = ExtractEntryToFile(archive, &entry, fd);
@@ -568,6 +593,11 @@
auto handle_guard = android::base::make_scope_guard([&handle] { CloseArchive(handle); });
+ auto create = CreateTmpfsDirIfNeeded();
+ if (!create.ok()) {
+ return create.error();
+ }
+
for (const auto& file : kApexSepolicy) {
auto extract = PutFileInTmpfs(handle, file);
if (!extract.ok()) {