Commit a447da7
tls: fix use-after-free in tls_push_record
syzkaller managed to trigger a use-after-free in tls like the
following:
BUG: KASAN: use-after-free in tls_push_record.constprop.15+0x6a2/0x810 [tls]
Write of size 1 at addr ffff88037aa08000 by task a.out/2317
CPU: 3 PID: 2317 Comm: a.out Not tainted 4.17.0+ torvalds#144
Hardware name: LENOVO 20FBCTO1WW/20FBCTO1WW, BIOS N1FET47W (1.21 ) 11/28/2016
Call Trace:
dump_stack+0x71/0xab
print_address_description+0x6a/0x280
kasan_report+0x258/0x380
? tls_push_record.constprop.15+0x6a2/0x810 [tls]
tls_push_record.constprop.15+0x6a2/0x810 [tls]
tls_sw_push_pending_record+0x2e/0x40 [tls]
tls_sk_proto_close+0x3fe/0x710 [tls]
? tcp_check_oom+0x4c0/0x4c0
? tls_write_space+0x260/0x260 [tls]
? kmem_cache_free+0x88/0x1f0
inet_release+0xd6/0x1b0
__sock_release+0xc0/0x240
sock_close+0x11/0x20
__fput+0x22d/0x660
task_work_run+0x114/0x1a0
do_exit+0x71a/0x2780
? mm_update_next_owner+0x650/0x650
? handle_mm_fault+0x2f5/0x5f0
? __do_page_fault+0x44f/0xa50
? mm_fault_error+0x2d0/0x2d0
do_group_exit+0xde/0x300
__x64_sys_exit_group+0x3a/0x50
do_syscall_64+0x9a/0x300
? page_fault+0x8/0x30
entry_SYSCALL_64_after_hwframe+0x44/0xa9
This happened through fault injection where aead_req allocation in
tls_do_encryption() eventually failed and we returned -ENOMEM from
the function. Turns out that the use-after-free is triggered from
tls_sw_sendmsg() in the second tls_push_record(). The error then
triggers a jump to waiting for memory in sk_stream_wait_memory()
resp. returning immediately in case of MSG_DONTWAIT. What follows is
the trim_both_sgl(sk, orig_size), which drops elements from the sg
list added via tls_sw_sendmsg(). Now the use-after-free gets triggered
when the socket is being closed, where tls_sk_proto_close() callback
is invoked. The tls_complete_pending_work() will figure that there's
a pending closed tls record to be flushed and thus calls into the
tls_push_pending_closed_record() from there. ctx->push_pending_record()
is called from the latter, which is the tls_sw_push_pending_record()
from sw path. This again calls into tls_push_record(). And here the
tls_fill_prepend() will panic since the buffer address has been freed
earlier via trim_both_sgl(). One way to fix it is to move the aead
request allocation out of tls_do_encryption() early into tls_push_record().
This means we don't prep the tls header and advance state to the
TLS_PENDING_CLOSED_RECORD before allocation which could potentially
fail happened. That fixes the issue on my side.
Fixes: 3c4d755 ("tls: kernel TLS support")
Reported-by: [email protected]
Reported-by: [email protected]
Signed-off-by: Daniel Borkmann <[email protected]>
Acked-by: Dave Watson <[email protected]>
Signed-off-by: David S. Miller <[email protected]>1 parent 695ad87 commit a447da7
1 file changed
+13
-13
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
191 | 191 | | |
192 | 192 | | |
193 | 193 | | |
194 | | - | |
195 | | - | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
196 | 197 | | |
197 | | - | |
198 | | - | |
199 | | - | |
200 | 198 | | |
201 | 199 | | |
202 | | - | |
203 | | - | |
204 | | - | |
205 | | - | |
206 | 200 | | |
207 | 201 | | |
208 | 202 | | |
| |||
219 | 213 | | |
220 | 214 | | |
221 | 215 | | |
222 | | - | |
223 | 216 | | |
224 | 217 | | |
225 | 218 | | |
| |||
228 | 221 | | |
229 | 222 | | |
230 | 223 | | |
| 224 | + | |
231 | 225 | | |
232 | 226 | | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
233 | 232 | | |
234 | 233 | | |
235 | 234 | | |
| |||
245 | 244 | | |
246 | 245 | | |
247 | 246 | | |
248 | | - | |
249 | | - | |
| 247 | + | |
250 | 248 | | |
251 | 249 | | |
252 | 250 | | |
253 | 251 | | |
254 | 252 | | |
255 | 253 | | |
256 | | - | |
| 254 | + | |
257 | 255 | | |
258 | 256 | | |
259 | 257 | | |
| |||
268 | 266 | | |
269 | 267 | | |
270 | 268 | | |
| 269 | + | |
| 270 | + | |
271 | 271 | | |
272 | 272 | | |
273 | 273 | | |
| |||
0 commit comments