Merge "fs_mgr_verity: Add support for squashfs"
diff --git a/adb/remount_service.cpp b/adb/remount_service.cpp
index 483ca3d..b150274 100644
--- a/adb/remount_service.cpp
+++ b/adb/remount_service.cpp
@@ -112,13 +112,13 @@
}
bool system_verified = false, vendor_verified = false;
- property_get("partition.system.verified", prop_buf, "0");
- if (!strcmp(prop_buf, "1")) {
+ property_get("partition.system.verified", prop_buf, "");
+ if (strlen(prop_buf) > 0) {
system_verified = true;
}
- property_get("partition.vendor.verified", prop_buf, "0");
- if (!strcmp(prop_buf, "1")) {
+ property_get("partition.vendor.verified", prop_buf, "");
+ if (strlen(prop_buf) > 0) {
vendor_verified = true;
}
diff --git a/fs_mgr/fs_mgr_verity.c b/fs_mgr/fs_mgr_verity.c
index 840cf5a..c457762 100644
--- a/fs_mgr/fs_mgr_verity.c
+++ b/fs_mgr/fs_mgr_verity.c
@@ -52,6 +52,8 @@
#define METADATA_TAG_MAX_LENGTH 63
#define METADATA_EOD "eod"
+#define VERITY_LASTSIG_TAG "verity_lastsig"
+
#define VERITY_STATE_TAG "verity_state"
#define VERITY_STATE_HEADER 0x83c0ae9d
#define VERITY_STATE_VERSION 1
@@ -192,8 +194,12 @@
int protocol_version;
int device;
int retval = FS_MGR_SETUP_VERITY_FAIL;
- *signature = 0;
- *table = 0;
+
+ *signature = NULL;
+
+ if (table) {
+ *table = NULL;
+ }
device = TEMP_FAILURE_RETRY(open(block_device, O_RDONLY | O_CLOEXEC));
if (device == -1) {
@@ -248,6 +254,11 @@
goto out;
}
+ if (!table) {
+ retval = FS_MGR_SETUP_VERITY_SUCCESS;
+ goto out;
+ }
+
// get the size of the table
if (TEMP_FAILURE_RETRY(read(device, &table_length, sizeof(table_length))) !=
sizeof(table_length)) {
@@ -275,10 +286,13 @@
TEMP_FAILURE_RETRY(close(device));
if (retval != FS_MGR_SETUP_VERITY_SUCCESS) {
- free(*table);
free(*signature);
- *table = 0;
- *signature = 0;
+ *signature = NULL;
+
+ if (table) {
+ free(*table);
+ *table = NULL;
+ }
}
return retval;
@@ -596,46 +610,29 @@
return rc;
}
-static int load_verity_state(struct fstab_rec *fstab, int *mode)
+static int read_verity_state(const char *fname, off64_t offset, int *mode)
{
int fd = -1;
int rc = -1;
- off64_t offset = 0;
struct verity_state s;
- if (metadata_find(fstab->verity_loc, VERITY_STATE_TAG, sizeof(s),
- &offset) < 0) {
- /* fall back to stateless behavior */
- *mode = VERITY_MODE_EIO;
- rc = 0;
- goto out;
- }
-
- if (was_verity_restart()) {
- /* device was restarted after dm-verity detected a corrupted
- * block, so switch to logging mode */
- *mode = VERITY_MODE_LOGGING;
- rc = write_verity_state(fstab->verity_loc, offset, *mode);
- goto out;
- }
-
- fd = TEMP_FAILURE_RETRY(open(fstab->verity_loc, O_RDONLY | O_CLOEXEC));
+ fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC));
if (fd == -1) {
- ERROR("Failed to open %s (%s)\n", fstab->verity_loc, strerror(errno));
+ ERROR("Failed to open %s (%s)\n", fname, strerror(errno));
goto out;
}
if (TEMP_FAILURE_RETRY(pread64(fd, &s, sizeof(s), offset)) != sizeof(s)) {
ERROR("Failed to read %zu bytes from %s offset %" PRIu64 " (%s)\n",
- sizeof(s), fstab->verity_loc, offset, strerror(errno));
+ sizeof(s), fname, offset, strerror(errno));
goto out;
}
if (s.header != VERITY_STATE_HEADER) {
/* space allocated, but no state written. write default state */
*mode = VERITY_MODE_DEFAULT;
- rc = write_verity_state(fstab->verity_loc, offset, *mode);
+ rc = write_verity_state(fname, offset, *mode);
goto out;
}
@@ -661,14 +658,126 @@
return rc;
}
+static int compare_last_signature(struct fstab_rec *fstab, int *match)
+{
+ char tag[METADATA_TAG_MAX_LENGTH + 1];
+ char *signature = NULL;
+ int fd = -1;
+ int rc = -1;
+ uint8_t curr[SHA256_DIGEST_SIZE];
+ uint8_t prev[SHA256_DIGEST_SIZE];
+ off64_t offset = 0;
+
+ *match = 1;
+
+ if (read_verity_metadata(fstab->blk_device, &signature, NULL) < 0) {
+ ERROR("Failed to read verity signature from %s\n", fstab->mount_point);
+ goto out;
+ }
+
+ SHA256_hash(signature, RSANUMBYTES, curr);
+
+ if (snprintf(tag, sizeof(tag), VERITY_LASTSIG_TAG "_%s",
+ basename(fstab->mount_point)) >= (int)sizeof(tag)) {
+ ERROR("Metadata tag name too long for %s\n", fstab->mount_point);
+ goto out;
+ }
+
+ if (metadata_find(fstab->verity_loc, tag, SHA256_DIGEST_SIZE,
+ &offset) < 0) {
+ goto out;
+ }
+
+ fd = TEMP_FAILURE_RETRY(open(fstab->verity_loc, O_RDWR | O_SYNC | O_CLOEXEC));
+
+ if (fd == -1) {
+ ERROR("Failed to open %s: %s\n", fstab->verity_loc, strerror(errno));
+ goto out;
+ }
+
+ if (TEMP_FAILURE_RETRY(pread64(fd, prev, sizeof(prev),
+ offset)) != sizeof(prev)) {
+ ERROR("Failed to read %zu bytes from %s offset %" PRIu64 " (%s)\n",
+ sizeof(prev), fstab->verity_loc, offset, strerror(errno));
+ goto out;
+ }
+
+ *match = !memcmp(curr, prev, SHA256_DIGEST_SIZE);
+
+ if (!*match) {
+ /* update current signature hash */
+ if (TEMP_FAILURE_RETRY(pwrite64(fd, curr, sizeof(curr),
+ offset)) != sizeof(curr)) {
+ ERROR("Failed to write %zu bytes to %s offset %" PRIu64 " (%s)\n",
+ sizeof(curr), fstab->verity_loc, offset, strerror(errno));
+ goto out;
+ }
+ }
+
+ rc = 0;
+
+out:
+ free(signature);
+
+ if (fd != -1) {
+ TEMP_FAILURE_RETRY(close(fd));
+ }
+
+ return rc;
+}
+
+static int get_verity_state_offset(struct fstab_rec *fstab, off64_t *offset)
+{
+ char tag[METADATA_TAG_MAX_LENGTH + 1];
+
+ if (snprintf(tag, sizeof(tag), VERITY_STATE_TAG "_%s",
+ basename(fstab->mount_point)) >= (int)sizeof(tag)) {
+ ERROR("Metadata tag name too long for %s\n", fstab->mount_point);
+ return -1;
+ }
+
+ return metadata_find(fstab->verity_loc, tag, sizeof(struct verity_state),
+ offset);
+}
+
+static int load_verity_state(struct fstab_rec *fstab, int *mode)
+{
+ off64_t offset = 0;
+ int match = 0;
+
+ if (get_verity_state_offset(fstab, &offset) < 0) {
+ /* fall back to stateless behavior */
+ *mode = VERITY_MODE_EIO;
+ return 0;
+ }
+
+ if (was_verity_restart()) {
+ /* device was restarted after dm-verity detected a corrupted
+ * block, so switch to logging mode */
+ *mode = VERITY_MODE_LOGGING;
+ return write_verity_state(fstab->verity_loc, offset, *mode);
+ }
+
+ if (!compare_last_signature(fstab, &match) && !match) {
+ /* partition has been reflashed, reset dm-verity state */
+ *mode = VERITY_MODE_DEFAULT;
+ return write_verity_state(fstab->verity_loc, offset, *mode);
+ }
+
+ return read_verity_state(fstab->verity_loc, offset, mode);
+}
+
int fs_mgr_load_verity_state(int *mode)
{
char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
char propbuf[PROPERTY_VALUE_MAX];
int rc = -1;
int i;
+ int current;
struct fstab *fstab = NULL;
+ /* return the default mode, unless any of the verified partitions are in
+ * logging mode, in which case return that */
*mode = VERITY_MODE_DEFAULT;
property_get("ro.hardware", propbuf, "");
@@ -686,20 +795,16 @@
continue;
}
- rc = load_verity_state(&fstab->recs[i], mode);
+ rc = load_verity_state(&fstab->recs[i], ¤t);
if (rc < 0) {
continue;
}
- /* if any of the verified partitions are in logging mode, return */
- if (*mode == VERITY_MODE_LOGGING) {
- rc = 0;
- goto out;
+ if (current == VERITY_MODE_LOGGING) {
+ *mode = current;
}
}
- /* if there were multiple partitions, all in non-logging mode, return the
- * state of the last one */
rc = 0;
out:
@@ -719,6 +824,7 @@
char *status;
int fd = -1;
int i;
+ int mode;
int rc = -1;
off64_t offset = 0;
struct dm_ioctl *io = (struct dm_ioctl *) buffer;
@@ -746,8 +852,8 @@
continue;
}
- if (metadata_find(fstab->recs[i].verity_loc, VERITY_STATE_TAG,
- sizeof(struct verity_state), &offset) < 0) {
+ if (get_verity_state_offset(&fstab->recs[i], &offset) < 0 ||
+ read_verity_state(fstab->recs[i].verity_loc, offset, &mode) < 0) {
continue;
}
@@ -757,26 +863,23 @@
if (ioctl(fd, DM_TABLE_STATUS, io)) {
ERROR("Failed to query DM_TABLE_STATUS for %s (%s)\n", mount_point,
strerror(errno));
- goto out;
+ continue;
}
status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
if (*status == 'C') {
- rc = write_verity_state(fstab->recs[i].verity_loc, offset,
- VERITY_MODE_LOGGING);
-
- if (rc == -1) {
- goto out;
+ if (write_verity_state(fstab->recs[i].verity_loc, offset,
+ VERITY_MODE_LOGGING) < 0) {
+ continue;
}
}
if (callback) {
- callback(&fstab->recs[i], mount_point, *status);
+ callback(&fstab->recs[i], mount_point, mode, *status);
}
}
- /* Don't overwrite possible previous state if there's no corruption. */
rc = 0;
out:
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index b5e02f9..c58a888 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -69,7 +69,7 @@
// Callback function for verity status
typedef void (*fs_mgr_verity_state_callback)(struct fstab_rec *fstab,
- const char *mount_point, int status);
+ const char *mount_point, int mode, int status);
struct fstab *fs_mgr_read_fstab(const char *fstab_path);
void fs_mgr_free_fstab(struct fstab *fstab);
diff --git a/include/private/android_logger.h b/include/private/android_logger.h
index 724ca51..04238a6 100644
--- a/include/private/android_logger.h
+++ b/include/private/android_logger.h
@@ -70,7 +70,17 @@
android_event_long_t payload;
} android_log_event_long_t;
-/* Event payload EVENT_TYPE_STRING */
+/*
+ * Event payload EVENT_TYPE_STRING
+ *
+ * Danger: do not embed this structure into another structure.
+ * This structure uses a flexible array member, and when
+ * compiled using g++, __builtin_object_size(data, 1) returns
+ * a bad value. This is possibly a g++ bug, or a bug due to
+ * the fact that flexible array members are not supported
+ * in C++.
+ * http://stackoverflow.com/questions/4412749/are-flexible-array-members-valid-in-c
+ */
typedef struct __attribute__((__packed__)) {
int8_t type; // EVENT_TYPE_STRING;
int32_t length; // Little Endian Order
@@ -80,7 +90,9 @@
/* Event with single EVENT_TYPE_STRING */
typedef struct __attribute__((__packed__)) {
android_event_header_t header;
- android_event_string_t payload;
+ int8_t type; // EVENT_TYPE_STRING;
+ int32_t length; // Little Endian Order
+ char data[];
} android_log_event_string_t;
#endif
diff --git a/init/builtins.cpp b/init/builtins.cpp
index ff6c937..3bbaf83 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -661,8 +661,9 @@
return rc;
}
-static void verity_update_property(fstab_rec *fstab, const char *mount_point, int status) {
- property_set(android::base::StringPrintf("partition.%s.verified", mount_point).c_str(), "1");
+static void verity_update_property(fstab_rec *fstab, const char *mount_point, int mode, int status) {
+ property_set(android::base::StringPrintf("partition.%s.verified", mount_point).c_str(),
+ android::base::StringPrintf("%d", mode).c_str());
}
int do_verity_update_state(int nargs, char** args) {
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 6b3e637..bdb2915 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -150,9 +150,9 @@
rc = -ENOMEM;
} else {
event->header.tag = htole32(AUDITD_LOG_TAG);
- event->payload.type = EVENT_TYPE_STRING;
- event->payload.length = htole32(l);
- memcpy(event->payload.data, str, l);
+ event->type = EVENT_TYPE_STRING;
+ event->length = htole32(l);
+ memcpy(event->data, str, l);
logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid,
reinterpret_cast<char *>(event),
diff --git a/rootdir/init.rc b/rootdir/init.rc
index cda79ce..e6f4f4a 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -188,6 +188,7 @@
on post-fs
+ start logd
# once everything is setup, no need to modify /
mount rootfs rootfs / ro remount
# mount shared so changes propagate into child namespaces
@@ -311,6 +312,7 @@
mkdir /data/media 0770 media_rw media_rw
mkdir /data/ss 0700 system system
mkdir /data/system 0775 system system
+ mkdir /data/system/heapdump 0700 system system
mkdir /data/user 0711 system system
# Reload policy from /data/security if present.
@@ -484,6 +486,7 @@
socket logdw dgram 0222 logd logd
service logd-reinit /system/bin/logd --reinit
+ start logd
oneshot
disabled
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 186a89f..6f5567d 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -41,7 +41,6 @@
OUR_TOOLS := \
df \
getevent \
- getprop \
iftop \
ioctl \
ionice \
@@ -54,9 +53,7 @@
ps \
prlimit \
renice \
- restorecon \
sendevent \
- setprop \
start \
stop \
top \
diff --git a/toolbox/getprop.c b/toolbox/getprop.c
deleted file mode 100644
index dcc0ea0..0000000
--- a/toolbox/getprop.c
+++ /dev/null
@@ -1,50 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <cutils/properties.h>
-
-#include "dynarray.h"
-
-static void record_prop(const char* key, const char* name, void* opaque)
-{
- strlist_t* list = opaque;
- char temp[PROP_VALUE_MAX + PROP_NAME_MAX + 16];
- snprintf(temp, sizeof temp, "[%s]: [%s]", key, name);
- strlist_append_dup(list, temp);
-}
-
-static void list_properties(void)
-{
- strlist_t list[1] = { STRLIST_INITIALIZER };
-
- /* Record properties in the string list */
- (void)property_list(record_prop, list);
-
- /* Sort everything */
- strlist_sort(list);
-
- /* print everything */
- STRLIST_FOREACH(list, str, printf("%s\n", str));
-
- /* voila */
- strlist_done(list);
-}
-
-int getprop_main(int argc, char *argv[])
-{
- if (argc == 1) {
- list_properties();
- } else {
- char value[PROPERTY_VALUE_MAX];
- char *default_value;
- if(argc > 2) {
- default_value = argv[2];
- } else {
- default_value = "";
- }
-
- property_get(argv[1], value, default_value);
- printf("%s\n", value);
- }
- return 0;
-}
diff --git a/toolbox/restorecon.c b/toolbox/restorecon.c
deleted file mode 100644
index cb5799e..0000000
--- a/toolbox/restorecon.c
+++ /dev/null
@@ -1,63 +0,0 @@
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <selinux/selinux.h>
-#include <selinux/android.h>
-
-static const char *progname;
-
-static void usage(void)
-{
- fprintf(stderr, "usage: %s [-DFnrRv] pathname...\n", progname);
- exit(1);
-}
-
-int restorecon_main(int argc, char **argv)
-{
- int ch, i, rc;
- unsigned int flags = 0;
-
- progname = argv[0];
-
- do {
- ch = getopt(argc, argv, "DFnrRv");
- if (ch == EOF)
- break;
- switch (ch) {
- case 'D':
- flags |= SELINUX_ANDROID_RESTORECON_DATADATA;
- break;
- case 'F':
- flags |= SELINUX_ANDROID_RESTORECON_FORCE;
- break;
- case 'n':
- flags |= SELINUX_ANDROID_RESTORECON_NOCHANGE;
- break;
- case 'r':
- case 'R':
- flags |= SELINUX_ANDROID_RESTORECON_RECURSE;
- break;
- case 'v':
- flags |= SELINUX_ANDROID_RESTORECON_VERBOSE;
- break;
- default:
- usage();
- }
- } while (1);
-
- argc -= optind;
- argv += optind;
- if (!argc)
- usage();
-
- for (i = 0; i < argc; i++) {
- rc = selinux_android_restorecon(argv[i], flags);
- if (rc < 0)
- fprintf(stderr, "Could not restorecon %s: %s\n", argv[i],
- strerror(errno));
- }
-
- return 0;
-}
diff --git a/toolbox/setprop.c b/toolbox/setprop.c
deleted file mode 100644
index 63ad2b4..0000000
--- a/toolbox/setprop.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-
-#include <cutils/properties.h>
-
-int setprop_main(int argc, char *argv[])
-{
- if(argc != 3) {
- fprintf(stderr,"usage: setprop <key> <value>\n");
- return 1;
- }
-
- if(property_set(argv[1], argv[2])){
- fprintf(stderr,"could not set property\n");
- return 1;
- }
-
- return 0;
-}