From nobody Fri Oct 04 15:57:11 2024 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4XKtTg3yDCz5XxX7; Fri, 04 Oct 2024 15:57:11 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4XKtTg16tjz41Dr; Fri, 4 Oct 2024 15:57:11 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1728057431; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=ol1+sqXsu0ObINMeHsGamq+lgA6jZFKPS90BTgjSnJU=; b=pJHWKbiFKmyWsE0ok7XhaXvC/682Qwy9N8faFz036hPyY5cLow806Z4Z8Me+gTw350yCp5 TYfyBWJZWXtGVW63Q5VPAoVsDU6M6F/bpsC5iuxGFEjYMt2OOcfeT6TRXyetAT54HZgrmS DKF+KAtOokHGhBvB6LjbLDi0PtOCuHepIt64mbsGpBlZOpaTNKQPr+taW7hj1ugD1fpXgg 95V7NPsy55hHu3cfJMYjp2pYnnn+/rSCTI/G4oF3GHye49KFZCb8SNSxlnrUcrVyqZe5mK d4hV37uKzXt6NVGsQQ8Po7dgMvZ33Ns+YinoOEHZ703NSC8q6XJjrDTPm2czKA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1728057431; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=ol1+sqXsu0ObINMeHsGamq+lgA6jZFKPS90BTgjSnJU=; b=nYMo7unh8rTqwMImKdJfPArD2h2VUvzXnPk/CnwRYyVwUXh47V3n/8q0WHojOW7X/7/in1 m2yrqS14+6oLaPna0vcJ1fJTvx++Ciiwmy/tXG2mGqzPmLcuLJRqwAxu5vCrT7qiyYAGUJ uBNdWcPg3CyPJeoqM5zaq/M3e+OsgRnPAEkKDcG7C05vIP9K5He52gqBBCqNXRTWIJwXSw xqM4MihjMv3k1gjUZzGCbLVj06eS1niRkA6zpJhLmdKJX2V/zKsrSdNYNrcATuLh3TX70k licBD9/pMU7BB/n9GSeJj0GE9M/qQqwXhLUpxGI/RjC2TZDqo0YbnGBTK0dhbg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1728057431; a=rsa-sha256; cv=none; b=l4H9Uq/8/eD4M+r9UKGAZQqrmzQGbKzzrRTCTEJvMSFSHo5XGe7Xn5sBYTvcNqM3WnYFZ4 dpfudTAk3TNGMLgMPWw/VO+i824wUjLBUJD6YFjQF8UO3irshq/z8xprOxppnOPj8UoecX ZCmugjbo0DEoZhmIWQFLAC7vgw2dEl9Q5KU7fYGViqeYBnHo/gyNi439WqgwEXtoIz8Tr1 n9VmmFGStwHM/425Lakk0NyMzpDzfZw13TSQY93bVoNSo+HJbrwk3WdPjMrfWwJhT9NafI PZxZ2fZMONQyA1MMbPFZm96SeWbQlLbk5Y/gUhYbA0baJOuvPATpX913eQtTYQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4XKtTg0jjWzhCW; Fri, 4 Oct 2024 15:57:11 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 494FvB5H048825; Fri, 4 Oct 2024 15:57:11 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 494FvBGg048822; Fri, 4 Oct 2024 15:57:11 GMT (envelope-from git) Date: Fri, 4 Oct 2024 15:57:11 GMT Message-Id: <202410041557.494FvBGg048822@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mark Johnston Subject: git: 33c2c58f0a3d - main - shm: Respect PROT_MAX when creating private mappings List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 33c2c58f0a3db0a6d3996fa14ac7967274678771 Auto-Submitted: auto-generated The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=33c2c58f0a3db0a6d3996fa14ac7967274678771 commit 33c2c58f0a3db0a6d3996fa14ac7967274678771 Author: Mark Johnston AuthorDate: 2024-10-04 14:54:44 +0000 Commit: Mark Johnston CommitDate: 2024-10-04 15:56:34 +0000 shm: Respect PROT_MAX when creating private mappings We were previously unconditionally adding PROT_WRITE to the maxprot of private mapping (because a private mapping can be written even if the fd is read-only), but this might violate the user's PROT_MAX request. While here, rename cap_maxprot to max_maxprot. This is the intersection of the maximum protections imposed by capsicum rights on the fd (not really relevant for private mappings) and the user-required maximum protections (which were not being obeyed). In particular, cap_maxprot is a misnomer after the introduction of PROT_MAX. Add some regression test cases. mmap__maxprot_shm fails without this patch. Note: Capsicum's CAP_MMAP_W is a bit ambiguous. Should it be required in order to create writeable private mappings? Currently it is, even though such mappings don't permit writes to the object referenced by the fd. Reported by: brooks Reviewed by: brooks MFC after: 1 month Fixes: c7841c6b8e41 ("Relax restrictions on private mappings of POSIX shm objects.") Differential Revision: https://reviews.freebsd.org/D46741 --- sys/kern/uipc_shm.c | 8 ++--- tests/sys/posixshm/posixshm_test.c | 29 +++++++++++++++- tests/sys/vm/mmap_test.c | 70 +++++++++++++++++++++++++++++++++++++- 3 files changed, 101 insertions(+), 6 deletions(-) diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index 49b5b56dee17..a5b2e62c568e 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -1658,7 +1658,7 @@ fail: static int shm_mmap(struct file *fp, vm_map_t map, vm_offset_t *addr, vm_size_t objsize, - vm_prot_t prot, vm_prot_t cap_maxprot, int flags, + vm_prot_t prot, vm_prot_t max_maxprot, int flags, vm_ooffset_t foff, struct thread *td) { struct shmfd *shmfd; @@ -1681,8 +1681,8 @@ shm_mmap(struct file *fp, vm_map_t map, vm_offset_t *addr, vm_size_t objsize, * writeable. */ if ((flags & MAP_SHARED) == 0) { - cap_maxprot |= VM_PROT_WRITE; - maxprot |= VM_PROT_WRITE; + if ((max_maxprot & VM_PROT_WRITE) != 0) + maxprot |= VM_PROT_WRITE; writecnt = false; } else { if ((fp->f_flag & FWRITE) != 0 && @@ -1702,7 +1702,7 @@ shm_mmap(struct file *fp, vm_map_t map, vm_offset_t *addr, vm_size_t objsize, goto out; } } - maxprot &= cap_maxprot; + maxprot &= max_maxprot; /* See comment in vn_mmap(). */ if ( diff --git a/tests/sys/posixshm/posixshm_test.c b/tests/sys/posixshm/posixshm_test.c index ade07a118707..55514a5f4bde 100644 --- a/tests/sys/posixshm/posixshm_test.c +++ b/tests/sys/posixshm/posixshm_test.c @@ -1190,6 +1190,33 @@ ATF_TC_BODY(accounting, tc) ATF_REQUIRE(close(fd) == 0); } +ATF_TC_WITHOUT_HEAD(mmap_prot); +ATF_TC_BODY(mmap_prot, tc) +{ + void *p; + int fd, pagesize; + + ATF_REQUIRE((pagesize = getpagesize()) > 0); + + gen_test_path(); + fd = shm_open(test_path, O_RDONLY | O_CREAT, 0644); + ATF_REQUIRE(fd >= 0); + + p = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0); + ATF_REQUIRE(p != MAP_FAILED); + ATF_REQUIRE(munmap(p, pagesize) == 0); + p = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + ATF_REQUIRE_ERRNO(EACCES, p == MAP_FAILED); + p = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + ATF_REQUIRE(p != MAP_FAILED); + ATF_REQUIRE(munmap(p, pagesize) == 0); + + ATF_REQUIRE_MSG(shm_unlink(test_path) == 0, + "shm_unlink failed; errno=%d", errno); + ATF_REQUIRE_MSG(close(fd) == 0, + "close failed; errno=%d", errno); +} + static int shm_open_large(int psind, int policy, size_t sz) { @@ -1920,7 +1947,6 @@ ATF_TC_BODY(largepage_reopen, tc) ATF_TP_ADD_TCS(tp) { - ATF_TP_ADD_TC(tp, remap_object); ATF_TP_ADD_TC(tp, rename_from_anon); ATF_TP_ADD_TC(tp, rename_bad_path_pointer); @@ -1954,6 +1980,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, fallocate); ATF_TP_ADD_TC(tp, fspacectl); ATF_TP_ADD_TC(tp, accounting); + ATF_TP_ADD_TC(tp, mmap_prot); ATF_TP_ADD_TC(tp, largepage_basic); ATF_TP_ADD_TC(tp, largepage_config); ATF_TP_ADD_TC(tp, largepage_mmap); diff --git a/tests/sys/vm/mmap_test.c b/tests/sys/vm/mmap_test.c index e5f4a81a7858..6bc30f73ca95 100644 --- a/tests/sys/vm/mmap_test.c +++ b/tests/sys/vm/mmap_test.c @@ -295,14 +295,82 @@ ATF_TC_BODY(mmap__write_only, tc) munmap(p, pagesize); } -ATF_TP_ADD_TCS(tp) +ATF_TC_WITHOUT_HEAD(mmap__maxprot_basic); +ATF_TC_BODY(mmap__maxprot_basic, tc) +{ + void *p; + int error, pagesize; + + ATF_REQUIRE((pagesize = getpagesize()) > 0); + + p = mmap(NULL, pagesize, PROT_READ | PROT_MAX(PROT_READ), + MAP_ANON, -1, 0); + ATF_REQUIRE(p != MAP_FAILED); + + error = mprotect(p, pagesize, PROT_WRITE); + ATF_REQUIRE_ERRNO(EACCES, error == -1); + error = mprotect(p, pagesize, PROT_READ | PROT_WRITE); + ATF_REQUIRE_ERRNO(EACCES, error == -1); + error = mprotect(p, pagesize, PROT_READ | PROT_EXEC); + ATF_REQUIRE_ERRNO(EACCES, error == -1); + + ATF_REQUIRE(munmap(p, pagesize) == 0); +} + +/* Make sure that PROT_MAX applies as expected to mappings of shm objects */ +ATF_TC_WITHOUT_HEAD(mmap__maxprot_shm); +ATF_TC_BODY(mmap__maxprot_shm, tc) { + void *p; + int error, fd, pagesize; + + ATF_REQUIRE((pagesize = getpagesize()) > 0); + fd = shm_open(SHM_ANON, O_RDWR, 0644); + ATF_REQUIRE(fd >= 0); + + error = ftruncate(fd, pagesize); + ATF_REQUIRE(error == 0); + + p = mmap(NULL, pagesize, PROT_READ | PROT_MAX(PROT_READ), + MAP_PRIVATE, fd, 0); + ATF_REQUIRE(p != MAP_FAILED); + + error = mprotect(p, pagesize, PROT_WRITE); + ATF_REQUIRE_ERRNO(EACCES, error == -1); + error = mprotect(p, pagesize, PROT_READ | PROT_WRITE); + ATF_REQUIRE_ERRNO(EACCES, error == -1); + error = mprotect(p, pagesize, PROT_READ | PROT_EXEC); + ATF_REQUIRE_ERRNO(EACCES, error == -1); + + ATF_REQUIRE(munmap(p, pagesize) == 0); + + /* Again, this time with a shared mapping. */ + p = mmap(NULL, pagesize, PROT_READ | PROT_MAX(PROT_READ), + MAP_SHARED, fd, 0); + ATF_REQUIRE(p != MAP_FAILED); + + error = mprotect(p, pagesize, PROT_WRITE); + ATF_REQUIRE_ERRNO(EACCES, error == -1); + error = mprotect(p, pagesize, PROT_READ | PROT_WRITE); + ATF_REQUIRE_ERRNO(EACCES, error == -1); + error = mprotect(p, pagesize, PROT_READ | PROT_EXEC); + ATF_REQUIRE_ERRNO(EACCES, error == -1); + + ATF_REQUIRE(munmap(p, pagesize) == 0); + + ATF_REQUIRE(close(fd) == 0); +} + +ATF_TP_ADD_TCS(tp) +{ ATF_TP_ADD_TC(tp, mmap__map_at_zero); ATF_TP_ADD_TC(tp, mmap__bad_arguments); ATF_TP_ADD_TC(tp, mmap__dev_zero_private); ATF_TP_ADD_TC(tp, mmap__dev_zero_shared); ATF_TP_ADD_TC(tp, mmap__write_only); + ATF_TP_ADD_TC(tp, mmap__maxprot_basic); + ATF_TP_ADD_TC(tp, mmap__maxprot_shm); return (atf_no_error()); }