From ea7e2d5e49c05e5db1922387b09ca74aa40f46e2 Mon Sep 17 00:00:00 2001 From: Shu Han Date: Tue, 17 Sep 2024 17:41:04 +0800 Subject: mm: call the security_mmap_file() LSM hook in remap_file_pages() The remap_file_pages syscall handler calls do_mmap() directly, which doesn't contain the LSM security check. And if the process has called personality(READ_IMPLIES_EXEC) before and remap_file_pages() is called for RW pages, this will actually result in remapping the pages to RWX, bypassing a W^X policy enforced by SELinux. So we should check prot by security_mmap_file LSM hook in the remap_file_pages syscall handler before do_mmap() is called. Otherwise, it potentially permits an attacker to bypass a W^X policy enforced by SELinux. The bypass is similar to CVE-2016-10044, which bypass the same thing via AIO and can be found in [1]. The PoC: $ cat > test.c int main(void) { size_t pagesz = sysconf(_SC_PAGE_SIZE); int mfd = syscall(SYS_memfd_create, "test", 0); const char *buf = mmap(NULL, 4 * pagesz, PROT_READ | PROT_WRITE, MAP_SHARED, mfd, 0); unsigned int old = syscall(SYS_personality, 0xffffffff); syscall(SYS_personality, READ_IMPLIES_EXEC | old); syscall(SYS_remap_file_pages, buf, pagesz, 0, 2, 0); syscall(SYS_personality, old); // show the RWX page exists even if W^X policy is enforced int fd = open("/proc/self/maps", O_RDONLY); unsigned char buf2[1024]; while (1) { int ret = read(fd, buf2, 1024); if (ret <= 0) break; write(1, buf2, ret); } close(fd); } $ gcc test.c -o test $ ./test | grep rwx 7f1836c34000-7f1836c35000 rwxs 00002000 00:01 2050 /memfd:test (deleted) Link: https://project-zero.issues.chromium.org/issues/42452389 [1] Cc: stable@vger.kernel.org Signed-off-by: Shu Han Acked-by: Stephen Smalley [PM: subject line tweaks] Signed-off-by: Paul Moore --- mm/mmap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mm/mmap.c b/mm/mmap.c index d0dfc85b209b..18fddcce03b8 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -3198,8 +3198,12 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, flags |= MAP_LOCKED; file = get_file(vma->vm_file); + ret = security_mmap_file(vma->vm_file, prot, flags); + if (ret) + goto out_fput; ret = do_mmap(vma->vm_file, start, size, prot, flags, 0, pgoff, &populate, NULL); +out_fput: fput(file); out: mmap_write_unlock(mm); -- cgit v1.2.3 From 8a23c9e1ba4642b60420e8caa75859883a509c24 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 19 Sep 2024 11:37:11 -0400 Subject: selinux,smack: properly reference the LSM blob in security_watch_key() Unfortunately when we migrated the lifecycle management of the key LSM blob to the LSM framework we forgot to convert the security_watch_key() callbacks for SELinux and Smack. This patch corrects this by making use of the selinux_key() and smack_key() helper functions respectively. This patch also removes some input checking in the Smack callback as it is no longer needed. Fixes: 5f8d28f6d7d5 ("lsm: infrastructure management of the key security blob") Reported-by: syzbot+044fdf24e96093584232@syzkaller.appspotmail.com Tested-by: syzbot+044fdf24e96093584232@syzkaller.appspotmail.com Reviewed-by: Casey Schaufler Signed-off-by: Paul Moore --- security/selinux/hooks.c | 2 +- security/smack/smack_lsm.c | 13 +++---------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 81fbfa5b80d4..67baa487cf7a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6720,7 +6720,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) #ifdef CONFIG_KEY_NOTIFICATIONS static int selinux_watch_key(struct key *key) { - struct key_security_struct *ksec = key->security; + struct key_security_struct *ksec = selinux_key(key); u32 sid = current_sid(); return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, KEY__VIEW, NULL); diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index da0c2bffbd08..563fb404f659 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4629,16 +4629,9 @@ static int smack_watch_key(struct key *key) { struct smk_audit_info ad; struct smack_known *tkp = smk_of_current(); + struct smack_known **blob = smack_key(key); int rc; - if (key == NULL) - return -EINVAL; - /* - * If the key hasn't been initialized give it access so that - * it may do so. - */ - if (key->security == NULL) - return 0; /* * This should not occur */ @@ -4653,8 +4646,8 @@ static int smack_watch_key(struct key *key) ad.a.u.key_struct.key = key->serial; ad.a.u.key_struct.key_desc = key->description; #endif - rc = smk_access(tkp, key->security, MAY_READ, &ad); - rc = smk_bu_note("key watch", tkp, key->security, MAY_READ, rc); + rc = smk_access(tkp, *blob, MAY_READ, &ad); + rc = smk_bu_note("key watch", tkp, *blob, MAY_READ, rc); return rc; } #endif /* CONFIG_KEY_NOTIFICATIONS */ -- cgit v1.2.3 From f89722faa31466ff41aed21bdeb9cf34c2312858 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 22 Sep 2024 07:52:26 -0700 Subject: ipe: Add missing terminator to list of unit tests Add missing terminator to list of unit tests to avoid random crashes seen when running the test. Fixes: 10ca05a76065 ("ipe: kunit test for parser") Cc: Deven Bowers Cc: Paul Moore Cc: Fan Wu Signed-off-by: Guenter Roeck Acked-by: Fan Wu Signed-off-by: Paul Moore --- security/ipe/policy_tests.c | 1 + 1 file changed, 1 insertion(+) diff --git a/security/ipe/policy_tests.c b/security/ipe/policy_tests.c index 89521f6b9994..5f1654deeb04 100644 --- a/security/ipe/policy_tests.c +++ b/security/ipe/policy_tests.c @@ -286,6 +286,7 @@ static void ipe_parser_widestring_test(struct kunit *test) static struct kunit_case ipe_parser_test_cases[] = { KUNIT_CASE_PARAM(ipe_parser_unsigned_test, ipe_policies_gen_params), KUNIT_CASE(ipe_parser_widestring_test), + { } }; static struct kunit_suite ipe_parser_test_suite = { -- cgit v1.2.3