PZ issue 735
作者:retme 发布时间:February 26, 2016 分类:AndroidSec
一个iovec最大长度是被规定为MAX_RW_COUNT,这个检查由vfs中的rw_copy_check_uvector去做
但是在aio中,命令IOCB_CMD_PWRITE会让buffer被aio_setup_single_vector组装成一个iovec
io_submit -> aio_run_iocb -> aio_setup_single_vector
static ssize_t aio_setup_single_vector(int rw, struct kiocb *kiocb) { if (unlikely(!access_ok(!rw, kiocb->ki_buf, kiocb->ki_nbytes))) return -EFAULT; kiocb->ki_iovec = &kiocb->ki_inline_vec; kiocb->ki_iovec->iov_base = kiocb->ki_buf; kiocb->ki_iovec->iov_len = kiocb->ki_nbytes; kiocb->ki_nr_segs = 1; return 0; }
kiocb是用户态参数iocb的内核拷贝,所以kiocb->ki_nbytes是用户可控的值,没有校验iov_len是否大于MAX_RW_COUNT(MAX_RW_COUNT=0x7FFFF000)
所以在64位机器上可以设置iov_len为0xffffffff,且绕过access_ok的检查.
static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb, struct file *file, const struct iovec *iov, unsigned long nr_segs) static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len = 0xffffffff) in pppol2tp_sendmsg skb = sock_wmalloc(sk, NET_SKB_PAD + sizeof(struct iphdr) + uhlen + session->hdr_len + sizeof(ppph) + total_len, 0, GFP_KERNEL); struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, gfp_t priority) { if (force || atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) { struct sk_buff *skb = alloc_skb(size, priority); if (skb) { skb_set_owner_w(skb, sk); return skb; } } return NULL; }
那么在alloc_skb中,把size_t len 转成了int len
skbuff会变得很小,skbuff后面的内存会被写入。
不过对硬件内存要求很高,一般安卓机肯定卡爆
https://code.google.com/p/google-security-research/issues/detail?id=735&can=1&start=500
评论已关闭