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
This commit is contained in:
Matthew Maurer 2020-06-15 14:08:55 -07:00
parent e4424ff422
commit e251fa32fd
5 changed files with 188 additions and 52 deletions

View file

@ -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

View file

@ -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

View file

@ -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 *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;
}

View file

@ -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

View file

@ -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 @@ 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);