From: Zhuling zhuling8@huawei.com
euleros inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4O31I?from=project-issue CVE: NA
--------------------------------
The reserve memory of PMEM conflicts with "add memmap interface to reserved memory for mremap syscall usage", need to rollback, resubmit after adaptation.
Feature related commit: 1.PMEM function commit: 94dc364f5eda10f49449ba573dc3322e1ea92280 2.PMEM feature config commit: 36d7a831e15ceb84e937122c87d01c14242dc377
Signed-off-by: Zhuling zhuling8@huawei.com Reviewed-by: Sang Yan sangyan@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/Kconfig | 21 ------ arch/arm64/configs/openeuler_defconfig | 3 - arch/arm64/kernel/Makefile | 1 - arch/arm64/kernel/pmem.c | 35 ---------- arch/arm64/kernel/setup.c | 10 --- arch/arm64/mm/init.c | 94 -------------------------- drivers/nvdimm/Kconfig | 5 -- drivers/nvdimm/Makefile | 1 - 8 files changed, 170 deletions(-) delete mode 100644 arch/arm64/kernel/pmem.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index df90a6e05ad2..2df4b310eb23 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1321,27 +1321,6 @@ config RODATA_FULL_DEFAULT_ENABLED This requires the linear region to be mapped down to pages, which may adversely affect performance in some cases.
-config ARM64_PMEM_RESERVE - bool "Reserve memory for persistent storage" - default n - help - Use memmap=nn[KMG]!ss[KMG](memmap=100K!0x1a0000000) reserve - memory for persistent storage. - - Say y here to enable this feature. - -config ARM64_PMEM_LEGACY_DEVICE - bool "Create persistent storage" - depends on BLK_DEV - depends on LIBNVDIMM - select ARM64_PMEM_RESERVE - help - Use reserved memory for persistent storage when the kernel - restart or update. the data in PMEM will not be lost and - can be loaded faster. - - Say y if unsure. - config ARM64_SW_TTBR0_PAN bool "Emulate Privileged Access Never using TTBR0_EL1 switching" help diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 17bc8750bba7..b5fc851f1949 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -416,8 +416,6 @@ CONFIG_ARM64_CPU_PARK=y CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_UNMAP_KERNEL_AT_EL0=y CONFIG_RODATA_FULL_DEFAULT_ENABLED=y -CONFIG_ARM64_PMEM_RESERVE=y -CONFIG_ARM64_PMEM_LEGACY_DEVICE=y # CONFIG_ARM64_SW_TTBR0_PAN is not set CONFIG_ARM64_TAGGED_ADDR_ABI=y CONFIG_ARM64_ILP32=y @@ -6026,7 +6024,6 @@ CONFIG_ND_BTT=m CONFIG_BTT=y CONFIG_OF_PMEM=m CONFIG_NVDIMM_KEYS=y -CONFIG_PMEM_LEGACY=m CONFIG_DAX_DRIVER=y CONFIG_DAX=y CONFIG_DEV_DAX=m diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index f6153250b631..169d90f11cf5 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -68,7 +68,6 @@ obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o obj-$(CONFIG_ARM64_MTE) += mte.o obj-$(CONFIG_MPAM) += mpam/ -obj-$(CONFIG_ARM64_PMEM_LEGACY_DEVICE) += pmem.o
obj-y += vdso/ probes/ obj-$(CONFIG_COMPAT_VDSO) += vdso32/ diff --git a/arch/arm64/kernel/pmem.c b/arch/arm64/kernel/pmem.c deleted file mode 100644 index 16eaf706f671..000000000000 --- a/arch/arm64/kernel/pmem.c +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2021 Huawei Technologies Co., Ltd - * - * Derived from x86 and arm64 implement PMEM. - */ -#include <linux/platform_device.h> -#include <linux/init.h> -#include <linux/ioport.h> -#include <linux/module.h> - -static int found(struct resource *res, void *data) -{ - return 1; -} - -static int __init register_e820_pmem(void) -{ - struct platform_device *pdev; - int rc; - - rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY, - IORESOURCE_MEM, 0, -1, NULL, found); - if (rc <= 0) - return 0; - - /* - * See drivers/nvdimm/e820.c for the implementation, this is - * simply here to trigger the module to load on demand. - */ - pdev = platform_device_alloc("e820_pmem", -1); - - return platform_device_add(pdev); -} -device_initcall(register_e820_pmem); diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 88ec49504001..7cd042536d3b 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -70,10 +70,6 @@ static int __init arm64_enable_cpu0_hotplug(char *str) __setup("arm64_cpu0_hotplug", arm64_enable_cpu0_hotplug); #endif
-#ifdef CONFIG_ARM64_PMEM_RESERVE -extern struct resource pmem_res; -#endif - phys_addr_t __fdt_pointer __initdata;
/* @@ -288,12 +284,6 @@ static void __init request_standard_resources(void) request_resource(res, &pin_memory_resource); #endif } - -#ifdef CONFIG_ARM64_PMEM_RESERVE - if (pmem_res.end && pmem_res.start) - request_resource(&iomem_resource, &pmem_res); -#endif - }
static int __init reserve_memblock_reserved_regions(void) diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 3b9401ee9c58..e8d446164c76 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -55,7 +55,6 @@ */ s64 memstart_addr __ro_after_init = -1; EXPORT_SYMBOL(memstart_addr); -phys_addr_t start_at, mem_size;
#ifdef CONFIG_PIN_MEMORY struct resource pin_memory_resource = { @@ -112,18 +111,6 @@ static void __init reserve_pin_memory_res(void) */ phys_addr_t arm64_dma_phys_limit __ro_after_init;
-static unsigned long long pmem_size, pmem_start; - -#ifdef CONFIG_ARM64_PMEM_RESERVE -struct resource pmem_res = { - .name = "Persistent Memory (legacy)", - .start = 0, - .end = 0, - .flags = IORESOURCE_MEM, - .desc = IORES_DESC_PERSISTENT_MEMORY_LEGACY -}; -#endif - #ifndef CONFIG_KEXEC_CORE static void __init reserve_crashkernel(void) { @@ -417,83 +404,6 @@ static int __init reserve_park_mem(void) } #endif
-static bool __init is_mem_valid(unsigned long long mem_size, unsigned long long mem_start) -{ - if (!memblock_is_region_memory(mem_start, mem_size)) { - pr_warn("cannot reserve mem: region is not memory!\n"); - return false; - } - - if (memblock_is_region_reserved(mem_start, mem_size)) { - pr_warn("cannot reserve mem: region overlaps reserved memory!\n"); - return false; - } - - if (!IS_ALIGNED(mem_start, SZ_2M)) { - pr_warn("cannot reserve mem: base address is not 2MB aligned!\n"); - return false; - } - - return true; -} - -static int __init parse_memmap_one(char *p) -{ - char *oldp; - - if (!p) - return -EINVAL; - - oldp = p; - mem_size = memparse(p, &p); - if (p == oldp) - return -EINVAL; - - if (!mem_size) - return -EINVAL; - - mem_size = PAGE_ALIGN(mem_size); - - if (*p == '!') { - start_at = memparse(p+1, &p); - - pmem_start = start_at; - pmem_size = mem_size; - } else - pr_info("Unrecognized memmap option, please check the parameter.\n"); - - return *p == '\0' ? 0 : -EINVAL; -} - -static int __init parse_memmap_opt(char *str) -{ - while (str) { - char *k = strchr(str, ','); - - if (k) - *k++ = 0; - parse_memmap_one(str); - str = k; - } - - return 0; -} -early_param("memmap", parse_memmap_opt); - -#ifdef CONFIG_ARM64_PMEM_RESERVE -static void __init reserve_pmem(void) -{ - if (!is_mem_valid(mem_size, start_at)) - return; - - memblock_remove(pmem_start, pmem_size); - pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n", - pmem_start, pmem_start + pmem_size, pmem_size >> 20); - pmem_res.start = pmem_start; - pmem_res.end = pmem_start + pmem_size - 1; -} -#endif - void __init arm64_memblock_init(void) { const s64 linear_region_size = BIT(vabits_actual - 1); @@ -668,10 +578,6 @@ void __init bootmem_init(void) reserve_quick_kexec(); #endif
-#ifdef CONFIG_ARM64_PMEM_RESERVE - reserve_pmem(); -#endif - reserve_pin_memory_res();
memblock_dump_all(); diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig index ce4de75262b9..b7d1eb38b27d 100644 --- a/drivers/nvdimm/Kconfig +++ b/drivers/nvdimm/Kconfig @@ -132,8 +132,3 @@ config NVDIMM_TEST_BUILD infrastructure.
endif - -config PMEM_LEGACY - tristate "Pmem_legacy" - select X86_PMEM_LEGACY if X86 - select ARM64_PMEM_LEGACY_DEVICE if ARM64 diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile index 6f8dc9242a81..04077532f7ed 100644 --- a/drivers/nvdimm/Makefile +++ b/drivers/nvdimm/Makefile @@ -3,7 +3,6 @@ obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o obj-$(CONFIG_ND_BTT) += nd_btt.o obj-$(CONFIG_ND_BLK) += nd_blk.o -obj-$(CONFIG_PMEM_LEGACY) += nd_e820.o obj-$(CONFIG_OF_PMEM) += of_pmem.o obj-$(CONFIG_VIRTIO_PMEM) += virtio_pmem.o nd_virtio.o
From: Thomas Gleixner tglx@linutronix.de
mainline inclusion from mainline-5.11-rc1 commit 372acbbaa80940189593f9d69c7c069955f24f7a category: feature feature: Deep isolation bugzilla: https://gitee.com/openeuler/kernel/issues/I4N00D CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
No point in doing calculations.
tick_next_period = last_jiffies_update + tick_period
Just check whether now is before tick_next_period to figure out whether jiffies need an update.
Add a comment why the intentional data race in the quick check is safe or not so safe in a 32bit corner case and why we don't worry about it.
Signed-off-by: Thomas Gleixner tglx@linutronix.de Link: https://lore.kernel.org/r/20201117132006.337366695@linutronix.de Signed-off-by: Yunfeng Ye yeyunfeng@huawei.com Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Chen Hui judy.chenhui@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- kernel/time/tick-sched.c | 46 ++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 13 deletions(-)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index e8d351b7f9b0..82a56b8bcd60 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -57,11 +57,29 @@ static void tick_do_update_jiffies64(ktime_t now) ktime_t delta;
/* - * Do a quick check without holding jiffies_lock: - * The READ_ONCE() pairs with two updates done later in this function. + * Do a quick check without holding jiffies_lock. The READ_ONCE() + * pairs with the update done later in this function. + * + * This is also an intentional data race which is even safe on + * 32bit in theory. If there is a concurrent update then the check + * might give a random answer. It does not matter because if it + * returns then the concurrent update is already taking care, if it + * falls through then it will pointlessly contend on jiffies_lock. + * + * Though there is one nasty case on 32bit due to store tearing of + * the 64bit value. If the first 32bit store makes the quick check + * return on all other CPUs and the writing CPU context gets + * delayed to complete the second store (scheduled out on virt) + * then jiffies can become stale for up to ~2^32 nanoseconds + * without noticing. After that point all CPUs will wait for + * jiffies lock. + * + * OTOH, this is not any different than the situation with NOHZ=off + * where one CPU is responsible for updating jiffies and + * timekeeping. If that CPU goes out for lunch then all other CPUs + * will operate on stale jiffies until it decides to come back. */ - delta = ktime_sub(now, READ_ONCE(last_jiffies_update)); - if (delta < tick_period) + if (ktime_before(now, READ_ONCE(tick_next_period))) return;
/* Reevaluate with jiffies_lock held */ @@ -72,9 +90,8 @@ static void tick_do_update_jiffies64(ktime_t now) if (delta >= tick_period) {
delta = ktime_sub(delta, tick_period); - /* Pairs with the lockless read in this function. */ - WRITE_ONCE(last_jiffies_update, - ktime_add(last_jiffies_update, tick_period)); + last_jiffies_update = ktime_add(last_jiffies_update, + tick_period);
/* Slow path for long timeouts */ if (unlikely(delta >= tick_period)) { @@ -82,15 +99,18 @@ static void tick_do_update_jiffies64(ktime_t now)
ticks = ktime_divns(delta, incr);
- /* Pairs with the lockless read in this function. */ - WRITE_ONCE(last_jiffies_update, - ktime_add_ns(last_jiffies_update, - incr * ticks)); + last_jiffies_update = ktime_add_ns(last_jiffies_update, + incr * ticks); } do_timer(++ticks);
- /* Keep the tick_next_period variable up to date */ - tick_next_period = ktime_add(last_jiffies_update, tick_period); + /* + * Keep the tick_next_period variable up to date. + * WRITE_ONCE() pairs with the READ_ONCE() in the lockless + * quick check above. + */ + WRITE_ONCE(tick_next_period, + ktime_add(last_jiffies_update, tick_period)); } else { write_seqcount_end(&jiffies_seq); raw_spin_unlock(&jiffies_lock);
From: Yunfeng Ye yeyunfeng@huawei.com
mainline inclusion from mainline-5.11-rc1 commit 94ad2e3cedb82af034f6d97c58022f162b669f9b category: feature feature: Deep isolation bugzilla: https://gitee.com/openeuler/kernel/issues/I4N00D CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
If jiffies are up to date already (caller lost the race against another CPU) there is no point to change the sequence count. Doing that just forces other CPUs into the seqcount retry loop in tick_nohz_next_event() for nothing.
Just bail out early.
[ tglx: Rewrote most of it ]
Signed-off-by: Yunfeng Ye yeyunfeng@huawei.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Link: https://lore.kernel.org/r/20201117132006.462195901@linutronix.de Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Chen Hui judy.chenhui@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- kernel/time/tick-sched.c | 47 +++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 25 deletions(-)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 82a56b8bcd60..a2a26a8feae6 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -84,38 +84,35 @@ static void tick_do_update_jiffies64(ktime_t now)
/* Reevaluate with jiffies_lock held */ raw_spin_lock(&jiffies_lock); + if (ktime_before(now, tick_next_period)) { + raw_spin_unlock(&jiffies_lock); + return; + } + write_seqcount_begin(&jiffies_seq);
- delta = ktime_sub(now, last_jiffies_update); - if (delta >= tick_period) { + last_jiffies_update = ktime_add(last_jiffies_update, tick_period);
- delta = ktime_sub(delta, tick_period); - last_jiffies_update = ktime_add(last_jiffies_update, - tick_period); + delta = ktime_sub(now, tick_next_period); + if (unlikely(delta >= tick_period)) { + /* Slow path for long idle sleep times */ + s64 incr = ktime_to_ns(tick_period);
- /* Slow path for long timeouts */ - if (unlikely(delta >= tick_period)) { - s64 incr = ktime_to_ns(tick_period); + ticks = ktime_divns(delta, incr);
- ticks = ktime_divns(delta, incr); + last_jiffies_update = ktime_add_ns(last_jiffies_update, + incr * ticks); + }
- last_jiffies_update = ktime_add_ns(last_jiffies_update, - incr * ticks); - } - do_timer(++ticks); + do_timer(++ticks); + + /* + * Keep the tick_next_period variable up to date. WRITE_ONCE() + * pairs with the READ_ONCE() in the lockless quick check above. + */ + WRITE_ONCE(tick_next_period, + ktime_add(last_jiffies_update, tick_period));
- /* - * Keep the tick_next_period variable up to date. - * WRITE_ONCE() pairs with the READ_ONCE() in the lockless - * quick check above. - */ - WRITE_ONCE(tick_next_period, - ktime_add(last_jiffies_update, tick_period)); - } else { - write_seqcount_end(&jiffies_seq); - raw_spin_unlock(&jiffies_lock); - return; - } write_seqcount_end(&jiffies_seq); raw_spin_unlock(&jiffies_lock); update_wall_time();
From: Thomas Gleixner tglx@linutronix.de
mainline inclusion from mainline-5.11-rc1 commit 7a35bf2a6a871cd0252cd371d741e7d070b53af9 category: feature feature: Deep isolation bugzilla: https://gitee.com/openeuler/kernel/issues/I4N00D CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Now that it's clear that there is always one tick to account, simplify the calculations some more.
Signed-off-by: Thomas Gleixner tglx@linutronix.de Link: https://lore.kernel.org/r/20201117132006.565663056@linutronix.de Signed-off-by: Yunfeng Ye yeyunfeng@huawei.com Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Chen Hui judy.chenhui@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- kernel/time/tick-sched.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index a2a26a8feae6..2b1eb5038a1f 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -53,7 +53,7 @@ static ktime_t last_jiffies_update; */ static void tick_do_update_jiffies64(ktime_t now) { - unsigned long ticks = 0; + unsigned long ticks = 1; ktime_t delta;
/* @@ -91,20 +91,21 @@ static void tick_do_update_jiffies64(ktime_t now)
write_seqcount_begin(&jiffies_seq);
- last_jiffies_update = ktime_add(last_jiffies_update, tick_period); - delta = ktime_sub(now, tick_next_period); if (unlikely(delta >= tick_period)) { /* Slow path for long idle sleep times */ s64 incr = ktime_to_ns(tick_period);
- ticks = ktime_divns(delta, incr); + ticks += ktime_divns(delta, incr);
last_jiffies_update = ktime_add_ns(last_jiffies_update, incr * ticks); + } else { + last_jiffies_update = ktime_add(last_jiffies_update, + tick_period); }
- do_timer(++ticks); + do_timer(ticks);
/* * Keep the tick_next_period variable up to date. WRITE_ONCE()
From: Yunfeng Ye yeyunfeng@huawei.com
mainline inclusion from mainline-5.11-rc1 commit 896b969e6732b68ee3c12ae4e1aeddf5db99bc46 category: feature feature: Deep isolation bugzilla: https://gitee.com/openeuler/kernel/issues/I4N00D CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
calc_load_global() does not need the sequence count protection.
[ tglx: Split it up properly and added comments ]
Signed-off-by: Yunfeng Ye yeyunfeng@huawei.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Link: https://lore.kernel.org/r/20201117132006.660902274@linutronix.de Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Chen Hui judy.chenhui@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- kernel/time/tick-sched.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 2b1eb5038a1f..651545679c3e 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -20,6 +20,7 @@ #include <linux/sched/clock.h> #include <linux/sched/stat.h> #include <linux/sched/nohz.h> +#include <linux/sched/loadavg.h> #include <linux/module.h> #include <linux/irq_work.h> #include <linux/posix-timers.h> @@ -105,7 +106,8 @@ static void tick_do_update_jiffies64(ktime_t now) tick_period); }
- do_timer(ticks); + /* Advance jiffies to complete the jiffies_seq protected job */ + jiffies_64 += ticks;
/* * Keep the tick_next_period variable up to date. WRITE_ONCE() @@ -114,7 +116,15 @@ static void tick_do_update_jiffies64(ktime_t now) WRITE_ONCE(tick_next_period, ktime_add(last_jiffies_update, tick_period));
+ /* + * Release the sequence count. calc_global_load() below is not + * protected by it, but jiffies_lock needs to be held to prevent + * concurrent invocations. + */ write_seqcount_end(&jiffies_seq); + + calc_global_load(); + raw_spin_unlock(&jiffies_lock); update_wall_time(); }
From: Yunfeng Ye yeyunfeng@huawei.com
mainline inclusion from mainline-5.14-rc1 commit a5183862e76fdc25f36b39c2489b816a5c66e2e5 category: feature feature: Deep isolation bugzilla: https://gitee.com/openeuler/kernel/issues/I4N00D CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
In nohz_full mode, switching from idle to a task will unconditionally issue a tick restart. If the task is alone in the runqueue or is the highest priority, the tick will fire once then eventually stop. But that alone is still undesired noise.
Therefore, only restart the tick on idle exit when it's strictly necessary.
Signed-off-by: Yunfeng Ye yeyunfeng@huawei.com Signed-off-by: Frederic Weisbecker frederic@kernel.org Signed-off-by: Ingo Molnar mingo@kernel.org Acked-by: Peter Zijlstra peterz@infradead.org Link: https://lore.kernel.org/r/20210512232924.150322-3-frederic@kernel.org Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Chen Hui judy.chenhui@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- kernel/time/tick-sched.c | 42 ++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 15 deletions(-)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 651545679c3e..eea50baf9cb0 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -906,22 +906,28 @@ static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now) tick_nohz_restart(ts, now); }
-static void tick_nohz_full_update_tick(struct tick_sched *ts) +static void __tick_nohz_full_update_tick(struct tick_sched *ts, + ktime_t now) { #ifdef CONFIG_NO_HZ_FULL int cpu = smp_processor_id();
- if (!tick_nohz_full_cpu(cpu)) + if (can_stop_full_tick(cpu, ts)) + tick_nohz_stop_sched_tick(ts, cpu); + else if (ts->tick_stopped) + tick_nohz_restart_sched_tick(ts, now); +#endif +} + +static void tick_nohz_full_update_tick(struct tick_sched *ts) +{ + if (!tick_nohz_full_cpu(smp_processor_id())) return;
if (!ts->tick_stopped && ts->nohz_mode == NOHZ_MODE_INACTIVE) return;
- if (can_stop_full_tick(cpu, ts)) - tick_nohz_stop_sched_tick(ts, cpu); - else if (ts->tick_stopped) - tick_nohz_restart_sched_tick(ts, ktime_get()); -#endif + __tick_nohz_full_update_tick(ts, ktime_get()); }
static bool can_stop_idle_tick(int cpu, struct tick_sched *ts) @@ -1185,18 +1191,24 @@ static void tick_nohz_account_idle_ticks(struct tick_sched *ts) #endif }
-static void __tick_nohz_idle_restart_tick(struct tick_sched *ts, ktime_t now) +void tick_nohz_idle_restart_tick(void) { - tick_nohz_restart_sched_tick(ts, now); - tick_nohz_account_idle_ticks(ts); + struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched); + + if (ts->tick_stopped) { + tick_nohz_restart_sched_tick(ts, ktime_get()); + tick_nohz_account_idle_ticks(ts); + } }
-void tick_nohz_idle_restart_tick(void) +static void tick_nohz_idle_update_tick(struct tick_sched *ts, ktime_t now) { - struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched); + if (tick_nohz_full_cpu(smp_processor_id())) + __tick_nohz_full_update_tick(ts, now); + else + tick_nohz_restart_sched_tick(ts, now);
- if (ts->tick_stopped) - __tick_nohz_idle_restart_tick(ts, ktime_get()); + tick_nohz_account_idle_ticks(ts); }
/** @@ -1228,7 +1240,7 @@ void tick_nohz_idle_exit(void) tick_nohz_stop_idle(ts, now);
if (tick_stopped) - __tick_nohz_idle_restart_tick(ts, now); + tick_nohz_idle_update_tick(ts, now);
local_irq_enable(); }
From: Frederic Weisbecker frederic@kernel.org
mainline inclusion from mainline-5.14-rc1 commit 3f624314b3f7c580aa5844a8930befd71e2a287c category: feature feature: Deep isolation bugzilla: https://gitee.com/openeuler/kernel/issues/I4N00D CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
The vtime_accounting_enabled_this_cpu() early check already makes what follows as dead code in the case of CONFIG_VIRT_CPU_ACCOUNTING_NATIVE. No need to keep the ifdeferry around.
Signed-off-by: Frederic Weisbecker frederic@kernel.org Signed-off-by: Ingo Molnar mingo@kernel.org Acked-by: Peter Zijlstra peterz@infradead.org Link: https://lore.kernel.org/r/20210512232924.150322-4-frederic@kernel.org Signed-off-by: Yunfeng Ye yeyunfeng@huawei.com Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Chen Hui judy.chenhui@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- kernel/time/tick-sched.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index eea50baf9cb0..f9ec75c35ac5 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -1172,7 +1172,6 @@ unsigned long tick_nohz_get_idle_calls(void)
static void tick_nohz_account_idle_ticks(struct tick_sched *ts) { -#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE unsigned long ticks;
if (vtime_accounting_enabled_this_cpu()) @@ -1188,7 +1187,6 @@ static void tick_nohz_account_idle_ticks(struct tick_sched *ts) */ if (ticks && ticks < LONG_MAX) account_idle_ticks(ticks); -#endif }
void tick_nohz_idle_restart_tick(void)
From: Yunfeng Ye yeyunfeng@huawei.com
mainline inclusion from mainline-5.14-rc1 commit 96c9b90396f9ab6caf13b4ebf00095818ac53b7f category: feature feature: Deep isolation bugzilla: https://gitee.com/openeuler/kernel/issues/I4N00D CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
The idle_exittime field of tick_sched is used to record the time when the idle state was left. but currently the idle_exittime is updated in the function tick_nohz_restart_sched_tick(), which is not always in idle state when nohz_full is configured:
tick_irq_exit tick_nohz_irq_exit tick_nohz_full_update_tick tick_nohz_restart_sched_tick ts->idle_exittime = now;
It's thus overwritten by mistake on nohz_full tick restart. Move the update to the appropriate idle exit path instead.
Signed-off-by: Yunfeng Ye yeyunfeng@huawei.com Signed-off-by: Frederic Weisbecker frederic@kernel.org Signed-off-by: Ingo Molnar mingo@kernel.org Acked-by: Peter Zijlstra peterz@infradead.org Link: https://lore.kernel.org/r/20210512232924.150322-5-frederic@kernel.org Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Chen Hui judy.chenhui@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- kernel/time/tick-sched.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index f9ec75c35ac5..e53a2a835f30 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -901,8 +901,6 @@ static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now) * Cancel the scheduled timer and restore the tick */ ts->tick_stopped = 0; - ts->idle_exittime = now; - tick_nohz_restart(ts, now); }
@@ -1170,10 +1168,13 @@ unsigned long tick_nohz_get_idle_calls(void) return ts->idle_calls; }
-static void tick_nohz_account_idle_ticks(struct tick_sched *ts) +static void tick_nohz_account_idle_time(struct tick_sched *ts, + ktime_t now) { unsigned long ticks;
+ ts->idle_exittime = now; + if (vtime_accounting_enabled_this_cpu()) return; /* @@ -1194,8 +1195,9 @@ void tick_nohz_idle_restart_tick(void) struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);
if (ts->tick_stopped) { - tick_nohz_restart_sched_tick(ts, ktime_get()); - tick_nohz_account_idle_ticks(ts); + ktime_t now = ktime_get(); + tick_nohz_restart_sched_tick(ts, now); + tick_nohz_account_idle_time(ts, now); } }
@@ -1206,7 +1208,7 @@ static void tick_nohz_idle_update_tick(struct tick_sched *ts, ktime_t now) else tick_nohz_restart_sched_tick(ts, now);
- tick_nohz_account_idle_ticks(ts); + tick_nohz_account_idle_time(ts, now); }
/**
From: Frederic Weisbecker frederic@kernel.org
mainline inclusion from mainline-5.14-rc1 commit 29721b859217b946bfc001c1644745ed4d7c26cb category: feature feature: Deep isolation bugzilla: https://gitee.com/openeuler/kernel/issues/I4N00D CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
When adding a tick dependency to a task, its necessary to wake up the CPU where the task resides to reevaluate tick dependencies on that CPU.
However the current code wakes up all nohz_full CPUs, which is unnecessary.
Switch to waking up a single CPU, by using ordering of writes to task->cpu and task->tick_dep_mask.
[ mingo: Minor readability edit. ]
Suggested-by: Peter Zijlstra peterz@infradead.org Signed-off-by: Frederic Weisbecker frederic@kernel.org Signed-off-by: Marcelo Tosatti mtosatti@redhat.com Signed-off-by: Ingo Molnar mingo@kernel.org Acked-by: Peter Zijlstra peterz@infradead.org Link: https://lore.kernel.org/r/20210512232924.150322-7-frederic@kernel.org Signed-off-by: Yunfeng Ye yeyunfeng@huawei.com Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Chen Hui judy.chenhui@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- kernel/time/tick-sched.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index e53a2a835f30..a88741991e03 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -302,6 +302,31 @@ void tick_nohz_full_kick_cpu(int cpu) irq_work_queue_on(&per_cpu(nohz_full_kick_work, cpu), cpu); }
+static void tick_nohz_kick_task(struct task_struct *tsk) +{ + int cpu = task_cpu(tsk); + + /* + * If the task concurrently migrates to another CPU, + * we guarantee it sees the new tick dependency upon + * schedule. + * + * + * set_task_cpu(p, cpu); + * STORE p->cpu = @cpu + * __schedule() (switch to task 'p') + * LOCK rq->lock + * smp_mb__after_spin_lock() STORE p->tick_dep_mask + * tick_nohz_task_switch() smp_mb() (atomic_fetch_or()) + * LOAD p->tick_dep_mask LOAD p->cpu + */ + + preempt_disable(); + if (cpu_online(cpu)) + tick_nohz_full_kick_cpu(cpu); + preempt_enable(); +} + /* * Kick all full dynticks CPUs in order to force these to re-evaluate * their dependency on the tick and restart it if necessary. @@ -384,19 +409,8 @@ EXPORT_SYMBOL_GPL(tick_nohz_dep_clear_cpu); */ void tick_nohz_dep_set_task(struct task_struct *tsk, enum tick_dep_bits bit) { - if (!atomic_fetch_or(BIT(bit), &tsk->tick_dep_mask)) { - if (tsk == current) { - preempt_disable(); - tick_nohz_full_kick(); - preempt_enable(); - } else { - /* - * Some future tick_nohz_full_kick_task() - * should optimize this. - */ - tick_nohz_full_kick_all(); - } - } + if (!atomic_fetch_or(BIT(bit), &tsk->tick_dep_mask)) + tick_nohz_kick_task(tsk); } EXPORT_SYMBOL_GPL(tick_nohz_dep_set_task);
From: Marcelo Tosatti mtosatti@redhat.com
mainline inclusion from mainline-5.14-rc1 commit 1e4ca26d367ae71743e25068e5cd8750ef3f5f7d category: feature feature: Deep isolation bugzilla: https://gitee.com/openeuler/kernel/issues/I4N00D CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Rather than waking up all nohz_full CPUs on the system, only wake up the target CPUs of member threads of the signal.
Reduces interruptions to nohz_full CPUs.
Signed-off-by: Marcelo Tosatti mtosatti@redhat.com Signed-off-by: Frederic Weisbecker frederic@kernel.org Signed-off-by: Ingo Molnar mingo@kernel.org Acked-by: Peter Zijlstra peterz@infradead.org Link: https://lore.kernel.org/r/20210512232924.150322-8-frederic@kernel.org Signed-off-by: Yunfeng Ye yeyunfeng@huawei.com Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Chen Hui judy.chenhui@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/tick.h | 8 ++++---- kernel/time/posix-cpu-timers.c | 4 ++-- kernel/time/tick-sched.c | 15 +++++++++++++-- 3 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/include/linux/tick.h b/include/linux/tick.h index 7340613c7eff..e20bb7ce3bbe 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h @@ -207,7 +207,7 @@ extern void tick_nohz_dep_set_task(struct task_struct *tsk, enum tick_dep_bits bit); extern void tick_nohz_dep_clear_task(struct task_struct *tsk, enum tick_dep_bits bit); -extern void tick_nohz_dep_set_signal(struct signal_struct *signal, +extern void tick_nohz_dep_set_signal(struct task_struct *tsk, enum tick_dep_bits bit); extern void tick_nohz_dep_clear_signal(struct signal_struct *signal, enum tick_dep_bits bit); @@ -252,11 +252,11 @@ static inline void tick_dep_clear_task(struct task_struct *tsk, if (tick_nohz_full_enabled()) tick_nohz_dep_clear_task(tsk, bit); } -static inline void tick_dep_set_signal(struct signal_struct *signal, +static inline void tick_dep_set_signal(struct task_struct *tsk, enum tick_dep_bits bit) { if (tick_nohz_full_enabled()) - tick_nohz_dep_set_signal(signal, bit); + tick_nohz_dep_set_signal(tsk, bit); } static inline void tick_dep_clear_signal(struct signal_struct *signal, enum tick_dep_bits bit) @@ -284,7 +284,7 @@ static inline void tick_dep_set_task(struct task_struct *tsk, enum tick_dep_bits bit) { } static inline void tick_dep_clear_task(struct task_struct *tsk, enum tick_dep_bits bit) { } -static inline void tick_dep_set_signal(struct signal_struct *signal, +static inline void tick_dep_set_signal(struct task_struct *tsk, enum tick_dep_bits bit) { } static inline void tick_dep_clear_signal(struct signal_struct *signal, enum tick_dep_bits bit) { } diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index 5d76edd0ad9c..d6b46346be1f 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -523,7 +523,7 @@ static void arm_timer(struct k_itimer *timer, struct task_struct *p) if (CPUCLOCK_PERTHREAD(timer->it_clock)) tick_dep_set_task(p, TICK_DEP_BIT_POSIX_TIMER); else - tick_dep_set_signal(p->signal, TICK_DEP_BIT_POSIX_TIMER); + tick_dep_set_signal(p, TICK_DEP_BIT_POSIX_TIMER); }
/* @@ -1373,7 +1373,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clkid, if (*newval < *nextevt) *nextevt = *newval;
- tick_dep_set_signal(tsk->signal, TICK_DEP_BIT_POSIX_TIMER); + tick_dep_set_signal(tsk, TICK_DEP_BIT_POSIX_TIMER); }
static int do_cpu_nanosleep(const clockid_t which_clock, int flags, diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index a88741991e03..054052a58567 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -424,9 +424,20 @@ EXPORT_SYMBOL_GPL(tick_nohz_dep_clear_task); * Set a per-taskgroup tick dependency. Posix CPU timers need this in order to elapse * per process timers. */ -void tick_nohz_dep_set_signal(struct signal_struct *sig, enum tick_dep_bits bit) +void tick_nohz_dep_set_signal(struct task_struct *tsk, + enum tick_dep_bits bit) { - tick_nohz_dep_set_all(&sig->tick_dep_mask, bit); + int prev; + struct signal_struct *sig = tsk->signal; + + prev = atomic_fetch_or(BIT(bit), &sig->tick_dep_mask); + if (!prev) { + struct task_struct *t; + + lockdep_assert_held(&tsk->sighand->siglock); + __for_each_thread(sig, t) + tick_nohz_kick_task(t); + } }
void tick_nohz_dep_clear_signal(struct signal_struct *sig, enum tick_dep_bits bit)
From: Marcelo Tosatti mtosatti@redhat.com
mainline inclusion from mainline-5.14-rc1 commit a1dfb6311c7739e21e160bc4c5575a1b21b48c87 category: feature feature: Deep isolation bugzilla: https://gitee.com/openeuler/kernel/issues/I4N00D CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
When the tick dependency of a task is updated, we want it to aknowledge the new state and restart the tick if needed. If the task is not running, we don't need to kick it because it will observe the new dependency upon scheduling in. But if the task is running, we may need to send an IPI to it so that it gets notified.
Unfortunately we don't have the means to check if a task is running in a race free way. Checking p->on_cpu in a synchronized way against p->tick_dep_mask would imply adding a full barrier between prepare_task_switch() and tick_nohz_task_switch(), which we want to avoid in this fast-path.
Therefore we blindly fire an IPI to the task's CPU.
Meanwhile we can check if the task is queued on the CPU rq because p->on_rq is always set to TASK_ON_RQ_QUEUED _before_ schedule() and its full barrier that precedes tick_nohz_task_switch(). And if the task is queued on a nohz_full CPU, it also has fair chances to be running as the isolation constraints prescribe running single tasks on full dynticks CPUs.
So use this as a trick to check if we can spare an IPI toward a non-running task.
NOTE: For the ordering to be correct, it is assumed that we never deactivate a task while it is running, the only exception being the task deactivating itself while scheduling out.
Suggested-by: Peter Zijlstra peterz@infradead.org Signed-off-by: Marcelo Tosatti mtosatti@redhat.com Signed-off-by: Frederic Weisbecker frederic@kernel.org Signed-off-by: Ingo Molnar mingo@kernel.org Acked-by: Peter Zijlstra peterz@infradead.org Link: https://lore.kernel.org/r/20210512232924.150322-9-frederic@kernel.org Signed-off-by: Yunfeng Ye yeyunfeng@huawei.com Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Chen Hui judy.chenhui@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/sched.h | 2 ++ kernel/sched/core.c | 5 +++++ kernel/time/tick-sched.c | 19 +++++++++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/include/linux/sched.h b/include/linux/sched.h index b977f07ed41c..d0312bdc00a0 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1962,6 +1962,8 @@ static inline void set_task_cpu(struct task_struct *p, unsigned int cpu)
#endif /* CONFIG_SMP */
+extern bool sched_task_on_rq(struct task_struct *p); + /* * In order to reduce various lock holder preemption latencies provide an * interface to see if a vCPU is currently running or not. diff --git a/kernel/sched/core.c b/kernel/sched/core.c index b46717970ab9..c880f5f4e6bb 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1561,6 +1561,11 @@ static inline void uclamp_post_fork(struct task_struct *p) { } static inline void init_uclamp(void) { } #endif /* CONFIG_UCLAMP_TASK */
+bool sched_task_on_rq(struct task_struct *p) +{ + return task_on_rq_queued(p); +} + static inline void enqueue_task(struct rq *rq, struct task_struct *p, int flags) { if (!(flags & ENQUEUE_NOCLOCK)) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 054052a58567..c5c1287f0d2a 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -304,14 +304,28 @@ void tick_nohz_full_kick_cpu(int cpu)
static void tick_nohz_kick_task(struct task_struct *tsk) { - int cpu = task_cpu(tsk); + int cpu; + + /* + * If the task is not running, run_posix_cpu_timers() + * has nothing to elapse, IPI can then be spared. + * + * activate_task() STORE p->tick_dep_mask + * STORE p->on_rq + * __schedule() (switch to task 'p') smp_mb() (atomic_fetch_or()) + * LOCK rq->lock LOAD p->on_rq + * smp_mb__after_spin_lock() + * tick_nohz_task_switch() + * LOAD p->tick_dep_mask + */ + if (!sched_task_on_rq(tsk)) + return;
/* * If the task concurrently migrates to another CPU, * we guarantee it sees the new tick dependency upon * schedule. * - * * set_task_cpu(p, cpu); * STORE p->cpu = @cpu * __schedule() (switch to task 'p') @@ -320,6 +334,7 @@ static void tick_nohz_kick_task(struct task_struct *tsk) * tick_nohz_task_switch() smp_mb() (atomic_fetch_or()) * LOAD p->tick_dep_mask LOAD p->cpu */ + cpu = task_cpu(tsk);
preempt_disable(); if (cpu_online(cpu))
From: Peter Zijlstra peterz@infradead.org
mainline inclusion from mainline-5.14-rc1 commit 0fdcccfafcffac70b452b3127cc3d981f0117655 category: feature feature: Deep isolation bugzilla: https://gitee.com/openeuler/kernel/issues/I4N00D CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Call tick_nohz_task_switch() slightly earlier after the context switch to benefit from disabled IRQs. This way the function doesn't need to disable them once more.
Signed-off-by: Peter Zijlstra peterz@infradead.org Signed-off-by: Frederic Weisbecker frederic@kernel.org Signed-off-by: Ingo Molnar mingo@kernel.org Link: https://lore.kernel.org/r/20210512232924.150322-10-frederic@kernel.org Signed-off-by: Yunfeng Ye yeyunfeng@huawei.com Reviewed-by: liu chao liuchao173@huawei.com Reviewed-by: Chen Hui judy.chenhui@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- kernel/sched/core.c | 2 +- kernel/time/tick-sched.c | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index c880f5f4e6bb..93961898567b 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3652,6 +3652,7 @@ static struct rq *finish_task_switch(struct task_struct *prev) vtime_task_switch(prev); perf_event_task_sched_in(prev, current); finish_task(prev); + tick_nohz_task_switch(); finish_lock_switch(rq); finish_arch_post_lock_switch(); kcov_finish_switch(current); @@ -3689,7 +3690,6 @@ static struct rq *finish_task_switch(struct task_struct *prev) put_task_struct_rcu_user(prev); }
- tick_nohz_task_switch(); return rq; }
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index c5c1287f0d2a..49423dffdfc3 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -467,13 +467,10 @@ void tick_nohz_dep_clear_signal(struct signal_struct *sig, enum tick_dep_bits bi */ void __tick_nohz_task_switch(void) { - unsigned long flags; struct tick_sched *ts;
- local_irq_save(flags); - if (!tick_nohz_full_cpu(smp_processor_id())) - goto out; + return;
ts = this_cpu_ptr(&tick_cpu_sched);
@@ -482,8 +479,6 @@ void __tick_nohz_task_switch(void) atomic_read(¤t->signal->tick_dep_mask)) tick_nohz_full_kick(); } -out: - local_irq_restore(flags); }
/* Get the boot-time nohz CPU list from the kernel parameters. */
From: Wang Wensheng wangwensheng4@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4N3XU CVE: NA
-------------------------------------------------
The cdm nodes are easiler to raise an ECC error and it may cause the kernel crash if the essential structures went wrong. So move the management structures for hbm nodes to the ddr nodes of the same partion to reduce the probability of kernel crashes.
Signed-off-by: Wang Wensheng wangwensheng4@huawei.com Signed-off-by: Lijun Fang fanglijun3@huawei.com Reviewed-by: Weilong Chen chenweilong@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/Kconfig | 9 ++++++ arch/arm64/mm/numa.c | 67 +++++++++++++++++++++++++++++++++++++++- include/linux/nodemask.h | 7 +++++ mm/sparse.c | 7 +++-- 4 files changed, 86 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 2df4b310eb23..44f1bf1a5b08 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -2000,6 +2000,15 @@ config ASCEND_DVPP_MMAP special memory for DvPP processor, the new flag is only valid for Ascend platform.
+config ASCEND_CLEAN_CDM + bool "move the management structure for HBM to DDR" + def_bool n + depends on COHERENT_DEVICE + help + The cdm nodes sometimes are easiler to raise an ECC error and it may + cause the kernel crash if the essential structures went wrong. So move + the management structures for hbm nodes to the ddr nodes of the same + partion to reduce the probability of kernel crashes. endif
endmenu diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c index 9a2e29a3a597..a167b74272b2 100644 --- a/arch/arm64/mm/numa.c +++ b/arch/arm64/mm/numa.c @@ -33,6 +33,70 @@ inline int arch_check_node_cdm(int nid) return node_isset(nid, cdmmask); }
+#ifdef CONFIG_ASCEND_CLEAN_CDM +/** + * cdm_node_to_ddr_node - Convert the cdm node to the ddr node of the + * same partion. + * @nid: input node ID + * + * Here is a typical memory topology in usage. + * There are some DDR and HBM in each partion and DDRs present at first, then + * come all the HBMs of the first partion, then HBMs of the second partion, etc. + * + * ------------------------- + * | P0 | P1 | + * ----------- | ----------- + * |node0 DDR| | |node1 DDR| + * |---------- | ----------| + * |node2 HBM| | |node4 HBM| + * |---------- | ----------| + * |node3 HBM| | |node5 HBM| + * |---------- | ----------| + * | ... | | | ... | + * |---------- | ----------| + * + * Return: + * This function returns a ddr node which is of the same partion with the input + * node if the input node is a HBM node. + * The input nid is returned if it is a DDR node or if the memory topology of + * the system doesn't apply to the above model. + */ +int __init cdm_node_to_ddr_node(int nid) +{ + nodemask_t ddr_mask; + int nr_ddr, cdm_per_part, fake_nid; + int nr_cdm = nodes_weight(cdmmask); + /* + * Specify the count of hbm nodes whoes management structrue would be + * moved. Here number 2 is a magic and we should make it configable + * for extending + */ + int hbm_per_part = 2; + + if (!nr_cdm || nodes_empty(numa_nodes_parsed)) + return nid; + + if (!node_isset(nid, cdmmask)) + return nid; + + nodes_xor(ddr_mask, cdmmask, numa_nodes_parsed); + nr_ddr = nodes_weight(ddr_mask); + cdm_per_part = nr_cdm / nr_ddr; + + if (cdm_per_part == 0 || nid < nr_ddr || + nid >= (hbm_per_part + 1) * nr_ddr) + /* our assumption has borken, just return the original nid. */ + return nid; + + fake_nid = (nid - nr_ddr) / hbm_per_part; + fake_nid = !node_isset(fake_nid, cdmmask) ? fake_nid : nid; + + pr_info("nid: %d, fake_nid: %d\n", nid, fake_nid); + + return fake_nid; +} +#endif + static int __init cdm_nodes_setup(char *s) { int nid; @@ -252,11 +316,12 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn) u64 nd_pa; void *nd; int tnid; + int fake_nid = cdm_node_to_ddr_node(nid);
if (start_pfn >= end_pfn) pr_info("Initmem setup node %d [<memory-less node>]\n", nid);
- nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); + nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, fake_nid); if (!nd_pa) panic("Cannot allocate %zu bytes for node %d data\n", nd_size, nid); diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h index 90ea204cc059..2636f08d685c 100644 --- a/include/linux/nodemask.h +++ b/include/linux/nodemask.h @@ -509,6 +509,12 @@ static inline int node_random(const nodemask_t *mask) #ifdef CONFIG_COHERENT_DEVICE extern int arch_check_node_cdm(int nid);
+#ifdef CONFIG_ASCEND_CLEAN_CDM +extern int cdm_node_to_ddr_node(int nid); +#else +static inline int cdm_node_to_ddr_node(int nid) { return nid; } +#endif + static inline nodemask_t system_mem_nodemask(void) { nodemask_t system_mem; @@ -552,6 +558,7 @@ static inline void node_clear_state_cdm(int node) #else
static inline int arch_check_node_cdm(int nid) { return 0; } +static inline int cdm_node_to_ddr_node(int nid) { return nid; }
static inline nodemask_t system_mem_nodemask(void) { diff --git a/mm/sparse.c b/mm/sparse.c index 0e645ff9cf0f..5a48ea3e9968 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -528,14 +528,15 @@ static void __init sparse_init_nid(int nid, unsigned long pnum_begin, struct mem_section_usage *usage; unsigned long pnum; struct page *map; + int fake_nid = cdm_node_to_ddr_node(nid);
- usage = sparse_early_usemaps_alloc_pgdat_section(NODE_DATA(nid), + usage = sparse_early_usemaps_alloc_pgdat_section(NODE_DATA(fake_nid), mem_section_usage_size() * map_count); if (!usage) { pr_err("%s: node[%d] usemap allocation failed", __func__, nid); goto failed; } - sparse_buffer_init(map_count * section_map_size(), nid); + sparse_buffer_init(map_count * section_map_size(), fake_nid); for_each_present_section_nr(pnum_begin, pnum) { unsigned long pfn = section_nr_to_pfn(pnum);
@@ -543,7 +544,7 @@ static void __init sparse_init_nid(int nid, unsigned long pnum_begin, break;
map = __populate_section_memmap(pfn, PAGES_PER_SECTION, - nid, NULL); + fake_nid, NULL); if (!map) { pr_err("%s: node[%d] memory map backing failed. Some memory will not be available.", __func__, nid);
From: Wang Wensheng wangwensheng4@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4N3XU CVE: NA
----------------------------------------------------------
Use a bootarg to precisely specify the target node to which we want to move the kernel structrue for a cdm node.
Signed-off-by: Wang Wensheng wangwensheng4@huawei.com Signed-off-by: Lijun Fang fanglijun3@huawei.com Reviewed-by: Weilong Chen chenweilong@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/mm/numa.c | 82 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c index a167b74272b2..480fcfb1b917 100644 --- a/arch/arm64/mm/numa.c +++ b/arch/arm64/mm/numa.c @@ -34,6 +34,85 @@ inline int arch_check_node_cdm(int nid) }
#ifdef CONFIG_ASCEND_CLEAN_CDM + +#define MAX_PARTATION_COUNT 8 +#define MAX_CDM_PER_PATRATION 8 + +/* + * Here we provide a way to precisely specify the target node to which we want + * to move the kernel structrue for a cdm node, instead of guessing the hardware + * topologies. Even the node isn't a cdm node, the movement could be reasonable. + * Suppose a node is designed to be used only by some certern processes and + * devices, the kernel structure of that node could be overwritten by a broken + * process. + * + * A possible configure in bootargs: + * cdm_move_map=0,2,3,6;1,4,5,7 + * That means to move the kernel structure for node 2,3,6 to node 0 and kernel + * structure for node 4,5,7 to node 1. + */ +static bool cdm_to_ddr_hardcode = true; +static int cdm_to_ddr_map[MAX_PARTATION_COUNT][MAX_CDM_PER_PATRATION + 1]; + +static int __init cdm_to_ddr_parse_param(char *str) +{ + int i, j; + char *p, *n; + + cdm_to_ddr_hardcode = false; + for (i = 0; i < MAX_PARTATION_COUNT; i++) + for (j = 0; j < MAX_CDM_PER_PATRATION + 1; j++) + cdm_to_ddr_map[i][j] = -1; + + for (p = n = str, i = 0; strsep(&p, ";"); i++, n = p) { + char *s = n; + + for (j = 0; strsep(&n, ","); j++, s = n) { + int err; + unsigned long long nid; + + if (j >= MAX_CDM_PER_PATRATION + 1) { + pr_warn("the cdm nodes in this partation is more than supported\n"); + break; + } + + err = kstrtoull(s, 0, &nid); + if (err) { + pr_err("bootargs for cdm_move_map invalid, %d\n", + err); + return err; + } + + cdm_to_ddr_map[i][j] = (int)nid; + if (j > 0) + pr_info("node %d moved to node %d\n", + cdm_to_ddr_map[i][j], + cdm_to_ddr_map[i][0]); + } + } + + return 0; +} +early_param("cdm_move_map", cdm_to_ddr_parse_param); + +static int __init cdm_node_to_ddr_node_mapped(int nid) +{ + int i, j; + + for (i = 0; i < MAX_PARTATION_COUNT; i++) { + if (cdm_to_ddr_map[i][0] == -1) + break; + for (j = 1; j < MAX_CDM_PER_PATRATION + 1; j++) { + if (cdm_to_ddr_map[i][j] == -1) + break; + else if (cdm_to_ddr_map[i][j] == nid) + return cdm_to_ddr_map[i][0]; + } + } + + return nid; +} + /** * cdm_node_to_ddr_node - Convert the cdm node to the ddr node of the * same partion. @@ -73,6 +152,9 @@ int __init cdm_node_to_ddr_node(int nid) */ int hbm_per_part = 2;
+ if (!cdm_to_ddr_hardcode) + return cdm_node_to_ddr_node_mapped(nid); + if (!nr_cdm || nodes_empty(numa_nodes_parsed)) return nid;
From: Lijun Fang fanglijun3@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4N3XU CVE: NA
----------------------------------------------------------
Enable CONFIG_ASCEND_CLEAN_CDM by default.
Signed-off-by: Lijun Fang fanglijun3@huawei.com Reviewed-by: Weilong Chen chenweilong@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/configs/openeuler_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index b5fc851f1949..6cdcbad3967e 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -475,6 +475,7 @@ CONFIG_RANDOMIZE_BASE=y CONFIG_RANDOMIZE_MODULE_REGION_FULL=y CONFIG_ASCEND_FEATURES=y CONFIG_ASCEND_DVPP_MMAP=y +CONFIG_ASCEND_CLEAN_CDM=y # end of Kernel Features
#
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 7fdd1c661de46e5d73583c300f8c35c41a6a7b7c.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- security/integrity/ima/ima_fs.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index b7959de25a5f..00cd8095d346 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -637,16 +637,12 @@ static const struct file_operations ima_data_upload_ops = { static int ima_open_for_children(struct inode *inode, struct file *file) { struct ima_namespace *ima_ns = get_current_ns(); - struct ima_namespace *ima_ns_for_children = current->nsproxy->ima_ns_for_children;
/* Allow to set children configuration only after unshare() */ if (ima_ns == current->nsproxy->ima_ns_for_children) return -EPERM;
- if (!ns_capable(ima_ns_for_children->user_ns, CAP_SYS_ADMIN)) - return -EPERM; - - return 0; + return ima_open_simple(inode, file); }
static ssize_t ima_write_x509_for_children(struct file *file,
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 44598ce37355e304ada1a77f83c612144e7720fb.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- security/integrity/digsig.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index c866a5c2c9b1..2c923dc0dbd3 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -74,11 +74,8 @@ static struct key_tag *domain_tag_from_id(const unsigned int id) return ERR_PTR(-EINVAL);
if (id == INTEGRITY_KEYRING_IMA) -#ifdef CONFIG_IMA_NS return current->nsproxy->ima_ns->key_domain; -#else - return init_ima_ns.key_domain; -#endif + return NULL; }
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 603cc292bfe4328ba42ee3545bc167fce0de38d1.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- security/integrity/ima/ima_digest_list.c | 12 ------------ security/integrity/ima/ima_fs.c | 11 +---------- 2 files changed, 1 insertion(+), 22 deletions(-)
diff --git a/security/integrity/ima/ima_digest_list.c b/security/integrity/ima/ima_digest_list.c index 9384affe8b30..2d7148ff09c1 100644 --- a/security/integrity/ima/ima_digest_list.c +++ b/security/integrity/ima/ima_digest_list.c @@ -89,9 +89,6 @@ struct ima_digest *ima_lookup_digest(u8 *digest, enum hash_algo algo, int digest_len = hash_digest_size[algo]; unsigned int key = ima_hash_key(digest);
- if (&init_ima_ns != get_current_ns()) - return NULL; - rcu_read_lock(); hlist_for_each_entry_rcu(d, &ima_digests_htable.queue[key], hnext) if (d->algo == algo && d->type == type && @@ -176,9 +173,6 @@ int ima_parse_compact_list(loff_t size, void *buf, int op) size_t digest_len; int ret = 0, i;
- if (&init_ima_ns != get_current_ns()) - return -EACCES; - if (!(ima_digest_list_actions & init_policy_data.ima_policy_flag)) return -EACCES;
@@ -251,9 +245,6 @@ void ima_check_measured_appraised(struct file *file) { struct integrity_iint_cache *iint;
- if (&init_ima_ns != get_current_ns()) - return; - if (!ima_digest_list_actions) return;
@@ -290,9 +281,6 @@ void ima_check_measured_appraised(struct file *file)
struct ima_digest *ima_digest_allow(struct ima_digest *digest, int action) { - if (&init_ima_ns != get_current_ns()) - return NULL; - if (!(ima_digest_list_actions & action)) return NULL;
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 00cd8095d346..d9c7e1d6d543 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -60,17 +60,11 @@ static int valid_policy = 1;
static int ima_open_simple(struct inode *inode, struct file *file) { - struct dentry *dentry = file_dentry(file); struct ima_namespace *ima_ns = get_current_ns();
if (!ns_capable(ima_ns->user_ns, CAP_SYS_ADMIN)) return -EPERM;
- if (dentry == digests_count) { - if (&init_ima_ns != get_current_ns()) - return -EACCES; - } - return 0; }
@@ -562,12 +556,9 @@ static int ima_open_data_upload(struct inode *inode, struct file *filp) if (test_and_set_bit(flag, &ima_fs_flags)) return -EBUSY;
- if (dentry == digest_list_data || dentry == digest_list_data_del) { - if (&init_ima_ns != get_current_ns()) - return -EACCES; + if (dentry == digest_list_data || dentry == digest_list_data_del) if (ima_check_current_is_parser()) ima_set_parser(); - }
return 0; }
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit a847fd9b9bc7a6303ff74d6c783cb0b150f79cac.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- security/integrity/ima/ima_template.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index 5cd4ccd0d240..e72497f37bb5 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c @@ -23,7 +23,6 @@ static struct ima_template_desc builtin_templates[] = { {.name = "ima-buf", .fmt = "d-ng|n-ng|buf"}, {.name = "ima-modsig", .fmt = "d-ng|n-ng|sig|d-modsig|modsig"}, {.name = "ima-ns", .fmt = "d-ng|n-ng|ns"}, - {.name = "ima-ns-sig", .fmt = "d-ng|n-ng|ns|sig"}, {.name = "", .fmt = ""}, /* placeholder for a custom format */ };
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 11047edeffe7e92b00dda3f885ac255ea2f32218.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- security/integrity/ima/ima_policy.c | 7 ------- 1 file changed, 7 deletions(-)
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 8b7ca11e82f7..35ec2c8f2069 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -208,13 +208,6 @@ static struct ima_rule_entry build_appraise_rules[] __ro_after_init = { {.action = APPRAISE, .func = POLICY_CHECK, .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, #endif -#if !defined(CONFIG_IMA_APPRAISE_REQUIRE_MODULE_SIGS) && \ - !defined(CONFIG_IMA_APPRAISE_REQUIRE_FIRMWARE_SIGS) && \ - !defined(CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS) && \ - !defined(CONFIG_IMA_APPRAISE_REQUIRE_POLICY_SIGS) - /* Add a member to avoid a zero length array */ - {.action = UNKNOWN, .func = NONE, .flags = 0}, -#endif };
static struct ima_rule_entry secure_boot_rules[] __ro_after_init = {
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit e16e05db4747e24f2fc3dd72c8a903819624baec.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 1 - security/integrity/ima/ima.h | 2 -- security/integrity/ima/ima_init.c | 1 - security/integrity/ima/ima_ns.c | 30 +-------------------- security/integrity/ima/ima_policy.c | 2 +- security/integrity/ima/ima_template.c | 38 +++++++++------------------ 6 files changed, 15 insertions(+), 59 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index 5a2dbd8fab6d..f011c6e6aa86 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -240,7 +240,6 @@ struct ima_namespace { #ifdef CONFIG_KEYS struct key_tag *key_domain; #endif - struct ima_template_desc *ima_template; struct task_struct *activating_tsk; /* used only for the ns activation */ } __randomize_layout;
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 6ab515592c62..5b1364eb1477 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -172,10 +172,8 @@ int template_desc_init_fields(const char *template_fmt, const struct ima_template_field ***fields, int *num_fields); struct ima_template_desc *ima_template_desc_current(void); -struct ima_template_desc *ima_template_desc_ns(struct ima_namespace *ima_ns); struct ima_template_desc *lookup_template_desc(const char *name); bool ima_template_has_modsig(const struct ima_template_desc *ima_template); -int ima_template_setup(char *str, struct ima_namespace *ima_ns); int ima_restore_measurement_entry(struct ima_template_entry *entry); int ima_restore_measurement_list(loff_t bufsize, void *buf); int ima_measurements_show(struct seq_file *m, void *v); diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index f4bd3ca98b54..73fb0f0e82c5 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -48,7 +48,6 @@ struct ima_namespace init_ima_ns = { #ifdef CONFIG_KEYS .key_domain = &init_ima_key_domain, #endif - .ima_template = NULL, }; EXPORT_SYMBOL(init_ima_ns);
diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 97185b8ed52c..29a1cbdac40d 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -49,28 +49,6 @@ static void dec_ima_namespaces(struct ucounts *ucounts) return dec_ucount(ucounts, UCOUNT_IMA_NAMESPACES); }
-static int ima_set_ns_template(struct ima_namespace *ima_ns) -{ - int result; - - if (!ima_ns->ima_template) - ima_ns->ima_template = - lookup_template_desc(CONFIG_IMA_DEFAULT_TEMPLATE); - - result = template_desc_init_fields(ima_ns->ima_template->fmt, - &(ima_ns->ima_template->fields), - &(ima_ns->ima_template->num_fields)); - if (result < 0) { - pr_err("template %s init failed, result: %d\n", - (strlen(ima_ns->ima_template->name) ? - ima_ns->ima_template->name : - ima_ns->ima_template->fmt), result); - ima_ns->ima_template = NULL; - } - - return result; -} - static int ima_ns_add_boot_aggregate(struct ima_namespace *ima_ns) { static const char op[] = "ns_add_boot_aggregate"; @@ -267,7 +245,6 @@ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, #endif ns->x509_path_for_children = NULL; ns->policy_setup_for_children = NULL; - ns->ima_template = NULL;
INIT_LIST_HEAD(&ns->ns_measurements); INIT_LIST_HEAD(&ns->policy_data->ima_default_rules); @@ -460,10 +437,6 @@ static int imans_activate(struct ima_namespace *ima_ns) if (ima_ns->frozen) goto out;
- res = ima_set_ns_template(ima_ns); - if (res < 0) - goto out; - ima_set_ns_policy(ima_ns);
ima_ns->frozen = true; @@ -583,11 +556,10 @@ struct ima_kernel_param { int (*set)(char *val, struct ima_namespace *ima_ns); };
-/* TODO: add ima_template_fmt, ima_hash, ... */ +/* TODO: add ima_template, ima_template_fmt, ima_hash, ... */ static const struct ima_kernel_param ima_kernel_params[] = { {"ima_appraise", ima_default_appraise_setup}, {"ima_policy", ima_policy_setup}, - {"ima_template", ima_template_setup}, }; static const size_t ima_kernel_params_size = ARRAY_SIZE(ima_kernel_params);
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 35ec2c8f2069..42bafb520e4e 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -737,7 +737,7 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, bool fail_unverifiable_sigs;
if (template_desc) - *template_desc = ima_template_desc_ns(ima_ns); + *template_desc = ima_template_desc_current();
rcu_read_lock(); list_for_each_entry_rcu(entry, ima_ns->policy_data->ima_rules, list) { diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index e72497f37bb5..3d6f6e9d530c 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c @@ -59,6 +59,8 @@ static const struct ima_template_field supported_fields[] = { */ #define MAX_TEMPLATE_NAME_LEN sizeof("d-ng|n-ng|sig|buf|d-modisg|modsig|ns")
+static struct ima_template_desc *ima_template; + /** * ima_template_has_modsig - Check whether template has modsig-related fields. * @ima_template: IMA template to check. @@ -78,12 +80,12 @@ bool ima_template_has_modsig(const struct ima_template_desc *ima_template) return false; }
-int ima_template_setup(char *str, struct ima_namespace *ima_ns) +static int __init ima_template_setup(char *str) { struct ima_template_desc *template_desc; int template_len = strlen(str);
- if (ima_ns->ima_template) + if (ima_template) return 1;
ima_init_template_list(); @@ -109,21 +111,16 @@ int ima_template_setup(char *str, struct ima_namespace *ima_ns) return 1; }
- ima_ns->ima_template = template_desc; + ima_template = template_desc; return 1; } - -static int __init template_setup(char *str) -{ - return ima_template_setup(str, &init_ima_ns); -} -__setup("ima_template=", template_setup); +__setup("ima_template=", ima_template_setup);
static int __init ima_template_fmt_setup(char *str) { int num_templates = ARRAY_SIZE(builtin_templates);
- if (init_ima_ns.ima_template) + if (ima_template) return 1;
if (template_desc_init_fields(str, NULL, NULL) < 0) { @@ -133,7 +130,7 @@ static int __init ima_template_fmt_setup(char *str) }
builtin_templates[num_templates - 1].fmt = str; - init_ima_ns.ima_template = builtin_templates + num_templates - 1; + ima_template = builtin_templates + num_templates - 1;
return 1; } @@ -250,23 +247,14 @@ void ima_init_template_list(void) spin_unlock(&template_list); }
-struct ima_template_desc *ima_template_desc_ns(struct ima_namespace *ima_ns) +struct ima_template_desc *ima_template_desc_current(void) { - if (!ima_ns) - return NULL; - - if (!ima_ns->ima_template) { + if (!ima_template) { ima_init_template_list(); - ima_ns->ima_template = - lookup_template_desc(CONFIG_IMA_DEFAULT_TEMPLATE); + ima_template = + lookup_template_desc(CONFIG_IMA_DEFAULT_TEMPLATE); } - return ima_ns->ima_template; -} - -struct ima_template_desc *ima_template_desc_current(void) -{ - struct ima_namespace *ima_ns = get_current_ns(); - return ima_template_desc_ns(ima_ns); + return ima_template; }
int __init ima_init_template(void)
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 9164a7e00a60c663a87a5672abbff96b50a6e56d.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- security/integrity/ima/ima_ns.c | 62 --------------------------------- 1 file changed, 62 deletions(-)
diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 29a1cbdac40d..b04f35f35f85 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -49,66 +49,6 @@ static void dec_ima_namespaces(struct ucounts *ucounts) return dec_ucount(ucounts, UCOUNT_IMA_NAMESPACES); }
-static int ima_ns_add_boot_aggregate(struct ima_namespace *ima_ns) -{ - static const char op[] = "ns_add_boot_aggregate"; - static const char ns_aggregate_name_prefix[] = "ns_aggregate_"; - const char *audit_cause = "ENOMEM"; - struct ima_template_entry *entry; - struct integrity_iint_cache tmp_iint, *iint = &tmp_iint; - struct ima_event_data event_data = { .iint = iint }; - int result = -ENOMEM; - int violation = 0; - struct { - struct ima_digest_data hdr; - char digest[TPM_DIGEST_SIZE]; - } hash; - unsigned int ns_id = get_ns_id(ima_ns); - char *ns_aggregate_name; - - ns_aggregate_name = kmalloc(sizeof(ns_aggregate_name_prefix) + - sizeof(unsigned int), - GFP_KERNEL); - if (!ns_aggregate_name) - goto err_out; - - sprintf(ns_aggregate_name, "%s%u", ns_aggregate_name_prefix, ns_id); - - event_data.filename = ns_aggregate_name; - event_data.ns_id = ns_id; - - memset(iint, 0, sizeof(*iint)); - memset(&hash, 0, sizeof(hash)); - iint->ima_hash = &hash.hdr; - iint->ima_hash->algo = HASH_ALGO_SHA1; - iint->ima_hash->length = SHA1_DIGEST_SIZE; - - result = ima_alloc_init_template(&event_data, &entry, NULL); - if (result < 0) { - audit_cause = "alloc_entry"; - goto err_out; - } - - result = ima_store_template(entry, violation, NULL, - ns_aggregate_name, - CONFIG_IMA_MEASURE_PCR_IDX, - NULL, - ima_ns); - if (result < 0) { - ima_free_template_entry(entry); - audit_cause = "store_entry"; - } - -err_out: - if (result < 0) - integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, - ns_aggregate_name, op, audit_cause, - result, 0); - kfree(ns_aggregate_name); - - return result; -} - #ifdef CONFIG_IMA_LOAD_X509 static int ima_ns_load_x509(struct ima_namespace *ima_ns) { @@ -445,8 +385,6 @@ static int imans_activate(struct ima_namespace *ima_ns) list_add_tail(&ima_ns->list, &ima_ns_list); up_write(&ima_ns_list_lock);
- ima_ns_add_boot_aggregate(ima_ns); - /* The x509 certificate has to be measured in the new namespace as * well as in the parent namespace, therefore it has to be loaded * after adding the namespace to the list of active namespaces. If
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 48b9f44a56cb6036d23c14e64e7eab69145acd69.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 1 - security/integrity/digsig.c | 6 +-- security/integrity/ima/ima_main.c | 12 ++---- security/integrity/ima/ima_ns.c | 65 +++++++------------------------ security/integrity/integrity.h | 2 +- 5 files changed, 21 insertions(+), 65 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index f011c6e6aa86..eb022229c694 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -240,7 +240,6 @@ struct ima_namespace { #ifdef CONFIG_KEYS struct key_tag *key_domain; #endif - struct task_struct *activating_tsk; /* used only for the ns activation */ } __randomize_layout;
extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 2c923dc0dbd3..4d2579a2c5ea 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -171,8 +171,8 @@ int __init integrity_init_keyring(const unsigned int id) return __integrity_init_keyring(id, perm, restriction); }
-int integrity_add_key(const unsigned int id, const void *data, - off_t size, key_perm_t perm) +int __init integrity_add_key(const unsigned int id, const void *data, + off_t size, key_perm_t perm) { key_ref_t key; int rc = 0; @@ -196,7 +196,7 @@ int integrity_add_key(const unsigned int id, const void *data,
}
-int integrity_load_x509(const unsigned int id, const char *path) +int __init integrity_load_x509(const unsigned int id, const char *path) { void *data = NULL; size_t size; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index e905b70ab0bd..5014eb586587 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -364,12 +364,9 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, return 0;
if (ima_ns != current_ima_ns) { - if (!(ima_ns->activating_tsk && (ima_ns->activating_tsk == - current))) { - iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); - if (!iint) - return 0; - } + iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); + if (!iint) + return 0; }
/* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action @@ -414,8 +411,7 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, goto out; if (!action) goto out; - if ((ima_ns != current_ima_ns) && - !(ima_ns->activating_tsk && (ima_ns->activating_tsk == current))) + if (ima_ns != current_ima_ns) goto out;
mutex_lock(&iint->mutex); diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index b04f35f35f85..639e5eadee31 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -49,30 +49,6 @@ static void dec_ima_namespaces(struct ucounts *ucounts) return dec_ucount(ucounts, UCOUNT_IMA_NAMESPACES); }
-#ifdef CONFIG_IMA_LOAD_X509 -static int ima_ns_load_x509(struct ima_namespace *ima_ns) -{ - int res = 0; - int unset_flags = - ima_ns->policy_data->ima_policy_flag & IMA_APPRAISE; - - if (!ima_ns->x509_path_for_children) - return res; - - ima_ns->policy_data->ima_policy_flag &= ~unset_flags; - res = integrity_load_x509(INTEGRITY_KEYRING_IMA, - ima_ns->x509_path_for_children); - ima_ns->policy_data->ima_policy_flag |= unset_flags; - - return res; -} -#else -static inline int ima_ns_load_x509(struct ima_namespace *ima_ns) -{ - return 0; -} -#endif - static struct ima_namespace *ima_ns_alloc(void) { struct ima_namespace *ima_ns; @@ -385,22 +361,6 @@ static int imans_activate(struct ima_namespace *ima_ns) list_add_tail(&ima_ns->list, &ima_ns_list); up_write(&ima_ns_list_lock);
- /* The x509 certificate has to be measured in the new namespace as - * well as in the parent namespace, therefore it has to be loaded - * after adding the namespace to the list of active namespaces. If - * defined in the policy, the parent IMA ns can also appraise the - * certificate, appraisal is disabled only in the new namespace. If - * loading the certificate fails, print a warning but don't return an - * error - there is no way to handle it well at this point, in - * the worst case, user will end up with a failed appraisal */ - ima_ns->activating_tsk = current; - res = ima_ns_load_x509(ima_ns); - ima_ns->activating_tsk = NULL; - if (res < 0) { - pr_err("IMA ns x509 cert. loading failed, appraisal will fail\n"); - res = 0; - } - destroy_child_config(ima_ns); out: mutex_unlock(&frozen_lock); @@ -410,10 +370,9 @@ static int imans_activate(struct ima_namespace *ima_ns)
static int imans_install(struct nsset *nsset, struct ns_common *new) { - int res = 0; + int res; struct nsproxy *nsproxy = nsset->nsproxy; struct ima_namespace *ns = to_ima_ns(new); - struct ima_namespace *old_ns = nsproxy->ima_ns;
if (!current_is_single_threaded()) return -EUSERS; @@ -422,20 +381,19 @@ static int imans_install(struct nsset *nsset, struct ns_common *new) !ns_capable(nsset->cred->user_ns, CAP_SYS_ADMIN)) return -EPERM;
+ res = imans_activate(ns); + if (res) + return res; + get_ima_ns(ns); - put_ima_ns(old_ns); + put_ima_ns(nsproxy->ima_ns); nsproxy->ima_ns = ns;
get_ima_ns(ns); put_ima_ns(nsproxy->ima_ns_for_children); nsproxy->ima_ns_for_children = ns;
- if (!ns->frozen && (ns->user_ns != nsset->cred->user_ns)) { - res = ima_swap_user_ns(ns, nsset->cred->user_ns); - if (res) - return res; - } - return imans_activate(ns); + return res; }
int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk, @@ -443,7 +401,6 @@ int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk, { int res; struct ima_namespace *ima_ns = nsproxy->ima_ns_for_children; - struct ima_namespace *old_ima_ns = nsproxy->ima_ns;
/* create_new_namespaces() already incremented the ref counter */ if (nsproxy->ima_ns == ima_ns) @@ -459,11 +416,15 @@ int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk, return res; }
+ res = imans_activate(ima_ns); + if (res) + return res; + get_ima_ns(ima_ns); - put_ima_ns(old_ima_ns); + put_ima_ns(nsproxy->ima_ns); nsproxy->ima_ns = ima_ns;
- return imans_activate(ima_ns); + return res; }
static struct user_namespace *imans_owner(struct ns_common *ns) diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index e00adc23f3e9..423e61627716 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -223,7 +223,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, int integrity_modsig_verify(unsigned int id, const struct modsig *modsig);
int __init integrity_init_keyring(const unsigned int id); -int integrity_load_x509(const unsigned int id, const char *path); +int __init integrity_load_x509(const unsigned int id, const char *path); int __init integrity_load_cert(const unsigned int id, const char *source, const void *data, size_t len, key_perm_t perm); #else
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 1939da7030a6b341cca58ee570e9243c63aa64a8.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/digsig.h | 11 +++---- lib/digsig.c | 11 ++++--- security/integrity/digsig.c | 40 ++++---------------------- security/integrity/digsig_asymmetric.c | 20 +++++-------- security/integrity/integrity.h | 11 +++---- 5 files changed, 26 insertions(+), 67 deletions(-)
diff --git a/include/linux/digsig.h b/include/linux/digsig.h index 9e4121253899..2ace69e41088 100644 --- a/include/linux/digsig.h +++ b/include/linux/digsig.h @@ -44,16 +44,13 @@ struct signature_hdr {
#if defined(CONFIG_SIGNATURE) || defined(CONFIG_SIGNATURE_MODULE)
-int digsig_verify(struct key *keyring, struct key_tag *domain_tag, - const char *sig, int siglen, const char *digest, - int digestlen); +int digsig_verify(struct key *keyring, const char *sig, int siglen, + const char *digest, int digestlen);
#else
-static inline int digsig_verify(struct key *keyring, - struct key_tag *domain_tag, - const char *sig, int siglen, const char *digest, - int digestlen) +static inline int digsig_verify(struct key *keyring, const char *sig, + int siglen, const char *digest, int digestlen) { return -EOPNOTSUPP; } diff --git a/lib/digsig.c b/lib/digsig.c index 4cf5327327c8..04b5e55ed95f 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -196,8 +196,8 @@ static int digsig_verify_rsa(struct key *key, * Normally hash of the content is used as a data for this function. * */ -int digsig_verify(struct key *keyring, struct key_tag *domain_tag, - const char *sig, int siglen, const char *data, int datalen) +int digsig_verify(struct key *keyring, const char *sig, int siglen, + const char *data, int datalen) { int err = -ENOMEM; struct signature_hdr *sh = (struct signature_hdr *)sig; @@ -217,15 +217,14 @@ int digsig_verify(struct key *keyring, struct key_tag *domain_tag, if (keyring) { /* search in specific keyring */ key_ref_t kref; - kref = keyring_search_tag(make_key_ref(keyring, 1UL), - &key_type_user, name, - domain_tag, true); + kref = keyring_search(make_key_ref(keyring, 1UL), + &key_type_user, name, true); if (IS_ERR(kref)) key = ERR_CAST(kref); else key = key_ref_to_ptr(kref); } else { - key = request_key_tag(&key_type_user, name, domain_tag, NULL); + key = request_key(&key_type_user, name, NULL); } if (IS_ERR(key)) { pr_err("key not found, id: %s\n", name); diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 4d2579a2c5ea..0f518dcfde05 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -16,7 +16,6 @@ #include <linux/vmalloc.h> #include <crypto/public_key.h> #include <keys/system_keyring.h> -#include <linux/ima.h>
#include "integrity.h"
@@ -33,16 +32,6 @@ static const char * const keyring_name[INTEGRITY_KEYRING_MAX] = { ".platform", };
-static unsigned long keyring_alloc_flags[INTEGRITY_KEYRING_MAX] = { - KEY_ALLOC_NOT_IN_QUOTA, -#ifdef CONFIG_IMA_NS - KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_DOMAIN_IMA, -#else - KEY_ALLOC_NOT_IN_QUOTA, -#endif - KEY_ALLOC_NOT_IN_QUOTA, -}; - #ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY #define restrict_link_to_ima restrict_link_by_builtin_and_secondary_trusted #else @@ -68,22 +57,10 @@ static struct key *integrity_keyring_from_id(const unsigned int id) return keyring[id]; }
-static struct key_tag *domain_tag_from_id(const unsigned int id) -{ - if (id >= INTEGRITY_KEYRING_MAX) - return ERR_PTR(-EINVAL); - - if (id == INTEGRITY_KEYRING_IMA) - return current->nsproxy->ima_ns->key_domain; - - return NULL; -} - int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, const char *digest, int digestlen) { struct key *keyring; - struct key_tag *domain_tag;
if (siglen < 2) return -EINVAL; @@ -92,18 +69,14 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, if (IS_ERR(keyring)) return PTR_ERR(keyring);
- domain_tag = domain_tag_from_id(id); - if (IS_ERR(domain_tag)) - return PTR_ERR(domain_tag); - switch (sig[1]) { case 1: /* v1 API expect signature without xattr type */ - return digsig_verify(keyring, domain_tag, - sig + 1, siglen - 1, digest, digestlen); + return digsig_verify(keyring, sig + 1, siglen - 1, digest, + digestlen); case 2: - return asymmetric_verify(keyring, domain_tag, sig, siglen, - digest, digestlen); + return asymmetric_verify(keyring, sig, siglen, digest, + digestlen); }
return -EOPNOTSUPP; @@ -129,8 +102,7 @@ static int __init __integrity_init_keyring(const unsigned int id,
keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), KGIDT_INIT(0), cred, perm, - keyring_alloc_flags[id], - restriction, NULL); + KEY_ALLOC_NOT_IN_QUOTA, restriction, NULL); if (IS_ERR(keyring[id])) { err = PTR_ERR(keyring[id]); pr_info("Can't allocate %s keyring (%d)\n", @@ -182,7 +154,7 @@ int __init integrity_add_key(const unsigned int id, const void *data,
key = key_create_or_update(make_key_ref(keyring[id], 1), "asymmetric", NULL, data, size, perm, - keyring_alloc_flags[id]); + KEY_ALLOC_NOT_IN_QUOTA); if (IS_ERR(key)) { rc = PTR_ERR(key); pr_err("Problem loading X.509 certificate %d\n", rc); diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index 8f4cffd73602..92dc64755e53 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c @@ -20,9 +20,7 @@ /* * Request an asymmetric key. */ -static struct key *request_asymmetric_key(struct key *keyring, - struct key_tag *domain_tag, - uint32_t keyid) +static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) { struct key *key; char name[12]; @@ -47,16 +45,14 @@ static struct key *request_asymmetric_key(struct key *keyring, /* search in specific keyring */ key_ref_t kref;
- kref = keyring_search_tag(make_key_ref(keyring, 1), - &key_type_asymmetric, name, - domain_tag, true); + kref = keyring_search(make_key_ref(keyring, 1), + &key_type_asymmetric, name, true); if (IS_ERR(kref)) key = ERR_CAST(kref); else key = key_ref_to_ptr(kref); } else { - key = request_key_tag(&key_type_asymmetric, - name, domain_tag, NULL); + key = request_key(&key_type_asymmetric, name, NULL); }
if (IS_ERR(key)) { @@ -93,9 +89,8 @@ static struct key *request_asymmetric_key(struct key *keyring, return key; }
-int asymmetric_verify(struct key *keyring, struct key_tag *domain_tag, - const char *sig, int siglen, - const char *data, int datalen) +int asymmetric_verify(struct key *keyring, const char *sig, + int siglen, const char *data, int datalen) { struct public_key_signature pks; struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig; @@ -113,8 +108,7 @@ int asymmetric_verify(struct key *keyring, struct key_tag *domain_tag, if (hdr->hash_algo >= HASH_ALGO__LAST) return -ENOPKG;
- key = request_asymmetric_key(keyring, domain_tag, - be32_to_cpu(hdr->keyid)); + key = request_asymmetric_key(keyring, be32_to_cpu(hdr->keyid)); if (IS_ERR(key)) return PTR_ERR(key);
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 423e61627716..78078d55fd33 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -256,14 +256,11 @@ static inline int __init integrity_load_cert(const unsigned int id, #endif /* CONFIG_INTEGRITY_SIGNATURE */
#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS -int asymmetric_verify(struct key *keyring, struct key_tag *domain_tag, - const char *sig, int siglen, - const char *data, int datalen); +int asymmetric_verify(struct key *keyring, const char *sig, + int siglen, const char *data, int datalen); #else -static inline int asymmetric_verify(struct key *keyring, - struct key_tag *domain_tag, - const char *sig, int siglen, - const char *data, int datalen) +static inline int asymmetric_verify(struct key *keyring, const char *sig, + int siglen, const char *data, int datalen) { return -EOPNOTSUPP; }
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 60499d14ead4eb34034adf590773bcebe2e96fe2.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 3 --- security/integrity/ima/ima_init.c | 8 -------- security/integrity/ima/ima_ns.c | 14 -------------- security/keys/key.c | 10 +++------- 4 files changed, 3 insertions(+), 32 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index eb022229c694..1270337c1d99 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -237,9 +237,6 @@ struct ima_namespace { atomic_long_t violations; char *x509_path_for_children; struct ima_policy_setup_data *policy_setup_for_children; -#ifdef CONFIG_KEYS - struct key_tag *key_domain; -#endif } __randomize_layout;
extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 73fb0f0e82c5..7a0a640fdf9c 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -18,7 +18,6 @@ #include <linux/kref.h> #include <linux/proc_ns.h> #include <linux/user_namespace.h> -#include <linux/key.h>
#include "ima.h"
@@ -26,10 +25,6 @@ const char boot_aggregate_name[] = "boot_aggregate"; struct tpm_chip *ima_tpm_chip;
-#ifdef CONFIG_KEYS -static struct key_tag init_ima_key_domain = { .usage = REFCOUNT_INIT(1) }; -#endif - struct ima_namespace init_ima_ns = { .kref = KREF_INIT(2), .user_ns = &init_user_ns, @@ -45,9 +40,6 @@ struct ima_namespace init_ima_ns = { .ns_measurements = LIST_HEAD_INIT(init_ima_ns.ns_measurements), .ml_len = ATOMIC_LONG_INIT(0), .violations = ATOMIC_LONG_INIT(0), -#ifdef CONFIG_KEYS - .key_domain = &init_ima_key_domain, -#endif }; EXPORT_SYMBOL(init_ima_ns);
diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 639e5eadee31..57dc9fedb8fd 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -29,7 +29,6 @@ #include <linux/spinlock.h> #include <linux/string.h> #include <linux/kernel.h> -#include <linux/key.h>
#include "ima.h"
@@ -67,16 +66,8 @@ static struct ima_namespace *ima_ns_alloc(void) if (!ima_ns->iint_tree) goto policy_free;
-#ifdef CONFIG_KEYS - ima_ns->key_domain = kzalloc(sizeof(struct key_tag), GFP_KERNEL); - if (!ima_ns->key_domain) - goto iint_free; -#endif - return ima_ns;
-iint_free: - kfree(ima_ns->iint_tree); policy_free: kfree(ima_ns->policy_data); ns_free: @@ -156,9 +147,6 @@ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, rwlock_init(&ns->iint_tree->lock); ns->iint_tree->root = RB_ROOT;
-#ifdef CONFIG_KEYS - refcount_set(&ns->key_domain->usage, 1); -#endif ns->x509_path_for_children = NULL; ns->policy_setup_for_children = NULL;
@@ -172,7 +160,6 @@ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, fail_free: kfree(ns->iint_tree); kfree(ns->policy_data); - kfree(ns->key_domain); kfree(ns); fail_dec: dec_ima_namespaces(ucounts); @@ -244,7 +231,6 @@ static void destroy_ima_ns(struct ima_namespace *ns)
imans_remove_hash_entries(ns); dec_ima_namespaces(ns->ucounts); - key_remove_domain(ns->key_domain); put_user_ns(ns->user_ns); ns_free_inum(&ns->ns); integrity_iint_tree_free(ns->iint_tree); diff --git a/security/keys/key.c b/security/keys/key.c index 43de2dfe95cf..d052b9a0b1fd 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -285,14 +285,10 @@ struct key *key_alloc(struct key_type *type, const char *desc,
/* set domain tag if it's not predefined for the key type */ if ((!type->flags) && (flags & KEY_ALLOC_DOMAIN_IMA)) - /* Use ima_ns_for_children, not ima_ns. ima_ns_for - * children is equal to ima_ns, unless ima namespace was - * unshared and the new namespace is being configured. - * In that case, new keys should be associated with the - * new ima namespace. + /* Set it to something meaningful after adding a key + * domain to the ima namespace. */ - key->index_key.domain_tag = - current->nsproxy->ima_ns_for_children->key_domain; + key->index_key.domain_tag = NULL; }
key->index_key.desc_len = desclen;
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 14409624e2d8b4a38a0d597d295b0337c6363118.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/key.h | 10 ---------- security/keys/key.c | 16 ---------------- 2 files changed, 26 deletions(-)
diff --git a/include/linux/key.h b/include/linux/key.h index 61250dfd9ccc..53684db44615 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -272,12 +272,6 @@ struct key { * restriction. */ struct key_restriction *restrict_link; - - /* This is set on a keyring to indicate that every key added to this - * keyring should be tagged with a given key domain tag. It is ignored - * for the non-keyring keys and can be overridden by the key-type flags. - */ - unsigned long key_alloc_domain; };
extern struct key *key_alloc(struct key_type *type, @@ -297,10 +291,6 @@ extern struct key *key_alloc(struct key_type *type, #define KEY_ALLOC_UID_KEYRING 0x0010 /* allocating a user or user session keyring */ #define KEY_ALLOC_SET_KEEP 0x0020 /* Set the KEEP flag on the key/keyring */
-/* Only one domain can be set */ -#define KEY_ALLOC_DOMAIN_IMA 0x0100 /* add IMA domain tag, based on the "current" */ -#define KEY_ALLOC_DOMAIN_MASK 0xFF00 - extern void key_revoke(struct key *key); extern void key_invalidate(struct key *key); extern void key_put(struct key *key); diff --git a/security/keys/key.c b/security/keys/key.c index d052b9a0b1fd..151ff39b6803 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -278,19 +278,6 @@ struct key *key_alloc(struct key_type *type, const char *desc, if (!key) goto no_memory_2;
- if (flags & KEY_ALLOC_DOMAIN_MASK) { - /* set alloc domain for all keys added to this keyring */ - if (type == &key_type_keyring) - key->key_alloc_domain = (flags & KEY_ALLOC_DOMAIN_MASK); - - /* set domain tag if it's not predefined for the key type */ - if ((!type->flags) && (flags & KEY_ALLOC_DOMAIN_IMA)) - /* Set it to something meaningful after adding a key - * domain to the ima namespace. - */ - key->index_key.domain_tag = NULL; - } - key->index_key.desc_len = desclen; key->index_key.description = kmemdup(desc, desclen + 1, GFP_KERNEL); if (!key->index_key.description) @@ -940,9 +927,6 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, perm |= KEY_POS_WRITE; }
- if (keyring->key_alloc_domain) - flags |= keyring->key_alloc_domain; - /* allocate a new key */ key = key_alloc(index_key.type, index_key.description, cred->fsuid, cred->fsgid, cred, perm, flags, NULL);
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 44313f67cf0a250d08efe9c87e3cea8bbe8138f0.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- crypto/asymmetric_keys/asymmetric_type.c | 20 ++++---------------- include/linux/key-type.h | 1 - security/keys/keyring.c | 10 +--------- 3 files changed, 5 insertions(+), 26 deletions(-)
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index 177429bc5c7b..33e77d846caa 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -249,15 +249,9 @@ static bool asymmetric_key_cmp(const struct key *key, { const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); const struct asymmetric_key_id *match_id = match_data->preparsed; - bool match;
- match = asymmetric_match_key_ids(kids, match_id, - asymmetric_key_id_same); - - if (match_data->domain_tag) - match &= key->index_key.domain_tag == match_data->domain_tag; - - return match; + return asymmetric_match_key_ids(kids, match_id, + asymmetric_key_id_same); }
/* @@ -268,15 +262,9 @@ static bool asymmetric_key_cmp_partial(const struct key *key, { const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); const struct asymmetric_key_id *match_id = match_data->preparsed; - bool match; - - match = asymmetric_match_key_ids(kids, match_id, - asymmetric_key_id_partial); - - if (match_data->domain_tag) - match &= key->index_key.domain_tag == match_data->domain_tag;
- return match; + return asymmetric_match_key_ids(kids, match_id, + asymmetric_key_id_partial); }
/* diff --git a/include/linux/key-type.h b/include/linux/key-type.h index c8ea26ab242c..2ab2d6d6aeab 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h @@ -55,7 +55,6 @@ struct key_match_data { unsigned lookup_type; /* Type of lookup for this search. */ #define KEYRING_SEARCH_LOOKUP_DIRECT 0x0000 /* Direct lookup by description. */ #define KEYRING_SEARCH_LOOKUP_ITERATE 0x0001 /* Iterative search. */ - struct key_tag *domain_tag; /* Key domain tag */ };
/* diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 7e45e534035f..12583241ff63 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -565,13 +565,7 @@ int restrict_link_reject(struct key *keyring, bool key_default_cmp(const struct key *key, const struct key_match_data *match_data) { - bool match; - - match = strcmp(key->description, match_data->raw_data) == 0; - if (match_data->domain_tag) - match &= key->index_key.domain_tag == match_data->domain_tag; - - return match; + return strcmp(key->description, match_data->raw_data) == 0; }
/* @@ -963,8 +957,6 @@ key_ref_t keyring_search_tag(key_ref_t keyring,
if (recurse) ctx.flags |= KEYRING_SEARCH_RECURSE; - if (domain_tag) - ctx.match_data.domain_tag = domain_tag; if (type->match_preparse) { ret = type->match_preparse(&ctx.match_data); if (ret < 0)
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit d3ef5f857c80b3cd26ce870544eda841410fb278.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/key.h | 17 ++++------------- security/keys/keyring.c | 15 ++++++--------- 2 files changed, 10 insertions(+), 22 deletions(-)
diff --git a/include/linux/key.h b/include/linux/key.h index 53684db44615..eed3ce139a32 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -417,11 +417,10 @@ extern int restrict_link_reject(struct key *keyring,
extern int keyring_clear(struct key *keyring);
-extern key_ref_t keyring_search_tag(key_ref_t keyring, - struct key_type *type, - const char *description, - struct key_tag *domain_tag, - bool recurse); +extern key_ref_t keyring_search(key_ref_t keyring, + struct key_type *type, + const char *description, + bool recurse);
extern int keyring_add_key(struct key *keyring, struct key *key); @@ -431,14 +430,6 @@ extern int keyring_restrict(key_ref_t keyring, const char *type,
extern struct key *key_lookup(key_serial_t id);
-static inline key_ref_t keyring_search(key_ref_t keyring, - struct key_type *type, - const char *description, - bool recurse) -{ - return keyring_search_tag(keyring, type, description, NULL, recurse); -} - static inline key_serial_t key_serial(const struct key *key) { return key ? key->serial : 0; diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 12583241ff63..14abfe765b7e 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -925,25 +925,22 @@ key_ref_t keyring_search_rcu(key_ref_t keyring_ref, }
/** - * keyring_search_tag - Search the supplied keyring tree for a matching key + * keyring_search - Search the supplied keyring tree for a matching key * @keyring: The root of the keyring tree to be searched. * @type: The type of keyring we want to find. * @description: The name of the keyring we want to find. - * @domain_tag: The domain_tag of the key we want to find. * @recurse: True to search the children of @keyring also * * As keyring_search_rcu() above, but using the current task's credentials and * type's default matching function and preferred search method. */ -key_ref_t keyring_search_tag(key_ref_t keyring, - struct key_type *type, - const char *description, - struct key_tag *domain_tag, - bool recurse) +key_ref_t keyring_search(key_ref_t keyring, + struct key_type *type, + const char *description, + bool recurse) { struct keyring_search_context ctx = { .index_key.type = type, - .index_key.domain_tag = domain_tag, .index_key.description = description, .index_key.desc_len = strlen(description), .cred = current_cred(), @@ -971,7 +968,7 @@ key_ref_t keyring_search_tag(key_ref_t keyring, type->match_free(&ctx.match_data); return key; } -EXPORT_SYMBOL(keyring_search_tag); +EXPORT_SYMBOL(keyring_search);
static struct key_restriction *keyring_restriction_alloc( key_restrict_link_func_t check)
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit dc3fb393396b4497550ea290ab4b0f04dbb6249c.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- security/integrity/ima/ima_policy.c | 99 ++++------------------------- 1 file changed, 12 insertions(+), 87 deletions(-)
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 42bafb520e4e..a2f1253b46dc 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -19,7 +19,6 @@ #include <linux/genhd.h> #include <linux/seq_file.h> #include <linux/ima.h> -#include <linux/user_namespace.h>
#include "ima.h" #include "ima_digest_list.h" @@ -87,10 +86,6 @@ struct ima_rule_entry { char *fsname; struct ima_rule_opt_list *keyrings; /* Measure keys added to these keyrings */ struct ima_template_desc *template; - bool remap_uid; /* IDs of all subject oriented rules, added before the - * user namespace mapping is defined, - * have to be remapped. - */ };
/* @@ -578,8 +573,6 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, const char *keyring) { int i; - kuid_t remapped_kuid; - struct ima_namespace *current_ima_ns = get_current_ns();
if (func == KEY_CHECK) { return (rule->flags & IMA_FUNC) && (rule->func == func) && @@ -603,49 +596,24 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, if ((rule->flags & IMA_FSUUID) && !uuid_equal(&rule->fsuuid, &inode->i_sb->s_uuid)) return false; - if (rule->flags & IMA_UID) { - if (rule->remap_uid) { - remapped_kuid = make_kuid(current_ima_ns->user_ns, - __kuid_val(rule->uid)); - if (!uid_valid(remapped_kuid)) - return false; - } else - remapped_kuid = rule->uid; - if (!rule->uid_op(cred->uid, remapped_kuid)) - return false; - } + if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid)) + return false; if (rule->flags & IMA_EUID) { - if (rule->remap_uid) { - remapped_kuid = make_kuid(current_ima_ns->user_ns, - __kuid_val(rule->uid)); - if (!uid_valid(remapped_kuid)) - return false; - } else - remapped_kuid = rule->uid; if (has_capability_noaudit(current, CAP_SETUID)) { - if (!rule->uid_op(cred->euid, remapped_kuid) - && !rule->uid_op(cred->suid, remapped_kuid) - && !rule->uid_op(cred->uid, remapped_kuid)) + if (!rule->uid_op(cred->euid, rule->uid) + && !rule->uid_op(cred->suid, rule->uid) + && !rule->uid_op(cred->uid, rule->uid)) return false; - } else if (!rule->uid_op(cred->euid, remapped_kuid)) + } else if (!rule->uid_op(cred->euid, rule->uid)) return false; }
- if (rule->flags & IMA_FOWNER) { - if (rule->remap_uid) { - remapped_kuid = make_kuid(current_ima_ns->user_ns, - __kuid_val(rule->fowner)); - if (!uid_valid(remapped_kuid)) - return false; - } else - remapped_kuid = rule->fowner; - if (!rule->fowner_op(inode->i_uid, remapped_kuid)) - return false; - } + if ((rule->flags & IMA_FOWNER) && + !rule->fowner_op(inode->i_uid, rule->fowner)) + return false; if ((rule->flags & IMA_PARSER) && !ima_current_is_parser()) return false; - for (i = 0; i < MAX_LSM_RULES; i++) { int rc = 0; u32 osid; @@ -828,9 +796,6 @@ static void add_rules(struct ima_namespace *ima_ns,
for (i = 0; i < count; i++) { struct ima_rule_entry *entry; - bool set_uidmap; - - set_uidmap = userns_set_uidmap(ima_ns->user_ns);
if (setup_data->ima_policy == EXEC_TCB) { if (entries == dont_measure_rules) @@ -867,17 +832,6 @@ static void add_rules(struct ima_namespace *ima_ns, GFP_KERNEL); if (!entry) continue; - - if (!set_uidmap) - entry->remap_uid = true; - else { - entry->uid = - make_kuid(ima_ns->user_ns, - __kuid_val(entry->uid)); - entry->fowner = - make_kuid(ima_ns->user_ns, - __kuid_val(entry->fowner)); - } }
list_add_tail(&entry->list, @@ -890,19 +844,6 @@ static void add_rules(struct ima_namespace *ima_ns, if (!entry) continue;
- if (ima_ns != &init_ima_ns) { - if (!set_uidmap) - entry->remap_uid = true; - else { - entry->uid = - make_kuid(ima_ns->user_ns, - __kuid_val(entry->uid)); - entry->fowner = - make_kuid(ima_ns->user_ns, - __kuid_val(entry->fowner)); - } - } - list_add_tail(&entry->list, &ima_ns->policy_data->ima_policy_rules); } @@ -1377,10 +1318,6 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry, ab = integrity_audit_log_start(audit_context(), GFP_KERNEL, AUDIT_INTEGRITY_POLICY_RULE);
- if ((ima_ns != &init_ima_ns) && - (!userns_set_uidmap(ima_ns->user_ns))) - entry->remap_uid = true; - entry->uid = INVALID_UID; entry->fowner = INVALID_UID; entry->uid_op = &uid_eq; @@ -1597,13 +1534,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry,
result = kstrtoul(args[0].from, 10, &lnum); if (!result) { - if (!entry->remap_uid) - entry->uid = - make_kuid(current_user_ns(), - (uid_t) lnum); - else - entry->uid = KUIDT_INIT((uid_t) lnum); - + entry->uid = make_kuid(current_user_ns(), + (uid_t) lnum); if (!uid_valid(entry->uid) || (uid_t)lnum != lnum) result = -EINVAL; @@ -1630,14 +1562,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry,
result = kstrtoul(args[0].from, 10, &lnum); if (!result) { - if (!entry->remap_uid) - entry->fowner = - make_kuid(current_user_ns(), - (uid_t) lnum); - else - entry->fowner = - KUIDT_INIT((uid_t) lnum); - + entry->fowner = make_kuid(current_user_ns(), (uid_t)lnum); if (!uid_valid(entry->fowner) || (((uid_t)lnum) != lnum)) result = -EINVAL; else
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 44a41d572da65f3975c5e36fe3270a7fdaabe821.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/user_namespace.h | 6 ------ kernel/user_namespace.c | 11 ----------- 2 files changed, 17 deletions(-)
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 6cb6a455e7aa..3eb64a50f248 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -141,7 +141,6 @@ extern bool in_userns(const struct user_namespace *ancestor, const struct user_namespace *child); extern bool current_in_userns(const struct user_namespace *target_ns); struct ns_common *ns_get_owner(struct ns_common *ns); -extern bool userns_set_uidmap(const struct user_namespace *ns); #else
static inline struct user_namespace *get_user_ns(struct user_namespace *ns) @@ -186,11 +185,6 @@ static inline struct ns_common *ns_get_owner(struct ns_common *ns) { return ERR_PTR(-EPERM); } - -static inline bool userns_set_uidmap(const struct user_namespace *ns) -{ - return true; -} #endif
#endif /* _LINUX_USER_H */ diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index a57d52edbc31..2c15bf6680c3 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -1291,17 +1291,6 @@ bool current_in_userns(const struct user_namespace *target_ns) } EXPORT_SYMBOL(current_in_userns);
-bool userns_set_uidmap(const struct user_namespace *ns) -{ - bool mapping_defined; - - mutex_lock(&userns_state_mutex); - mapping_defined = ns->uid_map.nr_extents != 0; - mutex_unlock(&userns_state_mutex); - - return mapping_defined; -} - static inline struct user_namespace *to_user_ns(struct ns_common *ns) { return container_of(ns, struct user_namespace, ns);
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 3ead0c63db58659733ce00c92af02554f5c03e14.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- security/integrity/ima/ima.h | 6 +++--- security/integrity/ima/ima_fs.c | 13 ++++++------- security/integrity/ima/ima_policy.c | 25 ++++++++++++++----------- 3 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 5b1364eb1477..dd43dbdab7b9 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -312,10 +312,10 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, void ima_init_policy(void); void ima_init_ns_policy(struct ima_namespace *ima_ns, const struct ima_policy_setup_data *policy_setup_data); -void ima_update_policy(struct ima_namespace *ima_ns); +void ima_update_policy(void); void ima_update_policy_flag(struct ima_namespace *ima_ns); -ssize_t ima_parse_add_rule(char *rule, struct ima_namespace *ima_ns); -void ima_delete_rules(struct ima_namespace *ima_ns); +ssize_t ima_parse_add_rule(char *); +void ima_delete_rules(void); int ima_check_policy(const struct ima_namespace *ima_ns); void *ima_policy_start(struct seq_file *m, loff_t *pos); void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index d9c7e1d6d543..74a4aad02f33 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -328,8 +328,7 @@ static const struct file_operations ima_ascii_measurements_ops = { .release = seq_release, };
-static ssize_t ima_read_sfs_file(char *path, struct dentry *dentry, - struct ima_namespace *ima_ns) +static ssize_t ima_read_sfs_file(char *path, struct dentry *dentry) { void *data = NULL; char *datap; @@ -371,7 +370,7 @@ static ssize_t ima_read_sfs_file(char *path, struct dentry *dentry, break;
pr_debug("rule: %s\n", p); - rc = ima_parse_add_rule(p, ima_ns); + rc = ima_parse_add_rule(p); } else if (dentry == digest_list_data || dentry == digest_list_data_del) { #ifdef CONFIG_IMA_DIGEST_LIST @@ -457,7 +456,7 @@ static ssize_t ima_write_data(struct file *file, const char __user *buf, goto out_free;
if (data[0] == '/') { - result = ima_read_sfs_file(data, dentry, ima_ns); + result = ima_read_sfs_file(data, dentry); } else if (dentry == ima_policy) { if (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_POLICY) { pr_err("signed policy file (specified " @@ -467,7 +466,7 @@ static ssize_t ima_write_data(struct file *file, const char __user *buf, "signed policy required", 1, 0); result = -EACCES; } else { - result = ima_parse_add_rule(data, ima_ns); + result = ima_parse_add_rule(data); } } else if (dentry == digest_list_data) { if (!ima_current_is_parser()) { @@ -598,13 +597,13 @@ static int ima_release_data_upload(struct inode *inode, struct file *file) "policy_update", cause, !valid_policy, 0);
if (!valid_policy) { - ima_delete_rules(ima_ns); + ima_delete_rules(); valid_policy = 1; clear_bit(flag, &ima_fs_flags); return 0; }
- ima_update_policy(ima_ns); + ima_update_policy(); #if !defined(CONFIG_IMA_WRITE_POLICY) && !defined(CONFIG_IMA_READ_POLICY) securityfs_remove(ima_policy); ima_policy = NULL; diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index a2f1253b46dc..828793553a0e 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -858,8 +858,7 @@ static void add_rules(struct ima_namespace *ima_ns, } }
-static int ima_parse_rule(char *rule, struct ima_rule_entry *entry, - struct ima_namespace *ima_ns); +static int ima_parse_rule(char *rule, struct ima_rule_entry *entry);
static int ima_init_arch_policy(void) { @@ -889,8 +888,7 @@ static int ima_init_arch_policy(void) result = strlcpy(rule, *rules, sizeof(rule));
INIT_LIST_HEAD(&arch_policy_entry[i].list); - result = ima_parse_rule(rule, &arch_policy_entry[i], - &init_ima_ns); + result = ima_parse_rule(rule, &arch_policy_entry[i]); if (result) { pr_warn("Skipping unknown architecture policy rule: %s\n", rule); @@ -1046,8 +1044,10 @@ int ima_check_policy(const struct ima_namespace *ima_ns) * Policy rules are never deleted so ima_policy_flag gets zeroed only once when * we switch from the default policy to user defined. */ -void ima_update_policy(struct ima_namespace *ima_ns) +void ima_update_policy(void) { + /* Update only the current ima namespace */ + struct ima_namespace *ima_ns = get_current_ns(); struct list_head *policy = &ima_ns->policy_data->ima_policy_rules;
list_splice_tail_init_rcu(&ima_ns->policy_data->ima_temp_rules, @@ -1305,8 +1305,7 @@ static bool ima_validate_rule(struct ima_rule_entry *entry) return true; }
-static int ima_parse_rule(char *rule, struct ima_rule_entry *entry, - struct ima_namespace *ima_ns) +static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) { struct audit_buffer *ab; char *from; @@ -1314,6 +1313,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry, bool uid_token; struct ima_template_desc *template_desc; int result = 0; + struct ima_namespace *ima_ns = get_current_ns();
ab = integrity_audit_log_start(audit_context(), GFP_KERNEL, AUDIT_INTEGRITY_POLICY_RULE); @@ -1692,18 +1692,19 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry, /** * ima_parse_add_rule - add a rule to ima_policy_rules * @rule - ima measurement policy rule - * @ima_ns - pointer to the ima namespace the rule will be added to * * Avoid locking by allowing just one writer at a time in ima_write_policy() * Returns the length of the rule parsed, an error code on failure */ -ssize_t ima_parse_add_rule(char *rule, struct ima_namespace *ima_ns) +ssize_t ima_parse_add_rule(char *rule) { static const char op[] = "update_policy"; char *p; struct ima_rule_entry *entry; ssize_t result, len; int audit_info = 0; + /* Add rules only to the current ima namespace */ + struct ima_namespace *ima_ns = get_current_ns();
p = strsep(&rule, "\n"); len = strlen(p) + 1; @@ -1721,7 +1722,7 @@ ssize_t ima_parse_add_rule(char *rule, struct ima_namespace *ima_ns)
INIT_LIST_HEAD(&entry->list);
- result = ima_parse_rule(p, entry, ima_ns); + result = ima_parse_rule(p, entry); if (result) { ima_free_rule(entry); integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, @@ -1741,8 +1742,10 @@ ssize_t ima_parse_add_rule(char *rule, struct ima_namespace *ima_ns) * different from the active one. There is also only one user of * ima_delete_rules() at a time. */ -void ima_delete_rules(struct ima_namespace *ima_ns) +void ima_delete_rules(void) { + /* Delete rules only from the current ima namespace */ + struct ima_namespace *ima_ns = get_current_ns(); struct ima_rule_entry *entry, *tmp;
ima_ns->policy_data->temp_ima_appraise = 0;
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit be54067bbe893e4cd860292c943854e24fdea25e.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 2 - security/integrity/ima/ima.h | 19 ++-- security/integrity/ima/ima_appraise.c | 9 +- security/integrity/ima/ima_fs.c | 121 ++-------------------- security/integrity/ima/ima_init.c | 2 - security/integrity/ima/ima_ns.c | 140 ++++---------------------- security/integrity/ima/ima_policy.c | 40 +++----- 7 files changed, 55 insertions(+), 278 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index 1270337c1d99..91c637c943ed 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -235,8 +235,6 @@ struct ima_namespace { struct list_head ns_measurements; atomic_long_t ml_len; /* number of stored measurements in the list */ atomic_long_t violations; - char *x509_path_for_children; - struct ima_policy_setup_data *policy_setup_for_children; } __randomize_layout;
extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index dd43dbdab7b9..fce3fc065027 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -67,7 +67,6 @@ struct ima_policy_setup_data { bool ima_use_appraise_tcb; bool ima_use_appraise_exec_tcb; bool ima_use_appraise_exec_immutable; - bool fail_unverifiable_sigs; };
/* IMA event related data */ @@ -322,10 +321,15 @@ void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos); void ima_policy_stop(struct seq_file *m, void *v); int ima_policy_show(struct seq_file *m, void *v);
-int ima_policy_setup(char *str, struct ima_namespace *ima_ns); -int ima_default_measure_policy_setup(char *str, struct ima_namespace *ima_ns); -int ima_default_appraise_policy_setup(char *str, struct ima_namespace *ima_ns); -int ima_default_appraise_setup(char *str, struct ima_namespace *ima_ns); +int ima_policy_setup(char *str, + struct ima_policy_setup_data *policy_setup_data, + bool *fail_unverifiable_sigs); +int ima_default_measure_policy_setup(const char *str, + struct ima_policy_setup_data *setup_data); +int ima_default_appraise_policy_setup(const char *str, + struct ima_policy_setup_data *setup_data); +int ima_default_appraise_setup(const char *str, + struct ima_policy_setup_data *setup_data);
/* Appraise integrity measurements */ #define IMA_APPRAISE_ENFORCE 0x01 @@ -428,11 +432,6 @@ static inline struct ima_namespace *get_current_ns(void)
void ima_delete_ns_rules(struct ima_policy_data *policy_data, bool is_root_ns); - -ssize_t ima_ns_write_x509_for_children(struct ima_namespace *ima_ns, - char *x509_path); -ssize_t ima_ns_write_kcmd_for_children(struct ima_namespace *ima_ns, - char *kcmd); #else static inline int __init ima_init_namespace(void) { diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index c30262468e4c..9d041e3deef2 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -19,12 +19,9 @@
static bool ima_appraise_req_evm __ro_after_init;
-int ima_default_appraise_setup(char *str, - struct ima_namespace *ima_ns) +int ima_default_appraise_setup(const char *str, + struct ima_policy_setup_data *setup_data) { - struct ima_policy_setup_data *setup_data = (ima_ns == &init_ima_ns) ? - &init_policy_setup_data : ima_ns->policy_setup_for_children; - #ifdef CONFIG_IMA_APPRAISE_BOOTPARAM bool sb_state = arch_ima_get_secureboot(); int appraisal_state = setup_data->ima_appraise; @@ -58,7 +55,7 @@ int ima_default_appraise_setup(char *str,
static int __init default_appraise_setup(char *str) { - return ima_default_appraise_setup(str, &init_ima_ns); + return ima_default_appraise_setup(str, &init_policy_setup_data); }
__setup("ima_appraise=", default_appraise_setup); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 74a4aad02f33..bda35e2bb45c 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -23,8 +23,6 @@ #include <linux/vmalloc.h> #include <linux/file.h> #include <linux/ctype.h> -#include <linux/string.h> -#include <linux/kernel.h>
#include "ima.h" #include "ima_digest_list.h" @@ -41,10 +39,6 @@ static struct dentry *ima_policy; static struct dentry *digests_count; static struct dentry *digest_list_data; static struct dentry *digest_list_data_del; -#ifdef CONFIG_IMA_NS -static struct dentry *x509_for_children; -static struct dentry *kcmd_for_children; -#endif /* CONFIG_IMA_NS */
bool ima_canonical_fmt; static int __init default_canonical_fmt_setup(char *str) @@ -58,16 +52,6 @@ __setup("ima_canonical_fmt", default_canonical_fmt_setup);
static int valid_policy = 1;
-static int ima_open_simple(struct inode *inode, struct file *file) -{ - struct ima_namespace *ima_ns = get_current_ns(); - - if (!ns_capable(ima_ns->user_ns, CAP_SYS_ADMIN)) - return -EPERM; - - return 0; -} - static ssize_t ima_show_htable_value(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { @@ -89,8 +73,18 @@ static ssize_t ima_show_htable_value(struct file *filp, char __user *buf, return simple_read_from_buffer(buf, count, ppos, tmpbuf, len); }
+static int ima_open_htable_value(struct inode *inode, struct file *file) +{ + struct ima_namespace *ima_ns = get_current_ns(); + + if (!ns_capable(ima_ns->user_ns, CAP_SYS_ADMIN)) + return -EPERM; + + return 0; +} + static const struct file_operations ima_htable_value_ops = { - .open = ima_open_simple, + .open = ima_open_htable_value, .read = ima_show_htable_value, .llseek = generic_file_llseek, }; @@ -623,79 +617,6 @@ static const struct file_operations ima_data_upload_ops = { .llseek = generic_file_llseek, };
-#ifdef CONFIG_IMA_NS -static int ima_open_for_children(struct inode *inode, struct file *file) -{ - struct ima_namespace *ima_ns = get_current_ns(); - - /* Allow to set children configuration only after unshare() */ - if (ima_ns == current->nsproxy->ima_ns_for_children) - return -EPERM; - - return ima_open_simple(inode, file); -} - -static ssize_t ima_write_x509_for_children(struct file *file, - const char __user *buf, - size_t count, loff_t *ppos) -{ - ssize_t res; - char *x509_path; - struct ima_namespace *ima_ns = current->nsproxy->ima_ns_for_children; - - /* Only allow < page size writes at the beginning of the file */ - if ((*ppos != 0) || (count >= PAGE_SIZE)) - return -EINVAL; - - x509_path = memdup_user_nul(buf, count); - if (IS_ERR(x509_path)) - return PTR_ERR(x509_path); - - res = ima_ns_write_x509_for_children(ima_ns, x509_path); - if (res) { - kfree(x509_path); - count = res; - } - - return count; -} - -static const struct file_operations ima_x509_for_children_ops = { - .open = ima_open_for_children, - .write = ima_write_x509_for_children, -}; - -static ssize_t ima_write_kcmd_for_children(struct file *file, - const char __user *buf, - size_t count, loff_t *ppos) -{ - ssize_t res; - char *kcmd; - struct ima_namespace *ima_ns = current->nsproxy->ima_ns_for_children; - - /* Only allow < page size writes at the beginning of the file */ - if ((*ppos != 0) || (count >= PAGE_SIZE)) - return -EINVAL; - - kcmd = memdup_user_nul(buf, count); - if (IS_ERR(kcmd)) - return PTR_ERR(kcmd); - - res = ima_ns_write_kcmd_for_children(ima_ns, kcmd); - if (res) - count = res; - - kfree(kcmd); - - return count; -} - -static const struct file_operations ima_kcmd_for_children_ops = { - .open = ima_open_for_children, - .write = ima_write_kcmd_for_children, -}; -#endif /* CONFIG_IMA_NS */ - int __init ima_fs_init(void) { ima_dir = securityfs_create_dir("ima", integrity_dir); @@ -759,22 +680,6 @@ int __init ima_fs_init(void) if (IS_ERR(digest_list_data_del)) goto out; #endif -#ifdef CONFIG_IMA_NS - x509_for_children = securityfs_create_file("x509_for_children", - 0202, - ima_dir, NULL, - &ima_x509_for_children_ops); - if (IS_ERR(x509_for_children)) - goto out; - - kcmd_for_children = securityfs_create_file("kcmd_for_children", - 0202, - ima_dir, NULL, - &ima_kcmd_for_children_ops); - if (IS_ERR(kcmd_for_children)) - goto out; -#endif /* CONFIG_IMA_NS */ - return 0; out: securityfs_remove(digest_list_data_del); @@ -787,9 +692,5 @@ int __init ima_fs_init(void) securityfs_remove(ima_symlink); securityfs_remove(ima_dir); securityfs_remove(ima_policy); -#ifdef CONFIG_IMA_NS - securityfs_remove(x509_for_children); - securityfs_remove(kcmd_for_children); -#endif /* CONFIG_IMA_NS */ return -1; } diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 7a0a640fdf9c..923373a12f5c 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -31,8 +31,6 @@ struct ima_namespace init_ima_ns = { .ns.inum = PROC_IMA_INIT_INO, #ifdef CONFIG_IMA_NS .ns.ops = &imans_operations, - .x509_path_for_children = NULL, - .policy_setup_for_children = NULL, #endif .frozen = true, .policy_data = &init_policy_data, diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 57dc9fedb8fd..ac000920d486 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -27,8 +27,6 @@ #include <linux/workqueue.h> #include <linux/mutex.h> #include <linux/spinlock.h> -#include <linux/string.h> -#include <linux/kernel.h>
#include "ima.h"
@@ -76,17 +74,23 @@ static struct ima_namespace *ima_ns_alloc(void) return NULL; }
-static void ima_set_ns_policy(struct ima_namespace *ima_ns) +static void ima_set_ns_policy(struct ima_namespace *ima_ns, + char *policy_setup_str) { - struct ima_policy_setup_data setup_data = {0}; + struct ima_policy_setup_data setup_data;
- if (!ima_ns->policy_setup_for_children) { #ifdef CONFIG_IMA_APPRAISE - setup_data.ima_appraise = IMA_APPRAISE_ENFORCE; + setup_data.ima_appraise = IMA_APPRAISE_ENFORCE; #endif - ima_init_ns_policy(ima_ns, &setup_data); - } else - ima_init_ns_policy(ima_ns, ima_ns->policy_setup_for_children); + /* Configuring IMA namespace will be implemented in the following + * patches. When it is done, parse configuration string and store result + * in setup_data. Temporarily use init_policy_setup_data. + */ + setup_data = init_policy_setup_data; + ima_ns->policy_data->ima_fail_unverifiable_sigs = + init_ima_ns.policy_data->ima_fail_unverifiable_sigs; + + ima_init_ns_policy(ima_ns, &setup_data); }
static int ima_swap_user_ns(struct ima_namespace *ima_ns, @@ -147,9 +151,6 @@ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, rwlock_init(&ns->iint_tree->lock); ns->iint_tree->root = RB_ROOT;
- ns->x509_path_for_children = NULL; - ns->policy_setup_for_children = NULL; - INIT_LIST_HEAD(&ns->ns_measurements); INIT_LIST_HEAD(&ns->policy_data->ima_default_rules); INIT_LIST_HEAD(&ns->policy_data->ima_policy_rules); @@ -217,14 +218,6 @@ static void imans_remove_hash_entries(struct ima_namespace *ima_ns) } }
-static void destroy_child_config(struct ima_namespace *ima_ns) -{ - kfree(ima_ns->x509_path_for_children); - ima_ns->x509_path_for_children = NULL; - kfree(ima_ns->policy_setup_for_children); - ima_ns->policy_setup_for_children = NULL; -} - static void destroy_ima_ns(struct ima_namespace *ns) { bool is_init_ns = (ns == &init_ima_ns); @@ -237,7 +230,6 @@ static void destroy_ima_ns(struct ima_namespace *ns) kfree(ns->iint_tree); ima_delete_ns_rules(ns->policy_data, is_init_ns); kfree(ns->policy_data); - destroy_child_config(ns); kfree(ns); }
@@ -327,31 +319,27 @@ static void imans_put(struct ns_common *ns)
static int imans_activate(struct ima_namespace *ima_ns) { - int res = 0; - if (ima_ns == &init_ima_ns) - return res; + return 0;
if (ima_ns->frozen) - return res; + return 0;
mutex_lock(&frozen_lock); if (ima_ns->frozen) goto out;
- ima_set_ns_policy(ima_ns); + ima_set_ns_policy(ima_ns, NULL);
ima_ns->frozen = true;
down_write(&ima_ns_list_lock); list_add_tail(&ima_ns->list, &ima_ns_list); up_write(&ima_ns_list_lock); - - destroy_child_config(ima_ns); out: mutex_unlock(&frozen_lock);
- return res; + return 0; }
static int imans_install(struct nsset *nsset, struct ns_common *new) @@ -436,97 +424,3 @@ const struct proc_ns_operations imans_for_children_operations = { .owner = imans_owner, };
-struct ima_kernel_param { - const char *name; - int (*set)(char *val, struct ima_namespace *ima_ns); -}; - -/* TODO: add ima_template, ima_template_fmt, ima_hash, ... */ -static const struct ima_kernel_param ima_kernel_params[] = { - {"ima_appraise", ima_default_appraise_setup}, - {"ima_policy", ima_policy_setup}, -}; -static const size_t ima_kernel_params_size = ARRAY_SIZE(ima_kernel_params); - -ssize_t ima_ns_write_x509_for_children(struct ima_namespace *ima_ns, - char *x509_path) -{ - ssize_t retval = 0; - - mutex_lock(&frozen_lock); - if (ima_ns->frozen) { - retval = -EACCES; - goto out; - } - - kfree(ima_ns->x509_path_for_children); - ima_ns->x509_path_for_children = x509_path; -out: - mutex_unlock(&frozen_lock); - - return retval; -} - -ssize_t ima_ns_write_kcmd_for_children(struct ima_namespace *ima_ns, - char *kcmd) -{ - u32 i; - char *param, *val; - ssize_t ret = 0; - - mutex_lock(&frozen_lock); - if (ima_ns->frozen) { - ret = -EACCES; - goto err_unlock; - } - - if (!ima_ns->policy_setup_for_children) { - ima_ns->policy_setup_for_children = - kmalloc(sizeof(struct ima_policy_setup_data), - GFP_KERNEL); - if (!ima_ns->policy_setup_for_children) { - ret = -ENOMEM; - goto err_unlock; - } - } - - memset(ima_ns->policy_setup_for_children, - 0, sizeof(struct ima_policy_setup_data)); - -#ifdef CONFIG_IMA_APPRAISE - ima_ns->policy_setup_for_children->ima_appraise = IMA_APPRAISE_ENFORCE; -#endif - - kcmd = skip_spaces(kcmd); - while (*kcmd) { - kcmd = next_arg(kcmd, ¶m, &val); - if (!val) { - ret = -EINVAL; - goto err_free; - } - - for (i = 0; i < ima_kernel_params_size; i++) { - if (strcmp(param, ima_kernel_params[i].name) == 0) - break; - } - - if (i == ima_kernel_params_size) { - ret = -EINVAL; - goto err_free; - } - - ima_kernel_params[i].set(val, ima_ns); - } - mutex_unlock(&frozen_lock); - - return ret; - -err_free: - kfree(ima_ns->policy_setup_for_children); - ima_ns->policy_setup_for_children = NULL; -err_unlock: - mutex_unlock(&frozen_lock); - - return ret; -} - diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 828793553a0e..0ab91cb31121 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -240,13 +240,9 @@ struct ima_policy_data init_policy_data = { .ima_rules = &init_policy_data.ima_default_rules, };
-int ima_default_measure_policy_setup(char *str, struct ima_namespace *ima_ns) +int ima_default_measure_policy_setup(const char *str, + struct ima_policy_setup_data *setup_data) { - struct ima_policy_setup_data *setup_data; - - setup_data = (ima_ns == &init_ima_ns) ? - &init_policy_setup_data : ima_ns->policy_setup_for_children; - if (setup_data->ima_policy) return 1;
@@ -256,7 +252,7 @@ int ima_default_measure_policy_setup(char *str, struct ima_namespace *ima_ns)
static int __init default_measure_policy_setup(char *str) { - return ima_default_measure_policy_setup(str, &init_ima_ns); + return ima_default_measure_policy_setup(str, &init_policy_setup_data); } __setup("ima_tcb", default_measure_policy_setup);
@@ -265,15 +261,15 @@ static bool ima_fail_unverifiable_sigs __ro_after_init; /** * ima_policy_setup - parse policy configuration string "ima_policy=" * @str: string to be parsed - * @ima_ns: pointer to the ima namespace which policy is being set + * @setup_data: pointer to a structure where parsed data is stored + * @fail_unverifiable_sigs: boolean flag treated separately to preserve + * __ro_after_init */ -int ima_policy_setup(char *str, struct ima_namespace *ima_ns) +int ima_policy_setup(char *str, + struct ima_policy_setup_data *setup_data, + bool *fail_unverifiable_sigs) { char *p; - struct ima_policy_setup_data *setup_data; - - setup_data = (ima_ns == &init_ima_ns) ? - &init_policy_setup_data : ima_ns->policy_setup_for_children;
while ((p = strsep(&str, " |\n")) != NULL) { if (*p == ' ') @@ -291,7 +287,7 @@ int ima_policy_setup(char *str, struct ima_namespace *ima_ns) else if (strcmp(p, "secure_boot") == 0) setup_data->ima_use_secure_boot = true; else if (strcmp(p, "fail_securely") == 0) - setup_data->fail_unverifiable_sigs = true; + *fail_unverifiable_sigs = true; else pr_err("policy "%s" not found", p); } @@ -301,27 +297,21 @@ int ima_policy_setup(char *str, struct ima_namespace *ima_ns)
static int __init policy_setup(char *str) { - ima_policy_setup(str, &init_ima_ns); - ima_fail_unverifiable_sigs = - init_policy_setup_data.fail_unverifiable_sigs; - return 1; + return ima_policy_setup(str, &init_policy_setup_data, + &ima_fail_unverifiable_sigs); } __setup("ima_policy=", policy_setup);
-int ima_default_appraise_policy_setup(char *str, struct ima_namespace *ima_ns) +int ima_default_appraise_policy_setup(const char *str, + struct ima_policy_setup_data *setup_data) { - struct ima_policy_setup_data *setup_data; - - setup_data = (ima_ns == &init_ima_ns) ? - &init_policy_setup_data : ima_ns->policy_setup_for_children; - setup_data->ima_use_appraise_tcb = true; return 1; }
static int __init default_appraise_policy_setup(char *str) { - return ima_default_appraise_policy_setup(str, &init_ima_ns); + return ima_default_appraise_policy_setup(str, &init_policy_setup_data); } __setup("ima_appraise_tcb", default_appraise_policy_setup);
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 2098d7b55941526b07dedc6b2ad7541b4073d0ff.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 6 ++--- kernel/nsproxy.c | 2 +- security/integrity/ima/ima_ns.c | 42 ++++++--------------------------- 3 files changed, 10 insertions(+), 40 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index 91c637c943ed..cfdd1280daff 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -246,8 +246,7 @@ struct ima_namespace *copy_ima_ns(unsigned long flags,
void free_ima_ns(struct kref *kref);
-int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk, - struct user_namespace *user_ns); +int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk);
static inline struct ima_namespace *get_ima_ns(struct ima_namespace *ns) { @@ -270,8 +269,7 @@ static inline struct ima_namespace *copy_ima_ns(unsigned long flags, }
static inline int imans_on_fork(struct nsproxy *nsproxy, - struct task_struct *tsk, - struct user_namespace *user_ns) + struct task_struct *tsk) { return 0; } diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index 277ae1fadafe..22b24123d524 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c @@ -204,7 +204,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk) return ret; }
- ret = imans_on_fork(new_ns, tsk, user_ns); + ret = imans_on_fork(new_ns, tsk); if (ret) { free_nsproxy(new_ns); return ret; diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index ac000920d486..26c9bcd5ff74 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -93,24 +93,6 @@ static void ima_set_ns_policy(struct ima_namespace *ima_ns, ima_init_ns_policy(ima_ns, &setup_data); }
-static int ima_swap_user_ns(struct ima_namespace *ima_ns, - struct user_namespace *user_ns) -{ - struct ucounts *ucounts; - - dec_ima_namespaces(ima_ns->ucounts); - put_user_ns(ima_ns->user_ns); - - ucounts = inc_ima_namespaces(user_ns); - if (!ucounts) - return -ENOSPC; - - ima_ns->user_ns = get_user_ns(user_ns); - ima_ns->ucounts = ucounts; - - return 0; -} - /** * Clone a new ns copying an original ima namespace, setting refcount to 1 * @@ -370,33 +352,23 @@ static int imans_install(struct nsset *nsset, struct ns_common *new) return res; }
-int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk, - struct user_namespace *user_ns) +int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk) { int res; - struct ima_namespace *ima_ns = nsproxy->ima_ns_for_children; + struct ns_common *nsc = &nsproxy->ima_ns_for_children->ns; + struct ima_namespace *ns = to_ima_ns(nsc);
/* create_new_namespaces() already incremented the ref counter */ - if (nsproxy->ima_ns == ima_ns) + if (nsproxy->ima_ns == nsproxy->ima_ns_for_children) return 0;
- /* It's possible that the user first unshares the IMA namespace and - * then creates a new user namespace on clone3(). In that case swap - * user namespace for the "current" one. - */ - if (ima_ns->user_ns != user_ns) { - res = ima_swap_user_ns(ima_ns, user_ns); - if (res) - return res; - } - - res = imans_activate(ima_ns); + res = imans_activate(ns); if (res) return res;
- get_ima_ns(ima_ns); + get_ima_ns(ns); put_ima_ns(nsproxy->ima_ns); - nsproxy->ima_ns = ima_ns; + nsproxy->ima_ns = ns;
return res; }
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 5622ee15fe4ce66427ae5e4fba87b9aa9673b5dc.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 1 - security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_api.c | 2 +- security/integrity/ima/ima_fs.c | 4 ++-- security/integrity/ima/ima_init.c | 1 - security/integrity/ima/ima_ns.c | 1 - security/integrity/ima/ima_queue.c | 1 + 7 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index cfdd1280daff..12738e37f714 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -234,7 +234,6 @@ struct ima_namespace { struct integrity_iint_tree *iint_tree; struct list_head ns_measurements; atomic_long_t ml_len; /* number of stored measurements in the list */ - atomic_long_t violations; } __randomize_layout;
extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index fce3fc065027..59d1afb3934d 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -191,6 +191,7 @@ extern spinlock_t ima_htable_lock;
struct ima_h_table { atomic_long_t len; /* number of stored measurements in the list */ + atomic_long_t violations; struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE]; }; extern struct ima_h_table ima_htable; diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 5921922d6930..6724ee072cd9 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -171,7 +171,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename, event_data.ns_id = get_ns_id(ima_ns);
/* can overflow, only indicator */ - atomic_long_inc(&ima_ns->violations); + atomic_long_inc(&ima_htable.violations);
result = ima_alloc_init_template(&event_data, &entry, NULL); if (result < 0) { diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index bda35e2bb45c..b5d45a67a261 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -61,7 +61,7 @@ static ssize_t ima_show_htable_value(struct file *filp, char __user *buf, struct ima_namespace *ima_ns = get_current_ns();
if (filp->f_path.dentry == violations) - val = &ima_ns->violations; + val = &ima_htable.violations; else if (filp->f_path.dentry == runtime_measurements_count) val = (ima_ns == &init_ima_ns) ? &ima_ml_len : &ima_ns->ml_len; #ifdef CONFIG_IMA_DIGEST_LIST @@ -650,7 +650,7 @@ int __init ima_fs_init(void) goto out;
violations = - securityfs_create_file("violations", S_IRUSR | S_IRGRP | S_IROTH, + securityfs_create_file("violations", S_IRUSR | S_IRGRP, ima_dir, NULL, &ima_htable_value_ops); if (IS_ERR(violations)) goto out; diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 923373a12f5c..99b9643e6763 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -37,7 +37,6 @@ struct ima_namespace init_ima_ns = { .iint_tree = &init_iint_tree, .ns_measurements = LIST_HEAD_INIT(init_ima_ns.ns_measurements), .ml_len = ATOMIC_LONG_INIT(0), - .violations = ATOMIC_LONG_INIT(0), }; EXPORT_SYMBOL(init_ima_ns);
diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 26c9bcd5ff74..2a4b7a23f9a7 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -128,7 +128,6 @@ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, ns->ucounts = ucounts; ns->frozen = false; atomic_long_set(&ns->ml_len, 0); - atomic_long_set(&ns->violations, 0);
rwlock_init(&ns->iint_tree->lock); ns->iint_tree->root = RB_ROOT; diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index e9a88910d726..89b9c3734890 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -38,6 +38,7 @@ DEFINE_SPINLOCK(ima_htable_lock); /* key: inode (before secure-hashing a file) */ struct ima_h_table ima_htable = { .len = ATOMIC_LONG_INIT(0), + .violations = ATOMIC_LONG_INIT(0), .queue[0 ... IMA_MEASURE_HTABLE_SIZE - 1] = HLIST_HEAD_INIT };
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 441a760d555e62b3fc96ba3c8c8ba4c0701a6e23.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- security/integrity/ima/ima.h | 4 ++-- security/integrity/ima/ima_fs.c | 32 +++++--------------------------- 2 files changed, 7 insertions(+), 29 deletions(-)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 59d1afb3934d..b1ab18d88803 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -512,9 +512,9 @@ static inline int ima_filter_rule_match(u32 secid, u32 field, u32 op, #endif /* CONFIG_IMA_LSM_RULES */
#ifdef CONFIG_IMA_READ_POLICY -#define POLICY_FILE_FLAGS (S_IWUSR | S_IRUSR | S_IROTH | S_IWOTH) +#define POLICY_FILE_FLAGS (S_IWUSR | S_IRUSR) #else -#define POLICY_FILE_FLAGS (S_IWUSR | S_IWOTH) +#define POLICY_FILE_FLAGS S_IWUSR #endif /* CONFIG_IMA_READ_POLICY */
#endif /* __LINUX_IMA_H */ diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index b5d45a67a261..8cba7e1693ce 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -73,18 +73,7 @@ static ssize_t ima_show_htable_value(struct file *filp, char __user *buf, return simple_read_from_buffer(buf, count, ppos, tmpbuf, len); }
-static int ima_open_htable_value(struct inode *inode, struct file *file) -{ - struct ima_namespace *ima_ns = get_current_ns(); - - if (!ns_capable(ima_ns->user_ns, CAP_SYS_ADMIN)) - return -EPERM; - - return 0; -} - static const struct file_operations ima_htable_value_ops = { - .open = ima_open_htable_value, .read = ima_show_htable_value, .llseek = generic_file_llseek, }; @@ -236,11 +225,6 @@ static const struct seq_operations ima_measurments_seqops = {
static int ima_measurements_open(struct inode *inode, struct file *file) { - struct ima_namespace *ima_ns = get_current_ns(); - - if (!ns_capable(ima_ns->user_ns, CAP_SYS_ADMIN)) - return -EPERM; - return seq_open(file, &ima_measurments_seqops); }
@@ -307,11 +291,6 @@ static const struct seq_operations ima_ascii_measurements_seqops = {
static int ima_ascii_measurements_open(struct inode *inode, struct file *file) { - struct ima_namespace *ima_ns = get_current_ns(); - - if (!ns_capable(ima_ns->user_ns, CAP_SYS_ADMIN)) - return -EPERM; - return seq_open(file, &ima_ascii_measurements_seqops); }
@@ -528,7 +507,6 @@ static int ima_open_data_upload(struct inode *inode, struct file *filp) const struct seq_operations *seq_ops = NULL; enum ima_fs_flags flag = ima_get_dentry_flag(dentry); bool read_allowed = false; - struct ima_namespace *ima_ns = get_current_ns();
if (dentry == ima_policy) { #ifdef CONFIG_IMA_READ_POLICY @@ -542,10 +520,10 @@ static int ima_open_data_upload(struct inode *inode, struct file *filp) return -EACCES; if ((filp->f_flags & O_ACCMODE) != O_RDONLY) return -EACCES; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; return seq_open(filp, seq_ops); } - if (!ns_capable(ima_ns->user_ns, CAP_SYS_ADMIN)) - return -EPERM; if (test_and_set_bit(flag, &ima_fs_flags)) return -EBUSY;
@@ -630,21 +608,21 @@ int __init ima_fs_init(void)
binary_runtime_measurements = securityfs_create_file("binary_runtime_measurements", - S_IRUSR | S_IRGRP | S_IROTH, ima_dir, NULL, + S_IRUSR | S_IRGRP, ima_dir, NULL, &ima_measurements_ops); if (IS_ERR(binary_runtime_measurements)) goto out;
ascii_runtime_measurements = securityfs_create_file("ascii_runtime_measurements", - S_IRUSR | S_IRGRP | S_IROTH, ima_dir, NULL, + S_IRUSR | S_IRGRP, ima_dir, NULL, &ima_ascii_measurements_ops); if (IS_ERR(ascii_runtime_measurements)) goto out;
runtime_measurements_count = securityfs_create_file("runtime_measurements_count", - S_IRUSR | S_IRGRP | S_IROTH, ima_dir, NULL, + S_IRUSR | S_IRGRP, ima_dir, NULL, &ima_htable_value_ops); if (IS_ERR(runtime_measurements_count)) goto out;
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit b80cb82f76da8cb7ef5da938edf7744b147a23a9.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- security/integrity/ima/ima_main.c | 75 +++++++++---------------------- security/integrity/integrity.h | 18 -------- 2 files changed, 21 insertions(+), 72 deletions(-)
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 5014eb586587..612c5e29cd85 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -30,11 +30,6 @@ #include "ima.h" #include "ima_digest_list.h"
-struct ima_file_data { - struct ima_namespace *ima_ns; - bool is_readcount; -}; - int ima_hash_algo = HASH_ALGO_SHA1;
/* Actions (measure/appraisal) for which digest lists can be used */ @@ -136,8 +131,8 @@ static void ima_rdwr_violation_check(struct file *file, iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); /* IMA_MEASURE is set from reader side */ - if (iint && atomic_read(&iint->readcount) && - test_bit(IMA_MUST_MEASURE, &iint->atomic_flags)) + if (iint && test_bit(IMA_MUST_MEASURE, + &iint->atomic_flags)) send_tomtou = true; } } else { @@ -245,7 +240,7 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, { fmode_t mode = file->f_mode; bool update; - struct ima_file_data *f_data = (struct ima_file_data *)file->f_ima; + struct ima_namespace *ima_ns = (struct ima_namespace *)file->f_ima;
if (!(mode & FMODE_WRITE)) return; @@ -260,7 +255,7 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE); iint->measured_pcrs = 0;
- ima_check_active_ns(f_data->ima_ns, inode); + ima_check_active_ns(ima_ns, inode);
if (update) ima_update_xattr(iint, file); @@ -281,8 +276,6 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, */ int ima_file_alloc(struct file *file) { - struct ima_file_data *f_data; - /* It is possible that ima_file_alloc() is called after * exit_task_namespaces(), when IMA does the last writer check from * __fput(). In that case it's not necessary to store the namespace @@ -290,16 +283,8 @@ int ima_file_alloc(struct file *file) if (!current->nsproxy) return 0;
- f_data = kmalloc(sizeof(struct ima_file_data), GFP_KERNEL); - if (!f_data) - return -ENOMEM; - - f_data->ima_ns = get_current_ns(); - f_data->is_readcount = false; - get_ima_ns(f_data->ima_ns); - - file->f_ima = f_data; - + file->f_ima = get_current_ns(); + get_ima_ns((struct ima_namespace *)file->f_ima); return 0; }
@@ -313,36 +298,30 @@ void ima_file_free(struct file *file) { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint; - struct ima_file_data *f_data = (struct ima_file_data *)file->f_ima; + struct ima_namespace *ima_ns = (struct ima_namespace *)file->f_ima;
- if (!f_data) + if (!ima_ns) return;
if (unlikely(!(file->f_mode & FMODE_OPENED))) goto out;
- if (!f_data->ima_ns->policy_data->ima_policy_flag || - !S_ISREG(inode->i_mode)) + if (!ima_ns->policy_data->ima_policy_flag || !S_ISREG(inode->i_mode)) goto out;
- iint = integrity_iint_rb_find(f_data->ima_ns->iint_tree, inode); + iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); if (!iint) goto out;
ima_check_last_writer(iint, inode, file); - - if (f_data->is_readcount) - iint_readcount_dec(iint); out: - put_ima_ns(f_data->ima_ns); - kfree(f_data); + put_ima_ns(ima_ns); }
static int process_ns_measurement(struct file *file, const struct cred *cred, u32 secid, char *buf, loff_t size, int mask, enum ima_hooks func, - struct ima_namespace *ima_ns, - bool readcount_open) + struct ima_namespace *ima_ns) { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint = NULL; @@ -363,12 +342,6 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, if (!ima_ns->policy_data->ima_policy_flag) return 0;
- if (ima_ns != current_ima_ns) { - iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); - if (!iint) - return 0; - } - /* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action * bitmask based on the appraise/audit/measurement policy. * Included is the appraise submask. @@ -389,18 +362,12 @@ static int process_ns_measurement(struct file *file, const struct cred *cred,
inode_lock(inode);
- if (action && !iint) { + if (action) { iint = integrity_inode_rb_get(ima_ns->iint_tree, inode); if (!iint) rc = -ENOMEM; }
- if ((ima_ns == current_ima_ns) && iint && readcount_open && - ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)) { - iint_readcount_inc(iint); - ((struct ima_file_data *)file->f_ima)->is_readcount = true; - } - if (!rc && violation_check) ima_rdwr_violation_check(file, iint, action & IMA_MEASURE, &pathbuf, &pathname, filename, ima_ns); @@ -554,7 +521,7 @@ static int process_ns_measurement(struct file *file, const struct cred *cred,
static int process_measurement(struct file *file, const struct cred *cred, u32 secid, char *buf, loff_t size, int mask, - enum ima_hooks func, bool readcount_open) + enum ima_hooks func) { int ret; struct ima_namespace *ima_ns; @@ -569,7 +536,7 @@ static int process_measurement(struct file *file, const struct cred *cred, continue;
ret = process_ns_measurement(file, cred, secid, buf, size, mask, - func, ima_ns, readcount_open); + func, ima_ns); if (ret != 0) break; } @@ -596,7 +563,7 @@ int ima_file_mmap(struct file *file, unsigned long prot) if (file && (prot & PROT_EXEC)) { security_task_getsecid(current, &secid); return process_measurement(file, current_cred(), secid, NULL, - 0, MAY_EXEC, MMAP_CHECK, true); + 0, MAY_EXEC, MMAP_CHECK); }
return 0; @@ -676,13 +643,13 @@ int ima_bprm_check(struct linux_binprm *bprm)
security_task_getsecid(current, &secid); ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0, - MAY_EXEC, BPRM_CHECK, false); + MAY_EXEC, BPRM_CHECK); if (ret) return ret;
security_cred_getsecid(bprm->cred, &secid); return process_measurement(bprm->file, bprm->cred, secid, NULL, 0, - MAY_EXEC, CREDS_CHECK, false); + MAY_EXEC, CREDS_CHECK); }
/** @@ -703,7 +670,7 @@ int ima_file_check(struct file *file, int mask) security_task_getsecid(current, &secid); rc = process_measurement(file, current_cred(), secid, NULL, 0, mask & (MAY_READ | MAY_WRITE | MAY_EXEC | - MAY_APPEND), FILE_CHECK, true); + MAY_APPEND), FILE_CHECK); if (ima_current_is_parser() && !rc) ima_check_measured_appraised(file); return rc; @@ -879,7 +846,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id, func = read_idmap[read_id] ?: FILE_CHECK; security_task_getsecid(current, &secid); return process_measurement(file, current_cred(), secid, NULL, - 0, MAY_READ, func, false); + 0, MAY_READ, func); }
const int read_idmap[READING_MAX_ID] = { @@ -924,7 +891,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, func = read_idmap[read_id] ?: FILE_CHECK; security_task_getsecid(current, &secid); return process_measurement(file, current_cred(), secid, buf, size, - MAY_READ, func, false); + MAY_READ, func); }
/** diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 78078d55fd33..05f6eabef9fe 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -18,7 +18,6 @@ #include <linux/key.h> #include <linux/audit.h> #include <linux/hash_info.h> -#include <linux/atomic.h>
/* iint action cache flags */ #define IMA_MEASURE 0x00000001 @@ -143,9 +142,6 @@ struct integrity_iint_cache { enum integrity_status ima_creds_status:4; enum integrity_status evm_status:4; struct ima_digest_data *ima_hash; - atomic_t readcount; /* Reader counter, incremented only in FILE_CHECK or - * MMAP_CHECK hooks, used for ima violation check. - */ };
enum compact_types { COMPACT_KEY, COMPACT_PARSER, COMPACT_FILE, @@ -342,17 +338,3 @@ static inline void __init add_to_platform_keyring(const char *source, { } #endif - -#ifdef CONFIG_IMA -static inline void iint_readcount_inc(struct integrity_iint_cache *iint) -{ - atomic_inc(&iint->readcount); -} -static inline void iint_readcount_dec(struct integrity_iint_cache *iint) -{ - if (WARN_ON(!atomic_read(&iint->readcount))) - return; - - atomic_dec(&iint->readcount); -} -#endif
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit ba729f30be8b74f3ca0d29971bf7f37f89768974.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 1 - security/integrity/ima/ima.h | 4 +-- security/integrity/ima/ima_fs.c | 52 ++++++++---------------------- security/integrity/ima/ima_init.c | 1 - security/integrity/ima/ima_ns.c | 1 - security/integrity/ima/ima_queue.c | 3 -- 6 files changed, 14 insertions(+), 48 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index 12738e37f714..0ab1dbf34c47 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -233,7 +233,6 @@ struct ima_namespace { struct ima_policy_data *policy_data; struct integrity_iint_tree *iint_tree; struct list_head ns_measurements; - atomic_long_t ml_len; /* number of stored measurements in the list */ } __randomize_layout;
extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index b1ab18d88803..a179f8f2cb8e 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -190,14 +190,12 @@ extern spinlock_t ima_queue_lock; extern spinlock_t ima_htable_lock;
struct ima_h_table { - atomic_long_t len; /* number of stored measurements in the list */ + atomic_long_t len; /* number of stored measurements in the list */ atomic_long_t violations; struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE]; }; extern struct ima_h_table ima_htable;
-extern atomic_long_t ima_ml_len; - static inline unsigned int ima_hash_key(u8 *digest) { /* there is no point in taking a hash of part of a digest */ diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 8cba7e1693ce..bf1d464620f7 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -58,12 +58,11 @@ static ssize_t ima_show_htable_value(struct file *filp, char __user *buf, atomic_long_t *val = NULL; char tmpbuf[32]; /* greater than largest 'long' string value */ ssize_t len; - struct ima_namespace *ima_ns = get_current_ns();
if (filp->f_path.dentry == violations) val = &ima_htable.violations; else if (filp->f_path.dentry == runtime_measurements_count) - val = (ima_ns == &init_ima_ns) ? &ima_ml_len : &ima_ns->ml_len; + val = &ima_htable.len; #ifdef CONFIG_IMA_DIGEST_LIST else if (filp->f_path.dentry == digests_count) val = &ima_digests_htable.len; @@ -83,57 +82,32 @@ static void *ima_measurements_start(struct seq_file *m, loff_t *pos) { loff_t l = *pos; struct ima_queue_entry *qe; - struct ima_namespace *ima_ns = get_current_ns();
- if (ima_ns == &init_ima_ns) { - /* we need a lock since pos could point beyond last element */ - rcu_read_lock(); - list_for_each_entry_rcu(qe, &ima_measurements, later) { - if (!l--) { - rcu_read_unlock(); - return qe; - } - } - rcu_read_unlock(); - } else { - rcu_read_lock(); - list_for_each_entry_rcu(qe, &ima_ns->ns_measurements, ns_later) { - if (!l--) { - rcu_read_unlock(); - return qe; - } + /* we need a lock since pos could point beyond last element */ + rcu_read_lock(); + list_for_each_entry_rcu(qe, &ima_measurements, later) { + if (!l--) { + rcu_read_unlock(); + return qe; } - rcu_read_unlock(); } - + rcu_read_unlock(); return NULL; }
static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos) { struct ima_queue_entry *qe = v; - struct ima_namespace *ima_ns = get_current_ns();
/* lock protects when reading beyond last element * against concurrent list-extension */ - if (ima_ns == &init_ima_ns) { - rcu_read_lock(); - qe = list_entry_rcu(qe->later.next, struct ima_queue_entry, - later); - rcu_read_unlock(); - (*pos)++; - - return (&qe->later == &ima_measurements) ? NULL : qe; - } else { - rcu_read_lock(); - qe = list_entry_rcu(qe->ns_later.next, struct ima_queue_entry, - ns_later); - rcu_read_unlock(); - (*pos)++; + rcu_read_lock(); + qe = list_entry_rcu(qe->later.next, struct ima_queue_entry, later); + rcu_read_unlock(); + (*pos)++;
- return (&qe->ns_later == &ima_ns->ns_measurements) ? NULL : qe; - } + return (&qe->later == &ima_measurements) ? NULL : qe; }
static void ima_measurements_stop(struct seq_file *m, void *v) diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 99b9643e6763..00c8dfea6ba8 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -36,7 +36,6 @@ struct ima_namespace init_ima_ns = { .policy_data = &init_policy_data, .iint_tree = &init_iint_tree, .ns_measurements = LIST_HEAD_INIT(init_ima_ns.ns_measurements), - .ml_len = ATOMIC_LONG_INIT(0), }; EXPORT_SYMBOL(init_ima_ns);
diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 2a4b7a23f9a7..885f12043cb3 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -127,7 +127,6 @@ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, ns->user_ns = get_user_ns(user_ns); ns->ucounts = ucounts; ns->frozen = false; - atomic_long_set(&ns->ml_len, 0);
rwlock_init(&ns->iint_tree->lock); ns->iint_tree->root = RB_ROOT; diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 89b9c3734890..3aeff7b5e036 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -25,7 +25,6 @@ /* pre-allocated array of tpm_digest structures to extend a PCR */ static struct tpm_digest *digests;
-atomic_long_t ima_ml_len = ATOMIC_LONG_INIT(0); /* number of stored measurements in the list */ LIST_HEAD(ima_measurements); /* list of all measurements */ #ifdef CONFIG_IMA_KEXEC static unsigned long binary_runtime_size; @@ -114,8 +113,6 @@ static int ima_add_digest_entry(struct ima_template_entry *entry, list_add_tail_rcu(&qe->ns_later, &ima_ns->ns_measurements);
atomic_long_inc(&ima_htable.len); - atomic_long_inc(&ima_ml_len); - atomic_long_inc(&ima_ns->ml_len); if (update_htable) { key = ima_hash_key(entry->digests[ima_hash_algo_idx].digest); spin_lock(&ima_htable_lock);
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 782baa66083321a9f4867a6aacbea61ab86492cd.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- security/integrity/ima/ima_template.c | 5 +---- security/integrity/ima/ima_template_lib.c | 13 ------------- security/integrity/ima/ima_template_lib.h | 2 -- 3 files changed, 1 insertion(+), 19 deletions(-)
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index 3d6f6e9d530c..db4d3893d32d 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c @@ -22,7 +22,6 @@ static struct ima_template_desc builtin_templates[] = { {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"}, {.name = "ima-buf", .fmt = "d-ng|n-ng|buf"}, {.name = "ima-modsig", .fmt = "d-ng|n-ng|sig|d-modsig|modsig"}, - {.name = "ima-ns", .fmt = "d-ng|n-ng|ns"}, {.name = "", .fmt = ""}, /* placeholder for a custom format */ };
@@ -48,8 +47,6 @@ static const struct ima_template_field supported_fields[] = { .field_show = ima_show_template_sig}, {.field_id = "evmsig", .field_init = ima_eventevmsig_init, .field_show = ima_show_template_sig}, - {.field_id = "ns", .field_init = ima_eventns_init, - .field_show = ima_show_template_buf}, };
/* @@ -57,7 +54,7 @@ static const struct ima_template_field supported_fields[] = { * need to be accounted for since they shouldn't be defined in the same template * description as 'd-ng' and 'n-ng' respectively. */ -#define MAX_TEMPLATE_NAME_LEN sizeof("d-ng|n-ng|sig|buf|d-modisg|modsig|ns") +#define MAX_TEMPLATE_NAME_LEN sizeof("d-ng|n-ng|sig|buf|d-modisg|modsig")
static struct ima_template_desc *ima_template;
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c index ca6153680cf0..90040fac150b 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c @@ -514,16 +514,3 @@ int ima_eventevmsig_init(struct ima_event_data *event_data, kfree(xattr_data); return rc; } - -/* - * ima_eventns_init - include the ima namespace id as part of the - * template data - */ -int ima_eventns_init(struct ima_event_data *event_data, - struct ima_field_data *field_data) -{ - return ima_write_template_field_data(&(event_data->ns_id), - sizeof(event_data->ns_id), - DATA_FMT_HEX, - field_data); -} diff --git a/security/integrity/ima/ima_template_lib.h b/security/integrity/ima/ima_template_lib.h index b34054858f05..f4b2a2056d1d 100644 --- a/security/integrity/ima/ima_template_lib.h +++ b/security/integrity/ima/ima_template_lib.h @@ -48,6 +48,4 @@ int ima_eventmodsig_init(struct ima_event_data *event_data, struct ima_field_data *field_data); int ima_eventevmsig_init(struct ima_event_data *event_data, struct ima_field_data *field_data); -int ima_eventns_init(struct ima_event_data *event_data, - struct ima_field_data *field_data); #endif /* __LINUX_IMA_TEMPLATE_LIB_H */
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit bd86d4c77193befb330c656c5703575976f89512.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- security/integrity/ima/ima.h | 1 - security/integrity/ima/ima_ns.c | 19 ------------------- security/integrity/ima/ima_queue.c | 12 +++--------- 3 files changed, 3 insertions(+), 29 deletions(-)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index a179f8f2cb8e..f515a4405641 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -187,7 +187,6 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event, * used to protect h_table and sha_table */ extern spinlock_t ima_queue_lock; -extern spinlock_t ima_htable_lock;
struct ima_h_table { atomic_long_t len; /* number of stored measurements in the list */ diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 885f12043cb3..a6197c708f3a 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -26,7 +26,6 @@ #include <linux/rwsem.h> #include <linux/workqueue.h> #include <linux/mutex.h> -#include <linux/spinlock.h>
#include "ima.h"
@@ -181,28 +180,10 @@ int __init ima_init_namespace(void) return 0; }
-static void imans_remove_hash_entries(struct ima_namespace *ima_ns) -{ - struct list_head *ele; - struct ima_queue_entry *qe; - - /* The namespace is inactive, no lock is needed */ - list_for_each(ele, &ima_ns->ns_measurements) { - qe = list_entry(ele, struct ima_queue_entry, ns_later); - /* Don't free the queue entry, it should stay on the global - * measurement list, remove only the hash table entry */ - spin_lock(&ima_htable_lock); - hlist_del_rcu(&qe->hnext); - spin_unlock(&ima_htable_lock); - atomic_long_dec(&ima_htable.len); - } -} - static void destroy_ima_ns(struct ima_namespace *ns) { bool is_init_ns = (ns == &init_ima_ns);
- imans_remove_hash_entries(ns); dec_ima_namespaces(ns->ucounts); put_user_ns(ns->user_ns); ns_free_inum(&ns->ns); diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 3aeff7b5e036..673fd95c8d33 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -17,7 +17,6 @@
#include <linux/rculist.h> #include <linux/slab.h> -#include <linux/spinlock.h> #include "ima.h"
#define AUDIT_CAUSE_LEN_MAX 32 @@ -32,8 +31,6 @@ static unsigned long binary_runtime_size; static unsigned long binary_runtime_size = ULONG_MAX; #endif
-DEFINE_SPINLOCK(ima_htable_lock); - /* key: inode (before secure-hashing a file) */ struct ima_h_table ima_htable = { .len = ATOMIC_LONG_INIT(0), @@ -49,7 +46,7 @@ static DEFINE_MUTEX(ima_extend_list_mutex);
/* lookup up the digest value in the hash table, and return the entry */ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value, - int pcr, int ns_id) + int pcr) { struct ima_queue_entry *qe, *ret = NULL; unsigned int key; @@ -60,8 +57,7 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value, hlist_for_each_entry_rcu(qe, &ima_htable.queue[key], hnext) { rc = memcmp(qe->entry->digests[ima_hash_algo_idx].digest, digest_value, hash_digest_size[ima_hash_algo]); - if ((rc == 0) && (qe->entry->pcr == pcr) && - (qe->entry->ns_id == ns_id)) { + if ((rc == 0) && (qe->entry->pcr == pcr)) { ret = qe; break; } @@ -115,9 +111,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry, atomic_long_inc(&ima_htable.len); if (update_htable) { key = ima_hash_key(entry->digests[ima_hash_algo_idx].digest); - spin_lock(&ima_htable_lock); hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]); - spin_unlock(&ima_htable_lock); }
if (binary_runtime_size != ULONG_MAX) { @@ -178,7 +172,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
mutex_lock(&ima_extend_list_mutex); if (!violation) { - if (ima_lookup_digest_entry(digest, entry->pcr, entry->ns_id)) { + if (ima_lookup_digest_entry(digest, entry->pcr)) { audit_cause = "hash_exists"; result = -EEXIST; goto out;
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit a1f9c162b7fa1a183921a3b4286c74a3c01fc307.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 1 - security/integrity/ima/ima.h | 7 ++----- security/integrity/ima/ima_api.c | 12 +++++------- security/integrity/ima/ima_init.c | 4 +--- security/integrity/ima/ima_main.c | 3 +-- security/integrity/ima/ima_ns.c | 1 - security/integrity/ima/ima_queue.c | 11 ++++------- 7 files changed, 13 insertions(+), 26 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index 0ab1dbf34c47..d7b2864d7d7c 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -232,7 +232,6 @@ struct ima_namespace { bool frozen; struct ima_policy_data *policy_data; struct integrity_iint_tree *iint_tree; - struct list_head ns_measurements; } __randomize_layout;
extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index f515a4405641..9086c261f0d7 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -119,7 +119,6 @@ struct ima_template_entry { struct ima_queue_entry { struct hlist_node hnext; /* place in hash collision list */ struct list_head later; /* place in ima_measurements list */ - struct list_head ns_later; /* place in ima namespace list */ struct ima_template_entry *entry; }; extern struct list_head ima_measurements; /* list of all measurements */ @@ -152,8 +151,7 @@ int ima_init(void); int ima_fs_init(void); int ima_add_template_entry(struct ima_template_entry *entry, int violation, const char *op, struct inode *inode, - const unsigned char *filename, - struct ima_namespace *ima_ns); + const unsigned char *filename); int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash); int ima_calc_buffer_hash(const void *buf, loff_t len, struct ima_digest_data *hash); @@ -295,8 +293,7 @@ int ima_alloc_init_template(struct ima_event_data *event_data, struct ima_template_desc *template_desc); int ima_store_template(struct ima_template_entry *entry, int violation, struct inode *inode, const unsigned char *filename, - int pcr, struct ima_digest *digest, - struct ima_namespace *ima_ns); + int pcr, struct ima_digest *digest); void ima_free_template_entry(struct ima_template_entry *entry); const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 6724ee072cd9..2678faaa7a15 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -104,8 +104,7 @@ int ima_alloc_init_template(struct ima_event_data *event_data, int ima_store_template(struct ima_template_entry *entry, int violation, struct inode *inode, const unsigned char *filename, int pcr, - struct ima_digest *digest, - struct ima_namespace *ima_ns) + struct ima_digest *digest) { static const char op[] = "add_template_measure"; static const char audit_cause[] = "hashing_error"; @@ -135,11 +134,10 @@ int ima_store_template(struct ima_template_entry *entry, }
entry->pcr = pcr; - result = ima_add_template_entry(entry, violation, op, inode, filename, - ima_ns); + result = ima_add_template_entry(entry, violation, op, inode, filename); if (!result && duplicated_entry) { result = ima_add_template_entry(duplicated_entry, violation, op, - inode, filename, ima_ns); + inode, filename); if (result < 0) kfree(duplicated_entry); } @@ -179,7 +177,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename, goto err_out; } result = ima_store_template(entry, violation, inode, filename, - CONFIG_IMA_MEASURE_PCR_IDX, NULL, ima_ns); + CONFIG_IMA_MEASURE_PCR_IDX, NULL); if (result < 0) ima_free_template_entry(entry); err_out: @@ -366,7 +364,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, }
result = ima_store_template(entry, violation, inode, filename, pcr, - digest, ima_ns); + digest); out: if ((!result || result == -EEXIST) && !(file->f_flags & O_DIRECT)) { iint->flags |= IMA_MEASURED; diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 00c8dfea6ba8..52b675d47177 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -35,7 +35,6 @@ struct ima_namespace init_ima_ns = { .frozen = true, .policy_data = &init_policy_data, .iint_tree = &init_iint_tree, - .ns_measurements = LIST_HEAD_INIT(init_ima_ns.ns_measurements), }; EXPORT_SYMBOL(init_ima_ns);
@@ -105,8 +104,7 @@ static int __init ima_add_boot_aggregate(void)
result = ima_store_template(entry, violation, NULL, boot_aggregate_name, - CONFIG_IMA_MEASURE_PCR_IDX, NULL, - &init_ima_ns); + CONFIG_IMA_MEASURE_PCR_IDX, NULL); if (result < 0) { ima_free_template_entry(entry); audit_cause = "store_entry"; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 612c5e29cd85..9da27ab3b360 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -1078,8 +1078,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, goto out; }
- ret = ima_store_template(entry, violation, NULL, buf, pcr, NULL, - ima_ns); + ret = ima_store_template(entry, violation, NULL, buf, pcr, NULL); if (ret < 0) { audit_cause = "store_entry"; ima_free_template_entry(entry); diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index a6197c708f3a..04aa50473971 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -130,7 +130,6 @@ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, rwlock_init(&ns->iint_tree->lock); ns->iint_tree->root = RB_ROOT;
- INIT_LIST_HEAD(&ns->ns_measurements); INIT_LIST_HEAD(&ns->policy_data->ima_default_rules); INIT_LIST_HEAD(&ns->policy_data->ima_policy_rules); INIT_LIST_HEAD(&ns->policy_data->ima_temp_rules); diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 673fd95c8d33..c096ef8945c7 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -91,8 +91,7 @@ static int get_binary_runtime_size(struct ima_template_entry *entry) * (Called with ima_extend_list_mutex held.) */ static int ima_add_digest_entry(struct ima_template_entry *entry, - bool update_htable, - struct ima_namespace *ima_ns) + bool update_htable) { struct ima_queue_entry *qe; unsigned int key; @@ -106,7 +105,6 @@ static int ima_add_digest_entry(struct ima_template_entry *entry,
INIT_LIST_HEAD(&qe->later); list_add_tail_rcu(&qe->later, &ima_measurements); - list_add_tail_rcu(&qe->ns_later, &ima_ns->ns_measurements);
atomic_long_inc(&ima_htable.len); if (update_htable) { @@ -160,8 +158,7 @@ static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr) */ int ima_add_template_entry(struct ima_template_entry *entry, int violation, const char *op, struct inode *inode, - const unsigned char *filename, - struct ima_namespace *ima_ns) + const unsigned char *filename) { u8 *digest = entry->digests[ima_hash_algo_idx].digest; struct tpm_digest *digests_arg = entry->digests; @@ -179,7 +176,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, } }
- result = ima_add_digest_entry(entry, 1, ima_ns); + result = ima_add_digest_entry(entry, 1); if (result < 0) { audit_cause = "ENOMEM"; audit_info = 0; @@ -208,7 +205,7 @@ int ima_restore_measurement_entry(struct ima_template_entry *entry) int result = 0;
mutex_lock(&ima_extend_list_mutex); - result = ima_add_digest_entry(entry, 0, &init_ima_ns); + result = ima_add_digest_entry(entry, 0); mutex_unlock(&ima_extend_list_mutex); return result; }
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 78e014108eae568a91f818e3c7c2814cdd0590f0.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- security/integrity/ima/ima.h | 10 +--------- security/integrity/ima/ima_api.c | 8 +------- security/integrity/ima/ima_init.c | 2 -- security/integrity/ima/ima_main.c | 5 ++--- security/integrity/ima/ima_template.c | 2 -- 5 files changed, 4 insertions(+), 23 deletions(-)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 9086c261f0d7..1fae3709266f 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -80,7 +80,6 @@ struct ima_event_data { const char *violation; const void *buf; int buf_len; - unsigned int ns_id; };
/* IMA template field data definition */ @@ -109,7 +108,6 @@ struct ima_template_desc {
struct ima_template_entry { int pcr; - unsigned int ns_id; struct tpm_digest *digests; struct ima_template_desc *template_desc; /* template descriptor */ u32 template_data_len; @@ -160,8 +158,7 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, int ima_calc_boot_aggregate(struct ima_digest_data *hash); void ima_add_violation(struct file *file, const unsigned char *filename, struct integrity_iint_cache *iint, - const char *op, const char *cause, - struct ima_namespace *ima_ns); + const char *op, const char *cause); int ima_init_crypto(void); void ima_putc(struct seq_file *m, void *data, int datalen); void ima_print_digest(struct seq_file *m, u8 *digest, u32 size); @@ -412,11 +409,6 @@ extern struct ima_policy_setup_data init_policy_setup_data; extern struct list_head ima_ns_list; extern struct rw_semaphore ima_ns_list_lock;
-static inline unsigned int get_ns_id(const struct ima_namespace *ima_ns) -{ - return ima_ns->ns.inum; -} - #ifdef CONFIG_IMA_NS int __init ima_init_namespace(void);
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 2678faaa7a15..743b9337d9e5 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -76,8 +76,6 @@ int ima_alloc_init_template(struct ima_event_data *event_data, (*entry)->template_data_len += sizeof(len); (*entry)->template_data_len += len; } - - (*entry)->ns_id = event_data->ns_id; return 0; out: ima_free_template_entry(*entry); @@ -154,8 +152,7 @@ int ima_store_template(struct ima_template_entry *entry, */ void ima_add_violation(struct file *file, const unsigned char *filename, struct integrity_iint_cache *iint, - const char *op, const char *cause, - struct ima_namespace *ima_ns) + const char *op, const char *cause) { struct ima_template_entry *entry; struct inode *inode = file_inode(file); @@ -166,8 +163,6 @@ void ima_add_violation(struct file *file, const unsigned char *filename, int violation = 1; int result;
- event_data.ns_id = get_ns_id(ima_ns); - /* can overflow, only indicator */ atomic_long_inc(&ima_htable.violations);
@@ -341,7 +336,6 @@ void ima_store_measurement(struct integrity_iint_cache *iint, .modsig = modsig }; int violation = 0;
- event_data.ns_id = get_ns_id(ima_ns); /* * We still need to store the measurement in the case of MODSIG because * we only have its contents to put in the list at the time of diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 52b675d47177..dea0251142fd 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -68,8 +68,6 @@ static int __init ima_add_boot_aggregate(void) char digest[TPM_MAX_DIGEST_SIZE]; } hash;
- event_data.ns_id = get_ns_id(&init_ima_ns); - memset(iint, 0, sizeof(*iint)); memset(&hash, 0, sizeof(hash)); iint->ima_hash = &hash.hdr; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 9da27ab3b360..7986dfb3e5d6 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -149,10 +149,10 @@ static void ima_rdwr_violation_check(struct file *file,
if (send_tomtou) ima_add_violation(file, *pathname, iint, - "invalid_pcr", "ToMToU", ima_ns); + "invalid_pcr", "ToMToU"); if (send_writers) ima_add_violation(file, *pathname, iint, - "invalid_pcr", "open_writers", ima_ns); + "invalid_pcr", "open_writers"); }
static enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, @@ -1071,7 +1071,6 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, goto out; }
- event_data.ns_id = get_ns_id(ima_ns); ret = ima_alloc_init_template(&event_data, &entry, template); if (ret < 0) { audit_cause = "alloc_entry"; diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index db4d3893d32d..0d4c698d2707 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c @@ -373,7 +373,6 @@ int ima_restore_measurement_list(loff_t size, void *buf) struct ima_template_desc *template_desc; DECLARE_BITMAP(hdr_mask, HDR__LAST); unsigned long count = 0; - unsigned int init_ns_id = get_ns_id(&init_ima_ns); int ret = 0;
if (!buf || size < sizeof(*khdr)) @@ -473,7 +472,6 @@ int ima_restore_measurement_list(loff_t size, void *buf)
entry->pcr = !ima_canonical_fmt ? *(u32 *)(hdr[HDR_PCR].data) : le32_to_cpu(*(u32 *)(hdr[HDR_PCR].data)); - entry->ns_id = init_ns_id; ret = ima_restore_measurement_entry(entry); if (ret < 0) break;
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 27229fcf200a646b1a795e9c0ac655a3f1bfda42.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 11 - kernel/kexec_file.c | 7 - security/integrity/ima/ima.h | 12 +- security/integrity/ima/ima_api.c | 2 +- security/integrity/ima/ima_appraise.c | 95 ++--- security/integrity/ima/ima_asymmetric_keys.c | 13 +- security/integrity/ima/ima_digest_list.c | 4 +- security/integrity/ima/ima_fs.c | 6 +- security/integrity/ima/ima_init.c | 7 +- security/integrity/ima/ima_main.c | 240 ++++--------- security/integrity/ima/ima_ns.c | 3 - security/integrity/ima/ima_policy.c | 345 ++++++++----------- security/integrity/ima/ima_queue_keys.c | 10 +- security/security.c | 2 +- 14 files changed, 250 insertions(+), 507 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index d7b2864d7d7c..f5683756f2b5 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -37,8 +37,6 @@ extern int ima_post_read_file(struct file *file, void *buf, loff_t size, extern void ima_post_path_mknod(struct dentry *dentry); extern int ima_file_hash(struct file *file, char *buf, size_t buf_size); extern void ima_kexec_cmdline(int kernel_fd, const void *buf, int size); -extern void ima_inode_free(struct inode *inode); -extern bool ima_is_root_namespace(void);
#ifdef CONFIG_IMA_KEXEC extern void ima_add_kexec_buffer(struct kimage *image); @@ -130,15 +128,6 @@ static inline int ima_file_hash(struct file *file, char *buf, size_t buf_size) }
static inline void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) {} - -static inline void ima_inode_free(struct inode *inode) -{ -} - -static inline bool ima_is_root_namespace(void) -{ - return true; -} #endif /* CONFIG_IMA */
#ifndef CONFIG_IMA_KEXEC diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index d407f7983020..33400ff051a8 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -362,13 +362,6 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, if (!capable(CAP_SYS_BOOT) || kexec_load_disabled) return -EPERM;
- /* Allow only from the initial IMA namespace, so that the user can't - * spawn a new IMA namespace with the empty policy and circumvent the - * appraisal protection. - */ - if (!ima_is_root_namespace()) - return -EPERM; - /* Make sure we have a legal set of flags */ if (flags != (flags & KEXEC_FILE_FLAGS)) return -EINVAL; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 1fae3709266f..8b59e03ec849 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -44,11 +44,15 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };
#define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0)
+/* current content of the policy */ +extern int ima_policy_flag; + /* set during initialization */ extern int ima_hash_algo; extern int ima_sha1_idx __ro_after_init; extern int ima_hash_algo_idx __ro_after_init; extern int ima_extra_slots __ro_after_init; +extern int ima_appraise; extern struct tpm_chip *ima_tpm_chip; extern int ima_digest_list_pcr; extern bool ima_plus_standard_pcr; @@ -65,8 +69,6 @@ struct ima_policy_setup_data { int ima_appraise; bool ima_use_secure_boot; bool ima_use_appraise_tcb; - bool ima_use_appraise_exec_tcb; - bool ima_use_appraise_exec_immutable; };
/* IMA event related data */ @@ -400,9 +402,6 @@ struct ima_policy_data { int temp_ima_appraise; };
-extern struct list_head ima_ns_list; -extern struct rw_semaphore ima_ns_list_lock; - extern struct ima_policy_data init_policy_data; extern struct ima_policy_setup_data init_policy_setup_data;
@@ -416,9 +415,6 @@ static inline struct ima_namespace *get_current_ns(void) { return current->nsproxy->ima_ns; } - -void ima_delete_ns_rules(struct ima_policy_data *policy_data, - bool is_root_ns); #else static inline int __init ima_init_namespace(void) { diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 743b9337d9e5..b4347eac9c85 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -212,7 +212,7 @@ int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, { int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
- flags &= ima_ns->policy_data->ima_policy_flag; + flags &= ima_policy_flag;
return ima_match_policy(inode, cred, secid, func, mask, flags, pcr, template_desc, keyring, ima_ns); diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 9d041e3deef2..9213c012cbe4 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -21,10 +21,18 @@ static bool ima_appraise_req_evm __ro_after_init;
int ima_default_appraise_setup(const char *str, struct ima_policy_setup_data *setup_data) +{ + /* Currently unused. It will be implemented after namespacing ima + * policy, when global variables are removed. + */ + return 1; +} + +static int __init default_appraise_setup(char *str) { #ifdef CONFIG_IMA_APPRAISE_BOOTPARAM bool sb_state = arch_ima_get_secureboot(); - int appraisal_state = setup_data->ima_appraise; + int appraisal_state = ima_appraise;
if (strncmp(str, "off", 3) == 0) appraisal_state = 0; @@ -44,7 +52,7 @@ int ima_default_appraise_setup(const char *str, pr_info("Secure boot enabled: ignoring ima_appraise=%s option", str); } else { - setup_data->ima_appraise = appraisal_state; + ima_appraise = appraisal_state; } #endif if (strcmp(str, "enforce-evm") == 0 || @@ -53,11 +61,6 @@ int ima_default_appraise_setup(const char *str, return 1; }
-static int __init default_appraise_setup(char *str) -{ - return ima_default_appraise_setup(str, &init_policy_setup_data); -} - __setup("ima_appraise=", default_appraise_setup);
static bool ima_appraise_no_metadata __ro_after_init; @@ -84,10 +87,7 @@ __setup("ima_appraise_digest_list=", appraise_digest_list_setup); */ bool is_ima_appraise_enabled(const struct ima_namespace *ima_ns) { - if (!ima_ns) - return false; - - return ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE; + return ima_appraise & IMA_APPRAISE_ENFORCE; }
/* @@ -95,18 +95,18 @@ bool is_ima_appraise_enabled(const struct ima_namespace *ima_ns) * * Return 1 to appraise or hash */ -int ima_must_appraise(struct inode *inode, int mask, - enum ima_hooks func, struct ima_namespace *ima_ns) +int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func, + struct ima_namespace *ima_ns) { u32 secid;
- if (!ima_ns->policy_data->ima_appraise) + if (!ima_appraise) return 0;
security_task_getsecid(current, &secid); return ima_match_policy(inode, current_cred(), secid, func, mask, IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL, - ima_ns); + NULL); }
static int ima_fix_xattr(struct dentry *dentry, @@ -352,7 +352,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint, if ((rc == -EPERM) && (iint->flags & IMA_MEASURE)) process_buffer_measurement(NULL, digest, digestsize, "blacklisted-hash", NONE, - pcr, NULL, ima_ns); + pcr, NULL, NULL); }
return rc; @@ -381,7 +381,6 @@ int ima_appraise_measurement(enum ima_hooks func, int rc = xattr_len, rc_evm; char _buf[sizeof(struct evm_ima_xattr_data) + 1 + SHA512_DIGEST_SIZE]; bool try_modsig = iint->flags & IMA_MODSIG_ALLOWED && modsig; - struct ima_namespace *ima_ns = get_current_ns();
/* If not appraising a modsig, we need an xattr. */ if (!(inode->i_opflags & IOP_XATTR) && !try_modsig) @@ -510,8 +509,7 @@ int ima_appraise_measurement(enum ima_hooks func, op, cause, rc, 0); } else if (status != INTEGRITY_PASS) { /* Fix mode, but don't replace file signatures. */ - if ((ima_ns->policy_data->ima_appraise & IMA_APPRAISE_FIX) && - !try_modsig && + if ((ima_appraise & IMA_APPRAISE_FIX) && !try_modsig && (!xattr_value || xattr_value->type != EVM_IMA_XATTR_DIGSIG)) { if (!ima_fix_xattr(dentry, iint)) @@ -576,30 +574,18 @@ void ima_inode_post_setattr(struct dentry *dentry) struct inode *inode = d_backing_inode(dentry); struct integrity_iint_cache *iint; int action; - struct ima_namespace *ima_ns;
- if (!S_ISREG(inode->i_mode) || - !(inode->i_opflags & IOP_XATTR)) + if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) + || !(inode->i_opflags & IOP_XATTR)) return;
- down_read(&ima_ns_list_lock); - list_for_each_entry(ima_ns, &ima_ns_list, list) { - if (atomic_read(&ima_ns->inactive)) - continue; - if (!(ima_ns->policy_data->ima_policy_flag & IMA_APPRAISE)) - continue; - - action = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR, - ima_ns); - iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); - if (iint) { - set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags); - if (!action) - clear_bit(IMA_UPDATE_XATTR, - &iint->atomic_flags); - } + action = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR, NULL); + iint = integrity_iint_find(inode); + if (iint) { + set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags); + if (!action) + clear_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); } - up_read(&ima_ns_list_lock); }
/* @@ -621,30 +607,19 @@ static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name, static void ima_reset_appraise_flags(struct inode *inode, int digsig) { struct integrity_iint_cache *iint; - struct ima_namespace *ima_ns;
- if (!S_ISREG(inode->i_mode)) + if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)) return;
- down_read(&ima_ns_list_lock); - list_for_each_entry(ima_ns, &ima_ns_list, list) { - if (atomic_read(&ima_ns->inactive)) - continue; - if (!(ima_ns->policy_data->ima_policy_flag & IMA_APPRAISE)) - continue; - - iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); - if (!iint) - continue; - - iint->measured_pcrs = 0; - set_bit(IMA_CHANGE_XATTR, &iint->atomic_flags); - if (digsig) - set_bit(IMA_DIGSIG, &iint->atomic_flags); - else - clear_bit(IMA_DIGSIG, &iint->atomic_flags); - } - up_read(&ima_ns_list_lock); + iint = integrity_iint_find(inode); + if (!iint) + return; + iint->measured_pcrs = 0; + set_bit(IMA_CHANGE_XATTR, &iint->atomic_flags); + if (digsig) + set_bit(IMA_DIGSIG, &iint->atomic_flags); + else + clear_bit(IMA_DIGSIG, &iint->atomic_flags); }
int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c index b3330a0a1481..58aa56b0422d 100644 --- a/security/integrity/ima/ima_asymmetric_keys.c +++ b/security/integrity/ima/ima_asymmetric_keys.c @@ -29,16 +29,6 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key, unsigned long flags, bool create) { bool queued = false; - /* Measure the keys according to the current ima namespace's policy - * rules. If the new ima namespace with empty policy is created to hide - * the log, parent can join it to inspect the log until the child - * namespace exists. After its destruction, log can be accessed only - * by the processes from the initial ima namespace that see all - * measurement list entries. If this is a problem, maybe the solution - * is to track in which namespaces the key was measured and re-measure - * it when necessary. - */ - struct ima_namespace *ima_ns = get_current_ns();
/* Only asymmetric keys are handled by this hook. */ if (key->type != &key_type_asymmetric) @@ -70,5 +60,6 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key, */ process_buffer_measurement(NULL, payload, payload_len, keyring->description, KEY_CHECK, 0, - keyring->description, ima_ns); + keyring->description, + NULL); } diff --git a/security/integrity/ima/ima_digest_list.c b/security/integrity/ima/ima_digest_list.c index 2d7148ff09c1..dd6dbdbbc7dd 100644 --- a/security/integrity/ima/ima_digest_list.c +++ b/security/integrity/ima/ima_digest_list.c @@ -173,7 +173,7 @@ int ima_parse_compact_list(loff_t size, void *buf, int op) size_t digest_len; int ret = 0, i;
- if (!(ima_digest_list_actions & init_policy_data.ima_policy_flag)) + if (!(ima_digest_list_actions & ima_policy_flag)) return -EACCES;
while (bufp < bufendp) { @@ -394,7 +394,7 @@ void __init ima_load_digest_lists(void) .ctx.actor = load_digest_list, };
- if (!(ima_digest_list_actions & init_policy_data.ima_policy_flag)) + if (!(ima_digest_list_actions & ima_policy_flag)) return;
ret = kern_path(CONFIG_IMA_DIGEST_LISTS_DIR, 0, &path); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index bf1d464620f7..64f5b0997760 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -369,7 +369,6 @@ static ssize_t ima_write_data(struct file *file, const char __user *buf, ssize_t result; struct dentry *dentry = file_dentry(file); int i; - struct ima_namespace *ima_ns = get_current_ns();
/* No partial writes. */ result = -EINVAL; @@ -405,7 +404,7 @@ static ssize_t ima_write_data(struct file *file, const char __user *buf, if (data[0] == '/') { result = ima_read_sfs_file(data, dentry); } else if (dentry == ima_policy) { - if (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_POLICY) { + if (ima_appraise & IMA_APPRAISE_POLICY) { pr_err("signed policy file (specified " "as an absolute pathname) required\n"); integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, @@ -520,7 +519,6 @@ static int ima_release_data_upload(struct inode *inode, struct file *file) struct dentry *dentry = file_dentry(file); const char *cause = valid_policy ? "completed" : "failed"; enum ima_fs_flags flag = ima_get_dentry_flag(dentry); - struct ima_namespace *ima_ns = get_current_ns();
if ((file->f_flags & O_ACCMODE) == O_RDONLY) return seq_release(inode, file); @@ -533,7 +531,7 @@ static int ima_release_data_upload(struct inode *inode, struct file *file) return 0; }
- if (valid_policy && ima_check_policy(ima_ns) < 0) { + if (valid_policy && ima_check_policy(NULL) < 0) { cause = "failed"; valid_policy = 0; } diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index dea0251142fd..3b8839b97a98 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -118,16 +118,15 @@ static int __init ima_add_boot_aggregate(void) #ifdef CONFIG_IMA_LOAD_X509 void __init ima_load_x509(void) { - int unset_flags = - init_ima_ns.policy_data->ima_policy_flag & IMA_APPRAISE; + int unset_flags = ima_policy_flag & IMA_APPRAISE;
- init_ima_ns.policy_data->ima_policy_flag &= ~unset_flags; + ima_policy_flag &= ~unset_flags; integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH);
/* load also EVM key to avoid appraisal */ evm_load_x509();
- init_ima_ns.policy_data->ima_policy_flag |= unset_flags; + ima_policy_flag |= unset_flags; } #endif
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 7986dfb3e5d6..9bbd716bff99 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -30,6 +30,12 @@ #include "ima.h" #include "ima_digest_list.h"
+#ifdef CONFIG_IMA_APPRAISE +int ima_appraise = IMA_APPRAISE_ENFORCE; +#else +int ima_appraise; +#endif + int ima_hash_algo = HASH_ALGO_SHA1;
/* Actions (measure/appraisal) for which digest lists can be used */ @@ -128,8 +134,7 @@ static void ima_rdwr_violation_check(struct file *file, if (mode & FMODE_WRITE) { if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { if (!iint) - iint = integrity_iint_rb_find(ima_ns->iint_tree, - inode); + iint = integrity_iint_find(inode); /* IMA_MEASURE is set from reader side */ if (iint && test_bit(IMA_MUST_MEASURE, &iint->atomic_flags)) @@ -209,38 +214,11 @@ static int ima_read_xattr(struct dentry *dentry, return ret; }
-static void ima_check_active_ns(struct ima_namespace *current_ima_ns, - struct inode *inode) -{ - struct ima_namespace *ima_ns; - struct integrity_iint_cache *iint; - - down_read(&ima_ns_list_lock); - list_for_each_entry(ima_ns, &ima_ns_list, list) { - if (atomic_read(&ima_ns->inactive)) - continue; - if ((ima_ns == current_ima_ns) || - !ima_ns->policy_data->ima_policy_flag) - continue; - - iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); - if (!iint) - continue; - - mutex_lock(&iint->mutex); - iint->flags &= ~IMA_DONE_MASK; - iint->measured_pcrs = 0; - mutex_unlock(&iint->mutex); - } - up_read(&ima_ns_list_lock); -} - static void ima_check_last_writer(struct integrity_iint_cache *iint, struct inode *inode, struct file *file) { fmode_t mode = file->f_mode; bool update; - struct ima_namespace *ima_ns = (struct ima_namespace *)file->f_ima;
if (!(mode & FMODE_WRITE)) return; @@ -254,9 +232,6 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, (iint->flags & IMA_NEW_FILE)) { iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE); iint->measured_pcrs = 0; - - ima_check_active_ns(ima_ns, inode); - if (update) ima_update_xattr(iint, file); } @@ -306,10 +281,10 @@ void ima_file_free(struct file *file) if (unlikely(!(file->f_mode & FMODE_OPENED))) goto out;
- if (!ima_ns->policy_data->ima_policy_flag || !S_ISREG(inode->i_mode)) + if (!ima_policy_flag || !S_ISREG(inode->i_mode)) goto out;
- iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); + iint = integrity_iint_find(inode); if (!iint) goto out;
@@ -318,10 +293,10 @@ void ima_file_free(struct file *file) put_ima_ns(ima_ns); }
-static int process_ns_measurement(struct file *file, const struct cred *cred, - u32 secid, char *buf, loff_t size, int mask, - enum ima_hooks func, - struct ima_namespace *ima_ns) +static int process_measurement(struct file *file, const struct cred *cred, + u32 secid, char *buf, loff_t size, int mask, + enum ima_hooks func, + struct ima_namespace *ima_ns) { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint = NULL; @@ -337,9 +312,8 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, int xattr_len = 0; bool violation_check; enum hash_algo hash_algo; - struct ima_namespace *current_ima_ns = get_current_ns();
- if (!ima_ns->policy_data->ima_policy_flag) + if (!ima_policy_flag || !S_ISREG(inode->i_mode)) return 0;
/* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action @@ -349,8 +323,7 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, action = ima_get_action(inode, cred, secid, mask, func, &pcr, &template_desc, NULL, ima_ns); violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) && - (ima_ns->policy_data->ima_policy_flag & - IMA_MEASURE)); + (ima_policy_flag & IMA_MEASURE)); if (!action && !violation_check) return 0;
@@ -363,7 +336,7 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, inode_lock(inode);
if (action) { - iint = integrity_inode_rb_get(ima_ns->iint_tree, inode); + iint = integrity_inode_get(inode); if (!iint) rc = -ENOMEM; } @@ -378,8 +351,6 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, goto out; if (!action) goto out; - if (ima_ns != current_ima_ns) - goto out;
mutex_lock(&iint->mutex);
@@ -510,8 +481,7 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, if (pathbuf) __putname(pathbuf); if (must_appraise) { - if (rc && - (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE)) + if (rc && (ima_appraise & IMA_APPRAISE_ENFORCE)) return -EACCES; if (file->f_mode & FMODE_WRITE) set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); @@ -519,32 +489,6 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, return 0; }
-static int process_measurement(struct file *file, const struct cred *cred, - u32 secid, char *buf, loff_t size, int mask, - enum ima_hooks func) -{ - int ret; - struct ima_namespace *ima_ns; - struct inode *inode = file_inode(file); - - if (!S_ISREG(inode->i_mode)) - return 0; - - down_read(&ima_ns_list_lock); - list_for_each_entry(ima_ns, &ima_ns_list, list) { - if (atomic_read(&ima_ns->inactive)) - continue; - - ret = process_ns_measurement(file, cred, secid, buf, size, mask, - func, ima_ns); - if (ret != 0) - break; - } - up_read(&ima_ns_list_lock); - - return ret; -} - /** * ima_file_mmap - based on policy, collect/store measurement. * @file: pointer to the file to be measured (May be NULL) @@ -563,7 +507,7 @@ int ima_file_mmap(struct file *file, unsigned long prot) if (file && (prot & PROT_EXEC)) { security_task_getsecid(current, &secid); return process_measurement(file, current_cred(), secid, NULL, - 0, MAY_EXEC, MMAP_CHECK); + 0, MAY_EXEC, MMAP_CHECK, NULL); }
return 0; @@ -583,7 +527,6 @@ int ima_file_mmap(struct file *file, unsigned long prot) */ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot) { - struct ima_namespace *ima_ns = get_current_ns(); struct ima_template_desc *template; struct file *file = vma->vm_file; char filename[NAME_MAX]; @@ -596,15 +539,14 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot) int pcr;
/* Is mprotect making an mmap'ed file executable? */ - if (!(ima_ns->policy_data->ima_policy_flag & IMA_APPRAISE) || - !vma->vm_file || !(prot & PROT_EXEC) || - (vma->vm_flags & VM_EXEC)) + if (!(ima_policy_flag & IMA_APPRAISE) || !vma->vm_file || + !(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC)) return 0;
security_task_getsecid(current, &secid); inode = file_inode(vma->vm_file); action = ima_get_action(inode, current_cred(), secid, MAY_EXEC, - MMAP_CHECK, &pcr, &template, 0, ima_ns); + MMAP_CHECK, &pcr, &template, 0, NULL);
/* Is the mmap'ed file in policy? */ if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK))) @@ -643,13 +585,13 @@ int ima_bprm_check(struct linux_binprm *bprm)
security_task_getsecid(current, &secid); ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0, - MAY_EXEC, BPRM_CHECK); + MAY_EXEC, BPRM_CHECK, NULL); if (ret) return ret;
security_cred_getsecid(bprm->cred, &secid); return process_measurement(bprm->file, bprm->cred, secid, NULL, 0, - MAY_EXEC, CREDS_CHECK); + MAY_EXEC, CREDS_CHECK, NULL); }
/** @@ -670,7 +612,7 @@ int ima_file_check(struct file *file, int mask) security_task_getsecid(current, &secid); rc = process_measurement(file, current_cred(), secid, NULL, 0, mask & (MAY_READ | MAY_WRITE | MAY_EXEC | - MAY_APPEND), FILE_CHECK); + MAY_APPEND), FILE_CHECK, NULL); if (ima_current_is_parser() && !rc) ima_check_measured_appraised(file); return rc; @@ -679,7 +621,7 @@ EXPORT_SYMBOL_GPL(ima_file_check);
/** * ima_file_hash - return the stored measurement if a file has been hashed and - * is in the iint cache of the current IMA namespace. + * is in the iint cache. * @file: pointer to the file * @buf: buffer in which to store the hash * @buf_size: length of the buffer @@ -697,7 +639,6 @@ EXPORT_SYMBOL_GPL(ima_file_check); */ int ima_file_hash(struct file *file, char *buf, size_t buf_size) { - struct ima_namespace *ima_ns = get_current_ns(); struct inode *inode; struct integrity_iint_cache *iint; int hash_algo; @@ -705,11 +646,11 @@ int ima_file_hash(struct file *file, char *buf, size_t buf_size) if (!file) return -EINVAL;
- if (!ima_ns->policy_data->ima_policy_flag) + if (!ima_policy_flag) return -EOPNOTSUPP;
inode = file_inode(file); - iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); + iint = integrity_iint_find(inode); if (!iint) return -EOPNOTSUPP;
@@ -747,30 +688,21 @@ EXPORT_SYMBOL_GPL(ima_file_hash); */ void ima_post_create_tmpfile(struct inode *inode) { - struct ima_namespace *ima_ns; struct integrity_iint_cache *iint; int must_appraise;
- down_read(&ima_ns_list_lock); - list_for_each_entry(ima_ns, &ima_ns_list, list) { - if (atomic_read(&ima_ns->inactive)) - continue; - - must_appraise = ima_must_appraise(inode, MAY_ACCESS, - FILE_CHECK, ima_ns); - if (!must_appraise) - continue; + must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK, NULL); + if (!must_appraise) + return;
- /* Nothing to do if we can't allocate memory */ - iint = integrity_inode_rb_get(ima_ns->iint_tree, inode); - if (!iint) - continue; + /* Nothing to do if we can't allocate memory */ + iint = integrity_inode_get(inode); + if (!iint) + return;
- /* needed for writing the security xattrs */ - set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); - iint->ima_file_status = INTEGRITY_PASS; - } - up_read(&ima_ns_list_lock); + /* needed for writing the security xattrs */ + set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); + iint->ima_file_status = INTEGRITY_PASS; }
/** @@ -782,30 +714,21 @@ void ima_post_create_tmpfile(struct inode *inode) */ void ima_post_path_mknod(struct dentry *dentry) { - struct ima_namespace *ima_ns; struct integrity_iint_cache *iint; struct inode *inode = dentry->d_inode; int must_appraise;
- down_read(&ima_ns_list_lock); - list_for_each_entry(ima_ns, &ima_ns_list, list) { - if (atomic_read(&ima_ns->inactive)) - continue; - - must_appraise = ima_must_appraise(inode, MAY_ACCESS, - FILE_CHECK, ima_ns); - if (!must_appraise) - continue; + must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK, NULL); + if (!must_appraise) + return;
- /* Nothing to do if we can't allocate memory */ - iint = integrity_inode_rb_get(ima_ns->iint_tree, inode); - if (!iint) - continue; + /* Nothing to do if we can't allocate memory */ + iint = integrity_inode_get(inode); + if (!iint) + return;
- /* needed for re-opening empty files */ - iint->flags |= IMA_NEW_FILE; - } - up_read(&ima_ns_list_lock); + /* needed for re-opening empty files */ + iint->flags |= IMA_NEW_FILE; }
/** @@ -846,7 +769,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id, func = read_idmap[read_id] ?: FILE_CHECK; security_task_getsecid(current, &secid); return process_measurement(file, current_cred(), secid, NULL, - 0, MAY_READ, func); + 0, MAY_READ, func, NULL); }
const int read_idmap[READING_MAX_ID] = { @@ -876,14 +799,13 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, { enum ima_hooks func; u32 secid; - struct ima_namespace *ima_ns = get_current_ns();
/* permit signed certs */ if (!file && read_id == READING_X509_CERTIFICATE) return 0;
if (!file || !buf || size == 0) { /* should never happen */ - if (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE) + if (ima_appraise & IMA_APPRAISE_ENFORCE) return -EACCES; return 0; } @@ -891,7 +813,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, func = read_idmap[read_id] ?: FILE_CHECK; security_task_getsecid(current, &secid); return process_measurement(file, current_cred(), secid, buf, size, - MAY_READ, func); + MAY_READ, func, NULL); }
/** @@ -909,16 +831,9 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, int ima_load_data(enum kernel_load_data_id id, bool contents) { bool ima_enforce, sig_enforce; - struct ima_namespace *ima_ns = get_current_ns(); - - if (ima_ns != &init_ima_ns) { - pr_err("Prevent data loading in IMA namespaces other than the root\n"); - return -EACCES; - }
ima_enforce = - (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE) == - IMA_APPRAISE_ENFORCE; + (ima_appraise & IMA_APPRAISE_ENFORCE) == IMA_APPRAISE_ENFORCE;
switch (id) { case LOADING_KEXEC_IMAGE: @@ -928,16 +843,13 @@ int ima_load_data(enum kernel_load_data_id id, bool contents) return -EACCES; }
- if (ima_enforce && - (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_KEXEC)) { + if (ima_enforce && (ima_appraise & IMA_APPRAISE_KEXEC)) { pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n"); return -EACCES; /* INTEGRITY_UNKNOWN */ } break; case LOADING_FIRMWARE: - if (ima_enforce && - (ima_ns->policy_data->ima_appraise & - IMA_APPRAISE_FIRMWARE) && !contents) { + if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE) && !contents) { pr_err("Prevent firmware sysfs fallback loading.\n"); return -EACCES; /* INTEGRITY_UNKNOWN */ } @@ -945,10 +857,8 @@ int ima_load_data(enum kernel_load_data_id id, bool contents) case LOADING_MODULE: sig_enforce = is_module_sig_enforced();
- if (ima_enforce && - (!sig_enforce && - (ima_ns->policy_data->ima_appraise & - IMA_APPRAISE_MODULES))) { + if (ima_enforce && (!sig_enforce + && (ima_appraise & IMA_APPRAISE_MODULES))) { pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n"); return -EACCES; /* INTEGRITY_UNKNOWN */ } @@ -975,14 +885,9 @@ int ima_post_load_data(char *buf, loff_t size, enum kernel_load_data_id load_id, char *description) { - struct ima_namespace *ima_ns = get_current_ns(); - if (load_id == LOADING_FIRMWARE) { - if (WARN_ON(ima_ns != &init_ima_ns)) - return -EACCES; - - if ((ima_ns->policy_data->ima_appraise & IMA_APPRAISE_FIRMWARE) && - (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE)) { + if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && + (ima_appraise & IMA_APPRAISE_ENFORCE)) { pr_err("Prevent firmware loading_store.\n"); return -EACCES; /* INTEGRITY_UNKNOWN */ } @@ -1001,7 +906,6 @@ int ima_post_load_data(char *buf, loff_t size, * @func: IMA hook * @pcr: pcr to extend the measurement * @keyring: keyring name to determine the action to be performed - * @ima_ns: pointer to the IMA namespace in consideration * * Based on policy, the buffer is measured into the ima log. */ @@ -1027,7 +931,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, int action = 0; u32 secid;
- if (!ima_ns->policy_data->ima_policy_flag) + if (!ima_policy_flag) return;
/* @@ -1040,7 +944,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, if (func) { security_task_getsecid(current, &secid); action = ima_get_action(inode, current_cred(), secid, 0, func, - &pcr, &template, keyring, ima_ns); + &pcr, &template, keyring, NULL); if (!(action & IMA_MEASURE)) return; } @@ -1103,11 +1007,6 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) { struct fd f; - struct ima_namespace *ima_ns = get_current_ns(); - - /* Currently allowed only from the root IMA namespace */ - if (WARN_ON(ima_ns != &init_ima_ns)) - return;
if (!buf || !size) return; @@ -1118,31 +1017,10 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
process_buffer_measurement(file_inode(f.file), buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0, NULL, - ima_ns); + NULL); fdput(f); }
-void ima_inode_free(struct inode *inode) -{ - struct ima_namespace *ima_ns; - - if (!IS_IMA(inode)) - return; - - down_read(&ima_ns_list_lock); - list_for_each_entry(ima_ns, &ima_ns_list, list) { - if (atomic_read(&ima_ns->inactive)) - continue; - integrity_inode_rb_free(ima_ns->iint_tree, inode); - } - up_read(&ima_ns_list_lock); -} - -bool ima_is_root_namespace(void) -{ - return get_current_ns() == &init_ima_ns; -} - static int __init init_ima(void) { int error; diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 04aa50473971..226a53279f71 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -181,14 +181,11 @@ int __init ima_init_namespace(void)
static void destroy_ima_ns(struct ima_namespace *ns) { - bool is_init_ns = (ns == &init_ima_ns); - dec_ima_namespaces(ns->ucounts); put_user_ns(ns->user_ns); ns_free_inum(&ns->ns); integrity_iint_tree_free(ns->iint_tree); kfree(ns->iint_tree); - ima_delete_ns_rules(ns->policy_data, is_init_ns); kfree(ns->policy_data); kfree(ns); } diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 0ab91cb31121..ebb4721032d4 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -49,6 +49,8 @@ #define INVALID_PCR(a) (((a) < 0) || \ (a) >= (sizeof_field(struct integrity_iint_cache, measured_pcrs) * 8))
+int ima_policy_flag; +static int temp_ima_appraise; static int build_ima_appraise __ro_after_init;
#define MAX_LSM_RULES 6 @@ -223,11 +225,16 @@ static struct ima_rule_entry ima_parser_appraise_rule __ro_after_init = { .flags = IMA_PARSER | IMA_DIGSIG_REQUIRED };
-/* Number of architecture specific rules found */ -static int arch_entries_size __ro_after_init; /* An array of architecture specific rules */ static struct ima_rule_entry *arch_policy_entry __ro_after_init;
+static LIST_HEAD(ima_default_rules); +static LIST_HEAD(ima_policy_rules); +static LIST_HEAD(ima_temp_rules); +static struct list_head *ima_rules = &ima_default_rules; + +static int ima_policy __initdata; + struct ima_policy_setup_data init_policy_setup_data = { #ifdef CONFIG_IMA_APPRAISE .ima_appraise = IMA_APPRAISE_ENFORCE, @@ -237,25 +244,31 @@ struct ima_policy_data init_policy_data = { .ima_default_rules = LIST_HEAD_INIT(init_policy_data.ima_default_rules), .ima_policy_rules = LIST_HEAD_INIT(init_policy_data.ima_policy_rules), .ima_temp_rules = LIST_HEAD_INIT(init_policy_data.ima_temp_rules), - .ima_rules = &init_policy_data.ima_default_rules, };
int ima_default_measure_policy_setup(const char *str, struct ima_policy_setup_data *setup_data) { - if (setup_data->ima_policy) - return 1; - - setup_data->ima_policy = ORIGINAL_TCB; + /* Currently unused. It will be implemented after namespacing ima + * policy, when global variables are removed. + */ return 1; }
static int __init default_measure_policy_setup(char *str) { - return ima_default_measure_policy_setup(str, &init_policy_setup_data); + if (ima_policy) + return 1; + + ima_policy = ORIGINAL_TCB; + return 1; } __setup("ima_tcb", default_measure_policy_setup);
+static bool ima_use_appraise_tcb __initdata; +static bool ima_use_appraise_exec_tcb __initdata; +static bool ima_use_appraise_exec_immutable __initdata; +static bool ima_use_secure_boot __initdata; static bool ima_fail_unverifiable_sigs __ro_after_init;
/** @@ -263,55 +276,61 @@ static bool ima_fail_unverifiable_sigs __ro_after_init; * @str: string to be parsed * @setup_data: pointer to a structure where parsed data is stored * @fail_unverifiable_sigs: boolean flag treated separately to preserve - * __ro_after_init + * __ro_after_init */ int ima_policy_setup(char *str, struct ima_policy_setup_data *setup_data, bool *fail_unverifiable_sigs) +{ + + /* Currently unused. It will be implemented after namespacing ima + * policy, when global variables are removed. + */ + return 1; +} + +static int __init policy_setup(char *str) { char *p;
while ((p = strsep(&str, " |\n")) != NULL) { if (*p == ' ') continue; - if ((strcmp(p, "tcb") == 0) && !setup_data->ima_policy) - setup_data->ima_policy = DEFAULT_TCB; - else if ((strcmp(p, "exec_tcb") == 0) && !setup_data->ima_policy) - setup_data->ima_policy = EXEC_TCB; + if ((strcmp(p, "tcb") == 0) && !ima_policy) + ima_policy = DEFAULT_TCB; + else if ((strcmp(p, "exec_tcb") == 0) && !ima_policy) + ima_policy = EXEC_TCB; else if (strcmp(p, "appraise_tcb") == 0) - setup_data->ima_use_appraise_tcb = true; + ima_use_appraise_tcb = true; else if (strcmp(p, "appraise_exec_tcb") == 0) - setup_data->ima_use_appraise_exec_tcb = true; + ima_use_appraise_exec_tcb = true; else if (strcmp(p, "appraise_exec_immutable") == 0) - setup_data->ima_use_appraise_exec_immutable = true; + ima_use_appraise_exec_immutable = true; else if (strcmp(p, "secure_boot") == 0) - setup_data->ima_use_secure_boot = true; + ima_use_secure_boot = true; else if (strcmp(p, "fail_securely") == 0) - *fail_unverifiable_sigs = true; + ima_fail_unverifiable_sigs = true; else pr_err("policy "%s" not found", p); }
return 1; } - -static int __init policy_setup(char *str) -{ - return ima_policy_setup(str, &init_policy_setup_data, - &ima_fail_unverifiable_sigs); -} __setup("ima_policy=", policy_setup);
int ima_default_appraise_policy_setup(const char *str, struct ima_policy_setup_data *setup_data) { - setup_data->ima_use_appraise_tcb = true; + /* Currently unused. It will be implemented after namespacing ima + * policy, when global variables are removed. + */ return 1; }
static int __init default_appraise_policy_setup(char *str) { - return ima_default_appraise_policy_setup(str, &init_policy_setup_data); + ima_use_appraise_tcb = true; + return 1; } __setup("ima_appraise_tcb", default_appraise_policy_setup);
@@ -486,11 +505,9 @@ static bool ima_rule_contains_lsm_cond(struct ima_rule_entry *entry) static void ima_lsm_update_rules(void) { struct ima_rule_entry *entry, *e; - struct ima_namespace *ima_ns = get_current_ns(); int result;
- list_for_each_entry_safe(entry, e, - &ima_ns->policy_data->ima_policy_rules, list) { + list_for_each_entry_safe(entry, e, &ima_policy_rules, list) { if (!ima_rule_contains_lsm_cond(entry)) continue;
@@ -692,13 +709,12 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, { struct ima_rule_entry *entry; int action = 0, actmask = flags | (flags << 1); - bool fail_unverifiable_sigs;
if (template_desc) *template_desc = ima_template_desc_current();
rcu_read_lock(); - list_for_each_entry_rcu(entry, ima_ns->policy_data->ima_rules, list) { + list_for_each_entry_rcu(entry, ima_rules, list) {
if (!(entry->action & actmask)) continue; @@ -713,10 +729,7 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, if (entry->action & IMA_APPRAISE) { action |= get_subaction(entry, func); action &= ~IMA_HASH; - fail_unverifiable_sigs = (ima_ns == &init_ima_ns) ? - ima_fail_unverifiable_sigs : - ima_ns->policy_data->ima_fail_unverifiable_sigs; - if (fail_unverifiable_sigs) + if (ima_fail_unverifiable_sigs) action |= IMA_FAIL_UNVERIFIABLE_SIGS; }
@@ -751,15 +764,14 @@ void ima_update_policy_flag(struct ima_namespace *ima_ns) { struct ima_rule_entry *entry;
- list_for_each_entry(entry, ima_ns->policy_data->ima_rules, list) { + list_for_each_entry(entry, ima_rules, list) { if (entry->action & IMA_DO_MASK) - ima_ns->policy_data->ima_policy_flag |= entry->action; + ima_policy_flag |= entry->action; }
- ima_ns->policy_data->ima_appraise |= - (build_ima_appraise | ima_ns->policy_data->temp_ima_appraise); - if (!ima_ns->policy_data->ima_appraise) - ima_ns->policy_data->ima_policy_flag &= ~IMA_APPRAISE; + ima_appraise |= (build_ima_appraise | temp_ima_appraise); + if (!ima_appraise) + ima_policy_flag &= ~IMA_APPRAISE; }
static int ima_appraise_flag(enum ima_hooks func) @@ -777,17 +789,16 @@ static int ima_appraise_flag(enum ima_hooks func) return 0; }
-static void add_rules(struct ima_namespace *ima_ns, - struct ima_rule_entry *entries, int count, - enum policy_rule_list policy_rule, - const struct ima_policy_setup_data *setup_data) +static void __init add_rules(struct ima_policy_data *policy_data, + struct ima_rule_entry *entries, int count, + enum policy_rule_list policy_rule) { int i = 0;
for (i = 0; i < count; i++) { struct ima_rule_entry *entry;
- if (setup_data->ima_policy == EXEC_TCB) { + if (ima_policy == EXEC_TCB) { if (entries == dont_measure_rules) if ((entries[i].flags & IMA_FSMAGIC) && entries[i].fsmagic == TMPFS_MAGIC) @@ -799,7 +810,7 @@ static void add_rules(struct ima_namespace *ima_ns, continue; }
- if (setup_data->ima_use_appraise_exec_tcb) { + if (ima_use_appraise_exec_tcb) { if (entries == default_appraise_rules) { if (entries[i].action != DONT_APPRAISE) continue; @@ -809,24 +820,14 @@ static void add_rules(struct ima_namespace *ima_ns, } }
- if (setup_data->ima_use_appraise_exec_immutable) + if (ima_use_appraise_exec_immutable) if (entries == appraise_exec_rules && (entries[i].flags & IMA_FUNC) && entries[i].func == BPRM_CHECK) entries[i].flags |= IMA_META_IMMUTABLE_REQUIRED;
- if (policy_rule & IMA_DEFAULT_POLICY) { - entry = &entries[i]; - if (ima_ns != &init_ima_ns) { - entry = kmemdup(&entries[i], sizeof(*entry), - GFP_KERNEL); - if (!entry) - continue; - } - - list_add_tail(&entry->list, - &ima_ns->policy_data->ima_default_rules); - } + if (policy_rule & IMA_DEFAULT_POLICY) + list_add_tail(&entries[i].list, &ima_default_rules);
if (policy_rule & IMA_CUSTOM_POLICY) { entry = kmemdup(&entries[i], sizeof(*entry), @@ -834,12 +835,11 @@ static void add_rules(struct ima_namespace *ima_ns, if (!entry) continue;
- list_add_tail(&entry->list, - &ima_ns->policy_data->ima_policy_rules); + list_add_tail(&entry->list, &ima_policy_rules); } if (entries[i].action == APPRAISE) { if (entries != build_appraise_rules) - ima_ns->policy_data->temp_ima_appraise |= + temp_ima_appraise |= ima_appraise_flag(entries[i].func); else build_ima_appraise |= @@ -850,7 +850,7 @@ static void add_rules(struct ima_namespace *ima_ns,
static int ima_parse_rule(char *rule, struct ima_rule_entry *entry);
-static int ima_init_arch_policy(void) +static int __init ima_init_arch_policy(void) { const char * const *arch_rules; const char * const *rules; @@ -899,71 +899,69 @@ static int ima_init_arch_policy(void) void ima_init_ns_policy(struct ima_namespace *ima_ns, const struct ima_policy_setup_data *setup_data) { - int build_appraise_entries; - - ima_ns->policy_data->ima_appraise = setup_data->ima_appraise; - - if (ima_ns == &init_ima_ns) { - /* - * Based on runtime secure boot flags, insert arch specific - * measurement and appraise rules requiring file signatures for - * both the initial and custom policies, prior to other - * appraise rules. (Highest priority) - */ - arch_entries_size = ima_init_arch_policy(); - if (!arch_entries_size) - pr_info("No architecture policies found\n"); + /* Set policy rules to the empty set of default rules. The rest will be + * implemented after namespacing policy. + */ + ima_ns->policy_data->ima_rules = + &ima_ns->policy_data->ima_default_rules; +}
- ima_ns->policy_data->ima_fail_unverifiable_sigs = - ima_fail_unverifiable_sigs; - } +/** + * ima_init_policy - initialize the default measure rules. + * + * ima_rules points to either the ima_default_rules or the + * the new ima_policy_rules. + */ +void __init ima_init_policy(void) +{ + int build_appraise_entries, arch_entries;
/* if !ima_policy, we load NO default rules */ - if (setup_data->ima_policy) - add_rules(ima_ns, dont_measure_rules, - ARRAY_SIZE(dont_measure_rules), - IMA_DEFAULT_POLICY, - setup_data); + if (ima_policy) + add_rules(NULL, + dont_measure_rules, ARRAY_SIZE(dont_measure_rules), + IMA_DEFAULT_POLICY);
- switch (setup_data->ima_policy) { + switch (ima_policy) { case ORIGINAL_TCB: - add_rules(ima_ns, original_measurement_rules, + add_rules(NULL, original_measurement_rules, ARRAY_SIZE(original_measurement_rules), - IMA_DEFAULT_POLICY, - setup_data); + IMA_DEFAULT_POLICY); break; case EXEC_TCB: fallthrough; case DEFAULT_TCB: - add_rules(ima_ns, default_measurement_rules, + add_rules(NULL, default_measurement_rules, ARRAY_SIZE(default_measurement_rules), - IMA_DEFAULT_POLICY, - setup_data); + IMA_DEFAULT_POLICY); default: break; }
- if (setup_data->ima_policy) - add_rules(ima_ns, &ima_parser_measure_rule, 1, IMA_DEFAULT_POLICY, - setup_data); + if (ima_policy) + add_rules(NULL, &ima_parser_measure_rule, 1, IMA_DEFAULT_POLICY);
- if (arch_entries_size) - add_rules(ima_ns, - arch_policy_entry, - arch_entries_size, - IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY, - setup_data); + /* + * Based on runtime secure boot flags, insert arch specific measurement + * and appraise rules requiring file signatures for both the initial + * and custom policies, prior to other appraise rules. + * (Highest priority) + */ + arch_entries = ima_init_arch_policy(); + if (!arch_entries) + pr_info("No architecture policies found\n"); + else + add_rules(NULL, arch_policy_entry, arch_entries, + IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
/* * Insert the builtin "secure_boot" policy rules requiring file * signatures, prior to other appraise rules. */ - if (setup_data->ima_use_secure_boot || - setup_data->ima_use_appraise_exec_tcb) - add_rules(ima_ns, secure_boot_rules, - ARRAY_SIZE(secure_boot_rules), - IMA_DEFAULT_POLICY, - setup_data); + if (ima_use_secure_boot || ima_use_appraise_exec_tcb) + add_rules(NULL, + secure_boot_rules, ARRAY_SIZE(secure_boot_rules), + IMA_DEFAULT_POLICY);
/* * Insert the build time appraise rules requiring file signatures @@ -972,53 +970,38 @@ void ima_init_ns_policy(struct ima_namespace *ima_ns, * rules, include either one or the other set of rules, but not both. */ build_appraise_entries = ARRAY_SIZE(build_appraise_rules); - if (build_appraise_entries && (ima_ns == &init_ima_ns)) { - if (setup_data->ima_use_secure_boot) - add_rules(ima_ns, build_appraise_rules, - build_appraise_entries, - IMA_CUSTOM_POLICY, - setup_data); + if (build_appraise_entries) { + if (ima_use_secure_boot) + add_rules(NULL, + build_appraise_rules, build_appraise_entries, + IMA_CUSTOM_POLICY); else - add_rules(ima_ns, build_appraise_rules, - build_appraise_entries, - IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY, - setup_data); + add_rules(NULL, + build_appraise_rules, build_appraise_entries, + IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY); }
- if (setup_data->ima_use_appraise_tcb || - setup_data->ima_use_appraise_exec_tcb) - add_rules(ima_ns, default_appraise_rules, + if (ima_use_appraise_tcb || ima_use_appraise_exec_tcb) + add_rules(NULL, default_appraise_rules, ARRAY_SIZE(default_appraise_rules), - IMA_DEFAULT_POLICY, setup_data); + IMA_DEFAULT_POLICY);
- if (setup_data->ima_use_appraise_exec_tcb) - add_rules(ima_ns, appraise_exec_rules, + if (ima_use_appraise_exec_tcb) + add_rules(NULL, appraise_exec_rules, ARRAY_SIZE(appraise_exec_rules), - IMA_DEFAULT_POLICY, setup_data); + IMA_DEFAULT_POLICY);
- if (setup_data->ima_use_secure_boot || - setup_data->ima_use_appraise_tcb || - setup_data->ima_use_appraise_exec_tcb) - add_rules(ima_ns, &ima_parser_appraise_rule, 1, - IMA_DEFAULT_POLICY, setup_data); + if (ima_use_secure_boot || ima_use_appraise_tcb || + ima_use_appraise_exec_tcb) + add_rules(NULL, &ima_parser_appraise_rule, 1, IMA_DEFAULT_POLICY);
- ima_ns->policy_data->ima_rules = - &ima_ns->policy_data->ima_default_rules; - ima_update_policy_flag(ima_ns); -} - -/** - * ima_init_policy - initialize the default measure rules for the initial ima ns - */ -void __init ima_init_policy(void) -{ - ima_init_ns_policy(&init_ima_ns, &init_policy_setup_data); + ima_update_policy_flag(NULL); }
/* Make sure we have a valid policy, at least containing some rules. */ int ima_check_policy(const struct ima_namespace *ima_ns) { - if (list_empty(&ima_ns->policy_data->ima_temp_rules)) + if (list_empty(&ima_temp_rules)) return -EINVAL; return 0; } @@ -1036,18 +1019,14 @@ int ima_check_policy(const struct ima_namespace *ima_ns) */ void ima_update_policy(void) { - /* Update only the current ima namespace */ - struct ima_namespace *ima_ns = get_current_ns(); - struct list_head *policy = &ima_ns->policy_data->ima_policy_rules; + struct list_head *policy = &ima_policy_rules;
- list_splice_tail_init_rcu(&ima_ns->policy_data->ima_temp_rules, - policy, synchronize_rcu); + list_splice_tail_init_rcu(&ima_temp_rules, policy, synchronize_rcu);
- if (ima_ns->policy_data->ima_rules != policy) { - ima_ns->policy_data->ima_policy_flag = 0; - ima_ns->policy_data->ima_rules = policy; + if (ima_rules != policy) { + ima_policy_flag = 0; + ima_rules = policy;
-#ifndef CONFIG_IMA_NS /* * IMA architecture specific policy rules are specified * as strings and converted to an array of ima_entry_rules @@ -1055,9 +1034,8 @@ void ima_update_policy(void) * architecture specific rules stored as an array. */ kfree(arch_policy_entry); -#endif } - ima_update_policy_flag(ima_ns); + ima_update_policy_flag(NULL);
/* Custom IMA policy has been loaded */ ima_process_queued_keys(); @@ -1121,7 +1099,6 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry, substring_t *args, int lsm_rule, int audit_type) { int result; - struct ima_namespace *ima_ns = get_current_ns();
if (entry->lsm[lsm_rule].rule) return -EINVAL; @@ -1138,8 +1115,7 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry, pr_warn("rule for LSM '%s' is undefined\n", entry->lsm[lsm_rule].args_p);
- if (ima_ns->policy_data->ima_rules == - &ima_ns->policy_data->ima_default_rules) { + if (ima_rules == &ima_default_rules) { kfree(entry->lsm[lsm_rule].args_p); entry->lsm[lsm_rule].args_p = NULL; result = -EINVAL; @@ -1303,7 +1279,6 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) bool uid_token; struct ima_template_desc *template_desc; int result = 0; - struct ima_namespace *ima_ns = get_current_ns();
ab = integrity_audit_log_start(audit_context(), GFP_KERNEL, AUDIT_INTEGRITY_POLICY_RULE); @@ -1665,8 +1640,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) if (!result && !ima_validate_rule(entry)) result = -EINVAL; else if (entry->action == APPRAISE) - ima_ns->policy_data->temp_ima_appraise |= - ima_appraise_flag(entry->func); + temp_ima_appraise |= ima_appraise_flag(entry->func);
if (!result && entry->flags & IMA_MODSIG_ALLOWED) { template_desc = entry->template ? entry->template : @@ -1693,8 +1667,6 @@ ssize_t ima_parse_add_rule(char *rule) struct ima_rule_entry *entry; ssize_t result, len; int audit_info = 0; - /* Add rules only to the current ima namespace */ - struct ima_namespace *ima_ns = get_current_ns();
p = strsep(&rule, "\n"); len = strlen(p) + 1; @@ -1721,7 +1693,7 @@ ssize_t ima_parse_add_rule(char *rule) return result; }
- list_add_tail(&entry->list, &ima_ns->policy_data->ima_temp_rules); + list_add_tail(&entry->list, &ima_temp_rules);
return len; } @@ -1733,51 +1705,15 @@ ssize_t ima_parse_add_rule(char *rule) * ima_delete_rules() at a time. */ void ima_delete_rules(void) -{ - /* Delete rules only from the current ima namespace */ - struct ima_namespace *ima_ns = get_current_ns(); - struct ima_rule_entry *entry, *tmp; - - ima_ns->policy_data->temp_ima_appraise = 0; - list_for_each_entry_safe(entry, tmp, - &ima_ns->policy_data->ima_temp_rules, list) { - list_del(&entry->list); - ima_free_rule(entry); - } -} - -#ifdef CONFIG_IMA_NS -/** - * ima_delete_ns_rules - delete policy rules and free the memory - * @policy_data: a pointer to the policy data of the given namespace - * @is_root_ns: indicates if the namespace being cleaned up is the root - * namespace - * - * This function should be called only for the inactive namespace, when it is - * being destroyed. - */ -void ima_delete_ns_rules(struct ima_policy_data *policy_data, - bool is_root_ns) { struct ima_rule_entry *entry, *tmp;
- /* no locks necessary, namespace is inactive */ - list_for_each_entry_safe(entry, tmp, - &policy_data->ima_policy_rules, list) { + temp_ima_appraise = 0; + list_for_each_entry_safe(entry, tmp, &ima_temp_rules, list) { list_del(&entry->list); ima_free_rule(entry); } - - if (!is_root_ns) { - list_for_each_entry_safe(entry, tmp, - &policy_data->ima_default_rules, - list) { - list_del(&entry->list); - ima_free_rule(entry); - } - } } -#endif
#define __ima_hook_stringify(func, str) (#func),
@@ -1801,10 +1737,9 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos) { loff_t l = *pos; struct ima_rule_entry *entry; - struct ima_namespace *ima_ns = get_current_ns();
rcu_read_lock(); - list_for_each_entry_rcu(entry, ima_ns->policy_data->ima_rules, list) { + list_for_each_entry_rcu(entry, ima_rules, list) { if (!l--) { rcu_read_unlock(); return entry; @@ -1816,7 +1751,6 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos)
void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos) { - struct ima_namespace *ima_ns = get_current_ns(); struct ima_rule_entry *entry = v;
rcu_read_lock(); @@ -1824,7 +1758,7 @@ void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos) rcu_read_unlock(); (*pos)++;
- return (&entry->list == ima_ns->policy_data->ima_rules) ? NULL : entry; + return (&entry->list == ima_rules) ? NULL : entry; }
void ima_policy_stop(struct seq_file *m, void *v) @@ -2022,7 +1956,6 @@ int ima_policy_show(struct seq_file *m, void *v) */ bool ima_appraise_signature(enum kernel_read_file_id id) { - struct ima_namespace *ima_ns = get_current_ns(); struct ima_rule_entry *entry; bool found = false; enum ima_hooks func; @@ -2033,7 +1966,7 @@ bool ima_appraise_signature(enum kernel_read_file_id id) func = read_idmap[id] ?: FILE_CHECK;
rcu_read_lock(); - list_for_each_entry_rcu(entry, ima_ns->policy_data->ima_rules, list) { + list_for_each_entry_rcu(entry, ima_rules, list) { if (entry->action != APPRAISE) continue;
diff --git a/security/integrity/ima/ima_queue_keys.c b/security/integrity/ima/ima_queue_keys.c index 542cbe894a99..34ca54ba52b7 100644 --- a/security/integrity/ima/ima_queue_keys.c +++ b/security/integrity/ima/ima_queue_keys.c @@ -110,11 +110,8 @@ bool ima_queue_key(struct key *keyring, const void *payload, if (!entry) return false;
- /* Queued keys will be processed according to the root IMA namespace - * policy, therefore allow queueing only for the root namespace. - */ mutex_lock(&ima_keys_lock); - if (!ima_process_keys && (get_current_ns() == &init_ima_ns)) { + if (!ima_process_keys) { list_add_tail(&entry->list, &ima_keys); queued = true; } @@ -161,15 +158,12 @@ void ima_process_queued_keys(void)
list_for_each_entry_safe(entry, tmp, &ima_keys, list) { if (!timer_expired) - /* Queued keys are always measured according to the - * initial namespace policy. - */ process_buffer_measurement(NULL, entry->payload, entry->payload_len, entry->keyring_name, KEY_CHECK, 0, entry->keyring_name, - &init_ima_ns); + NULL); list_del(&entry->list); ima_free_key_entry(entry); } diff --git a/security/security.c b/security/security.c index 33d0d1a28b42..4fb58543eeb9 100644 --- a/security/security.c +++ b/security/security.c @@ -990,7 +990,7 @@ static void inode_free_by_rcu(struct rcu_head *head)
void security_inode_free(struct inode *inode) { - ima_inode_free(inode); + integrity_inode_free(inode); call_void_hook(inode_free_security, inode); /* * The inode may still be referenced in a path walk and
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 5f7f33c2af796b77e0b252cc505d8b4cc8c448fc.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 1 - security/integrity/ima/ima_init.c | 1 - security/integrity/ima/ima_ns.c | 17 ++--------------- 3 files changed, 2 insertions(+), 17 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index f5683756f2b5..7f847cf0297c 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -220,7 +220,6 @@ struct ima_namespace { atomic_t inactive; /* set only when ns is added to the cleanup list */ bool frozen; struct ima_policy_data *policy_data; - struct integrity_iint_tree *iint_tree; } __randomize_layout;
extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 3b8839b97a98..9f0e9dc3b77f 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -34,7 +34,6 @@ struct ima_namespace init_ima_ns = { #endif .frozen = true, .policy_data = &init_policy_data, - .iint_tree = &init_iint_tree, }; EXPORT_SYMBOL(init_ima_ns);
diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 226a53279f71..1aeb9cfeb3a2 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -56,18 +56,11 @@ static struct ima_namespace *ima_ns_alloc(void) ima_ns->policy_data = kzalloc(sizeof(struct ima_policy_data), GFP_KERNEL); if (!ima_ns->policy_data) - goto ns_free; - - ima_ns->iint_tree = kzalloc(sizeof(struct integrity_iint_tree), - GFP_KERNEL); - if (!ima_ns->iint_tree) - goto policy_free; + goto out_free;
return ima_ns;
-policy_free: - kfree(ima_ns->policy_data); -ns_free: +out_free: kfree(ima_ns); out: return NULL; @@ -127,9 +120,6 @@ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, ns->ucounts = ucounts; ns->frozen = false;
- rwlock_init(&ns->iint_tree->lock); - ns->iint_tree->root = RB_ROOT; - INIT_LIST_HEAD(&ns->policy_data->ima_default_rules); INIT_LIST_HEAD(&ns->policy_data->ima_policy_rules); INIT_LIST_HEAD(&ns->policy_data->ima_temp_rules); @@ -137,7 +127,6 @@ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, return ns;
fail_free: - kfree(ns->iint_tree); kfree(ns->policy_data); kfree(ns); fail_dec: @@ -184,8 +173,6 @@ static void destroy_ima_ns(struct ima_namespace *ns) dec_ima_namespaces(ns->ucounts); put_user_ns(ns->user_ns); ns_free_inum(&ns->ns); - integrity_iint_tree_free(ns->iint_tree); - kfree(ns->iint_tree); kfree(ns->policy_data); kfree(ns); }
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit eecf0d8324b4fd931349e6528f82fc115dca5928.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/integrity.h | 31 -------- security/integrity/iint.c | 126 +++++++-------------------------- security/integrity/integrity.h | 11 --- 3 files changed, 24 insertions(+), 144 deletions(-)
diff --git a/include/linux/integrity.h b/include/linux/integrity.h index 4a38310e6e7e..2ea0f2f65ab6 100644 --- a/include/linux/integrity.h +++ b/include/linux/integrity.h @@ -8,10 +8,6 @@ #define _LINUX_INTEGRITY_H
#include <linux/fs.h> -#include <linux/rwlock_types.h> - -struct rb_root; -struct integrity_iint_tree;
enum integrity_status { INTEGRITY_PASS = 0, @@ -26,15 +22,8 @@ enum integrity_status { /* List of EVM protected security xattrs */ #ifdef CONFIG_INTEGRITY extern struct integrity_iint_cache *integrity_inode_get(struct inode *inode); -extern struct integrity_iint_cache *integrity_inode_rb_get(struct - integrity_iint_tree - *iint_tree, - struct inode *inode); extern void integrity_inode_free(struct inode *inode); -extern void integrity_inode_rb_free(struct integrity_iint_tree *iint_tree, - struct inode *inode); extern void __init integrity_load_keys(void); -extern void integrity_iint_tree_free(struct integrity_iint_tree *iint_tree);
#else static inline struct integrity_iint_cache * @@ -43,34 +32,14 @@ static inline struct integrity_iint_cache * return NULL; }
-static inline struct integrity_iint_cache * - integrity_inode_rb_get(struct - integrity_iint_tree - *iint_tree, - struct inode *inode) -{ - return NULL; -} - static inline void integrity_inode_free(struct inode *inode) { return; }
-static inline void integrity_inode_rb_free(struct integrity_iint_tree - *iint_tree, - struct inode *inode) -{ -} - static inline void integrity_load_keys(void) { } - -static inline void integrity_iint_tree_free(struct integrity_iint_tree - *iint_tree) -{ -} #endif /* CONFIG_INTEGRITY */
#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS diff --git a/security/integrity/iint.c b/security/integrity/iint.c index 48716d058ed1..8953ac6412c3 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -21,29 +21,19 @@ #include <linux/lsm_hooks.h> #include "integrity.h"
-struct integrity_iint_tree init_iint_tree = { - .lock = __RW_LOCK_UNLOCKED(init_iint_tree.lock), - .root = RB_ROOT -}; - +static struct rb_root integrity_iint_tree = RB_ROOT; +static DEFINE_RWLOCK(integrity_iint_lock); static struct kmem_cache *iint_cache __read_mostly;
struct dentry *integrity_dir;
/* - * __integrity_iint_rb_find - return the iint associated with an inode - * @iint_rb_root: pointer to the root of the iint tree - * @inode: pointer to the inode - * @return: pointer to the iint if found, NULL otherwise + * __integrity_iint_find - return the iint associated with an inode */ -static struct integrity_iint_cache * - __integrity_iint_rb_find(const struct rb_root - *iint_rb_root, - const struct inode - *inode) +static struct integrity_iint_cache *__integrity_iint_find(struct inode *inode) { struct integrity_iint_cache *iint; - struct rb_node *n = iint_rb_root->rb_node; + struct rb_node *n = integrity_iint_tree.rb_node;
while (n) { iint = rb_entry(n, struct integrity_iint_cache, rb_node); @@ -62,37 +52,22 @@ static struct integrity_iint_cache * }
/* - * integrity_iint_rb_find - return the iint associated with an inode - * @iint_tree: pointer to the iint tree root node and the associated lock - * @inode: pointer to the inode - * @return: pointer to the iint if found, NULL otherwise + * integrity_iint_find - return the iint associated with an inode */ -struct integrity_iint_cache *integrity_iint_rb_find(struct integrity_iint_tree - *iint_tree, - const struct inode *inode) +struct integrity_iint_cache *integrity_iint_find(struct inode *inode) { struct integrity_iint_cache *iint;
if (!IS_IMA(inode)) return NULL;
- read_lock(&iint_tree->lock); - iint = __integrity_iint_rb_find(&iint_tree->root, inode); - read_unlock(&iint_tree->lock); + read_lock(&integrity_iint_lock); + iint = __integrity_iint_find(inode); + read_unlock(&integrity_iint_lock);
return iint; }
-/* - * integrity_iint_find - return the iint associated with an inode - * @inode: pointer to the inode - * @return: pointer to the iint if found, NULL otherwise - */ -struct integrity_iint_cache *integrity_iint_find(struct inode *inode) -{ - return integrity_iint_rb_find(&init_iint_tree, inode); -} - static void iint_free(struct integrity_iint_cache *iint) { kfree(iint->ima_hash); @@ -111,36 +86,13 @@ static void iint_free(struct integrity_iint_cache *iint) }
/** - * integrity_iint_tree_free - traverse the tree and free all nodes - * @iint_tree: pointer to the iint tree root node and the associated lock - * - * The tree cannot be in use. This function should be called only from the - * destructor when no locks are required. - */ -void integrity_iint_tree_free(struct integrity_iint_tree *iint_tree) -{ - struct rb_root *root = &iint_tree->root; - struct integrity_iint_cache *iint, *tmp; - - rbtree_postorder_for_each_entry_safe(iint, tmp, root, rb_node) { - iint_free(iint); - } - - iint_tree->root = RB_ROOT; -} - -/** - * integrity_inode_rb_get - find or allocate an iint associated with an inode - * @iint_tree: pointer to the iint tree root node and the associated lock + * integrity_inode_get - find or allocate an iint associated with an inode * @inode: pointer to the inode - * @return: pointer to the existing iint if found, pointer to the allocated iint - * if it didn't exist, NULL in case of error + * @return: allocated iint * * Caller must lock i_mutex */ -struct integrity_iint_cache *integrity_inode_rb_get(struct integrity_iint_tree - *iint_tree, - struct inode *inode) +struct integrity_iint_cache *integrity_inode_get(struct inode *inode) { struct rb_node **p; struct rb_node *node, *parent = NULL; @@ -154,7 +106,7 @@ struct integrity_iint_cache *integrity_inode_rb_get(struct integrity_iint_tree if (!iint_cache) panic("%s: lsm=integrity required.\n", __func__);
- iint = integrity_iint_rb_find(iint_tree, inode); + iint = integrity_iint_find(inode); if (iint) return iint;
@@ -162,9 +114,9 @@ struct integrity_iint_cache *integrity_inode_rb_get(struct integrity_iint_tree if (!iint) return NULL;
- write_lock(&iint_tree->lock); + write_lock(&integrity_iint_lock);
- p = &iint_tree->root.rb_node; + p = &integrity_iint_tree.rb_node; while (*p) { parent = *p; test_iint = rb_entry(parent, struct integrity_iint_cache, @@ -179,63 +131,33 @@ struct integrity_iint_cache *integrity_inode_rb_get(struct integrity_iint_tree node = &iint->rb_node; inode->i_flags |= S_IMA; rb_link_node(node, parent, p); - rb_insert_color(node, &iint_tree->root); + rb_insert_color(node, &integrity_iint_tree);
- write_unlock(&iint_tree->lock); + write_unlock(&integrity_iint_lock); return iint; }
/** - * integrity_inode_get - find or allocate an iint associated with an inode - * @inode: pointer to the inode - * @return: pointer to the existing iint if found, pointer to the allocated iint - * if it didn't exist, NULL in case of error - * - * Caller must lock i_mutex - */ -struct integrity_iint_cache *integrity_inode_get(struct inode *inode) -{ - return integrity_inode_rb_get(&init_iint_tree, inode); -} - -/** - * integrity_inode_rb_free - called on security_inode_free - * @iint_tree: pointer to the iint tree root node and the associated lock + * integrity_inode_free - called on security_inode_free * @inode: pointer to the inode * * Free the integrity information(iint) associated with an inode. */ -void integrity_inode_rb_free(struct integrity_iint_tree *iint_tree, - struct inode *inode) +void integrity_inode_free(struct inode *inode) { struct integrity_iint_cache *iint;
if (!IS_IMA(inode)) return;
- write_lock(&iint_tree->lock); - iint = __integrity_iint_rb_find(&iint_tree->root, inode); - if (!iint) { - write_unlock(&iint_tree->lock); - return; - } - rb_erase(&iint->rb_node, &iint_tree->root); - write_unlock(&iint_tree->lock); + write_lock(&integrity_iint_lock); + iint = __integrity_iint_find(inode); + rb_erase(&iint->rb_node, &integrity_iint_tree); + write_unlock(&integrity_iint_lock);
iint_free(iint); }
-/** - * integrity_inode_free - called on security_inode_free - * @inode: pointer to the inode - * - * Free the integrity information(iint) associated with an inode. - */ -void integrity_inode_free(struct inode *inode) -{ - integrity_inode_rb_free(&init_iint_tree, inode); -} - static void init_once(void *foo) { struct integrity_iint_cache *iint = foo; diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 05f6eabef9fe..77e6819e8db8 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -184,20 +184,11 @@ static inline void ima_load_digest_lists(void) } #endif
-struct integrity_iint_tree { - rwlock_t lock; - struct rb_root root; -}; - /* rbtree tree calls to lookup, insert, delete * integrity data associated with an inode. */ struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
-struct integrity_iint_cache *integrity_iint_rb_find(struct integrity_iint_tree - *iint_tree, - const struct inode *inode); - int integrity_kernel_read(struct file *file, loff_t offset, void *addr, unsigned long count);
@@ -208,8 +199,6 @@ int integrity_kernel_read(struct file *file, loff_t offset,
extern struct dentry *integrity_dir;
-extern struct integrity_iint_tree init_iint_tree; - struct modsig;
#ifdef CONFIG_INTEGRITY_SIGNATURE
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit c2b095cc0f1447fbbeade7ba09c6e9e9ee75fca4.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 4 +- security/integrity/ima/ima.h | 28 +++++-------- security/integrity/ima/ima_api.c | 9 ++-- security/integrity/ima/ima_appraise.c | 16 +++----- security/integrity/ima/ima_asymmetric_keys.c | 3 +- security/integrity/ima/ima_fs.c | 2 +- security/integrity/ima/ima_main.c | 43 +++++++++----------- security/integrity/ima/ima_policy.c | 42 ++++++++----------- security/integrity/ima/ima_queue_keys.c | 3 +- 9 files changed, 60 insertions(+), 90 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index 7f847cf0297c..5cb5659c0a06 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -152,7 +152,7 @@ static inline void ima_post_key_create_or_update(struct key *keyring, #endif /* CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS */
#ifdef CONFIG_IMA_APPRAISE -extern bool is_ima_appraise_enabled(const struct ima_namespace *ima_ns); +extern bool is_ima_appraise_enabled(void); extern void ima_inode_post_setattr(struct dentry *dentry); extern int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, const void *xattr_value, size_t xattr_value_len); @@ -164,7 +164,7 @@ extern int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name); extern void ima_inode_post_removexattr(struct dentry *dentry, const char *xattr_name); #else -static inline bool is_ima_appraise_enabled(const struct ima_namespace *ima_ns) +static inline bool is_ima_appraise_enabled(void) { return 0; } diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 8b59e03ec849..071e9e749420 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -268,8 +268,7 @@ static inline void ima_process_queued_keys(void) {} int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, int mask, enum ima_hooks func, int *pcr, struct ima_template_desc **template_desc, - const char *keyring, - struct ima_namespace *ima_ns); + const char *keyring); int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func); int ima_collect_measurement(struct integrity_iint_cache *iint, struct file *file, void *buf, loff_t size, @@ -279,12 +278,10 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig, int pcr, struct ima_template_desc *template_desc, - struct ima_digest *digest, - struct ima_namespace *ima_ns); + struct ima_digest *digest); void process_buffer_measurement(struct inode *inode, const void *buf, int size, const char *eventname, enum ima_hooks func, - int pcr, const char *keyring, - struct ima_namespace *ima_ns); + int pcr, const char *keyring); void ima_audit_measurement(struct integrity_iint_cache *iint, const unsigned char *filename); int ima_alloc_init_template(struct ima_event_data *event_data, @@ -300,16 +297,15 @@ const char *ima_d_path(const struct path *path, char **pathbuf, char *filename); int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, enum ima_hooks func, int mask, int flags, int *pcr, struct ima_template_desc **template_desc, - const char *keyring, - struct ima_namespace *ima_ns); + const char *keyring); void ima_init_policy(void); void ima_init_ns_policy(struct ima_namespace *ima_ns, const struct ima_policy_setup_data *policy_setup_data); void ima_update_policy(void); -void ima_update_policy_flag(struct ima_namespace *ima_ns); +void ima_update_policy_flag(void); ssize_t ima_parse_add_rule(char *); void ima_delete_rules(void); -int ima_check_policy(const struct ima_namespace *ima_ns); +int ima_check_policy(void); void *ima_policy_start(struct seq_file *m, loff_t *pos); void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos); void ima_policy_stop(struct seq_file *m, void *v); @@ -337,23 +333,20 @@ int ima_default_appraise_setup(const char *str,
#ifdef CONFIG_IMA_APPRAISE int ima_check_blacklist(struct integrity_iint_cache *iint, - const struct modsig *modsig, int pcr, - struct ima_namespace *ima_ns); + const struct modsig *modsig, int pcr); int ima_appraise_measurement(enum ima_hooks func, struct integrity_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig, struct ima_digest *found_digest); -int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func, - struct ima_namespace *ima_ns); +int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, enum ima_hooks func); #else static inline int ima_check_blacklist(struct integrity_iint_cache *iint, - const struct modsig *modsig, int pcr, - struct ima_namespace *ima_ns) + const struct modsig *modsig, int pcr) { return 0; } @@ -371,8 +364,7 @@ static inline int ima_appraise_measurement(enum ima_hooks func, }
static inline int ima_must_appraise(struct inode *inode, int mask, - enum ima_hooks func, - struct ima_namespace *ima_ns) + enum ima_hooks func) { return 0; } diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index b4347eac9c85..d9f4599dee40 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -191,7 +191,6 @@ void ima_add_violation(struct file *file, const unsigned char *filename, * @pcr: pointer filled in if matched measure policy sets pcr= * @template_desc: pointer filled in if matched measure policy sets template= * @keyring: keyring name used to determine the action - * @ima_ns: ima namespace whose policy data will be used * * The policy is defined in terms of keypairs: * subj=, obj=, type=, func=, mask=, fsmagic= @@ -207,15 +206,14 @@ void ima_add_violation(struct file *file, const unsigned char *filename, int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, int mask, enum ima_hooks func, int *pcr, struct ima_template_desc **template_desc, - const char *keyring, - struct ima_namespace *ima_ns) + const char *keyring) { int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
flags &= ima_policy_flag;
return ima_match_policy(inode, cred, secid, func, mask, flags, pcr, - template_desc, keyring, ima_ns); + template_desc, keyring); }
/* @@ -320,8 +318,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig, int pcr, struct ima_template_desc *template_desc, - struct ima_digest *digest, - struct ima_namespace *ima_ns) + struct ima_digest *digest) { static const char op[] = "add_template_measure"; static const char audit_cause[] = "ENOMEM"; diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 9213c012cbe4..ad7715822e06 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -81,11 +81,10 @@ __setup("ima_appraise_digest_list=", appraise_digest_list_setup);
/* * is_ima_appraise_enabled - return appraise status - * @ima_ns: pointer to the ima namespace being checked * * Only return enabled, if not in ima_appraise="fix" or "log" modes. */ -bool is_ima_appraise_enabled(const struct ima_namespace *ima_ns) +bool is_ima_appraise_enabled(void) { return ima_appraise & IMA_APPRAISE_ENFORCE; } @@ -95,8 +94,7 @@ bool is_ima_appraise_enabled(const struct ima_namespace *ima_ns) * * Return 1 to appraise or hash */ -int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func, - struct ima_namespace *ima_ns) +int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func) { u32 secid;
@@ -105,8 +103,7 @@ int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func,
security_task_getsecid(current, &secid); return ima_match_policy(inode, current_cred(), secid, func, mask, - IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL, - NULL); + IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL); }
static int ima_fix_xattr(struct dentry *dentry, @@ -334,8 +331,7 @@ static int modsig_verify(enum ima_hooks func, const struct modsig *modsig, * Returns -EPERM if the hash is blacklisted. */ int ima_check_blacklist(struct integrity_iint_cache *iint, - const struct modsig *modsig, int pcr, - struct ima_namespace *ima_ns) + const struct modsig *modsig, int pcr) { enum hash_algo hash_algo; const u8 *digest = NULL; @@ -352,7 +348,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint, if ((rc == -EPERM) && (iint->flags & IMA_MEASURE)) process_buffer_measurement(NULL, digest, digestsize, "blacklisted-hash", NONE, - pcr, NULL, NULL); + pcr, NULL); }
return rc; @@ -579,7 +575,7 @@ void ima_inode_post_setattr(struct dentry *dentry) || !(inode->i_opflags & IOP_XATTR)) return;
- action = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR, NULL); + action = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR); iint = integrity_iint_find(inode); if (iint) { set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags); diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c index 58aa56b0422d..1c68c500c26f 100644 --- a/security/integrity/ima/ima_asymmetric_keys.c +++ b/security/integrity/ima/ima_asymmetric_keys.c @@ -60,6 +60,5 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key, */ process_buffer_measurement(NULL, payload, payload_len, keyring->description, KEY_CHECK, 0, - keyring->description, - NULL); + keyring->description); } diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 64f5b0997760..90f1d9c85b31 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -531,7 +531,7 @@ static int ima_release_data_upload(struct inode *inode, struct file *file) return 0; }
- if (valid_policy && ima_check_policy(NULL) < 0) { + if (valid_policy && ima_check_policy() < 0) { cause = "failed"; valid_policy = 0; } diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 9bbd716bff99..e4b0ad29dbd8 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -124,8 +124,7 @@ static void ima_rdwr_violation_check(struct file *file, int must_measure, char **pathbuf, const char **pathname, - char *filename, - struct ima_namespace *ima_ns) + char *filename) { struct inode *inode = file_inode(file); fmode_t mode = file->f_mode; @@ -295,8 +294,7 @@ void ima_file_free(struct file *file)
static int process_measurement(struct file *file, const struct cred *cred, u32 secid, char *buf, loff_t size, int mask, - enum ima_hooks func, - struct ima_namespace *ima_ns) + enum ima_hooks func) { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint = NULL; @@ -321,7 +319,7 @@ static int process_measurement(struct file *file, const struct cred *cred, * Included is the appraise submask. */ action = ima_get_action(inode, cred, secid, mask, func, &pcr, - &template_desc, NULL, ima_ns); + &template_desc, NULL); violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) && (ima_policy_flag & IMA_MEASURE)); if (!action && !violation_check) @@ -343,7 +341,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
if (!rc && violation_check) ima_rdwr_violation_check(file, iint, action & IMA_MEASURE, - &pathbuf, &pathname, filename, ima_ns); + &pathbuf, &pathname, filename);
inode_unlock(inode);
@@ -447,11 +445,10 @@ static int process_measurement(struct file *file, const struct cred *cred, xattr_value, xattr_len, modsig, pcr, template_desc, ima_digest_allow(found_digest, - IMA_MEASURE), - ima_ns); + IMA_MEASURE));
if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) { - rc = ima_check_blacklist(iint, modsig, pcr, ima_ns); + rc = ima_check_blacklist(iint, modsig, pcr); if (rc != -EPERM) { inode_lock(inode); rc = ima_appraise_measurement(func, iint, file, @@ -507,7 +504,7 @@ int ima_file_mmap(struct file *file, unsigned long prot) if (file && (prot & PROT_EXEC)) { security_task_getsecid(current, &secid); return process_measurement(file, current_cred(), secid, NULL, - 0, MAY_EXEC, MMAP_CHECK, NULL); + 0, MAY_EXEC, MMAP_CHECK); }
return 0; @@ -546,7 +543,7 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot) security_task_getsecid(current, &secid); inode = file_inode(vma->vm_file); action = ima_get_action(inode, current_cred(), secid, MAY_EXEC, - MMAP_CHECK, &pcr, &template, 0, NULL); + MMAP_CHECK, &pcr, &template, 0);
/* Is the mmap'ed file in policy? */ if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK))) @@ -585,13 +582,13 @@ int ima_bprm_check(struct linux_binprm *bprm)
security_task_getsecid(current, &secid); ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0, - MAY_EXEC, BPRM_CHECK, NULL); + MAY_EXEC, BPRM_CHECK); if (ret) return ret;
security_cred_getsecid(bprm->cred, &secid); return process_measurement(bprm->file, bprm->cred, secid, NULL, 0, - MAY_EXEC, CREDS_CHECK, NULL); + MAY_EXEC, CREDS_CHECK); }
/** @@ -612,7 +609,7 @@ int ima_file_check(struct file *file, int mask) security_task_getsecid(current, &secid); rc = process_measurement(file, current_cred(), secid, NULL, 0, mask & (MAY_READ | MAY_WRITE | MAY_EXEC | - MAY_APPEND), FILE_CHECK, NULL); + MAY_APPEND), FILE_CHECK); if (ima_current_is_parser() && !rc) ima_check_measured_appraised(file); return rc; @@ -691,7 +688,7 @@ void ima_post_create_tmpfile(struct inode *inode) struct integrity_iint_cache *iint; int must_appraise;
- must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK, NULL); + must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK); if (!must_appraise) return;
@@ -718,7 +715,7 @@ void ima_post_path_mknod(struct dentry *dentry) struct inode *inode = dentry->d_inode; int must_appraise;
- must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK, NULL); + must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK); if (!must_appraise) return;
@@ -769,7 +766,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id, func = read_idmap[read_id] ?: FILE_CHECK; security_task_getsecid(current, &secid); return process_measurement(file, current_cred(), secid, NULL, - 0, MAY_READ, func, NULL); + 0, MAY_READ, func); }
const int read_idmap[READING_MAX_ID] = { @@ -813,7 +810,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, func = read_idmap[read_id] ?: FILE_CHECK; security_task_getsecid(current, &secid); return process_measurement(file, current_cred(), secid, buf, size, - MAY_READ, func, NULL); + MAY_READ, func); }
/** @@ -911,8 +908,7 @@ int ima_post_load_data(char *buf, loff_t size, */ void process_buffer_measurement(struct inode *inode, const void *buf, int size, const char *eventname, enum ima_hooks func, - int pcr, const char *keyring, - struct ima_namespace *ima_ns) + int pcr, const char *keyring) { int ret = 0; const char *audit_cause = "ENOMEM"; @@ -944,7 +940,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, if (func) { security_task_getsecid(current, &secid); action = ima_get_action(inode, current_cred(), secid, 0, func, - &pcr, &template, keyring, NULL); + &pcr, &template, keyring); if (!(action & IMA_MEASURE)) return; } @@ -1016,8 +1012,7 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) return;
process_buffer_measurement(file_inode(f.file), buf, size, - "kexec-cmdline", KEXEC_CMDLINE, 0, NULL, - NULL); + "kexec-cmdline", KEXEC_CMDLINE, 0, NULL); fdput(f); }
@@ -1046,7 +1041,7 @@ static int __init init_ima(void) pr_warn("Couldn't register LSM notifier, error %d\n", error);
if (!error) - ima_update_policy_flag(&init_ima_ns); + ima_update_policy_flag();
return error; } diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index ebb4721032d4..fe5d0f311f1c 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -692,7 +692,6 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) * @template_desc: the template that should be used for this rule * @keyring: the keyring name, if given, to be used to check in the policy. * keyring can be NULL if func is anything other than KEY_CHECK. - * @ima_ns: IMA namespace whose policies are being checked * * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type) * conditions. @@ -704,8 +703,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, enum ima_hooks func, int mask, int flags, int *pcr, struct ima_template_desc **template_desc, - const char *keyring, - struct ima_namespace *ima_ns) + const char *keyring) { struct ima_rule_entry *entry; int action = 0, actmask = flags | (flags << 1); @@ -758,9 +756,8 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, * loaded policy. Based on this flag, the decision to short circuit * out of a function or not call the function in the first place * can be made earlier. - * @ima_ns: pointer to the ima namespace whose policy flag is updated */ -void ima_update_policy_flag(struct ima_namespace *ima_ns) +void ima_update_policy_flag(void) { struct ima_rule_entry *entry;
@@ -789,8 +786,7 @@ static int ima_appraise_flag(enum ima_hooks func) return 0; }
-static void __init add_rules(struct ima_policy_data *policy_data, - struct ima_rule_entry *entries, int count, +static void __init add_rules(struct ima_rule_entry *entries, int count, enum policy_rule_list policy_rule) { int i = 0; @@ -918,20 +914,19 @@ void __init ima_init_policy(void)
/* if !ima_policy, we load NO default rules */ if (ima_policy) - add_rules(NULL, - dont_measure_rules, ARRAY_SIZE(dont_measure_rules), + add_rules(dont_measure_rules, ARRAY_SIZE(dont_measure_rules), IMA_DEFAULT_POLICY);
switch (ima_policy) { case ORIGINAL_TCB: - add_rules(NULL, original_measurement_rules, + add_rules(original_measurement_rules, ARRAY_SIZE(original_measurement_rules), IMA_DEFAULT_POLICY); break; case EXEC_TCB: fallthrough; case DEFAULT_TCB: - add_rules(NULL, default_measurement_rules, + add_rules(default_measurement_rules, ARRAY_SIZE(default_measurement_rules), IMA_DEFAULT_POLICY); default: @@ -939,7 +934,7 @@ void __init ima_init_policy(void) }
if (ima_policy) - add_rules(NULL, &ima_parser_measure_rule, 1, IMA_DEFAULT_POLICY); + add_rules(&ima_parser_measure_rule, 1, IMA_DEFAULT_POLICY);
/* * Based on runtime secure boot flags, insert arch specific measurement @@ -951,7 +946,7 @@ void __init ima_init_policy(void) if (!arch_entries) pr_info("No architecture policies found\n"); else - add_rules(NULL, arch_policy_entry, arch_entries, + add_rules(arch_policy_entry, arch_entries, IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
/* @@ -959,8 +954,7 @@ void __init ima_init_policy(void) * signatures, prior to other appraise rules. */ if (ima_use_secure_boot || ima_use_appraise_exec_tcb) - add_rules(NULL, - secure_boot_rules, ARRAY_SIZE(secure_boot_rules), + add_rules(secure_boot_rules, ARRAY_SIZE(secure_boot_rules), IMA_DEFAULT_POLICY);
/* @@ -972,34 +966,32 @@ void __init ima_init_policy(void) build_appraise_entries = ARRAY_SIZE(build_appraise_rules); if (build_appraise_entries) { if (ima_use_secure_boot) - add_rules(NULL, - build_appraise_rules, build_appraise_entries, + add_rules(build_appraise_rules, build_appraise_entries, IMA_CUSTOM_POLICY); else - add_rules(NULL, - build_appraise_rules, build_appraise_entries, + add_rules(build_appraise_rules, build_appraise_entries, IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY); }
if (ima_use_appraise_tcb || ima_use_appraise_exec_tcb) - add_rules(NULL, default_appraise_rules, + add_rules(default_appraise_rules, ARRAY_SIZE(default_appraise_rules), IMA_DEFAULT_POLICY);
if (ima_use_appraise_exec_tcb) - add_rules(NULL, appraise_exec_rules, + add_rules(appraise_exec_rules, ARRAY_SIZE(appraise_exec_rules), IMA_DEFAULT_POLICY);
if (ima_use_secure_boot || ima_use_appraise_tcb || ima_use_appraise_exec_tcb) - add_rules(NULL, &ima_parser_appraise_rule, 1, IMA_DEFAULT_POLICY); + add_rules(&ima_parser_appraise_rule, 1, IMA_DEFAULT_POLICY);
- ima_update_policy_flag(NULL); + ima_update_policy_flag(); }
/* Make sure we have a valid policy, at least containing some rules. */ -int ima_check_policy(const struct ima_namespace *ima_ns) +int ima_check_policy(void) { if (list_empty(&ima_temp_rules)) return -EINVAL; @@ -1035,7 +1027,7 @@ void ima_update_policy(void) */ kfree(arch_policy_entry); } - ima_update_policy_flag(NULL); + ima_update_policy_flag();
/* Custom IMA policy has been loaded */ ima_process_queued_keys(); diff --git a/security/integrity/ima/ima_queue_keys.c b/security/integrity/ima/ima_queue_keys.c index 34ca54ba52b7..69a8626a35c0 100644 --- a/security/integrity/ima/ima_queue_keys.c +++ b/security/integrity/ima/ima_queue_keys.c @@ -162,8 +162,7 @@ void ima_process_queued_keys(void) entry->payload_len, entry->keyring_name, KEY_CHECK, 0, - entry->keyring_name, - NULL); + entry->keyring_name); list_del(&entry->list); ima_free_key_entry(entry); }
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit dcc22cddc59e3af11ddd7ab9a52dc42addc04a5e.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- security/integrity/ima/ima.h | 10 -------- security/integrity/ima/ima_appraise.c | 10 -------- security/integrity/ima/ima_policy.c | 37 --------------------------- 3 files changed, 57 deletions(-)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 071e9e749420..95a877691cd0 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -311,16 +311,6 @@ void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos); void ima_policy_stop(struct seq_file *m, void *v); int ima_policy_show(struct seq_file *m, void *v);
-int ima_policy_setup(char *str, - struct ima_policy_setup_data *policy_setup_data, - bool *fail_unverifiable_sigs); -int ima_default_measure_policy_setup(const char *str, - struct ima_policy_setup_data *setup_data); -int ima_default_appraise_policy_setup(const char *str, - struct ima_policy_setup_data *setup_data); -int ima_default_appraise_setup(const char *str, - struct ima_policy_setup_data *setup_data); - /* Appraise integrity measurements */ #define IMA_APPRAISE_ENFORCE 0x01 #define IMA_APPRAISE_FIX 0x02 diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index ad7715822e06..3fb378017f9d 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -18,16 +18,6 @@ #include "ima_digest_list.h"
static bool ima_appraise_req_evm __ro_after_init; - -int ima_default_appraise_setup(const char *str, - struct ima_policy_setup_data *setup_data) -{ - /* Currently unused. It will be implemented after namespacing ima - * policy, when global variables are removed. - */ - return 1; -} - static int __init default_appraise_setup(char *str) { #ifdef CONFIG_IMA_APPRAISE_BOOTPARAM diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index fe5d0f311f1c..bdfe5ec0a79a 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -246,15 +246,6 @@ struct ima_policy_data init_policy_data = { .ima_temp_rules = LIST_HEAD_INIT(init_policy_data.ima_temp_rules), };
-int ima_default_measure_policy_setup(const char *str, - struct ima_policy_setup_data *setup_data) -{ - /* Currently unused. It will be implemented after namespacing ima - * policy, when global variables are removed. - */ - return 1; -} - static int __init default_measure_policy_setup(char *str) { if (ima_policy) @@ -270,25 +261,6 @@ static bool ima_use_appraise_exec_tcb __initdata; static bool ima_use_appraise_exec_immutable __initdata; static bool ima_use_secure_boot __initdata; static bool ima_fail_unverifiable_sigs __ro_after_init; - -/** - * ima_policy_setup - parse policy configuration string "ima_policy=" - * @str: string to be parsed - * @setup_data: pointer to a structure where parsed data is stored - * @fail_unverifiable_sigs: boolean flag treated separately to preserve - * __ro_after_init - */ -int ima_policy_setup(char *str, - struct ima_policy_setup_data *setup_data, - bool *fail_unverifiable_sigs) -{ - - /* Currently unused. It will be implemented after namespacing ima - * policy, when global variables are removed. - */ - return 1; -} - static int __init policy_setup(char *str) { char *p; @@ -318,15 +290,6 @@ static int __init policy_setup(char *str) } __setup("ima_policy=", policy_setup);
-int ima_default_appraise_policy_setup(const char *str, - struct ima_policy_setup_data *setup_data) -{ - /* Currently unused. It will be implemented after namespacing ima - * policy, when global variables are removed. - */ - return 1; -} - static int __init default_appraise_policy_setup(char *str) { ima_use_appraise_tcb = true;
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 3c7598779aaa682aceff7372aec0efe162e1fbab.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 2 -- security/integrity/ima/ima.h | 24 ----------------- security/integrity/ima/ima_init.c | 3 +-- security/integrity/ima/ima_ns.c | 41 ++--------------------------- security/integrity/ima/ima_policy.c | 26 ------------------ 5 files changed, 3 insertions(+), 93 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index 5cb5659c0a06..88734870af59 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -17,7 +17,6 @@ struct nsproxy; struct task_struct; struct list_head; struct llist_node; -struct ima_policy_data;
#ifdef CONFIG_IMA extern int ima_bprm_check(struct linux_binprm *bprm); @@ -219,7 +218,6 @@ struct ima_namespace { struct llist_node cleanup_list; /* namespaces on a death row */ atomic_t inactive; /* set only when ns is added to the cleanup list */ bool frozen; - struct ima_policy_data *policy_data; } __randomize_layout;
extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 95a877691cd0..86e3499b3523 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -63,14 +63,6 @@ extern int ima_digest_db_max_size __ro_after_init; extern int ima_digest_db_size; #endif
-/* IMA policy setup data */ -struct ima_policy_setup_data { - int ima_policy; - int ima_appraise; - bool ima_use_secure_boot; - bool ima_use_appraise_tcb; -}; - /* IMA event related data */ struct ima_event_data { struct integrity_iint_cache *iint; @@ -299,8 +291,6 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, struct ima_template_desc **template_desc, const char *keyring); void ima_init_policy(void); -void ima_init_ns_policy(struct ima_namespace *ima_ns, - const struct ima_policy_setup_data *policy_setup_data); void ima_update_policy(void); void ima_update_policy_flag(void); ssize_t ima_parse_add_rule(char *); @@ -373,20 +363,6 @@ static inline enum integrity_status ima_get_cache_status(struct integrity_iint_c
#endif /* CONFIG_IMA_APPRAISE */
-struct ima_policy_data { - struct list_head ima_default_rules; - struct list_head ima_policy_rules; - struct list_head ima_temp_rules; - struct list_head *ima_rules; - bool ima_fail_unverifiable_sigs; - int ima_policy_flag; /* current content of the policy */ - int ima_appraise; - int temp_ima_appraise; -}; - -extern struct ima_policy_data init_policy_data; -extern struct ima_policy_setup_data init_policy_setup_data; - extern struct list_head ima_ns_list; extern struct rw_semaphore ima_ns_list_lock;
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 9f0e9dc3b77f..2238fb21eaf0 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -32,8 +32,7 @@ struct ima_namespace init_ima_ns = { #ifdef CONFIG_IMA_NS .ns.ops = &imans_operations, #endif - .frozen = true, - .policy_data = &init_policy_data, + .frozen = true }; EXPORT_SYMBOL(init_ima_ns);
diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 1aeb9cfeb3a2..3a98cd536d05 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -51,38 +51,9 @@ static struct ima_namespace *ima_ns_alloc(void)
ima_ns = kzalloc(sizeof(*ima_ns), GFP_KERNEL); if (!ima_ns) - goto out; - - ima_ns->policy_data = kzalloc(sizeof(struct ima_policy_data), - GFP_KERNEL); - if (!ima_ns->policy_data) - goto out_free; + return NULL;
return ima_ns; - -out_free: - kfree(ima_ns); -out: - return NULL; -} - -static void ima_set_ns_policy(struct ima_namespace *ima_ns, - char *policy_setup_str) -{ - struct ima_policy_setup_data setup_data; - -#ifdef CONFIG_IMA_APPRAISE - setup_data.ima_appraise = IMA_APPRAISE_ENFORCE; -#endif - /* Configuring IMA namespace will be implemented in the following - * patches. When it is done, parse configuration string and store result - * in setup_data. Temporarily use init_policy_setup_data. - */ - setup_data = init_policy_setup_data; - ima_ns->policy_data->ima_fail_unverifiable_sigs = - init_ima_ns.policy_data->ima_fail_unverifiable_sigs; - - ima_init_ns_policy(ima_ns, &setup_data); }
/** @@ -93,7 +64,7 @@ static void ima_set_ns_policy(struct ima_namespace *ima_ns, * Return: ERR_PTR(-ENOMEM) on error (failure to kmalloc), new ns otherwise */ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, - struct ima_namespace *old_ns) + struct ima_namespace *old_ns) { struct ima_namespace *ns; struct ucounts *ucounts; @@ -120,14 +91,9 @@ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, ns->ucounts = ucounts; ns->frozen = false;
- INIT_LIST_HEAD(&ns->policy_data->ima_default_rules); - INIT_LIST_HEAD(&ns->policy_data->ima_policy_rules); - INIT_LIST_HEAD(&ns->policy_data->ima_temp_rules); - return ns;
fail_free: - kfree(ns->policy_data); kfree(ns); fail_dec: dec_ima_namespaces(ucounts); @@ -173,7 +139,6 @@ static void destroy_ima_ns(struct ima_namespace *ns) dec_ima_namespaces(ns->ucounts); put_user_ns(ns->user_ns); ns_free_inum(&ns->ns); - kfree(ns->policy_data); kfree(ns); }
@@ -273,8 +238,6 @@ static int imans_activate(struct ima_namespace *ima_ns) if (ima_ns->frozen) goto out;
- ima_set_ns_policy(ima_ns, NULL); - ima_ns->frozen = true;
down_write(&ima_ns_list_lock); diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index bdfe5ec0a79a..8e288da66503 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -235,17 +235,6 @@ static struct list_head *ima_rules = &ima_default_rules;
static int ima_policy __initdata;
-struct ima_policy_setup_data init_policy_setup_data = { -#ifdef CONFIG_IMA_APPRAISE - .ima_appraise = IMA_APPRAISE_ENFORCE, -#endif -}; -struct ima_policy_data init_policy_data = { - .ima_default_rules = LIST_HEAD_INIT(init_policy_data.ima_default_rules), - .ima_policy_rules = LIST_HEAD_INIT(init_policy_data.ima_policy_rules), - .ima_temp_rules = LIST_HEAD_INIT(init_policy_data.ima_temp_rules), -}; - static int __init default_measure_policy_setup(char *str) { if (ima_policy) @@ -850,21 +839,6 @@ static int __init ima_init_arch_policy(void) return i; }
-/** - * ima_init_ns_policy - initialize the default measure rules. - * @ima_ns: pointer to the namespace whose rules are being initialized - * @setup_data: pointer to the policy setup data - */ -void ima_init_ns_policy(struct ima_namespace *ima_ns, - const struct ima_policy_setup_data *setup_data) -{ - /* Set policy rules to the empty set of default rules. The rest will be - * implemented after namespacing policy. - */ - ima_ns->policy_data->ima_rules = - &ima_ns->policy_data->ima_default_rules; -} - /** * ima_init_policy - initialize the default measure rules. *
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit 9cf5b2e85d83daf8922d81bb43283fe216cad706.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- fs/file_table.c | 6 +---- include/linux/fs.h | 3 --- include/linux/ima.h | 6 ----- security/integrity/ima/ima_main.c | 37 ++----------------------------- 4 files changed, 3 insertions(+), 49 deletions(-)
diff --git a/fs/file_table.c b/fs/file_table.c index 40020a81c216..709ada3151da 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -109,8 +109,6 @@ static struct file *__alloc_file(int flags, const struct cred *cred) return ERR_PTR(error); }
- ima_file_alloc(f); - atomic_long_set(&f->f_count, 1); rwlock_init(&f->f_owner.lock); spin_lock_init(&f->f_lock); @@ -261,10 +259,8 @@ static void __fput(struct file *file) struct inode *inode = file->f_inode; fmode_t mode = file->f_mode;
- if (unlikely(!(file->f_mode & FMODE_OPENED))) { - ima_file_free(file); + if (unlikely(!(file->f_mode & FMODE_OPENED))) goto out; - }
might_sleep();
diff --git a/include/linux/fs.h b/include/linux/fs.h index a56184847086..ce2cab22d942 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -954,9 +954,6 @@ struct file { struct address_space *f_mapping; errseq_t f_wb_err; errseq_t f_sb_err; /* for syncfs */ -#ifdef CONFIG_IMA - void *f_ima; -#endif } __randomize_layout __attribute__((aligned(4))); /* lest something weird decides that 2 is OK */
diff --git a/include/linux/ima.h b/include/linux/ima.h index 88734870af59..77e7f512f61b 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -22,7 +22,6 @@ struct llist_node; extern int ima_bprm_check(struct linux_binprm *bprm); extern int ima_file_check(struct file *file, int mask); extern void ima_post_create_tmpfile(struct inode *inode); -extern int ima_file_alloc(struct file *file); extern void ima_file_free(struct file *file); extern int ima_file_mmap(struct file *file, unsigned long prot); extern int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot); @@ -71,11 +70,6 @@ static inline void ima_post_create_tmpfile(struct inode *inode) { }
-static inline int ima_file_alloc(struct file *file) -{ - return 0; -} - static inline void ima_file_free(struct file *file) { return; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index e4b0ad29dbd8..5fd890c85413 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -238,30 +238,6 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, mutex_unlock(&iint->mutex); }
-/** - * ima_file_alloc - called on __alloc_file() - * @file: pointer to file structure being created - * - * Bind IMA namespace to the file descriptor. This is necessary, because - * __fput can be called after exit_task_namespaces() in do_exit(). - * In that case nsproxy is already NULL and ima ns has to be found - * differently in ima_file_free(). If process joins different ima ns, files - * opened in the old ns will point to that (old) ns. - */ -int ima_file_alloc(struct file *file) -{ - /* It is possible that ima_file_alloc() is called after - * exit_task_namespaces(), when IMA does the last writer check from - * __fput(). In that case it's not necessary to store the namespace - * information */ - if (!current->nsproxy) - return 0; - - file->f_ima = get_current_ns(); - get_ima_ns((struct ima_namespace *)file->f_ima); - return 0; -} - /** * ima_file_free - called on __fput() * @file: pointer to file structure being freed @@ -272,24 +248,15 @@ void ima_file_free(struct file *file) { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint; - struct ima_namespace *ima_ns = (struct ima_namespace *)file->f_ima; - - if (!ima_ns) - return; - - if (unlikely(!(file->f_mode & FMODE_OPENED))) - goto out;
if (!ima_policy_flag || !S_ISREG(inode->i_mode)) - goto out; + return;
iint = integrity_iint_find(inode); if (!iint) - goto out; + return;
ima_check_last_writer(iint, inode, file); -out: - put_ima_ns(ima_ns); }
static int process_measurement(struct file *file, const struct cred *cred,
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit ee67fcbf6c74606fb4cbd038c64fb05c5a6ed20e.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 8 +-- security/integrity/ima/ima.h | 11 ---- security/integrity/ima/ima_init.c | 5 -- security/integrity/ima/ima_main.c | 3 - security/integrity/ima/ima_ns.c | 101 ++---------------------------- 5 files changed, 6 insertions(+), 122 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index 77e7f512f61b..67af79961e4e 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -11,12 +11,10 @@ #include <linux/fs.h> #include <linux/security.h> #include <linux/kexec.h> - struct linux_binprm; + struct nsproxy; struct task_struct; -struct list_head; -struct llist_node;
#ifdef CONFIG_IMA extern int ima_bprm_check(struct linux_binprm *bprm); @@ -208,10 +206,6 @@ struct ima_namespace { struct ns_common ns; struct ucounts *ucounts; struct user_namespace *user_ns; - struct list_head list; - struct llist_node cleanup_list; /* namespaces on a death row */ - atomic_t inactive; /* set only when ns is added to the cleanup list */ - bool frozen; } __randomize_layout;
extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 86e3499b3523..edfdb1f0835d 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -363,23 +363,12 @@ static inline enum integrity_status ima_get_cache_status(struct integrity_iint_c
#endif /* CONFIG_IMA_APPRAISE */
-extern struct list_head ima_ns_list; -extern struct rw_semaphore ima_ns_list_lock; - #ifdef CONFIG_IMA_NS -int __init ima_init_namespace(void); - static inline struct ima_namespace *get_current_ns(void) { return current->nsproxy->ima_ns; } #else -static inline int __init ima_init_namespace(void) -{ - list_add_tail(&init_ima_ns.list, &ima_ns_list); - return 0; -} - static inline struct ima_namespace *get_current_ns(void) { return &init_ima_ns; diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 2238fb21eaf0..b1c341e239a8 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -32,7 +32,6 @@ struct ima_namespace init_ima_ns = { #ifdef CONFIG_IMA_NS .ns.ops = &imans_operations, #endif - .frozen = true }; EXPORT_SYMBOL(init_ima_ns);
@@ -159,10 +158,6 @@ int __init ima_init(void)
ima_init_policy();
- rc = ima_init_namespace(); - if (rc != 0) - return rc; - rc = ima_fs_init(); if (rc != 0) return rc; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 5fd890c85413..999d5904cce0 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -47,9 +47,6 @@ bool ima_plus_standard_pcr;
static int hash_setup_done;
-DECLARE_RWSEM(ima_ns_list_lock); -LIST_HEAD(ima_ns_list); - static struct notifier_block ima_lsm_policy_notifier = { .notifier_call = ima_lsm_policy_change, }; diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 3a98cd536d05..8f5f301406a2 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -21,20 +21,9 @@ #include <linux/user_namespace.h> #include <linux/nsproxy.h> #include <linux/sched.h> -#include <linux/list.h> -#include <linux/llist.h> -#include <linux/rwsem.h> -#include <linux/workqueue.h> -#include <linux/mutex.h>
#include "ima.h"
-static LLIST_HEAD(cleanup_list); -static struct workqueue_struct *imans_wq; - -/* Protects tasks entering the same, not yet active namespace */ -static DEFINE_MUTEX(frozen_lock); - static struct ucounts *inc_ima_namespaces(struct user_namespace *ns) { return inc_ucount(ns, current_euid(), UCOUNT_IMA_NAMESPACES); @@ -89,7 +78,6 @@ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, ns->ns.ops = &imans_operations; ns->user_ns = get_user_ns(user_ns); ns->ucounts = ucounts; - ns->frozen = false;
return ns;
@@ -121,19 +109,6 @@ struct ima_namespace *copy_ima_ns(unsigned long flags, return clone_ima_ns(user_ns, old_ns); }
-int __init ima_init_namespace(void) -{ - /* Create workqueue for cleanup */ - imans_wq = create_singlethread_workqueue("imans"); - if (unlikely(!imans_wq)) - return -ENOMEM; - - /* No other reader or writer at this stage */ - list_add_tail(&init_ima_ns.list, &ima_ns_list); - - return 0; -} - static void destroy_ima_ns(struct ima_namespace *ns) { dec_ima_namespaces(ns->ucounts); @@ -142,46 +117,13 @@ static void destroy_ima_ns(struct ima_namespace *ns) kfree(ns); }
-static void cleanup_ima(struct work_struct *work) -{ - struct ima_namespace *ima_ns, *tmp; - struct llist_node *ima_kill_list; - - /* Atomically snapshot the list of namespaces to cleanup */ - ima_kill_list = llist_del_all(&cleanup_list); - - /* Remove ima namespace from the namespace list */ - down_write(&ima_ns_list_lock); - llist_for_each_entry(ima_ns, ima_kill_list, cleanup_list) - list_del(&ima_ns->list); - up_write(&ima_ns_list_lock); - - /* After removing ima namespace from the ima_ns_list, memory can be - * freed. At this stage nothing should keep a reference to the given - * namespace. - */ - llist_for_each_entry_safe(ima_ns, tmp, ima_kill_list, cleanup_list) - destroy_ima_ns(ima_ns); -} - -static DECLARE_WORK(ima_cleanup_work, cleanup_ima); - void free_ima_ns(struct kref *kref) { - struct ima_namespace *ima_ns; + struct ima_namespace *ns;
- ima_ns = container_of(kref, struct ima_namespace, kref); - /* Namespace can be destroyed instantly if no process ever was born - * into it - it was never added to the ima_ns_list. - */ - if (!ima_ns->frozen) { - destroy_ima_ns(ima_ns); - return; - } + ns = container_of(kref, struct ima_namespace, kref);
- atomic_set(&ima_ns->inactive, 1); - if (llist_add(&ima_ns->cleanup_list, &cleanup_list)) - queue_work(imans_wq, &ima_cleanup_work); + destroy_ima_ns(ns); }
static inline struct ima_namespace *to_ima_ns(struct ns_common *ns) @@ -226,32 +168,8 @@ static void imans_put(struct ns_common *ns) put_ima_ns(to_ima_ns(ns)); }
-static int imans_activate(struct ima_namespace *ima_ns) -{ - if (ima_ns == &init_ima_ns) - return 0; - - if (ima_ns->frozen) - return 0; - - mutex_lock(&frozen_lock); - if (ima_ns->frozen) - goto out; - - ima_ns->frozen = true; - - down_write(&ima_ns_list_lock); - list_add_tail(&ima_ns->list, &ima_ns_list); - up_write(&ima_ns_list_lock); -out: - mutex_unlock(&frozen_lock); - - return 0; -} - static int imans_install(struct nsset *nsset, struct ns_common *new) { - int res; struct nsproxy *nsproxy = nsset->nsproxy; struct ima_namespace *ns = to_ima_ns(new);
@@ -262,10 +180,6 @@ static int imans_install(struct nsset *nsset, struct ns_common *new) !ns_capable(nsset->cred->user_ns, CAP_SYS_ADMIN)) return -EPERM;
- res = imans_activate(ns); - if (res) - return res; - get_ima_ns(ns); put_ima_ns(nsproxy->ima_ns); nsproxy->ima_ns = ns; @@ -274,12 +188,11 @@ static int imans_install(struct nsset *nsset, struct ns_common *new) put_ima_ns(nsproxy->ima_ns_for_children); nsproxy->ima_ns_for_children = ns;
- return res; + return 0; }
int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk) { - int res; struct ns_common *nsc = &nsproxy->ima_ns_for_children->ns; struct ima_namespace *ns = to_ima_ns(nsc);
@@ -287,15 +200,11 @@ int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk) if (nsproxy->ima_ns == nsproxy->ima_ns_for_children) return 0;
- res = imans_activate(ns); - if (res) - return res; - get_ima_ns(ns); put_ima_ns(nsproxy->ima_ns); nsproxy->ima_ns = ns;
- return res; + return 0; }
static struct user_namespace *imans_owner(struct ns_common *ns)
From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit a8352473e0aa18693cd0a911beab237cb2d396b9.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- fs/proc/namespaces.c | 4 - include/linux/ima.h | 57 -------- include/linux/nsproxy.h | 3 - include/linux/proc_ns.h | 5 +- include/linux/user_namespace.h | 1 - include/uapi/linux/sched.h | 1 - init/Kconfig | 12 -- kernel/fork.c | 24 +--- kernel/nsproxy.c | 42 +----- kernel/ucount.c | 1 - security/integrity/ima/Makefile | 1 - security/integrity/ima/ima.h | 13 -- security/integrity/ima/ima_fs.c | 4 +- security/integrity/ima/ima_init.c | 13 -- security/integrity/ima/ima_ns.c | 232 ------------------------------ 15 files changed, 11 insertions(+), 402 deletions(-) delete mode 100644 security/integrity/ima/ima_ns.c
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c index 117812a59e5d..8e159fc78c0a 100644 --- a/fs/proc/namespaces.c +++ b/fs/proc/namespaces.c @@ -37,10 +37,6 @@ static const struct proc_ns_operations *ns_entries[] = { &timens_operations, &timens_for_children_operations, #endif -#ifdef CONFIG_IMA_NS - &imans_operations, - &imans_for_children_operations, -#endif };
static const char *proc_ns_get_link(struct dentry *dentry, diff --git a/include/linux/ima.h b/include/linux/ima.h index 67af79961e4e..f7a088b2579e 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -13,9 +13,6 @@ #include <linux/kexec.h> struct linux_binprm;
-struct nsproxy; -struct task_struct; - #ifdef CONFIG_IMA extern int ima_bprm_check(struct linux_binprm *bprm); extern int ima_file_check(struct file *file, int mask); @@ -200,58 +197,4 @@ static inline bool ima_appraise_signature(enum kernel_read_file_id func) return false; } #endif /* CONFIG_IMA_APPRAISE && CONFIG_INTEGRITY_TRUSTED_KEYRING */ - -struct ima_namespace { - struct kref kref; - struct ns_common ns; - struct ucounts *ucounts; - struct user_namespace *user_ns; -} __randomize_layout; - -extern struct ima_namespace init_ima_ns; - -#ifdef CONFIG_IMA_NS -struct ima_namespace *copy_ima_ns(unsigned long flags, - struct user_namespace *user_ns, - struct ima_namespace *old_ns); - -void free_ima_ns(struct kref *kref); - -int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk); - -static inline struct ima_namespace *get_ima_ns(struct ima_namespace *ns) -{ - if (ns) - kref_get(&ns->kref); - return ns; -} -static inline void put_ima_ns(struct ima_namespace *ns) -{ - if (ns) - kref_put(&ns->kref, free_ima_ns); -} - -#else -static inline struct ima_namespace *copy_ima_ns(unsigned long flags, - struct user_namespace *user_ns, - struct ima_namespace *old_ns) -{ - return old_ns; -} - -static inline int imans_on_fork(struct nsproxy *nsproxy, - struct task_struct *tsk) -{ - return 0; -} - -static inline struct ima_namespace *get_ima_ns(struct ima_namespace *ns) -{ - return ns; -} - -static inline void put_ima_ns(struct ima_namespace *ns) -{ -} -#endif /* CONFIG_IMA_NS */ #endif /* _LINUX_IMA_H */ diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h index 56216a94009d..cdb171efc7cb 100644 --- a/include/linux/nsproxy.h +++ b/include/linux/nsproxy.h @@ -10,7 +10,6 @@ struct uts_namespace; struct ipc_namespace; struct pid_namespace; struct cgroup_namespace; -struct ima_namespace; struct fs_struct;
/* @@ -39,8 +38,6 @@ struct nsproxy { struct time_namespace *time_ns; struct time_namespace *time_ns_for_children; struct cgroup_namespace *cgroup_ns; - struct ima_namespace *ima_ns; - struct ima_namespace *ima_ns_for_children; }; extern struct nsproxy init_nsproxy;
diff --git a/include/linux/proc_ns.h b/include/linux/proc_ns.h index c8c596d67629..75807ecef880 100644 --- a/include/linux/proc_ns.h +++ b/include/linux/proc_ns.h @@ -16,7 +16,7 @@ struct inode; struct proc_ns_operations { const char *name; const char *real_ns_name; - uint64_t type; + int type; struct ns_common *(*get)(struct task_struct *task); void (*put)(struct ns_common *ns); int (*install)(struct nsset *nsset, struct ns_common *ns); @@ -34,8 +34,6 @@ extern const struct proc_ns_operations mntns_operations; extern const struct proc_ns_operations cgroupns_operations; extern const struct proc_ns_operations timens_operations; extern const struct proc_ns_operations timens_for_children_operations; -extern const struct proc_ns_operations imans_operations; -extern const struct proc_ns_operations imans_for_children_operations;
/* * We always define these enumerators @@ -48,7 +46,6 @@ enum { PROC_PID_INIT_INO = 0xEFFFFFFCU, PROC_CGROUP_INIT_INO = 0xEFFFFFFBU, PROC_TIME_INIT_INO = 0xEFFFFFFAU, - PROC_IMA_INIT_INO = 0xEFFFFFF9U, };
#ifdef CONFIG_PROC_FS diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 3eb64a50f248..7616c7bf4b24 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -46,7 +46,6 @@ enum ucount_type { UCOUNT_MNT_NAMESPACES, UCOUNT_CGROUP_NAMESPACES, UCOUNT_TIME_NAMESPACES, - UCOUNT_IMA_NAMESPACES, #ifdef CONFIG_INOTIFY_USER UCOUNT_INOTIFY_INSTANCES, UCOUNT_INOTIFY_WATCHES, diff --git a/include/uapi/linux/sched.h b/include/uapi/linux/sched.h index b30e27efee92..3bac0a8ceab2 100644 --- a/include/uapi/linux/sched.h +++ b/include/uapi/linux/sched.h @@ -36,7 +36,6 @@ /* Flags for the clone3() syscall. */ #define CLONE_CLEAR_SIGHAND 0x100000000ULL /* Clear any signal handler and reset to SIG_DFL. */ #define CLONE_INTO_CGROUP 0x200000000ULL /* Clone into a specific cgroup given the right permissions. */ -#define CLONE_NEWIMA 0x400000000ULL /* New IMA namespace. */
/* * cloning flags intersect with CSIGNAL so can be used with unshare and clone3 diff --git a/init/Kconfig b/init/Kconfig index 310082cd88fe..6d2f69cafe15 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1226,18 +1226,6 @@ config NET_NS Allow user space to create what appear to be multiple instances of the network stack.
-config IMA_NS - bool "IMA namespace" - depends on IMA - default n - help - This allows container engines to use ima namespaces to provide - different IMA policy rules for different containers. Also, it allows - to create what appear to be multiple instances of the IMA measurement - list and other IMA related resources. - - If unsure, say N. - endif # NAMESPACES
config SCHED_STEAL diff --git a/kernel/fork.c b/kernel/fork.c index 6417b818b3a1..d730b57c9c22 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1924,24 +1924,11 @@ static __latent_entropy struct task_struct *copy_process( }
/* - * If the new process will be in a different time namespace or a - * different ima namespace, do not allow it to share VM or a thread - * group with the forking task. + * If the new process will be in a different time namespace + * do not allow it to share VM or a thread group with the forking task. */ if (clone_flags & (CLONE_THREAD | CLONE_VM)) { - if ((nsp->time_ns != nsp->time_ns_for_children) || - ((clone_flags & CLONE_NEWIMA) || - (nsp->ima_ns != nsp->ima_ns_for_children))) - return ERR_PTR(-EINVAL); - } - - /* - * If the new process will be in a different ima namespace - * do not allow it to share the same file descriptor table. - */ - if (clone_flags & CLONE_FILES) { - if ((clone_flags & CLONE_NEWIMA) || - (nsp->ima_ns != nsp->ima_ns_for_children)) + if (nsp->time_ns != nsp->time_ns_for_children) return ERR_PTR(-EINVAL); }
@@ -2720,8 +2707,7 @@ static bool clone3_args_valid(struct kernel_clone_args *kargs) { /* Verify that no unknown flags are passed along. */ if (kargs->flags & - ~(CLONE_LEGACY_FLAGS | - CLONE_CLEAR_SIGHAND | CLONE_INTO_CGROUP | CLONE_NEWIMA)) + ~(CLONE_LEGACY_FLAGS | CLONE_CLEAR_SIGHAND | CLONE_INTO_CGROUP)) return false;
/* @@ -2868,7 +2854,7 @@ static int check_unshare_flags(unsigned long unshare_flags) CLONE_VM|CLONE_FILES|CLONE_SYSVSEM| CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET| CLONE_NEWUSER|CLONE_NEWPID|CLONE_NEWCGROUP| - CLONE_NEWTIME|CLONE_NEWIMA)) + CLONE_NEWTIME)) return -EINVAL; /* * Not implemented, but pretend it works if there is nothing diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index 22b24123d524..3d5a5faf91b5 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c @@ -19,7 +19,6 @@ #include <net/net_namespace.h> #include <linux/ipc_namespace.h> #include <linux/time_namespace.h> -#include <linux/ima.h> #include <linux/fs_struct.h> #include <linux/proc_fs.h> #include <linux/proc_ns.h> @@ -48,10 +47,6 @@ struct nsproxy init_nsproxy = { .time_ns = &init_time_ns, .time_ns_for_children = &init_time_ns, #endif -#ifdef CONFIG_IMA_NS - .ima_ns = &init_ima_ns, - .ima_ns_for_children = &init_ima_ns, -#endif };
static inline struct nsproxy *create_nsproxy(void) @@ -126,19 +121,8 @@ static struct nsproxy *create_new_namespaces(unsigned long flags, } new_nsp->time_ns = get_time_ns(tsk->nsproxy->time_ns);
- new_nsp->ima_ns_for_children = copy_ima_ns(flags, user_ns, - tsk->nsproxy->ima_ns_for_children); - if (IS_ERR(new_nsp->ima_ns_for_children)) { - err = PTR_ERR(new_nsp->ima_ns_for_children); - goto out_ima; - } - new_nsp->ima_ns = get_ima_ns(tsk->nsproxy->ima_ns); - return new_nsp;
-out_ima: - put_time_ns(new_nsp->time_ns); - put_time_ns(new_nsp->time_ns_for_children); out_time: put_net(new_nsp->net_ns); out_net: @@ -173,10 +157,8 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNET | - CLONE_NEWCGROUP | CLONE_NEWTIME | - CLONE_NEWIMA)))) { - if (likely((old_ns->time_ns_for_children == old_ns->time_ns) && - (old_ns->ima_ns_for_children == old_ns->ima_ns))) { + CLONE_NEWCGROUP | CLONE_NEWTIME)))) { + if (likely(old_ns->time_ns_for_children == old_ns->time_ns)) { get_nsproxy(old_ns); return 0; } @@ -204,12 +186,6 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk) return ret; }
- ret = imans_on_fork(new_ns, tsk); - if (ret) { - free_nsproxy(new_ns); - return ret; - } - tsk->nsproxy = new_ns; return 0; } @@ -228,10 +204,6 @@ void free_nsproxy(struct nsproxy *ns) put_time_ns(ns->time_ns); if (ns->time_ns_for_children) put_time_ns(ns->time_ns_for_children); - if (ns->ima_ns) - put_ima_ns(ns->ima_ns); - if (ns->ima_ns_for_children) - put_ima_ns(ns->ima_ns_for_children); put_cgroup_ns(ns->cgroup_ns); put_net(ns->net_ns); kmem_cache_free(nsproxy_cachep, ns); @@ -249,7 +221,7 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags,
if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWNET | CLONE_NEWPID | CLONE_NEWCGROUP | - CLONE_NEWTIME | CLONE_NEWIMA))) + CLONE_NEWTIME))) return 0;
user_ns = new_cred ? new_cred->user_ns : current_user_ns(); @@ -504,14 +476,6 @@ static int validate_nsset(struct nsset *nsset, struct pid *pid) } #endif
-#ifdef CONFIG_IMA_NS - if (flags & CLONE_NEWIMA) { - ret = validate_ns(nsset, &nsp->ima_ns->ns); - if (ret) - goto out; - } -#endif - out: if (pid_ns) put_pid_ns(pid_ns); diff --git a/kernel/ucount.c b/kernel/ucount.c index 3f4768d62b8f..11b1596e2542 100644 --- a/kernel/ucount.c +++ b/kernel/ucount.c @@ -70,7 +70,6 @@ static struct ctl_table user_table[] = { UCOUNT_ENTRY("max_mnt_namespaces"), UCOUNT_ENTRY("max_cgroup_namespaces"), UCOUNT_ENTRY("max_time_namespaces"), - UCOUNT_ENTRY("max_ima_namespaces"), #ifdef CONFIG_INOTIFY_USER UCOUNT_ENTRY("max_inotify_instances"), UCOUNT_ENTRY("max_inotify_watches"), diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index 7c7272b8df65..9dda78739c85 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -15,4 +15,3 @@ ima-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o ima-$(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) += ima_asymmetric_keys.o ima-$(CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS) += ima_queue_keys.o ima-$(CONFIG_IMA_DIGEST_LIST) += ima_digest_list.o -ima-$(CONFIG_IMA_NS) += ima_ns.o diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index edfdb1f0835d..46afb6bef45b 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -20,7 +20,6 @@ #include <linux/hash.h> #include <linux/tpm.h> #include <linux/audit.h> -#include <linux/ima.h> #include <crypto/hash_info.h>
#include "../integrity.h" @@ -363,18 +362,6 @@ static inline enum integrity_status ima_get_cache_status(struct integrity_iint_c
#endif /* CONFIG_IMA_APPRAISE */
-#ifdef CONFIG_IMA_NS -static inline struct ima_namespace *get_current_ns(void) -{ - return current->nsproxy->ima_ns; -} -#else -static inline struct ima_namespace *get_current_ns(void) -{ - return &init_ima_ns; -} -#endif /* CONFIG_IMA_NS */ - #ifdef CONFIG_IMA_APPRAISE_MODSIG int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, struct modsig **modsig); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 90f1d9c85b31..ecdeab23f022 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -275,7 +275,7 @@ static const struct file_operations ima_ascii_measurements_ops = { .release = seq_release, };
-static ssize_t ima_read_sfs_file(char *path, struct dentry *dentry) +static ssize_t ima_read_file(char *path, struct dentry *dentry) { void *data = NULL; char *datap; @@ -402,7 +402,7 @@ static ssize_t ima_write_data(struct file *file, const char __user *buf, goto out_free;
if (data[0] == '/') { - result = ima_read_sfs_file(data, dentry); + result = ima_read_file(data, dentry); } else if (dentry == ima_policy) { if (ima_appraise & IMA_APPRAISE_POLICY) { pr_err("signed policy file (specified " diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index b1c341e239a8..913d6b879b0b 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -15,9 +15,6 @@ #include <linux/scatterlist.h> #include <linux/slab.h> #include <linux/err.h> -#include <linux/kref.h> -#include <linux/proc_ns.h> -#include <linux/user_namespace.h>
#include "ima.h"
@@ -25,16 +22,6 @@ const char boot_aggregate_name[] = "boot_aggregate"; struct tpm_chip *ima_tpm_chip;
-struct ima_namespace init_ima_ns = { - .kref = KREF_INIT(2), - .user_ns = &init_user_ns, - .ns.inum = PROC_IMA_INIT_INO, -#ifdef CONFIG_IMA_NS - .ns.ops = &imans_operations, -#endif -}; -EXPORT_SYMBOL(init_ima_ns); - /* Add the boot aggregate to the IMA measurement list and extend * the PCR register. * diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c deleted file mode 100644 index 8f5f301406a2..000000000000 --- a/security/integrity/ima/ima_ns.c +++ /dev/null @@ -1,232 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2019-2020 Huawei Technologies Duesseldorf GmbH - * - * Author: Krzysztof Struczynski krzysztof.struczynski@huawei.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2 of the - * License. - * - * File: ima_ns.c - * Functions to manage the IMA namespace. - */ - -#include <linux/export.h> -#include <linux/ima.h> -#include <linux/kref.h> -#include <linux/proc_ns.h> -#include <linux/slab.h> -#include <linux/user_namespace.h> -#include <linux/nsproxy.h> -#include <linux/sched.h> - -#include "ima.h" - -static struct ucounts *inc_ima_namespaces(struct user_namespace *ns) -{ - return inc_ucount(ns, current_euid(), UCOUNT_IMA_NAMESPACES); -} - -static void dec_ima_namespaces(struct ucounts *ucounts) -{ - return dec_ucount(ucounts, UCOUNT_IMA_NAMESPACES); -} - -static struct ima_namespace *ima_ns_alloc(void) -{ - struct ima_namespace *ima_ns; - - ima_ns = kzalloc(sizeof(*ima_ns), GFP_KERNEL); - if (!ima_ns) - return NULL; - - return ima_ns; -} - -/** - * Clone a new ns copying an original ima namespace, setting refcount to 1 - * - * @user_ns: User namespace that current task runs in - * @old_ns: Old ima namespace to clone - * Return: ERR_PTR(-ENOMEM) on error (failure to kmalloc), new ns otherwise - */ -static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, - struct ima_namespace *old_ns) -{ - struct ima_namespace *ns; - struct ucounts *ucounts; - int err; - - err = -ENOSPC; - ucounts = inc_ima_namespaces(user_ns); - if (!ucounts) - goto fail; - - err = -ENOMEM; - ns = ima_ns_alloc(); - if (!ns) - goto fail_dec; - - kref_init(&ns->kref); - - err = ns_alloc_inum(&ns->ns); - if (err) - goto fail_free; - - ns->ns.ops = &imans_operations; - ns->user_ns = get_user_ns(user_ns); - ns->ucounts = ucounts; - - return ns; - -fail_free: - kfree(ns); -fail_dec: - dec_ima_namespaces(ucounts); -fail: - return ERR_PTR(err); -} - -/** - * Copy task's ima namespace, or clone it if flags specifies CLONE_NEWNS. - * - * @flags: Cloning flags - * @user_ns: User namespace that current task runs in - * @old_ns: Old ima namespace to clone - * - * Return: IMA namespace or ERR_PTR. - */ - -struct ima_namespace *copy_ima_ns(unsigned long flags, - struct user_namespace *user_ns, - struct ima_namespace *old_ns) -{ - if (!(flags & CLONE_NEWIMA)) - return get_ima_ns(old_ns); - - return clone_ima_ns(user_ns, old_ns); -} - -static void destroy_ima_ns(struct ima_namespace *ns) -{ - dec_ima_namespaces(ns->ucounts); - put_user_ns(ns->user_ns); - ns_free_inum(&ns->ns); - kfree(ns); -} - -void free_ima_ns(struct kref *kref) -{ - struct ima_namespace *ns; - - ns = container_of(kref, struct ima_namespace, kref); - - destroy_ima_ns(ns); -} - -static inline struct ima_namespace *to_ima_ns(struct ns_common *ns) -{ - return container_of(ns, struct ima_namespace, ns); -} - -static struct ns_common *imans_get(struct task_struct *task) -{ - struct ima_namespace *ns = NULL; - struct nsproxy *nsproxy; - - task_lock(task); - nsproxy = task->nsproxy; - if (nsproxy) { - ns = nsproxy->ima_ns; - get_ima_ns(ns); - } - task_unlock(task); - - return ns ? &ns->ns : NULL; -} - -static struct ns_common *imans_for_children_get(struct task_struct *task) -{ - struct ima_namespace *ns = NULL; - struct nsproxy *nsproxy; - - task_lock(task); - nsproxy = task->nsproxy; - if (nsproxy) { - ns = nsproxy->ima_ns_for_children; - get_ima_ns(ns); - } - task_unlock(task); - - return ns ? &ns->ns : NULL; -} - -static void imans_put(struct ns_common *ns) -{ - put_ima_ns(to_ima_ns(ns)); -} - -static int imans_install(struct nsset *nsset, struct ns_common *new) -{ - struct nsproxy *nsproxy = nsset->nsproxy; - struct ima_namespace *ns = to_ima_ns(new); - - if (!current_is_single_threaded()) - return -EUSERS; - - if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) || - !ns_capable(nsset->cred->user_ns, CAP_SYS_ADMIN)) - return -EPERM; - - get_ima_ns(ns); - put_ima_ns(nsproxy->ima_ns); - nsproxy->ima_ns = ns; - - get_ima_ns(ns); - put_ima_ns(nsproxy->ima_ns_for_children); - nsproxy->ima_ns_for_children = ns; - - return 0; -} - -int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk) -{ - struct ns_common *nsc = &nsproxy->ima_ns_for_children->ns; - struct ima_namespace *ns = to_ima_ns(nsc); - - /* create_new_namespaces() already incremented the ref counter */ - if (nsproxy->ima_ns == nsproxy->ima_ns_for_children) - return 0; - - get_ima_ns(ns); - put_ima_ns(nsproxy->ima_ns); - nsproxy->ima_ns = ns; - - return 0; -} - -static struct user_namespace *imans_owner(struct ns_common *ns) -{ - return to_ima_ns(ns)->user_ns; -} - -const struct proc_ns_operations imans_operations = { - .name = "ima", - .type = CLONE_NEWIMA, - .get = imans_get, - .put = imans_put, - .install = imans_install, - .owner = imans_owner, -}; - -const struct proc_ns_operations imans_for_children_operations = { - .name = "ima_for_children", - .type = CLONE_NEWIMA, - .get = imans_for_children_get, - .put = imans_put, - .install = imans_install, - .owner = imans_owner, -}; -
From: Victor Ding victording@google.com
mainline inclusion from mainline-5.16-rc7 commit 298ed2b31f55280624417f80a09de0e28db8f786 category: feature feature: milan cpu bugzilla: https://gitee.com/openeuler/kernel/issues/I4NX57 CVE: NA
--------------------------------
MSRs in the rest of this file are sorted by their addresses; fixing the two outliers.
No functional changes.
Signed-off-by: Victor Ding victording@google.com Acked-by: Kim Phillips kim.phillips@amd.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: qinyu qinyu16@huawei.com Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/x86/include/asm/msr-index.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 972a34d93505..21917e134ad4 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -326,8 +326,8 @@ #define MSR_PP1_ENERGY_STATUS 0x00000641 #define MSR_PP1_POLICY 0x00000642
-#define MSR_AMD_PKG_ENERGY_STATUS 0xc001029b #define MSR_AMD_RAPL_POWER_UNIT 0xc0010299 +#define MSR_AMD_PKG_ENERGY_STATUS 0xc001029b
/* Config TDP MSRs */ #define MSR_CONFIG_TDP_NOMINAL 0x00000648
From: Victor Ding victording@google.com
mainline inclusion from mainline-5.16-rc6 commit a2c32fa736a590a7ab6e9601066a6772ae09869b category: feature feature: milan cpu bugzilla: https://gitee.com/openeuler/kernel/issues/I4NX57 CVE: NA
--------------------------------
Changes the static struct rapl_msr_priv to a pointer to allow using a different RAPL MSR interface, preparing for supporting AMD's RAPL MSR interface.
No functional changes.
Signed-off-by: Victor Ding victording@google.com Acked-by: Kim Phillips kim.phillips@amd.com [ rjw: Changelog edits ] Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: qinyu qinyu16@huawei.com Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Reviewed-by: Chao Liu liuchao173@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/powercap/intel_rapl_msr.c | 33 +++++++++++++++++-------------- 1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/drivers/powercap/intel_rapl_msr.c b/drivers/powercap/intel_rapl_msr.c index 1646808d354c..a819b3b89b2f 100644 --- a/drivers/powercap/intel_rapl_msr.c +++ b/drivers/powercap/intel_rapl_msr.c @@ -31,7 +31,9 @@ #define MSR_VR_CURRENT_CONFIG 0x00000601
/* private data for RAPL MSR Interface */ -static struct rapl_if_priv rapl_msr_priv = { +static struct rapl_if_priv *rapl_msr_priv; + +static struct rapl_if_priv rapl_msr_priv_intel = { .reg_unit = MSR_RAPL_POWER_UNIT, .regs[RAPL_DOMAIN_PACKAGE] = { MSR_PKG_POWER_LIMIT, MSR_PKG_ENERGY_STATUS, MSR_PKG_PERF_STATUS, 0, MSR_PKG_POWER_INFO }, @@ -58,9 +60,9 @@ static int rapl_cpu_online(unsigned int cpu) { struct rapl_package *rp;
- rp = rapl_find_package_domain(cpu, &rapl_msr_priv); + rp = rapl_find_package_domain(cpu, rapl_msr_priv); if (!rp) { - rp = rapl_add_package(cpu, &rapl_msr_priv); + rp = rapl_add_package(cpu, rapl_msr_priv); if (IS_ERR(rp)) return PTR_ERR(rp); } @@ -73,7 +75,7 @@ static int rapl_cpu_down_prep(unsigned int cpu) struct rapl_package *rp; int lead_cpu;
- rp = rapl_find_package_domain(cpu, &rapl_msr_priv); + rp = rapl_find_package_domain(cpu, rapl_msr_priv); if (!rp) return 0;
@@ -136,40 +138,41 @@ static int rapl_msr_probe(struct platform_device *pdev) const struct x86_cpu_id *id = x86_match_cpu(pl4_support_ids); int ret;
- rapl_msr_priv.read_raw = rapl_msr_read_raw; - rapl_msr_priv.write_raw = rapl_msr_write_raw; + rapl_msr_priv = &rapl_msr_priv_intel; + rapl_msr_priv->read_raw = rapl_msr_read_raw; + rapl_msr_priv->write_raw = rapl_msr_write_raw;
if (id) { - rapl_msr_priv.limits[RAPL_DOMAIN_PACKAGE] = 3; - rapl_msr_priv.regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4] = + rapl_msr_priv->limits[RAPL_DOMAIN_PACKAGE] = 3; + rapl_msr_priv->regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4] = MSR_VR_CURRENT_CONFIG; pr_info("PL4 support detected.\n"); }
- rapl_msr_priv.control_type = powercap_register_control_type(NULL, "intel-rapl", NULL); - if (IS_ERR(rapl_msr_priv.control_type)) { + rapl_msr_priv->control_type = powercap_register_control_type(NULL, "intel-rapl", NULL); + if (IS_ERR(rapl_msr_priv->control_type)) { pr_debug("failed to register powercap control_type.\n"); - return PTR_ERR(rapl_msr_priv.control_type); + return PTR_ERR(rapl_msr_priv->control_type); }
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powercap/rapl:online", rapl_cpu_online, rapl_cpu_down_prep); if (ret < 0) goto out; - rapl_msr_priv.pcap_rapl_online = ret; + rapl_msr_priv->pcap_rapl_online = ret;
return 0;
out: if (ret) - powercap_unregister_control_type(rapl_msr_priv.control_type); + powercap_unregister_control_type(rapl_msr_priv->control_type); return ret; }
static int rapl_msr_remove(struct platform_device *pdev) { - cpuhp_remove_state(rapl_msr_priv.pcap_rapl_online); - powercap_unregister_control_type(rapl_msr_priv.control_type); + cpuhp_remove_state(rapl_msr_priv->pcap_rapl_online); + powercap_unregister_control_type(rapl_msr_priv->control_type); return 0; }
From: Victor Ding victording@google.com
mainline inclusion from mainline-5.16-rc6 commit 43756a298928c9a4e8201baaeb205c0c103728af category: feature feature: milan cpu bugzilla: https://gitee.com/openeuler/kernel/issues/I4NX57 CVE: NA
--------------------------------
Enable AMD Fam17h RAPL support for the power capping framework.
The support is as per AMD Fam17h Model31h (Zen2) and model 00-ffh (Zen1) PPR.
Tested by comparing the results of following two sysfs entries and the values directly read from corresponding MSRs via /dev/cpu/[x]/msr: /sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj /sys/class/powercap/intel-rapl/intel-rapl:0/intel-rapl:0:0/energy_uj
Signed-off-by: Victor Ding victording@google.com Acked-by: Kim Phillips kim.phillips@amd.com [ rjw: Changelog edits ] Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: qinyu qinyu16@huawei.com Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/x86/include/asm/msr-index.h | 1 + drivers/powercap/intel_rapl_common.c | 6 ++++++ drivers/powercap/intel_rapl_msr.c | 20 +++++++++++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 21917e134ad4..c36a083c8ec0 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -327,6 +327,7 @@ #define MSR_PP1_POLICY 0x00000642
#define MSR_AMD_RAPL_POWER_UNIT 0xc0010299 +#define MSR_AMD_CORE_ENERGY_STATUS 0xc001029a #define MSR_AMD_PKG_ENERGY_STATUS 0xc001029b
/* Config TDP MSRs */ diff --git a/drivers/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c index 70d6d52bc1e2..1ecd09424445 100644 --- a/drivers/powercap/intel_rapl_common.c +++ b/drivers/powercap/intel_rapl_common.c @@ -1011,6 +1011,10 @@ static const struct rapl_defaults rapl_defaults_cht = { .compute_time_window = rapl_compute_time_window_atom, };
+static const struct rapl_defaults rapl_defaults_amd = { + .check_unit = rapl_check_unit_core, +}; + static const struct x86_cpu_id rapl_ids[] __initconst = { X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE, &rapl_defaults_core), X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X, &rapl_defaults_core), @@ -1061,6 +1065,8 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, &rapl_defaults_hsw_server), X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, &rapl_defaults_hsw_server), + + X86_MATCH_VENDOR_FAM(AMD, 0x17, &rapl_defaults_amd), {} }; MODULE_DEVICE_TABLE(x86cpu, rapl_ids); diff --git a/drivers/powercap/intel_rapl_msr.c b/drivers/powercap/intel_rapl_msr.c index a819b3b89b2f..78213d4b5b16 100644 --- a/drivers/powercap/intel_rapl_msr.c +++ b/drivers/powercap/intel_rapl_msr.c @@ -49,6 +49,14 @@ static struct rapl_if_priv rapl_msr_priv_intel = { .limits[RAPL_DOMAIN_PLATFORM] = 2, };
+static struct rapl_if_priv rapl_msr_priv_amd = { + .reg_unit = MSR_AMD_RAPL_POWER_UNIT, + .regs[RAPL_DOMAIN_PACKAGE] = { + 0, MSR_AMD_PKG_ENERGY_STATUS, 0, 0, 0 }, + .regs[RAPL_DOMAIN_PP0] = { + 0, MSR_AMD_CORE_ENERGY_STATUS, 0, 0, 0 }, +}; + /* Handles CPU hotplug on multi-socket systems. * If a CPU goes online as the first CPU of the physical package * we add the RAPL package to the system. Similarly, when the last @@ -138,7 +146,17 @@ static int rapl_msr_probe(struct platform_device *pdev) const struct x86_cpu_id *id = x86_match_cpu(pl4_support_ids); int ret;
- rapl_msr_priv = &rapl_msr_priv_intel; + switch (boot_cpu_data.x86_vendor) { + case X86_VENDOR_INTEL: + rapl_msr_priv = &rapl_msr_priv_intel; + break; + case X86_VENDOR_AMD: + rapl_msr_priv = &rapl_msr_priv_amd; + break; + default: + pr_err("intel-rapl does not support CPU vendor %d\n", boot_cpu_data.x86_vendor); + return -ENODEV; + } rapl_msr_priv->read_raw = rapl_msr_read_raw; rapl_msr_priv->write_raw = rapl_msr_write_raw;
From: Kim Phillips kim.phillips@amd.com
mainline inclusion from mainline-5.16-rc6 commit 8a9d881f22d7a0e06a46a326d0880fb45a06d3b5 category: feature feature: milan cpu bugzilla: https://gitee.com/openeuler/kernel/issues/I4NX57 CVE: NA
--------------------------------
AMD Family 19h's RAPL MSRs are identical to Family 17h's. Extend Family 17h's support to Family 19h.
Signed-off-by: Kim Phillips kim.phillips@amd.com Signed-off-by: Victor Ding victording@google.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: qinyu qinyu16@huawei.com Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/powercap/intel_rapl_common.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c index 1ecd09424445..c9e57237d778 100644 --- a/drivers/powercap/intel_rapl_common.c +++ b/drivers/powercap/intel_rapl_common.c @@ -1067,6 +1067,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = { X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, &rapl_defaults_hsw_server),
X86_MATCH_VENDOR_FAM(AMD, 0x17, &rapl_defaults_amd), + X86_MATCH_VENDOR_FAM(AMD, 0x19, &rapl_defaults_amd), {} }; MODULE_DEVICE_TABLE(x86cpu, rapl_ids);
From: Arnaldo Carvalho de Melo acme@redhat.com
mainline inclusion from mainline-5.16-rc6 commit e9bde94f1eb53c5721ba8e477dee837632fedebe category: feature feature: milan cpu bugzilla: https://gitee.com/openeuler/kernel/issues/I4NX57 CVE: NA
--------------------------------
To pick up the changes in:
d205e0f1426e0f99 ("x86/{cpufeatures,msr}: Add Intel SGX Launch Control hardware bits") e7b6385b01d8e9fb ("x86/cpufeatures: Add Intel SGX hardware bits") 43756a298928c9a4 ("powercap: Add AMD Fam17h RAPL support") 298ed2b31f552806 ("x86/msr-index: sort AMD RAPL MSRs by address") 68299a42f8428853 ("x86/mce: Enable additional error logging on certain Intel CPUs")
That cause these changes in tooling:
$ tools/perf/trace/beauty/tracepoints/x86_msr.sh > before $ cp arch/x86/include/asm/msr-index.h tools/arch/x86/include/asm/msr-index.h $ tools/perf/trace/beauty/tracepoints/x86_msr.sh > after $ diff -u before after --- before 2020-12-17 14:45:49.036994450 -0300 +++ after 2020-12-17 14:46:01.654256639 -0300 @@ -22,6 +22,10 @@ [0x00000060] = "LBR_CORE_TO", [0x00000079] = "IA32_UCODE_WRITE", [0x0000008b] = "IA32_UCODE_REV", + [0x0000008C] = "IA32_SGXLEPUBKEYHASH0", + [0x0000008D] = "IA32_SGXLEPUBKEYHASH1", + [0x0000008E] = "IA32_SGXLEPUBKEYHASH2", + [0x0000008F] = "IA32_SGXLEPUBKEYHASH3", [0x0000009b] = "IA32_SMM_MONITOR_CTL", [0x0000009e] = "IA32_SMBASE", [0x000000c1] = "IA32_PERFCTR0", @@ -59,6 +63,7 @@ [0x00000179] = "IA32_MCG_CAP", [0x0000017a] = "IA32_MCG_STATUS", [0x0000017b] = "IA32_MCG_CTL", + [0x0000017f] = "ERROR_CONTROL", [0x00000180] = "IA32_MCG_EAX", [0x00000181] = "IA32_MCG_EBX", [0x00000182] = "IA32_MCG_ECX", @@ -294,6 +299,7 @@ [0xc0010241 - x86_AMD_V_KVM_MSRs_offset] = "F15H_NB_PERF_CTR", [0xc0010280 - x86_AMD_V_KVM_MSRs_offset] = "F15H_PTSC", [0xc0010299 - x86_AMD_V_KVM_MSRs_offset] = "AMD_RAPL_POWER_UNIT", + [0xc001029a - x86_AMD_V_KVM_MSRs_offset] = "AMD_CORE_ENERGY_STATUS", [0xc001029b - x86_AMD_V_KVM_MSRs_offset] = "AMD_PKG_ENERGY_STATUS", [0xc00102f0 - x86_AMD_V_KVM_MSRs_offset] = "AMD_PPIN_CTL", [0xc00102f1 - x86_AMD_V_KVM_MSRs_offset] = "AMD_PPIN", $
Which causes these parts of tools/perf/ to be rebuilt:
CC /tmp/build/perf/trace/beauty/tracepoints/x86_msr.o LD /tmp/build/perf/trace/beauty/tracepoints/perf-in.o LD /tmp/build/perf/trace/beauty/perf-in.o LD /tmp/build/perf/perf-in.o LINK /tmp/build/perf/perf
At some point these should just be tables read by perf on demand.
This allows 'perf trace' users to use those strings to translate from the msr ids provided by the msr: tracepoints.
This addresses this perf tools build warning:
diff -u tools/arch/x86/include/asm/msr-index.h arch/x86/include/asm/msr-index.h Warning: Kernel ABI header at 'tools/arch/x86/include/asm/msr-index.h' differs from latest version at 'arch/x86/include/asm/msr-index.h'
Cc: Adrian Hunter adrian.hunter@intel.com Cc: Borislav Petkov bp@suse.de Cc: Ian Rogers irogers@google.com Cc: Jiri Olsa jolsa@kernel.org Cc: Namhyung Kim namhyung@kernel.org Cc: Rafael J. Wysocki rafael.j.wysocki@intel.com Cc: Sean Christopherson seanjc@google.com Cc: Tony Luck tony.luck@intel.com Cc: Victor Ding victording@google.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com
conflicts: following patches haven't been backported: d205e0f1426e0f99 ("x86/{cpufeatures,msr}: Add Intel SGX Launch Control hardware bits") e7b6385b01d8e9fb ("x86/cpufeatures: Add Intel SGX hardware bits") 68299a42f8428853 ("x86/mce: Enable additional error logging on certain Intel CPUs") so fixing code related to above patches in this patch is not applied.
Signed-off-by: qinyu qinyu16@huawei.com Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- tools/arch/x86/include/asm/msr-index.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/arch/x86/include/asm/msr-index.h b/tools/arch/x86/include/asm/msr-index.h index 972a34d93505..c36a083c8ec0 100644 --- a/tools/arch/x86/include/asm/msr-index.h +++ b/tools/arch/x86/include/asm/msr-index.h @@ -326,8 +326,9 @@ #define MSR_PP1_ENERGY_STATUS 0x00000641 #define MSR_PP1_POLICY 0x00000642
-#define MSR_AMD_PKG_ENERGY_STATUS 0xc001029b #define MSR_AMD_RAPL_POWER_UNIT 0xc0010299 +#define MSR_AMD_CORE_ENERGY_STATUS 0xc001029a +#define MSR_AMD_PKG_ENERGY_STATUS 0xc001029b
/* Config TDP MSRs */ #define MSR_CONFIG_TDP_NOMINAL 0x00000648
From: Vlastimil Babka vbabka@suse.cz
mainline inclusion from mainline-5.11-rc1 commit 7115ac6ef0b26017676e88a44a0b40c2d1d99299 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4MWJF CVE: NA
-------------------------------------------------
Patch series "disable pcplists during memory offline", v3.
As per the discussions [1] [2] this is an attempt to implement David's suggestion that page isolation should disable pcplists to avoid races with page freeing in progress. This is done without extra checks in fast paths, as explained in Patch 9. The repeated draining done by [2] is then no longer needed. Previous version (RFC) is at [3].
The RFC tried to hide pcplists disabling/enabling into page isolation, but it wasn't completely possible, as memory offline does not unisolation. Michal suggested an explicit API in [4] so that's the current implementation and it seems indeed nicer.
Once we accept that page isolation users need to do explicit actions around it depending on the needed guarantees, we can also IMHO accept that the current pcplist draining can be also done by the callers, which is more effective. After all, there are only two users of page isolation. So patch 6 does effectively the same thing as Pavel proposed in [5], and patch 7 implement stronger guarantees only for memory offline. If CMA decides to opt-in to the stronger guarantee, it can be added later.
Patches 1-5 are preparatory cleanups for pcplist disabling.
Patchset was briefly tested in QEMU so that memory online/offline works, but I haven't done a stress test that would prove the race fixed by [2] is eliminated.
Note that patch 7 could be avoided if we instead adjusted page freeing in shown in [6], but I believe the current implementation of disabling pcplists is not too much complex, so I would prefer this instead of adding new checks and longer irq-disabled section into page freeing hotpaths.
[1] https://lore.kernel.org/linux-mm/20200901124615.137200-1-pasha.tatashin@sole... [2] https://lore.kernel.org/linux-mm/20200903140032.380431-1-pasha.tatashin@sole... [3] https://lore.kernel.org/linux-mm/20200907163628.26495-1-vbabka@suse.cz/ [4] https://lore.kernel.org/linux-mm/20200909113647.GG7348@dhcp22.suse.cz/ [5] https://lore.kernel.org/linux-mm/20200904151448.100489-3-pasha.tatashin@sole... [6] https://lore.kernel.org/linux-mm/3d3b53db-aeaa-ff24-260b-36427fac9b1c@suse.c... [7] https://lore.kernel.org/linux-mm/20200922143712.12048-1-vbabka@suse.cz/ [8] https://lore.kernel.org/linux-mm/20201008114201.18824-1-vbabka@suse.cz/
This patch (of 7):
The updates to pcplists' high and batch values are handled by multiple functions that make the calculations hard to follow. Consolidate everything to pageset_set_high_and_batch() and remove pageset_set_batch() and pageset_set_high() wrappers.
The only special case using one of the removed wrappers was: build_all_zonelists_init()
setup_pageset() pageset_set_batch()
which was hardcoding batch as 0, so we can just open-code a call to pageset_update() with constant parameters instead.
No functional change.
Link: https://lkml.kernel.org/r/20201111092812.11329-1-vbabka@suse.cz Link: https://lkml.kernel.org/r/20201111092812.11329-2-vbabka@suse.cz Signed-off-by: Vlastimil Babka vbabka@suse.cz Reviewed-by: Oscar Salvador osalvador@suse.de Reviewed-by: David Hildenbrand david@redhat.com Acked-by: Michal Hocko mhocko@suse.com Acked-by: Pankaj Gupta pankaj.gupta@cloud.ionos.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org (cherry picked from commit 7115ac6ef0b26017676e88a44a0b40c2d1d99299) Signed-off-by: Guilei Xie xieguilei@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- mm/page_alloc.c | 49 ++++++++++++++++++++----------------------------- 1 file changed, 20 insertions(+), 29 deletions(-)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 62c94ea31e17..7911cf8a4c4b 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -6112,7 +6112,7 @@ static void build_zonelists(pg_data_t *pgdat) * not check if the processor is online before following the pageset pointer. * Other parts of the kernel may not check if the zone is available. */ -static void setup_pageset(struct per_cpu_pageset *p, unsigned long batch); +static void setup_pageset(struct per_cpu_pageset *p); static DEFINE_PER_CPU(struct per_cpu_pageset, boot_pageset); static DEFINE_PER_CPU(struct per_cpu_nodestat, boot_nodestats);
@@ -6180,7 +6180,7 @@ build_all_zonelists_init(void) * (a chicken-egg dilemma). */ for_each_possible_cpu(cpu) - setup_pageset(&per_cpu(boot_pageset, cpu), 0); + setup_pageset(&per_cpu(boot_pageset, cpu));
mminit_verify_zonelist(); cpuset_init_current_mems_allowed(); @@ -6590,12 +6590,6 @@ static void pageset_update(struct per_cpu_pages *pcp, unsigned long high, pcp->batch = batch; }
-/* a companion to pageset_set_high() */ -static void pageset_set_batch(struct per_cpu_pageset *p, unsigned long batch) -{ - pageset_update(&p->pcp, 6 * batch, max(1UL, 1 * batch)); -} - static void pageset_init(struct per_cpu_pageset *p) { struct per_cpu_pages *pcp; @@ -6608,35 +6602,32 @@ static void pageset_init(struct per_cpu_pageset *p) INIT_LIST_HEAD(&pcp->lists[migratetype]); }
-static void setup_pageset(struct per_cpu_pageset *p, unsigned long batch) +static void setup_pageset(struct per_cpu_pageset *p) { pageset_init(p); - pageset_set_batch(p, batch); + pageset_update(&p->pcp, 0, 1); }
/* - * pageset_set_high() sets the high water mark for hot per_cpu_pagelist - * to the value high for the pageset p. + * Calculate and set new high and batch values for given per-cpu pageset of a + * zone, based on the zone's size and the percpu_pagelist_fraction sysctl. */ -static void pageset_set_high(struct per_cpu_pageset *p, - unsigned long high) -{ - unsigned long batch = max(1UL, high / 4); - if ((high / 4) > (PAGE_SHIFT * 8)) - batch = PAGE_SHIFT * 8; - - pageset_update(&p->pcp, high, batch); -} - static void pageset_set_high_and_batch(struct zone *zone, - struct per_cpu_pageset *pcp) + struct per_cpu_pageset *p) { - if (percpu_pagelist_fraction) - pageset_set_high(pcp, - (zone_managed_pages(zone) / - percpu_pagelist_fraction)); - else - pageset_set_batch(pcp, zone_batchsize(zone)); + unsigned long new_high, new_batch; + + if (percpu_pagelist_fraction) { + new_high = zone_managed_pages(zone) / percpu_pagelist_fraction; + new_batch = max(1UL, new_high / 4); + if ((new_high / 4) > (PAGE_SHIFT * 8)) + new_batch = PAGE_SHIFT * 8; + } else { + new_batch = zone_batchsize(zone); + new_high = 6 * new_batch; + new_batch = max(1UL, 1 * new_batch); + } + pageset_update(&p->pcp, new_high, new_batch); }
static void __meminit zone_pageset_init(struct zone *zone, int cpu)
From: Vlastimil Babka vbabka@suse.cz
mainline inclusion from mainline-5.11-rc1 commit 0a8b4f1d5bf4108cfd2877223bf125b1fa1dc4b1 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4MWJF CVE: NA
-------------------------------------------------
We currently call pageset_set_high_and_batch() for each possible cpu, which repeats the same calculations of high and batch values.
Instead call the function just once per zone, and make it apply the calculated values to all per-cpu pagesets of the zone.
This also allows removing the zone_pageset_init() and __zone_pcp_update() wrappers.
No functional change.
Link: https://lkml.kernel.org/r/20201111092812.11329-3-vbabka@suse.cz Signed-off-by: Vlastimil Babka vbabka@suse.cz Reviewed-by: Oscar Salvador osalvador@suse.de Reviewed-by: David Hildenbrand david@redhat.com Acked-by: Michal Hocko mhocko@suse.com Acked-by: Pankaj Gupta pankaj.gupta@cloud.ionos.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org (cherry picked from commit 0a8b4f1d5bf4108cfd2877223bf125b1fa1dc4b1) Signed-off-by: Guilei Xie xieguilei@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- mm/page_alloc.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 7911cf8a4c4b..b22cd247e571 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -6609,13 +6609,14 @@ static void setup_pageset(struct per_cpu_pageset *p) }
/* - * Calculate and set new high and batch values for given per-cpu pageset of a + * Calculate and set new high and batch values for all per-cpu pagesets of a * zone, based on the zone's size and the percpu_pagelist_fraction sysctl. */ -static void pageset_set_high_and_batch(struct zone *zone, - struct per_cpu_pageset *p) +static void zone_set_pageset_high_and_batch(struct zone *zone) { unsigned long new_high, new_batch; + struct per_cpu_pageset *p; + int cpu;
if (percpu_pagelist_fraction) { new_high = zone_managed_pages(zone) / percpu_pagelist_fraction; @@ -6627,23 +6628,25 @@ static void pageset_set_high_and_batch(struct zone *zone, new_high = 6 * new_batch; new_batch = max(1UL, 1 * new_batch); } - pageset_update(&p->pcp, new_high, new_batch); -} - -static void __meminit zone_pageset_init(struct zone *zone, int cpu) -{ - struct per_cpu_pageset *pcp = per_cpu_ptr(zone->pageset, cpu);
- pageset_init(pcp); - pageset_set_high_and_batch(zone, pcp); + for_each_possible_cpu(cpu) { + p = per_cpu_ptr(zone->pageset, cpu); + pageset_update(&p->pcp, new_high, new_batch); + } }
void __meminit setup_zone_pageset(struct zone *zone) { + struct per_cpu_pageset *p; int cpu; + zone->pageset = alloc_percpu(struct per_cpu_pageset); - for_each_possible_cpu(cpu) - zone_pageset_init(zone, cpu); + for_each_possible_cpu(cpu) { + p = per_cpu_ptr(zone->pageset, cpu); + pageset_init(p); + } + + zone_set_pageset_high_and_batch(zone); }
/* @@ -8292,15 +8295,6 @@ int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *table, int write, return 0; }
-static void __zone_pcp_update(struct zone *zone) -{ - unsigned int cpu; - - for_each_possible_cpu(cpu) - pageset_set_high_and_batch(zone, - per_cpu_ptr(zone->pageset, cpu)); -} - /* * percpu_pagelist_fraction - changes the pcp->high for each zone on each * cpu. It is the fraction of total pages in each zone that a hot per cpu @@ -8333,7 +8327,7 @@ int percpu_pagelist_fraction_sysctl_handler(struct ctl_table *table, int write, goto out;
for_each_populated_zone(zone) - __zone_pcp_update(zone); + zone_set_pageset_high_and_batch(zone); out: mutex_unlock(&pcp_batch_high_lock); return ret; @@ -8942,7 +8936,7 @@ EXPORT_SYMBOL(free_contig_range); void __meminit zone_pcp_update(struct zone *zone) { mutex_lock(&pcp_batch_high_lock); - __zone_pcp_update(zone); + zone_set_pageset_high_and_batch(zone); mutex_unlock(&pcp_batch_high_lock); }
From: Vlastimil Babka vbabka@suse.cz
mainline inclusion from mainline-5.11-rc1 commit 69a8396a2647feac197497bd992f0a91da9fd801 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4MWJF CVE: NA
-------------------------------------------------
We initialize boot-time pagesets with setup_pageset(), which sets high and batch values that effectively disable pcplists.
We can remove this wrapper if we just set these values for all pagesets in pageset_init(). Non-boot pagesets then subsequently update them to the proper values.
No functional change.
Link: https://lkml.kernel.org/r/20201111092812.11329-4-vbabka@suse.cz Signed-off-by: Vlastimil Babka vbabka@suse.cz Reviewed-by: David Hildenbrand david@redhat.com Reviewed-by: Oscar Salvador osalvador@suse.de Acked-by: Michal Hocko mhocko@suse.com Acked-by: Pankaj Gupta pankaj.gupta@cloud.ionos.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org (cherry picked from commit 69a8396a2647feac197497bd992f0a91da9fd801) Signed-off-by: Guilei Xie xieguilei@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- mm/page_alloc.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index b22cd247e571..9994fa212abc 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -6112,7 +6112,7 @@ static void build_zonelists(pg_data_t *pgdat) * not check if the processor is online before following the pageset pointer. * Other parts of the kernel may not check if the zone is available. */ -static void setup_pageset(struct per_cpu_pageset *p); +static void pageset_init(struct per_cpu_pageset *p); static DEFINE_PER_CPU(struct per_cpu_pageset, boot_pageset); static DEFINE_PER_CPU(struct per_cpu_nodestat, boot_nodestats);
@@ -6180,7 +6180,7 @@ build_all_zonelists_init(void) * (a chicken-egg dilemma). */ for_each_possible_cpu(cpu) - setup_pageset(&per_cpu(boot_pageset, cpu)); + pageset_init(&per_cpu(boot_pageset, cpu));
mminit_verify_zonelist(); cpuset_init_current_mems_allowed(); @@ -6600,12 +6600,15 @@ static void pageset_init(struct per_cpu_pageset *p) pcp = &p->pcp; for (migratetype = 0; migratetype < MIGRATE_PCPTYPES; migratetype++) INIT_LIST_HEAD(&pcp->lists[migratetype]); -}
-static void setup_pageset(struct per_cpu_pageset *p) -{ - pageset_init(p); - pageset_update(&p->pcp, 0, 1); + /* + * Set batch and high values safe for a boot pageset. A true percpu + * pageset's initialization will update them subsequently. Here we don't + * need to be as careful as pageset_update() as nobody can access the + * pageset yet. + */ + pcp->high = 0; + pcp->batch = 1; }
/*
From: Vlastimil Babka vbabka@suse.cz
mainline inclusion from mainline-5.11-rc1 commit 5c3ad2eb7104754a36580079a2e4aed04a10631d category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4MWJF CVE: NA
-------------------------------------------------
pageset_update() attempts to update pcplist's high and batch values in a way that readers don't observe batch > high. It uses smp_wmb() to order the updates in a way to achieve this. However, without proper pairing read barriers in readers this guarantee doesn't hold, and there are no such barriers in e.g. free_unref_page_commit().
Commit 88e8ac11d2ea ("mm, page_alloc: fix core hung in free_pcppages_bulk()") already showed this is problematic, and solved this by ultimately only trusing pcp->count of the current cpu with interrupts disabled.
The update dance with unpaired write barriers thus makes no sense. Replace them with plain WRITE_ONCE to prevent store tearing, and document that the values can change asynchronously and should not be trusted for correctness.
All current readers appear to be OK after 88e8ac11d2ea. Convert them to READ_ONCE to prevent unnecessary read tearing, but mainly to alert anybody making future changes to the code that special care is needed.
Link: https://lkml.kernel.org/r/20201111092812.11329-5-vbabka@suse.cz Signed-off-by: Vlastimil Babka vbabka@suse.cz Reviewed-by: Oscar Salvador osalvador@suse.de Acked-by: David Hildenbrand david@redhat.com Acked-by: Michal Hocko mhocko@suse.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org (cherry picked from commit 5c3ad2eb7104754a36580079a2e4aed04a10631d) Signed-off-by: Guilei Xie xieguilei@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- mm/page_alloc.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 9994fa212abc..f14560e8b34c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1348,7 +1348,7 @@ static void free_pcppages_bulk(struct zone *zone, int count, { int migratetype = 0; int batch_free = 0; - int prefetch_nr = 0; + int prefetch_nr = READ_ONCE(pcp->batch); bool isolated_pageblocks; struct page *page, *tmp; LIST_HEAD(head); @@ -1399,8 +1399,10 @@ static void free_pcppages_bulk(struct zone *zone, int count, * avoid excessive prefetching due to large count, only * prefetch buddy for the first pcp->batch nr of pages. */ - if (prefetch_nr++ < pcp->batch) + if (prefetch_nr) { prefetch_buddy(page); + prefetch_nr--; + } } while (--count && --batch_free && !list_empty(list)); }
@@ -3195,10 +3197,8 @@ static void free_unref_page_commit(struct page *page, unsigned long pfn) pcp = &this_cpu_ptr(zone->pageset)->pcp; list_add(&page->lru, &pcp->lists[migratetype]); pcp->count++; - if (pcp->count >= pcp->high) { - unsigned long batch = READ_ONCE(pcp->batch); - free_pcppages_bulk(zone, batch, pcp); - } + if (pcp->count >= READ_ONCE(pcp->high)) + free_pcppages_bulk(zone, READ_ONCE(pcp->batch), pcp); }
/* @@ -3385,7 +3385,7 @@ struct page *__rmqueue_pcplist(struct zone *zone, int migratetype, do { if (list_empty(list)) { pcp->count += rmqueue_bulk(zone, 0, - pcp->batch, list, + READ_ONCE(pcp->batch), list, migratetype, alloc_flags); if (unlikely(list_empty(list))) return NULL; @@ -6564,13 +6564,16 @@ static int zone_batchsize(struct zone *zone) }
/* - * pcp->high and pcp->batch values are related and dependent on one another: - * ->batch must never be higher then ->high. - * The following function updates them in a safe manner without read side - * locking. + * pcp->high and pcp->batch values are related and generally batch is lower + * than high. They are also related to pcp->count such that count is lower + * than high, and as soon as it reaches high, the pcplist is flushed. * - * Any new users of pcp->batch and pcp->high should ensure they can cope with - * those fields changing asynchronously (acording to the above rule). + * However, guaranteeing these relations at all times would require e.g. write + * barriers here but also careful usage of read barriers at the read side, and + * thus be prone to error and bad for performance. Thus the update only prevents + * store tearing. Any new users of pcp->batch and pcp->high should ensure they + * can cope with those fields changing asynchronously, and fully trust only the + * pcp->count field on the local CPU with interrupts disabled. * * mutex_is_locked(&pcp_batch_high_lock) required when calling this function * outside of boot time (or some other assurance that no concurrent updaters @@ -6579,15 +6582,8 @@ static int zone_batchsize(struct zone *zone) static void pageset_update(struct per_cpu_pages *pcp, unsigned long high, unsigned long batch) { - /* start with a fail safe value for batch */ - pcp->batch = 1; - smp_wmb(); - - /* Update high, then batch, in order */ - pcp->high = high; - smp_wmb(); - - pcp->batch = batch; + WRITE_ONCE(pcp->batch, batch); + WRITE_ONCE(pcp->high, high); }
static void pageset_init(struct per_cpu_pageset *p)
From: Vlastimil Babka vbabka@suse.cz
mainline inclusion from mainline-5.11-rc1 commit 952eaf815925f106eb6b68346b3458a68bb18ec1 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4MWJF CVE: NA
-------------------------------------------------
All per-cpu pagesets for a zone use the same high and batch values, that are duplicated there just for performance (locality) reasons. This patch adds the same variables also to struct zone as a shared copy.
This will be useful later for making possible to disable pcplists temporarily by setting high value to 0, while remembering the values for restoring them later. But we can also immediately benefit from not updating pagesets of all possible cpus in case the newly recalculated values (after sysctl change or memory online/offline) are actually unchanged from the previous ones.
Link: https://lkml.kernel.org/r/20201111092812.11329-6-vbabka@suse.cz Signed-off-by: Vlastimil Babka vbabka@suse.cz Reviewed-by: Oscar Salvador osalvador@suse.de Acked-by: Michal Hocko mhocko@suse.com Reviewed-by: David Hildenbrand david@redhat.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org (cherry picked from commit 952eaf815925f106eb6b68346b3458a68bb18ec1) Signed-off-by: Guilei Xie xieguilei@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/mmzone.h | 6 ++++++ mm/page_alloc.c | 16 ++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 82fceef88448..d73b1486ffb8 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -451,6 +451,12 @@ struct zone { #endif struct pglist_data *zone_pgdat; struct per_cpu_pageset __percpu *pageset; + /* + * the high and batch values are copied to individual pagesets for + * faster access + */ + int pageset_high; + int pageset_batch;
#ifndef CONFIG_SPARSEMEM /* diff --git a/mm/page_alloc.c b/mm/page_alloc.c index f14560e8b34c..20cdcd2b3280 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -6113,6 +6113,9 @@ static void build_zonelists(pg_data_t *pgdat) * Other parts of the kernel may not check if the zone is available. */ static void pageset_init(struct per_cpu_pageset *p); +/* These effectively disable the pcplists in the boot pageset completely */ +#define BOOT_PAGESET_HIGH 0 +#define BOOT_PAGESET_BATCH 1 static DEFINE_PER_CPU(struct per_cpu_pageset, boot_pageset); static DEFINE_PER_CPU(struct per_cpu_nodestat, boot_nodestats);
@@ -6603,8 +6606,8 @@ static void pageset_init(struct per_cpu_pageset *p) * need to be as careful as pageset_update() as nobody can access the * pageset yet. */ - pcp->high = 0; - pcp->batch = 1; + pcp->high = BOOT_PAGESET_HIGH; + pcp->batch = BOOT_PAGESET_BATCH; }
/* @@ -6628,6 +6631,13 @@ static void zone_set_pageset_high_and_batch(struct zone *zone) new_batch = max(1UL, 1 * new_batch); }
+ if (zone->pageset_high == new_high && + zone->pageset_batch == new_batch) + return; + + zone->pageset_high = new_high; + zone->pageset_batch = new_batch; + for_each_possible_cpu(cpu) { p = per_cpu_ptr(zone->pageset, cpu); pageset_update(&p->pcp, new_high, new_batch); @@ -6688,6 +6698,8 @@ static __meminit void zone_pcp_init(struct zone *zone) * offset of a (static) per cpu variable into the per cpu area. */ zone->pageset = &boot_pageset; + zone->pageset_high = BOOT_PAGESET_HIGH; + zone->pageset_batch = BOOT_PAGESET_BATCH;
if (populated_zone(zone)) printk(KERN_DEBUG " %s zone: %lu pages, LIFO batch:%u\n",
From: Vlastimil Babka vbabka@suse.cz
mainline inclusion from mainline-5.11-rc1 commit 7612921f2376d51d020ae2f06ffb7da40422b75b category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4MWJF CVE: NA
-------------------------------------------------
Currently, pcplists are drained during set_migratetype_isolate() which means once per pageblock processed start_isolate_page_range(). This is somewhat wasteful. Moreover, the callers might need different guarantees, and the draining is currently prone to races and does not guarantee that no page from isolated pageblock will end up on the pcplist after the drain.
Better guarantees are added by later patches and require explicit actions by page isolation users that need them. Thus it makes sense to move the current imperfect draining to the callers also as a preparation step.
Link: https://lkml.kernel.org/r/20201111092812.11329-7-vbabka@suse.cz Suggested-by: David Hildenbrand david@redhat.com Suggested-by: Pavel Tatashin pasha.tatashin@soleen.com Signed-off-by: Vlastimil Babka vbabka@suse.cz Reviewed-by: David Hildenbrand david@redhat.com Reviewed-by: Oscar Salvador osalvador@suse.de Acked-by: Michal Hocko mhocko@suse.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org (cherry picked from commit 7612921f2376d51d020ae2f06ffb7da40422b75b) Signed-off-by: Guilei Xie xieguilei@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- mm/memory_hotplug.c | 11 ++++++----- mm/page_alloc.c | 2 ++ mm/page_isolation.c | 10 +++++----- 3 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index a8f0d804a758..fcc50f6fdb46 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -1394,6 +1394,8 @@ int __ref offline_pages(unsigned long start_pfn, unsigned long nr_pages) goto failed_removal; }
+ drain_all_pages(zone); + arg.start_pfn = start_pfn; arg.nr_pages = nr_pages; node_states_check_changes_offline(nr_pages, zone, &arg); @@ -1444,11 +1446,10 @@ int __ref offline_pages(unsigned long start_pfn, unsigned long nr_pages) }
/* - * per-cpu pages are drained in start_isolate_page_range, but if - * there are still pages that are not free, make sure that we - * drain again, because when we isolated range we might - * have raced with another thread that was adding pages to pcp - * list. + * per-cpu pages are drained after start_isolate_page_range, but + * if there are still pages that are not free, make sure that we + * drain again, because when we isolated range we might have + * raced with another thread that was adding pages to pcp list. * * Forward progress should be still guaranteed because * pages on the pcp list can only belong to MOVABLE_ZONE diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 20cdcd2b3280..da0663435f0a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -8739,6 +8739,8 @@ int alloc_contig_range(unsigned long start, unsigned long end, if (ret) return ret;
+ drain_all_pages(cc.zone); + /* * In case of -EBUSY, we'd like to know which page causes problem. * So, just fall through. test_pages_isolated() has a tracepoint diff --git a/mm/page_isolation.c b/mm/page_isolation.c index 756d1542f2c8..46005c960ffa 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c @@ -49,7 +49,6 @@ static int set_migratetype_isolate(struct page *page, int migratetype, int isol_
__mod_zone_freepage_state(zone, -nr_pages, mt); spin_unlock_irqrestore(&zone->lock, flags); - drain_all_pages(zone); return 0; }
@@ -172,11 +171,12 @@ __first_valid_page(unsigned long pfn, unsigned long nr_pages) * * Please note that there is no strong synchronization with the page allocator * either. Pages might be freed while their page blocks are marked ISOLATED. - * In some cases pages might still end up on pcp lists and that would allow + * A call to drain_all_pages() after isolation can flush most of them. However + * in some cases pages might still end up on pcp lists and that would allow * for their allocation even when they are in fact isolated already. Depending - * on how strong of a guarantee the caller needs drain_all_pages might be needed - * (e.g. __offline_pages will need to call it after check for isolated range for - * a next retry). + * on how strong of a guarantee the caller needs, further drain_all_pages() + * might be needed (e.g. __offline_pages will need to call it after check for + * isolated range for a next retry). * * Return: 0 on success and -EBUSY if any part of range cannot be isolated. */
From: Vlastimil Babka vbabka@suse.cz
mainline inclusion from mainline-5.11-rc1 commit ec6e8c7e03147c65380e6c04c4cf4290e96280b6 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4MWJF CVE: NA
-------------------------------------------------
Memory offlining relies on page isolation to guarantee a forward progress because pages cannot be reused while they are isolated. But the page isolation itself doesn't prevent from races while freed pages are stored on pcp lists and thus can be reused. This can be worked around by repeated draining of pcplists, as done by commit 968318261221 ("mm/memory_hotplug: drain per-cpu pages again during memory offline").
David and Michal would prefer that this race was closed in a way that callers of page isolation who need stronger guarantees don't need to repeatedly drain. David suggested disabling pcplists usage completely during page isolation, instead of repeatedly draining them.
To achieve this without adding special cases in alloc/free fastpath, we can use the same approach as boot pagesets - when pcp->high is 0, any pcplist addition will be immediately flushed.
The race can thus be closed by setting pcp->high to 0 and draining pcplists once, before calling start_isolate_page_range(). The draining will serialize after processes that already disabled interrupts and read the old value of pcp->high in free_unref_page_commit(), and processes that have not yet disabled interrupts, will observe pcp->high == 0 when they are rescheduled, and skip pcplists. This guarantees no stray pages on pcplists in zones where isolation happens.
This patch thus adds zone_pcp_disable() and zone_pcp_enable() functions that page isolation users can call before start_isolate_page_range() and after unisolating (or offlining) the isolated pages.
Also, drain_all_pages() is optimized to only execute on cpus where pcplists are not empty. The check can however race with a free to pcplist that has not yet increased the pcp->count from 0 to 1. Thus make the drain optionally skip the racy check and drain on all cpus, and use this option in zone_pcp_disable().
As we have to avoid external updates to high and batch while pcplists are disabled, we take pcp_batch_high_lock in zone_pcp_disable() and release it in zone_pcp_enable(). This also synchronizes multiple users of zone_pcp_disable()/enable().
Currently the only user of this functionality is offline_pages().
[vbabka@suse.cz: add comment, per David] Link: https://lkml.kernel.org/r/527480ef-ed72-e1c1-52a0-1c5b0113df45@suse.cz
Link: https://lkml.kernel.org/r/20201111092812.11329-8-vbabka@suse.cz Signed-off-by: Vlastimil Babka vbabka@suse.cz Suggested-by: David Hildenbrand david@redhat.com Suggested-by: Michal Hocko mhocko@suse.com Reviewed-by: Oscar Salvador osalvador@suse.de Reviewed-by: David Hildenbrand david@redhat.com Acked-by: Michal Hocko mhocko@suse.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org (cherry picked from commit ec6e8c7e03147c65380e6c04c4cf4290e96280b6) Signed-off-by: Guilei Xie xieguilei@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- mm/internal.h | 2 ++ mm/memory_hotplug.c | 28 ++++++++--------- mm/page_alloc.c | 73 +++++++++++++++++++++++++++++++++++++-------- mm/page_isolation.c | 6 ++-- 4 files changed, 78 insertions(+), 31 deletions(-)
diff --git a/mm/internal.h b/mm/internal.h index 9451ba9bbcf3..db9546707695 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -201,6 +201,8 @@ extern int user_min_free_kbytes;
extern void zone_pcp_update(struct zone *zone); extern void zone_pcp_reset(struct zone *zone); +extern void zone_pcp_disable(struct zone *zone); +extern void zone_pcp_enable(struct zone *zone);
#if defined CONFIG_COMPACTION || defined CONFIG_CMA
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index fcc50f6fdb46..1549b19b36f6 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -1385,17 +1385,21 @@ int __ref offline_pages(unsigned long start_pfn, unsigned long nr_pages) } node = zone_to_nid(zone);
+ /* + * Disable pcplists so that page isolation cannot race with freeing + * in a way that pages from isolated pageblock are left on pcplists. + */ + zone_pcp_disable(zone); + /* set above range as isolated */ ret = start_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE, MEMORY_OFFLINE | REPORT_FAILURE); if (ret) { reason = "failure to isolate range"; - goto failed_removal; + goto failed_removal_pcplists_disabled; }
- drain_all_pages(zone); - arg.start_pfn = start_pfn; arg.nr_pages = nr_pages; node_states_check_changes_offline(nr_pages, zone, &arg); @@ -1445,20 +1449,8 @@ int __ref offline_pages(unsigned long start_pfn, unsigned long nr_pages) goto failed_removal_isolated; }
- /* - * per-cpu pages are drained after start_isolate_page_range, but - * if there are still pages that are not free, make sure that we - * drain again, because when we isolated range we might have - * raced with another thread that was adding pages to pcp list. - * - * Forward progress should be still guaranteed because - * pages on the pcp list can only belong to MOVABLE_ZONE - * because has_unmovable_pages explicitly checks for - * PageBuddy on freed pages on other zones. - */ ret = test_pages_isolated(start_pfn, end_pfn, MEMORY_OFFLINE); - if (ret) - drain_all_pages(zone); + } while (ret);
/* Mark all sections offline and remove free pages from the buddy. */ @@ -1474,6 +1466,8 @@ int __ref offline_pages(unsigned long start_pfn, unsigned long nr_pages) zone->nr_isolate_pageblock -= nr_pages / pageblock_nr_pages; spin_unlock_irqrestore(&zone->lock, flags);
+ zone_pcp_enable(zone); + /* removal success */ adjust_managed_page_count(pfn_to_page(start_pfn), -nr_pages); zone->present_pages -= nr_pages; @@ -1507,6 +1501,8 @@ int __ref offline_pages(unsigned long start_pfn, unsigned long nr_pages) failed_removal_isolated: undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE); memory_notify(MEM_CANCEL_OFFLINE, &arg); +failed_removal_pcplists_disabled: + zone_pcp_enable(zone); failed_removal: pr_debug("memory offlining [mem %#010llx-%#010llx] failed due to %s\n", (unsigned long long) start_pfn << PAGE_SHIFT, diff --git a/mm/page_alloc.c b/mm/page_alloc.c index da0663435f0a..43fe0c8e592e 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3024,13 +3024,16 @@ static void drain_local_pages_wq(struct work_struct *work) }
/* - * Spill all the per-cpu pages from all CPUs back into the buddy allocator. - * - * When zone parameter is non-NULL, spill just the single zone's pages. + * The implementation of drain_all_pages(), exposing an extra parameter to + * drain on all cpus. * - * Note that this can be extremely slow as the draining happens in a workqueue. + * drain_all_pages() is optimized to only execute on cpus where pcplists are + * not empty. The check for non-emptiness can however race with a free to + * pcplist that has not yet increased the pcp->count from 0 to 1. Callers + * that need the guarantee that every CPU has drained can disable the + * optimizing racy check. */ -void drain_all_pages(struct zone *zone) +void __drain_all_pages(struct zone *zone, bool force_all_cpus) { int cpu;
@@ -3069,7 +3072,13 @@ void drain_all_pages(struct zone *zone) struct zone *z; bool has_pcps = false;
- if (zone) { + if (force_all_cpus) { + /* + * The pcp.count check is racy, some callers need a + * guarantee that no cpu is missed. + */ + has_pcps = true; + } else if (zone) { pcp = per_cpu_ptr(zone->pageset, cpu); if (pcp->pcp.count) has_pcps = true; @@ -3102,6 +3111,18 @@ void drain_all_pages(struct zone *zone) mutex_unlock(&pcpu_drain_mutex); }
+/* + * Spill all the per-cpu pages from all CPUs back into the buddy allocator. + * + * When zone parameter is non-NULL, spill just the single zone's pages. + * + * Note that this can be extremely slow as the draining happens in a workqueue. + */ +void drain_all_pages(struct zone *zone) +{ + __drain_all_pages(zone, false); +} + #ifdef CONFIG_HIBERNATION
/* @@ -6610,6 +6631,18 @@ static void pageset_init(struct per_cpu_pageset *p) pcp->batch = BOOT_PAGESET_BATCH; }
+void __zone_set_pageset_high_and_batch(struct zone *zone, unsigned long high, + unsigned long batch) +{ + struct per_cpu_pageset *p; + int cpu; + + for_each_possible_cpu(cpu) { + p = per_cpu_ptr(zone->pageset, cpu); + pageset_update(&p->pcp, high, batch); + } +} + /* * Calculate and set new high and batch values for all per-cpu pagesets of a * zone, based on the zone's size and the percpu_pagelist_fraction sysctl. @@ -6617,8 +6650,6 @@ static void pageset_init(struct per_cpu_pageset *p) static void zone_set_pageset_high_and_batch(struct zone *zone) { unsigned long new_high, new_batch; - struct per_cpu_pageset *p; - int cpu;
if (percpu_pagelist_fraction) { new_high = zone_managed_pages(zone) / percpu_pagelist_fraction; @@ -6638,10 +6669,7 @@ static void zone_set_pageset_high_and_batch(struct zone *zone) zone->pageset_high = new_high; zone->pageset_batch = new_batch;
- for_each_possible_cpu(cpu) { - p = per_cpu_ptr(zone->pageset, cpu); - pageset_update(&p->pcp, new_high, new_batch); - } + __zone_set_pageset_high_and_batch(zone, new_high, new_batch); }
void __meminit setup_zone_pageset(struct zone *zone) @@ -8953,6 +8981,27 @@ void __meminit zone_pcp_update(struct zone *zone) mutex_unlock(&pcp_batch_high_lock); }
+/* + * Effectively disable pcplists for the zone by setting the high limit to 0 + * and draining all cpus. A concurrent page freeing on another CPU that's about + * to put the page on pcplist will either finish before the drain and the page + * will be drained, or observe the new high limit and skip the pcplist. + * + * Must be paired with a call to zone_pcp_enable(). + */ +void zone_pcp_disable(struct zone *zone) +{ + mutex_lock(&pcp_batch_high_lock); + __zone_set_pageset_high_and_batch(zone, 0, 1); + __drain_all_pages(zone, true); +} + +void zone_pcp_enable(struct zone *zone) +{ + __zone_set_pageset_high_and_batch(zone, zone->pageset_high, zone->pageset_batch); + mutex_unlock(&pcp_batch_high_lock); +} + void zone_pcp_reset(struct zone *zone) { unsigned long flags; diff --git a/mm/page_isolation.c b/mm/page_isolation.c index 46005c960ffa..bddf788f45bf 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c @@ -174,9 +174,9 @@ __first_valid_page(unsigned long pfn, unsigned long nr_pages) * A call to drain_all_pages() after isolation can flush most of them. However * in some cases pages might still end up on pcp lists and that would allow * for their allocation even when they are in fact isolated already. Depending - * on how strong of a guarantee the caller needs, further drain_all_pages() - * might be needed (e.g. __offline_pages will need to call it after check for - * isolated range for a next retry). + * on how strong of a guarantee the caller needs, zone_pcp_disable/enable() + * might be used to flush and disable pcplist before isolation and enable after + * unisolation. * * Return: 0 on success and -EBUSY if any part of range cannot be isolated. */
From: Yunfeng Ye yeyunfeng@huawei.com
mainline inclusion from mainline-v5.16-rc2 commit 9a543f007b702b0be4acacad416a0f90233b4558 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4MVAT Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
---------------------------
After the memory is freed, it can be immediately allocated by other CPUs, before the "free" trace report has been emitted. This causes inaccurate traces.
For example, if the following sequence of events occurs:
CPU 0 CPU 1
(1) alloc xxxxxx (2) free xxxxxx (3) alloc xxxxxx (4) free xxxxxx
Then they will be inaccurately reported via tracing, so that they appear to have happened in this order:
CPU 0 CPU 1
(1) alloc xxxxxx (2) alloc xxxxxx (3) free xxxxxx (4) free xxxxxx
This makes it look like CPU 1 somehow managed to allocate mmemory that CPU 0 still had allocated for itself.
In order to avoid this, emit the "free xxxxxx" tracing report just before the actual call to free the memory, instead of just after it.
Link: https://lkml.kernel.org/r/374eb75d-7404-8721-4e1e-65b0e5b17279@huawei.com Signed-off-by: Yunfeng Ye yeyunfeng@huawei.com Reviewed-by: Vlastimil Babka vbabka@suse.cz Reviewed-by: John Hubbard jhubbard@nvidia.com Cc: Christoph Lameter cl@linux.com Cc: Pekka Enberg penberg@kernel.org Cc: David Rientjes rientjes@google.com Cc: Joonsoo Kim iamjoonsoo.kim@lge.com Cc: Vlastimil Babka vbabka@suse.cz Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- mm/slab.c | 3 +-- mm/slob.c | 3 +-- mm/slub.c | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/mm/slab.c b/mm/slab.c index 43104a23ebff..d152f910da26 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3705,14 +3705,13 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp) if (!cachep) return;
+ trace_kmem_cache_free(_RET_IP_, objp); local_irq_save(flags); debug_check_no_locks_freed(objp, cachep->object_size); if (!(cachep->flags & SLAB_DEBUG_OBJECTS)) debug_check_no_obj_freed(objp, cachep->object_size); __cache_free(cachep, objp, _RET_IP_); local_irq_restore(flags); - - trace_kmem_cache_free(_RET_IP_, objp); } EXPORT_SYMBOL(kmem_cache_free);
diff --git a/mm/slob.c b/mm/slob.c index 7cc9805c8091..65d790cefd8a 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -660,6 +660,7 @@ static void kmem_rcu_free(struct rcu_head *head) void kmem_cache_free(struct kmem_cache *c, void *b) { kmemleak_free_recursive(b, c->flags); + trace_kmem_cache_free(_RET_IP_, b); if (unlikely(c->flags & SLAB_TYPESAFE_BY_RCU)) { struct slob_rcu *slob_rcu; slob_rcu = b + (c->size - sizeof(struct slob_rcu)); @@ -668,8 +669,6 @@ void kmem_cache_free(struct kmem_cache *c, void *b) } else { __kmem_cache_free(b, c->size); } - - trace_kmem_cache_free(_RET_IP_, b); } EXPORT_SYMBOL(kmem_cache_free);
diff --git a/mm/slub.c b/mm/slub.c index 5b509cdb37ec..7a7b0bf82b8e 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3192,8 +3192,8 @@ void kmem_cache_free(struct kmem_cache *s, void *x) s = cache_from_obj(s, x); if (!s) return; - slab_free(s, virt_to_head_page(x), x, NULL, 1, _RET_IP_); trace_kmem_cache_free(_RET_IP_, x); + slab_free(s, virt_to_head_page(x), x, NULL, 1, _RET_IP_); } EXPORT_SYMBOL(kmem_cache_free);
From: Yunfeng Ye yeyunfeng@huawei.com
euleros inclusion category: feature feature: Memory debug feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4MTG7
-------------------------------------------------
When pagealloc debug is enabled, block mappings or contiguous hints are no longer used for linear address area. Therefore, support setting page attributes in this case is useful for debugging memory corruption problems.
Signed-off-by: Yunfeng Ye yeyunfeng@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/mm/pageattr.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c index 1b94f5b82654..0bc12dbf2843 100644 --- a/arch/arm64/mm/pageattr.c +++ b/arch/arm64/mm/pageattr.c @@ -81,8 +81,16 @@ static int change_memory_common(unsigned long addr, int numpages, area = find_vm_area((void *)addr); if (!area || end > (unsigned long)area->addr + area->size || - !(area->flags & VM_ALLOC)) + !(area->flags & VM_ALLOC)) { + /* + * When pagealloc debug is enabled, the linear address is + * mapped with NO_BLOCK_MAPPINGS and NO_CONT_MAPPINGS flags. + */ + if (numpages && debug_pagealloc_enabled()) + return __change_memory_common(start, size, + set_mask, clear_mask); return -EINVAL; + }
if (!numpages) return 0;