diff options
-rw-r--r-- | cmds/installd/InstalldNativeService.cpp | 99 | ||||
-rw-r--r-- | libs/binder/rust/src/binder.rs | 10 | ||||
-rw-r--r-- | libs/binder/rust/src/native.rs | 7 | ||||
-rw-r--r-- | libs/binder/rust/tests/integration.rs | 4 | ||||
-rw-r--r-- | opengl/Android.bp | 4 |
5 files changed, 86 insertions, 38 deletions
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 073d0c4854..1347450a77 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -472,6 +472,49 @@ status_t InstalldNativeService::dump(int fd, const Vector<String16>& /* args */) return NO_ERROR; } +constexpr const char kXattrRestoreconInProgress[] = "user.restorecon_in_progress"; + +static std::string lgetfilecon(const std::string& path) { + char* context; + if (::lgetfilecon(path.c_str(), &context) < 0) { + PLOG(ERROR) << "Failed to lgetfilecon for " << path; + return {}; + } + std::string result{context}; + free(context); + return result; +} + +static bool getRestoreconInProgress(const std::string& path) { + bool inProgress = false; + if (getxattr(path.c_str(), kXattrRestoreconInProgress, &inProgress, sizeof(inProgress)) != + sizeof(inProgress)) { + if (errno != ENODATA) { + PLOG(ERROR) << "Failed to check in-progress restorecon for " << path; + } + return false; + } + return inProgress; +} + +struct RestoreconInProgress { + explicit RestoreconInProgress(const std::string& path) : mPath(path) { + bool inProgress = true; + if (setxattr(mPath.c_str(), kXattrRestoreconInProgress, &inProgress, sizeof(inProgress), + 0) != 0) { + PLOG(ERROR) << "Failed to set in-progress restorecon for " << path; + } + } + ~RestoreconInProgress() { + if (removexattr(mPath.c_str(), kXattrRestoreconInProgress) < 0) { + PLOG(ERROR) << "Failed to clear in-progress restorecon for " << mPath; + } + } + +private: + const std::string& mPath; +}; + /** * Perform restorecon of the given path, but only perform recursive restorecon * if the label of that top-level file actually changed. This can save us @@ -480,56 +523,56 @@ status_t InstalldNativeService::dump(int fd, const Vector<String16>& /* args */) static int restorecon_app_data_lazy(const std::string& path, const std::string& seInfo, uid_t uid, bool existing) { ScopedTrace tracer("restorecon-lazy"); - int res = 0; - char* before = nullptr; - char* after = nullptr; if (!existing) { ScopedTrace tracer("new-path"); if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid, SELINUX_ANDROID_RESTORECON_RECURSE) < 0) { PLOG(ERROR) << "Failed recursive restorecon for " << path; - goto fail; + return -1; } - return res; + return 0; } - // Note that SELINUX_ANDROID_RESTORECON_DATADATA flag is set by - // libselinux. Not needed here. - if (lgetfilecon(path.c_str(), &before) < 0) { - PLOG(ERROR) << "Failed before getfilecon for " << path; - goto fail; - } - if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid, 0) < 0) { - PLOG(ERROR) << "Failed top-level restorecon for " << path; - goto fail; - } - if (lgetfilecon(path.c_str(), &after) < 0) { - PLOG(ERROR) << "Failed after getfilecon for " << path; - goto fail; + // Note that SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here. + + // Check to see if there was an interrupted operation. + bool inProgress = getRestoreconInProgress(path); + std::string before, after; + if (!inProgress) { + if (before = lgetfilecon(path); before.empty()) { + PLOG(ERROR) << "Failed before getfilecon for " << path; + return -1; + } + if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid, 0) < 0) { + PLOG(ERROR) << "Failed top-level restorecon for " << path; + return -1; + } + if (after = lgetfilecon(path); after.empty()) { + PLOG(ERROR) << "Failed after getfilecon for " << path; + return -1; + } } // If the initial top-level restorecon above changed the label, then go // back and restorecon everything recursively - if (strcmp(before, after)) { + if (inProgress || before != after) { ScopedTrace tracer("label-change"); if (existing) { LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at " << path << "; running recursive restorecon"; } + + // Temporary mark the folder as "in-progress" to resume in case of reboot/other failure. + RestoreconInProgress fence(path); + if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid, SELINUX_ANDROID_RESTORECON_RECURSE) < 0) { PLOG(ERROR) << "Failed recursive restorecon for " << path; - goto fail; + return -1; } } - goto done; -fail: - res = -1; -done: - free(before); - free(after); - return res; + return 0; } static bool internal_storage_has_project_id() { // The following path is populated in setFirstBoot, so if this file is present @@ -3295,7 +3338,7 @@ binder::Status InstalldNativeService::linkNativeLibraryDirectory( } char *con = nullptr; - if (lgetfilecon(pkgdir, &con) < 0) { + if (::lgetfilecon(pkgdir, &con) < 0) { return error("Failed to lgetfilecon " + _pkgdir); } diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs index 78f8877c1d..6d122c5388 100644 --- a/libs/binder/rust/src/binder.rs +++ b/libs/binder/rust/src/binder.rs @@ -27,7 +27,7 @@ use std::cmp::Ordering; use std::convert::TryFrom; use std::ffi::{c_void, CStr, CString}; use std::fmt; -use std::fs::File; +use std::io::Write; use std::marker::PhantomData; use std::ops::Deref; use std::os::raw::c_char; @@ -62,7 +62,7 @@ pub trait Interface: Send + Sync + DowncastSync { /// /// This handler is a no-op by default and should be implemented for each /// Binder service struct that wishes to respond to dump transactions. - fn dump(&self, _file: &File, _args: &[&CStr]) -> Result<()> { + fn dump(&self, _writer: &mut dyn Write, _args: &[&CStr]) -> Result<()> { Ok(()) } } @@ -165,7 +165,7 @@ pub trait Remotable: Send + Sync + 'static { /// Handle a request to invoke the dump transaction on this /// object. - fn on_dump(&self, file: &File, args: &[&CStr]) -> Result<()>; + fn on_dump(&self, file: &mut dyn Write, args: &[&CStr]) -> Result<()>; /// Retrieve the class of this remote object. /// @@ -934,8 +934,8 @@ macro_rules! declare_binder_interface { } } - fn on_dump(&self, file: &std::fs::File, args: &[&std::ffi::CStr]) -> std::result::Result<(), $crate::StatusCode> { - self.0.dump(file, args) + fn on_dump(&self, writer: &mut dyn std::io::Write, args: &[&std::ffi::CStr]) -> std::result::Result<(), $crate::StatusCode> { + self.0.dump(writer, args) } fn get_class() -> $crate::binder_impl::InterfaceClass { diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs index b248f5eb28..b250012801 100644 --- a/libs/binder/rust/src/native.rs +++ b/libs/binder/rust/src/native.rs @@ -25,6 +25,7 @@ use crate::sys; use std::convert::TryFrom; use std::ffi::{c_void, CStr, CString}; use std::fs::File; +use std::io::Write; use std::mem::ManuallyDrop; use std::ops::Deref; use std::os::raw::c_char; @@ -341,7 +342,7 @@ impl<T: Remotable> InterfaceClassMethods for Binder<T> { } // Safety: Our caller promised that fd is a file descriptor. We don't // own this file descriptor, so we need to be careful not to drop it. - let file = unsafe { ManuallyDrop::new(File::from_raw_fd(fd)) }; + let mut file = unsafe { ManuallyDrop::new(File::from_raw_fd(fd)) }; if args.is_null() && num_args != 0 { return StatusCode::UNEXPECTED_NULL as status_t; @@ -366,7 +367,7 @@ impl<T: Remotable> InterfaceClassMethods for Binder<T> { // Safety: Our caller promised that the binder has a `T` pointer in its // user data. let binder: &T = unsafe { &*(object as *const T) }; - let res = binder.on_dump(&file, &args); + let res = binder.on_dump(&mut *file, &args); match res { Ok(()) => 0, @@ -569,7 +570,7 @@ impl Remotable for () { Ok(()) } - fn on_dump(&self, _file: &File, _args: &[&CStr]) -> Result<()> { + fn on_dump(&self, _writer: &mut dyn Write, _args: &[&CStr]) -> Result<()> { Ok(()) } diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs index c049b807df..c87fa89756 100644 --- a/libs/binder/rust/tests/integration.rs +++ b/libs/binder/rust/tests/integration.rs @@ -26,7 +26,7 @@ use binder::binder_impl::{ use std::convert::{TryFrom, TryInto}; use std::ffi::CStr; -use std::fs::File; +use std::io::Write; use std::sync::Mutex; /// Name of service runner. @@ -118,7 +118,7 @@ impl TryFrom<u32> for TestTransactionCode { } impl Interface for TestService { - fn dump(&self, _file: &File, args: &[&CStr]) -> Result<(), StatusCode> { + fn dump(&self, _writer: &mut dyn Write, args: &[&CStr]) -> Result<(), StatusCode> { let mut dump_args = self.dump_args.lock().unwrap(); dump_args.extend(args.iter().map(|s| s.to_str().unwrap().to_owned())); Ok(()) diff --git a/opengl/Android.bp b/opengl/Android.bp index b15694bf50..4454f36b67 100644 --- a/opengl/Android.bp +++ b/opengl/Android.bp @@ -72,6 +72,10 @@ cc_library_headers { llndk: { llndk_headers: true, }, + apex_available: [ + "//apex_available:platform", + "com.android.virt", + ], } subdirs = [ |