From patchwork Mon Oct 14 21:50:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 13835520 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 15EBAD18153 for ; Mon, 14 Oct 2024 21:50:34 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 71F2B6B0083; Mon, 14 Oct 2024 17:50:34 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 6A8AE6B0085; Mon, 14 Oct 2024 17:50:34 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 4D5B86B0088; Mon, 14 Oct 2024 17:50:34 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 2B4B26B0083 for ; Mon, 14 Oct 2024 17:50:34 -0400 (EDT) Received: from smtpin20.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay07.hostedemail.com (Postfix) with ESMTP id B716E160CBB for ; Mon, 14 Oct 2024 21:50:24 +0000 (UTC) X-FDA: 82673552010.20.1B6B23E Received: from mail-pf1-f176.google.com (mail-pf1-f176.google.com [209.85.210.176]) by imf28.hostedemail.com (Postfix) with ESMTP id 726F3C0009 for ; Mon, 14 Oct 2024 21:50:25 +0000 (UTC) Authentication-Results: imf28.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b="C7u8M/J2"; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf28.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.210.176 as permitted sender) smtp.mailfrom=jeffxu@chromium.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1728942585; a=rsa-sha256; cv=none; b=4n3ucMPK+9/drAxKd56bKtdHVbUixLOGOKwHUxSjwEl6E6u+WQt+gbURfwqwt2ek+aPPHd S0CrDTy5uYrKhvQeGdLTISW5QS9MYGLaz3PaDqHOWjNIchjeaMutYjFmAvvBczTIL79VGs zm4JnUHh323ZZFOLv0gCGbzSqeIPO8Y= ARC-Authentication-Results: i=1; imf28.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b="C7u8M/J2"; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf28.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.210.176 as permitted sender) smtp.mailfrom=jeffxu@chromium.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1728942585; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=gCqzm4XprfPZ6h5KSF8yerh8aBwfFdviFsIk/AJKr8Q=; b=SjCweeCmor5eTv0P8BUyq7PTmta1S5HXixqEineC+pwpurrxLh92u+gquQorbDtDnIa7O2 d47VpwUQ+PeDPZm4KgPUUYGKMufsaPc1cZceJAzw9C9ru9GZD7WcZBCMLkz8+NO86aabKp ah2UKtcGIspe0g35VWtwVDbzf1JPwlk= Received: by mail-pf1-f176.google.com with SMTP id d2e1a72fcca58-71e49d5deeeso90084b3a.0 for ; Mon, 14 Oct 2024 14:50:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1728942630; x=1729547430; darn=kvack.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gCqzm4XprfPZ6h5KSF8yerh8aBwfFdviFsIk/AJKr8Q=; b=C7u8M/J2zZT/VBpFGWcVs70LK0bTiFtOSj5lCnCbNOfIdee2tAyZdsN1w3bB1lKY/w pjrVmzlGoKsRNAQkVX5eP5E2JJuJXD0uBqzzzQAkPHQssKPHyfpTk/LvMap7yBT7/an1 OgXNe0crzUuzm6HFbmTcHpbMY4mNqG1g/dTCI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728942630; x=1729547430; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gCqzm4XprfPZ6h5KSF8yerh8aBwfFdviFsIk/AJKr8Q=; b=ck/A3dnEeY8V1wvQiR3hF+2O/IVyZN6+C19vrhUwAyy0QlUXsaybG1oBaftgkRAhyN Z8tS777wtwVmxAtDlzRksdMkUZ0Qa1q3uhAxzf9mHPoxq1235sJ3PWRcCMbSkiwAo39H /YBhmfmzj99desWQ7JobMpZy6xwVijP99em8sWwOf6CSPye0KBHALgU0zZXpFCONb+hI 35CmJ2mYentsAJ3/TdBHBg1ulIWb3v6hmQKt72ZH1UKNkuLfXsiSYu6XhD/i2+ld/+Th 9RX+uLbxBUyYRvqaOslDxrZshXkRiyDQClXks5nYGERsXJ80QqH7L20ANTCmiXlv2QO+ 0RbQ== X-Forwarded-Encrypted: i=1; AJvYcCW6cxGfRvIHMXslwepPSkuzQ/arU6QO7wqMUhfxLQfDVBaz6xtZcz7DTxtL2W1VgPkUO+oA8cT2bQ==@kvack.org X-Gm-Message-State: AOJu0YyyO/H82fgc7yNqFp5wy9PjTqgcvD6AYboNWPlJXUElCUmYboXX TIGRpgzF1CnGgrnIEGh3dIt+fbozx/LE2vhRHV0IhLzG4DbOg9KJl2XADMK/KA== X-Google-Smtp-Source: AGHT+IHJibLG55dv20aw5zAlf9R+lVo01HQFW7VTQTck/5caHO6/ZiNO6n2U3rR/biiiYKEMvgayNg== X-Received: by 2002:a05:6a00:1ad3:b0:71e:5400:1b35 with SMTP id d2e1a72fcca58-71e54001b7bmr4887430b3a.5.1728942630535; Mon, 14 Oct 2024 14:50:30 -0700 (PDT) Received: from localhost (56.4.82.34.bc.googleusercontent.com. [34.82.4.56]) by smtp.gmail.com with UTF8SMTPSA id d2e1a72fcca58-71e4a77cb0bsm5458012b3a.193.2024.10.14.14.50.30 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 14 Oct 2024 14:50:30 -0700 (PDT) From: jeffxu@chromium.org To: akpm@linux-foundation.org, keescook@chromium.org, jannh@google.com, torvalds@linux-foundation.org, adhemerval.zanella@linaro.org, oleg@redhat.com Cc: linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org, linux-mm@kvack.org, jorgelo@chromium.org, sroettger@google.com, ojeda@kernel.org, adobriyan@gmail.com, anna-maria@linutronix.de, mark.rutland@arm.com, linus.walleij@linaro.org, Jason@zx2c4.com, deller@gmx.de, rdunlap@infradead.org, davem@davemloft.net, hch@lst.de, peterx@redhat.com, hca@linux.ibm.com, f.fainelli@gmail.com, gerg@kernel.org, dave.hansen@linux.intel.com, mingo@kernel.org, ardb@kernel.org, Liam.Howlett@Oracle.com, mhocko@suse.com, 42.hyeyoo@gmail.com, peterz@infradead.org, ardb@google.com, enh@google.com, rientjes@google.com, groeck@chromium.org, lorenzo.stoakes@oracle.com, Jeff Xu Subject: [RFC PATCH v2 1/1] exec: seal system mappings Date: Mon, 14 Oct 2024 21:50:20 +0000 Message-ID: <20241014215022.68530-2-jeffxu@google.com> X-Mailer: git-send-email 2.47.0.rc1.288.g06298d1525-goog In-Reply-To: <20241014215022.68530-1-jeffxu@google.com> References: <20241014215022.68530-1-jeffxu@google.com> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Queue-Id: 726F3C0009 X-Rspamd-Server: rspam01 X-Stat-Signature: bc1qwxxnpusdhjwgxcq6wbt14ae1rrqs X-HE-Tag: 1728942625-367327 X-HE-Meta: U2FsdGVkX18eNkryryW+nWPXP9gglt5svOVkJxfNJIP+TigAgvtV2scGcY2mduCuThDACL9xso9xY2+jlezkOiHBD2xmFvNoaBQXjSYsGH+x1j52jk/B9S2JINYfy3EP9q4Hq+zpTDO0hnLp8XYeHrWouAppYLpZ+8Xovb47ztioy2MOCnHDZkBv9ndkrPn2vecvxIZarqy1S+QnGxIOhRvNhWKwy8XeT/lvwLg3WxZ5Fsuhj6rRu0fpN1nYmuQGS5e/PAqsd1KfrtPZhFmlQtLIBxtf/JaBtOhOakNo9635olrfwhPGewX55mWZDYCJKTBoXJc+3KVO/Qe/wIG2wBg4xbvdMM2WGl7jy0sqvhVJpwy0Oo/jkAM6HRvg72NQaguv4MFMi+AbMs3Y6bk45BArMazAJOcQHnsIP86SyWcAqy+DwQm/z3ooB6gcx3OwWAXNp/1ldKYQPU0L0M4DwofEo8Ki3ftqIxCK2VDSXU+5Bfu+aVtTzM4dXhLZ7OMgSMLxXvAvNkWilAUgcu+H/tiyuAGXUH6luPy5WvZXE26UL7JR3QQZWhBgwMLZmPstzhrhwdO0sr3C2iqzLpNanMjgWOgY9LNTAEQbCBHCa/eCr5q8luLM3beyIAvNdVIbKDrGf2POGKNB31yUoaHb10JXNtm52kEs8VzZaTzfdhOCbpgbD/HjTssquy6U7mQ3Quj1f2/C3lgCuOKqhnEoMn2QeNJfjEeVeAMOhzPtvli0S+q2vqlINjxEUqzV/cGvyX5XNmWs1MGwVOJzDrsbcJuV24+ZbPx/kq65eiJ8gQOzpvPu1iT/PGEB9ijmt3SJcinn2P9GBy4Oo27LPbVpfdggm1vJgAtkNMBUithuf9KvnAUZdYsDPzKqT3uqMBVdnf4tvWbu042uMYgnglTgI2bysMAxz+E+TWX/ecOuierjwTRV9IEMHIW10vATIDFyVJFRb/rtl+e+JLxCvVC DgIbwuJi EndIDsRCR/eF98UnSLMICmb2Iw51//ydAhOEI0GdYmR2LTuadOqfKE9g3Q2yYhnR0eB6/95hRYCEep97JOtS5VLd1t51yvY/0/GE8GP+ZCYUIGGPPZFm5dVdfJgeDw1jbl9uDEH8D3Q7yf5gPLgoUhXx65L24Hu9QW0C5yZSuxaCT39ZxyIh4RW1sQjilzY+2GdreV5YDokJ1ZLyaYq8XrmQvwbBl04FMegXJQQ8pSomYPrqC1xSki/bntkGRLSR8gXxBXeaZKllYOpv21LRPlYDM0iPu8z9vPFo+Oa7y0VMKp8Do6js1WfmtEJui8MfrBDiB+c+enumN0aCfVKpXLujwmR3S59j1UvmQT9YCzXMGQuo7JfXiRa8mYA== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: From: Jeff Xu Seal vdso, vvar, sigpage, uprobes and vsyscall. Those mappings are readonly or executable only, sealing can protect them from ever changing during the life time of the process. For complete descriptions of memory sealing, please see mseal.rst [1]. System mappings such as vdso, vvar, and sigpage (for arm) are generated by the kernel during program initialization. These mappings are designated as non-writable, and sealing them will prevent them from ever becoming writeable. Unlike the aforementioned mappings, the uprobe mapping is not established during program startup. However, its lifetime is the same as the process's lifetime [2], thus sealable. The vdso, vvar, sigpage, and uprobe mappings all invoke the _install_special_mapping() function. As no other mappings utilize this function, it is logical to incorporate sealing logic within _install_special_mapping(). This approach avoids the necessity of modifying code across various architecture-specific implementations. The vsyscall mapping, which has its own initialization function, is sealed in the XONLY case, it seems to be the most common and secure case of using vsyscall. It is important to note that the CHECKPOINT_RESTORE feature (CRIU) may alter the mapping of vdso, vvar, and sigpage during restore operations. Consequently, this feature cannot be universally enabled across all systems. To address this, a kernel configuration option has been introduced to enable or disable this functionality. Note, uprobe is always sealed and not controlled by this kernel configuration. [1] Documentation/userspace-api/mseal.rst [2] https://lore.kernel.org/all/CABi2SkU9BRUnqf70-nksuMCQ+yyiWjo3fM4XkRkL-NrCZxYAyg@mail.gmail.com/ Signed-off-by: Jeff Xu --- .../admin-guide/kernel-parameters.txt | 10 ++++ arch/x86/entry/vsyscall/vsyscall_64.c | 9 +++- fs/exec.c | 53 +++++++++++++++++++ include/linux/fs.h | 1 + kernel/events/uprobes.c | 2 +- mm/mmap.c | 1 + security/Kconfig | 26 +++++++++ 7 files changed, 99 insertions(+), 3 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index e7bfe1bde49e..02e5eb23d76f 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -1538,6 +1538,16 @@ Permit 'security.evm' to be updated regardless of current integrity status. + exec.seal_system_mappings = [KNL] + Format: { never | always } + Seal system mappings: vdso, vvar, sigpage, uprobes, + vsyscall. + This overwrites KCONFIG CONFIG_SEAL_SYSTEM_MAPPINGS_* + - 'never': never seal system mappings. + - 'always': always seal system mappings. + If not specified or invalid, default is the KCONFIG value. + This option has no effect if CONFIG_64BIT=n + early_page_ext [KNL,EARLY] Enforces page_ext initialization to earlier stages so cover more early boot allocations. Please note that as side effect some optimizations diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c index 2fb7d53cf333..20a3000550d2 100644 --- a/arch/x86/entry/vsyscall/vsyscall_64.c +++ b/arch/x86/entry/vsyscall/vsyscall_64.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -366,8 +367,12 @@ void __init map_vsyscall(void) set_vsyscall_pgtable_user_bits(swapper_pg_dir); } - if (vsyscall_mode == XONLY) - vm_flags_init(&gate_vma, VM_EXEC); + if (vsyscall_mode == XONLY) { + unsigned long vm_flags = VM_EXEC; + + update_seal_exec_system_mappings(&vm_flags); + vm_flags_init(&gate_vma, vm_flags); + } BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_PAGE) != (unsigned long)VSYSCALL_ADDR); diff --git a/fs/exec.c b/fs/exec.c index 77364806b48d..5030879cda47 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -68,6 +68,7 @@ #include #include #include +#include #include #include @@ -2159,3 +2160,55 @@ fs_initcall(init_fs_exec_sysctls); #ifdef CONFIG_EXEC_KUNIT_TEST #include "tests/exec_kunit.c" #endif + +#ifdef CONFIG_64BIT +/* + * Kernel cmdline overwrite for CONFIG_SEAL_SYSTEM_MAPPINGS_X + */ +enum seal_system_mappings_type { + SEAL_SYSTEM_MAPPINGS_NEVER, + SEAL_SYSTEM_MAPPINGS_ALWAYS +}; + +static enum seal_system_mappings_type seal_system_mappings __ro_after_init = + IS_ENABLED(CONFIG_SEAL_SYSTEM_MAPPINGS_ALWAYS) ? SEAL_SYSTEM_MAPPINGS_ALWAYS : + SEAL_SYSTEM_MAPPINGS_NEVER; + +static const struct constant_table value_table_sys_mapping[] __initconst = { + { "never", SEAL_SYSTEM_MAPPINGS_NEVER}, + { "always", SEAL_SYSTEM_MAPPINGS_ALWAYS}, + { } +}; + +static int __init early_seal_system_mappings_override(char *buf) +{ + if (!buf) + return -EINVAL; + + seal_system_mappings = lookup_constant(value_table_sys_mapping, + buf, seal_system_mappings); + + return 0; +} + +early_param("exec.seal_system_mappings", early_seal_system_mappings_override); + +static bool seal_system_mappings_enabled(void) +{ + if (seal_system_mappings == SEAL_SYSTEM_MAPPINGS_ALWAYS) + return true; + + return false; +} + +void update_seal_exec_system_mappings(unsigned long *vm_flags) +{ + if (!(*vm_flags & VM_SEALED) && seal_system_mappings_enabled()) + *vm_flags |= VM_SEALED; + +} +#else +void update_seal_exec_system_mappings(unsigned long *vm_flags) +{ +} +#endif /* CONFIG_64BIT */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 42444ec95c9b..6e44aca4b24b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3079,6 +3079,7 @@ ssize_t __kernel_read(struct file *file, void *buf, size_t count, loff_t *pos); extern ssize_t kernel_write(struct file *, const void *, size_t, loff_t *); extern ssize_t __kernel_write(struct file *, const void *, size_t, loff_t *); extern struct file * open_exec(const char *); +extern void update_seal_exec_system_mappings(unsigned long *vm_flags); /* fs/dcache.c -- generic fs support functions */ extern bool is_subdir(struct dentry *, struct dentry *); diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index c47a0bf25e58..e9876fae8887 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -1506,7 +1506,7 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area) } vma = _install_special_mapping(mm, area->vaddr, PAGE_SIZE, - VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO, + VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO|VM_SEALED, &xol_mapping); if (IS_ERR(vma)) { ret = PTR_ERR(vma); diff --git a/mm/mmap.c b/mm/mmap.c index 57fd5ab2abe7..d4717e34a60d 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2133,6 +2133,7 @@ struct vm_area_struct *_install_special_mapping( unsigned long addr, unsigned long len, unsigned long vm_flags, const struct vm_special_mapping *spec) { + update_seal_exec_system_mappings(&vm_flags); return __install_special_mapping(mm, addr, len, vm_flags, (void *)spec, &special_mapping_vmops); } diff --git a/security/Kconfig b/security/Kconfig index 28e685f53bd1..4ec8045339c3 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -51,6 +51,32 @@ config PROC_MEM_NO_FORCE endchoice +choice + prompt "Seal system mappings" + default SEAL_SYSTEM_MAPPINGS_NEVER + help + Seal system mappings such as vdso, vvar, sigpage, uprobes and + vsyscall. + Note: kernel command line exec.seal_system_mappings overwrites this. + +config SEAL_SYSTEM_MAPPINGS_NEVER + bool "Traditional behavior - not sealed" + help + Do not seal system mappings. + This is default. + +config SEAL_SYSTEM_MAPPINGS_ALWAYS + bool "Always seal system mappings" + depends on 64BIT + depends on !CHECKPOINT_RESTORE + help + Seal system mappings such as vdso, vvar, sigpage, uprobes and + vsyscall. + Note: CHECKPOINT_RESTORE might relocate vdso mapping during restore, + and remap will fail if the mapping is sealed, therefore + !CHECKPOINT_RESTORE is added as dependency. +endchoice + config SECURITY bool "Enable different security models" depends on SYSFS