diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 489362b0cd8578f4eeff9a04930a5d25c767ffa5..f58ea2f058815194acd61459ad8b58fa500e5c84 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -176,6 +176,9 @@ LSM_HOOK(int, 0, file_ioctl_compat, struct file *file, unsigned int cmd, LSM_HOOK(int, 0, mmap_addr, unsigned long addr) LSM_HOOK(int, 0, mmap_file, struct file *file, unsigned long reqprot, unsigned long prot, unsigned long flags) +#ifdef CONFIG_SECURITY_XPM +LSM_HOOK(int, 0, mmap_region, struct vm_area_struct *vma) +#endif LSM_HOOK(int, 0, file_mprotect, struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot) LSM_HOOK(int, 0, file_lock, struct file *file, unsigned int cmd) diff --git a/include/linux/mm.h b/include/linux/mm.h index bf5d0b1b16f4341e8851d9bdfef30df631f62226..7179e3f6a0304b87cdfdf004383b55c301ac93b6 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -320,14 +320,22 @@ extern unsigned int kobjsize(const void *objp); #define VM_HIGH_ARCH_BIT_3 35 /* bit only usable on 64-bit architectures */ #define VM_HIGH_ARCH_BIT_4 36 /* bit only usable on 64-bit architectures */ #define VM_HIGH_ARCH_BIT_5 37 /* bit only usable on 64-bit architectures */ +#define VM_HIGH_ARCH_BIT_7 39 /* bit only usable on 64-bit architectures */ #define VM_HIGH_ARCH_0 BIT(VM_HIGH_ARCH_BIT_0) #define VM_HIGH_ARCH_1 BIT(VM_HIGH_ARCH_BIT_1) #define VM_HIGH_ARCH_2 BIT(VM_HIGH_ARCH_BIT_2) #define VM_HIGH_ARCH_3 BIT(VM_HIGH_ARCH_BIT_3) #define VM_HIGH_ARCH_4 BIT(VM_HIGH_ARCH_BIT_4) #define VM_HIGH_ARCH_5 BIT(VM_HIGH_ARCH_BIT_5) +#define VM_HIGH_ARCH_7 BIT(VM_HIGH_ARCH_BIT_7) #endif /* CONFIG_ARCH_USES_HIGH_VMA_FLAGS */ +#ifdef CONFIG_SECURITY_XPM +#define VM_XPM VM_HIGH_ARCH_7 +#else /* CONFIG_SECURITY_XPM */ +#define VM_XPM VM_NONE +#endif /* CONFIG_SECURITY_XPM */ + #ifdef CONFIG_ARCH_HAS_PKEYS # define VM_PKEY_SHIFT VM_HIGH_ARCH_BIT_0 # define VM_PKEY_BIT0 VM_HIGH_ARCH_0 /* A protection key is a 4-bit value */ @@ -3318,6 +3326,7 @@ extern unsigned long __must_check vm_mmap(struct file *, unsigned long, struct vm_unmapped_area_info { #define VM_UNMAPPED_AREA_TOPDOWN 1 +#define VM_UNMAPPED_AREA_XPM 2 unsigned long flags; unsigned long length; unsigned long low_limit; diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 36c5b43999e608a84fda4f34c07e0df3e7884ac3..db7003d2886f0e687e7ad4d27475b82a561e7404 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -917,6 +918,14 @@ struct mm_struct { #endif } lru_gen; #endif /* CONFIG_LRU_GEN */ + +#ifdef CONFIG_SECURITY_XPM + struct xpm_region xpm_region; +#endif + +#ifdef CONFIG_SECURITY_CODE_SIGN + struct cs_info pcs_info; +#endif } __randomize_layout; /* diff --git a/include/linux/mman.h b/include/linux/mman.h index 40d94411d49204e7276a6ad9554eb17335fd4577..754ff3e912e54a3206f19d8fe4f0e927cc07f0eb 100644 --- a/include/linux/mman.h +++ b/include/linux/mman.h @@ -156,6 +156,7 @@ calc_vm_flag_bits(unsigned long flags) return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) | _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ) | _calc_vm_trans(flags, MAP_SYNC, VM_SYNC ) | + _calc_vm_trans(flags, MAP_XPM, VM_XPM ) | arch_calc_vm_flag_bits(flags); } diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h index f86a08ba0207ee1dd1bb704b6380d55b2d3feb1f..704c7d819139d846a6479f6c5d64bf3d09e50583 100644 --- a/include/linux/oid_registry.h +++ b/include/linux/oid_registry.h @@ -136,6 +136,9 @@ enum OID { OID_SM2_with_SM3, /* 1.2.156.10197.1.501 */ OID_sm3WithRSAEncryption, /* 1.2.156.10197.1.504 */ + /* Code signature defined OIDS */ + OID_ownerid, /* 1.3.6.1.4.1.2011.2.376.1.4.1 */ + /* TCG defined OIDS for TPM based keys */ OID_TPMLoadableKey, /* 2.23.133.10.1.3 */ OID_TPMImportableKey, /* 2.23.133.10.1.4 */ diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 5c02720c53a5848e37f03beeadb2ac787a6a91f4..4d2e0c913baf37f3293702f95e5c6cad4fe3391d 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -135,6 +135,10 @@ enum pageflags { #ifdef CONFIG_ARCH_USES_PG_ARCH_X PG_arch_2, PG_arch_3, +#endif +#ifdef CONFIG_SECURITY_XPM + PG_xpm_readonly, + PG_xpm_writetainted, #endif __NR_PAGEFLAGS, @@ -481,6 +485,14 @@ PAGEFLAG(Workingset, workingset, PF_HEAD) __PAGEFLAG(Slab, slab, PF_NO_TAIL) PAGEFLAG(Checked, checked, PF_NO_COMPOUND) /* Used by some filesystems */ +#ifdef CONFIG_SECURITY_XPM +PAGEFLAG(XPMReadonly, xpm_readonly, PF_HEAD) +PAGEFLAG(XPMWritetainted, xpm_writetainted, PF_HEAD) +#else +PAGEFLAG_FALSE(XPMReadonly) +PAGEFLAG_FALSE(XPMWritetainted) +#endif + /* Xen */ PAGEFLAG(Pinned, pinned, PF_NO_COMPOUND) TESTSCFLAG(Pinned, pinned, PF_NO_COMPOUND) @@ -1050,6 +1062,12 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page) #define __PG_MLOCKED 0 #endif +#ifdef CONFIG_SECURITY_XPM +#define __XPM_PAGE_FLAGS (1UL << PG_xpm_readonly | 1UL << PG_xpm_writetainted) +#else +#define __XPM_PAGE_FLAGS 0 +#endif + /* * Flags checked when a page is freed. Pages being freed should not have * these flags set. If they are, there is a problem. @@ -1059,6 +1077,7 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page) 1UL << PG_private | 1UL << PG_private_2 | \ 1UL << PG_writeback | 1UL << PG_reserved | \ 1UL << PG_slab | 1UL << PG_active | \ + __XPM_PAGE_FLAGS | \ 1UL << PG_unevictable | __PG_MLOCKED | LRU_GEN_MASK) /* diff --git a/include/linux/security.h b/include/linux/security.h index b50c7f56618905b19192d0dbd6a040217e959a78..897ef945d0cfdf89ec801f42d548583098829ccd 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -2111,6 +2111,15 @@ static inline int security_perf_event_write(struct perf_event *event) #endif /* CONFIG_SECURITY */ #endif /* CONFIG_PERF_EVENTS */ +#if IS_ENABLED(CONFIG_SECURITY) && IS_ENABLED(CONFIG_SECURITY_XPM) +extern int security_mmap_region(struct vm_area_struct *vma); +#else +static inline int security_mmap_region(struct vm_area_struct *vma) +{ + return 0; +} +#endif /* CONFIG_SECURITY && CONFIG_SECURITY_XPM */ + #ifdef CONFIG_IO_URING #ifdef CONFIG_SECURITY extern int security_uring_override_creds(const struct cred *new); diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h index 1478b9dd05fae42e2c41eeee83e05d583a966b87..bd547551177376105a4c066eae7f687406a6e318 100644 --- a/include/trace/events/mmflags.h +++ b/include/trace/events/mmflags.h @@ -65,6 +65,12 @@ __def_gfpflag_names __def_gfpflag_names_kasan \ ) : "none" +#ifdef CONFIG_SECURITY_XPM +#define IF_HAVE_PG_XPM_INTEGRITY(flag,string) ,{1UL << flag, string} +#else +#define IF_HAVE_PG_XPM_INTEGRITY(flag,string) +#endif + #ifdef CONFIG_MMU #define IF_HAVE_PG_MLOCK(_name) ,{1UL << PG_##_name, __stringify(_name)} #else @@ -126,6 +132,8 @@ IF_HAVE_PG_IDLE(idle) \ IF_HAVE_PG_IDLE(young) \ IF_HAVE_PG_ARCH_X(arch_2) \ IF_HAVE_PG_ARCH_X(arch_3) +IF_HAVE_PG_ARCH_X(xpm_readonly) \ +IF_HAVE_PG_ARCH_X(xpm_writetainted) #define show_page_flags(flags) \ (flags) ? __print_flags(flags, "|", \ diff --git a/include/uapi/asm-generic/mman-common.h b/include/uapi/asm-generic/mman-common.h index 2b18883487ac92545cc82d7525b5b38a374cef72..98172b9311c74502aa7c9a41c699a1cffd7fbbc6 100644 --- a/include/uapi/asm-generic/mman-common.h +++ b/include/uapi/asm-generic/mman-common.h @@ -21,6 +21,7 @@ #define MAP_TYPE 0x0f /* Mask for type of mapping */ #define MAP_FIXED 0x10 /* Interpret addr exactly */ #define MAP_ANONYMOUS 0x20 /* don't use a file */ +#define MAP_XPM 0x40 /* xpm control memory */ /* 0x0100 - 0x4000 flags are defined in asm-generic/mman.h */ #define MAP_POPULATE 0x008000 /* populate (prefault) pagetables */ diff --git a/security/Kconfig b/security/Kconfig index f01e53cce1d9f17cb24b40ae99a3d8032c5e03dd..89e5dbcb46e00c4addb74c42ec131d801cf6af08 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -193,6 +193,7 @@ source "security/loadpin/Kconfig" source "security/yama/Kconfig" source "security/safesetid/Kconfig" source "security/lockdown/Kconfig" +source "security/xpm/Kconfig" source "security/landlock/Kconfig" source "security/container_escape_detection/Kconfig" diff --git a/security/Makefile b/security/Makefile index 9405ac9c85faba0f9edbde3a738b72e958efc07a..1fbed3e27486a1782a1f8be1139172a1b541009a 100644 --- a/security/Makefile +++ b/security/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_SECURITY_SAFESETID) += safesetid/ obj-$(CONFIG_SECURITY_LOCKDOWN_LSM) += lockdown/ obj-$(CONFIG_CGROUPS) += device_cgroup.o obj-$(CONFIG_BPF_LSM) += bpf/ +obj-$(CONFIG_SECURITY_XPM) += xpm/ obj-$(CONFIG_SECURITY_LANDLOCK) += landlock/ obj-$(CONFIG_SECURITY_CONTAINER_ESCAPE_DETECTION) += container_escape_detection/ diff --git a/security/security.c b/security/security.c index 407b51719f79765db414a04170a78aa26dbf45db..ffd622209e0351e2883825466ca9f850e0f60749 100644 --- a/security/security.c +++ b/security/security.c @@ -5349,6 +5349,21 @@ int security_perf_event_write(struct perf_event *event) } #endif /* CONFIG_PERF_EVENTS */ +/** + * security_mmap_region() - Check if mmap region is allowed + * @vma: vm area + * + * Mmap region if allowed. + * + * Return: Returns 0 if permission is granted. + */ +#ifdef CONFIG_SECURITY_XPM +int security_mmap_region(struct vm_area_struct *vma) +{ + return call_int_hook(mmap_region, 0, vma); +} +#endif + #ifdef CONFIG_IO_URING /** * security_uring_override_creds() - Check if overriding creds is allowed diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 3ea4602a2c1477d4702d700a8b92990abdfaa14f..2c4e9fb3c6d3a9dff328b5377aba8a0c337dccc0 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -264,6 +264,8 @@ const struct security_class_mapping secclass_map[] = { { "container_escape_check", NULL} }, { "code_sign", { "add_cert_chain", "remove_cert_chain", NULL } }, + { "xpm", + { "exec_no_sign", "exec_anon_mem", NULL } }, { NULL } };