Merge "Add fdsan capabilities for native handles" am: 98e474ab43 am: aa83e839b0

Original change: https://android-review.googlesource.com/c/platform/system/core/+/2199556

Change-Id: Ic4939621203328251bfa72ec7e5b4b7fee2f9dc9
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Treehugger Robot 2022-09-06 23:31:54 +00:00 committed by Automerger Merge Worker
commit a894c263d0
3 changed files with 121 additions and 33 deletions

View file

@ -168,6 +168,9 @@ cc_library {
target: { target: {
linux_bionic: { linux_bionic: {
enabled: true, enabled: true,
static_libs: [
"libasync_safe",
],
}, },
not_windows: { not_windows: {
srcs: libcutils_nonwindows_sources + [ srcs: libcutils_nonwindows_sources + [
@ -190,6 +193,9 @@ cc_library {
], ],
}, },
android: { android: {
static_libs: [
"libasync_safe",
],
srcs: libcutils_nonwindows_sources + [ srcs: libcutils_nonwindows_sources + [
"android_reboot.cpp", "android_reboot.cpp",
"ashmem-dev.cpp", "ashmem-dev.cpp",

View file

@ -49,18 +49,28 @@ typedef struct native_handle
typedef const native_handle_t* buffer_handle_t; typedef const native_handle_t* buffer_handle_t;
/* /*
* native_handle_close * Closes the file descriptors contained in this native_handle_t, which may
* * either be untagged or tagged for ownership by this native_handle_t via
* closes the file descriptors contained in this native_handle_t * native_handle_set_tag(). Mixing untagged and tagged fds in the same
* * native_handle_t is not permitted and triggers an fdsan exception, but
* native_handle_set_fdsan_tag() can be used to bring consistency if this is
* intentional.
*
* If it's known that fds are tagged, prefer native_handle_close_with_tag() for
* better safety.
*
* return 0 on success, or a negative error code on failure * return 0 on success, or a negative error code on failure
*
*/ */
int native_handle_close(const native_handle_t* h); int native_handle_close(const native_handle_t* h);
/* /*
* native_handle_init * Equivalent to native_handle_close(), but throws an fdsan exception if the fds
* * are untagged. Use if it's known that the fds in this native_handle_t were
* previously tagged via native_handle_set_tag().
*/
int native_handle_close_with_tag(const native_handle_t* h);
/*
* Initializes a native_handle_t from storage. storage must be declared with * Initializes a native_handle_t from storage. storage must be declared with
* NATIVE_HANDLE_DECLARE_STORAGE. numFds and numInts must not respectively * NATIVE_HANDLE_DECLARE_STORAGE. numFds and numInts must not respectively
* exceed maxFds and maxInts used to declare the storage. * exceed maxFds and maxInts used to declare the storage.
@ -68,33 +78,42 @@ int native_handle_close(const native_handle_t* h);
native_handle_t* native_handle_init(char* storage, int numFds, int numInts); native_handle_t* native_handle_init(char* storage, int numFds, int numInts);
/* /*
* native_handle_create * Creates a native_handle_t and initializes it. Must be destroyed with
*
* creates a native_handle_t and initializes it. must be destroyed with
* native_handle_delete(). Note that numFds must be <= NATIVE_HANDLE_MAX_FDS, * native_handle_delete(). Note that numFds must be <= NATIVE_HANDLE_MAX_FDS,
* numInts must be <= NATIVE_HANDLE_MAX_INTS, and both must be >= 0. * numInts must be <= NATIVE_HANDLE_MAX_INTS, and both must be >= 0.
*
*/ */
native_handle_t* native_handle_create(int numFds, int numInts); native_handle_t* native_handle_create(int numFds, int numInts);
/* /*
* native_handle_clone * Updates the fdsan tag for any file descriptors contained in the supplied
* * handle to indicate that they are owned by this handle and should only be
* creates a native_handle_t and initializes it from another native_handle_t. * closed via native_handle_close()/native_handle_close_with_tag(). Each fd in
* the handle must have a tag of either 0 (unset) or the tag associated with
* this handle, otherwise an fdsan exception will be triggered.
*/
void native_handle_set_fdsan_tag(const native_handle_t* handle);
/*
* Clears the fdsan tag for any file descriptors contained in the supplied
* native_handle_t. Use if this native_handle_t is giving up ownership of its
* fds, but the fdsan tags were previously set. Each fd in the handle must have
* a tag of either 0 (unset) or the tag associated with this handle, otherwise
* an fdsan exception will be triggered.
*/
void native_handle_unset_fdsan_tag(const native_handle_t* handle);
/*
* Creates a native_handle_t and initializes it from another native_handle_t.
* Must be destroyed with native_handle_delete(). * Must be destroyed with native_handle_delete().
*
*/ */
native_handle_t* native_handle_clone(const native_handle_t* handle); native_handle_t* native_handle_clone(const native_handle_t* handle);
/* /*
* native_handle_delete * Frees a native_handle_t allocated with native_handle_create().
*
* frees a native_handle_t allocated with native_handle_create().
* This ONLY frees the memory allocated for the native_handle_t, but doesn't * This ONLY frees the memory allocated for the native_handle_t, but doesn't
* close the file descriptors; which can be achieved with native_handle_close(). * close the file descriptors; which can be achieved with native_handle_close().
* *
* return 0 on success, or a negative error code on failure * return 0 on success, or a negative error code on failure
*
*/ */
int native_handle_delete(native_handle_t* h); int native_handle_delete(native_handle_t* h);

View file

@ -22,13 +22,74 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
// Needs to come after stdlib includes to capture the __BIONIC__ definition
#ifdef __BIONIC__
#include <android/fdsan.h>
#endif
namespace {
#if !defined(__BIONIC__)
// fdsan stubs when not linked against bionic
#define ANDROID_FDSAN_OWNER_TYPE_NATIVE_HANDLE 0
uint64_t android_fdsan_create_owner_tag(int /*type*/, uint64_t /*tag*/) {
return 0;
}
uint64_t android_fdsan_get_owner_tag(int /*fd*/) {
return 0;
}
int android_fdsan_close_with_tag(int fd, uint64_t /*tag*/) {
return close(fd);
}
void android_fdsan_exchange_owner_tag(int /*fd*/, uint64_t /*expected_tag*/, uint64_t /*tag*/) {}
#endif // !__BIONIC__
uint64_t get_fdsan_tag(const native_handle_t* handle) {
return android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_NATIVE_HANDLE,
reinterpret_cast<uint64_t>(handle));
}
int close_internal(const native_handle_t* h, bool allowUntagged) {
if (!h) return 0;
if (h->version != sizeof(native_handle_t)) return -EINVAL;
const int numFds = h->numFds;
uint64_t tag;
if (allowUntagged && numFds > 0 && android_fdsan_get_owner_tag(h->data[0]) == 0) {
tag = 0;
} else {
tag = get_fdsan_tag(h);
}
int saved_errno = errno;
for (int i = 0; i < numFds; ++i) {
android_fdsan_close_with_tag(h->data[i], tag);
}
errno = saved_errno;
return 0;
}
void swap_fdsan_tags(const native_handle_t* handle, uint64_t expected_tag, uint64_t new_tag) {
if (!handle || handle->version != sizeof(native_handle_t)) return;
for (int i = 0; i < handle->numFds; i++) {
// allow for idempotence to make the APIs easier to use
if (android_fdsan_get_owner_tag(handle->data[i]) != new_tag) {
android_fdsan_exchange_owner_tag(handle->data[i], expected_tag, new_tag);
}
}
}
} // anonymous namespace
native_handle_t* native_handle_init(char* storage, int numFds, int numInts) { native_handle_t* native_handle_init(char* storage, int numFds, int numInts) {
if ((uintptr_t) storage % alignof(native_handle_t)) { if ((uintptr_t)storage % alignof(native_handle_t)) {
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
native_handle_t* handle = (native_handle_t*) storage; native_handle_t* handle = (native_handle_t*)storage;
handle->version = sizeof(native_handle_t); handle->version = sizeof(native_handle_t);
handle->numFds = numFds; handle->numFds = numFds;
handle->numInts = numInts; handle->numInts = numInts;
@ -52,6 +113,14 @@ native_handle_t* native_handle_create(int numFds, int numInts) {
return h; return h;
} }
void native_handle_set_fdsan_tag(const native_handle_t* handle) {
swap_fdsan_tags(handle, 0, get_fdsan_tag(handle));
}
void native_handle_unset_fdsan_tag(const native_handle_t* handle) {
swap_fdsan_tags(handle, get_fdsan_tag(handle), 0);
}
native_handle_t* native_handle_clone(const native_handle_t* handle) { native_handle_t* native_handle_clone(const native_handle_t* handle) {
native_handle_t* clone = native_handle_create(handle->numFds, handle->numInts); native_handle_t* clone = native_handle_create(handle->numFds, handle->numInts);
if (clone == NULL) return NULL; if (clone == NULL) return NULL;
@ -81,15 +150,9 @@ int native_handle_delete(native_handle_t* h) {
} }
int native_handle_close(const native_handle_t* h) { int native_handle_close(const native_handle_t* h) {
if (!h) return 0; return close_internal(h, /*allowUntagged=*/true);
}
if (h->version != sizeof(native_handle_t)) return -EINVAL;
int native_handle_close_with_tag(const native_handle_t* h) {
int saved_errno = errno; return close_internal(h, /*allowUntagged=*/false);
const int numFds = h->numFds;
for (int i = 0; i < numFds; ++i) {
close(h->data[i]);
}
errno = saved_errno;
return 0;
} }