Comment 0 for bug 1883840

Revision history for this message
Hadar Manor (hadarm) wrote :

I found this exploitable bug in Linux Kernel which affects all ubuntu distributions,
I have responsibly disclosed and patched a pretty similar bug in late 2017, you can
see the work here : https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-3.2.y&id=e23d13a89d8ca5fe717d75248672e1b8bc4a3be8.
But the bug appears again in a different look and still affect the kernel.

The problem is when the sock object gets cloned via dccp_create_openreq_child(),
it gives all its attributes to the child sock object, and no reference counter
is taken for the object dccps_hc_tx_ccid.
If one of the sock objects (the parent or the cahild) is closes or disconnected,
it frees the target objects dccps_hc_tx_ccid and provides us a dagling pointer in the other sock object.
This causes an exploitable double free for an object contains function pointers.

We can free dccps_hc_tx_ccid by calling connect(AF_UNSPEC),then spray the heap with other allocations,
then call close() we'll potentially have a RIP control.

This chunk of code is the responsible of freeing dccps_hc_tx_ccid, if called again it will call
ccid_hc_tx_exit() from a freed object

void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk)
{
 if (ccid != NULL) {
  if (ccid->ccid_ops->ccid_hc_tx_exit != NULL)
   ccid->ccid_ops->ccid_hc_tx_exit(sk); // <-- Calling a function pointer
  kmem_cache_free(ccid->ccid_ops->ccid_hc_tx_slab, ccid);
 }
}

disassembly :

(gdb) disas ccid_hc_tx_delete
Dump of assembler code for function ccid_hc_tx_delete:
   0xffffffff81a7a3a0 <+0>: test rdi,rdi
   0xffffffff81a7a3a3 <+3>: je 0xffffffff81a7a3cd <ccid_hc_tx_delete+45>
   0xffffffff81a7a3a5 <+5>: push rbx
   0xffffffff81a7a3a6 <+6>: mov rbx,rdi
   0xffffffff81a7a3a9 <+9>: mov rdi,rsi
   0xffffffff81a7a3ac <+12>: mov rax,QWORD PTR [rbx]

   0xffffffff81a7a3af <+15>: mov rdx,QWORD PTR [rax+0x80] <— rax points to a freed object

   0xffffffff81a7a3b6 <+22>: test rdx,rdx
   0xffffffff81a7a3b9 <+25>: je 0xffffffff81a7a3c0 <ccid_hc_tx_delete+32>

   0xffffffff81a7a3bb <+27>: call rdx // <-- arbitrary call

   0xffffffff81a7a3bd <+29>: mov rax,QWORD PTR [rbx]
   0xffffffff81a7a3c0 <+32>: mov rsi,rbx
   0xffffffff81a7a3c3 <+35>: mov rdi,QWORD PTR [rax+0x18]
   0xffffffff81a7a3c7 <+39>: pop rbx
   0xffffffff81a7a3c8 <+40>: jmp 0xffffffff811fb980 <kmem_cache_free>
   0xffffffff81a7a3cd <+45>: repz ret
End of assembler dump.