Headline
CVE-2023-0597: git/torvalds/linux.git - Linux kernel source tree
A flaw possibility of memory leak in the Linux kernel cpu_entry_area mapping of X86 CPU data to memory was found in the way user can guess location of exception stack(s) or other important data. A local user could use this flaw to get access to some important data with expected location in memory.
Seth found that the CPU-entry-area; the piece of per-cpu data that is mapped into the userspace page-tables for kPTI is not subject to any randomization – irrespective of kASLR settings. On x86_64 a whole P4D (512 GB) of virtual address space is reserved for this structure, which is plenty large enough to randomize things a little. As such, use a straight forward randomization scheme that avoids duplicates to spread the existing CPUs over the available space. [ bp: Fix le build. ] Reported-by: Seth Jenkins [email protected] Reviewed-by: Kees Cook [email protected] Signed-off-by: Peter Zijlstra (Intel) [email protected] Signed-off-by: Dave Hansen [email protected] Signed-off-by: Borislav Petkov [email protected]
@@ -130,10 +130,6 @@ struct cpu_entry_area {
};
#define CPU_ENTRY_AREA_SIZE (sizeof(struct cpu_entry_area))
-#define CPU_ENTRY_AREA_ARRAY_SIZE (CPU_ENTRY_AREA_SIZE * NR_CPUS)
-
-/* Total size includes the readonly IDT mapping page as well: */
-#define CPU_ENTRY_AREA_TOTAL_SIZE (CPU_ENTRY_AREA_ARRAY_SIZE + PAGE_SIZE)
DECLARE_PER_CPU(struct cpu_entry_area *, cpu_entry_area);
DECLARE_PER_CPU(struct cea_exception_stacks *, cea_exception_stacks);
@@ -11,6 +11,12 @@
#define CPU_ENTRY_AREA_RO_IDT_VADDR ((void *)CPU_ENTRY_AREA_RO_IDT)
-#define CPU_ENTRY_AREA_MAP_SIZE (CPU_ENTRY_AREA_PER_CPU + CPU_ENTRY_AREA_ARRAY_SIZE - CPU_ENTRY_AREA_BASE)
+#ifdef CONFIG_X86_32
+#define CPU_ENTRY_AREA_MAP_SIZE (CPU_ENTRY_AREA_PER_CPU + \
+ (CPU_ENTRY_AREA_SIZE * NR_CPUS) - \
+ CPU_ENTRY_AREA_BASE)
+#else
+#define CPU_ENTRY_AREA_MAP_SIZE P4D_SIZE
+#endif
#endif /* _ASM_X86_PGTABLE_AREAS_H */
@@ -266,7 +266,7 @@ static inline bool within_cpu_entry(unsigned long addr, unsigned long end)
/* CPU entry erea is always used for CPU entry */
if (within_area(addr, end, CPU_ENTRY_AREA_BASE,
- CPU_ENTRY_AREA_TOTAL_SIZE))
+ CPU_ENTRY_AREA_MAP_SIZE))
return true;
/*
@@ -16,16 +16,53 @@ static DEFINE_PER_CPU_PAGE_ALIGNED(struct entry_stack_page, entry_stack_storage)
#ifdef CONFIG_X86_64
static DEFINE_PER_CPU_PAGE_ALIGNED(struct exception_stacks, exception_stacks);
DEFINE_PER_CPU(struct cea_exception_stacks*, cea_exception_stacks);
-#endif
-#ifdef CONFIG_X86_32
+static DEFINE_PER_CPU_READ_MOSTLY(unsigned long, _cea_offset);
+static __always_inline unsigned int cea_offset(unsigned int cpu)
+{
+ return per_cpu(_cea_offset, cpu);
+}
+static __init void init_cea_offsets(void)
+{
+ unsigned int max_cea;
+ unsigned int i, j;
+ max_cea = (CPU_ENTRY_AREA_MAP_SIZE - PAGE_SIZE) / CPU_ENTRY_AREA_SIZE;
+ /* O(sodding terrible) */
+ for_each_possible_cpu(i) {
+ unsigned int cea;
+again:
+ cea = prandom_u32_max(max_cea);
+ for_each_possible_cpu(j) {
+ if (cea_offset(j) == cea)
+ goto again;
+ if (i == j)
+ break;
+ }
+ per_cpu(_cea_offset, i) = cea;
+ }
+}
+#else /* !X86_64 */
DECLARE_PER_CPU_PAGE_ALIGNED(struct doublefault_stack, doublefault_stack);
+static __always_inline unsigned int cea_offset(unsigned int cpu)
+{
+ return cpu;
+}
+static inline void init_cea_offsets(void) { }
#endif
/* Is called from entry code, so must be noinstr */
noinstr struct cpu_entry_area *get_cpu_entry_area(int cpu)
{
- unsigned long va = CPU_ENTRY_AREA_PER_CPU + cpu * CPU_ENTRY_AREA_SIZE;
+ unsigned long va = CPU_ENTRY_AREA_PER_CPU + cea_offset(cpu) * CPU_ENTRY_AREA_SIZE;
BUILD_BUG_ON(sizeof(struct cpu_entry_area) % PAGE_SIZE != 0);
return (struct cpu_entry_area *) va;
@@ -211,7 +248,6 @@ static __init void setup_cpu_entry_area_ptes(void)
/* The +1 is for the readonly IDT: */
BUILD_BUG_ON((CPU_ENTRY_AREA_PAGES+1)*PAGE_SIZE != CPU_ENTRY_AREA_MAP_SIZE);
- BUILD_BUG_ON(CPU_ENTRY_AREA_TOTAL_SIZE != CPU_ENTRY_AREA_MAP_SIZE);
BUG_ON(CPU_ENTRY_AREA_BASE & ~PMD_MASK);
start = CPU_ENTRY_AREA_BASE;
@@ -227,6 +263,8 @@ void __init setup_cpu_entry_areas(void)
{
unsigned int cpu;
+ init_cea_offsets();
setup_cpu_entry_area_ptes();
for_each_possible_cpu(cpu)
Related news
Red Hat Security Advisory 2024-1188-03 - An update for kernel is now available for Red Hat Enterprise Linux 8.6 Extended Update Support. Issues addressed include code execution, denial of service, memory leak, out of bounds read, out of bounds write, and use-after-free vulnerabilities.
Red Hat Security Advisory 2023-7077-01 - An update for kernel is now available for Red Hat Enterprise Linux 8. Issues addressed include buffer overflow, denial of service, double free, information leakage, memory leak, null pointer, out of bounds access, out of bounds write, and use-after-free vulnerabilities.
Ubuntu Security Notice 6462-2 - Seth Jenkins discovered that the Linux kernel did not properly perform address randomization for a per-cpu memory management structure. A local attacker could use this to expose sensitive information or in conjunction with another kernel vulnerability. Yu Hao and Weiteng Chen discovered that the Bluetooth HCI UART driver in the Linux kernel contained a race condition, leading to a null pointer dereference vulnerability. A local attacker could use this to cause a denial of service.
Ubuntu Security Notice 6440-2 - Seth Jenkins discovered that the Linux kernel did not properly perform address randomization for a per-cpu memory management structure. A local attacker could use this to expose sensitive information or in conjunction with another kernel vulnerability. It was discovered that the IPv6 implementation in the Linux kernel contained a high rate of hash collisions in connection lookup table. A remote attacker could use this to cause a denial of service.
Ubuntu Security Notice 6440-1 - Seth Jenkins discovered that the Linux kernel did not properly perform address randomization for a per-cpu memory management structure. A local attacker could use this to expose sensitive information or in conjunction with another kernel vulnerability. It was discovered that the IPv6 implementation in the Linux kernel contained a high rate of hash collisions in connection lookup table. A remote attacker could use this to cause a denial of service.
Ubuntu Security Notice 6347-1 - William Zhao discovered that the Traffic Control subsystem in the Linux kernel did not properly handle network packet retransmission in certain situations. A local attacker could use this to cause a denial of service. It was discovered that the NTFS file system implementation in the Linux kernel did not properly check buffer indexes in certain situations, leading to an out-of-bounds read vulnerability. A local attacker could possibly use this to expose sensitive information.
Ubuntu Security Notice 6332-1 - Daniel Moghimi discovered that some Intel Processors did not properly clear microarchitectural state after speculative execution of various instructions. A local unprivileged user could use this to obtain to sensitive information. William Zhao discovered that the Traffic Control subsystem in the Linux kernel did not properly handle network packet retransmission in certain situations. A local attacker could use this to cause a denial of service.
Ubuntu Security Notice 6311-1 - William Zhao discovered that the Traffic Control subsystem in the Linux kernel did not properly handle network packet retransmission in certain situations. A local attacker could use this to cause a denial of service. It was discovered that the NTFS file system implementation in the Linux kernel did not properly check buffer indexes in certain situations, leading to an out-of-bounds read vulnerability. A local attacker could possibly use this to expose sensitive information.
Ubuntu Security Notice 6300-1 - William Zhao discovered that the Traffic Control subsystem in the Linux kernel did not properly handle network packet retransmission in certain situations. A local attacker could use this to cause a denial of service. It was discovered that the NTFS file system implementation in the Linux kernel did not properly check buffer indexes in certain situations, leading to an out-of-bounds read vulnerability. A local attacker could possibly use this to expose sensitive information.
Ubuntu Security Notice 6235-1 - It was discovered that the NTFS file system implementation in the Linux kernel contained a null pointer dereference in some situations. A local attacker could use this to cause a denial of service. Jordy Zomer and Alexandra Sandulescu discovered that the Linux kernel did not properly implement speculative execution barriers in usercopy functions in certain situations. A local attacker could use this to expose sensitive information.
Ubuntu Security Notice 6206-1 - Hangyu Hua discovered that the Flower classifier implementation in the Linux kernel contained an out-of-bounds write vulnerability. An attacker could use this to cause a denial of service or possibly execute arbitrary code. It was discovered that the NTFS file system implementation in the Linux kernel contained a null pointer dereference in some situations. A local attacker could use this to cause a denial of service.
Dell VxRail, version(s) 8.0.100 and earlier contain a denial-of-service vulnerability in the upgrade functionality. A remote unauthenticated attacker could potentially exploit this vulnerability, leading to degraded performance and system malfunction.
Dell SCG 5.14 contains an information disclosure vulnerability during the SRS to SCG upgrade path. A remote low privileged malicious user could potentially exploit this vulnerability to retrieve the plain text.