Run app payloads as non-root.
This is in preparation before moving to running multiple payload
processes in multiple UIDs.
Add a new payload user and group in the system-reserved range, only
within Microdroid, and assign them to the payload process. Fix up a
bunch of DAC permissions to make sure the payload still has access to
the things it should have.
Add a test to check we aren't running as root, and make some minor
test fixes.
This is a potentially breaking change, so for now I've disabled it via
Rust conditional compilation (and marked the new test as @Ignore). I
claim the changes that aren't protected by this are harmless.
I've run tests with and without the cfg option enabled.
Unrelated changes done in passing:
- Move a comment from reference to definition.
- Make sure encryptedstore logs any errors in full.
- Use with_context in a few more places.
Bug: 296393106
Test: atest MicrodroidTests
Change-Id: I6648580615a9fce906dd170f999e11f63e5874d9
diff --git a/encryptedstore/Android.bp b/encryptedstore/Android.bp
index 94ebcfc..8ba5016 100644
--- a/encryptedstore/Android.bp
+++ b/encryptedstore/Android.bp
@@ -14,6 +14,7 @@
"libclap",
"libhex",
"liblog_rust",
+ "libmicrodroid_uids",
"libnix",
"libdm_rust",
],
diff --git a/encryptedstore/src/main.rs b/encryptedstore/src/main.rs
index 1a16f49..2a698ea 100644
--- a/encryptedstore/src/main.rs
+++ b/encryptedstore/src/main.rs
@@ -21,24 +21,32 @@
use anyhow::{ensure, Context, Result};
use clap::arg;
use dm::{crypt::CipherType, util};
-use log::info;
+use log::{error, info};
use std::ffi::CString;
use std::fs::{create_dir_all, OpenOptions};
use std::io::{Error, Read, Write};
use std::os::unix::ffi::OsStrExt;
-use std::os::unix::fs::FileTypeExt;
+use std::os::unix::fs::{FileTypeExt, PermissionsExt};
use std::path::{Path, PathBuf};
use std::process::Command;
const MK2FS_BIN: &str = "/system/bin/mke2fs";
const UNFORMATTED_STORAGE_MAGIC: &str = "UNFORMATTED-STORAGE";
-fn main() -> Result<()> {
+fn main() {
android_logger::init_once(
android_logger::Config::default()
.with_tag("encryptedstore")
.with_min_level(log::Level::Info),
);
+
+ if let Err(e) = try_main() {
+ error!("{:?}", e);
+ std::process::exit(1)
+ }
+}
+
+fn try_main() -> Result<()> {
info!("Starting encryptedstore binary");
let matches = clap_command().get_matches();
@@ -47,10 +55,12 @@
let key = matches.get_one::<String>("key").unwrap();
let mountpoint = Path::new(matches.get_one::<String>("mountpoint").unwrap());
// Note this error context is used in MicrodroidTests.
- encryptedstore_init(blkdevice, key, mountpoint).context(format!(
- "Unable to initialize encryptedstore on {:?} & mount at {:?}",
- blkdevice, mountpoint
- ))?;
+ encryptedstore_init(blkdevice, key, mountpoint).with_context(|| {
+ format!(
+ "Unable to initialize encryptedstore on {:?} & mount at {:?}",
+ blkdevice, mountpoint
+ )
+ })?;
Ok(())
}
@@ -65,7 +75,7 @@
fn encryptedstore_init(blkdevice: &Path, key: &str, mountpoint: &Path) -> Result<()> {
ensure!(
std::fs::metadata(blkdevice)
- .context(format!("Failed to get metadata of {:?}", blkdevice))?
+ .with_context(|| format!("Failed to get metadata of {:?}", blkdevice))?
.file_type()
.is_block_device(),
"The path:{:?} is not of a block device",
@@ -82,7 +92,12 @@
info!("Freshly formatting the crypt device");
format_ext4(&crypt_device)?;
}
- mount(&crypt_device, mountpoint).context(format!("Unable to mount {:?}", crypt_device))?;
+ mount(&crypt_device, mountpoint)
+ .with_context(|| format!("Unable to mount {:?}", crypt_device))?;
+ if needs_formatting {
+ std::fs::set_permissions(mountpoint, PermissionsExt::from_mode(0o770))
+ .context("Failed to chmod root directory")?;
+ }
Ok(())
}
@@ -124,6 +139,11 @@
}
fn format_ext4(device: &Path) -> Result<()> {
+ let root_dir_uid_gid = format!(
+ "root_owner={}:{}",
+ microdroid_uids::ROOT_UID,
+ microdroid_uids::MICRODROID_PAYLOAD_GID
+ );
let mkfs_options = [
"-j", // Create appropriate sized journal
/* metadata_csum: enabled for filesystem integrity
@@ -131,20 +151,22 @@
* 64bit: larger fields afforded by this feature enable full-strength checksumming.
*/
"-O metadata_csum, extents, 64bit",
- "-b 4096", // block size in the filesystem
+ "-b 4096", // block size in the filesystem,
+ "-E",
+ &root_dir_uid_gid,
];
let mut cmd = Command::new(MK2FS_BIN);
let status = cmd
.args(mkfs_options)
.arg(device)
.status()
- .context(format!("failed to execute {}", MK2FS_BIN))?;
+ .with_context(|| format!("failed to execute {}", MK2FS_BIN))?;
ensure!(status.success(), "mkfs failed with {:?}", status);
Ok(())
}
fn mount(source: &Path, mountpoint: &Path) -> Result<()> {
- create_dir_all(mountpoint).context(format!("Failed to create {:?}", &mountpoint))?;
+ create_dir_all(mountpoint).with_context(|| format!("Failed to create {:?}", &mountpoint))?;
let mount_options = CString::new(
"fscontext=u:object_r:encryptedstore_fs:s0,context=u:object_r:encryptedstore_file:s0",
)