Received: by 2002:a25:ef43:0:0:0:0:0 with SMTP id w3csp175787ybm; Tue, 26 May 2020 13:48:55 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyIiS+DueHGxf+spKLb9eLaLa8J1hgvnYdBng7hGu0W1Agt3+fixaAnkAz9wV5OiDlxAum3 X-Received: by 2002:a17:906:18e9:: with SMTP id e9mr2661458ejf.140.1590526134983; Tue, 26 May 2020 13:48:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1590526134; cv=none; d=google.com; s=arc-20160816; b=Rqp5rMf//BAQJGQTVhWDp27B+j5j32MWhgX23/TqkHTyzl+P4w4Sj0+Guknfqoqsvc +0oeP0L1mntgNPJNSTG8eRMAz7enxIYgBCwuoM8EP0TfYER9r5xrO8xoFvgdDriHNYEZ G6uDTA2XxnOz70phnAMFZI2T9wzsSQ7AwcrsL5z22mpeI12iOYfPdciBEDtLXgEw0jqr qnnHDtLLgJCitguPhojZXvDLqYPC8xBQ0RGuNh+0urgUmKBUu3mcHW1jW1EF3XOBlwhm efjf05/AQNofCU3xa/eVwFfWc7QRc86ZOx+LE6tcf9/UxI6Fa1hX1q0QEvUNAxe4+tnk 2Zmw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=4b4DUcYgweLdkUlpyOfAnLft/+AD8ErCpwzse34n/EE=; b=tHlmUyPdYR4z5lhaPFdiSHk3+M+rvwQ2+P3LPbg7k3/TZ9DVC0eEIw2dDke3KUds/R yc4hsZiaTXBOj46bxViQ/nkN63rFT3uFrWgs+0SwEJiouoM5WO5GlmDse8ir7ObfPXyE HV9HThB07gXhkl3RulfGzSCjPSlERT8smsBts2j4mKmuCYW6RsLz/efwHj9NPKrWIq3w CQBg1KOqZTzYwVnANRYIOyctvf0qHS37WQtyoqvnW8ZsurFlBOaLqxc1479XrbR9MVxx tF8u8g62LAbCxXej6MF9CSHq5aDmFBHINYA/AtFhBZn6CieBX7ZqUsHem4mVZkn6178z Ix3A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=fV9Wki0R; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id f30si558771edj.524.2020.05.26.13.48.31; Tue, 26 May 2020 13:48:54 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=fV9Wki0R; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2404582AbgEZTPw (ORCPT + 99 others); Tue, 26 May 2020 15:15:52 -0400 Received: from mail.kernel.org ([198.145.29.99]:47724 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2404470AbgEZTPr (ORCPT ); Tue, 26 May 2020 15:15:47 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id D691D20776; Tue, 26 May 2020 19:15:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1590520546; bh=SCfhZTIaHqAp/kDN9R0eV/qpGB7J/zlJUu4kD5LbpR4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fV9Wki0ROEZVoDxOUiqdUHkUJ9mLuzpinmfeDpIrOLQ4LLSAUxrHAdQFYaykRe85j Lh/8vJreYHrBt7PjpPzN3Q47mx98OqFy+Wkgqzb3Bj0XhBHA1r7wWOvoBf3dhbd3us Yf5XD0kAtxpje325Jen8IV3zdvfS3E0vQ+vHkX8s= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jann Horn , Andrii Nakryiko , Alexei Starovoitov , Sasha Levin Subject: [PATCH 5.6 123/126] bpf: Prevent mmap()ing read-only maps as writable Date: Tue, 26 May 2020 20:54:20 +0200 Message-Id: <20200526183947.664403627@linuxfoundation.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200526183937.471379031@linuxfoundation.org> References: <20200526183937.471379031@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Andrii Nakryiko [ Upstream commit dfeb376dd4cb2c5004aeb625e2475f58a5ff2ea7 ] As discussed in [0], it's dangerous to allow mapping BPF map, that's meant to be frozen and is read-only on BPF program side, because that allows user-space to actually store a writable view to the page even after it is frozen. This is exacerbated by BPF verifier making a strong assumption that contents of such frozen map will remain unchanged. To prevent this, disallow mapping BPF_F_RDONLY_PROG mmap()'able BPF maps as writable, ever. [0] https://lore.kernel.org/bpf/CAEf4BzYGWYhXdp6BJ7_=9OQPJxQpgug080MMjdSB72i9R+5c6g@mail.gmail.com/ Fixes: fc9702273e2e ("bpf: Add mmap() support for BPF_MAP_TYPE_ARRAY") Suggested-by: Jann Horn Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov Reviewed-by: Jann Horn Link: https://lore.kernel.org/bpf/20200519053824.1089415-1-andriin@fb.com Signed-off-by: Sasha Levin --- kernel/bpf/syscall.c | 17 ++++++++++++++--- tools/testing/selftests/bpf/prog_tests/mmap.c | 13 ++++++++++++- tools/testing/selftests/bpf/progs/test_mmap.c | 8 ++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index e04ea4c8f935..c0ab9bfdf28a 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -629,9 +629,20 @@ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma) mutex_lock(&map->freeze_mutex); - if ((vma->vm_flags & VM_WRITE) && map->frozen) { - err = -EPERM; - goto out; + if (vma->vm_flags & VM_WRITE) { + if (map->frozen) { + err = -EPERM; + goto out; + } + /* map is meant to be read-only, so do not allow mapping as + * writable, because it's possible to leak a writable page + * reference and allows user-space to still modify it after + * freezing, while verifier will assume contents do not change + */ + if (map->map_flags & BPF_F_RDONLY_PROG) { + err = -EACCES; + goto out; + } } /* set default open/close callbacks */ diff --git a/tools/testing/selftests/bpf/prog_tests/mmap.c b/tools/testing/selftests/bpf/prog_tests/mmap.c index b0e789678aa4..5495b669fccc 100644 --- a/tools/testing/selftests/bpf/prog_tests/mmap.c +++ b/tools/testing/selftests/bpf/prog_tests/mmap.c @@ -19,7 +19,7 @@ void test_mmap(void) const size_t map_sz = roundup_page(sizeof(struct map_data)); const int zero = 0, one = 1, two = 2, far = 1500; const long page_size = sysconf(_SC_PAGE_SIZE); - int err, duration = 0, i, data_map_fd; + int err, duration = 0, i, data_map_fd, rdmap_fd; struct bpf_map *data_map, *bss_map; void *bss_mmaped = NULL, *map_mmaped = NULL, *tmp1, *tmp2; struct test_mmap__bss *bss_data; @@ -36,6 +36,17 @@ void test_mmap(void) data_map = skel->maps.data_map; data_map_fd = bpf_map__fd(data_map); + rdmap_fd = bpf_map__fd(skel->maps.rdonly_map); + tmp1 = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, rdmap_fd, 0); + if (CHECK(tmp1 != MAP_FAILED, "rdonly_write_mmap", "unexpected success\n")) { + munmap(tmp1, 4096); + goto cleanup; + } + /* now double-check if it's mmap()'able at all */ + tmp1 = mmap(NULL, 4096, PROT_READ, MAP_SHARED, rdmap_fd, 0); + if (CHECK(tmp1 == MAP_FAILED, "rdonly_read_mmap", "failed: %d\n", errno)) + goto cleanup; + bss_mmaped = mmap(NULL, bss_sz, PROT_READ | PROT_WRITE, MAP_SHARED, bpf_map__fd(bss_map), 0); if (CHECK(bss_mmaped == MAP_FAILED, "bss_mmap", diff --git a/tools/testing/selftests/bpf/progs/test_mmap.c b/tools/testing/selftests/bpf/progs/test_mmap.c index 6239596cd14e..4eb42cff5fe9 100644 --- a/tools/testing/selftests/bpf/progs/test_mmap.c +++ b/tools/testing/selftests/bpf/progs/test_mmap.c @@ -7,6 +7,14 @@ char _license[] SEC("license") = "GPL"; +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 4096); + __uint(map_flags, BPF_F_MMAPABLE | BPF_F_RDONLY_PROG); + __type(key, __u32); + __type(value, char); +} rdonly_map SEC(".maps"); + struct { __uint(type, BPF_MAP_TYPE_ARRAY); __uint(max_entries, 512 * 4); /* at least 4 pages of data */ -- 2.25.1