1 /*
2 * Copyright (c) 2022 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <stdbool.h>
9 #include <zephyr/rtio/rtio.h>
10 #include <zephyr/internal/syscall_handler.h>
11
12 /**
13 * Verify each SQE type operation and its fields ensuring
14 * the iodev is a valid accessible k_object (if given) and
15 * the buffer pointers are valid accessible memory by the calling
16 * thread.
17 *
18 * Each op code that is acceptable from user mode must also be validated.
19 */
rtio_vrfy_sqe(struct rtio_sqe * sqe)20 static inline bool rtio_vrfy_sqe(struct rtio_sqe *sqe)
21 {
22 if (sqe->iodev != NULL) {
23 if (K_SYSCALL_OBJ(sqe->iodev, K_OBJ_RTIO_IODEV)) {
24 return false;
25 }
26 }
27
28 bool valid_sqe = true;
29
30 switch (sqe->op) {
31 case RTIO_OP_NOP:
32 break;
33 case RTIO_OP_TX:
34 valid_sqe &= K_SYSCALL_MEMORY(sqe->tx.buf, sqe->tx.buf_len, false);
35 break;
36 case RTIO_OP_RX:
37 if ((sqe->flags & RTIO_SQE_MEMPOOL_BUFFER) == 0) {
38 valid_sqe &= K_SYSCALL_MEMORY(sqe->rx.buf, sqe->rx.buf_len, true);
39 }
40 break;
41 case RTIO_OP_TINY_TX:
42 break;
43 case RTIO_OP_TXRX:
44 valid_sqe &= K_SYSCALL_MEMORY(sqe->txrx.tx_buf, sqe->txrx.buf_len, true);
45 valid_sqe &= K_SYSCALL_MEMORY(sqe->txrx.rx_buf, sqe->txrx.buf_len, true);
46 break;
47 default:
48 /* RTIO OP must be known and allowable from user mode
49 * otherwise it is invalid
50 */
51 valid_sqe = false;
52 }
53
54 return valid_sqe;
55 }
56
z_vrfy_rtio_release_buffer(struct rtio * r,void * buff,uint32_t buff_len)57 static inline void z_vrfy_rtio_release_buffer(struct rtio *r, void *buff, uint32_t buff_len)
58 {
59 K_OOPS(K_SYSCALL_OBJ(r, K_OBJ_RTIO));
60 z_impl_rtio_release_buffer(r, buff, buff_len);
61 }
62 #include <zephyr/syscalls/rtio_release_buffer_mrsh.c>
63
z_vrfy_rtio_cqe_get_mempool_buffer(const struct rtio * r,struct rtio_cqe * cqe,uint8_t ** buff,uint32_t * buff_len)64 static inline int z_vrfy_rtio_cqe_get_mempool_buffer(const struct rtio *r, struct rtio_cqe *cqe,
65 uint8_t **buff, uint32_t *buff_len)
66 {
67 K_OOPS(K_SYSCALL_OBJ(r, K_OBJ_RTIO));
68 K_OOPS(K_SYSCALL_MEMORY_READ(cqe, sizeof(struct rtio_cqe)));
69 K_OOPS(K_SYSCALL_MEMORY_READ(buff, sizeof(void *)));
70 K_OOPS(K_SYSCALL_MEMORY_READ(buff_len, sizeof(uint32_t)));
71 return z_impl_rtio_cqe_get_mempool_buffer(r, cqe, buff, buff_len);
72 }
73 #include <zephyr/syscalls/rtio_cqe_get_mempool_buffer_mrsh.c>
74
z_vrfy_rtio_sqe_cancel(struct rtio_sqe * sqe)75 static inline int z_vrfy_rtio_sqe_cancel(struct rtio_sqe *sqe)
76 {
77 return z_impl_rtio_sqe_cancel(sqe);
78 }
79 #include <zephyr/syscalls/rtio_sqe_cancel_mrsh.c>
80
z_vrfy_rtio_sqe_copy_in_get_handles(struct rtio * r,const struct rtio_sqe * sqes,struct rtio_sqe ** handle,size_t sqe_count)81 static inline int z_vrfy_rtio_sqe_copy_in_get_handles(struct rtio *r, const struct rtio_sqe *sqes,
82 struct rtio_sqe **handle, size_t sqe_count)
83 {
84 K_OOPS(K_SYSCALL_OBJ(r, K_OBJ_RTIO));
85
86 K_OOPS(K_SYSCALL_MEMORY_ARRAY_READ(sqes, sqe_count, sizeof(struct rtio_sqe)));
87 struct rtio_sqe *sqe;
88 uint32_t acquirable = rtio_sqe_acquirable(r);
89
90 if (acquirable < sqe_count) {
91 return -ENOMEM;
92 }
93
94
95 for (int i = 0; i < sqe_count; i++) {
96 sqe = rtio_sqe_acquire(r);
97 __ASSERT_NO_MSG(sqe != NULL);
98 if (handle != NULL && i == 0) {
99 *handle = sqe;
100 }
101 *sqe = sqes[i];
102
103 if (!rtio_vrfy_sqe(sqe)) {
104 rtio_sqe_drop_all(r);
105 K_OOPS(true);
106 }
107 }
108
109 /* Already copied *and* verified, no need to redo */
110 return z_impl_rtio_sqe_copy_in_get_handles(r, NULL, NULL, 0);
111 }
112 #include <zephyr/syscalls/rtio_sqe_copy_in_get_handles_mrsh.c>
113
z_vrfy_rtio_cqe_copy_out(struct rtio * r,struct rtio_cqe * cqes,size_t cqe_count,k_timeout_t timeout)114 static inline int z_vrfy_rtio_cqe_copy_out(struct rtio *r,
115 struct rtio_cqe *cqes,
116 size_t cqe_count,
117 k_timeout_t timeout)
118 {
119 K_OOPS(K_SYSCALL_OBJ(r, K_OBJ_RTIO));
120
121 K_OOPS(K_SYSCALL_MEMORY_ARRAY_WRITE(cqes, cqe_count, sizeof(struct rtio_cqe)));
122
123 return z_impl_rtio_cqe_copy_out(r, cqes, cqe_count, timeout);
124 }
125 #include <zephyr/syscalls/rtio_cqe_copy_out_mrsh.c>
126
z_vrfy_rtio_submit(struct rtio * r,uint32_t wait_count)127 static inline int z_vrfy_rtio_submit(struct rtio *r, uint32_t wait_count)
128 {
129 K_OOPS(K_SYSCALL_OBJ(r, K_OBJ_RTIO));
130
131 #ifdef CONFIG_RTIO_SUBMIT_SEM
132 K_OOPS(K_SYSCALL_OBJ(r->submit_sem, K_OBJ_SEM));
133 #endif
134
135 return z_impl_rtio_submit(r, wait_count);
136 }
137 #include <zephyr/syscalls/rtio_submit_mrsh.c>
138
139
z_vrfy_rtio_pool_acquire(struct rtio_pool * rpool)140 static inline struct rtio *z_vrfy_rtio_pool_acquire(struct rtio_pool *rpool)
141 {
142 K_OOPS(K_SYSCALL_OBJ(rpool, K_OBJ_RTIO_POOL));
143
144 return z_impl_rtio_pool_acquire(rpool);
145 }
146 #include <zephyr/syscalls/rtio_pool_acquire_mrsh.c>
147
148
z_vrfy_rtio_pool_release(struct rtio_pool * rpool,struct rtio * r)149 static inline void z_vrfy_rtio_pool_release(struct rtio_pool *rpool, struct rtio *r)
150 {
151 K_OOPS(K_SYSCALL_OBJ(rpool, K_OBJ_RTIO_POOL));
152 K_OOPS(K_SYSCALL_OBJ(r, K_OBJ_RTIO));
153
154 z_impl_rtio_pool_release(rpool, r);
155 }
156 #include <zephyr/syscalls/rtio_pool_release_mrsh.c>
157