Re: GPF in shm_lock ipc

From: Kirill A. Shutemov
Date: Mon Oct 12 2015 - 08:27:11 EST


On Mon, Oct 12, 2015 at 11:55:44AM +0200, Dmitry Vyukov wrote:
> Hello,
>
> The following program crashes kernel:
>
> // autogenerated by syzkaller (http://github.com/google/syzkaller)
> #include <syscall.h>
> #include <string.h>
> #include <stdint.h>
>
> int main()
> {
> long r0 = syscall(SYS_shmget, 0x0ul, 0x2ul, 0x8ul);
> long r1 = syscall(SYS_shmat, r0, 0x20000000ul, 0x0ul);
> long r2 = syscall(SYS_mremap, 0x20000000ul, 0x1000ul,
> 0x3000ul, 0x3ul, 0x207f9000ul);
> long r19 = syscall(SYS_shmctl, r0, 0x0ul, 0);
> long r20 = syscall(SYS_remap_file_pages, 0x207f9000ul,
> 0x3000ul, 0x0ul, 0x7ul, 0x0ul);
> return 0;
> }

Here's slightly simplified and more human readable reproducer:

#define _GNU_SOURCE
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/shm.h>

#define PAGE_SIZE 4096

int main()
{
int id;
void *p;

id = shmget(IPC_PRIVATE, 3 * PAGE_SIZE, 0);
p = shmat(id, NULL, 0);
shmctl(id, IPC_RMID, NULL);
remap_file_pages(p, 3 * PAGE_SIZE, 0, 7, 0);

return 0;
}

>
> On commit dd36d7393d6310b0c1adefb22fba79c3cf8a577c
> (git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git)
>
> ------------[ cut here ]------------
> WARNING: CPU: 2 PID: 2636 at ipc/shm.c:162 shm_open+0x74/0x80()
> Modules linked in:
> CPU: 2 PID: 2636 Comm: a.out Not tainted 4.3.0-rc3+ #37
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
> ffffffff81bcb43c ffff88081bf0bd70 ffffffff812fe8d6 0000000000000000
> ffff88081bf0bda8 ffffffff81051ff1 ffffffffffffffea ffff88081b896ca8
> ffff880819b81620 ffff8800bbaa6d00 ffff880819b81600 ffff88081bf0bdb8
> Call Trace:
> [< inline >] __dump_stack lib/dump_stack.c:15
> [<ffffffff812fe8d6>] dump_stack+0x44/0x5e lib/dump_stack.c:50
> [<ffffffff81051ff1>] warn_slowpath_common+0x81/0xc0 kernel/panic.c:447
> [<ffffffff810520e5>] warn_slowpath_null+0x15/0x20 kernel/panic.c:480
> [< inline >] shm_lock ipc/shm.c:162
> [<ffffffff81295c64>] shm_open+0x74/0x80 ipc/shm.c:196
> [<ffffffff81295cbe>] shm_mmap+0x4e/0x80 ipc/shm.c:399 (discriminator 2)
> [<ffffffff81142d14>] mmap_region+0x3c4/0x5e0 mm/mmap.c:1627
> [<ffffffff81143227>] do_mmap+0x2f7/0x3d0 mm/mmap.c:1402
> [< inline >] do_mmap_pgoff include/linux/mm.h:1930
> [< inline >] SYSC_remap_file_pages mm/mmap.c:2694
> [<ffffffff811434a9>] SyS_remap_file_pages+0x179/0x240 mm/mmap.c:2641
> [<ffffffff81859a97>] entry_SYSCALL_64_fastpath+0x12/0x6a
> arch/x86/entry/entry_64.S:185
> ---[ end trace 0873e743fc645a8c ]---

Okay. The problem is that SysV IPC SHM doesn't expect the memory region to
be mmap'ed after IPC_RMID, but remap_file_pages() manages to create new
VMA using existing one.

I'm not sure what the right way to fix it. The SysV SHM VMA is pretty
normal from mm POV (no special flags, etc.) and it meats remap_file_pages
criteria (shared mapping). Every fix I can think of on mm side is ugly.

Probably better to teach shm_mmap() to fall off gracefully in case of
non-existing shmid? I'm not familiar with IPC code.
Could anyone look into it?

--
Kirill A. Shutemov
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/