diff --git a/trusty/libtrusty/include/trusty/ipc.h b/trusty/libtrusty/include/trusty/ipc.h new file mode 100644 index 000000000..1fa6fe4aa --- /dev/null +++ b/trusty/libtrusty/include/trusty/ipc.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2020 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 _UAPI_LINUX_TRUSTY_IPC_H_ +#define _UAPI_LINUX_TRUSTY_IPC_H_ + +#include +#include +#include + +/** + * enum transfer_kind - How to send an fd to Trusty + * @TRUSTY_SHARE: Memory will be accessible by Linux and Trusty. On ARM it will + * be mapped as nonsecure. Suitable for shared memory. The paired + * fd must be a "memfd". + * @TRUSTY_LEND: Memory will be accessible only to Trusty. On ARM it will be + * transitioned to "Secure" memory if Trusty is in TrustZone. + * This transfer kind is suitable for donating video buffers or + * other similar resources. The paired fd may need to come from a + * platform-specific allocator for memory that may be + * transitioned to "Secure". + * + * Describes how the user would like the resource in question to be sent to + * Trusty. Options may be valid only for certain kinds of fds. + */ +enum transfer_kind { + TRUSTY_SHARE = 0, + TRUSTY_LEND = 1, +}; + +/** + * struct trusty_shm - Describes a transfer of memory to Trusty + * @fd: The fd to transfer + * @transfer: How to transfer it - see &enum transfer_kind + */ +struct trusty_shm { + __s32 fd; + __u32 transfer; +}; + +/** + * struct tipc_send_msg_req - Request struct for @TIPC_IOC_SEND_MSG + * @iov: Pointer to an array of &struct iovec describing data to be sent + * @shm: Pointer to an array of &struct trusty_shm describing any file + * descriptors to be transferred. + * @iov_cnt: Number of elements in the @iov array + * @shm_cnt: Number of elements in the @shm array + */ +struct tipc_send_msg_req { + __u64 iov; + __u64 shm; + __u64 iov_cnt; + __u64 shm_cnt; +}; + +#define TIPC_IOC_MAGIC 'r' +#define TIPC_IOC_CONNECT _IOW(TIPC_IOC_MAGIC, 0x80, char*) +#define TIPC_IOC_SEND_MSG _IOW(TIPC_IOC_MAGIC, 0x81, struct tipc_send_msg_req) + +#if defined(CONFIG_COMPAT) +#define TIPC_IOC_CONNECT_COMPAT _IOW(TIPC_IOC_MAGIC, 0x80, compat_uptr_t) +#endif + +#endif diff --git a/trusty/libtrusty/include/trusty/tipc.h b/trusty/libtrusty/include/trusty/tipc.h index a3f2a3f61..b44afd337 100644 --- a/trusty/libtrusty/include/trusty/tipc.h +++ b/trusty/libtrusty/include/trusty/tipc.h @@ -21,7 +21,11 @@ extern "C" { #endif +#include +#include + int tipc_connect(const char *dev_name, const char *srv_name); +ssize_t tipc_send(int fd, const struct iovec* iov, int iovcnt, struct trusty_shm* shm, int shmcnt); int tipc_close(int fd); #ifdef __cplusplus diff --git a/trusty/libtrusty/tipc-test/tipc_test.c b/trusty/libtrusty/tipc-test/tipc_test.c index d20d4eebf..ca581dc2d 100644 --- a/trusty/libtrusty/tipc-test/tipc_test.c +++ b/trusty/libtrusty/tipc-test/tipc_test.c @@ -21,6 +21,8 @@ #include #include #include +#define __USE_GNU +#include #include #include @@ -39,6 +41,7 @@ static const char *closer1_name = "com.android.ipc-unittest.srv.closer1"; static const char *closer2_name = "com.android.ipc-unittest.srv.closer2"; static const char *closer3_name = "com.android.ipc-unittest.srv.closer3"; static const char *main_ctrl_name = "com.android.ipc-unittest.ctrl"; +static const char* receiver_name = "com.android.trusty.memref.receiver"; static const char *_sopts = "hsvD:t:r:m:b:"; static const struct option _lopts[] = { @@ -66,25 +69,25 @@ static const char *usage = "\n" ; -static const char *usage_long = -"\n" -"The following tests are available:\n" -" connect - connect to datasink service\n" -" connect_foo - connect to non existing service\n" -" burst_write - send messages to datasink service\n" -" echo - send/receive messages to echo service\n" -" select - test select call\n" -" blocked_read - test blocked read\n" -" closer1 - connection closed by remote (test1)\n" -" closer2 - connection closed by remote (test2)\n" -" closer3 - connection closed by remote (test3)\n" -" ta2ta-ipc - execute TA to TA unittest\n" -" dev-uuid - print device uuid\n" -" ta-access - test ta-access flags\n" -" writev - writev test\n" -" readv - readv test\n" -"\n" -; +static const char* usage_long = + "\n" + "The following tests are available:\n" + " connect - connect to datasink service\n" + " connect_foo - connect to non existing service\n" + " burst_write - send messages to datasink service\n" + " echo - send/receive messages to echo service\n" + " select - test select call\n" + " blocked_read - test blocked read\n" + " closer1 - connection closed by remote (test1)\n" + " closer2 - connection closed by remote (test2)\n" + " closer3 - connection closed by remote (test3)\n" + " ta2ta-ipc - execute TA to TA unittest\n" + " dev-uuid - print device uuid\n" + " ta-access - test ta-access flags\n" + " writev - writev test\n" + " readv - readv test\n" + " send-fd - transmit memfd to trusty, use as shm\n" + "\n"; static uint opt_repeat = 1; static uint opt_msgsize = 32; @@ -885,6 +888,66 @@ static int readv_test(uint repeat, uint msgsz, bool var) return 0; } +static int send_fd_test(void) { + int ret; + int memfd = -1; + int fd = -1; + volatile char* buf = MAP_FAILED; + + fd = tipc_connect(dev_name, receiver_name); + if (fd < 0) { + fprintf(stderr, "Failed to connect to test support TA - is it missing?\n"); + ret = -1; + goto cleanup; + } + + memfd = memfd_create("tipc-send-fd", 0); + if (memfd < 0) { + fprintf(stderr, "Failed to create memfd: %s\n", strerror(errno)); + ret = -1; + goto cleanup; + } + + if (ftruncate(memfd, PAGE_SIZE) < 0) { + fprintf(stderr, "Failed to resize memfd: %s\n", strerror(errno)); + ret = -1; + goto cleanup; + } + + buf = mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, 0); + if (buf == MAP_FAILED) { + fprintf(stderr, "Failed to map memfd: %s\n", strerror(errno)); + ret = -1; + goto cleanup; + } + + strcpy((char*)buf, "From NS"); + + struct trusty_shm shm = { + .fd = memfd, + .transfer = TRUSTY_SHARE, + }; + + ssize_t rc = tipc_send(fd, NULL, 0, &shm, 1); + if (rc < 0) { + fprintf(stderr, "tipc_send failed\n"); + ret = rc; + goto cleanup; + } + char c; + read(fd, &c, 1); + tipc_close(fd); + + ret = strcmp("Hello from Trusty!", (const char*)buf) ? (-1) : 0; + +cleanup: + if (buf != MAP_FAILED) { + munmap((char*)buf, PAGE_SIZE); + } + close(memfd); + tipc_close(fd); + return ret; +} int main(int argc, char **argv) { @@ -933,10 +996,12 @@ int main(int argc, char **argv) rc = writev_test(opt_repeat, opt_msgsize, opt_variable); } else if (strcmp(test_name, "readv") == 0) { rc = readv_test(opt_repeat, opt_msgsize, opt_variable); - } else { - fprintf(stderr, "Unrecognized test name '%s'\n", test_name); - print_usage_and_exit(argv[0], EXIT_FAILURE, true); - } + } else if (strcmp(test_name, "send-fd") == 0) { + rc = send_fd_test(); + } else { + fprintf(stderr, "Unrecognized test name '%s'\n", test_name); + print_usage_and_exit(argv[0], EXIT_FAILURE, true); + } - return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE; + return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/trusty/libtrusty/tipc_ioctl.h b/trusty/libtrusty/tipc_ioctl.h deleted file mode 100644 index 27da56a9e..000000000 --- a/trusty/libtrusty/tipc_ioctl.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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. - */ - -#ifndef _TIPC_IOCTL_H -#define _TIPC_IOCTL_H - -#include -#include - -#define TIPC_IOC_MAGIC 'r' -#define TIPC_IOC_CONNECT _IOW(TIPC_IOC_MAGIC, 0x80, char *) - -#endif diff --git a/trusty/libtrusty/trusty.c b/trusty/libtrusty/trusty.c index a6238af7d..ad4d8cd54 100644 --- a/trusty/libtrusty/trusty.c +++ b/trusty/libtrusty/trusty.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright (C) 2020 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. @@ -27,7 +27,7 @@ #include -#include "tipc_ioctl.h" +#include int tipc_connect(const char *dev_name, const char *srv_name) { @@ -55,6 +55,22 @@ int tipc_connect(const char *dev_name, const char *srv_name) return fd; } +ssize_t tipc_send(int fd, const struct iovec* iov, int iovcnt, struct trusty_shm* shms, + int shmcnt) { + struct tipc_send_msg_req req; + req.iov = (__u64)iov; + req.iov_cnt = (__u64)iovcnt; + req.shm = (__u64)shms; + req.shm_cnt = (__u64)shmcnt; + + int rc = ioctl(fd, TIPC_IOC_SEND_MSG, &req); + if (rc < 0) { + ALOGE("%s: failed to send message (err=%d)\n", __func__, rc); + } + + return rc; +} + void tipc_close(int fd) { close(fd);