Merge "create_snapshot: Create snapshot patch comparing two partition images" into main
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index e929f42..d605393 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -661,6 +661,17 @@
if (!android::gsi::DisableGsi()) {
return device->WriteStatus(FastbootResult::FAIL, strerror(errno));
}
+ } else if (args[1] == "status") {
+ std::string active_dsu;
+ if (!android::gsi::IsGsiRunning()) {
+ device->WriteInfo("Not running");
+ } else if (!android::gsi::GetActiveDsu(&active_dsu)) {
+ return device->WriteFail(strerror(errno));
+ } else {
+ device->WriteInfo("Running active DSU: " + active_dsu);
+ }
+ } else {
+ return device->WriteFail("Invalid arguments");
}
return device->WriteStatus(FastbootResult::OKAY, "Success");
}
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 8c607dd..d7e3db6 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -350,23 +350,22 @@
//
// The returned Transport is a singleton, so multiple calls to this function will return the same
// object, and the caller should not attempt to delete the returned Transport.
-static Transport* open_device(const char* local_serial, bool wait_for_device = true,
- bool announce = true) {
+static std::unique_ptr<Transport> open_device(const char* local_serial,
+ bool wait_for_device = true,
+ bool announce = true) {
const Result<NetworkSerial, FastbootError> network_serial = ParseNetworkSerial(local_serial);
- Transport* transport = nullptr;
+ std::unique_ptr<Transport> transport;
while (true) {
if (network_serial.ok()) {
std::string error;
if (network_serial->protocol == Socket::Protocol::kTcp) {
- transport = tcp::Connect(network_serial->address, network_serial->port, &error)
- .release();
+ transport = tcp::Connect(network_serial->address, network_serial->port, &error);
} else if (network_serial->protocol == Socket::Protocol::kUdp) {
- transport = udp::Connect(network_serial->address, network_serial->port, &error)
- .release();
+ transport = udp::Connect(network_serial->address, network_serial->port, &error);
}
- if (transport == nullptr && announce) {
+ if (!transport && announce) {
LOG(ERROR) << "error: " << error;
}
} else if (network_serial.error().code() ==
@@ -378,12 +377,12 @@
Expect(network_serial);
}
- if (transport != nullptr) {
+ if (transport) {
return transport;
}
if (!wait_for_device) {
- return nullptr;
+ return transport;
}
if (announce) {
@@ -394,9 +393,9 @@
}
}
-static Transport* NetworkDeviceConnected(bool print = false) {
- Transport* transport = nullptr;
- Transport* result = nullptr;
+static std::unique_ptr<Transport> NetworkDeviceConnected(bool print = false) {
+ std::unique_ptr<Transport> transport;
+ std::unique_ptr<Transport> result;
ConnectedDevicesStorage storage;
std::set<std::string> devices;
@@ -409,11 +408,11 @@
transport = open_device(device.c_str(), false, false);
if (print) {
- PrintDevice(device.c_str(), transport == nullptr ? "offline" : "fastboot");
+ PrintDevice(device.c_str(), transport ? "offline" : "fastboot");
}
- if (transport != nullptr) {
- result = transport;
+ if (transport) {
+ result = std::move(transport);
}
}
@@ -431,21 +430,21 @@
//
// The returned Transport is a singleton, so multiple calls to this function will return the same
// object, and the caller should not attempt to delete the returned Transport.
-static Transport* open_device() {
+static std::unique_ptr<Transport> open_device() {
if (serial != nullptr) {
return open_device(serial);
}
bool announce = true;
- Transport* transport = nullptr;
+ std::unique_ptr<Transport> transport;
while (true) {
transport = usb_open(match_fastboot(nullptr));
- if (transport != nullptr) {
+ if (transport) {
return transport;
}
transport = NetworkDeviceConnected();
- if (transport != nullptr) {
+ if (transport) {
return transport;
}
@@ -455,6 +454,8 @@
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
+
+ return transport;
}
static int Connect(int argc, char* argv[]) {
@@ -466,8 +467,7 @@
const char* local_serial = *argv;
Expect(ParseNetworkSerial(local_serial));
- const Transport* transport = open_device(local_serial, false);
- if (transport == nullptr) {
+ if (!open_device(local_serial, false)) {
return 1;
}
@@ -531,6 +531,7 @@
usb_open(list_devices_callback);
NetworkDeviceConnected(/* print */ true);
}
+
void syntax_error(const char* fmt, ...) {
fprintf(stderr, "fastboot: usage: ");
@@ -1547,9 +1548,7 @@
void reboot_to_userspace_fastboot() {
fb->RebootTo("fastboot");
-
- auto* old_transport = fb->set_transport(nullptr);
- delete old_transport;
+ fb->set_transport(nullptr);
// Give the current connection time to close.
std::this_thread::sleep_for(std::chrono::seconds(1));
@@ -2372,8 +2371,8 @@
return show_help();
}
- Transport* transport = open_device();
- if (transport == nullptr) {
+ std::unique_ptr<Transport> transport = open_device();
+ if (!transport) {
return 1;
}
fastboot::DriverCallbacks driver_callbacks = {
@@ -2383,7 +2382,7 @@
.text = TextMessage,
};
- fastboot::FastBootDriver fastboot_driver(transport, driver_callbacks, false);
+ fastboot::FastBootDriver fastboot_driver(std::move(transport), driver_callbacks, false);
fb = &fastboot_driver;
fp->fb = &fastboot_driver;
@@ -2574,14 +2573,12 @@
std::make_unique<ResizeTask>(fp.get(), partition, size, fp->slot_override);
resize_task->Run();
} else if (command == "gsi") {
- std::string arg = next_arg(&args);
- if (arg == "wipe") {
- fb->RawCommand("gsi:wipe", "wiping GSI");
- } else if (arg == "disable") {
- fb->RawCommand("gsi:disable", "disabling GSI");
- } else {
- syntax_error("expected 'wipe' or 'disable'");
+ if (args.empty()) syntax_error("invalid gsi command");
+ std::string cmd("gsi");
+ while (!args.empty()) {
+ cmd += ":" + next_arg(&args);
}
+ fb->RawCommand(cmd, "");
} else if (command == "wipe-super") {
std::string image;
if (args.empty()) {
@@ -2628,9 +2625,6 @@
}
fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start));
- auto* old_transport = fb->set_transport(nullptr);
- delete old_transport;
-
return 0;
}
diff --git a/fastboot/fastboot_driver.cpp b/fastboot/fastboot_driver.cpp
index 9770ab2..e5ef66b 100644
--- a/fastboot/fastboot_driver.cpp
+++ b/fastboot/fastboot_driver.cpp
@@ -58,9 +58,10 @@
namespace fastboot {
/*************************** PUBLIC *******************************/
-FastBootDriver::FastBootDriver(Transport* transport, DriverCallbacks driver_callbacks,
+FastBootDriver::FastBootDriver(std::unique_ptr<Transport> transport,
+ DriverCallbacks driver_callbacks,
bool no_checks)
- : transport_(transport),
+ : transport_(std::move(transport)),
prolog_(std::move(driver_callbacks.prolog)),
epilog_(std::move(driver_callbacks.epilog)),
info_(std::move(driver_callbacks.info)),
@@ -627,9 +628,8 @@
return 0;
}
-Transport* FastBootDriver::set_transport(Transport* transport) {
- std::swap(transport_, transport);
- return transport;
+void FastBootDriver::set_transport(std::unique_ptr<Transport> transport) {
+ transport_ = std::move(transport);
}
} // End namespace fastboot
diff --git a/fastboot/fastboot_driver.h b/fastboot/fastboot_driver.h
index 8774ead..30298cb 100644
--- a/fastboot/fastboot_driver.h
+++ b/fastboot/fastboot_driver.h
@@ -30,6 +30,7 @@
#include <deque>
#include <functional>
#include <limits>
+#include <memory>
#include <string>
#include <vector>
@@ -63,7 +64,7 @@
static constexpr uint32_t MAX_DOWNLOAD_SIZE = std::numeric_limits<uint32_t>::max();
static constexpr size_t TRANSPORT_CHUNK_SIZE = 1024;
- FastBootDriver(Transport* transport, DriverCallbacks driver_callbacks = {},
+ FastBootDriver(std::unique_ptr<Transport> transport, DriverCallbacks driver_callbacks = {},
bool no_checks = false);
~FastBootDriver();
@@ -124,9 +125,7 @@
std::string Error();
RetCode WaitForDisconnect() override;
- // Note: set_transport will return the previous transport.
- Transport* set_transport(Transport* transport);
- Transport* transport() const { return transport_; }
+ void set_transport(std::unique_ptr<Transport> transport);
RetCode RawCommand(const std::string& cmd, const std::string& message,
std::string* response = nullptr, std::vector<std::string>* info = nullptr,
@@ -143,7 +142,7 @@
std::string ErrnoStr(const std::string& msg);
- Transport* transport_;
+ std::unique_ptr<Transport> transport_;
private:
RetCode SendBuffer(android::base::borrowed_fd fd, size_t size);
diff --git a/fastboot/fastboot_driver_test.cpp b/fastboot/fastboot_driver_test.cpp
index 6f6cf8c..d2033b0 100644
--- a/fastboot/fastboot_driver_test.cpp
+++ b/fastboot/fastboot_driver_test.cpp
@@ -16,6 +16,7 @@
#include "fastboot_driver.h"
+#include <memory>
#include <optional>
#include <gtest/gtest.h>
@@ -30,13 +31,14 @@
};
TEST_F(DriverTest, GetVar) {
- MockTransport transport;
- FastBootDriver driver(&transport);
+ std::unique_ptr<MockTransport> transport_pointer = std::make_unique<MockTransport>();
+ MockTransport* transport = transport_pointer.get();
+ FastBootDriver driver(std::move(transport_pointer));
- EXPECT_CALL(transport, Write(_, _))
+ EXPECT_CALL(*transport, Write(_, _))
.With(AllArgs(RawData("getvar:version")))
.WillOnce(ReturnArg<1>());
- EXPECT_CALL(transport, Read(_, _)).WillOnce(Invoke(CopyData("OKAY0.4")));
+ EXPECT_CALL(*transport, Read(_, _)).WillOnce(Invoke(CopyData("OKAY0.4")));
std::string output;
ASSERT_EQ(driver.GetVar("version", &output), SUCCESS) << driver.Error();
@@ -44,14 +46,15 @@
}
TEST_F(DriverTest, InfoMessage) {
- MockTransport transport;
- FastBootDriver driver(&transport);
+ std::unique_ptr<MockTransport> transport_pointer = std::make_unique<MockTransport>();
+ MockTransport* transport = transport_pointer.get();
+ FastBootDriver driver(std::move(transport_pointer));
- EXPECT_CALL(transport, Write(_, _))
+ EXPECT_CALL(*transport, Write(_, _))
.With(AllArgs(RawData("oem dmesg")))
.WillOnce(ReturnArg<1>());
- EXPECT_CALL(transport, Read(_, _)).WillOnce(Invoke(CopyData("INFOthis is an info line")));
- EXPECT_CALL(transport, Read(_, _)).WillOnce(Invoke(CopyData("OKAY")));
+ EXPECT_CALL(*transport, Read(_, _)).WillOnce(Invoke(CopyData("INFOthis is an info line")));
+ EXPECT_CALL(*transport, Read(_, _)).WillOnce(Invoke(CopyData("OKAY")));
std::vector<std::string> info;
ASSERT_EQ(driver.RawCommand("oem dmesg", "", nullptr, &info), SUCCESS) << driver.Error();
@@ -60,28 +63,29 @@
}
TEST_F(DriverTest, TextMessage) {
- MockTransport transport;
std::string text;
+ std::unique_ptr<MockTransport> transport_pointer = std::make_unique<MockTransport>();
+ MockTransport* transport = transport_pointer.get();
DriverCallbacks callbacks{[](const std::string&) {}, [](int) {}, [](const std::string&) {},
[&text](const std::string& extra_text) { text += extra_text; }};
- FastBootDriver driver(&transport, callbacks);
+ FastBootDriver driver(std::move(transport_pointer), callbacks);
- EXPECT_CALL(transport, Write(_, _))
+ EXPECT_CALL(*transport, Write(_, _))
.With(AllArgs(RawData("oem trusty runtest trusty.hwaes.bench")))
.WillOnce(ReturnArg<1>());
- EXPECT_CALL(transport, Read(_, _)).WillOnce(Invoke(CopyData("TEXTthis is a text line")));
- EXPECT_CALL(transport, Read(_, _))
+ EXPECT_CALL(*transport, Read(_, _)).WillOnce(Invoke(CopyData("TEXTthis is a text line")));
+ EXPECT_CALL(*transport, Read(_, _))
.WillOnce(Invoke(
CopyData("TEXT, albeit very long and split over multiple TEXT messages.")));
- EXPECT_CALL(transport, Read(_, _))
+ EXPECT_CALL(*transport, Read(_, _))
.WillOnce(Invoke(CopyData("TEXT Indeed we can do that now with a TEXT message whenever "
"we feel like it.")));
- EXPECT_CALL(transport, Read(_, _))
+ EXPECT_CALL(*transport, Read(_, _))
.WillOnce(Invoke(CopyData("TEXT Isn't that truly super cool?")));
- EXPECT_CALL(transport, Read(_, _)).WillOnce(Invoke(CopyData("OKAY")));
+ EXPECT_CALL(*transport, Read(_, _)).WillOnce(Invoke(CopyData("OKAY")));
std::vector<std::string> info;
ASSERT_EQ(driver.RawCommand("oem trusty runtest trusty.hwaes.bench", "", nullptr, &info),
diff --git a/fastboot/fuzzy_fastboot/fixtures.cpp b/fastboot/fuzzy_fastboot/fixtures.cpp
index 9b5e5f7..94a53ed 100644
--- a/fastboot/fuzzy_fastboot/fixtures.cpp
+++ b/fastboot/fuzzy_fastboot/fixtures.cpp
@@ -128,7 +128,7 @@
return MatchFastboot(info, device_serial);
};
for (int i = 0; i < MAX_USB_TRIES && !transport; i++) {
- std::unique_ptr<UsbTransport> usb(usb_open(matcher, USB_TIMEOUT));
+ std::unique_ptr<UsbTransport> usb = usb_open(matcher, USB_TIMEOUT);
if (usb)
transport = std::unique_ptr<TransportSniffer>(
new TransportSniffer(std::move(usb), serial_port));
@@ -143,7 +143,7 @@
} else {
ASSERT_EQ(device_path, cb_scratch); // The path can not change
}
- fb = std::unique_ptr<FastBootDriver>(new FastBootDriver(transport.get(), {}, true));
+ fb = std::unique_ptr<FastBootDriver>(new FastBootDriver(std::move(transport), {}, true));
// No error checking since non-A/B devices may not support the command
fb->GetVar("current-slot", &initial_slot);
}
@@ -200,7 +200,7 @@
if (IsFastbootOverTcp()) {
ConnectTcpFastbootDevice();
device_path = cb_scratch;
- fb = std::unique_ptr<FastBootDriver>(new FastBootDriver(transport.get(), {}, true));
+ fb = std::unique_ptr<FastBootDriver>(new FastBootDriver(std::move(transport), {}, true));
return;
}
@@ -212,7 +212,7 @@
return MatchFastboot(info, device_serial);
};
while (!transport) {
- std::unique_ptr<UsbTransport> usb(usb_open(matcher, USB_TIMEOUT));
+ std::unique_ptr<UsbTransport> usb = usb_open(matcher, USB_TIMEOUT);
if (usb) {
transport = std::unique_ptr<TransportSniffer>(
new TransportSniffer(std::move(usb), serial_port));
@@ -220,7 +220,7 @@
std::this_thread::sleep_for(1s);
}
device_path = cb_scratch;
- fb = std::unique_ptr<FastBootDriver>(new FastBootDriver(transport.get(), {}, true));
+ fb = std::unique_ptr<FastBootDriver>(new FastBootDriver(std::move(transport), {}, true));
}
void FastBootTest::SetLockState(bool unlock, bool assert_change) {
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp
index e635937..43aaec9 100644
--- a/fastboot/fuzzy_fastboot/main.cpp
+++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -166,16 +166,15 @@
const auto matcher = [](usb_ifc_info* info) -> int {
return FastBootTest::MatchFastboot(info, fastboot::FastBootTest::device_serial);
};
- Transport* transport = nullptr;
+ std::unique_ptr<Transport> transport;
for (int i = 0; i < FastBootTest::MAX_USB_TRIES && !transport; i++) {
transport = usb_open(matcher);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
- ASSERT_NE(transport, nullptr) << "Could not find the fastboot device after: "
- << 10 * FastBootTest::MAX_USB_TRIES << "ms";
+ ASSERT_NE(transport.get(), nullptr) << "Could not find the fastboot device after: "
+ << 10 * FastBootTest::MAX_USB_TRIES << "ms";
if (transport) {
transport->Close();
- delete transport;
}
}
@@ -1897,7 +1896,7 @@
const auto matcher = [](usb_ifc_info* info) -> int {
return fastboot::FastBootTest::MatchFastboot(info, fastboot::FastBootTest::device_serial);
};
- Transport* transport = nullptr;
+ std::unique_ptr<Transport> transport;
while (!transport) {
transport = usb_open(matcher);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
diff --git a/fastboot/usb.h b/fastboot/usb.h
index 69581ab..d85cb81 100644
--- a/fastboot/usb.h
+++ b/fastboot/usb.h
@@ -29,6 +29,7 @@
#pragma once
#include <functional>
+#include <memory>
#include "transport.h"
@@ -66,4 +67,4 @@
typedef std::function<int(usb_ifc_info*)> ifc_match_func;
// 0 is non blocking
-UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms = 0);
+std::unique_ptr<UsbTransport> usb_open(ifc_match_func callback, uint32_t timeout_ms = 0);
diff --git a/fastboot/usb_linux.cpp b/fastboot/usb_linux.cpp
index 964488c..37bb304 100644
--- a/fastboot/usb_linux.cpp
+++ b/fastboot/usb_linux.cpp
@@ -503,9 +503,15 @@
return 0;
}
-UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms) {
+std::unique_ptr<UsbTransport> usb_open(ifc_match_func callback, uint32_t timeout_ms) {
+ std::unique_ptr<UsbTransport> result;
std::unique_ptr<usb_handle> handle = find_usb_device("/sys/bus/usb/devices", callback);
- return handle ? new LinuxUsbTransport(std::move(handle), timeout_ms) : nullptr;
+
+ if (handle) {
+ result = std::make_unique<LinuxUsbTransport>(std::move(handle), timeout_ms);
+ }
+
+ return result;
}
/* Wait for the system to notice the device is gone, so that a subsequent
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index 8b852f5..28300b2 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -469,16 +469,20 @@
/*
* Definitions of this file's public functions.
*/
-
-UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms) {
+std::unique_ptr<UsbTransport> usb_open(ifc_match_func callback, uint32_t timeout_ms) {
+ std::unique_ptr<UsbTransport> result;
std::unique_ptr<usb_handle> handle;
if (init_usb(callback, &handle) < 0) {
/* Something went wrong initializing USB. */
- return nullptr;
+ return result;
}
- return new OsxUsbTransport(std::move(handle), timeout_ms);
+ if (handle) {
+ result = std::make_unique<OsxUsbTransport>(std::move(handle), timeout_ms);
+ }
+
+ return result;
}
OsxUsbTransport::~OsxUsbTransport() {
diff --git a/fastboot/usb_windows.cpp b/fastboot/usb_windows.cpp
index 67bf8a3..56a6e7d 100644
--- a/fastboot/usb_windows.cpp
+++ b/fastboot/usb_windows.cpp
@@ -381,7 +381,13 @@
return handle;
}
-UsbTransport* usb_open(ifc_match_func callback, uint32_t) {
+std::unique_ptr<UsbTransport> usb_open(ifc_match_func callback, uint32_t) {
+ std::unique_ptr<UsbTransport> result;
std::unique_ptr<usb_handle> handle = find_usb_device(callback);
- return handle ? new WindowsUsbTransport(std::move(handle)) : nullptr;
+
+ if (handle) {
+ result = std::make_unique<WindowsUsbTransport>(std::move(handle));
+ }
+
+ return result;
}
diff --git a/init/Android.bp b/init/Android.bp
index d4852d6..4c25ad7 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -174,7 +174,6 @@
"libprotobuf-cpp-lite",
"libpropertyinfoserializer",
"libpropertyinfoparser",
- "libsigningutils",
"libsnapshot_cow",
"libsnapshot_init",
"libxml2",
@@ -183,7 +182,6 @@
],
shared_libs: [
"libbase",
- "libcrypto",
"libcutils",
"libdl",
"libext4_utils",
@@ -199,7 +197,6 @@
"libselinux",
"libunwindstack",
"libutils",
- "libziparchive",
],
header_libs: ["bionic_libc_platform_headers"],
bootstrap: true,
diff --git a/init/TEST_MAPPING b/init/TEST_MAPPING
index 402b501..36ca379 100644
--- a/init/TEST_MAPPING
+++ b/init/TEST_MAPPING
@@ -8,14 +8,6 @@
},
{
"name": "MicrodroidHostTestCases"
- },
- {
- "name": "CtsSecurityHostTestCases",
- "options": [
- {
- "include-filter": "android.security.cts.SeamendcHostTest"
- }
- ]
}
],
"hwasan-presubmit": [
@@ -27,14 +19,6 @@
},
{
"name": "MicrodroidHostTestCases"
- },
- {
- "name": "CtsSecurityHostTestCases",
- "options": [
- {
- "include-filter": "android.security.cts.SeamendcHostTest"
- }
- ]
}
]
}
diff --git a/init/property_service.cpp b/init/property_service.cpp
index f5de17d..2064fae 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -1247,9 +1247,6 @@
// Don't check for failure here, since we don't always have all of these partitions.
// E.g. In case of recovery, the vendor partition will not have mounted and we
// still need the system / platform properties to function.
- if (access("/dev/selinux/apex_property_contexts", R_OK) != -1) {
- LoadPropertyInfoFromFile("/dev/selinux/apex_property_contexts", &property_infos);
- }
if (access("/system_ext/etc/selinux/system_ext_property_contexts", R_OK) != -1) {
LoadPropertyInfoFromFile("/system_ext/etc/selinux/system_ext_property_contexts",
&property_infos);
@@ -1273,7 +1270,6 @@
LoadPropertyInfoFromFile("/vendor_property_contexts", &property_infos);
LoadPropertyInfoFromFile("/product_property_contexts", &property_infos);
LoadPropertyInfoFromFile("/odm_property_contexts", &property_infos);
- LoadPropertyInfoFromFile("/dev/selinux/apex_property_contexts", &property_infos);
}
auto serialized_contexts = std::string();
diff --git a/init/selinux.cpp b/init/selinux.cpp
index ac102eb..9095b85 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -26,29 +26,26 @@
// The monolithic policy variant is for legacy non-treble devices that contain a single SEPolicy
// file located at /sepolicy and is directly loaded into the kernel SELinux subsystem.
-// The split policy is for supporting treble devices and updateable apexes. It splits the SEPolicy
-// across files on /system/etc/selinux (the 'plat' portion of the policy), /vendor/etc/selinux
-// (the 'vendor' portion of the policy), /system_ext/etc/selinux, /product/etc/selinux,
-// /odm/etc/selinux, and /dev/selinux (the apex portion of policy). This is necessary to allow
-// images to be updated independently of the vendor image, while maintaining contributions from
-// multiple partitions in the SEPolicy. This is especially important for VTS testing, where the
-// SEPolicy on the Google System Image may not be identical to the system image shipped on a
-// vendor's device.
+// The split policy is for supporting treble devices. It splits the SEPolicy across files on
+// /system/etc/selinux (the 'plat' portion of the policy) and /vendor/etc/selinux (the 'vendor'
+// portion of the policy). This is necessary to allow the system image to be updated independently
+// of the vendor image, while maintaining contributions from both partitions in the SEPolicy. This
+// is especially important for VTS testing, where the SEPolicy on the Google System Image may not be
+// identical to the system image shipped on a vendor's device.
// The split SEPolicy is loaded as described below:
// 1) There is a precompiled SEPolicy located at either /vendor/etc/selinux/precompiled_sepolicy or
// /odm/etc/selinux/precompiled_sepolicy if odm parition is present. Stored along with this file
-// are the sha256 hashes of the parts of the SEPolicy on /system, /system_ext, /product, and apex
-// that were used to compile this precompiled policy. The system partition contains a similar
-// sha256 of the parts of the SEPolicy that it currently contains. Symmetrically, system_ext,
-// product, and apex contain sha256 hashes of their SEPolicy. Init loads this
+// are the sha256 hashes of the parts of the SEPolicy on /system, /system_ext and /product that
+// were used to compile this precompiled policy. The system partition contains a similar sha256
+// of the parts of the SEPolicy that it currently contains. Symmetrically, system_ext and
+// product paritition contain sha256 hashes of their SEPolicy. The init loads this
// precompiled_sepolicy directly if and only if the hashes along with the precompiled SEPolicy on
-// /vendor or /odm match the hashes for system, system_ext, product, and apex SEPolicy,
-// respectively.
-// 2) If these hashes do not match, then either /system or /system_ext /product, or apex (or some of
-// them) have been updated out of sync with /vendor (or /odm if it is present) and the init needs
-// to compile the SEPolicy. /system contains the SEPolicy compiler, secilc, and it is used by
-// the OpenSplitPolicy() function below to compile the SEPolicy to a temp directory and load it.
+// /vendor or /odm match the hashes for system, system_ext and product SEPolicy, respectively.
+// 2) If these hashes do not match, then either /system or /system_ext or /product (or some of them)
+// have been updated out of sync with /vendor (or /odm if it is present) and the init needs to
+// compile the SEPolicy. /system contains the SEPolicy compiler, secilc, and it is used by the
+// OpenSplitPolicy() function below to compile the SEPolicy to a temp directory and load it.
// That function contains even more documentation with the specific implementation details of how
// the SEPolicy is compiled if needed.
@@ -61,15 +58,12 @@
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
-#include <fstream>
-#include <CertUtils.h>
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/result.h>
-#include <android-base/scopeguard.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <fs_avb/fs_avb.h>
@@ -77,7 +71,6 @@
#include <libgsi/libgsi.h>
#include <libsnapshot/snapshot.h>
#include <selinux/android.h>
-#include <ziparchive/zip_archive.h>
#include "block_dev_initializer.h"
#include "debug_ramdisk.h"
@@ -245,7 +238,6 @@
precompiled_sepolicy + ".system_ext_sepolicy_and_mapping.sha256"},
{"/product/etc/selinux/product_sepolicy_and_mapping.sha256",
precompiled_sepolicy + ".product_sepolicy_and_mapping.sha256"},
- {"/dev/selinux/apex_sepolicy.sha256", precompiled_sepolicy + ".apex_sepolicy.sha256"},
};
for (const auto& [actual_id_path, precompiled_id_path] : sepolicy_hashes) {
@@ -324,7 +316,7 @@
// * vendor -- policy needed due to logic contained in the vendor image,
// * mapping -- mapping policy which helps preserve forward-compatibility of non-platform policy
// with newer versions of platform policy.
- // * (optional) policy needed due to logic on product, system_ext, odm, or apex.
+ // * (optional) policy needed due to logic on product, system_ext, or odm images.
// secilc is invoked to compile the above three policy files into a single monolithic policy
// file. This file is then loaded into the kernel.
@@ -420,12 +412,6 @@
if (access(odm_policy_cil_file.c_str(), F_OK) == -1) {
odm_policy_cil_file.clear();
}
-
- // apex_sepolicy.cil is default but optional.
- std::string apex_policy_cil_file("/dev/selinux/apex_sepolicy.cil");
- if (access(apex_policy_cil_file.c_str(), F_OK) == -1) {
- apex_policy_cil_file.clear();
- }
const std::string version_as_string = std::to_string(SEPOLICY_VERSION);
// clang-format off
@@ -468,9 +454,6 @@
if (!odm_policy_cil_file.empty()) {
compile_args.push_back(odm_policy_cil_file.c_str());
}
- if (!apex_policy_cil_file.empty()) {
- compile_args.push_back(apex_policy_cil_file.c_str());
- }
compile_args.push_back(nullptr);
if (!ForkExecveAndWaitForCompletion(compile_args[0], (char**)compile_args.data())) {
@@ -497,194 +480,6 @@
return true;
}
-constexpr const char* kSigningCertRelease =
- "/system/etc/selinux/com.android.sepolicy.cert-release.der";
-const std::string kSepolicyApexMetadataDir = "/metadata/sepolicy/";
-const std::string kSepolicyApexSystemDir = "/system/etc/selinux/apex/";
-const std::string kSepolicyZip = "SEPolicy.zip";
-const std::string kSepolicySignature = "SEPolicy.zip.sig";
-
-const std::string kTmpfsDir = "/dev/selinux/";
-
-// Files that are deleted after policy is compiled/loaded.
-const std::vector<std::string> kApexSepolicyTmp{"apex_sepolicy.cil", "apex_sepolicy.sha256"};
-// Files that need to persist because they are used by userspace processes.
-const std::vector<std::string> kApexSepolicy{"apex_file_contexts", "apex_property_contexts",
- "apex_service_contexts", "apex_seapp_contexts",
- "apex_test"};
-
-Result<void> CreateTmpfsDir() {
- 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.";
- }
- LOG(WARNING) << "Directory " << kTmpfsDir << " already exists";
- }
-
- // 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;
-
- int ret = FindEntry(archive, fileName, &entry);
- if (ret != 0) {
- // All files are optional. If a file doesn't exist, return without error.
- return {};
- }
-
- 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 ErrnoError() << "Failed to open " << dstPath;
- }
-
- ret = ExtractEntryToFile(archive, &entry, fd.get());
- if (ret != 0) {
- return Error() << "Failed to extract entry \"" << fileName << "\" ("
- << entry.uncompressed_length << " bytes) to \"" << dstPath
- << "\": " << ErrorCodeString(ret);
- }
-
- return {};
-}
-
-Result<void> GetPolicyFromApex(const std::string& dir) {
- LOG(INFO) << "Loading APEX Sepolicy from " << dir + kSepolicyZip;
- unique_fd fd(open((dir + kSepolicyZip).c_str(), O_RDONLY | O_BINARY | O_CLOEXEC));
- if (fd < 0) {
- return ErrnoError() << "Failed to open package " << dir + kSepolicyZip;
- }
-
- ZipArchiveHandle handle;
- int ret = OpenArchiveFd(fd.get(), (dir + kSepolicyZip).c_str(), &handle,
- /*assume_ownership=*/false);
- if (ret < 0) {
- return Error() << "Failed to open package " << dir + kSepolicyZip << ": "
- << ErrorCodeString(ret);
- }
-
- auto handle_guard = android::base::make_scope_guard([&handle] { CloseArchive(handle); });
-
- auto create = CreateTmpfsDir();
- if (!create.ok()) {
- return create.error();
- }
-
- for (const auto& file : kApexSepolicy) {
- auto extract = PutFileInTmpfs(handle, file);
- if (!extract.ok()) {
- return extract.error();
- }
- }
- for (const auto& file : kApexSepolicyTmp) {
- auto extract = PutFileInTmpfs(handle, file);
- if (!extract.ok()) {
- return extract.error();
- }
- }
- return {};
-}
-
-Result<void> SepolicyCheckSignature(const std::string& dir) {
- std::string signature;
- if (!android::base::ReadFileToString(dir + kSepolicySignature, &signature)) {
- return ErrnoError() << "Failed to read " << kSepolicySignature;
- }
-
- std::fstream sepolicyZip(dir + kSepolicyZip, std::ios::in | std::ios::binary);
- if (!sepolicyZip) {
- return Error() << "Failed to open " << kSepolicyZip;
- }
- sepolicyZip.seekg(0);
- std::string sepolicyStr((std::istreambuf_iterator<char>(sepolicyZip)),
- std::istreambuf_iterator<char>());
-
- auto releaseKey = extractPublicKeyFromX509(kSigningCertRelease);
- if (!releaseKey.ok()) {
- return releaseKey.error();
- }
-
- return verifySignature(sepolicyStr, signature, *releaseKey);
-}
-
-Result<void> SepolicyVerify(const std::string& dir) {
- auto sepolicySignature = SepolicyCheckSignature(dir);
- if (!sepolicySignature.ok()) {
- return Error() << "Apex SEPolicy failed signature check";
- }
- return {};
-}
-
-void CleanupApexSepolicy() {
- for (const auto& file : kApexSepolicyTmp) {
- std::string path = kTmpfsDir + file;
- unlink(path.c_str());
- }
-}
-
-// Updatable sepolicy is shipped within an zip within an APEX. Because
-// it needs to be available before Apexes are mounted, apexd copies
-// the zip from the APEX and stores it in /metadata/sepolicy. If there is
-// no updatable sepolicy in /metadata/sepolicy, then the updatable policy is
-// loaded from /system/etc/selinux/apex. Init performs the following
-// steps on boot:
-//
-// 1. Validates the zip by checking its signature against a public key that is
-// stored in /system/etc/selinux.
-// 2. Extracts files from zip and stores them in /dev/selinux.
-// 3. Checks if the apex_sepolicy.sha256 matches the sha256 of precompiled_sepolicy.
-// if so, the precompiled sepolicy is used. Otherwise, an on-device compile of the policy
-// is used. This is the same flow as on-device compilation of policy for Treble.
-// 4. Cleans up files in /dev/selinux which are no longer needed.
-// 5. Restorecons the remaining files in /dev/selinux.
-// 6. Sets selinux into enforcing mode and continues normal booting.
-//
-void PrepareApexSepolicy() {
- // If apex sepolicy zip exists in /metadata/sepolicy, use that, otherwise use version on
- // /system. If neither exists, do nothing.
- std::string dir;
- if (access((kSepolicyApexMetadataDir + kSepolicyZip).c_str(), F_OK) == 0) {
- dir = kSepolicyApexMetadataDir;
- } else if (access((kSepolicyApexSystemDir + kSepolicyZip).c_str(), F_OK) == 0) {
- dir = kSepolicyApexSystemDir;
- } else {
- LOG(INFO) << "APEX Sepolicy not found";
- return;
- }
-
- auto sepolicyVerify = SepolicyVerify(dir);
- if (!sepolicyVerify.ok()) {
- LOG(INFO) << "Error: " << sepolicyVerify.error();
- // If signature verification fails, fall back to version on /system.
- // This file doesn't need to be verified because it lives on the system partition which
- // is signed and protected by verified boot.
- dir = kSepolicyApexSystemDir;
- }
-
- auto apex = GetPolicyFromApex(dir);
- if (!apex.ok()) {
- // TODO(b/199914227) Make failure fatal. For now continue booting with non-apex sepolicy.
- LOG(ERROR) << apex.error();
- }
-}
-
void ReadPolicy(std::string* policy) {
PolicyFile policy_file;
@@ -961,12 +756,9 @@
LOG(INFO) << "Opening SELinux policy";
- PrepareApexSepolicy();
-
// Read the policy before potentially killing snapuserd.
std::string policy;
ReadPolicy(&policy);
- CleanupApexSepolicy();
auto snapuserd_helper = SnapuserdSelinuxHelper::CreateIfNeeded();
if (snapuserd_helper) {
@@ -982,13 +774,6 @@
snapuserd_helper->FinishTransition();
snapuserd_helper = nullptr;
}
-
- // This restorecon is intentionally done before SelinuxSetEnforcement because the permissions
- // needed to transition files from tmpfs to *_contexts_file context should not be granted to
- // any process after selinux is set into enforcing mode.
- if (selinux_android_restorecon("/dev/selinux/", SELINUX_ANDROID_RESTORECON_RECURSE) == -1) {
- PLOG(FATAL) << "restorecon failed of /dev/selinux failed";
- }
}
int SetupSelinux(char** argv) {
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 162f0f4..2c05fbc 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -185,10 +185,21 @@
support_system_process: true,
},
- header_abi_checker: {
- // AFDO affects weak symbols.
- diff_flags: ["-allow-adding-removing-weak-symbols"],
- ref_dump_dirs: ["abi-dumps"],
+ target: {
+ product: {
+ header_abi_checker: {
+ // AFDO affects weak symbols.
+ diff_flags: ["-allow-adding-removing-weak-symbols"],
+ ref_dump_dirs: ["abi-dumps"],
+ },
+ },
+ vendor: {
+ header_abi_checker: {
+ // AFDO affects weak symbols.
+ diff_flags: ["-allow-adding-removing-weak-symbols"],
+ ref_dump_dirs: ["abi-dumps"],
+ },
+ },
},
}