sys-kernel/hardened-kernel: version 6.14.6 with bcachefs and openpax upstream patches

Signed-off-by: Alexander Miroshnichenko <alex@millerson.name>
This commit is contained in:
Alexander Miroshnichenko 2025-05-14 19:41:06 +03:00
parent 91a17ba827
commit dfc3b3eee4
6 changed files with 32278 additions and 0 deletions

View File

@ -1,10 +1,20 @@
DIST genpatches-6.12-23.base.tar.xz 1435492 BLAKE2B ca65b4ead188bb8c561e47dd7aca29c2cb10d98ed28e78113cedd1bf9d9bf2a380bf12a807bcfc3cce3976621355e087cb8a2a5a06857660401eea0e9156830f SHA512 82fc23bb6e04227bcea2d29336d5a46a6e7f1649244b9ceae2869fac65e3f785e7512ea8d1e32f34281d48c76831223cc5c8b448452d2dd036445773a1329c6d
DIST genpatches-6.12-23.experimental.tar.xz 78500 BLAKE2B f7c0bbe38f90fe3c203725c83bae75f105de44ecc3b4bb5d262056936cc472f8678d50900587e51fd388ed54d95fefa624ba86642f5d12bfc650f0bb4a2a0e37 SHA512 9738997ec9056d66a0e56fb21bc1d6f06c198394993d2960c13acf29821b0f6f1e8b6637abca0abdd3e57ff25b734286a309d991c9614fe6b9ee1f8de59e25fc
DIST genpatches-6.12-23.extras.tar.xz 4056 BLAKE2B dc27e7f57ea95e678f08d3b6f791a26cec5b51e2204f3d527538f3c54333c8f25194981cdc68b7812973ee8baa95e0d5c575be26e918b25c160178d3bcf80769 SHA512 c7d92cc303dde284b5c1f31b87081167a1a8645e5611a65780d09ebc49f9cc2ded94007d10e1764d90e0d25e31fa73095227d381977c1ba13714654a328ac77f
DIST genpatches-6.14-7.base.tar.xz 632760 BLAKE2B 12a26d7a4cd6b24ae3dc36648b0e890ce3ef20b3eba0583cd920ca200ecb92a6405dc79e2a58700e125f7ea2385db8ffa0f7a829e45f1204d19ef41a91a6fc99 SHA512 a0a0df6ae8f6c7c26594a55f6b071522b59a5537501ae78b569418a8cbacee5ad02fef705be7eb22468bb288a56de89b51273f1d32e52727de6046d878b28e1d
DIST genpatches-6.14-7.experimental.tar.xz 79808 BLAKE2B 913985f9276088dd965e6bde50b83088a298dba576c728b8254b86964ca5126d39f2a39ce8fc4441171acf4d6d686f81ee1012c3ba532f20e99494dfa36a3c3d SHA512 035c4ffdc033e4565be7c3701ed505efd780c1d061f13db77ff7b75a34d8d36ba01ec0aabaeb10ecf8e574149ab4e7a8292cd7b48fe34afc65eda8506fa4d615
DIST genpatches-6.14-7.extras.tar.xz 4052 BLAKE2B 1089c810902b96b2d17ebaec90ed484e9500fca9a813058815c7e951119e903fb544db3295ee47a2ae08e23319c03239261803fcb76d3ef42bcf626abb5ca6dc SHA512 6d1dfdf3632ced4e7202d4f93a5ae1e65fd80379fdeb466f95d1f1bda9b005a00dc28963c25b0dd07a48fc06e189b4f42bb648bab9507a116c555eb68a02ca4e
DIST gentoo-kernel-config-g15.tar.gz 5746 BLAKE2B 2baef40e18cbf3bb975362d71ad674604ad80338d1e6914ffa2fc03af26f1b9c9cec66d39a56077693a7327060bc29bd5eb5787549857dd3779e841192cb2016 SHA512 45d609ee25a529988868b8c99c808f4e6abbde34ae501bf35523431ee85c9f3657663d6f938f2036a5f012a55a68965b32fd41fc44d8f6ca606a6fd38f952445
DIST gentoo-kernel-config-g16.tar.gz 5995 BLAKE2B cddb80d45169749c707d87efd186f7a981534aab2479b6c51790008ea61e9f9feac35d0d74b95dc18281e4b81771e09f259a1d9f216f5d7f806fa7cd6aeeb4d1 SHA512 f8114e645e1ab99e45703790b7e43c2fa9ee17b41a2265dccdd9187c122bf8b5a09ba918fbcf094aa899bb959f05d105ed474b75cdfa9a19c4d49fd138825647
DIST kernel-aarch64-fedora.config.6.12.8-gentoo 288081 BLAKE2B 08273a34c387621d0ccffcc325a0a34b40e0a8fbe78f2429c8a9efc73aa05f8fb563ed53e5fadb25662089f23ebafb61b2d08f91ea00b073e67e702798255e9c SHA512 58ea4f247aa9af6f7535ab5fe44dae2fbf286c7fbceeda86df532125807bbd4c25a89ddeeff4284592efefbaaef5022626abad7f1d1d64976e3040dc6e89251a
DIST kernel-aarch64-fedora.config.6.14.5-gentoo 291637 BLAKE2B 3255e3c098f6c161328633886473ee4cec96799545e9b1a106b1f3fe59fa373407435ee970a9b5d442ceb26869ddc8cf62c962105757630be2fc741a378c4014 SHA512 aded4b58a526b1fd8ece961f04a0885d12fb860bb9e246489242a3060bbebfad904ed1a72935bc6f5a9aabf9b062eccada430772299a958e8393e2980d5b255a
DIST kernel-i686-fedora.config.6.12.8-gentoo 255163 BLAKE2B 7015bbcfb2aed0ba70173dc7e9abf464e167184e2bc8cea6d26623972bbe6b42956241a7d75ff8604d70d5c0202db6e40cdb890abfcea3d0c8e0d00aa869353e SHA512 a1b4b688510a231fe079b4158e8aaddaddc4e719367132668279edcb16e32b6c7f2c449ec196646b0986171dc43a82475255502ae40679e0433de9f9876e0a20
DIST kernel-i686-fedora.config.6.14.5-gentoo 259410 BLAKE2B c28dfc8cd90f60b57ac80f357ea787bbb68e86e58e21880f643bd5276121f9ff1f6afaf70852694d8bb3a11616c278281d067e248baa439487d7870f76ac7b25 SHA512 d53d840cc1dc2359b3b03198c3416e2f2cbceae1e0555478ab6592d7b280aac07da2a3813c3e3e175160c4674adcb6ec4232b0073fc40b14e64dcc60b278e400
DIST kernel-ppc64le-fedora.config.6.12.8-gentoo 241851 BLAKE2B e7b8833572348037d7af2ba1f9671e8010276d853e0d85b8a175c0dcc5c212c57c7660be54a7ba2621c427cc8120acbeb1063a1c1a1c293894ebe1d63921b684 SHA512 7a81fe1c4b1d4fb9f2d68846882a8869c0888c8fa764ec41f41d27e61b7a69825ea8ceba2209b40deb7c0e8f4bb2c5d81226a4f28e7ca8aff4788bc7a3292194
DIST kernel-ppc64le-fedora.config.6.14.5-gentoo 243480 BLAKE2B 1174ca580d5de7db3e94e7a040e655136ce9356c6bccd9c7d6e0c4c6f0cae0b325ac0fd3345e6e493891a4e648ccecf22a0e36adb53f4e028611cf99d1ca4876 SHA512 99adb16c8a84c31442dfae67a828eaa6689fb1b96b4d5fe2505bcf5ae1803e9df742eb239c4524566375eabe64cb93d26390edb4ff651f48cb5f87c27895e2b4
DIST kernel-x86_64-fedora.config.6.12.8-gentoo 256210 BLAKE2B f14f7de8ae573561824df47cf94c3c0ce52a820456ebd0e618e4c1e7f5454b7d3f6f86c559a3cd98dd94c55aaeed397f3d0cee6b0e37cf6b47d3aedd920a9dea SHA512 ea87b4b45c78888e02d0288dd5844cf2d97a14e251b565c7d6451a0e62fbe0dbef38f46715467af2f869995d6bbc8be61d5b70476a86d607a5bfa27fbaf36e92
DIST kernel-x86_64-fedora.config.6.14.5-gentoo 260496 BLAKE2B b68058a75bc02afcc3e45371be25d295ccb959efb9047ec394d1d11becea30f3d9007e78da02253ebb8cea41500e0fbb392866b1086c9746cdefdb78cc4edd3c SHA512 2f1e6f112db46bd3765e29cfe0cff1f45991d652c49b520b46b0c5ced4c995e2ef7753c13730b0a918379200cb05f50eaadc827516136177ea5900b4e10d6192
DIST linux-6.12.tar.xz 147906904 BLAKE2B b2ec2fc69218cacabbbe49f78384a5d259ca581b717617c12b000b16f4a4c59ee348ea886b37147f5f70fb9a7a01c1e2c8f19021078f6b23f5bc62d1c48d5e5e SHA512 a37b1823df7b4f72542f689b65882634740ba0401a42fdcf6601d9efd2e132e5a7650e70450ba76f6cd1f13ca31180f2ccee9d54fe4df89bc0000ade4380a548
DIST linux-6.14.tar.xz 149408504 BLAKE2B 11835719804b406fe281ea1c276a84dc0cbaa808552ddcca9233d3eaeb1c001d0455c7205379b02de8e8db758c1bae6fe7ceb6697e63e3cf9ae7187dc7a9715e SHA512 71dcaa3772d8d9797c3ae30cae9c582b11a7047a3bbcb8dfd479a4dffb40ff0da74cf3d45175f50cc9992e338bcadd46c9c570f54054ca3bde6661768d3d22eb
DIST linux-hardened-v6.12.19-hardened1.patch 89621 BLAKE2B dcd5dace9b76852547e02ce79f98eb417ebe0290654f6f19d18655d873c868a4e84d72608714e0bf02ae71178726cf69bcee20c38b30b590ef44de9ba7b88470 SHA512 e96e7028303d2d7660d71de2e90a03ea467bafeb3af296c456d859235274d1c92b9f92b093bc3747f1f47d9f0a2ed2e501b05baf22a483b473dc00cb983433ed
DIST linux-hardened-v6.14.6-hardened1.patch 90843 BLAKE2B d01444293df3334ff2dc43b2940043b1287ec791b72a77608662209754532e96b2fc84351f370fba5e49e0a5f7089845e01f2229c644d88a22d14b99be4bbcfa SHA512 84fc877eca63c9376bf203b32b14c7bfb25b826ce2b164f8b3b96757447338507c36188769ac07d37ee764f5d22249e98be0c95e1589ede5389e9a32a20d1ad3

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,128 @@
From ee3912c8c293b09acc90ba6ad7443ceacc33ef79 Mon Sep 17 00:00:00 2001
From: Alexander Miroshnichenko <alex@millerson.name>
Date: Wed, 14 May 2025 16:48:38 +0300
Subject: [PATCH] bcachefs: revert 6.14 backport fixes
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit
Signed-off-by: Alexander Miroshnichenko <alex@millerson.name>
---
fs/bcachefs/btree_update_interior.c | 17 +----------------
fs/bcachefs/error.c | 8 --------
fs/bcachefs/error.h | 2 --
fs/bcachefs/fs-ioctl.c | 6 ++----
fs/bcachefs/xattr_format.h | 8 +-------
5 files changed, 4 insertions(+), 37 deletions(-)
diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c
index e9be8b5571a4..e4e7c804625e 100644
--- a/fs/bcachefs/btree_update_interior.c
+++ b/fs/bcachefs/btree_update_interior.c
@@ -35,8 +35,6 @@ static const char * const bch2_btree_update_modes[] = {
NULL
};
-static void bch2_btree_update_to_text(struct printbuf *, struct btree_update *);
-
static int bch2_btree_insert_node(struct btree_update *, struct btree_trans *,
btree_path_idx_t, struct btree *, struct keylist *);
static void bch2_btree_update_add_new_node(struct btree_update *, struct btree *);
@@ -1784,24 +1782,11 @@ static int bch2_btree_insert_node(struct btree_update *as, struct btree_trans *t
int ret;
lockdep_assert_held(&c->gc_lock);
+ BUG_ON(!btree_node_intent_locked(path, b->c.level));
BUG_ON(!b->c.level);
BUG_ON(!as || as->b);
bch2_verify_keylist_sorted(keys);
- if (!btree_node_intent_locked(path, b->c.level)) {
- struct printbuf buf = PRINTBUF;
- bch2_log_msg_start(c, &buf);
- prt_printf(&buf, "%s(): node not locked at level %u\n",
- __func__, b->c.level);
- bch2_btree_update_to_text(&buf, as);
- bch2_btree_path_to_text(&buf, trans, path_idx);
-
- bch2_print_string_as_lines(KERN_ERR, buf.buf);
- printbuf_exit(&buf);
- bch2_fs_emergency_read_only(c);
- return -EIO;
- }
-
ret = bch2_btree_node_lock_write(trans, path, &b->c);
if (ret)
return ret;
diff --git a/fs/bcachefs/error.c b/fs/bcachefs/error.c
index 6cbf4819e923..038da6a61f6b 100644
--- a/fs/bcachefs/error.c
+++ b/fs/bcachefs/error.c
@@ -11,14 +11,6 @@
#define FSCK_ERR_RATELIMIT_NR 10
-void bch2_log_msg_start(struct bch_fs *c, struct printbuf *out)
-{
-#ifdef BCACHEFS_LOG_PREFIX
- prt_printf(out, bch2_log_msg(c, ""));
-#endif
- printbuf_indent_add(out, 2);
-}
-
bool bch2_inconsistent_error(struct bch_fs *c)
{
set_bit(BCH_FS_error, &c->flags);
diff --git a/fs/bcachefs/error.h b/fs/bcachefs/error.h
index 5730eb6b2f38..7acf2a27ca28 100644
--- a/fs/bcachefs/error.h
+++ b/fs/bcachefs/error.h
@@ -18,8 +18,6 @@ struct work_struct;
/* Error messages: */
-void bch2_log_msg_start(struct bch_fs *, struct printbuf *);
-
/*
* Inconsistency errors: The on disk data is inconsistent. If these occur during
* initial recovery, they don't indicate a bug in the running code - we walk all
diff --git a/fs/bcachefs/fs-ioctl.c b/fs/bcachefs/fs-ioctl.c
index 4d6193820483..15725b4ce393 100644
--- a/fs/bcachefs/fs-ioctl.c
+++ b/fs/bcachefs/fs-ioctl.c
@@ -515,12 +515,10 @@ static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
ret = -ENOENT;
goto err;
}
-
- ret = inode_permission(file_mnt_idmap(filp), d_inode(victim), MAY_WRITE) ?:
- __bch2_unlink(dir, victim, true);
+ ret = __bch2_unlink(dir, victim, true);
if (!ret) {
fsnotify_rmdir(dir, victim);
- d_invalidate(victim);
+ d_delete(victim);
}
err:
inode_unlock(dir);
diff --git a/fs/bcachefs/xattr_format.h b/fs/bcachefs/xattr_format.h
index 67426e33d04e..c7916011ef34 100644
--- a/fs/bcachefs/xattr_format.h
+++ b/fs/bcachefs/xattr_format.h
@@ -13,13 +13,7 @@ struct bch_xattr {
__u8 x_type;
__u8 x_name_len;
__le16 x_val_len;
- /*
- * x_name contains the name and value counted by
- * x_name_len + x_val_len. The introduction of
- * __counted_by(x_name_len) caused a false positive
- * detection of an out of bounds write.
- */
- __u8 x_name[];
+ __u8 x_name[] __counted_by(x_name_len);
} __packed __aligned(8);
#endif /* _BCACHEFS_XATTR_FORMAT_H */
--
2.49.0

View File

@ -0,0 +1,720 @@
From a80207aef480f66179564003807d7a4ecf5aef8e Mon Sep 17 00:00:00 2001
From: Alexander Miroshnichenko <alex@millerson.name>
Date: Wed, 14 May 2025 19:33:06 +0300
Subject: [PATCH] openpax: cherry-pick updates from master fb1be96e0a3e
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit
Signed-off-by: Alexander Miroshnichenko <alex@millerson.name>
---
.../admin-guide/kernel-parameters.txt | 3 +
arch/x86/mm/fault.c | 218 ++++++++++++++++++
fs/binfmt_elf.c | 88 ++++++-
fs/proc/array.c | 15 ++
fs/xattr.c | 16 ++
include/linux/init.h | 1 +
include/linux/mm_types.h | 11 +
include/linux/mman.h | 11 +-
include/linux/xattr.h | 4 +
include/uapi/linux/xattr.h | 5 +
init/main.c | 11 +
kernel/sysctl.c | 15 ++
security/Kconfig | 1 +
security/Kconfig.openpax | 89 +++++++
14 files changed, 485 insertions(+), 3 deletions(-)
create mode 100644 security/Kconfig.openpax
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index bd53e2675c75..d46f21aa6a26 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4579,6 +4579,9 @@
from the first 4GB of memory as the bootmem allocator
passes the memory pages to the buddy allocator.
+ pax_softmode=<int>
+ Enables OpenPaX soft mode if set to a non-zero value.
+
pcbit= [HW,ISDN]
pci=option[,option...] [PCI,EARLY] various PCI subsystem options.
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 296d294142c8..65665982e401 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1198,6 +1198,217 @@ do_kern_addr_fault(struct pt_regs *regs, unsigned long hw_error_code,
}
NOKPROBE_SYMBOL(do_kern_addr_fault);
+#ifdef CONFIG_OPENPAX_EMUTRAMP
+/*
+ * Determine if a fault is possibly caused by an emulatable stack or
+ * heap trampoline. We return false if trampoline emulation is not
+ * enabled.
+ */
+static inline
+bool openpax_fault_is_trampoline(unsigned long error_code,
+ struct pt_regs *regs,
+ unsigned long address)
+{
+ struct mm_struct *mm = current->mm;
+ unsigned long ip = regs->ip;
+
+ if (!test_bit(PAXF_EMUTRAMP, &mm->pax_flags))
+ return false;
+
+ if (v8086_mode(regs))
+ ip = ((regs->cs & 0xffff) << 4) + (ip & 0xffff);
+
+ if (test_bit(PAXF_PAGEEXEC, &mm->pax_flags)) {
+ if ((__supported_pte_mask & _PAGE_NX) && (error_code & X86_PF_INSTR))
+ return true;
+ if (!(error_code & (X86_PF_PROT | X86_PF_WRITE)) && ip == address)
+ return true;
+ return false;
+ }
+
+ return false;
+}
+NOKPROBE_SYMBOL(openpax_fault_is_trampoline);
+
+static inline
+bool openpax_emulate_trampoline_32(struct pt_regs *regs)
+{
+ int err;
+
+ /* libffi trampoline type 1, gcc trampoline type 2 */
+ do {
+ unsigned char mov, jmp;
+ unsigned int addr1, addr2;
+
+#ifdef CONFIG_X86_64
+ if ((regs->ip + 9) >> 32)
+ break;
+#endif
+
+ err = get_user(mov, (unsigned char __user *) regs->ip);
+ err |= get_user(addr1, (unsigned int __user *) (regs->ip + 1));
+ err |= get_user(jmp, (unsigned char __user *) (regs->ip + 5));
+ err |= get_user(addr2, (unsigned int __user *) (regs->ip + 6));
+
+ if (err)
+ break;
+
+ if ((mov == 0xB8 || mov == 0xB9) && jmp == 0xE9) {
+ if (mov == 0xB8)
+ regs->ax = addr1;
+ else
+ regs->cx = addr1;
+
+ regs->ip = (unsigned int)(regs->ip + addr2 + 10);
+ return true;
+ }
+ } while (0);
+
+ /* older gcc trampoline type... */
+ do {
+ unsigned char mov1, mov2;
+ unsigned short jmp;
+ unsigned int addr1, addr2;
+
+#ifdef CONFIG_X86_64
+ if ((regs->ip + 11) >> 32)
+ break;
+#endif
+
+ err = get_user(mov1, (unsigned char __user *) regs->ip);
+ err |= get_user(addr1, (unsigned int __user *) (regs->ip + 1));
+ err |= get_user(mov2, (unsigned char __user *) (regs->ip + 5));
+ err |= get_user(addr2, (unsigned int __user *) (regs->ip + 6));
+ err |= get_user(jmp, (unsigned short __user *) (regs->ip + 10));
+
+ if (err)
+ break;
+
+ if (mov1 == 0xB9 && mov2 == 0xB8 && jmp == 0xE0FF) {
+ regs->cx = addr1;
+ regs->ax = addr2;
+ regs->ip = addr2;
+ return true;
+ }
+ } while (0);
+
+ return false;
+}
+NOKPROBE_SYMBOL(openpax_emulate_trampoline_32);
+
+#ifdef CONFIG_X86_64
+static inline
+bool openpax_emulate_trampoline_64(struct pt_regs *regs)
+{
+ int err;
+
+ /* libffi trampoline type 1 */
+ do {
+ unsigned short mov1, mov2, jmp1;
+ unsigned char stcclc, jmp2;
+ unsigned long addr1, addr2;
+
+ err = get_user(mov1, (unsigned short __user *) regs->ip);
+ err |= get_user(addr1, (unsigned long __user *) (regs->ip + 2));
+ err |= get_user(mov2, (unsigned short __user *) (regs->ip + 10));
+ err |= get_user(addr2, (unsigned long __user *) (regs->ip + 12));
+ err |= get_user(stcclc, (unsigned char __user *) (regs->ip + 20));
+ err |= get_user(jmp1, (unsigned short __user *) (regs->ip + 21));
+ err |= get_user(jmp2, (unsigned char __user *) (regs->ip + 23));
+
+ if (err)
+ break;
+
+ if (mov1 == 0xBB49 && mov2 == 0xBA49 && (stcclc == 0xF8 || stcclc == 0xF9) && jmp1 == 0xFF49 && jmp2 == 0xE3) {
+ regs->r11 = addr1;
+ regs->r10 = addr2;
+
+ if (stcclc == 0xF8)
+ regs->flags &= ~X86_EFLAGS_CF;
+ else
+ regs->flags |= X86_EFLAGS_CF;
+
+ regs->ip = addr1;
+ return true;
+ }
+ } while (0);
+
+ /* gcc trampoline type 1 */
+ do {
+ unsigned short mov1, mov2, jmp1;
+ unsigned char jmp2;
+ unsigned int addr1;
+ unsigned long addr2;
+
+ err = get_user(mov1, (unsigned short __user *) regs->ip);
+ err |= get_user(addr1, (unsigned int __user *) (regs->ip + 2));
+ err |= get_user(mov2, (unsigned short __user *) (regs->ip + 6));
+ err |= get_user(addr2, (unsigned long __user *) (regs->ip + 8));
+ err |= get_user(jmp1, (unsigned short __user *) (regs->ip + 16));
+ err |= get_user(jmp2, (unsigned char __user *) (regs->ip + 18));
+
+ if (err)
+ break;
+
+ if (mov1 == 0xBB41 && mov2 == 0xBA49 && jmp1 == 0xFF49 && jmp2 == 0xE3) {
+ regs->r11 = addr1;
+ regs->r10 = addr2;
+ regs->ip = addr1;
+ return true;
+ }
+ } while (0);
+
+ /* gcc trampoline type 2 */
+ do {
+ unsigned short mov1, mov2, jmp1;
+ unsigned char jmp2;
+ unsigned long addr1, addr2;
+
+ err = get_user(mov1, (unsigned short __user *) regs->ip);
+ err |= get_user(addr1, (unsigned long __user *) (regs->ip + 2));
+ err |= get_user(mov2, (unsigned short __user *) (regs->ip + 10));
+ err |= get_user(addr2, (unsigned long __user *) (regs->ip + 12));
+ err |= get_user(jmp1, (unsigned short __user *) (regs->ip + 20));
+ err |= get_user(jmp2, (unsigned char __user *) (regs->ip + 22));
+
+ if (err)
+ break;
+
+ if (mov1 == 0xBB49 && mov2 == 0xBA49 && jmp1 == 0xFF49 && jmp2 == 0xE3) {
+ regs->r11 = addr1;
+ regs->r10 = addr2;
+ regs->ip = addr1;
+ return true;
+ }
+ } while (0);
+
+ return false;
+}
+NOKPROBE_SYMBOL(openpax_emulate_trampoline_64);
+#endif
+
+/*
+ * Emulate a trampoline. Returns false if emulation failed, meaning
+ * that the task should be killed.
+ */
+static inline
+bool openpax_emulate_trampoline(struct pt_regs *regs)
+{
+ if (v8086_mode(regs))
+ return false;
+
+ if (regs->cs == __USER32_CS || (regs->cs & SEGMENT_LDT))
+ return openpax_emulate_trampoline_32(regs);
+#ifdef CONFIG_X86_64
+ else
+ return openpax_emulate_trampoline_64(regs);
+#endif
+
+ return false;
+}
+NOKPROBE_SYMBOL(openpax_emulate_trampoline);
+#endif
+
/*
* Handle faults in the user portion of the address space. Nothing in here
* should check X86_PF_USER without a specific justification: for almost
@@ -1322,6 +1533,13 @@ void do_user_addr_fault(struct pt_regs *regs,
}
#endif
+#ifdef CONFIG_OPENPAX_EMUTRAMP
+ if (openpax_fault_is_trampoline(error_code, regs, address)) {
+ if (openpax_emulate_trampoline(regs))
+ return;
+ }
+#endif
+
if (!(flags & FAULT_FLAG_USER))
goto lock_mmap;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 8054f44d39cf..00f436d6d0a8 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -47,6 +47,7 @@
#include <linux/dax.h>
#include <linux/uaccess.h>
#include <linux/rseq.h>
+#include <linux/xattr.h>
#include <asm/param.h>
#include <asm/page.h>
@@ -822,6 +823,72 @@ static int parse_elf_properties(struct file *f, const struct elf_phdr *phdr,
return ret == -ENOENT ? 0 : ret;
}
+#ifdef CONFIG_OPENPAX
+#ifdef CONFIG_OPENPAX_XATTR_PAX_FLAGS
+static int openpax_parse_xattr_flags(struct file * const file)
+{
+ ssize_t xattr_size, i;
+ unsigned char xattr_value[sizeof("pemrs") - 1];
+
+ xattr_size = pax_getxattr(file, xattr_value, sizeof xattr_value);
+ if (xattr_size < 0 || xattr_size > sizeof xattr_value)
+ return -ENOENT;
+
+ for (i = 0; i < xattr_size; i++)
+ switch (xattr_value[i]) {
+ default:
+ return -EINVAL;
+
+#define parse_flag(option_disable, option_enable, flag) \
+ case option_disable: \
+ clear_bit(flag, &current->mm->pax_flags); \
+ break; \
+ case option_enable: \
+ set_bit(flag, &current->mm->pax_flags); \
+ break;
+
+ parse_flag('p', 'P', PAXF_PAGEEXEC);
+ parse_flag('e', 'E', PAXF_EMUTRAMP);
+ parse_flag('m', 'M', PAXF_MPROTECT);
+ parse_flag('r', 'R', PAXF_RANDMMAP);
+ parse_flag('s', 'S', PAXF_SEGMEXEC);
+#undef parse_flag
+ }
+
+ return 0;
+}
+#endif
+
+static int openpax_set_flags(struct file * const file, const int snapshot_randomize_va_space)
+{
+#ifdef CONFIG_OPENPAX_XATTR_PAX_FLAGS
+ int error;
+#endif
+ current->mm->pax_flags = 0;
+
+ if (snapshot_randomize_va_space) {
+ set_bit(PAXF_RANDMMAP, &current->mm->pax_flags);
+ }
+
+ if (!pax_softmode) {
+ set_bit(PAXF_PAGEEXEC, &current->mm->pax_flags);
+ set_bit(PAXF_MPROTECT, &current->mm->pax_flags);
+ }
+
+#ifdef CONFIG_OPENPAX_EMUTRAMP_DEFAULT
+ set_bit(PAXF_EMUTRAMP, &current->mm->pax_flags);
+#endif
+
+#ifdef CONFIG_OPENPAX_XATTR_PAX_FLAGS
+ error = openpax_parse_xattr_flags(file);
+ if (error != -ENOENT)
+ return error;
+#endif
+
+ return 0;
+}
+#endif
+
static int load_elf_binary(struct linux_binprm *bprm)
{
struct file *interpreter = NULL; /* to shut gcc up */
@@ -1006,11 +1073,28 @@ static int load_elf_binary(struct linux_binprm *bprm)
/* Do this immediately, since STACK_TOP as used in setup_arg_pages
may depend on the personality. */
SET_PERSONALITY2(*elf_ex, &arch_state);
+
+ const int snapshot_randomize_va_space = READ_ONCE(randomize_va_space);
+
+#ifdef CONFIG_OPENPAX
+ retval = openpax_set_flags(bprm->file, snapshot_randomize_va_space);
+ if (retval)
+ goto out_free_dentry;
+
+ if (test_bit(PAXF_PAGEEXEC, &current->mm->pax_flags) || test_bit(PAXF_SEGMEXEC, &current->mm->pax_flags)) {
+ executable_stack = EXSTACK_DISABLE_X;
+ current->personality &= ~READ_IMPLIES_EXEC;
+ } else
+#endif
+
if (elf_read_implies_exec(*elf_ex, executable_stack))
current->personality |= READ_IMPLIES_EXEC;
- const int snapshot_randomize_va_space = READ_ONCE(randomize_va_space);
- if (!(current->personality & ADDR_NO_RANDOMIZE) && snapshot_randomize_va_space)
+ if (!(current->personality & ADDR_NO_RANDOMIZE) && snapshot_randomize_va_space
+#ifdef CONFIG_OPENPAX
+ && test_bit(PAXF_RANDMMAP, &current->mm->pax_flags)
+#endif
+ )
current->flags |= PF_RANDOMIZE;
setup_new_exec(bprm);
diff --git a/fs/proc/array.c b/fs/proc/array.c
index d6a0369caa93..242c8a969400 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -436,6 +436,18 @@ __weak void arch_proc_pid_thread_features(struct seq_file *m,
{
}
+#ifdef CONFIG_OPENPAX
+static inline void task_pax(struct seq_file *m, struct mm_struct *mm)
+{
+ seq_printf(m, "PaX:\t%c%c%c%c%c\n",
+ test_bit(PAXF_PAGEEXEC, &mm->pax_flags) ? 'P' : 'p',
+ test_bit(PAXF_EMUTRAMP, &mm->pax_flags) ? 'E' : 'e',
+ test_bit(PAXF_MPROTECT, &mm->pax_flags) ? 'M' : 'm',
+ test_bit(PAXF_RANDMMAP, &mm->pax_flags) ? 'R' : 'r',
+ test_bit(PAXF_SEGMEXEC, &mm->pax_flags) ? 'S' : 's');
+}
+#endif
+
int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)
{
@@ -452,6 +464,9 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
task_core_dumping(m, task);
task_thp_status(m, mm);
task_untag_mask(m, mm);
+#ifdef CONFIG_OPENPAX
+ task_pax(m, mm);
+#endif
mmput(mm);
}
task_sig(m, task);
diff --git a/fs/xattr.c b/fs/xattr.c
index fabb2a04501e..76c2b5f8d6e6 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -424,6 +424,22 @@ __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
}
EXPORT_SYMBOL(__vfs_getxattr);
+#ifdef CONFIG_OPENPAX_XATTR_PAX_FLAGS
+ssize_t
+pax_getxattr(struct file *file, void *value, size_t size)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ ssize_t error;
+
+ error = inode_permission(file_mnt_idmap(file), inode, MAY_EXEC);
+ if (error)
+ return error;
+
+ return __vfs_getxattr(file->f_path.dentry, inode, XATTR_NAME_USER_PAX_FLAGS, value, size);
+}
+EXPORT_SYMBOL(pax_getxattr);
+#endif
+
ssize_t
vfs_getxattr(struct mnt_idmap *idmap, struct dentry *dentry,
const char *name, void *value, size_t size)
diff --git a/include/linux/init.h b/include/linux/init.h
index ee1309473bc6..4abbce4cf60b 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -144,6 +144,7 @@ extern char __initdata boot_command_line[];
extern char *saved_command_line;
extern unsigned int saved_command_line_len;
extern unsigned int reset_devices;
+extern int pax_softmode;
/* used by init/main.c */
void setup_arch(char **);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 0234f14f2aa6..fd8bd5517e4d 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -973,6 +973,9 @@ struct mm_struct {
mm_context_t context;
unsigned long flags; /* Must use atomic bitops to access */
+#ifdef CONFIG_OPENPAX
+ unsigned long pax_flags;
+#endif
#ifdef CONFIG_AIO
spinlock_t ioctx_lock;
@@ -1656,4 +1659,12 @@ static inline unsigned long mmf_init_flags(unsigned long flags)
return flags & MMF_INIT_MASK;
}
+#ifdef CONFIG_OPENPAX
+#define PAXF_PAGEEXEC 1
+#define PAXF_EMUTRAMP 2
+#define PAXF_MPROTECT 3
+#define PAXF_RANDMMAP 4
+#define PAXF_SEGMEXEC 5
+#endif
+
#endif /* _LINUX_MM_TYPES_H */
diff --git a/include/linux/mman.h b/include/linux/mman.h
index a842783ffa62..e108371ff12e 100644
--- a/include/linux/mman.h
+++ b/include/linux/mman.h
@@ -197,12 +197,21 @@ static inline bool arch_memory_deny_write_exec_supported(void)
* we propose to set.
*
* Return: false if proposed change is OK, true if not ok and should be denied.
+ *
+ * Note: If OpenPaX is enabled, it will be assumed that we want to deny
+ * PROT_WRITE | PROT_EXEC by default, unless the MPROTECT feature bit is
+ * disabled on a binary.
*/
static inline bool map_deny_write_exec(unsigned long old, unsigned long new)
{
/* If MDWE is disabled, we have nothing to deny. */
- if (!test_bit(MMF_HAS_MDWE, &current->mm->flags))
+ if (
+#ifdef CONFIG_OPENPAX_MPROTECT
+ !test_bit(PAXF_MPROTECT, &current->mm->pax_flags) &&
+#endif
+ !test_bit(MMF_HAS_MDWE, &current->mm->flags)) {
return false;
+ }
/* If the new VMA is not executable, we have nothing to deny. */
if (!(new & VM_EXEC))
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 86b0d47984a1..c4ad3af7e1a2 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -25,6 +25,7 @@
struct inode;
struct dentry;
+struct file;
static inline bool is_posix_acl_xattr(const char *name)
{
@@ -75,6 +76,9 @@ struct xattr {
size_t value_len;
};
+#ifdef CONFIG_OPENPAX_XATTR_PAX_FLAGS
+ssize_t pax_getxattr(struct file *, void *, size_t);
+#endif
ssize_t __vfs_getxattr(struct dentry *, struct inode *, const char *, void *, size_t);
ssize_t vfs_getxattr(struct mnt_idmap *, struct dentry *, const char *,
void *, size_t);
diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h
index 9854f9cff3c6..843787b91ef0 100644
--- a/include/uapi/linux/xattr.h
+++ b/include/uapi/linux/xattr.h
@@ -88,5 +88,10 @@ struct xattr_args {
#define XATTR_POSIX_ACL_DEFAULT "posix_acl_default"
#define XATTR_NAME_POSIX_ACL_DEFAULT XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_DEFAULT
+/* User namespace */
+#define XATTR_PAX_PREFIX "pax."
+#define XATTR_PAX_FLAGS_SUFFIX "flags"
+#define XATTR_NAME_USER_PAX_FLAGS XATTR_USER_PREFIX XATTR_PAX_PREFIX XATTR_PAX_FLAGS_SUFFIX
+#define XATTR_NAME_PAX_FLAGS XATTR_PAX_PREFIX XATTR_PAX_FLAGS_SUFFIX
#endif /* _UAPI_LINUX_XATTR_H */
diff --git a/init/main.c b/init/main.c
index 2a1757826397..4720dce1a3b9 100644
--- a/init/main.c
+++ b/init/main.c
@@ -188,6 +188,17 @@ static int __init set_reset_devices(char *str)
__setup("reset_devices", set_reset_devices);
+int pax_softmode;
+
+#ifdef CONFIG_OPENPAX_SOFTMODE
+static int __init setup_pax_softmode(char *str)
+{
+ get_option(&str, &pax_softmode);
+ return 1;
+}
+__setup("pax_softmode=", setup_pax_softmode);
+#endif
+
static const char *argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
const char *envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
static const char *panic_later, *panic_param;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 1d600ae89f15..44aff4b84516 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1647,6 +1647,18 @@ int proc_do_static_key(const struct ctl_table *table, int write,
return ret;
}
+#ifdef CONFIG_OPENPAX_SOFTMODE
+static const struct ctl_table pax_table[] = {
+ {
+ .procname = "softmode",
+ .data = &pax_softmode,
+ .maxlen = sizeof(int),
+ .mode = 0600,
+ .proc_handler = proc_dointvec,
+ },
+};
+#endif
+
static const struct ctl_table kern_table[] = {
{
.procname = "panic",
@@ -2279,6 +2291,9 @@ int __init sysctl_init_bases(void)
{
register_sysctl_init("kernel", kern_table);
register_sysctl_init("vm", vm_table);
+#ifdef CONFIG_OPENPAX_SOFTMODE
+ register_sysctl_init("kernel/pax", pax_table);
+#endif
return 0;
}
diff --git a/security/Kconfig b/security/Kconfig
index adc4a853ce0d..e9cfe77f08e0 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -311,6 +311,7 @@ config LSM
If unsure, leave this as the default.
source "security/Kconfig.hardening"
+source "security/Kconfig.openpax"
endmenu
diff --git a/security/Kconfig.openpax b/security/Kconfig.openpax
new file mode 100644
index 000000000000..76ee145094d9
--- /dev/null
+++ b/security/Kconfig.openpax
@@ -0,0 +1,89 @@
+#
+# OpenPaX configuration
+#
+
+menu "OpenPaX options"
+
+config OPENPAX
+ bool "Enable OpenPaX features"
+ default y
+ help
+ This configuration setting enables OpenPaX features.
+ OpenPaX adds memory safety-related defenses to the kernel which
+ reduce the risks posed by exploitable memory safety bugs.
+
+config OPENPAX_SOFTMODE
+ bool "Support PaX soft mode"
+ default y
+ help
+ Enabling this option will allow you to configure OpenPaX
+ features to run in soft mode. In this mode, OpenPaX features
+ will be disabled by default, only running on applications
+ which explicitly enable them.
+
+ Soft mode can be enabled via the kernel.pax.softmode sysctl,
+ or the pax_softmode=1 kernel command-line option.
+
+config OPENPAX_XATTR_PAX_FLAGS
+ bool "Use filesystem extended attributes to modify OpenPaX features"
+ depends on OPENPAX
+ default y
+ help
+ Enabling this option will allow you to control whether
+ OpenPaX features are enabled on a per-executable basis via
+ xattr attributes.
+
+ For compatibility with the original PaX patch, the feature
+ flags are read from the user.pax.flags extended attribute.
+
+ If you disable this feature, then all applications will run
+ with OpenPaX enabled by default.
+
+config OPENPAX_MPROTECT
+ bool "Enforce W^X for memory mappings"
+ depends on OPENPAX
+ default y
+ help
+ Enabling this option prevents programs from making pages
+ executable when they are also writable. In addition, it
+ also denies transition of writable mappings to executable
+ mappings.
+
+ This feature is known to break programs which depend on
+ just-in-time (JIT) compilation. It is advisable to enable
+ this feature system-wide, but mark programs which have
+ JIT compilation appropriately so the W^X enforcement is
+ disabled for them.
+
+config OPENPAX_EMUTRAMP
+ bool "Emulate stack and heap trampolines"
+ depends on OPENPAX
+ default y
+ help
+ Enabling this option allows programs to depend on common
+ types of stack and heap trampolines (such as the ones
+ generated by GCC and libffi) to continue working despite
+ the stack and heap being non-executable memory.
+
+ This option works by intercepting the page faults caused
+ by executing code in non-executable memory and emulating
+ the side effects that would have happened from executing
+ the trampoline.
+
+ Most likely, you should say 'y' here.
+
+config OPENPAX_EMUTRAMP_DEFAULT
+ bool "Enable trampoline emulation by default"
+ depends on OPENPAX_EMUTRAMP
+ default y
+ help
+ Enabling this option allows programs which require
+ trampolines to be emulated to continue working by default.
+
+ Otherwise, the emulation flag must be enabled in a binary's
+ PaX marking, e.g. with paxmark -E <binary>.
+
+ If you do not say 'y' here, you will have to manually mark
+ all programs which require trampoline emulation.
+
+endmenu
--
2.49.0

View File

@ -0,0 +1,145 @@
# Copyright 2020-2025 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=8
KERNEL_IUSE_GENERIC_UKI=1
KERNEL_IUSE_MODULES_SIGN=1
inherit kernel-build toolchain-funcs
MY_P=linux-${PV%.*}
GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 1 ))
# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
# forked to https://github.com/projg2/fedora-kernel-config-for-gentoo
CONFIG_VER=6.14.5-gentoo
GENTOO_CONFIG_VER=g16
HARDENED_PATCH_VER="${PV}-hardened1"
GENPATCHES_EXCLUDE="1500_XATTR_USER_PREFIX.patch
1510_fs-enable-link-security-restrictions-by-default.patch
2900_dev-root-proc-mount-fix.patch
4200_fbcondecor.patch
4400_alpha-sysctl-uac.patch"
DESCRIPTION="Linux kernel built with Gentoo patches"
HOMEPAGE="
https://wiki.gentoo.org/wiki/Project:Distribution_Kernel
https://www.kernel.org/
"
SRC_URI+="
https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.base.tar.xz
https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.extras.tar.xz
experimental? (
https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.experimental.tar.xz
)
https://github.com/anthraxx/linux-hardened/releases/download/v${HARDENED_PATCH_VER}/linux-hardened-v${HARDENED_PATCH_VER}.patch
https://github.com/projg2/gentoo-kernel-config/archive/${GENTOO_CONFIG_VER}.tar.gz
-> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
amd64? (
https://raw.githubusercontent.com/projg2/fedora-kernel-config-for-gentoo/${CONFIG_VER}/kernel-x86_64-fedora.config
-> kernel-x86_64-fedora.config.${CONFIG_VER}
)
arm64? (
https://raw.githubusercontent.com/projg2/fedora-kernel-config-for-gentoo/${CONFIG_VER}/kernel-aarch64-fedora.config
-> kernel-aarch64-fedora.config.${CONFIG_VER}
)
ppc64? (
https://raw.githubusercontent.com/projg2/fedora-kernel-config-for-gentoo/${CONFIG_VER}/kernel-ppc64le-fedora.config
-> kernel-ppc64le-fedora.config.${CONFIG_VER}
)
x86? (
https://raw.githubusercontent.com/projg2/fedora-kernel-config-for-gentoo/${CONFIG_VER}/kernel-i686-fedora.config
-> kernel-i686-fedora.config.${CONFIG_VER}
)
"
S=${WORKDIR}/${MY_P}
KEYWORDS="amd64 ~arm arm64 ~hppa ~loong ~ppc ppc64 ~riscv ~sparc x86"
IUSE="debug +experimental"
REQUIRED_USE="
arm? ( savedconfig )
hppa? ( savedconfig )
riscv? ( savedconfig )
sparc? ( savedconfig )
"
RDEPEND="
!sys-kernel/gentoo-kernel-bin:${SLOT}
"
BDEPEND="
debug? ( dev-util/pahole )
"
PDEPEND="
>=virtual/dist-kernel-${PV}
"
QA_FLAGS_IGNORED="
usr/src/linux-.*/scripts/gcc-plugins/.*.so
usr/src/linux-.*/vmlinux
usr/src/linux-.*/arch/powerpc/kernel/vdso.*/vdso.*.so.dbg
"
src_prepare() {
# remove some genpatches causes conflicts with linux-hardened patch
for patch in ${GENPATCHES_EXCLUDE}; do
rm -f ${WORKDIR}/${patch}
done
# Remove already exists changes in linux-hardened patch
sed -i '322,337d' "${WORKDIR}/4567_distro-Gentoo-Kconfig.patch"
# include linux-hardened patch with priority
cp ${DISTDIR}/linux-hardened-v${HARDENED_PATCH_VER}.patch ${WORKDIR}/1198_linux-hardened-${HARDENED_PATCH_VER}.patch
# copy pkg maintainer supplied patches
if [ -d "${FILESDIR}/${MY_P}" ]; then
cp "${FILESDIR}/${MY_P}"/*.patch ${WORKDIR}/
fi
local PATCHES=(
# meh, genpatches have no directory
"${WORKDIR}"/*.patch
)
default
#sed -i "s@\-hardened1@@g" Makefile || die
local biendian=false
# prepare the default config
case ${ARCH} in
amd64)
cp "${FILESDIR}/${MY_P}.amd64.config" .config || die
;;
*)
die "Unsupported arch ${ARCH}"
;;
esac
local myversion="-gentoo-dist"
echo "CONFIG_LOCALVERSION=\"${myversion}\"" > "${T}"/version.config || die
local dist_conf_path="${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"
local merge_configs=(
"${T}"/version.config
)
use debug || merge_configs+=(
"${dist_conf_path}"/no-debug.config
)
merge_configs+=( "${dist_conf_path}"/hardened-base.config )
tc-is-gcc && merge_configs+=( "${dist_conf_path}"/hardened-gcc-plugins.config )
if [[ -f "${dist_conf_path}/hardened-${ARCH}.config" ]]; then
merge_configs+=( "${dist_conf_path}/hardened-${ARCH}.config" )
fi
# this covers ppc64 and aarch64_be only for now
if [[ ${biendian} == true && $(tc-endian) == big ]]; then
merge_configs+=( "${dist_conf_path}/big-endian.config" )
fi
use secureboot && merge_configs+=( "${dist_conf_path}/secureboot.config" )
kernel-build_merge_configs "${merge_configs[@]}"
}