All of lore.kernel.org
 help / color / mirror / Atom feed
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.