From 1120f7f4a9d5a7391d7a34be9f0821379e6a9bc5 Mon Sep 17 00:00:00 2001 From: Sandro Date: Mon, 5 Sep 2022 15:56:38 +0000 Subject: [PATCH] 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 --- init/selinux.cpp | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/init/selinux.cpp b/init/selinux.cpp index be8c5542f..613798803 100644 --- a/init/selinux.cpp +++ b/init/selinux.cpp @@ -237,9 +237,9 @@ Result FindPrecompiledSplitPolicy() { // 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 @@ const std::vector kApexSepolicy{"apex_file_contexts", "apex_propert "apex_service_contexts", "apex_seapp_contexts", "apex_test"}; +Result 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 PutFileInTmpfs(ZipArchiveHandle archive, const std::string& fileName) { ZipEntry entry; std::string dstPath = kTmpfsDir + fileName; @@ -538,7 +563,7 @@ Result PutFileInTmpfs(ZipArchiveHandle archive, const std::string& fileNam 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 @@ Result GetPolicyFromApex(const std::string& dir) { 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()) {