Merge "MappedFile and FileMap should support zero-length mappings."
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index c878b21..e684293 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -378,7 +378,7 @@
// Set the number of reserved filesystem blocks if needed.
static void tune_reserved_size(const std::string& blk_device, const FstabEntry& entry,
const struct ext4_super_block* sb, int* fs_stat) {
- if (!entry.fs_mgr_flags.reserved_size) {
+ if (entry.reserved_size != 0) {
return;
}
@@ -551,7 +551,7 @@
}
if (is_extfs(entry.fs_type) &&
- (entry.fs_mgr_flags.reserved_size || entry.fs_mgr_flags.file_encryption ||
+ (entry.reserved_size != 0 || entry.fs_mgr_flags.file_encryption ||
entry.fs_mgr_flags.fs_verity)) {
struct ext4_super_block sb;
@@ -806,7 +806,7 @@
}
static bool should_use_metadata_encryption(const FstabEntry& entry) {
- return entry.fs_mgr_flags.key_directory &&
+ return !entry.key_dir.empty() &&
(entry.fs_mgr_flags.file_encryption || entry.fs_mgr_flags.force_fde_or_fbe);
}
@@ -1374,18 +1374,6 @@
return FS_MGR_DOMNT_FAILED;
}
-int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point) {
- auto new_fstab = LegacyFstabToFstab(fstab);
- return fs_mgr_do_mount_helper(&new_fstab, n_name, n_blk_device, tmp_mount_point, -1);
-}
-
-int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
- bool needs_checkpoint) {
- auto new_fstab = LegacyFstabToFstab(fstab);
- return fs_mgr_do_mount_helper(&new_fstab, n_name, n_blk_device, tmp_mount_point,
- needs_checkpoint);
-}
-
int fs_mgr_do_mount(Fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point) {
return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, -1);
}
@@ -1556,48 +1544,6 @@
return ret;
}
-struct fstab_rec const* fs_mgr_get_crypt_entry(fstab const* fstab) {
- int i;
-
- if (!fstab) {
- return NULL;
- }
-
- /* Look for the encryptable partition to find the data */
- for (i = 0; i < fstab->num_entries; i++) {
- /* Don't deal with vold managed enryptable partitions here */
- if (!(fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) &&
- (fstab->recs[i].fs_mgr_flags &
- (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE | MF_FILEENCRYPTION))) {
- return &fstab->recs[i];
- }
- }
- return NULL;
-}
-
-/*
- * key_loc must be at least PROPERTY_VALUE_MAX bytes long
- *
- * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long
- */
-void fs_mgr_get_crypt_info(fstab* fstab, char* key_loc, char* real_blk_device, size_t size) {
- struct fstab_rec const* rec = fs_mgr_get_crypt_entry(fstab);
- if (key_loc) {
- if (rec) {
- strlcpy(key_loc, rec->key_loc, size);
- } else {
- *key_loc = '\0';
- }
- }
- if (real_blk_device) {
- if (rec) {
- strlcpy(real_blk_device, rec->blk_device, size);
- } else {
- *real_blk_device = '\0';
- }
- }
-}
-
bool fs_mgr_load_verity_state(int* mode) {
/* return the default mode, unless any of the verified partitions are in
* logging mode, in which case return that */
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index ee88e0d..4d44fcf 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -175,8 +175,8 @@
}
void ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) {
- entry->fs_mgr_flags.val = 0U;
for (const auto& flag : Split(flags, ",")) {
+ if (flag.empty() || flag == "defaults") continue;
std::string arg;
if (auto equal_sign = flag.find('='); equal_sign != std::string::npos) {
arg = flag.substr(equal_sign + 1);
@@ -239,18 +239,14 @@
}
} else if (StartsWith(flag, "length=")) {
// The length flag is followed by an = and the size of the partition.
- entry->fs_mgr_flags.length = true;
if (!ParseInt(arg, &entry->length)) {
LWARNING << "Warning: length= flag malformed: " << arg;
}
} else if (StartsWith(flag, "swapprio=")) {
- entry->fs_mgr_flags.swap_prio = true;
if (!ParseInt(arg, &entry->swap_prio)) {
LWARNING << "Warning: length= flag malformed: " << arg;
}
} else if (StartsWith(flag, "zramsize=")) {
- entry->fs_mgr_flags.zram_size = true;
-
if (!arg.empty() && arg.back() == '%') {
arg.pop_back();
int val;
@@ -282,13 +278,11 @@
entry->file_contents_mode = "aes-256-xts";
entry->file_names_mode = "aes-256-cts";
} else if (StartsWith(flag, "max_comp_streams=")) {
- entry->fs_mgr_flags.max_comp_streams = true;
if (!ParseInt(arg, &entry->max_comp_streams)) {
LWARNING << "Warning: max_comp_streams= flag malformed: " << arg;
}
} else if (StartsWith(flag, "reservedsize=")) {
// The reserved flag is followed by an = and the reserved size of the partition.
- entry->fs_mgr_flags.reserved_size = true;
uint64_t size;
if (!ParseByteCount(arg, &size)) {
LWARNING << "Warning: reservedsize= flag malformed: " << arg;
@@ -298,7 +292,6 @@
} else if (StartsWith(flag, "eraseblk=")) {
// The erase block size flag is followed by an = and the flash erase block size. Get it,
// check that it is a power of 2 and at least 4096, and return it.
- entry->fs_mgr_flags.erase_blk_size = true;
off64_t val;
if (!ParseInt(arg, &val) || val < 4096 || (val & (val - 1)) != 0) {
LWARNING << "Warning: eraseblk= flag malformed: " << arg;
@@ -308,7 +301,6 @@
} else if (StartsWith(flag, "logicalblk=")) {
// The logical block size flag is followed by an = and the flash logical block size. Get
// it, check that it is a power of 2 and at least 4096, and return it.
- entry->fs_mgr_flags.logical_blk_size = true;
off64_t val;
if (!ParseInt(arg, &val) || val < 4096 || (val & (val - 1)) != 0) {
LWARNING << "Warning: logicalblk= flag malformed: " << arg;
@@ -320,23 +312,18 @@
entry->vbmeta_partition = arg;
} else if (StartsWith(flag, "keydirectory=")) {
// The metadata flag is followed by an = and the directory for the keys.
- entry->fs_mgr_flags.key_directory = true;
entry->key_dir = arg;
} else if (StartsWith(flag, "sysfs_path=")) {
// The path to trigger device gc by idle-maint of vold.
- entry->fs_mgr_flags.sysfs = true;
entry->sysfs_path = arg;
} else if (StartsWith(flag, "zram_loopback_path=")) {
// The path to use loopback for zram.
- entry->fs_mgr_flags.zram_loopback_path = true;
entry->zram_loopback_path = arg;
} else if (StartsWith(flag, "zram_loopback_size=")) {
- entry->fs_mgr_flags.zram_loopback_size = true;
if (!ParseByteCount(arg, &entry->zram_loopback_size)) {
LWARNING << "Warning: zram_loopback_size= flag malformed: " << arg;
}
} else if (StartsWith(flag, "zram_backing_dev_path=")) {
- entry->fs_mgr_flags.zram_backing_dev_path = true;
entry->zram_backing_dev_path = arg;
} else if (StartsWith(flag, "avb_key=")) {
entry->avb_key = arg;
@@ -778,214 +765,3 @@
return false;
}
-
-// Everything from here down is deprecated and will be removed shortly.
-
-using android::fs_mgr::Fstab;
-using android::fs_mgr::FstabEntry;
-using android::fs_mgr::ReadDefaultFstab;
-using android::fs_mgr::ReadFstabFromFile;
-
-struct fstab* fs_mgr_read_fstab(const char* fstab_path) {
- Fstab fstab;
- if (!ReadFstabFromFile(fstab_path, &fstab)) {
- return nullptr;
- }
-
- return FstabToLegacyFstab(fstab);
-}
-
-struct fstab* fs_mgr_read_fstab_default() {
- Fstab fstab;
- if (!ReadDefaultFstab(&fstab)) {
- return nullptr;
- }
-
- return FstabToLegacyFstab(fstab);
-}
-
-void fs_mgr_free_fstab(struct fstab *fstab)
-{
- int i;
-
- if (!fstab) {
- return;
- }
-
- for (i = 0; i < fstab->num_entries; i++) {
- /* Free the pointers return by strdup(3) */
- free(fstab->recs[i].blk_device);
- free(fstab->recs[i].logical_partition_name);
- free(fstab->recs[i].mount_point);
- free(fstab->recs[i].fs_type);
- free(fstab->recs[i].fs_options);
- free(fstab->recs[i].key_loc);
- free(fstab->recs[i].key_dir);
- free(fstab->recs[i].label);
- free(fstab->recs[i].file_contents_mode);
- free(fstab->recs[i].file_names_mode);
- free(fstab->recs[i].sysfs_path);
- free(fstab->recs[i].zram_loopback_path);
- free(fstab->recs[i].zram_backing_dev_path);
- }
-
- /* Free the fstab_recs array created by calloc(3) */
- free(fstab->recs);
-
- /* Free fstab */
- free(fstab);
-}
-
-struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const std::string& path) {
- if (!fstab) {
- return nullptr;
- }
- for (int i = 0; i < fstab->num_entries; i++) {
- if (fstab->recs[i].mount_point && path == fstab->recs[i].mount_point) {
- return &fstab->recs[i];
- }
- }
- return nullptr;
-}
-
-FstabEntry FstabRecToFstabEntry(const fstab_rec* fstab_rec) {
- FstabEntry entry;
- entry.blk_device = fstab_rec->blk_device;
- entry.logical_partition_name = fstab_rec->logical_partition_name;
- entry.mount_point = fstab_rec->mount_point;
- entry.fs_type = fstab_rec->fs_type;
- entry.flags = fstab_rec->flags;
- entry.fs_options = fstab_rec->fs_options;
- entry.fs_mgr_flags.val = fstab_rec->fs_mgr_flags;
- entry.key_loc = fstab_rec->key_loc;
- entry.key_dir = fstab_rec->key_dir;
- entry.verity_loc = fstab_rec->verity_loc;
- entry.length = fstab_rec->length;
- entry.label = fstab_rec->label;
- entry.partnum = fstab_rec->partnum;
- entry.swap_prio = fstab_rec->swap_prio;
- entry.max_comp_streams = fstab_rec->max_comp_streams;
- entry.zram_size = fstab_rec->zram_size;
- entry.reserved_size = fstab_rec->reserved_size;
- entry.file_contents_mode = fstab_rec->file_contents_mode;
- entry.file_names_mode = fstab_rec->file_names_mode;
- entry.erase_blk_size = fstab_rec->erase_blk_size;
- entry.logical_blk_size = fstab_rec->logical_blk_size;
- entry.sysfs_path = fstab_rec->sysfs_path;
- entry.zram_loopback_path = fstab_rec->zram_loopback_path;
- entry.zram_loopback_size = fstab_rec->zram_loopback_size;
- entry.zram_backing_dev_path = fstab_rec->zram_backing_dev_path;
-
- return entry;
-}
-
-Fstab LegacyFstabToFstab(const struct fstab* legacy_fstab) {
- Fstab fstab;
- for (int i = 0; i < legacy_fstab->num_entries; i++) {
- fstab.emplace_back(FstabRecToFstabEntry(&legacy_fstab->recs[i]));
- }
-
- return fstab;
-}
-
-fstab* FstabToLegacyFstab(const Fstab& fstab) {
- struct fstab* legacy_fstab = static_cast<struct fstab*>(calloc(1, sizeof(struct fstab)));
- legacy_fstab->num_entries = fstab.size();
- legacy_fstab->recs =
- static_cast<fstab_rec*>(calloc(legacy_fstab->num_entries, sizeof(fstab_rec)));
-
- for (int i = 0; i < legacy_fstab->num_entries; i++) {
- legacy_fstab->recs[i].blk_device = strdup(fstab[i].blk_device.c_str());
- legacy_fstab->recs[i].logical_partition_name =
- strdup(fstab[i].logical_partition_name.c_str());
- legacy_fstab->recs[i].mount_point = strdup(fstab[i].mount_point.c_str());
- legacy_fstab->recs[i].fs_type = strdup(fstab[i].fs_type.c_str());
- legacy_fstab->recs[i].flags = fstab[i].flags;
- legacy_fstab->recs[i].fs_options = strdup(fstab[i].fs_options.c_str());
- legacy_fstab->recs[i].fs_mgr_flags = fstab[i].fs_mgr_flags.val;
- legacy_fstab->recs[i].key_loc = strdup(fstab[i].key_loc.c_str());
- legacy_fstab->recs[i].key_dir = strdup(fstab[i].key_dir.c_str());
- legacy_fstab->recs[i].verity_loc = strdup(fstab[i].verity_loc.c_str());
- legacy_fstab->recs[i].length = fstab[i].length;
- legacy_fstab->recs[i].label = strdup(fstab[i].label.c_str());
- legacy_fstab->recs[i].partnum = fstab[i].partnum;
- legacy_fstab->recs[i].swap_prio = fstab[i].swap_prio;
- legacy_fstab->recs[i].max_comp_streams = fstab[i].max_comp_streams;
- legacy_fstab->recs[i].zram_size = fstab[i].zram_size;
- legacy_fstab->recs[i].reserved_size = fstab[i].reserved_size;
- legacy_fstab->recs[i].file_contents_mode = strdup(fstab[i].file_contents_mode.c_str());
- legacy_fstab->recs[i].file_names_mode = strdup(fstab[i].file_names_mode.c_str());
- legacy_fstab->recs[i].erase_blk_size = fstab[i].erase_blk_size;
- legacy_fstab->recs[i].logical_blk_size = fstab[i].logical_blk_size;
- legacy_fstab->recs[i].sysfs_path = strdup(fstab[i].sysfs_path.c_str());
- legacy_fstab->recs[i].zram_loopback_path = strdup(fstab[i].zram_loopback_path.c_str());
- legacy_fstab->recs[i].zram_loopback_size = fstab[i].zram_loopback_size;
- legacy_fstab->recs[i].zram_backing_dev_path = strdup(fstab[i].zram_backing_dev_path.c_str());
- }
- return legacy_fstab;
-}
-
-int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
-{
- return fstab->fs_mgr_flags & MF_VOLDMANAGED;
-}
-
-int fs_mgr_is_nonremovable(const struct fstab_rec *fstab)
-{
- return fstab->fs_mgr_flags & MF_NONREMOVABLE;
-}
-
-int fs_mgr_is_verified(const struct fstab_rec *fstab)
-{
- return fstab->fs_mgr_flags & MF_VERIFY;
-}
-
-int fs_mgr_is_encryptable(const struct fstab_rec *fstab)
-{
- return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE);
-}
-
-void fs_mgr_get_file_encryption_modes(const struct fstab_rec* fstab, const char** contents_mode_ret,
- const char** filenames_mode_ret) {
- *contents_mode_ret = fstab->file_contents_mode;
- *filenames_mode_ret = fstab->file_names_mode;
-}
-
-int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab)
-{
- return fstab->fs_mgr_flags & MF_FORCEFDEORFBE;
-}
-
-int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab)
-{
- return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
-}
-
-int fs_mgr_is_notrim(const struct fstab_rec* fstab) {
- return fstab->fs_mgr_flags & MF_NOTRIM;
-}
-
-int fs_mgr_is_quota(const struct fstab_rec* fstab) {
- return fstab->fs_mgr_flags & MF_QUOTA;
-}
-
-int fs_mgr_has_sysfs_path(const struct fstab_rec *fstab)
-{
- return fstab->fs_mgr_flags & MF_SYSFS;
-}
-
-int fs_mgr_is_logical(const struct fstab_rec* fstab) {
- return fstab->fs_mgr_flags & MF_LOGICAL;
-}
-
-int fs_mgr_is_checkpoint(const struct fstab_rec* fstab) {
- return fstab->fs_mgr_flags & (MF_CHECKPOINT_FS | MF_CHECKPOINT_BLK);
-}
-
-int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab) {
- return fstab->fs_mgr_flags & MF_CHECKPOINT_FS;
-}
-
-int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab) {
- return fstab->fs_mgr_flags & MF_CHECKPOINT_BLK;
-}
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 83e5d7b..166c32b 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef __CORE_FS_MGR_PRIV_H
-#define __CORE_FS_MGR_PRIV_H
+#pragma once
#include <chrono>
#include <string>
@@ -85,53 +84,6 @@
*
*/
-// clang-format off
-#define MF_WAIT 0x1
-#define MF_CHECK 0x2
-#define MF_CRYPT 0x4
-#define MF_NONREMOVABLE 0x8
-#define MF_VOLDMANAGED 0x10
-#define MF_LENGTH 0x20
-#define MF_RECOVERYONLY 0x40
-#define MF_SWAPPRIO 0x80
-#define MF_ZRAMSIZE 0x100
-#define MF_VERIFY 0x200
-#define MF_FORCECRYPT 0x400
-#define MF_NOEMULATEDSD 0x800 /* no emulated sdcard daemon, sd card is the only
- external storage */
-#define MF_NOTRIM 0x1000
-#define MF_FILEENCRYPTION 0x2000
-#define MF_FORMATTABLE 0x4000
-#define MF_SLOTSELECT 0x8000
-#define MF_FORCEFDEORFBE 0x10000
-#define MF_LATEMOUNT 0x20000
-#define MF_NOFAIL 0x40000
-#define MF_VERIFYATBOOT 0x80000
-#define MF_MAX_COMP_STREAMS 0x100000
-#define MF_RESERVEDSIZE 0x200000
-#define MF_QUOTA 0x400000
-#define MF_ERASEBLKSIZE 0x800000
-#define MF_LOGICALBLKSIZE 0X1000000
-#define MF_AVB 0X2000000
-#define MF_KEYDIRECTORY 0X4000000
-#define MF_SYSFS 0X8000000
-#define MF_LOGICAL 0x10000000
-#define MF_CHECKPOINT_BLK 0x20000000
-#define MF_CHECKPOINT_FS 0x40000000
-#define MF_FIRST_STAGE_MOUNT \
- 0x80000000
-#define MF_SLOTSELECT_OTHER \
- 0x100000000
-#define MF_ZRAM_LOOPBACK_PATH \
- 0x200000000
-#define MF_ZRAM_LOOPBACK_SIZE \
- 0x400000000
-#define MF_ZRAM_BACKING_DEV_PATH \
- 0x800000000
-#define MF_FS_VERITY \
- 0x1000000000
-// clang-format on
-
#define DM_BUF_SIZE 4096
using namespace std::chrono_literals;
@@ -148,5 +100,3 @@
const std::string& get_android_dt_dir();
bool is_dt_compatible();
int load_verity_state(const android::fs_mgr::FstabEntry& entry, int* mode);
-
-#endif /* __CORE_FS_MGR_PRIV_H */
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 6e9f1b0..8af80a7 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -65,9 +65,6 @@
#define FS_MGR_DOMNT_FAILED (-1)
#define FS_MGR_DOMNT_BUSY (-2)
#define FS_MGR_DOMNT_SUCCESS 0
-int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point);
-int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
- bool needs_checkpoint);
int fs_mgr_do_mount(android::fs_mgr::Fstab* fstab, const char* n_name, char* n_blk_device,
char* tmp_mount_point);
int fs_mgr_do_mount(android::fs_mgr::Fstab* fstab, const char* n_name, char* n_blk_device,
@@ -75,8 +72,6 @@
int fs_mgr_do_mount_one(const android::fs_mgr::FstabEntry& entry,
const std::string& mount_point = "");
int fs_mgr_do_tmpfs_mount(const char *n_name);
-fstab_rec const* fs_mgr_get_crypt_entry(fstab const* fstab);
-void fs_mgr_get_crypt_info(fstab* fstab, char* key_loc, char* real_blk_device, size_t size);
bool fs_mgr_load_verity_state(int* mode);
bool fs_mgr_update_verity_state(
std::function<void(const std::string& mount_point, int mode)> callback);
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index a942d43..a3d9fdd 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -16,75 +16,13 @@
#pragma once
-#include <linux/dm-ioctl.h>
-#include <stdbool.h>
#include <stdint.h>
-#include <stdio.h>
#include <sys/types.h>
#include <set>
#include <string>
#include <vector>
-/*
- * The entries must be kept in the same order as they were seen in the fstab.
- * Unless explicitly requested, a lookup on mount point should always
- * return the 1st one.
- */
-struct fstab {
- int num_entries;
- struct fstab_rec* recs;
-};
-
-struct fstab_rec {
- char* blk_device;
- char* logical_partition_name;
- char* mount_point;
- char* fs_type;
- unsigned long flags;
- char* fs_options;
- uint64_t fs_mgr_flags;
- char* key_loc;
- char* key_dir;
- char* verity_loc;
- off64_t length;
- char* label;
- int partnum;
- int swap_prio;
- int max_comp_streams;
- off64_t zram_size;
- off64_t reserved_size;
- char* file_contents_mode;
- char* file_names_mode;
- off64_t erase_blk_size;
- off64_t logical_blk_size;
- char* sysfs_path;
- char* zram_loopback_path;
- uint64_t zram_loopback_size;
- char* zram_backing_dev_path;
-};
-
-struct fstab* fs_mgr_read_fstab_default();
-struct fstab* fs_mgr_read_fstab(const char* fstab_path);
-void fs_mgr_free_fstab(struct fstab* fstab);
-
-struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const std::string& path);
-int fs_mgr_is_voldmanaged(const struct fstab_rec* fstab);
-int fs_mgr_is_nonremovable(const struct fstab_rec* fstab);
-int fs_mgr_is_verified(const struct fstab_rec* fstab);
-int fs_mgr_is_encryptable(const struct fstab_rec* fstab);
-void fs_mgr_get_file_encryption_modes(const struct fstab_rec* fstab, const char** contents_mode_ret,
- const char** filenames_mode_ret);
-int fs_mgr_is_convertible_to_fbe(const struct fstab_rec* fstab);
-int fs_mgr_is_noemulatedsd(const struct fstab_rec* fstab);
-int fs_mgr_is_notrim(const struct fstab_rec* fstab);
-int fs_mgr_is_quota(const struct fstab_rec* fstab);
-int fs_mgr_is_logical(const struct fstab_rec* fstab);
-int fs_mgr_is_checkpoint(const struct fstab_rec* fstab);
-int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab);
-int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab);
-int fs_mgr_has_sysfs_path(const struct fstab_rec* fstab);
-
std::string fs_mgr_get_slot_suffix();
std::string fs_mgr_get_other_slot_suffix();
@@ -119,60 +57,34 @@
std::string zram_backing_dev_path;
std::string avb_key;
- // TODO: Remove this union once fstab_rec is deprecated. It only serves as a
- // convenient way to convert between fstab_rec::fs_mgr_flags and these bools.
- union FsMgrFlags {
- uint64_t val;
- struct {
- // bit 0
- bool wait : 1;
- bool check : 1;
- bool crypt : 1;
- bool nonremovable : 1;
- bool vold_managed : 1;
- bool length : 1;
- bool recovery_only : 1;
- bool swap_prio : 1;
-
- // bit 8
- bool zram_size : 1;
- bool verify : 1;
- bool force_crypt : 1;
- bool no_emulated_sd : 1; // No emulated sdcard daemon; sd card is the only external
- // storage.
- bool no_trim : 1;
- bool file_encryption : 1;
- bool formattable : 1;
- bool slot_select : 1;
-
- // bit 16
- bool force_fde_or_fbe : 1;
- bool late_mount : 1;
- bool no_fail : 1;
- bool verify_at_boot : 1;
- bool max_comp_streams : 1;
- bool reserved_size : 1;
- bool quota : 1;
- bool erase_blk_size : 1;
-
- // bit 24
- bool logical_blk_size : 1;
- bool avb : 1;
- bool key_directory : 1;
- bool sysfs : 1;
- bool logical : 1;
- bool checkpoint_blk : 1;
- bool checkpoint_fs : 1;
- bool first_stage_mount : 1;
-
- // bit 32
- bool slot_select_other : 1;
- bool zram_loopback_path : 1;
- bool zram_loopback_size : 1;
- bool zram_backing_dev_path : 1;
- bool fs_verity : 1;
- };
- } fs_mgr_flags;
+ struct FsMgrFlags {
+ bool wait : 1;
+ bool check : 1;
+ bool crypt : 1;
+ bool nonremovable : 1;
+ bool vold_managed : 1;
+ bool recovery_only : 1;
+ bool verify : 1;
+ bool force_crypt : 1;
+ bool no_emulated_sd : 1; // No emulated sdcard daemon; sd card is the only external
+ // storage.
+ bool no_trim : 1;
+ bool file_encryption : 1;
+ bool formattable : 1;
+ bool slot_select : 1;
+ bool force_fde_or_fbe : 1;
+ bool late_mount : 1;
+ bool no_fail : 1;
+ bool verify_at_boot : 1;
+ bool quota : 1;
+ bool avb : 1;
+ bool logical : 1;
+ bool checkpoint_blk : 1;
+ bool checkpoint_fs : 1;
+ bool first_stage_mount : 1;
+ bool slot_select_other : 1;
+ bool fs_verity : 1;
+ } fs_mgr_flags = {};
bool is_encryptable() const {
return fs_mgr_flags.crypt || fs_mgr_flags.force_crypt || fs_mgr_flags.force_fde_or_fbe;
@@ -180,6 +92,8 @@
};
// An Fstab is a collection of FstabEntry structs.
+// The entries must be kept in the same order as they were seen in the fstab.
+// Unless explicitly requested, a lookup on mount point should always return the 1st one.
using Fstab = std::vector<FstabEntry>;
bool ReadFstabFromFile(const std::string& path, Fstab* fstab);
@@ -195,8 +109,3 @@
} // namespace fs_mgr
} // namespace android
-
-// Temporary conversion functions.
-android::fs_mgr::FstabEntry FstabRecToFstabEntry(const fstab_rec* fstab_rec);
-android::fs_mgr::Fstab LegacyFstabToFstab(const struct fstab* legacy_fstab);
-fstab* FstabToLegacyFstab(const android::fs_mgr::Fstab& fstab);
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 870c98c..1815a38 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -256,6 +256,36 @@
EXPECT_EQ("", fstab[10].fs_options);
}
+static bool CompareFlags(FstabEntry::FsMgrFlags& lhs, FstabEntry::FsMgrFlags& rhs) {
+ // clang-format off
+ return lhs.wait == rhs.wait &&
+ lhs.check == rhs.check &&
+ lhs.crypt == rhs.crypt &&
+ lhs.nonremovable == rhs.nonremovable &&
+ lhs.vold_managed == rhs.vold_managed &&
+ lhs.recovery_only == rhs.recovery_only &&
+ lhs.verify == rhs.verify &&
+ lhs.force_crypt == rhs.force_crypt &&
+ lhs.no_emulated_sd == rhs.no_emulated_sd &&
+ lhs.no_trim == rhs.no_trim &&
+ lhs.file_encryption == rhs.file_encryption &&
+ lhs.formattable == rhs.formattable &&
+ lhs.slot_select == rhs.slot_select &&
+ lhs.force_fde_or_fbe == rhs.force_fde_or_fbe &&
+ lhs.late_mount == rhs.late_mount &&
+ lhs.no_fail == rhs.no_fail &&
+ lhs.verify_at_boot == rhs.verify_at_boot &&
+ lhs.quota == rhs.quota &&
+ lhs.avb == rhs.avb &&
+ lhs.logical == rhs.logical &&
+ lhs.checkpoint_blk == rhs.checkpoint_blk &&
+ lhs.checkpoint_fs == rhs.checkpoint_fs &&
+ lhs.first_stage_mount == rhs.first_stage_mount &&
+ lhs.slot_select_other == rhs.slot_select_other &&
+ lhs.fs_verity == rhs.fs_verity;
+ // clang-format on
+}
+
TEST(fs_mgr, ReadFstabFromFile_FsMgrFlags) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
@@ -276,62 +306,62 @@
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
{
- FstabEntry::FsMgrFlags flags = {0};
+ FstabEntry::FsMgrFlags flags = {};
flags.wait = true;
flags.check = true;
flags.nonremovable = true;
flags.recovery_only = true;
flags.verify_at_boot = true;
flags.verify = true;
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
}
entry++;
EXPECT_EQ("none1", entry->mount_point);
{
- FstabEntry::FsMgrFlags flags = {0};
+ FstabEntry::FsMgrFlags flags = {};
flags.avb = true;
flags.no_emulated_sd = true;
flags.no_trim = true;
flags.formattable = true;
flags.slot_select = true;
flags.no_fail = true;
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
}
entry++;
EXPECT_EQ("none2", entry->mount_point);
{
- FstabEntry::FsMgrFlags flags = {0};
+ FstabEntry::FsMgrFlags flags = {};
flags.first_stage_mount = true;
flags.late_mount = true;
flags.quota = true;
flags.logical = true;
flags.slot_select_other = true;
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
}
entry++;
EXPECT_EQ("none3", entry->mount_point);
{
- FstabEntry::FsMgrFlags flags = {0};
+ FstabEntry::FsMgrFlags flags = {};
flags.checkpoint_blk = true;
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
}
entry++;
EXPECT_EQ("none4", entry->mount_point);
{
- FstabEntry::FsMgrFlags flags = {0};
+ FstabEntry::FsMgrFlags flags = {};
flags.checkpoint_fs = true;
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
}
entry++;
EXPECT_EQ("none5", entry->mount_point);
{
- FstabEntry::FsMgrFlags flags = {0};
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ FstabEntry::FsMgrFlags flags = {};
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
}
}
@@ -355,8 +385,8 @@
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
{
- FstabEntry::FsMgrFlags flags = {0};
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ FstabEntry::FsMgrFlags flags = {};
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
}
EXPECT_EQ("", entry->key_loc);
EXPECT_EQ("", entry->key_dir);
@@ -380,25 +410,13 @@
EXPECT_EQ("none1", entry->mount_point);
{
- FstabEntry::FsMgrFlags flags = {0};
+ FstabEntry::FsMgrFlags flags = {};
flags.crypt = true;
flags.force_crypt = true;
flags.file_encryption = true;
- flags.key_directory = true;
- flags.length = true;
- flags.swap_prio = true;
- flags.zram_size = true;
- flags.max_comp_streams = true;
flags.verify = true;
flags.avb = true;
- flags.reserved_size = true;
- flags.erase_blk_size = true;
- flags.logical_blk_size = true;
- flags.sysfs = true;
- flags.zram_loopback_path = true;
- flags.zram_loopback_size = true;
- flags.zram_backing_dev_path = true;
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
}
EXPECT_EQ("", entry->key_loc);
EXPECT_EQ("", entry->key_dir);
@@ -423,9 +441,9 @@
// forcefdeorfbe sets file_contents_mode and file_names_mode by default, so test it separately.
EXPECT_EQ("none2", entry->mount_point);
{
- FstabEntry::FsMgrFlags flags = {0};
+ FstabEntry::FsMgrFlags flags = {};
flags.force_fde_or_fbe = true;
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
}
EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
EXPECT_EQ("aes-256-cts", entry->file_names_mode);
@@ -444,12 +462,12 @@
EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
ASSERT_EQ(1U, fstab.size());
- FstabEntry::FsMgrFlags flags = {0};
+ FstabEntry::FsMgrFlags flags = {};
flags.crypt = true;
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("/dir/key", entry->key_loc);
}
@@ -468,30 +486,30 @@
EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
ASSERT_EQ(4U, fstab.size());
- FstabEntry::FsMgrFlags flags = {0};
+ FstabEntry::FsMgrFlags flags = {};
flags.vold_managed = true;
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_TRUE(entry->label.empty());
EXPECT_EQ(-1, entry->partnum);
entry++;
EXPECT_EQ("none1", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_TRUE(entry->label.empty());
EXPECT_EQ(-1, entry->partnum);
entry++;
EXPECT_EQ("none2", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("sdcard", entry->label);
EXPECT_EQ(3, entry->partnum);
entry++;
EXPECT_EQ("none3", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("sdcard", entry->label);
EXPECT_EQ(-1, entry->partnum);
}
@@ -509,17 +527,16 @@
EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
ASSERT_EQ(2U, fstab.size());
- FstabEntry::FsMgrFlags flags = {0};
- flags.length = true;
+ FstabEntry::FsMgrFlags flags = {};
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(0, entry->length);
entry++;
EXPECT_EQ("none1", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(123456, entry->length);
}
@@ -536,17 +553,16 @@
EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
ASSERT_EQ(2U, fstab.size());
- FstabEntry::FsMgrFlags flags = {0};
- flags.swap_prio = true;
+ FstabEntry::FsMgrFlags flags = {};
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(-1, entry->swap_prio);
entry++;
EXPECT_EQ("none1", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(123456, entry->swap_prio);
}
@@ -567,37 +583,36 @@
EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
ASSERT_EQ(6U, fstab.size());
- FstabEntry::FsMgrFlags flags = {0};
- flags.zram_size = true;
+ FstabEntry::FsMgrFlags flags = {};
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(0, entry->zram_size);
entry++;
EXPECT_EQ("none1", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(123456, entry->zram_size);
entry++;
EXPECT_EQ("none2", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(0, entry->zram_size);
entry++;
EXPECT_EQ("none3", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_NE(0, entry->zram_size);
entry++;
EXPECT_EQ("none4", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(0, entry->zram_size);
entry++;
EXPECT_EQ("none5", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(0, entry->zram_size);
}
@@ -617,9 +632,9 @@
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- FstabEntry::FsMgrFlags flags = {0};
+ FstabEntry::FsMgrFlags flags = {};
flags.verify = true;
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("/dir/key", entry->verity_loc);
}
@@ -640,9 +655,9 @@
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- FstabEntry::FsMgrFlags flags = {0};
+ FstabEntry::FsMgrFlags flags = {};
flags.force_crypt = true;
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("/dir/key", entry->key_loc);
}
@@ -663,9 +678,9 @@
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- FstabEntry::FsMgrFlags flags = {0};
+ FstabEntry::FsMgrFlags flags = {};
flags.force_fde_or_fbe = true;
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("/dir/key", entry->key_loc);
EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
@@ -695,72 +710,72 @@
EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
ASSERT_EQ(11U, fstab.size());
- FstabEntry::FsMgrFlags flags = {0};
+ FstabEntry::FsMgrFlags flags = {};
flags.file_encryption = true;
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("", entry->file_contents_mode);
EXPECT_EQ("", entry->file_names_mode);
entry++;
EXPECT_EQ("none1", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
EXPECT_EQ("aes-256-cts", entry->file_names_mode);
entry++;
EXPECT_EQ("none2", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
EXPECT_EQ("aes-256-cts", entry->file_names_mode);
entry++;
EXPECT_EQ("none3", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("adiantum", entry->file_contents_mode);
EXPECT_EQ("adiantum", entry->file_names_mode);
entry++;
EXPECT_EQ("none4", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("adiantum", entry->file_contents_mode);
EXPECT_EQ("aes-256-heh", entry->file_names_mode);
entry++;
EXPECT_EQ("none5", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("ice", entry->file_contents_mode);
EXPECT_EQ("aes-256-cts", entry->file_names_mode);
entry++;
EXPECT_EQ("none6", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("ice", entry->file_contents_mode);
EXPECT_EQ("", entry->file_names_mode);
entry++;
EXPECT_EQ("none7", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("ice", entry->file_contents_mode);
EXPECT_EQ("aes-256-cts", entry->file_names_mode);
entry++;
EXPECT_EQ("none8", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("ice", entry->file_contents_mode);
EXPECT_EQ("aes-256-heh", entry->file_names_mode);
entry++;
EXPECT_EQ("none9", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("ice", entry->file_contents_mode);
EXPECT_EQ("adiantum", entry->file_names_mode);
entry++;
EXPECT_EQ("none10", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("", entry->file_contents_mode);
EXPECT_EQ("", entry->file_names_mode);
}
@@ -778,17 +793,16 @@
EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
ASSERT_EQ(2U, fstab.size());
- FstabEntry::FsMgrFlags flags = {0};
- flags.max_comp_streams = true;
+ FstabEntry::FsMgrFlags flags = {};
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(0, entry->max_comp_streams);
entry++;
EXPECT_EQ("none1", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(123456, entry->max_comp_streams);
}
@@ -807,27 +821,26 @@
EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
ASSERT_EQ(4U, fstab.size());
- FstabEntry::FsMgrFlags flags = {0};
- flags.reserved_size = true;
+ FstabEntry::FsMgrFlags flags = {};
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(0, entry->reserved_size);
entry++;
EXPECT_EQ("none1", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(2, entry->reserved_size);
entry++;
EXPECT_EQ("none2", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(1024, entry->reserved_size);
entry++;
EXPECT_EQ("none3", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(2 * 1024 * 1024, entry->reserved_size);
}
@@ -846,27 +859,26 @@
EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
ASSERT_EQ(4U, fstab.size());
- FstabEntry::FsMgrFlags flags = {0};
- flags.erase_blk_size = true;
+ FstabEntry::FsMgrFlags flags = {};
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(0, entry->erase_blk_size);
entry++;
EXPECT_EQ("none1", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(0, entry->erase_blk_size);
entry++;
EXPECT_EQ("none2", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(0, entry->erase_blk_size);
entry++;
EXPECT_EQ("none3", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(8192, entry->erase_blk_size);
}
@@ -885,27 +897,26 @@
EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
ASSERT_EQ(4U, fstab.size());
- FstabEntry::FsMgrFlags flags = {0};
- flags.logical_blk_size = true;
+ FstabEntry::FsMgrFlags flags = {};
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(0, entry->logical_blk_size);
entry++;
EXPECT_EQ("none1", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(0, entry->logical_blk_size);
entry++;
EXPECT_EQ("none2", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(0, entry->logical_blk_size);
entry++;
EXPECT_EQ("none3", entry->mount_point);
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(8192, entry->logical_blk_size);
}
@@ -925,9 +936,9 @@
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- FstabEntry::FsMgrFlags flags = {0};
+ FstabEntry::FsMgrFlags flags = {};
flags.avb = true;
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("vbmeta_partition", entry->vbmeta_partition);
}
@@ -948,9 +959,8 @@
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- FstabEntry::FsMgrFlags flags = {0};
- flags.key_directory = true;
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ FstabEntry::FsMgrFlags flags = {};
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("/dir/key", entry->key_dir);
}
@@ -971,9 +981,8 @@
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
- FstabEntry::FsMgrFlags flags = {0};
- flags.sysfs = true;
- EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+ FstabEntry::FsMgrFlags flags = {};
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ("/sys/device", entry->sysfs_path);
}
diff --git a/init/README.md b/init/README.md
index 3a7c71c..f0e5d55 100644
--- a/init/README.md
+++ b/init/README.md
@@ -161,11 +161,13 @@
Options are modifiers to services. They affect how and when init
runs the service.
-`capabilities <capability> [ <capability>\* ]`
+`capabilities [ <capability>\* ]`
> Set capabilities when exec'ing this service. 'capability' should be a Linux
capability without the "CAP\_" prefix, like "NET\_ADMIN" or "SETPCAP". See
http://man7.org/linux/man-pages/man7/capabilities.7.html for a list of Linux
capabilities.
+ If no capabilities are provided, then all capabilities are removed from this service, even if it
+ runs as root.
`class <name> [ <name>\* ]`
> Specify class names for the service. All services in a
diff --git a/init/init.cpp b/init/init.cpp
index 5a3cc15..a8924f2 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -192,7 +192,8 @@
if (waiting_for_prop) {
if (wait_prop_name == name && wait_prop_value == value) {
- LOG(INFO) << "Wait for property took " << *waiting_for_prop;
+ LOG(INFO) << "Wait for property '" << wait_prop_name << "=" << wait_prop_value
+ << "' took " << *waiting_for_prop;
ResetWaitForProp();
}
}
diff --git a/init/service.cpp b/init/service.cpp
index 84cb2d8..2186a85 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -218,12 +218,12 @@
Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
const std::vector<std::string>& args)
- : Service(name, 0, 0, 0, {}, 0, 0, "", subcontext_for_restart_commands, args) {}
+ : Service(name, 0, 0, 0, {}, 0, "", subcontext_for_restart_commands, args) {}
Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
- const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
- unsigned namespace_flags, const std::string& seclabel,
- Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args)
+ const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
+ const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
+ const std::vector<std::string>& args)
: name_(name),
classnames_({"default"}),
flags_(flags),
@@ -232,7 +232,6 @@
uid_(uid),
gid_(gid),
supp_gids_(supp_gids),
- capabilities_(capabilities),
namespace_flags_(namespace_flags),
seclabel_(seclabel),
onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0,
@@ -289,7 +288,7 @@
}
}
// Keep capabilites on uid change.
- if (capabilities_.any() && uid_) {
+ if (capabilities_ && uid_) {
// If Android is running in a container, some securebits might already
// be locked, so don't change those.
unsigned long securebits = prctl(PR_GET_SECUREBITS);
@@ -328,8 +327,8 @@
PLOG(FATAL) << "setpriority failed for " << name_;
}
}
- if (capabilities_.any()) {
- if (!SetCapsForExec(capabilities_)) {
+ if (capabilities_) {
+ if (!SetCapsForExec(*capabilities_)) {
LOG(FATAL) << "cannot set capabilities for " << name_;
}
} else if (uid_) {
@@ -375,7 +374,7 @@
// If we crash > 4 times in 4 minutes, reboot into bootloader or set crashing property
boot_clock::time_point now = boot_clock::now();
- if (((flags_ & SVC_CRITICAL) || classnames_.count("updatable")) && !(flags_ & SVC_RESTART)) {
+ if (((flags_ & SVC_CRITICAL) || !pre_apexd_) && !(flags_ & SVC_RESTART)) {
if (now < time_crashed_ + 4min) {
if (++crash_count_ > 4) {
if (flags_ & SVC_CRITICAL) {
@@ -420,7 +419,7 @@
}
unsigned int last_valid_cap = GetLastValidCap();
- if (last_valid_cap >= capabilities_.size()) {
+ if (last_valid_cap >= capabilities_->size()) {
LOG(WARNING) << "last valid run-time capability is larger than CAP_LAST_CAP";
}
@@ -435,7 +434,7 @@
return Error() << StringPrintf("capability '%s' not supported by the kernel",
arg.c_str());
}
- capabilities_[cap] = true;
+ (*capabilities_)[cap] = true;
}
return Success();
}
@@ -796,7 +795,7 @@
// clang-format off
static const Map option_parsers = {
{"capabilities",
- {1, kMax, &Service::ParseCapabilities}},
+ {0, kMax, &Service::ParseCapabilities}},
{"class", {1, kMax, &Service::ParseClass}},
{"console", {0, 1, &Service::ParseConsole}},
{"critical", {0, 0, &Service::ParseCritical}},
@@ -1268,7 +1267,6 @@
std::string name = "exec " + std::to_string(exec_count) + " (" + Join(str_args, " ") + ")";
unsigned flags = SVC_ONESHOT | SVC_TEMPORARY;
- CapSet no_capabilities;
unsigned namespace_flags = 0;
std::string seclabel = "";
@@ -1303,8 +1301,8 @@
}
}
- return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, no_capabilities,
- namespace_flags, seclabel, nullptr, str_args);
+ return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, namespace_flags, seclabel,
+ nullptr, str_args);
}
// Shutdown services in the opposite order that they were started.
diff --git a/init/service.h b/init/service.h
index c29723a..c42a5a3 100644
--- a/init/service.h
+++ b/init/service.h
@@ -68,9 +68,9 @@
const std::vector<std::string>& args);
Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
- const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
- unsigned namespace_flags, const std::string& seclabel,
- Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args);
+ const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
+ const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
+ const std::vector<std::string>& args);
static std::unique_ptr<Service> MakeTemporaryOneshotService(const std::vector<std::string>& args);
@@ -192,7 +192,7 @@
uid_t uid_;
gid_t gid_;
std::vector<gid_t> supp_gids_;
- CapSet capabilities_;
+ std::optional<CapSet> capabilities_;
unsigned namespace_flags_;
// Pair of namespace type, path to namespace.
std::vector<std::pair<int, std::string>> namespaces_to_enter_;
diff --git a/init/service_test.cpp b/init/service_test.cpp
index 194aa2b..4bfaa6b 100644
--- a/init/service_test.cpp
+++ b/init/service_test.cpp
@@ -57,7 +57,7 @@
}
Service* service_in_old_memory2 = new (old_memory) Service(
- "test_old_memory", 0U, 0U, 0U, std::vector<gid_t>(), CapSet(), 0U, "", nullptr, dummy_args);
+ "test_old_memory", 0U, 0U, 0U, std::vector<gid_t>(), 0U, "", nullptr, dummy_args);
EXPECT_EQ(0U, service_in_old_memory2->flags());
EXPECT_EQ(0, service_in_old_memory2->pid());
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 0dbbc3f..fab4b4e 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -172,7 +172,10 @@
}
},
- shared_libs: ["liblog"],
+ shared_libs: [
+ "liblog",
+ "libbase",
+ ],
header_libs: [
"libbase_headers",
"libcutils_headers",
diff --git a/libcutils/ashmem-dev.cpp b/libcutils/ashmem-dev.cpp
index 0cc4fc0..e35b91a 100644
--- a/libcutils/ashmem-dev.cpp
+++ b/libcutils/ashmem-dev.cpp
@@ -23,20 +23,40 @@
*/
#define LOG_TAG "ashmem"
+#ifndef __ANDROID_VNDK__
+#include <dlfcn.h>
+#endif
#include <errno.h>
#include <fcntl.h>
#include <linux/ashmem.h>
+#include <linux/memfd.h>
+#include <log/log.h>
#include <pthread.h>
+#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
+#include <sys/mman.h>
#include <sys/stat.h>
+#include <sys/syscall.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <unistd.h>
-#include <log/log.h>
+
+#include <android-base/properties.h>
+#include <android-base/unique_fd.h>
#define ASHMEM_DEVICE "/dev/ashmem"
+/* Will be added to UAPI once upstream change is merged */
+#define F_SEAL_FUTURE_WRITE 0x0010
+
+/*
+ * The minimum vendor API level at and after which it is safe to use memfd.
+ * This is to facilitate deprecation of ashmem.
+ */
+#define MIN_MEMFD_VENDOR_API_LEVEL 29
+#define MIN_MEMFD_VENDOR_API_LEVEL_CHAR 'Q'
+
/* ashmem identity */
static dev_t __ashmem_rdev;
/*
@@ -45,13 +65,170 @@
*/
static pthread_mutex_t __ashmem_lock = PTHREAD_MUTEX_INITIALIZER;
+/*
+ * We use ashmemd to enforce that apps don't open /dev/ashmem directly. Vendor
+ * code can't access system aidl services per Treble requirements. So we limit
+ * ashmemd access to the system variant of libcutils.
+ */
+#ifndef __ANDROID_VNDK__
+using openFdType = int (*)();
+
+openFdType initOpenAshmemFd() {
+ openFdType openFd = nullptr;
+ void* handle = dlopen("libashmemd_client.so", RTLD_NOW);
+ if (!handle) {
+ ALOGE("Failed to dlopen() libashmemd_client.so: %s", dlerror());
+ return openFd;
+ }
+
+ openFd = reinterpret_cast<openFdType>(dlsym(handle, "openAshmemdFd"));
+ if (!openFd) {
+ ALOGE("Failed to dlsym() openAshmemdFd() function: %s", dlerror());
+ }
+ return openFd;
+}
+#endif
+
+/*
+ * has_memfd_support() determines if the device can use memfd. memfd support
+ * has been there for long time, but certain things in it may be missing. We
+ * check for needed support in it. Also we check if the VNDK version of
+ * libcutils being used is new enough, if its not, then we cannot use memfd
+ * since the older copies may be using ashmem so we just use ashmem. Once all
+ * Android devices that are getting updates are new enough (ex, they were
+ * originally shipped with Android release > P), then we can just use memfd and
+ * delete all ashmem code from libcutils (while preserving the interface).
+ *
+ * NOTE:
+ * The sys.use_memfd property is set by default to false in Android
+ * to temporarily disable memfd, till vendor and apps are ready for it.
+ * The main issue: either apps or vendor processes can directly make ashmem
+ * IOCTLs on FDs they receive by assuming they are ashmem, without going
+ * through libcutils. Such fds could have very well be originally created with
+ * libcutils hence they could be memfd. Thus the IOCTLs will break.
+ *
+ * Set default value of sys.use_memfd property to true once the issue is
+ * resolved, so that the code can then self-detect if kernel support is present
+ * on the device. The property can also set to true from adb shell, for
+ * debugging.
+ */
+
+static bool debug_log = false; /* set to true for verbose logging and other debug */
+static bool pin_deprecation_warn = true; /* Log the pin deprecation warning only once */
+
+/* Determine if vendor processes would be ok with memfd in the system:
+ *
+ * If VNDK is using older libcutils, don't use memfd. This is so that the
+ * same shared memory mechanism is used across binder transactions between
+ * vendor partition processes and system partition processes.
+ */
+static bool check_vendor_memfd_allowed() {
+ std::string vndk_version = android::base::GetProperty("ro.vndk.version", "");
+
+ if (vndk_version == "") {
+ ALOGE("memfd: ro.vndk.version not defined or invalid (%s), this is mandated since P.\n",
+ vndk_version.c_str());
+ return false;
+ }
+
+ /* No issues if vendor is targetting current Dessert */
+ if (vndk_version == "current") {
+ return false;
+ }
+
+ /* Check if VNDK version is a number and act on it */
+ char* p;
+ long int vers = strtol(vndk_version.c_str(), &p, 10);
+ if (*p == 0) {
+ if (vers < MIN_MEMFD_VENDOR_API_LEVEL) {
+ ALOGI("memfd: device VNDK version (%s) is < Q so using ashmem.\n",
+ vndk_version.c_str());
+ return false;
+ }
+
+ return true;
+ }
+
+ /* If its not a number, assume string, but check if its a sane string */
+ if (tolower(vndk_version[0]) < 'a' || tolower(vndk_version[0]) > 'z') {
+ ALOGE("memfd: ro.vndk.version not defined or invalid (%s), this is mandated since P.\n",
+ vndk_version.c_str());
+ return false;
+ }
+
+ if (tolower(vndk_version[0]) < tolower(MIN_MEMFD_VENDOR_API_LEVEL_CHAR)) {
+ ALOGI("memfd: device is using VNDK version (%s) which is less than Q. Use ashmem only.\n",
+ vndk_version.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+
+/* Determine if memfd can be supported. This is just one-time hardwork
+ * which will be cached by the caller.
+ */
+static bool __has_memfd_support() {
+ if (check_vendor_memfd_allowed() == false) {
+ return false;
+ }
+
+ /* Used to turn on/off the detection at runtime, in the future this
+ * property will be removed once we switch everything over to ashmem.
+ * Currently it is used only for debugging to switch the system over.
+ */
+ if (!android::base::GetBoolProperty("sys.use_memfd", false)) {
+ if (debug_log) {
+ ALOGD("sys.use_memfd=false so memfd disabled\n");
+ }
+ return false;
+ }
+
+ /* Check if kernel support exists, otherwise fall back to ashmem */
+ android::base::unique_fd fd(
+ syscall(__NR_memfd_create, "test_android_memfd", MFD_ALLOW_SEALING));
+ if (fd == -1) {
+ ALOGE("memfd_create failed: %s, no memfd support.\n", strerror(errno));
+ return false;
+ }
+
+ if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE) == -1) {
+ ALOGE("fcntl(F_ADD_SEALS) failed: %s, no memfd support.\n", strerror(errno));
+ return false;
+ }
+
+ if (debug_log) {
+ ALOGD("memfd: device has memfd support, using it\n");
+ }
+ return true;
+}
+
+static bool has_memfd_support() {
+ /* memfd_supported is the initial global per-process state of what is known
+ * about memfd.
+ */
+ static bool memfd_supported = __has_memfd_support();
+
+ return memfd_supported;
+}
+
/* logistics of getting file descriptor for ashmem */
static int __ashmem_open_locked()
{
int ret;
struct stat st;
- int fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR | O_CLOEXEC));
+ int fd = -1;
+#ifndef __ANDROID_VNDK__
+ static auto openFd = initOpenAshmemFd();
+ if (openFd) {
+ fd = openFd();
+ }
+#endif
+ if (fd < 0) {
+ fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR | O_CLOEXEC));
+ }
if (fd < 0) {
return fd;
}
@@ -141,11 +318,49 @@
return result;
}
+static bool memfd_is_ashmem(int fd) {
+ static bool fd_check_error_once = false;
+
+ if (__ashmem_is_ashmem(fd, 0) == 0) {
+ if (!fd_check_error_once) {
+ ALOGE("memfd: memfd expected but ashmem fd used - please use libcutils.\n");
+ fd_check_error_once = true;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
int ashmem_valid(int fd)
{
+ if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+ return 1;
+ }
+
return __ashmem_is_ashmem(fd, 0) >= 0;
}
+static int memfd_create_region(const char* name, size_t size) {
+ android::base::unique_fd fd(syscall(__NR_memfd_create, name, MFD_ALLOW_SEALING));
+
+ if (fd == -1) {
+ ALOGE("memfd_create(%s, %zd) failed: %s\n", name, size, strerror(errno));
+ return -1;
+ }
+
+ if (ftruncate(fd, size) == -1) {
+ ALOGE("ftruncate(%s, %zd) failed for memfd creation: %s\n", name, size, strerror(errno));
+ return -1;
+ }
+
+ if (debug_log) {
+ ALOGE("memfd_create(%s, %zd) success. fd=%d\n", name, size, fd.get());
+ }
+ return fd.release();
+}
+
/*
* ashmem_create_region - creates a new ashmem region and returns the file
* descriptor, or <0 on error
@@ -157,6 +372,10 @@
{
int ret, save_errno;
+ if (has_memfd_support()) {
+ return memfd_create_region(name ? name : "none", size);
+ }
+
int fd = __ashmem_open();
if (fd < 0) {
return fd;
@@ -186,28 +405,78 @@
return ret;
}
+static int memfd_set_prot_region(int fd, int prot) {
+ /* Only proceed if an fd needs to be write-protected */
+ if (prot & PROT_WRITE) {
+ return 0;
+ }
+
+ if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE) == -1) {
+ ALOGE("memfd_set_prot_region(%d, %d): F_SEAL_FUTURE_WRITE seal failed: %s\n", fd, prot,
+ strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
int ashmem_set_prot_region(int fd, int prot)
{
+ if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+ return memfd_set_prot_region(fd, prot);
+ }
+
return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_PROT_MASK, prot)));
}
int ashmem_pin_region(int fd, size_t offset, size_t len)
{
+ if (!pin_deprecation_warn || debug_log) {
+ ALOGE("Pinning is deprecated since Android Q. Please use trim or other methods.\n");
+ pin_deprecation_warn = true;
+ }
+
+ if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+ return 0;
+ }
+
// TODO: should LP64 reject too-large offset/len?
ashmem_pin pin = { static_cast<uint32_t>(offset), static_cast<uint32_t>(len) };
-
return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_PIN, &pin)));
}
int ashmem_unpin_region(int fd, size_t offset, size_t len)
{
+ if (!pin_deprecation_warn || debug_log) {
+ ALOGE("Pinning is deprecated since Android Q. Please use trim or other methods.\n");
+ pin_deprecation_warn = true;
+ }
+
+ if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+ return 0;
+ }
+
// TODO: should LP64 reject too-large offset/len?
ashmem_pin pin = { static_cast<uint32_t>(offset), static_cast<uint32_t>(len) };
-
return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_UNPIN, &pin)));
}
int ashmem_get_size_region(int fd)
{
+ if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+ struct stat sb;
+
+ if (fstat(fd, &sb) == -1) {
+ ALOGE("ashmem_get_size_region(%d): fstat failed: %s\n", fd, strerror(errno));
+ return -1;
+ }
+
+ if (debug_log) {
+ ALOGD("ashmem_get_size_region(%d): %d\n", fd, static_cast<int>(sb.st_size));
+ }
+
+ return sb.st_size;
+ }
+
return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL)));
}
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 47af90d..5394d7e 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -103,6 +103,11 @@
static constexpr const char kVndkspNativeLibrariesSystemConfigPathFromRoot[] =
"/etc/vndksp.libraries.txt";
+static const std::vector<const std::string> kRuntimePublicLibraries = {
+ "libicuuc.so",
+ "libicui18n.so",
+};
+
// The device may be configured to have the vendor libraries loaded to a separate namespace.
// For historical reasons this namespace was named sphal but effectively it is intended
// to use to load vendor libraries to separate namespace with controlled interface between
@@ -111,7 +116,18 @@
static constexpr const char* kVndkNamespaceName = "vndk";
+static constexpr const char* kRuntimeNamespaceName = "runtime";
+
+// classloader-namespace is a linker namespace that is created for the loaded
+// app. To be specific, it is created for the app classloader. When
+// System.load() is called from a Java class that is loaded from the
+// classloader, the classloader-namespace namespace associated with that
+// classloader is selected for dlopen. The namespace is configured so that its
+// search path is set to the app-local JNI directory and it is linked to the
+// default namespace with the names of libs listed in the public.libraries.txt.
+// This way an app can only load its own JNI libraries along with the public libs.
static constexpr const char* kClassloaderNamespaceName = "classloader-namespace";
+// Same thing for vendor APKs.
static constexpr const char* kVendorClassloaderNamespaceName = "vendor-classloader-namespace";
// (http://b/27588281) This is a workaround for apps using custom classloaders and calling
@@ -245,6 +261,8 @@
}
}
+ std::string runtime_exposed_libraries = base::Join(kRuntimePublicLibraries, ":");
+
NativeLoaderNamespace native_loader_ns;
if (!is_native_bridge) {
android_namespace_t* android_parent_ns =
@@ -265,11 +283,21 @@
// which is expected behavior in this case.
android_namespace_t* vendor_ns = android_get_exported_namespace(kVendorNamespaceName);
+ android_namespace_t* runtime_ns = android_get_exported_namespace(kRuntimeNamespaceName);
+
if (!android_link_namespaces(ns, nullptr, system_exposed_libraries.c_str())) {
*error_msg = dlerror();
return nullptr;
}
+ // Runtime apex does not exist in host, and under certain build conditions.
+ if (runtime_ns != nullptr) {
+ if (!android_link_namespaces(ns, runtime_ns, runtime_exposed_libraries.c_str())) {
+ *error_msg = dlerror();
+ return nullptr;
+ }
+ }
+
if (vndk_ns != nullptr && !system_vndksp_libraries_.empty()) {
// vendor apks are allowed to use VNDK-SP libraries.
if (!android_link_namespaces(ns, vndk_ns, system_vndksp_libraries_.c_str())) {
@@ -301,12 +329,21 @@
}
native_bridge_namespace_t* vendor_ns = NativeBridgeGetExportedNamespace(kVendorNamespaceName);
+ native_bridge_namespace_t* runtime_ns =
+ NativeBridgeGetExportedNamespace(kRuntimeNamespaceName);
if (!NativeBridgeLinkNamespaces(ns, nullptr, system_exposed_libraries.c_str())) {
*error_msg = NativeBridgeGetError();
return nullptr;
}
+ // Runtime apex does not exist in host, and under certain build conditions.
+ if (runtime_ns != nullptr) {
+ if (!NativeBridgeLinkNamespaces(ns, runtime_ns, runtime_exposed_libraries.c_str())) {
+ *error_msg = NativeBridgeGetError();
+ return nullptr;
+ }
+ }
if (!vendor_public_libraries_.empty()) {
if (!NativeBridgeLinkNamespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) {
*error_msg = NativeBridgeGetError();
diff --git a/libpixelflinger/tests/Android.bp b/libpixelflinger/tests/Android.bp
index 820a84d..e20dd93 100644
--- a/libpixelflinger/tests/Android.bp
+++ b/libpixelflinger/tests/Android.bp
@@ -8,6 +8,7 @@
header_libs: ["libpixelflinger_internal"],
static_libs: [
+ "libbase",
"libcutils",
"liblog",
"libpixelflinger",
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index 12cfb7e..cd8ef94 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -19,6 +19,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <grp.h>
#include <pwd.h>
#include <sys/mman.h>
#include <sys/mount.h>
@@ -72,26 +73,28 @@
}
}
- passwd* uid_pwd = nullptr;
- passwd* gid_pwd = nullptr;
-
- if (!uid.empty()) {
- uid_pwd = getpwnam(uid.c_str());
- if (!uid_pwd) {
- PLOG(ERROR) << "Unable to decode UID for '" << uid << "'";
- return false;
- }
-
- if (!gid.empty()) {
- gid_pwd = getpwnam(gid.c_str());
- if (!gid_pwd) {
- PLOG(ERROR) << "Unable to decode GID for '" << gid << "'";
- return false;
- }
- }
+ if (uid.empty()) {
+ return true;
}
- if (uid_pwd && lchown(path.c_str(), uid_pwd->pw_uid, gid_pwd ? gid_pwd->pw_uid : -1) < 0) {
+ passwd* uid_pwd = getpwnam(uid.c_str());
+ if (!uid_pwd) {
+ PLOG(ERROR) << "Unable to decode UID for '" << uid << "'";
+ return false;
+ }
+
+ uid_t pw_uid = uid_pwd->pw_uid;
+ gid_t gr_gid = -1;
+ if (!gid.empty()) {
+ group* gid_pwd = getgrnam(gid.c_str());
+ if (!gid_pwd) {
+ PLOG(ERROR) << "Unable to decode GID for '" << gid << "'";
+ return false;
+ }
+ gr_gid = gid_pwd->gr_gid;
+ }
+
+ if (lchown(path.c_str(), pw_uid, gr_gid) < 0) {
PLOG(ERROR) << "lchown() failed for " << path;
return false;
}
@@ -128,7 +131,8 @@
std::string name = cgroups[i]["Controller"].asString();
descriptors->emplace(std::make_pair(
name,
- CgroupDescriptor(1, name, cgroups[i]["Path"].asString(), cgroups[i]["Mode"].asInt(),
+ CgroupDescriptor(1, name, cgroups[i]["Path"].asString(),
+ std::strtoul(cgroups[i]["Mode"].asString().c_str(), 0, 8),
cgroups[i]["UID"].asString(), cgroups[i]["GID"].asString())));
}
@@ -136,8 +140,8 @@
descriptors->emplace(std::make_pair(
CGROUPV2_CONTROLLER_NAME,
CgroupDescriptor(2, CGROUPV2_CONTROLLER_NAME, cgroups2["Path"].asString(),
- cgroups2["Mode"].asInt(), cgroups2["UID"].asString(),
- cgroups2["GID"].asString())));
+ std::strtoul(cgroups2["Mode"].asString().c_str(), 0, 8),
+ cgroups2["UID"].asString(), cgroups2["GID"].asString())));
return true;
}
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index ec6cbbc..447852d 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -132,6 +132,7 @@
SetCgroupAction::SetCgroupAction(const CgroupController* c, const std::string& p)
: controller_(c), path_(p) {
+#ifdef CACHE_FILE_DESCRIPTORS
// cache file descriptor only if path is app independent
if (IsAppDependentPath(path_)) {
// file descriptor is not cached
@@ -155,6 +156,7 @@
}
fd_ = std::move(fd);
+#endif
}
bool SetCgroupAction::AddTidToCgroup(int tid, int fd) {
@@ -176,6 +178,7 @@
}
bool SetCgroupAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
+#ifdef CACHE_FILE_DESCRIPTORS
if (fd_ >= 0) {
// fd is cached, reuse it
if (!AddTidToCgroup(pid, fd_)) {
@@ -203,9 +206,24 @@
}
return true;
+#else
+ std::string procs_path = controller_->GetProcsFilePath(path_.c_str(), uid, pid);
+ unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(procs_path.c_str(), O_WRONLY | O_CLOEXEC)));
+ if (tmp_fd < 0) {
+ // no permissions to access the file, ignore
+ return true;
+ }
+ if (!AddTidToCgroup(pid, tmp_fd)) {
+ PLOG(ERROR) << "Failed to add task into cgroup";
+ return false;
+ }
+
+ return true;
+#endif
}
bool SetCgroupAction::ExecuteForTask(int tid) const {
+#ifdef CACHE_FILE_DESCRIPTORS
if (fd_ >= 0) {
// fd is cached, reuse it
if (!AddTidToCgroup(tid, fd_)) {
@@ -223,6 +241,20 @@
// application-dependent path can't be used with tid
PLOG(ERROR) << "Application profile can't be applied to a thread";
return false;
+#else
+ std::string tasks_path = controller_->GetTasksFilePath(path_.c_str());
+ unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(tasks_path.c_str(), O_WRONLY | O_CLOEXEC)));
+ if (tmp_fd < 0) {
+ // no permissions to access the file, ignore
+ return true;
+ }
+ if (!AddTidToCgroup(tid, tmp_fd)) {
+ PLOG(ERROR) << "Failed to add task into cgroup";
+ return false;
+ }
+
+ return true;
+#endif
}
bool TaskProfile::ExecuteForProcess(uid_t uid, pid_t pid) const {
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 83e74b2..b2e39f9 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -117,7 +117,9 @@
private:
const CgroupController* controller_;
std::string path_;
+#ifdef CACHE_FILE_DESCRIPTORS
android::base::unique_fd fd_;
+#endif
static bool IsAppDependentPath(const std::string& path);
static bool AddTidToCgroup(int tid, int fd);
diff --git a/rootdir/cgroups.json b/rootdir/cgroups.json
index 6eb88c9..aa71956 100644
--- a/rootdir/cgroups.json
+++ b/rootdir/cgroups.json
@@ -3,40 +3,40 @@
{
"Controller": "cpu",
"Path": "/dev/cpuctl",
- "Mode": 0755,
+ "Mode": "0755",
"UID": "system",
"GID": "system"
},
{
"Controller": "cpuacct",
"Path": "/acct",
- "Mode": 0555
+ "Mode": "0555"
},
{
"Controller": "cpuset",
"Path": "/dev/cpuset",
- "Mode": 0755,
+ "Mode": "0755",
"UID": "system",
"GID": "system"
},
{
"Controller": "memory",
"Path": "/dev/memcg",
- "Mode": 0700,
+ "Mode": "0700",
"UID": "root",
"GID": "system"
},
{
"Controller": "schedtune",
"Path": "/dev/stune",
- "Mode": 0755,
+ "Mode": "0755",
"UID": "system",
"GID": "system"
}
],
"Cgroups2": {
"Path": "/dev/cg2_bpf",
- "Mode": 0600,
+ "Mode": "0600",
"UID": "root",
"GID": "root"
}
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 9bf9058..7aa097d 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -24,6 +24,9 @@
dir.system = /data/nativetest64
dir.system = /data/benchmarktest
dir.system = /data/benchmarktest64
+# TODO(b/123864775): Ensure tests are run from one of the directories above and
+# remove this.
+dir.system = /data/local/tmp
dir.postinstall = /postinstall
@@ -78,9 +81,9 @@
namespace.default.asan.search.paths = /data/asan/system/${LIB}
namespace.default.asan.search.paths += /system/${LIB}
-namespace.default.asan.search.paths += /data/asan/product/${LIB}
+namespace.default.asan.search.paths += /data/asan/%PRODUCT%/${LIB}
namespace.default.asan.search.paths += /%PRODUCT%/${LIB}
-namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
+namespace.default.asan.search.paths += /data/asan/%PRODUCT_SERVICES%/${LIB}
namespace.default.asan.search.paths += /%PRODUCT_SERVICES%/${LIB}
namespace.default.asan.permitted.paths = /data
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index ca180c0..1904445 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -50,9 +50,9 @@
namespace.default.asan.search.paths += /odm/${LIB}
namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
namespace.default.asan.search.paths += /vendor/${LIB}
-namespace.default.asan.search.paths += /data/asan/product/${LIB}
+namespace.default.asan.search.paths += /data/asan/%PRODUCT%/${LIB}
namespace.default.asan.search.paths += /%PRODUCT%/${LIB}
-namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
+namespace.default.asan.search.paths += /data/asan/%PRODUCT_SERVICES%/${LIB}
namespace.default.asan.search.paths += /%PRODUCT_SERVICES%/${LIB}
# Keep in sync with the platform namespace in the com.android.runtime APEX
diff --git a/rootdir/init.rc b/rootdir/init.rc
index c6e2116..370bc1c 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -531,6 +531,9 @@
mkdir /data/anr 0775 system system
mkdir /data/apex 0750 root system
+ mkdir /data/apex/active 0750 root system
+ mkdir /data/apex/backup 0700 root system
+ mkdir /data/apex/sessions 0700 root system
mkdir /data/staging 0750 system system
# NFC: create data/nfc for nv storage
@@ -590,6 +593,11 @@
# Set indication (checked by vold) that we have finished this action
#setprop vold.post_fs_data_done 1
+ # sys.memfd_use set to false by default, which keeps it disabled
+ # until it is confirmed that apps and vendor processes don't make
+ # IOCTLs on ashmem fds any more.
+ setprop sys.use_memfd false
+
# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
on zygote-start && property:ro.crypto.state=unencrypted
diff --git a/rootdir/update_and_install_ld_config.mk b/rootdir/update_and_install_ld_config.mk
index 450be66..852e234 100644
--- a/rootdir/update_and_install_ld_config.mk
+++ b/rootdir/update_and_install_ld_config.mk
@@ -118,7 +118,12 @@
$(hide) sed -i.bak -e "s?%SANITIZER_RUNTIME_LIBRARIES%?$(PRIVATE_SANITIZER_RUNTIME_LIBRARIES)?g" $@
$(hide) sed -i.bak -e "s?%VNDK_VER%?$(PRIVATE_VNDK_VERSION_SUFFIX)?g" $@
$(hide) sed -i.bak -e "s?%PRODUCT%?$(TARGET_COPY_OUT_PRODUCT)?g" $@
+ifeq ($(TARGET_COPY_OUT_PRODUCT),$(TARGET_COPY_OUT_PRODUCT_SERVICES))
+ # Remove lines containing %PRODUCT_SERVICES% (identical to the %PRODUCT% ones)
+ $(hide) sed -i.bak -e "\?%PRODUCT_SERVICES%?d" $@
+else
$(hide) sed -i.bak -e "s?%PRODUCT_SERVICES%?$(TARGET_COPY_OUT_PRODUCT_SERVICES)?g" $@
+endif
$(hide) sed -i.bak -e "s?^$(PRIVATE_VNDK_VERSION_TAG)??g" $@
$(hide) sed -i.bak "/^\#VNDK[0-9]\{2\}\#.*$$/d" $@
$(hide) rm -f $@.bak