Add support for tipc_send()
* Supports sending memfds in addition to data from an iovec
* Also add a basic test called send-fd
Bug: 117221195
Test: Run send-fd with corresponding Trusty application.
Change-Id: I562d2ff744938c868323a016659ca1332f6a576b
diff --git a/trusty/libtrusty/include/trusty/ipc.h b/trusty/libtrusty/include/trusty/ipc.h
new file mode 100644
index 0000000..1fa6fe4
--- /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 <linux/ioctl.h>
+#include <linux/types.h>
+#include <linux/uio.h>
+
+/**
+ * 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 a3f2a3f..b44afd3 100644
--- a/trusty/libtrusty/include/trusty/tipc.h
+++ b/trusty/libtrusty/include/trusty/tipc.h
@@ -21,7 +21,11 @@
extern "C" {
#endif
+#include <sys/uio.h>
+#include <trusty/ipc.h>
+
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 d20d4ee..ca581dc 100644
--- a/trusty/libtrusty/tipc-test/tipc_test.c
+++ b/trusty/libtrusty/tipc-test/tipc_test.c
@@ -21,6 +21,8 @@
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
+#define __USE_GNU
+#include <sys/mman.h>
#include <sys/uio.h>
#include <trusty/tipc.h>
@@ -39,6 +41,7 @@
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 @@
"\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 @@
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 @@
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 27da56a..0000000
--- 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 <linux/ioctl.h>
-#include <linux/types.h>
-
-#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 a6238af..ad4d8cd 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 <log/log.h>
-#include "tipc_ioctl.h"
+#include <trusty/ipc.h>
int tipc_connect(const char *dev_name, const char *srv_name)
{
@@ -55,6 +55,22 @@
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);