• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: MIT */
2 
3 #include "liburing/sanitize.h"
4 
5 #include <sanitizer/asan_interface.h>
6 #include <stdlib.h>
7 #include "liburing.h"
8 
sanitize_sqe_addr(struct io_uring_sqe * sqe)9 static inline void sanitize_sqe_addr(struct io_uring_sqe *sqe)
10 {
11 	if (__asan_address_is_poisoned((void *) (unsigned long) sqe->addr) != 0) {
12 		__asan_describe_address((void *) (unsigned long) sqe->addr);
13 		exit(1);
14 	}
15 }
sanitize_sqe_optval(struct io_uring_sqe * sqe)16 static inline void sanitize_sqe_optval(struct io_uring_sqe *sqe)
17 {
18 	if (__asan_region_is_poisoned((void *) (unsigned long) sqe->optval, sqe->optlen) != 0) {
19 		__asan_describe_address((void *) (unsigned long) sqe->optval);
20 		exit(1);
21 	}
22 }
sanitize_sqe_addr2(struct io_uring_sqe * sqe)23 static inline void sanitize_sqe_addr2(struct io_uring_sqe *sqe)
24 {
25 	if (__asan_address_is_poisoned((void *) (unsigned long) sqe->addr2) != 0) {
26 		__asan_describe_address((void *) (unsigned long) sqe->addr2);
27 		exit(1);
28 	}
29 }
sanitize_sqe_addr3(struct io_uring_sqe * sqe)30 static inline void sanitize_sqe_addr3(struct io_uring_sqe *sqe)
31 {
32 	if (__asan_address_is_poisoned((void *) (unsigned long) sqe->addr3) != 0) {
33 		__asan_describe_address((void *) (unsigned long) sqe->addr3);
34 		exit(1);
35 	}
36 }
sanitize_sqe_addr_and_add2(struct io_uring_sqe * sqe)37 static inline void sanitize_sqe_addr_and_add2(struct io_uring_sqe *sqe)
38 {
39 	sanitize_sqe_addr(sqe);
40 	sanitize_sqe_addr2(sqe);
41 }
sanitize_sqe_addr_and_add3(struct io_uring_sqe * sqe)42 static inline void sanitize_sqe_addr_and_add3(struct io_uring_sqe *sqe)
43 {
44 	sanitize_sqe_addr(sqe);
45 	sanitize_sqe_addr3(sqe);
46 }
sanitize_sqe_nop(struct io_uring_sqe * sqe)47 static inline void sanitize_sqe_nop(struct io_uring_sqe *sqe)
48 {
49 }
50 
51 typedef void (*sanitize_sqe_handler)(struct io_uring_sqe *sqe);
52 sanitize_sqe_handler sanitize_handlers[IORING_OP_LAST];
53 bool sanitize_handlers_initialized = false;
54 
initialize_sanitize_handlers()55 static inline void initialize_sanitize_handlers()
56 {
57 	if (sanitize_handlers_initialized)
58 		return;
59 
60 	sanitize_handlers[IORING_OP_NOP] = sanitize_sqe_nop;
61 	sanitize_handlers[IORING_OP_READV] = sanitize_sqe_addr;
62 	sanitize_handlers[IORING_OP_WRITEV] = sanitize_sqe_addr;
63 	sanitize_handlers[IORING_OP_FSYNC] = sanitize_sqe_addr;
64 	sanitize_handlers[IORING_OP_READ_FIXED] = sanitize_sqe_addr;
65 	sanitize_handlers[IORING_OP_WRITE_FIXED] = sanitize_sqe_addr;
66 	sanitize_handlers[IORING_OP_POLL_ADD] = sanitize_sqe_addr;
67 	sanitize_handlers[IORING_OP_POLL_REMOVE] = sanitize_sqe_nop;
68 	sanitize_handlers[IORING_OP_SYNC_FILE_RANGE] = sanitize_sqe_addr;
69 	sanitize_handlers[IORING_OP_SENDMSG] = sanitize_sqe_addr;
70 	sanitize_handlers[IORING_OP_RECVMSG] = sanitize_sqe_addr;
71 	sanitize_handlers[IORING_OP_TIMEOUT] = sanitize_sqe_addr;
72 	sanitize_handlers[IORING_OP_TIMEOUT_REMOVE] = sanitize_sqe_nop;
73 	sanitize_handlers[IORING_OP_ACCEPT] = sanitize_sqe_addr;
74 	sanitize_handlers[IORING_OP_ASYNC_CANCEL] = sanitize_sqe_nop;
75 	sanitize_handlers[IORING_OP_LINK_TIMEOUT] = sanitize_sqe_addr;
76 	sanitize_handlers[IORING_OP_CONNECT] = sanitize_sqe_addr;
77 	sanitize_handlers[IORING_OP_FALLOCATE] = sanitize_sqe_nop;
78 	sanitize_handlers[IORING_OP_OPENAT] = sanitize_sqe_addr;
79 	sanitize_handlers[IORING_OP_CLOSE] = sanitize_sqe_addr;
80 	sanitize_handlers[IORING_OP_FILES_UPDATE] = sanitize_sqe_addr;
81 	sanitize_handlers[IORING_OP_STATX] = sanitize_sqe_addr;
82 	sanitize_handlers[IORING_OP_READ] = sanitize_sqe_addr;
83 	sanitize_handlers[IORING_OP_WRITE] = sanitize_sqe_addr;
84 	sanitize_handlers[IORING_OP_FADVISE] = sanitize_sqe_nop;
85 	sanitize_handlers[IORING_OP_MADVISE] = sanitize_sqe_addr;
86 	sanitize_handlers[IORING_OP_SEND] = sanitize_sqe_addr_and_add2;
87 	sanitize_handlers[IORING_OP_RECV] = sanitize_sqe_addr;
88 	sanitize_handlers[IORING_OP_OPENAT2] = sanitize_sqe_addr;
89 	sanitize_handlers[IORING_OP_EPOLL_CTL] = sanitize_sqe_addr;
90 	sanitize_handlers[IORING_OP_SPLICE] = sanitize_sqe_nop;
91 	sanitize_handlers[IORING_OP_PROVIDE_BUFFERS] = sanitize_sqe_addr;
92 	sanitize_handlers[IORING_OP_REMOVE_BUFFERS] = sanitize_sqe_addr;
93 	sanitize_handlers[IORING_OP_TEE] = sanitize_sqe_nop;
94 	sanitize_handlers[IORING_OP_SHUTDOWN] = sanitize_sqe_addr;
95 	sanitize_handlers[IORING_OP_RENAMEAT] = sanitize_sqe_addr;
96 	sanitize_handlers[IORING_OP_UNLINKAT] = sanitize_sqe_addr;
97 	sanitize_handlers[IORING_OP_MKDIRAT] = sanitize_sqe_addr;
98 	sanitize_handlers[IORING_OP_SYMLINKAT] = sanitize_sqe_addr;
99 	sanitize_handlers[IORING_OP_LINKAT] = sanitize_sqe_addr;
100 	sanitize_handlers[IORING_OP_MSG_RING] = sanitize_sqe_addr_and_add3;
101 	sanitize_handlers[IORING_OP_FSETXATTR] = sanitize_sqe_addr;
102 	sanitize_handlers[IORING_OP_SETXATTR] = sanitize_sqe_addr_and_add3;
103 	sanitize_handlers[IORING_OP_FGETXATTR] = sanitize_sqe_addr;
104 	sanitize_handlers[IORING_OP_GETXATTR] = sanitize_sqe_addr_and_add3;
105 	sanitize_handlers[IORING_OP_SOCKET] = sanitize_sqe_addr;
106 	sanitize_handlers[IORING_OP_URING_CMD] = sanitize_sqe_optval;
107 	sanitize_handlers[IORING_OP_SEND_ZC] = sanitize_sqe_addr;
108 	sanitize_handlers[IORING_OP_SENDMSG_ZC] = sanitize_sqe_addr;
109 	sanitize_handlers[IORING_OP_READ_MULTISHOT] = sanitize_sqe_addr;
110 	sanitize_handlers[IORING_OP_WAITID] = sanitize_sqe_addr_and_add2;
111 	sanitize_handlers[IORING_OP_FUTEX_WAIT] = sanitize_sqe_addr;
112 	sanitize_handlers[IORING_OP_FUTEX_WAKE] = sanitize_sqe_addr;
113 	sanitize_handlers[IORING_OP_FUTEX_WAITV] = sanitize_sqe_addr;
114 	sanitize_handlers[IORING_OP_FIXED_FD_INSTALL] = sanitize_sqe_addr;
115 	sanitize_handlers[IORING_OP_FTRUNCATE] = sanitize_sqe_addr;
116 	sanitize_handlers[IORING_OP_BIND] = sanitize_sqe_addr;
117 	sanitize_handlers[IORING_OP_LISTEN] = sanitize_sqe_addr;
118 	sanitize_handlers_initialized = true;
119 }
120 
liburing_sanitize_ring(struct io_uring * ring)121 void liburing_sanitize_ring(struct io_uring *ring)
122 {
123 	struct io_uring_sq *sq = &ring->sq;
124 	struct io_uring_sqe *sqe;
125 	unsigned int head;
126 	int shift = 0;
127 
128 	initialize_sanitize_handlers();
129 
130 	if (ring->flags & IORING_SETUP_SQE128)
131 		shift = 1;
132 	if (!(ring->flags & IORING_SETUP_SQPOLL))
133 		head = *sq->khead;
134 	else
135 		head = io_uring_smp_load_acquire(sq->khead);
136 
137 	while (head != sq->sqe_tail) {
138 		sqe = &sq->sqes[(head & sq->ring_mask) << shift];
139 		if (sqe->opcode < IORING_OP_LAST)
140 			sanitize_handlers[sqe->opcode](sqe);
141 		head++;
142 	}
143 }
144 
liburing_sanitize_address(const void * addr)145 void liburing_sanitize_address(const void *addr)
146 {
147 	if (__asan_address_is_poisoned(addr) != 0) {
148 		__asan_describe_address((void *)addr);
149 		exit(1);
150 	}
151 }
152 
liburing_sanitize_region(const void * addr,unsigned int len)153 void liburing_sanitize_region(const void *addr, unsigned int len)
154 {
155 	if (__asan_region_is_poisoned((void *)addr, len) != 0) {
156 		__asan_describe_address((void *)addr);
157 		exit(1);
158 	}
159 }
160 
liburing_sanitize_iovecs(const struct iovec * iovecs,unsigned nr)161 void liburing_sanitize_iovecs(const struct iovec *iovecs, unsigned nr)
162 {
163 	unsigned i;
164 
165 	if (__asan_address_is_poisoned((void *)iovecs) != 0) {
166 		__asan_describe_address((void *)iovecs);
167 		exit(1);
168 	}
169 
170 	for (i = 0; i < nr; i++) {
171 		if (__asan_region_is_poisoned((void *)iovecs[i].iov_base, iovecs[i].iov_len) != 0) {
172 			__asan_describe_address((void *)iovecs[i].iov_base);
173 			exit(1);
174 		}
175 	}
176 }
177