diff options
53 files changed, 1008 insertions, 238 deletions
diff --git a/adb/transport.cpp b/adb/transport.cpp index 6020ad5b1..f8c8c615f 100644 --- a/adb/transport.cpp +++ b/adb/transport.cpp @@ -788,9 +788,7 @@ const FeatureSet& supported_features() { // Local static allocation to avoid global non-POD variables. static const FeatureSet* features = new FeatureSet{ kFeatureShell2, - // Internal master has 'cmd'. AOSP master doesn't. - // kFeatureCmd - + kFeatureCmd // Increment ADB_SERVER_VERSION whenever the feature list changes to // make sure that the adb client and server features stay in sync // (http://b/24370690). diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index b21956446..7c7d417c5 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -84,6 +84,8 @@ static unsigned ramdisk_offset = 0x01000000; static unsigned second_offset = 0x00f00000; static unsigned tags_offset = 0x00000100; +static const std::string convert_fbe_marker_filename("convert_fbe"); + enum fb_buffer_type { FB_BUFFER, FB_BUFFER_SPARSE, @@ -365,11 +367,17 @@ static void usage() { " given by --slot. If slots are not\n" " supported, this does nothing. This will\n" " run after all non-reboot commands.\n" +#if !defined(_WIN32) + " --wipe-and-use-fbe On devices which support it,\n" + " erase userdata and cache, and\n" + " enable file-based encryption\n" +#endif " --unbuffered Do not buffer input or output.\n" " --version Display version.\n" " -h, --help show this message.\n" ); } + static void* load_bootable_image(const char* kernel, const char* ramdisk, const char* secondstage, int64_t* sz, const char* cmdline) { @@ -489,8 +497,60 @@ static FILE* win32_tmpfile() { #define tmpfile win32_tmpfile +static std::string make_temporary_directory() { + fprintf(stderr, "make_temporary_directory not supported under Windows, sorry!"); + return ""; +} + +#else + +static std::string make_temporary_directory() { + const char *tmpdir = getenv("TMPDIR"); + if (tmpdir == nullptr) { + tmpdir = P_tmpdir; + } + std::string result = std::string(tmpdir) + "/fastboot_userdata_XXXXXX"; + if (mkdtemp(&result[0]) == NULL) { + fprintf(stderr, "Unable to create temporary directory: %s\n", + strerror(errno)); + return ""; + } + return result; +} + #endif +static std::string create_fbemarker_tmpdir() { + std::string dir = make_temporary_directory(); + if (dir.empty()) { + fprintf(stderr, "Unable to create local temp directory for FBE marker\n"); + return ""; + } + std::string marker_file = dir + "/" + convert_fbe_marker_filename; + int fd = open(marker_file.c_str(), O_CREAT | O_WRONLY | O_CLOEXEC, 0666); + if (fd == -1) { + fprintf(stderr, "Unable to create FBE marker file %s locally: %d, %s\n", + marker_file.c_str(), errno, strerror(errno)); + return ""; + } + close(fd); + return dir; +} + +static void delete_fbemarker_tmpdir(const std::string& dir) { + std::string marker_file = dir + "/" + convert_fbe_marker_filename; + if (unlink(marker_file.c_str()) == -1) { + fprintf(stderr, "Unable to delete FBE marker file %s locally: %d, %s\n", + marker_file.c_str(), errno, strerror(errno)); + return; + } + if (rmdir(dir.c_str()) == -1) { + fprintf(stderr, "Unable to delete FBE marker directory %s locally: %d, %s\n", + dir.c_str(), errno, strerror(errno)); + return; + } +} + static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) { FILE* fp = tmpfile(); if (fp == nullptr) { @@ -1076,7 +1136,8 @@ static int64_t parse_num(const char *arg) static void fb_perform_format(Transport* transport, const char* partition, int skip_if_not_supported, - const char* type_override, const char* size_override) { + const char* type_override, const char* size_override, + const std::string& initial_dir) { std::string partition_type, partition_size; struct fastboot_buffer buf; @@ -1140,7 +1201,7 @@ static void fb_perform_format(Transport* transport, } fd = fileno(tmpfile()); - if (fs_generator_generate(gen, fd, size)) { + if (fs_generator_generate(gen, fd, size, initial_dir)) { fprintf(stderr, "Cannot generate image: %s\n", strerror(errno)); close(fd); return; @@ -1169,6 +1230,7 @@ int main(int argc, char **argv) bool wants_reboot_bootloader = false; bool wants_set_active = false; bool erase_first = true; + bool set_fbe_marker = false; void *data; int64_t sz; int longindex; @@ -1191,6 +1253,9 @@ int main(int argc, char **argv) {"slot", required_argument, 0, 0}, {"set_active", optional_argument, 0, 'a'}, {"set-active", optional_argument, 0, 'a'}, +#if !defined(_WIN32) + {"wipe-and-use-fbe", no_argument, 0, 0}, +#endif {0, 0, 0, 0} }; @@ -1272,6 +1337,15 @@ int main(int argc, char **argv) return 0; } else if (strcmp("slot", longopts[longindex].name) == 0) { slot_override = std::string(optarg); +#if !defined(_WIN32) + } else if (strcmp("wipe-and-use-fbe", longopts[longindex].name) == 0) { + wants_wipe = true; + set_fbe_marker = true; +#endif + } else { + fprintf(stderr, "Internal error in options processing for %s\n", + longopts[longindex].name); + return 1; } break; default: @@ -1369,7 +1443,8 @@ int main(int argc, char **argv) if (erase_first && needs_erase(transport, partition.c_str())) { fb_queue_erase(partition.c_str()); } - fb_perform_format(transport, partition.c_str(), 0, type_override, size_override); + fb_perform_format(transport, partition.c_str(), 0, + type_override, size_override, ""); }; do_for_partitions(transport, argv[1], slot_override.c_str(), format, true); skip(2); @@ -1504,13 +1579,23 @@ int main(int argc, char **argv) if (wants_wipe) { fprintf(stderr, "wiping userdata...\n"); fb_queue_erase("userdata"); - fb_perform_format(transport, "userdata", 1, nullptr, nullptr); + if (set_fbe_marker) { + fprintf(stderr, "setting FBE marker...\n"); + std::string initial_userdata_dir = create_fbemarker_tmpdir(); + if (initial_userdata_dir.empty()) { + return 1; + } + fb_perform_format(transport, "userdata", 1, nullptr, nullptr, initial_userdata_dir); + delete_fbemarker_tmpdir(initial_userdata_dir); + } else { + fb_perform_format(transport, "userdata", 1, nullptr, nullptr, ""); + } std::string cache_type; if (fb_getvar(transport, "partition-type:cache", &cache_type) && !cache_type.empty()) { fprintf(stderr, "wiping cache...\n"); fb_queue_erase("cache"); - fb_perform_format(transport, "cache", 1, nullptr, nullptr); + fb_perform_format(transport, "cache", 1, nullptr, nullptr, ""); } } if (wants_set_active) { diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp index 90d84742b..8539e2382 100644 --- a/fastboot/fs.cpp +++ b/fastboot/fs.cpp @@ -1,7 +1,8 @@ +#include "fs.h" + #include "fastboot.h" #include "make_ext4fs.h" #include "make_f2fs.h" -#include "fs.h" #include <errno.h> #include <stdio.h> @@ -13,24 +14,32 @@ #include <sparse/sparse.h> -static int generate_ext4_image(int fd, long long partSize) +static int generate_ext4_image(int fd, long long partSize, const std::string& initial_dir) { - make_ext4fs_sparse_fd(fd, partSize, NULL, NULL); - + if (initial_dir.empty()) { + make_ext4fs_sparse_fd(fd, partSize, NULL, NULL); + } else { + make_ext4fs_sparse_fd_directory(fd, partSize, NULL, NULL, initial_dir.c_str()); + } return 0; } #ifdef USE_F2FS -static int generate_f2fs_image(int fd, long long partSize) +static int generate_f2fs_image(int fd, long long partSize, const std::string& initial_dir) { + if (!initial_dir.empty()) { + fprintf(stderr, "Unable to set initial directory on F2FS filesystem\n"); + return -1; + } return make_f2fs_sparse_fd(fd, partSize, NULL, NULL); } #endif static const struct fs_generator { - const char* fs_type; //must match what fastboot reports for partition type - int (*generate)(int fd, long long partSize); //returns 0 or error value + + //returns 0 or error value + int (*generate)(int fd, long long partSize, const std::string& initial_dir); } generators[] = { { "ext4", generate_ext4_image}, @@ -48,7 +57,8 @@ const struct fs_generator* fs_get_generator(const std::string& fs_type) { return nullptr; } -int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize) +int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize, + const std::string& initial_dir) { - return gen->generate(tmpFileNo, partSize); + return gen->generate(tmpFileNo, partSize, initial_dir); } diff --git a/fastboot/fs.h b/fastboot/fs.h index 289488b2d..0a68507b0 100644 --- a/fastboot/fs.h +++ b/fastboot/fs.h @@ -1,11 +1,13 @@ #ifndef _FS_H_ #define _FS_H_ +#include <string> #include <stdint.h> struct fs_generator; const struct fs_generator* fs_get_generator(const std::string& fs_type); -int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize); +int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize, + const std::string& initial_dir); #endif diff --git a/fingerprintd/FingerprintDaemonProxy.cpp b/fingerprintd/FingerprintDaemonProxy.cpp index beb95de73..1c7da30c3 100644 --- a/fingerprintd/FingerprintDaemonProxy.cpp +++ b/fingerprintd/FingerprintDaemonProxy.cpp @@ -88,6 +88,16 @@ void FingerprintDaemonProxy::hal_notify_callback(const fingerprint_msg_t *msg) { msg->data.removed.finger.fid, msg->data.removed.finger.gid); break; + case FINGERPRINT_TEMPLATE_ENUMERATING: + ALOGD("onEnumerate(fid=%d, gid=%d, rem=%d)", + msg->data.enumerated.finger.fid, + msg->data.enumerated.finger.gid, + msg->data.enumerated.remaining_templates); + callback->onEnumerate(device, + msg->data.enumerated.finger.fid, + msg->data.enumerated.finger.gid, + msg->data.enumerated.remaining_templates); + break; default: ALOGE("invalid msg type: %d", msg->type); return; @@ -158,6 +168,11 @@ int32_t FingerprintDaemonProxy::remove(int32_t fingerId, int32_t groupId) { return mDevice->remove(mDevice, groupId, fingerId); } +int32_t FingerprintDaemonProxy::enumerate() { + ALOG(LOG_VERBOSE, LOG_TAG, "enumerate()\n"); + return mDevice->enumerate(mDevice); +} + uint64_t FingerprintDaemonProxy::getAuthenticatorId() { return mDevice->get_authenticator_id(mDevice); } diff --git a/fingerprintd/FingerprintDaemonProxy.h b/fingerprintd/FingerprintDaemonProxy.h index 871c0e62a..145b4c936 100644 --- a/fingerprintd/FingerprintDaemonProxy.h +++ b/fingerprintd/FingerprintDaemonProxy.h @@ -40,6 +40,7 @@ class FingerprintDaemonProxy : public BnFingerprintDaemon { virtual int32_t authenticate(uint64_t sessionId, uint32_t groupId); virtual int32_t stopAuthentication(); virtual int32_t remove(int32_t fingerId, int32_t groupId); + virtual int32_t enumerate(); virtual uint64_t getAuthenticatorId(); virtual int32_t setActiveGroup(int32_t groupId, const uint8_t* path, ssize_t pathLen); virtual int64_t openHal(); diff --git a/fingerprintd/IFingerprintDaemon.cpp b/fingerprintd/IFingerprintDaemon.cpp index 71317932c..bc4af5685 100644 --- a/fingerprintd/IFingerprintDaemon.cpp +++ b/fingerprintd/IFingerprintDaemon.cpp @@ -125,6 +125,16 @@ status_t BnFingerprintDaemon::onTransact(uint32_t code, const Parcel& data, Parc reply->writeInt32(ret); return NO_ERROR; } + case ENUMERATE: { + CHECK_INTERFACE(IFingerprintDaemon, data, reply); + if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { + return PERMISSION_DENIED; + } + const int32_t ret = enumerate(); + reply->writeNoException(); + reply->writeInt32(ret); + return NO_ERROR; + } case GET_AUTHENTICATOR_ID: { CHECK_INTERFACE(IFingerprintDaemon, data, reply); if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { diff --git a/fingerprintd/IFingerprintDaemon.h b/fingerprintd/IFingerprintDaemon.h index 1eb4ac179..23c36ff87 100644 --- a/fingerprintd/IFingerprintDaemon.h +++ b/fingerprintd/IFingerprintDaemon.h @@ -44,6 +44,7 @@ class IFingerprintDaemon : public IInterface, public IBinder::DeathRecipient { CLOSE_HAL = IBinder::FIRST_CALL_TRANSACTION + 9, INIT = IBinder::FIRST_CALL_TRANSACTION + 10, POST_ENROLL = IBinder::FIRST_CALL_TRANSACTION + 11, + ENUMERATE = IBinder::FIRST_CALL_TRANSACTION + 12, }; IFingerprintDaemon() { } @@ -60,6 +61,7 @@ class IFingerprintDaemon : public IInterface, public IBinder::DeathRecipient { virtual int32_t authenticate(uint64_t sessionId, uint32_t groupId) = 0; virtual int32_t stopAuthentication() = 0; virtual int32_t remove(int32_t fingerId, int32_t groupId) = 0; + virtual int32_t enumerate() = 0; virtual uint64_t getAuthenticatorId() = 0; virtual int32_t setActiveGroup(int32_t groupId, const uint8_t* path, ssize_t pathLen) = 0; virtual int64_t openHal() = 0; diff --git a/fingerprintd/IFingerprintDaemonCallback.cpp b/fingerprintd/IFingerprintDaemonCallback.cpp index 44d8020ae..19838c908 100644 --- a/fingerprintd/IFingerprintDaemonCallback.cpp +++ b/fingerprintd/IFingerprintDaemonCallback.cpp @@ -74,13 +74,13 @@ public: return remote()->transact(ON_REMOVED, data, &reply, IBinder::FLAG_ONEWAY); } - virtual status_t onEnumerate(int64_t devId, const int32_t* fpIds, const int32_t* gpIds, - int32_t sz) { + virtual status_t onEnumerate(int64_t devId, int32_t fpId, int32_t gpId, int32_t rem) { Parcel data, reply; data.writeInterfaceToken(IFingerprintDaemonCallback::getInterfaceDescriptor()); data.writeInt64(devId); - data.writeInt32Array(sz, fpIds); - data.writeInt32Array(sz, gpIds); + data.writeInt32(fpId); + data.writeInt32(gpId); + data.writeInt32(rem); return remote()->transact(ON_ENUMERATE, data, &reply, IBinder::FLAG_ONEWAY); } }; diff --git a/fingerprintd/IFingerprintDaemonCallback.h b/fingerprintd/IFingerprintDaemonCallback.h index 6e32213b4..e343cb4f6 100644 --- a/fingerprintd/IFingerprintDaemonCallback.h +++ b/fingerprintd/IFingerprintDaemonCallback.h @@ -44,8 +44,7 @@ class IFingerprintDaemonCallback : public IInterface { virtual status_t onAuthenticated(int64_t devId, int32_t fingerId, int32_t groupId) = 0; virtual status_t onError(int64_t devId, int32_t error) = 0; virtual status_t onRemoved(int64_t devId, int32_t fingerId, int32_t groupId) = 0; - virtual status_t onEnumerate(int64_t devId, const int32_t* fpIds, const int32_t* gpIds, - int32_t sz) = 0; + virtual status_t onEnumerate(int64_t devId, int32_t fingerId, int32_t groupId, int32_t rem) = 0; DECLARE_META_INTERFACE(FingerprintDaemonCallback); }; diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c index c47a58591..bd30e943e 100644 --- a/fs_mgr/fs_mgr.c +++ b/fs_mgr/fs_mgr.c @@ -101,6 +101,7 @@ static void check_fs(char *blk_device, char *fs_type, char *target) char tmpmnt_opts[64] = "errors=remount-ro"; char *e2fsck_argv[] = { E2FSCK_BIN, + "-f", "-y", blk_device }; @@ -440,10 +441,24 @@ out: } // Check to see if a mountable volume has encryption requirements -static int handle_encryptable(struct fstab *fstab, const struct fstab_rec* rec) +static int handle_encryptable(const struct fstab_rec* rec) { + /* Check for existence of convert_fbe breadcrumb file */ + char convert_fbe_name[PATH_MAX]; + snprintf(convert_fbe_name, sizeof(convert_fbe_name), + "%s/convert_fbe", rec->mount_point); + bool convert_fbe = (access(convert_fbe_name, F_OK) == 0); + + /* Check for existence of convert_fbe breadcrumb file */ + char convert_fde_name[PATH_MAX]; + snprintf(convert_fde_name, sizeof(convert_fbe_name), + "%s/misc/vold/convert_fde", rec->mount_point); + bool convert_fde = (access(convert_fde_name, F_OK) == 0); + /* If this is block encryptable, need to trigger encryption */ if ( (rec->fs_mgr_flags & MF_FORCECRYPT) + || ((rec->fs_mgr_flags & MF_CRYPT) && convert_fde) + || ((rec->fs_mgr_flags & MF_FORCEFDEORFBE) && !convert_fbe) || (device_is_force_encrypted() && fs_mgr_is_encryptable(rec))) { if (umount(rec->mount_point) == 0) { return FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION; @@ -455,42 +470,10 @@ static int handle_encryptable(struct fstab *fstab, const struct fstab_rec* rec) } // Deal with file level encryption - if (rec->fs_mgr_flags & MF_FILEENCRYPTION) { - // Default or not yet initialized encryption requires no more work here - if (!e4crypt_non_default_key(rec->mount_point)) { - INFO("%s is default file encrypted\n", rec->mount_point); - return FS_MGR_MNTALL_DEV_DEFAULT_FILE_ENCRYPTED; - } - - INFO("%s is non-default file encrypted\n", rec->mount_point); - - // Uses non-default key, so must unmount and set up temp file system - if (umount(rec->mount_point)) { - ERROR("Failed to umount %s - rebooting\n", rec->mount_point); - return FS_MGR_MNTALL_FAIL; - } - - if (fs_mgr_do_tmpfs_mount(rec->mount_point) != 0) { - ERROR("Failed to mount a tmpfs at %s\n", rec->mount_point); - return FS_MGR_MNTALL_FAIL; - } - - // Mount data temporarily so we can access unencrypted dir - char tmp_mnt[PATH_MAX]; - strlcpy(tmp_mnt, rec->mount_point, sizeof(tmp_mnt)); - strlcat(tmp_mnt, "/tmp_mnt", sizeof(tmp_mnt)); - if (mkdir(tmp_mnt, 0700)) { - ERROR("Failed to create temp mount point\n"); - return FS_MGR_MNTALL_FAIL; - } - - if (fs_mgr_do_mount(fstab, rec->mount_point, - rec->blk_device, tmp_mnt)) { - ERROR("Error temp mounting encrypted file system\n"); - return FS_MGR_MNTALL_FAIL; - } - - return FS_MGR_MNTALL_DEV_NON_DEFAULT_FILE_ENCRYPTED; + if ( (rec->fs_mgr_flags & MF_FILEENCRYPTION) + || ((rec->fs_mgr_flags & MF_FORCEFDEORFBE) && convert_fbe)) { + INFO("%s is file encrypted\n", rec->mount_point); + return FS_MGR_MNTALL_DEV_FILE_ENCRYPTED; } return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED; @@ -568,7 +551,7 @@ int fs_mgr_mount_all(struct fstab *fstab) /* Deal with encryptability. */ if (!mret) { - int status = handle_encryptable(fstab, &fstab->recs[attempted_idx]); + int status = handle_encryptable(&fstab->recs[attempted_idx]); if (status == FS_MGR_MNTALL_FAIL) { /* Fatal error - no point continuing */ @@ -881,7 +864,8 @@ int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_dev if (fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) { continue; } - if (!(fstab->recs[i].fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT))) { + if (!(fstab->recs[i].fs_mgr_flags + & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE))) { continue; } diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c index cf35b3f42..c8c624d8f 100644 --- a/fs_mgr/fs_mgr_fstab.c +++ b/fs_mgr/fs_mgr_fstab.c @@ -64,6 +64,7 @@ static struct flag_list fs_mgr_flags[] = { { "encryptable=",MF_CRYPT }, { "forceencrypt=",MF_FORCECRYPT }, { "fileencryption",MF_FILEENCRYPTION }, + { "forcefdeorfbe=",MF_FORCEFDEORFBE }, { "nonremovable",MF_NONREMOVABLE }, { "voldmanaged=",MF_VOLDMANAGED}, { "length=", MF_LENGTH }, @@ -140,6 +141,11 @@ static int parse_flags(char *flags, struct flag_list *fl, * location of the keys. Get it and return it. */ flag_vals->key_loc = strdup(strchr(p, '=') + 1); + } else if ((fl[i].flag == MF_FORCEFDEORFBE) && flag_vals) { + /* The forcefdeorfbe flag is followed by an = and the + * location of the keys. Get it and return it. + */ + flag_vals->key_loc = strdup(strchr(p, '=') + 1); } else if ((fl[i].flag == MF_LENGTH) && flag_vals) { /* The length flag is followed by an = and the * size of the partition. Get it and return it. @@ -464,7 +470,7 @@ int fs_mgr_is_verified(const struct fstab_rec *fstab) int fs_mgr_is_encryptable(const struct fstab_rec *fstab) { - return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT); + return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE); } int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab) @@ -472,6 +478,11 @@ int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab) return fstab->fs_mgr_flags & MF_FILEENCRYPTION; } +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; diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h index ba0e097b0..181b6cdf5 100644 --- a/fs_mgr/fs_mgr_priv.h +++ b/fs_mgr/fs_mgr_priv.h @@ -82,6 +82,7 @@ __BEGIN_DECLS #define MF_FILEENCRYPTION 0x2000 #define MF_FORMATTABLE 0x4000 #define MF_SLOTSELECT 0x8000 +#define MF_FORCEFDEORFBE 0x10000 #define DM_BUF_SIZE 4096 diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index 27fccf72e..d9a7c4ce6 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -74,8 +74,7 @@ typedef void (*fs_mgr_verity_state_callback)(struct fstab_rec *fstab, struct fstab *fs_mgr_read_fstab(const char *fstab_path); void fs_mgr_free_fstab(struct fstab *fstab); -#define FS_MGR_MNTALL_DEV_NON_DEFAULT_FILE_ENCRYPTED 5 -#define FS_MGR_MNTALL_DEV_DEFAULT_FILE_ENCRYPTED 4 +#define FS_MGR_MNTALL_DEV_FILE_ENCRYPTED 4 #define FS_MGR_MNTALL_DEV_NEEDS_RECOVERY 3 #define FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION 2 #define FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED 1 @@ -102,6 +101,7 @@ 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); int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab); +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(struct fstab_rec *fstab); int fs_mgr_is_formattable(struct fstab_rec *fstab); diff --git a/gatekeeperd/tests/gatekeeper_test.cpp b/gatekeeperd/tests/gatekeeper_test.cpp index c504f9228..47a8bfa9d 100644 --- a/gatekeeperd/tests/gatekeeper_test.cpp +++ b/gatekeeperd/tests/gatekeeper_test.cpp @@ -18,9 +18,8 @@ #include <iostream> #include <gtest/gtest.h> -#include <UniquePtr.h> - #include <hardware/hw_auth_token.h> +#include <UniquePtr.h> #include "../SoftGateKeeper.h" diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp index 8f98f1734..6aa360bdb 100644 --- a/healthd/BatteryMonitor.cpp +++ b/healthd/BatteryMonitor.cpp @@ -614,7 +614,7 @@ void BatteryMonitor::init(struct healthd_config *hc) { KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n"); if (mHealthdConfig->batteryTechnologyPath.isEmpty()) KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n"); - if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) + if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) KLOG_WARNING(LOG_TAG, "BatteryCurrentNowPath not found\n"); if (mHealthdConfig->batteryFullChargePath.isEmpty()) KLOG_WARNING(LOG_TAG, "BatteryFullChargePath not found\n"); diff --git a/include/cutils/fs.h b/include/cutils/fs.h index 70f0b9291..be9e819dc 100644 --- a/include/cutils/fs.h +++ b/include/cutils/fs.h @@ -40,11 +40,18 @@ extern "C" { #endif /* - * Ensure that directory exists with given mode and owners. + * Ensure that directory exists with given mode and owners. If it exists + * with a different mode or owners, they are fixed to match the given values. */ extern int fs_prepare_dir(const char* path, mode_t mode, uid_t uid, gid_t gid); /* + * Ensure that directory exists with given mode and owners. If it exists + * with different owners, they are not fixed and -1 is returned. + */ +extern int fs_prepare_dir_strict(const char* path, mode_t mode, uid_t uid, gid_t gid); + +/* * Read single plaintext integer from given file, correctly handling files * partially written with fs_write_atomic_int(). */ diff --git a/include/cutils/sched_policy.h b/include/cutils/sched_policy.h index 6a8d570b2..591bd4478 100644 --- a/include/cutils/sched_policy.h +++ b/include/cutils/sched_policy.h @@ -29,6 +29,7 @@ typedef enum { SP_SYSTEM = 2, // can't be used with set_sched_policy() SP_AUDIO_APP = 3, SP_AUDIO_SYS = 4, + SP_TOP_APP = 5, SP_CNT, SP_MAX = SP_CNT - 1, SP_SYSTEM_DEFAULT = SP_FOREGROUND, diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h index 85d6c1931..c220a0c62 100644 --- a/include/private/android_filesystem_config.h +++ b/include/private/android_filesystem_config.h @@ -88,6 +88,7 @@ #define AID_WEBSERV 1044 /* webservd process */ #define AID_DEBUGGERD 1045 /* debuggerd unprivileged user */ #define AID_MEDIA_CODEC 1046 /* mediacodec process */ +#define AID_CAMERASERVER 1047 /* cameraserver process */ #define AID_SHELL 2000 /* adb and debug shell user */ #define AID_CACHE 2001 /* cache access */ @@ -194,6 +195,7 @@ static const struct android_id_info android_ids[] = { { "webserv", AID_WEBSERV }, { "debuggerd", AID_DEBUGGERD, }, { "mediacodec", AID_MEDIA_CODEC, }, + { "cameraserver", AID_CAMERASERVER, }, { "shell", AID_SHELL, }, { "cache", AID_CACHE, }, diff --git a/include/system/graphics.h b/include/system/graphics.h index cf2d7de01..ac5ae96d4 100644 --- a/include/system/graphics.h +++ b/include/system/graphics.h @@ -17,6 +17,7 @@ #ifndef SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H #define SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H +#include <stddef.h> #include <stdint.h> #ifdef __cplusplus diff --git a/include/system/radio.h b/include/system/radio.h index a08852604..9e291c83d 100644 --- a/include/system/radio.h +++ b/include/system/radio.h @@ -94,6 +94,7 @@ typedef struct radio_hal_fm_band_config { radio_rds_t rds; /* RDS variants supported */ bool ta; /* Traffic Announcement supported */ bool af; /* Alternate Frequency supported */ + bool ea; /* Emergency announcements supported */ } radio_hal_fm_band_config_t; /* Additional attributes for an AM band configuration */ @@ -184,6 +185,7 @@ enum { RADIO_EVENT_METADATA = 4, /* New meta data received */ RADIO_EVENT_TA = 5, /* Traffic announcement start or stop */ RADIO_EVENT_AF_SWITCH = 6, /* Switch to Alternate Frequency */ + RADIO_EVENT_EA = 7, /* Emergency announcement start or stop */ // begin framework only events RADIO_EVENT_CONTROL = 100, /* loss/gain of tuner control */ RADIO_EVENT_SERVER_DIED = 101, /* radio service died */ @@ -195,7 +197,8 @@ typedef struct radio_hal_event { radio_event_type_t type; /* event type */ int status; /* used by RADIO_EVENT_CONFIG, RADIO_EVENT_TUNED */ union { - bool on; /* RADIO_EVENT_ANTENNA, RADIO_EVENT_TA */ + /* RADIO_EVENT_ANTENNA, RADIO_EVENT_TA, RADIO_EVENT_EA */ + bool on; radio_hal_band_config_t config; /* RADIO_EVENT_CONFIG */ radio_program_info_t info; /* RADIO_EVENT_TUNED, RADIO_EVENT_AF_SWITCH */ radio_metadata_t *metadata; /* RADIO_EVENT_METADATA */ diff --git a/include/system/window.h b/include/system/window.h index 508ce00ba..14cce27bf 100644 --- a/include/system/window.h +++ b/include/system/window.h @@ -25,6 +25,7 @@ #include <sys/cdefs.h> #include <system/graphics.h> #include <unistd.h> +#include <stdbool.h> #ifndef __UNUSED #define __UNUSED __attribute__((__unused__)) @@ -311,6 +312,7 @@ enum { NATIVE_WINDOW_SET_SIDEBAND_STREAM = 18, NATIVE_WINDOW_SET_BUFFERS_DATASPACE = 19, NATIVE_WINDOW_SET_SURFACE_DAMAGE = 20, /* private */ + NATIVE_WINDOW_SET_SINGLE_BUFFER_MODE = 21, }; /* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */ @@ -351,7 +353,8 @@ enum { NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY = 0x08 }; -/* parameter for NATIVE_WINDOW_SET_SCALING_MODE */ +/* parameter for NATIVE_WINDOW_SET_SCALING_MODE + * keep in sync with Surface.java in frameworks/base */ enum { /* the window content is not updated (frozen) until a buffer of * the window size is received (enqueued) @@ -949,6 +952,18 @@ static inline int native_window_set_surface_damage( rects, numRects); } +/* + * native_window_set_single_buffer_mode(..., bool singleBufferMode) + * Enable/disable single buffer mode + */ +static inline int native_window_set_single_buffer_mode( + struct ANativeWindow* window, + bool singleBufferMode) +{ + return window->perform(window, NATIVE_WINDOW_SET_SINGLE_BUFFER_MODE, + singleBufferMode); +} + __END_DECLS #endif /* SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H */ diff --git a/include/usbhost/usbhost.h b/include/usbhost/usbhost.h index 4350ec103..88b5b4406 100644 --- a/include/usbhost/usbhost.h +++ b/include/usbhost/usbhost.h @@ -219,6 +219,9 @@ int usb_device_bulk_transfer(struct usb_device *device, int length, unsigned int timeout); +/** Reset USB bus for the device */ +int usb_device_reset(struct usb_device *device); + /* Creates a new usb_request. */ struct usb_request *usb_request_new(struct usb_device *dev, const struct usb_endpoint_descriptor *ep_desc); diff --git a/init/builtins.cpp b/init/builtins.cpp index 35f1a9e04..210ce4ad3 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -510,7 +510,7 @@ static int do_mount_all(const std::vector<std::string>& args) { ERROR("fs_mgr_mount_all suggested recovery, so wiping data via recovery.\n"); ret = wipe_data_via_recovery(); /* If reboot worked, there is no return. */ - } else if (ret == FS_MGR_MNTALL_DEV_DEFAULT_FILE_ENCRYPTED) { + } else if (ret == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) { if (e4crypt_install_keyring()) { return -1; } @@ -520,13 +520,6 @@ static int do_mount_all(const std::vector<std::string>& args) { // Although encrypted, we have device key, so we do not need to // do anything different from the nonencrypted case. ActionManager::GetInstance().QueueEventTrigger("nonencrypted"); - } else if (ret == FS_MGR_MNTALL_DEV_NON_DEFAULT_FILE_ENCRYPTED) { - if (e4crypt_install_keyring()) { - return -1; - } - property_set("ro.crypto.state", "encrypted"); - property_set("ro.crypto.type", "file"); - property_set("vold.decrypt", "trigger_restart_min_framework"); } else if (ret > 0) { ERROR("fs_mgr_mount_all returned unexpected error %d\n", ret); } @@ -884,11 +877,11 @@ static int do_installkey(const std::vector<std::string>& args) { do_installkeys_ensure_dir_exists); } -static int do_setusercryptopolicies(const std::vector<std::string>& args) { +static int do_init_user0(const std::vector<std::string>& args) { if (!is_file_crypto()) { return 0; } - return e4crypt_set_user_crypto_policies(args[1].c_str()); + return e4crypt_do_init_user0(); } BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { @@ -907,6 +900,7 @@ BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { {"export", {2, 2, do_export}}, {"hostname", {1, 1, do_hostname}}, {"ifup", {1, 1, do_ifup}}, + {"init_user0", {0, 0, do_init_user0}}, {"insmod", {1, kMax, do_insmod}}, {"installkey", {1, 1, do_installkey}}, {"load_persist_props", {0, 0, do_load_persist_props}}, @@ -923,7 +917,6 @@ BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { {"rmdir", {1, 1, do_rmdir}}, {"setprop", {2, 2, do_setprop}}, {"setrlimit", {3, 3, do_setrlimit}}, - {"setusercryptopolicies", {1, 1, do_setusercryptopolicies}}, {"start", {1, 1, do_start}}, {"stop", {1, 1, do_stop}}, {"swapon_all", {1, 1, do_swapon_all}}, diff --git a/libcutils/fs.c b/libcutils/fs.c index 45c7add4c..5e2ef0b8d 100644 --- a/libcutils/fs.c +++ b/libcutils/fs.c @@ -37,7 +37,8 @@ #define ALL_PERMS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) #define BUF_SIZE 64 -int fs_prepare_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) { +static int fs_prepare_dir_impl(const char* path, mode_t mode, uid_t uid, gid_t gid, + int allow_fixup) { // Check if path needs to be created struct stat sb; if (TEMP_FAILURE_RETRY(lstat(path, &sb)) == -1) { @@ -54,10 +55,22 @@ int fs_prepare_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) { ALOGE("Not a directory: %s", path); return -1; } - if (((sb.st_mode & ALL_PERMS) == mode) && (sb.st_uid == uid) && (sb.st_gid == gid)) { + int owner_match = ((sb.st_uid == uid) && (sb.st_gid == gid)); + int mode_match = ((sb.st_mode & ALL_PERMS) == mode); + if (owner_match && mode_match) { return 0; - } else { + } else if (allow_fixup) { goto fixup; + } else { + if (!owner_match) { + ALOGE("Expected path %s with owner %d:%d but found %d:%d", + path, uid, gid, sb.st_uid, sb.st_gid); + return -1; + } else { + ALOGW("Expected path %s with mode %o but found %o", + path, mode, (sb.st_mode & ALL_PERMS)); + return 0; + } } create: @@ -81,6 +94,14 @@ fixup: return 0; } +int fs_prepare_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) { + return fs_prepare_dir_impl(path, mode, uid, gid, 1); +} + +int fs_prepare_dir_strict(const char* path, mode_t mode, uid_t uid, gid_t gid) { + return fs_prepare_dir_impl(path, mode, uid, gid, 0); +} + int fs_read_atomic_int(const char* path, int* out_value) { int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY)); if (fd == -1) { diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c index 6d50adca1..645edd105 100644 --- a/libcutils/fs_config.c +++ b/libcutils/fs_config.c @@ -79,6 +79,7 @@ static const struct fs_path_config android_dirs[] = { { 00500, AID_ROOT, AID_ROOT, 0, "config" }, { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" }, { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private" }, + { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-ephemeral" }, { 00771, AID_ROOT, AID_ROOT, 0, "data/dalvik-cache" }, { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" }, { 00771, AID_SHELL, AID_SHELL, 0, "data/local/tmp" }, @@ -126,6 +127,7 @@ static const struct fs_path_config android_files[] = { { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app/*" }, { 00644, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/*" }, { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private/*" }, + { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-ephemeral/*" }, { 00644, AID_APP, AID_APP, 0, "data/data/*" }, { 00640, AID_ROOT, AID_SHELL, 0, "data/nativetest/tests.txt" }, { 00640, AID_ROOT, AID_SHELL, 0, "data/nativetest64/tests.txt" }, diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c index 6bba3a7b1..54d112290 100644 --- a/libcutils/sched_policy.c +++ b/libcutils/sched_policy.c @@ -62,8 +62,10 @@ static int fg_cgroup_fd = -1; #ifdef USE_CPUSETS // File descriptors open to /dev/cpuset/../tasks, setup by initialize, or -1 on error +static int system_bg_cpuset_fd = -1; static int bg_cpuset_fd = -1; static int fg_cpuset_fd = -1; +static int ta_cpuset_fd = -1; // special cpuset for top app static int bg_schedboost_fd = -1; static int fg_schedboost_fd = -1; #endif @@ -130,6 +132,11 @@ static void __initialize(void) { fg_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC); filename = "/dev/cpuset/background/tasks"; bg_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC); + filename = "/dev/cpuset/system-background/tasks"; + system_bg_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC); + filename = "/dev/cpuset/top-app/tasks"; + ta_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC); + #ifdef USE_SCHEDBOOST filename = "/sys/fs/cgroup/stune/foreground/tasks"; fg_schedboost_fd = open(filename, O_WRONLY | O_CLOEXEC); @@ -138,7 +145,6 @@ static void __initialize(void) { #endif } #endif - } /* @@ -273,6 +279,14 @@ int set_cpuset_policy(int tid, SchedPolicy policy) fd = fg_cpuset_fd; boost_fd = fg_schedboost_fd; break; + case SP_TOP_APP : + fd = ta_cpuset_fd; + boost_fd = fg_schedboost_fd; + break; + case SP_SYSTEM: + fd = system_bg_cpuset_fd; + boost_fd = bg_schedboost_fd; + break; default: boost_fd = fd = -1; break; @@ -330,6 +344,7 @@ int set_sched_policy(int tid, SchedPolicy policy) case SP_FOREGROUND: case SP_AUDIO_APP: case SP_AUDIO_SYS: + case SP_TOP_APP: SLOGD("^^^ tid %d (%s)", tid, thread_name); break; case SP_SYSTEM: @@ -350,6 +365,7 @@ int set_sched_policy(int tid, SchedPolicy policy) case SP_FOREGROUND: case SP_AUDIO_APP: case SP_AUDIO_SYS: + case SP_TOP_APP: fd = fg_cgroup_fd; break; default: @@ -404,6 +420,7 @@ const char *get_sched_policy_name(SchedPolicy policy) [SP_SYSTEM] = " ", [SP_AUDIO_APP] = "aa", [SP_AUDIO_SYS] = "as", + [SP_TOP_APP] = "ta", }; if ((policy < SP_CNT) && (strings[policy] != NULL)) return strings[policy]; diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp index 209ff1cc3..75d2a2db7 100644 --- a/libnativeloader/native_loader.cpp +++ b/libnativeloader/native_loader.cpp @@ -36,7 +36,12 @@ namespace android { #ifdef __ANDROID__ // TODO(dimitry): move this to system properties. static const char* kPublicNativeLibraries = "libandroid.so:" + // TODO (dimitry): This is a workaround for http://b/26436837 + // will be removed before the release. + "libart.so:" + // END OF WORKAROUND "libc.so:" + "libcamera2ndk.so:" "libdl.so:" "libEGL.so:" "libGLESv1_CM.so:" diff --git a/libnetutils/dhcptool.c b/libnetutils/dhcptool.c index 352ac5e57..a2d3869b4 100644 --- a/libnetutils/dhcptool.c +++ b/libnetutils/dhcptool.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include <err.h> #include <errno.h> #include <error.h> #include <stdbool.h> @@ -29,12 +30,14 @@ int main(int argc, char* argv[]) { char* interface = argv[1]; if (ifc_init()) { - error(EXIT_FAILURE, errno, "dhcptool %s: ifc_init failed", interface); + err(errno, "dhcptool %s: ifc_init failed", interface); + ifc_close(); + return EXIT_FAILURE; } int rc = do_dhcp(interface); if (rc) { - error(0, errno, "dhcptool %s: do_dhcp failed", interface); + err(errno, "dhcptool %s: do_dhcp failed", interface); } ifc_close(); diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c index e0a9f7f88..85ff070a7 100644 --- a/libnetutils/ifc_utils.c +++ b/libnetutils/ifc_utils.c @@ -19,6 +19,7 @@ #include <unistd.h> #include <string.h> #include <errno.h> +#include <pthread.h> #include <sys/socket.h> #include <sys/select.h> @@ -57,6 +58,8 @@ static int ifc_ctl_sock = -1; static int ifc_ctl_sock6 = -1; +static pthread_mutex_t ifc_sock_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +static pthread_mutex_t ifc_sock6_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; void printerr(char *fmt, ...); #define DBG 0 @@ -122,6 +125,8 @@ int string_to_ip(const char *string, struct sockaddr_storage *ss) { int ifc_init(void) { int ret; + + pthread_mutex_lock(&ifc_sock_mutex); if (ifc_ctl_sock == -1) { ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (ifc_ctl_sock < 0) { @@ -136,6 +141,7 @@ int ifc_init(void) int ifc_init6(void) { + pthread_mutex_lock(&ifc_sock6_mutex); if (ifc_ctl_sock6 == -1) { ifc_ctl_sock6 = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (ifc_ctl_sock6 < 0) { @@ -152,6 +158,7 @@ void ifc_close(void) (void)close(ifc_ctl_sock); ifc_ctl_sock = -1; } + pthread_mutex_unlock(&ifc_sock_mutex); } void ifc_close6(void) @@ -160,6 +167,7 @@ void ifc_close6(void) (void)close(ifc_ctl_sock6); ifc_ctl_sock6 = -1; } + pthread_mutex_unlock(&ifc_sock6_mutex); } static void ifc_init_ifr(const char *name, struct ifreq *ifr) @@ -541,6 +549,7 @@ int ifc_act_on_ipv4_route(int action, const char *ifname, struct in_addr dst, in ifc_init(); if (ifc_ctl_sock < 0) { + ifc_close(); return -errno; } diff --git a/libprocessgroup/Android.mk b/libprocessgroup/Android.mk index ee6ba5868..1885fa5dd 100644 --- a/libprocessgroup/Android.mk +++ b/libprocessgroup/Android.mk @@ -7,14 +7,4 @@ LOCAL_SHARED_LIBRARIES := liblog libutils LOCAL_C_INCLUDES := $(LOCAL_PATH)/include LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include LOCAL_CFLAGS := -Wall -Werror -LOCAL_REQUIRED_MODULE := processgroup_cleanup include $(BUILD_SHARED_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_SRC_FILES := cleanup.cpp -LOCAL_MODULE := processgroup_cleanup -LOCAL_C_INCLUDES := $(LOCAL_PATH)/include -LOCAL_CFLAGS := -Wall -Werror -LOCAL_FORCE_STATIC_EXECUTABLE := true -LOCAL_STATIC_LIBRARIES := libc libcutils -include $(BUILD_EXECUTABLE) diff --git a/libprocessgroup/cleanup.cpp b/libprocessgroup/cleanup.cpp deleted file mode 100644 index cca8dc428..000000000 --- a/libprocessgroup/cleanup.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2014 Google, Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <string.h> -#include <unistd.h> -#include <sys/syslimits.h> - -#include "processgroup_priv.h" - -int main(int argc, char **argv) -{ - char buf[PATH_MAX]; - if (argc != 2) - return -1; - - memcpy(buf, PROCESSGROUP_CGROUP_PATH, sizeof(PROCESSGROUP_CGROUP_PATH)); - strlcat(buf, argv[1], sizeof(buf)); - return rmdir(buf); -} diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp index ad0500dab..f160ac17d 100644 --- a/libprocessgroup/processgroup.cpp +++ b/libprocessgroup/processgroup.cpp @@ -22,6 +22,7 @@ #include <errno.h> #include <fcntl.h> #include <inttypes.h> +#include <mutex> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> @@ -35,7 +36,26 @@ #include <utils/SystemClock.h> #include <processgroup/processgroup.h> -#include "processgroup_priv.h" + +#define MEM_CGROUP_PATH "/dev/memcg/apps" +#define ACCT_CGROUP_PATH "/acct" + +#define PROCESSGROUP_UID_PREFIX "uid_" +#define PROCESSGROUP_PID_PREFIX "pid_" +#define PROCESSGROUP_CGROUP_PROCS_FILE "/cgroup.procs" +#define PROCESSGROUP_MAX_UID_LEN 11 +#define PROCESSGROUP_MAX_PID_LEN 11 +#define PROCESSGROUP_MAX_PATH_LEN \ + ((sizeof(MEM_CGROUP_PATH) > sizeof(ACCT_CGROUP_PATH) ? \ + sizeof(MEM_CGROUP_PATH) : sizeof(ACCT_CGROUP_PATH)) + \ + sizeof(PROCESSGROUP_UID_PREFIX) + 1 + \ + PROCESSGROUP_MAX_UID_LEN + \ + sizeof(PROCESSGROUP_PID_PREFIX) + 1 + \ + PROCESSGROUP_MAX_PID_LEN + \ + sizeof(PROCESSGROUP_CGROUP_PROCS_FILE) + \ + 1) + +std::once_flag init_path_flag; struct ctx { bool initialized; @@ -45,10 +65,18 @@ struct ctx { size_t buf_len; }; +static const char* getCgroupRootPath() { + static const char* cgroup_root_path = NULL; + std::call_once(init_path_flag, [&]() { + cgroup_root_path = access(MEM_CGROUP_PATH, W_OK) ? ACCT_CGROUP_PATH : MEM_CGROUP_PATH; + }); + return cgroup_root_path; +} + static int convertUidToPath(char *path, size_t size, uid_t uid) { return snprintf(path, size, "%s/%s%d", - PROCESSGROUP_CGROUP_PATH, + getCgroupRootPath(), PROCESSGROUP_UID_PREFIX, uid); } @@ -56,7 +84,7 @@ static int convertUidToPath(char *path, size_t size, uid_t uid) static int convertUidPidToPath(char *path, size_t size, uid_t uid, int pid) { return snprintf(path, size, "%s/%s%d/%s%d", - PROCESSGROUP_CGROUP_PATH, + getCgroupRootPath(), PROCESSGROUP_UID_PREFIX, uid, PROCESSGROUP_PID_PREFIX, @@ -188,9 +216,10 @@ static void removeUidProcessGroups(const char *uid_path) void removeAllProcessGroups() { SLOGV("removeAllProcessGroups()"); - DIR *root = opendir(PROCESSGROUP_CGROUP_PATH); + const char *cgroup_root_path = getCgroupRootPath(); + DIR *root = opendir(cgroup_root_path); if (root == NULL) { - SLOGE("failed to open %s: %s", PROCESSGROUP_CGROUP_PATH, strerror(errno)); + SLOGE("failed to open %s: %s", cgroup_root_path, strerror(errno)); } else { struct dirent cur; struct dirent *dir; @@ -204,7 +233,7 @@ void removeAllProcessGroups() continue; } - snprintf(path, sizeof(path), "%s/%s", PROCESSGROUP_CGROUP_PATH, dir->d_name); + snprintf(path, sizeof(path), "%s/%s", cgroup_root_path, dir->d_name); removeUidProcessGroups(path); SLOGV("removing %s\n", path); rmdir(path); diff --git a/libprocessgroup/processgroup_priv.h b/libprocessgroup/processgroup_priv.h deleted file mode 100644 index 1895bf9d5..000000000 --- a/libprocessgroup/processgroup_priv.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2014 Google, Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _PROCESSGROUP_PRIV_H_ -#define _PROCESSGROUP_PRIV_H_ - -#define PROCESSGROUP_CGROUP_PATH "/acct" -#define PROCESSGROUP_UID_PREFIX "uid_" -#define PROCESSGROUP_PID_PREFIX "pid_" -#define PROCESSGROUP_CGROUP_PROCS_FILE "/cgroup.procs" -#define PROCESSGROUP_MAX_UID_LEN 11 -#define PROCESSGROUP_MAX_PID_LEN 11 -#define PROCESSGROUP_MAX_PATH_LEN \ - (sizeof(PROCESSGROUP_CGROUP_PATH) + \ - sizeof(PROCESSGROUP_UID_PREFIX) + 1 + \ - PROCESSGROUP_MAX_UID_LEN + \ - sizeof(PROCESSGROUP_PID_PREFIX) + 1 + \ - PROCESSGROUP_MAX_PID_LEN + \ - sizeof(PROCESSGROUP_CGROUP_PROCS_FILE) + \ - 1) - -#endif diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c index b8e32154f..299fdc475 100644 --- a/libusbhost/usbhost.c +++ b/libusbhost/usbhost.c @@ -617,6 +617,11 @@ int usb_device_bulk_transfer(struct usb_device *device, return ioctl(device->fd, USBDEVFS_BULK, &ctrl); } +int usb_device_reset(struct usb_device *device) +{ + return ioctl(device->fd, USBDEVFS_RESET); +} + struct usb_request *usb_request_new(struct usb_device *dev, const struct usb_endpoint_descriptor *ep_desc) { diff --git a/libutils/Android.mk b/libutils/Android.mk index 631b5a3b4..8c4fd15b6 100644 --- a/libutils/Android.mk +++ b/libutils/Android.mk @@ -106,19 +106,16 @@ LOCAL_CLANG := true LOCAL_SANITIZE := integer include $(BUILD_SHARED_LIBRARY) -# Include subdirectory makefiles -# ============================================================ - include $(CLEAR_VARS) LOCAL_MODULE := SharedBufferTest -LOCAL_STATIC_LIBRARIES := libutils libcutils +LOCAL_STATIC_LIBRARIES := libutils LOCAL_SHARED_LIBRARIES := liblog LOCAL_SRC_FILES := SharedBufferTest.cpp include $(BUILD_NATIVE_TEST) include $(CLEAR_VARS) LOCAL_MODULE := SharedBufferTest -LOCAL_STATIC_LIBRARIES := libutils libcutils +LOCAL_STATIC_LIBRARIES := libutils LOCAL_SHARED_LIBRARIES := liblog LOCAL_SRC_FILES := SharedBufferTest.cpp include $(BUILD_HOST_NATIVE_TEST) diff --git a/libutils/SharedBuffer.cpp b/libutils/SharedBuffer.cpp index c7dd1ab34..34d75eebc 100644 --- a/libutils/SharedBuffer.cpp +++ b/libutils/SharedBuffer.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define __STDC_LIMIT_MACROS -#include <stdint.h> #include <stdlib.h> #include <string.h> diff --git a/libutils/SharedBufferTest.cpp b/libutils/SharedBufferTest.cpp index a0484ffb5..33a4e0c90 100644 --- a/libutils/SharedBufferTest.cpp +++ b/libutils/SharedBufferTest.cpp @@ -31,10 +31,10 @@ TEST(SharedBufferTest, TestAlloc) { // Check that null is returned, as we are asking for the whole address space. android::SharedBuffer* buf = android::SharedBuffer::alloc(SIZE_MAX - sizeof(android::SharedBuffer) - 1); - ASSERT_TRUE(NULL == buf); + ASSERT_EQ(nullptr, buf); buf = android::SharedBuffer::alloc(0); - ASSERT_FALSE(NULL == buf); + ASSERT_NE(nullptr, buf); ASSERT_EQ(0U, buf->size()); buf->release(); } @@ -49,7 +49,7 @@ TEST(SharedBufferTest, TestEditResize) { // Make sure we don't die here. // Check that null is returned, as we are asking for the whole address space. buf = buf->editResize(SIZE_MAX - sizeof(android::SharedBuffer) - 1); - ASSERT_TRUE(NULL == buf); + ASSERT_EQ(nullptr, buf); buf = android::SharedBuffer::alloc(10); buf = buf->editResize(0); diff --git a/libutils/tests/String8_test.cpp b/libutils/tests/String8_test.cpp index c42c68dce..01e64f60a 100644 --- a/libutils/tests/String8_test.cpp +++ b/libutils/tests/String8_test.cpp @@ -72,4 +72,9 @@ TEST_F(String8Test, OperatorPlusEquals) { EXPECT_STREQ(src3, " Verify me."); } +TEST_F(String8Test, SetToSizeMaxReturnsNoMemory) { + const char *in = "some string"; + EXPECT_EQ(NO_MEMORY, String8("").setTo(in, SIZE_MAX)); +} + } diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c index aa3db8a05..511bf6852 100644 --- a/lmkd/lmkd.c +++ b/lmkd/lmkd.c @@ -77,12 +77,7 @@ static int ctrl_dfd_reopened; /* did we reopen ctrl conn on this loop? */ static int epollfd; static int maxevents; -#define OOM_DISABLE (-17) -/* inclusive */ -#define OOM_ADJUST_MIN (-16) -#define OOM_ADJUST_MAX 15 - -/* kernel OOM score values */ +/* OOM score values used by both kernel and framework */ #define OOM_SCORE_ADJ_MIN (-1000) #define OOM_SCORE_ADJ_MAX 1000 @@ -114,8 +109,8 @@ struct proc { static struct proc *pidhash[PIDHASH_SZ]; #define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1)) -#define ADJTOSLOT(adj) (adj + -OOM_ADJUST_MIN) -static struct adjslot_list procadjslot_list[ADJTOSLOT(OOM_ADJUST_MAX) + 1]; +#define ADJTOSLOT(adj) (adj + -OOM_SCORE_ADJ_MIN) +static struct adjslot_list procadjslot_list[ADJTOSLOT(OOM_SCORE_ADJ_MAX) + 1]; /* * Wait 1-2 seconds for the death report of a killed process prior to @@ -148,14 +143,6 @@ static ssize_t read_all(int fd, char *buf, size_t max_len) return ret; } -static int lowmem_oom_adj_to_oom_score_adj(int oom_adj) -{ - if (oom_adj == OOM_ADJUST_MAX) - return OOM_SCORE_ADJ_MAX; - else - return (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE; -} - static struct proc *pid_lookup(int pid) { struct proc *procp; @@ -254,13 +241,13 @@ static void cmd_procprio(int pid, int uid, int oomadj) { char path[80]; char val[20]; - if (oomadj < OOM_DISABLE || oomadj > OOM_ADJUST_MAX) { + if (oomadj < OOM_SCORE_ADJ_MIN || oomadj > OOM_SCORE_ADJ_MAX) { ALOGE("Invalid PROCPRIO oomadj argument %d", oomadj); return; } snprintf(path, sizeof(path), "/proc/%d/oom_score_adj", pid); - snprintf(val, sizeof(val), "%d", lowmem_oom_adj_to_oom_score_adj(oomadj)); + snprintf(val, sizeof(val), "%d", oomadj); writefilestring(path, val); if (use_inkernel_interface) @@ -608,7 +595,7 @@ static int kill_one_process(struct proc *procp, int other_free, int other_file, static int find_and_kill_process(int other_free, int other_file, bool first) { int i; - int min_score_adj = OOM_ADJUST_MAX + 1; + int min_score_adj = OOM_SCORE_ADJ_MAX + 1; int minfree = 0; int killed_size = 0; @@ -620,10 +607,10 @@ static int find_and_kill_process(int other_free, int other_file, bool first) } } - if (min_score_adj == OOM_ADJUST_MAX + 1) + if (min_score_adj == OOM_SCORE_ADJ_MAX + 1) return 0; - for (i = OOM_ADJUST_MAX; i >= min_score_adj; i--) { + for (i = OOM_SCORE_ADJ_MAX; i >= min_score_adj; i--) { struct proc *procp; retry: @@ -784,7 +771,7 @@ static int init(void) { ALOGE("Kernel does not support memory pressure events or in-kernel low memory killer"); } - for (i = 0; i <= ADJTOSLOT(OOM_ADJUST_MAX); i++) { + for (i = 0; i <= ADJTOSLOT(OOM_SCORE_ADJ_MAX); i++) { procadjslot_list[i].next = &procadjslot_list[i]; procadjslot_list[i].prev = &procadjslot_list[i]; } diff --git a/rootdir/init.rc b/rootdir/init.rc index 8ce476071..b354cbb30 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -43,19 +43,6 @@ on init mount cgroup none /acct cpuacct mkdir /acct/uid - # Create cgroup mount point for memory - mount tmpfs none /sys/fs/cgroup mode=0750,uid=0,gid=1000 - mkdir /sys/fs/cgroup/memory 0750 root system - mount cgroup none /sys/fs/cgroup/memory memory - write /sys/fs/cgroup/memory/memory.move_charge_at_immigrate 1 - chown root system /sys/fs/cgroup/memory/tasks - chmod 0660 /sys/fs/cgroup/memory/tasks - mkdir /sys/fs/cgroup/memory/sw 0750 root system - write /sys/fs/cgroup/memory/sw/memory.swappiness 100 - write /sys/fs/cgroup/memory/sw/memory.move_charge_at_immigrate 1 - chown root system /sys/fs/cgroup/memory/sw/tasks - chmod 0660 /sys/fs/cgroup/memory/sw/tasks - # Create energy-aware scheduler tuning nodes mkdir /sys/fs/cgroup/stune mount cgroup none /sys/fs/cgroup/stune schedtune @@ -80,6 +67,7 @@ on init mkdir /mnt/user 0755 root root mkdir /mnt/user/0 0755 root root mkdir /mnt/expand 0771 system system + mkdir /mnt/appfuse 0711 root root # Storage views to support runtime permissions mkdir /mnt/runtime 0700 root root @@ -94,9 +82,11 @@ on init symlink /storage/self/primary /sdcard symlink /mnt/user/0/primary /mnt/runtime/default/self/primary - # memory control cgroup + # root memory control cgroup, used by lmkd mkdir /dev/memcg 0700 root system mount cgroup none /dev/memcg memory + # app mem cgroups, used by activity manager and lmkd + mkdir /dev/memcg/apps/ 0755 system system write /proc/sys/kernel/panic_on_oops 1 write /proc/sys/kernel/hung_task_timeout_secs 0 @@ -172,21 +162,32 @@ on init write /dev/cpuset/system-background/cpus 0 write /dev/cpuset/system-background/mems 0 + mkdir /dev/cpuset/top-app + write /dev/cpuset/top-app/cpus 0 + write /dev/cpuset/top-app/mems 0 + # change permissions for all cpusets we'll touch at runtime chown system system /dev/cpuset chown system system /dev/cpuset/foreground chown system system /dev/cpuset/foreground/boost chown system system /dev/cpuset/background chown system system /dev/cpuset/system-background + chown system system /dev/cpuset/top-app chown system system /dev/cpuset/tasks chown system system /dev/cpuset/foreground/tasks chown system system /dev/cpuset/foreground/boost/tasks chown system system /dev/cpuset/background/tasks chown system system /dev/cpuset/system-background/tasks + chown system system /dev/cpuset/top-app/tasks + + # set system-background to 0775 so SurfaceFlinger can touch it + chmod 0775 /dev/cpuset/system-background + chmod 0664 /dev/cpuset/foreground/tasks chmod 0664 /dev/cpuset/foreground/boost/tasks chmod 0664 /dev/cpuset/background/tasks chmod 0664 /dev/cpuset/system-background/tasks + chmod 0664 /dev/cpuset/top-app/tasks chmod 0664 /dev/cpuset/tasks @@ -282,6 +283,10 @@ on post-fs # permissions if created by the recovery system. mkdir /cache/recovery 0770 system cache + # Backup/restore mechanism uses the cache partition + mkdir /cache/backup_stage 0700 system system + mkdir /cache/backup 0700 system system + #change permissions on vmallocinfo so we can grab it from bugreports chown root log /proc/vmallocinfo chmod 0440 /proc/vmallocinfo @@ -318,8 +323,6 @@ on post-fs-data start vold installkey /data - # Emulated internal storage area - mkdir /data/media 0770 media_rw media_rw # Start bootcharting as soon as possible after the data partition is # mounted to collect more data. mkdir /data/bootchart 0755 shell shell @@ -366,6 +369,7 @@ on post-fs-data mkdir /data/local/tmp 0771 shell shell mkdir /data/data 0771 system system mkdir /data/app-private 0771 system system + mkdir /data/app-ephemeral 0771 system system mkdir /data/app-asec 0700 root root mkdir /data/app-lib 0771 system system mkdir /data/app 0771 system system @@ -374,6 +378,8 @@ on post-fs-data # create dalvik-cache, so as to enforce our permissions mkdir /data/dalvik-cache 0771 root root + # create the A/B OTA directory, so as to enforce our permissions + mkdir /data/ota 0771 root root # create resource-cache and double-check the perms mkdir /data/resource-cache 0771 system system @@ -402,13 +408,24 @@ on post-fs-data # Create all remaining /data root dirs so that they are made through init # and get proper encryption policy installed mkdir /data/backup 0700 system system - 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/system_ce 0770 system system + mkdir /data/system_ce/0 0770 system system + mkdir /data/user 0711 system system + mkdir /data/user_de 0711 system system + mkdir /data/user_de/0 0771 system system + + mkdir /data/media 0770 media_rw media_rw + mkdir /data/media/0 0770 media_rw media_rw + mkdir /data/media/obb 0770 media_rw media_rw + + symlink /data/data /data/user/0 - setusercryptopolicies /data/user + init_user0 # Reload policy from /data/security if present. setprop selinux.reload_policy 1 diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc index 0ca38b9cd..1b1d747ef 100644 --- a/rootdir/init.zygote32.rc +++ b/rootdir/init.zygote32.rc @@ -3,6 +3,8 @@ service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-sys socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on + onrestart restart audioserver + onrestart restart cameraserver onrestart restart media onrestart restart netd writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc index 1646c0f7e..04b88549c 100644 --- a/rootdir/init.zygote32_64.rc +++ b/rootdir/init.zygote32_64.rc @@ -3,6 +3,8 @@ service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-s socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on + onrestart restart audioserver + onrestart restart cameraserver onrestart restart media onrestart restart netd writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc index b477c8ef2..21ff647f3 100644 --- a/rootdir/init.zygote64.rc +++ b/rootdir/init.zygote64.rc @@ -3,6 +3,8 @@ service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-s socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on + onrestart restart audioserver + onrestart restart cameraserver onrestart restart media onrestart restart netd writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc index 633a98108..257ae19b6 100644 --- a/rootdir/init.zygote64_32.rc +++ b/rootdir/init.zygote64_32.rc @@ -3,6 +3,8 @@ service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-s socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on + onrestart restart audioserver + onrestart restart cameraserver onrestart restart media onrestart restart netd writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c index f86256195..45efe369e 100644 --- a/sdcard/sdcard.c +++ b/sdcard/sdcard.c @@ -1214,13 +1214,7 @@ static int handle_open(struct fuse* fuse, struct fuse_handler* handler, } out.fh = ptr_to_id(h); out.open_flags = 0; - -#ifdef FUSE_STACKED_IO - out.lower_fd = h->fd; -#else out.padding = 0; -#endif - fuse_reply(fuse, hdr->unique, &out, sizeof(out)); return NO_STATUS; } @@ -1384,13 +1378,7 @@ static int handle_opendir(struct fuse* fuse, struct fuse_handler* handler, } out.fh = ptr_to_id(h); out.open_flags = 0; - -#ifdef FUSE_STACKED_IO - out.lower_fd = -1; -#else out.padding = 0; -#endif - fuse_reply(fuse, hdr->unique, &out, sizeof(out)); return NO_STATUS; } @@ -1472,11 +1460,6 @@ static int handle_init(struct fuse* fuse, struct fuse_handler* handler, out.major = FUSE_KERNEL_VERSION; out.max_readahead = req->max_readahead; out.flags = FUSE_ATOMIC_O_TRUNC | FUSE_BIG_WRITES; - -#ifdef FUSE_STACKED_IO - out.flags |= FUSE_STACKED_IO; -#endif - out.max_background = 32; out.congestion_threshold = 32; out.max_write = MAX_WRITE; diff --git a/trusty/gatekeeper/Android.mk b/trusty/gatekeeper/Android.mk new file mode 100644 index 000000000..13e9a09a1 --- /dev/null +++ b/trusty/gatekeeper/Android.mk @@ -0,0 +1,50 @@ +# +# Copyright (C) 2015 The Android Open-Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# WARNING: Everything listed here will be built on ALL platforms, +# including x86, the emulator, and the SDK. Modules must be uniquely +# named (liblights.panda), and must build everywhere, or limit themselves +# to only building on ARM if they include assembly. Individual makefiles +# are responsible for having their own logic, for fine-grained control. + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := gatekeeper.trusty + +LOCAL_MODULE_RELATIVE_PATH := hw + +LOCAL_SRC_FILES := \ + module.cpp \ + trusty_gatekeeper_ipc.c \ + trusty_gatekeeper.cpp + +LOCAL_CLFAGS = -fvisibility=hidden -Wall -Werror + +LOCAL_SHARED_LIBRARIES := \ + libgatekeeper \ + liblog \ + libcutils \ + libtrusty + +LOCAL_MODULE_TAGS := optional + +# Symlink gatekeeper.trusty.so -> gatekeeper.<device>.so so libhardware can find it. +LOCAL_POST_INSTALL_CMD = \ + $(hide) ln -sf $(notdir $(LOCAL_INSTALLED_MODULE)) $(dir $(LOCAL_INSTALLED_MODULE))gatekeeper.$(TARGET_DEVICE).so + +include $(BUILD_SHARED_LIBRARY) diff --git a/trusty/gatekeeper/gatekeeper_ipc.h b/trusty/gatekeeper/gatekeeper_ipc.h new file mode 100644 index 000000000..b05dcd848 --- /dev/null +++ b/trusty/gatekeeper/gatekeeper_ipc.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#define GATEKEEPER_PORT "com.android.trusty.gatekeeper" +#define GATEKEEPER_MAX_BUFFER_LENGTH 1024 + +enum gatekeeper_command { + GK_REQ_SHIFT = 1, + GK_RESP_BIT = 1, + + GK_ENROLL = (0 << GK_REQ_SHIFT), + GK_VERIFY = (1 << GK_REQ_SHIFT), +}; + +/** + * gatekeeper_message - Serial header for communicating with GK server + * @cmd: the command, one of ENROLL, VERIFY. Payload must be a serialized + * buffer of the corresponding request object. + * @payload: start of the serialized command specific payload + */ +struct gatekeeper_message { + uint32_t cmd; + uint8_t payload[0]; +}; + diff --git a/trusty/gatekeeper/module.cpp b/trusty/gatekeeper/module.cpp new file mode 100644 index 000000000..0ee3c2f28 --- /dev/null +++ b/trusty/gatekeeper/module.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <hardware/hardware.h> + +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +#include "trusty_gatekeeper.h" + +using gatekeeper::TrustyGateKeeperDevice; + +static int trusty_gatekeeper_open(const hw_module_t *module, const char *name, + hw_device_t **device) { + + if (strcmp(name, HARDWARE_GATEKEEPER) != 0) { + return -EINVAL; + } + + TrustyGateKeeperDevice *gatekeeper = new TrustyGateKeeperDevice(module); + if (gatekeeper == NULL) return -ENOMEM; + *device = gatekeeper->hw_device(); + + return 0; +} + +static struct hw_module_methods_t gatekeeper_module_methods = { + .open = trusty_gatekeeper_open, +}; + +struct gatekeeper_module HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = GATEKEEPER_MODULE_API_VERSION_0_1, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = GATEKEEPER_HARDWARE_MODULE_ID, + .name = "Trusty GateKeeper HAL", + .author = "The Android Open Source Project", + .methods = &gatekeeper_module_methods, + .dso = 0, + .reserved = {} + }, +}; diff --git a/trusty/gatekeeper/trusty_gatekeeper.cpp b/trusty/gatekeeper/trusty_gatekeeper.cpp new file mode 100644 index 000000000..d24f44f2e --- /dev/null +++ b/trusty/gatekeeper/trusty_gatekeeper.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <errno.h> +#include <stdio.h> +#include <assert.h> +#include <type_traits> + +#include "trusty_gatekeeper.h" +#include "trusty_gatekeeper_ipc.h" +#include "gatekeeper_ipc.h" + +#define LOG_TAG "TrustyGateKeeper" +#include <cutils/log.h> + +namespace gatekeeper { + +const uint32_t SEND_BUF_SIZE = 8192; +const uint32_t RECV_BUF_SIZE = 8192; + +TrustyGateKeeperDevice::TrustyGateKeeperDevice(const hw_module_t *module) { +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) + static_assert(std::is_standard_layout<TrustyGateKeeperDevice>::value, + "TrustyGateKeeperDevice must be standard layout"); + static_assert(offsetof(TrustyGateKeeperDevice, device_) == 0, + "device_ must be the first member of TrustyGateKeeperDevice"); + static_assert(offsetof(TrustyGateKeeperDevice, device_.common) == 0, + "common must be the first member of gatekeeper_device"); +#else + assert(reinterpret_cast<gatekeeper_device_t *>(this) == &device_); + assert(reinterpret_cast<hw_device_t *>(this) == &(device_.common)); +#endif + + memset(&device_, 0, sizeof(device_)); + device_.common.tag = HARDWARE_DEVICE_TAG; + device_.common.version = 1; + device_.common.module = const_cast<hw_module_t *>(module); + device_.common.close = close_device; + + device_.enroll = enroll; + device_.verify = verify; + device_.delete_user = nullptr; + device_.delete_all_users = nullptr; + + int rc = trusty_gatekeeper_connect(); + if (rc < 0) { + ALOGE("Error initializing trusty session: %d", rc); + } + + error_ = rc; + +} + +hw_device_t* TrustyGateKeeperDevice::hw_device() { + return &device_.common; +} + +int TrustyGateKeeperDevice::close_device(hw_device_t* dev) { + delete reinterpret_cast<TrustyGateKeeperDevice *>(dev); + return 0; +} + +TrustyGateKeeperDevice::~TrustyGateKeeperDevice() { + trusty_gatekeeper_disconnect(); +} + +int TrustyGateKeeperDevice::Enroll(uint32_t uid, const uint8_t *current_password_handle, + uint32_t current_password_handle_length, const uint8_t *current_password, + uint32_t current_password_length, const uint8_t *desired_password, + uint32_t desired_password_length, uint8_t **enrolled_password_handle, + uint32_t *enrolled_password_handle_length) { + + if (error_ != 0) { + return error_; + } + + SizedBuffer desired_password_buffer(desired_password_length); + memcpy(desired_password_buffer.buffer.get(), desired_password, desired_password_length); + + SizedBuffer current_password_handle_buffer(current_password_handle_length); + if (current_password_handle) { + memcpy(current_password_handle_buffer.buffer.get(), current_password_handle, + current_password_handle_length); + } + + SizedBuffer current_password_buffer(current_password_length); + if (current_password) { + memcpy(current_password_buffer.buffer.get(), current_password, current_password_length); + } + + EnrollRequest request(uid, ¤t_password_handle_buffer, &desired_password_buffer, + ¤t_password_buffer); + EnrollResponse response; + + gatekeeper_error_t error = Send(request, &response); + + if (error == ERROR_RETRY) { + return response.retry_timeout; + } else if (error != ERROR_NONE) { + return -EINVAL; + } + + *enrolled_password_handle = response.enrolled_password_handle.buffer.release(); + *enrolled_password_handle_length = response.enrolled_password_handle.length; + + + return 0; +} + +int TrustyGateKeeperDevice::Verify(uint32_t uid, uint64_t challenge, + const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length, + const uint8_t *provided_password, uint32_t provided_password_length, + uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll) { + if (error_ != 0) { + return error_; + } + + SizedBuffer password_handle_buffer(enrolled_password_handle_length); + memcpy(password_handle_buffer.buffer.get(), enrolled_password_handle, + enrolled_password_handle_length); + SizedBuffer provided_password_buffer(provided_password_length); + memcpy(provided_password_buffer.buffer.get(), provided_password, provided_password_length); + + VerifyRequest request(uid, challenge, &password_handle_buffer, &provided_password_buffer); + VerifyResponse response; + + gatekeeper_error_t error = Send(request, &response); + + if (error == ERROR_RETRY) { + return response.retry_timeout; + } else if (error != ERROR_NONE) { + return -EINVAL; + } + + if (auth_token != NULL && auth_token_length != NULL) { + *auth_token = response.auth_token.buffer.release(); + *auth_token_length = response.auth_token.length; + } + + if (request_reenroll != NULL) { + *request_reenroll = response.request_reenroll; + } + + return 0; +} + +gatekeeper_error_t TrustyGateKeeperDevice::Send(uint32_t command, const GateKeeperMessage& request, + GateKeeperMessage *response) { + uint32_t request_size = request.GetSerializedSize(); + if (request_size > SEND_BUF_SIZE) + return ERROR_INVALID; + uint8_t send_buf[SEND_BUF_SIZE]; + request.Serialize(send_buf, send_buf + request_size); + + // Send it + uint8_t recv_buf[RECV_BUF_SIZE]; + uint32_t response_size = RECV_BUF_SIZE; + int rc = trusty_gatekeeper_call(command, send_buf, request_size, recv_buf, &response_size); + if (rc < 0) { + ALOGE("error (%d) calling gatekeeper TA", rc); + return ERROR_INVALID; + } + + const gatekeeper_message *msg = reinterpret_cast<gatekeeper_message *>(recv_buf); + const uint8_t *payload = msg->payload; + + return response->Deserialize(payload, payload + response_size); +} + +static inline TrustyGateKeeperDevice *convert_device(const gatekeeper_device *dev) { + return reinterpret_cast<TrustyGateKeeperDevice *>(const_cast<gatekeeper_device *>(dev)); +} + +/* static */ +int TrustyGateKeeperDevice::enroll(const struct gatekeeper_device *dev, uint32_t uid, + const uint8_t *current_password_handle, uint32_t current_password_handle_length, + const uint8_t *current_password, uint32_t current_password_length, + const uint8_t *desired_password, uint32_t desired_password_length, + uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) { + + if (dev == NULL || + enrolled_password_handle == NULL || enrolled_password_handle_length == NULL || + desired_password == NULL || desired_password_length == 0) + return -EINVAL; + + // Current password and current password handle go together + if (current_password_handle == NULL || current_password_handle_length == 0 || + current_password == NULL || current_password_length == 0) { + current_password_handle = NULL; + current_password_handle_length = 0; + current_password = NULL; + current_password_length = 0; + } + + return convert_device(dev)->Enroll(uid, current_password_handle, current_password_handle_length, + current_password, current_password_length, desired_password, desired_password_length, + enrolled_password_handle, enrolled_password_handle_length); + +} + +/* static */ +int TrustyGateKeeperDevice::verify(const struct gatekeeper_device *dev, uint32_t uid, + uint64_t challenge, const uint8_t *enrolled_password_handle, + uint32_t enrolled_password_handle_length, const uint8_t *provided_password, + uint32_t provided_password_length, uint8_t **auth_token, uint32_t *auth_token_length, + bool *request_reenroll) { + + if (dev == NULL || enrolled_password_handle == NULL || + provided_password == NULL) { + return -EINVAL; + } + + return convert_device(dev)->Verify(uid, challenge, enrolled_password_handle, + enrolled_password_handle_length, provided_password, provided_password_length, + auth_token, auth_token_length, request_reenroll); +} +}; diff --git a/trusty/gatekeeper/trusty_gatekeeper.h b/trusty/gatekeeper/trusty_gatekeeper.h new file mode 100644 index 000000000..82108dc04 --- /dev/null +++ b/trusty/gatekeeper/trusty_gatekeeper.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TRUSTY_GATEKEEPER_H +#define TRUSTY_GATEKEEPER_H + +#include <hardware/gatekeeper.h> +#include <gatekeeper/gatekeeper_messages.h> + +#include "gatekeeper_ipc.h" + +namespace gatekeeper { + +class TrustyGateKeeperDevice { + public: + + TrustyGateKeeperDevice(const hw_module_t* module); + ~TrustyGateKeeperDevice(); + + hw_device_t* hw_device(); + + /** + * Enrolls password_payload, which should be derived from a user selected pin or password, + * with the authentication factor private key used only for enrolling authentication + * factor data. + * + * Returns: 0 on success or an error code less than 0 on error. + * On error, enrolled_password will not be allocated. + */ + int Enroll(uint32_t uid, const uint8_t *current_password_handle, + uint32_t current_password_handle_length, const uint8_t *current_password, + uint32_t current_password_length, const uint8_t *desired_password, + uint32_t desired_password_length, uint8_t **enrolled_password_handle, + uint32_t *enrolled_password_handle_length); + + /** + * Verifies provided_password matches expected_password after enrolling + * with the authentication factor private key. + * + * Implementations of this module may retain the result of this call + * to attest to the recency of authentication. + * + * On success, writes the address of a verification token to verification_token, + * + * Returns: 0 on success or an error code less than 0 on error + * On error, verification token will not be allocated + */ + int Verify(uint32_t uid, uint64_t challenge, const uint8_t *enrolled_password_handle, + uint32_t enrolled_password_handle_length, const uint8_t *provided_password, + uint32_t provided_password_length, uint8_t **auth_token, uint32_t *auth_token_length, + bool *request_reenroll); + + private: + + gatekeeper_error_t Send(uint32_t command, const GateKeeperMessage& request, + GateKeeperMessage* response); + + gatekeeper_error_t Send(const EnrollRequest& request, EnrollResponse *response) { + return Send(GK_ENROLL, request, response); + } + + gatekeeper_error_t Send(const VerifyRequest& request, VerifyResponse *response) { + return Send(GK_VERIFY, request, response); + } + + // Static methods interfacing the HAL API with the TrustyGateKeeper device + + /** + * Enrolls desired_password, which should be derived from a user selected pin or password, + * with the authentication factor private key used only for enrolling authentication + * factor data. + * + * If there was already a password enrolled, it should be provided in + * current_password_handle, along with the current password in current_password + * that should validate against current_password_handle. + * + * Returns: 0 on success or an error code less than 0 on error. + * On error, enrolled_password_handle will not be allocated. + */ + static int enroll(const struct gatekeeper_device *dev, uint32_t uid, + const uint8_t *current_password_handle, uint32_t current_password_handle_length, + const uint8_t *current_password, uint32_t current_password_length, + const uint8_t *desired_password, uint32_t desired_password_length, + uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length); + + /** + * Verifies provided_password matches enrolled_password_handle. + * + * Implementations of this module may retain the result of this call + * to attest to the recency of authentication. + * + * On success, writes the address of a verification token to auth_token, + * usable to attest password verification to other trusted services. Clients + * may pass NULL for this value. + * + * Returns: 0 on success or an error code less than 0 on error + * On error, verification token will not be allocated + */ + static int verify(const struct gatekeeper_device *dev, uint32_t uid, uint64_t challenge, + const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length, + const uint8_t *provided_password, uint32_t provided_password_length, + uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll); + + static int close_device(hw_device_t* dev); + + gatekeeper_device device_; + int error_; + +}; +} + +#endif + diff --git a/trusty/gatekeeper/trusty_gatekeeper_ipc.c b/trusty/gatekeeper/trusty_gatekeeper_ipc.c new file mode 100644 index 000000000..a1c319e5a --- /dev/null +++ b/trusty/gatekeeper/trusty_gatekeeper_ipc.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#define LOG_TAG "TrustyGateKeeper" +#include <cutils/log.h> +#include <trusty/tipc.h> + +#include "trusty_gatekeeper_ipc.h" +#include "gatekeeper_ipc.h" + +#define TRUSTY_DEVICE_NAME "/dev/trusty-ipc-dev0" + +static int handle_ = 0; + +int trusty_gatekeeper_connect() { + int rc = tipc_connect(TRUSTY_DEVICE_NAME, GATEKEEPER_PORT); + if (rc < 0) { + return rc; + } + + handle_ = rc; + return 0; +} + +int trusty_gatekeeper_call(uint32_t cmd, void *in, uint32_t in_size, uint8_t *out, + uint32_t *out_size) { + if (handle_ == 0) { + ALOGE("not connected\n"); + return -EINVAL; + } + + size_t msg_size = in_size + sizeof(struct gatekeeper_message); + struct gatekeeper_message *msg = malloc(msg_size); + msg->cmd = cmd; + memcpy(msg->payload, in, in_size); + + ssize_t rc = write(handle_, msg, msg_size); + free(msg); + + if (rc < 0) { + ALOGE("failed to send cmd (%d) to %s: %s\n", cmd, + GATEKEEPER_PORT, strerror(errno)); + return -errno; + } + + rc = read(handle_, out, *out_size); + if (rc < 0) { + ALOGE("failed to retrieve response for cmd (%d) to %s: %s\n", + cmd, GATEKEEPER_PORT, strerror(errno)); + return -errno; + } + + if ((size_t) rc < sizeof(struct gatekeeper_message)) { + ALOGE("invalid response size (%d)\n", (int) rc); + return -EINVAL; + } + + msg = (struct gatekeeper_message *) out; + + if ((cmd | GK_RESP_BIT) != msg->cmd) { + ALOGE("invalid command (%d)\n", msg->cmd); + return -EINVAL; + } + + *out_size = ((size_t) rc) - sizeof(struct gatekeeper_message); + return rc; +} + +void trusty_gatekeeper_disconnect() { + if (handle_ != 0) { + tipc_close(handle_); + } +} + diff --git a/trusty/gatekeeper/trusty_gatekeeper_ipc.h b/trusty/gatekeeper/trusty_gatekeeper_ipc.h new file mode 100644 index 000000000..f8de7f873 --- /dev/null +++ b/trusty/gatekeeper/trusty_gatekeeper_ipc.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +__BEGIN_DECLS + +int trusty_gatekeeper_connect(); +int trusty_gatekeeper_call(uint32_t cmd, void *in, uint32_t in_size, uint8_t *out, + uint32_t *out_size); +void trusty_gatekeeper_disconnect(); + +__END_DECLS |