Merge "fastboot: use cutils socket functions." am: bbedd9523f
am: f0bfaf9503
* commit 'f0bfaf95038241c3f8ed65099c7d532a6c112e86':
fastboot: use cutils socket functions.
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 6020ad5..f8c8c61 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -788,9 +788,7 @@
// 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 4573da0..e409bf6 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -84,6 +84,8 @@
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,
@@ -329,11 +331,17 @@
" 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) {
@@ -453,8 +461,60 @@
#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) {
@@ -1040,7 +1100,8 @@
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;
@@ -1104,7 +1165,7 @@
}
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;
@@ -1133,6 +1194,7 @@
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;
@@ -1155,6 +1217,9 @@
{"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}
};
@@ -1236,6 +1301,15 @@
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:
@@ -1329,7 +1403,8 @@
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);
@@ -1464,13 +1539,23 @@
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 90d8474..8539e23 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 @@
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 289488b..0a68507 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 beb95de..1c7da30 100644
--- a/fingerprintd/FingerprintDaemonProxy.cpp
+++ b/fingerprintd/FingerprintDaemonProxy.cpp
@@ -88,6 +88,16 @@
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 @@
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 871c0e6..145b4c9 100644
--- a/fingerprintd/FingerprintDaemonProxy.h
+++ b/fingerprintd/FingerprintDaemonProxy.h
@@ -40,6 +40,7 @@
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 7131793..bc4af56 100644
--- a/fingerprintd/IFingerprintDaemon.cpp
+++ b/fingerprintd/IFingerprintDaemon.cpp
@@ -125,6 +125,16 @@
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 1eb4ac1..23c36ff 100644
--- a/fingerprintd/IFingerprintDaemon.h
+++ b/fingerprintd/IFingerprintDaemon.h
@@ -44,6 +44,7 @@
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 @@
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 44d8020..19838c9 100644
--- a/fingerprintd/IFingerprintDaemonCallback.cpp
+++ b/fingerprintd/IFingerprintDaemonCallback.cpp
@@ -74,13 +74,13 @@
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 6e32213..e343cb4 100644
--- a/fingerprintd/IFingerprintDaemonCallback.h
+++ b/fingerprintd/IFingerprintDaemonCallback.h
@@ -44,8 +44,7 @@
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 c47a585..2ff6273 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -101,6 +101,7 @@
char tmpmnt_opts[64] = "errors=remount-ro";
char *e2fsck_argv[] = {
E2FSCK_BIN,
+ "-f",
"-y",
blk_device
};
@@ -442,8 +443,22 @@
// Check to see if a mountable volume has encryption requirements
static int handle_encryptable(struct fstab *fstab, 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,7 +470,8 @@
}
// Deal with file level encryption
- if (rec->fs_mgr_flags & MF_FILEENCRYPTION) {
+ if ( (rec->fs_mgr_flags & MF_FILEENCRYPTION)
+ || ((rec->fs_mgr_flags & MF_FORCEFDEORFBE) && convert_fbe)) {
// 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);
@@ -881,7 +897,8 @@
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 cf35b3f..c8c624d 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -64,6 +64,7 @@
{ "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 @@
* 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_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 @@
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 ba0e097..181b6cd 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -82,6 +82,7 @@
#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 27fccf7..eb0a7fc 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -102,6 +102,7 @@
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 c504f92..47a8bfa 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 cdfe9c5..3b5ff35 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -611,7 +611,7 @@
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 70f0b92..be9e819 100644
--- a/include/cutils/fs.h
+++ b/include/cutils/fs.h
@@ -40,11 +40,18 @@
#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/system/radio.h b/include/system/radio.h
index a088526..9e291c8 100644
--- a/include/system/radio.h
+++ b/include/system/radio.h
@@ -94,6 +94,7 @@
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 @@
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 @@
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 508ce00..14cce27 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 @@
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 @@
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 @@
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 4350ec1..88b5b44 100644
--- a/include/usbhost/usbhost.h
+++ b/include/usbhost/usbhost.h
@@ -219,6 +219,9 @@
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 35f1a9e..5918609 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -884,13 +884,6 @@
do_installkeys_ensure_dir_exists);
}
-static int do_setusercryptopolicies(const std::vector<std::string>& args) {
- if (!is_file_crypto()) {
- return 0;
- }
- return e4crypt_set_user_crypto_policies(args[1].c_str());
-}
-
BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
static const Map builtin_functions = {
@@ -923,7 +916,6 @@
{"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 45c7add..5e2ef0b 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 @@
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 @@
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 6d50adc..645edd1 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -79,6 +79,7 @@
{ 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 @@
{ 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/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 6e6b0b9..2e2ef36 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -36,6 +36,10 @@
#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:"
"libdl.so:"
"libEGL.so:"
diff --git a/libnetutils/dhcptool.c b/libnetutils/dhcptool.c
index 352ac5e..a2d3869 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 @@
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 e0a9f7f..85ff070 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 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_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)close(ifc_ctl_sock);
ifc_ctl_sock = -1;
}
+ pthread_mutex_unlock(&ifc_sock_mutex);
}
void ifc_close6(void)
@@ -160,6 +167,7 @@
(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 @@
ifc_init();
if (ifc_ctl_sock < 0) {
+ ifc_close();
return -errno;
}
diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c
index b8e3215..299fdc4 100644
--- a/libusbhost/usbhost.c
+++ b/libusbhost/usbhost.c
@@ -617,6 +617,11 @@
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 631b5a3..8c4fd15 100644
--- a/libutils/Android.mk
+++ b/libutils/Android.mk
@@ -106,19 +106,16 @@
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 c7dd1ab..34d75ee 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 a0484ff..33a4e0c 100644
--- a/libutils/SharedBufferTest.cpp
+++ b/libutils/SharedBufferTest.cpp
@@ -31,10 +31,10 @@
// 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 @@
// 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 c42c68d..01e64f6 100644
--- a/libutils/tests/String8_test.cpp
+++ b/libutils/tests/String8_test.cpp
@@ -72,4 +72,9 @@
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 aa3db8a..511bf68 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -77,12 +77,7 @@
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 @@
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 @@
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 @@
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 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 @@
}
}
- 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 @@
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 15928f8..a839729 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -76,6 +76,7 @@
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
@@ -307,8 +308,6 @@
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
@@ -355,6 +354,7 @@
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
@@ -391,13 +391,22 @@
# 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/user 0711 system system
+ mkdir /data/system_ce 0770 system system
+ mkdir /data/system_ce/0 0770 system system
- setusercryptopolicies /data/user
+ 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
# 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 0ca38b9..53cfcc2 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -3,6 +3,7 @@
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 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 1646c0f..a9a94d7 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -3,6 +3,7 @@
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 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 b477c8e..8f47174 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -3,6 +3,7 @@
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 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 633a981..70a9678 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -3,6 +3,7 @@
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 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 f862561..45efe36 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -1214,13 +1214,7 @@
}
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 @@
}
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 @@
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 0000000..13e9a09
--- /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 0000000..b05dcd8
--- /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 0000000..0ee3c2f
--- /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 0000000..d24f44f
--- /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 0000000..82108dc
--- /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 0000000..a1c319e
--- /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 0000000..f8de7f8
--- /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