2021-03-31 16:32:06

by Jisheng Zhang

[permalink] [raw]
Subject: [PATCH v2 0/9] riscv: improve self-protection

From: Jisheng Zhang <[email protected]>

patch1 is a trivial improvement patch to move some functions to .init
section

Then following patches improve self-protection by:

Marking some variables __ro_after_init
Constifing some variables
Enabling ARCH_HAS_STRICT_MODULE_RWX


Since v1:
- no need to move bpf_jit_alloc_exec() and bpf_jit_free_exec() to core
because RV32 uses the default module_alloc() for jit code which also
meets W^X after patch8
- fix a build error caused by local debug code clean up

Jisheng Zhang (9):
riscv: add __init section marker to some functions
riscv: Mark some global variables __ro_after_init
riscv: Constify sys_call_table
riscv: Constify sbi_ipi_ops
riscv: kprobes: Implement alloc_insn_page()
riscv: bpf: Write protect JIT code
riscv: bpf: Avoid breaking W^X on RV64
riscv: module: Create module allocations without exec permissions
riscv: Set ARCH_HAS_STRICT_MODULE_RWX if MMU

arch/riscv/Kconfig | 1 +
arch/riscv/include/asm/smp.h | 4 ++--
arch/riscv/include/asm/syscall.h | 2 +-
arch/riscv/kernel/module.c | 10 ++++++++--
arch/riscv/kernel/probes/kprobes.c | 8 ++++++++
arch/riscv/kernel/sbi.c | 10 +++++-----
arch/riscv/kernel/smp.c | 6 +++---
arch/riscv/kernel/syscall_table.c | 2 +-
arch/riscv/kernel/time.c | 2 +-
arch/riscv/kernel/traps.c | 2 +-
arch/riscv/kernel/vdso.c | 4 ++--
arch/riscv/mm/init.c | 12 ++++++------
arch/riscv/mm/kasan_init.c | 6 +++---
arch/riscv/mm/ptdump.c | 2 +-
arch/riscv/net/bpf_jit_comp64.c | 2 +-
arch/riscv/net/bpf_jit_core.c | 1 +
16 files changed, 45 insertions(+), 29 deletions(-)

--
2.31.0



2021-03-31 16:32:07

by Jisheng Zhang

[permalink] [raw]
Subject: [PATCH v2 1/9] riscv: add __init section marker to some functions

From: Jisheng Zhang <[email protected]>

They are not needed after booting, so mark them as __init to move them
to the __init section.

Signed-off-by: Jisheng Zhang <[email protected]>
---
arch/riscv/kernel/traps.c | 2 +-
arch/riscv/mm/init.c | 6 +++---
arch/riscv/mm/kasan_init.c | 6 +++---
arch/riscv/mm/ptdump.c | 2 +-
4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index 1357abf79570..07fdded10c21 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -197,6 +197,6 @@ int is_valid_bugaddr(unsigned long pc)
#endif /* CONFIG_GENERIC_BUG */

/* stvec & scratch is already set from head.S */
-void trap_init(void)
+void __init trap_init(void)
{
}
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 067583ab1bd7..76bf2de8aa59 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -57,7 +57,7 @@ static void __init zone_sizes_init(void)
free_area_init(max_zone_pfns);
}

-static void setup_zero_page(void)
+static void __init setup_zero_page(void)
{
memset((void *)empty_zero_page, 0, PAGE_SIZE);
}
@@ -75,7 +75,7 @@ static inline void print_mlm(char *name, unsigned long b, unsigned long t)
(((t) - (b)) >> 20));
}

-static void print_vm_layout(void)
+static void __init print_vm_layout(void)
{
pr_notice("Virtual kernel memory layout:\n");
print_mlk("fixmap", (unsigned long)FIXADDR_START,
@@ -557,7 +557,7 @@ static inline void setup_vm_final(void)
#endif /* CONFIG_MMU */

#ifdef CONFIG_STRICT_KERNEL_RWX
-void protect_kernel_text_data(void)
+void __init protect_kernel_text_data(void)
{
unsigned long text_start = (unsigned long)_start;
unsigned long init_text_start = (unsigned long)__init_text_begin;
diff --git a/arch/riscv/mm/kasan_init.c b/arch/riscv/mm/kasan_init.c
index 4f85c6d0ddf8..e1d041ac1534 100644
--- a/arch/riscv/mm/kasan_init.c
+++ b/arch/riscv/mm/kasan_init.c
@@ -60,7 +60,7 @@ asmlinkage void __init kasan_early_init(void)
local_flush_tlb_all();
}

-static void kasan_populate_pte(pmd_t *pmd, unsigned long vaddr, unsigned long end)
+static void __init kasan_populate_pte(pmd_t *pmd, unsigned long vaddr, unsigned long end)
{
phys_addr_t phys_addr;
pte_t *ptep, *base_pte;
@@ -82,7 +82,7 @@ static void kasan_populate_pte(pmd_t *pmd, unsigned long vaddr, unsigned long en
set_pmd(pmd, pfn_pmd(PFN_DOWN(__pa(base_pte)), PAGE_TABLE));
}

-static void kasan_populate_pmd(pgd_t *pgd, unsigned long vaddr, unsigned long end)
+static void __init kasan_populate_pmd(pgd_t *pgd, unsigned long vaddr, unsigned long end)
{
phys_addr_t phys_addr;
pmd_t *pmdp, *base_pmd;
@@ -117,7 +117,7 @@ static void kasan_populate_pmd(pgd_t *pgd, unsigned long vaddr, unsigned long en
set_pgd(pgd, pfn_pgd(PFN_DOWN(__pa(base_pmd)), PAGE_TABLE));
}

-static void kasan_populate_pgd(unsigned long vaddr, unsigned long end)
+static void __init kasan_populate_pgd(unsigned long vaddr, unsigned long end)
{
phys_addr_t phys_addr;
pgd_t *pgdp = pgd_offset_k(vaddr);
diff --git a/arch/riscv/mm/ptdump.c b/arch/riscv/mm/ptdump.c
index ace74dec7492..3b7b6e4d025e 100644
--- a/arch/riscv/mm/ptdump.c
+++ b/arch/riscv/mm/ptdump.c
@@ -331,7 +331,7 @@ static int ptdump_show(struct seq_file *m, void *v)

DEFINE_SHOW_ATTRIBUTE(ptdump);

-static int ptdump_init(void)
+static int __init ptdump_init(void)
{
unsigned int i, j;

--
2.31.0


2021-03-31 16:33:45

by Jisheng Zhang

[permalink] [raw]
Subject: [PATCH v2 4/9] riscv: Constify sbi_ipi_ops

From: Jisheng Zhang <[email protected]>

Constify the sbi_ipi_ops so that it will be placed in the .rodata
section. This will cause attempts to modify it to fail when strict
page permissions are in place.

Signed-off-by: Jisheng Zhang <[email protected]>
---
arch/riscv/include/asm/smp.h | 4 ++--
arch/riscv/kernel/sbi.c | 2 +-
arch/riscv/kernel/smp.c | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h
index df1f7c4cd433..a7d2811f3536 100644
--- a/arch/riscv/include/asm/smp.h
+++ b/arch/riscv/include/asm/smp.h
@@ -46,7 +46,7 @@ int riscv_hartid_to_cpuid(int hartid);
void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out);

/* Set custom IPI operations */
-void riscv_set_ipi_ops(struct riscv_ipi_ops *ops);
+void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops);

/* Clear IPI for current CPU */
void riscv_clear_ipi(void);
@@ -92,7 +92,7 @@ static inline void riscv_cpuid_to_hartid_mask(const struct cpumask *in,
cpumask_set_cpu(boot_cpu_hartid, out);
}

-static inline void riscv_set_ipi_ops(struct riscv_ipi_ops *ops)
+static inline void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops)
{
}

diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
index cbd94a72eaa7..cb848e80865e 100644
--- a/arch/riscv/kernel/sbi.c
+++ b/arch/riscv/kernel/sbi.c
@@ -556,7 +556,7 @@ static void sbi_send_cpumask_ipi(const struct cpumask *target)
sbi_send_ipi(cpumask_bits(&hartid_mask));
}

-static struct riscv_ipi_ops sbi_ipi_ops = {
+static const struct riscv_ipi_ops sbi_ipi_ops = {
.ipi_inject = sbi_send_cpumask_ipi
};

diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c
index 504284d49135..e035124f06dc 100644
--- a/arch/riscv/kernel/smp.c
+++ b/arch/riscv/kernel/smp.c
@@ -85,9 +85,9 @@ static void ipi_stop(void)
wait_for_interrupt();
}

-static struct riscv_ipi_ops *ipi_ops __ro_after_init;
+static const struct riscv_ipi_ops *ipi_ops __ro_after_init;

-void riscv_set_ipi_ops(struct riscv_ipi_ops *ops)
+void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops)
{
ipi_ops = ops;
}
--
2.31.0


2021-03-31 16:34:20

by Jisheng Zhang

[permalink] [raw]
Subject: [PATCH v2 2/9] riscv: Mark some global variables __ro_after_init

From: Jisheng Zhang <[email protected]>

All of these are never modified after init, so they can be
__ro_after_init.

Signed-off-by: Jisheng Zhang <[email protected]>
---
arch/riscv/kernel/sbi.c | 8 ++++----
arch/riscv/kernel/smp.c | 4 ++--
arch/riscv/kernel/time.c | 2 +-
arch/riscv/kernel/vdso.c | 4 ++--
arch/riscv/mm/init.c | 6 +++---
5 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
index d3bf756321a5..cbd94a72eaa7 100644
--- a/arch/riscv/kernel/sbi.c
+++ b/arch/riscv/kernel/sbi.c
@@ -11,14 +11,14 @@
#include <asm/smp.h>

/* default SBI version is 0.1 */
-unsigned long sbi_spec_version = SBI_SPEC_VERSION_DEFAULT;
+unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
EXPORT_SYMBOL(sbi_spec_version);

-static void (*__sbi_set_timer)(uint64_t stime);
-static int (*__sbi_send_ipi)(const unsigned long *hart_mask);
+static void (*__sbi_set_timer)(uint64_t stime) __ro_after_init;
+static int (*__sbi_send_ipi)(const unsigned long *hart_mask) __ro_after_init;
static int (*__sbi_rfence)(int fid, const unsigned long *hart_mask,
unsigned long start, unsigned long size,
- unsigned long arg4, unsigned long arg5);
+ unsigned long arg4, unsigned long arg5) __ro_after_init;

struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
unsigned long arg1, unsigned long arg2,
diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c
index ea028d9e0d24..504284d49135 100644
--- a/arch/riscv/kernel/smp.c
+++ b/arch/riscv/kernel/smp.c
@@ -30,7 +30,7 @@ enum ipi_message_type {
IPI_MAX
};

-unsigned long __cpuid_to_hartid_map[NR_CPUS] = {
+unsigned long __cpuid_to_hartid_map[NR_CPUS] __ro_after_init = {
[0 ... NR_CPUS-1] = INVALID_HARTID
};

@@ -85,7 +85,7 @@ static void ipi_stop(void)
wait_for_interrupt();
}

-static struct riscv_ipi_ops *ipi_ops;
+static struct riscv_ipi_ops *ipi_ops __ro_after_init;

void riscv_set_ipi_ops(struct riscv_ipi_ops *ops)
{
diff --git a/arch/riscv/kernel/time.c b/arch/riscv/kernel/time.c
index 1b432264f7ef..8217b0f67c6c 100644
--- a/arch/riscv/kernel/time.c
+++ b/arch/riscv/kernel/time.c
@@ -11,7 +11,7 @@
#include <asm/processor.h>
#include <asm/timex.h>

-unsigned long riscv_timebase;
+unsigned long riscv_timebase __ro_after_init;
EXPORT_SYMBOL_GPL(riscv_timebase);

void __init time_init(void)
diff --git a/arch/riscv/kernel/vdso.c b/arch/riscv/kernel/vdso.c
index 3f1d35e7c98a..25a3b8849599 100644
--- a/arch/riscv/kernel/vdso.c
+++ b/arch/riscv/kernel/vdso.c
@@ -20,8 +20,8 @@

extern char vdso_start[], vdso_end[];

-static unsigned int vdso_pages;
-static struct page **vdso_pagelist;
+static unsigned int vdso_pages __ro_after_init;
+static struct page **vdso_pagelist __ro_after_init;

/*
* The vDSO data page.
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 76bf2de8aa59..719ec72ef069 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -149,11 +149,11 @@ void __init setup_bootmem(void)
}

#ifdef CONFIG_MMU
-static struct pt_alloc_ops pt_ops;
+static struct pt_alloc_ops pt_ops __ro_after_init;

-unsigned long va_pa_offset;
+unsigned long va_pa_offset __ro_after_init;
EXPORT_SYMBOL(va_pa_offset);
-unsigned long pfn_base;
+unsigned long pfn_base __ro_after_init;
EXPORT_SYMBOL(pfn_base);

pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
--
2.31.0


2021-03-31 16:35:33

by Jisheng Zhang

[permalink] [raw]
Subject: [PATCH v2 3/9] riscv: Constify sys_call_table

From: Jisheng Zhang <[email protected]>

Constify the sys_call_table so that it will be placed in the .rodata
section. This will cause attempts to modify the table to fail when
strict page permissions are in place.

Signed-off-by: Jisheng Zhang <[email protected]>
---
arch/riscv/include/asm/syscall.h | 2 +-
arch/riscv/kernel/syscall_table.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/include/asm/syscall.h b/arch/riscv/include/asm/syscall.h
index 49350c8bd7b0..b933b1583c9f 100644
--- a/arch/riscv/include/asm/syscall.h
+++ b/arch/riscv/include/asm/syscall.h
@@ -15,7 +15,7 @@
#include <linux/err.h>

/* The array of function pointers for syscalls. */
-extern void *sys_call_table[];
+extern void * const sys_call_table[];

/*
* Only the low 32 bits of orig_r0 are meaningful, so we return int.
diff --git a/arch/riscv/kernel/syscall_table.c b/arch/riscv/kernel/syscall_table.c
index f1ead9df96ca..a63c667c27b3 100644
--- a/arch/riscv/kernel/syscall_table.c
+++ b/arch/riscv/kernel/syscall_table.c
@@ -13,7 +13,7 @@
#undef __SYSCALL
#define __SYSCALL(nr, call) [nr] = (call),

-void *sys_call_table[__NR_syscalls] = {
+void * const sys_call_table[__NR_syscalls] = {
[0 ... __NR_syscalls - 1] = sys_ni_syscall,
#include <asm/unistd.h>
};
--
2.31.0


2021-03-31 16:35:54

by Jisheng Zhang

[permalink] [raw]
Subject: [PATCH v2 7/9] riscv: bpf: Avoid breaking W^X on RV64

From: Jisheng Zhang <[email protected]>

bpf_jit_binary_lock_ro() in core not only set RO but also set EXEC
permission when JIT is done, so no need to allocate RWX from the
beginning, and it's not safe.

Signed-off-by: Jisheng Zhang <[email protected]>
---
arch/riscv/net/bpf_jit_comp64.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index b44ff52f84a6..1c61a82a2856 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -1153,7 +1153,7 @@ void *bpf_jit_alloc_exec(unsigned long size)
{
return __vmalloc_node_range(size, PAGE_SIZE, BPF_JIT_REGION_START,
BPF_JIT_REGION_END, GFP_KERNEL,
- PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
+ PAGE_KERNEL, 0, NUMA_NO_NODE,
__builtin_return_address(0));
}

--
2.31.0


2021-03-31 16:35:59

by Jisheng Zhang

[permalink] [raw]
Subject: [PATCH v2 8/9] riscv: module: Create module allocations without exec permissions

From: Jisheng Zhang <[email protected]>

The core code manages the executable permissions of code regions of
modules explicitly, it is not necessary to create the module vmalloc
regions with RWX permissions. Create them with RW- permissions instead.

Signed-off-by: Jisheng Zhang <[email protected]>
---
arch/riscv/kernel/module.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c
index 104fba889cf7..e89367bba7c9 100644
--- a/arch/riscv/kernel/module.c
+++ b/arch/riscv/kernel/module.c
@@ -407,14 +407,20 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
return 0;
}

-#if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
+#ifdef CONFIG_MMU
+
+#ifdef CONFIG_64BIT
#define VMALLOC_MODULE_START \
max(PFN_ALIGN((unsigned long)&_end - SZ_2G), VMALLOC_START)
+#else
+#define VMALLOC_MODULE_START VMALLOC_START
+#endif
+
void *module_alloc(unsigned long size)
{
return __vmalloc_node_range(size, 1, VMALLOC_MODULE_START,
VMALLOC_END, GFP_KERNEL,
- PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
+ PAGE_KERNEL, 0, NUMA_NO_NODE,
__builtin_return_address(0));
}
#endif
--
2.31.0


2021-03-31 16:36:42

by Jisheng Zhang

[permalink] [raw]
Subject: [PATCH v2 5/9] riscv: kprobes: Implement alloc_insn_page()

From: Jisheng Zhang <[email protected]>

Allocate PAGE_KERNEL_READ_EXEC(read only, executable) page for kprobes
insn page. This is to prepare for STRICT_MODULE_RWX.

Signed-off-by: Jisheng Zhang <[email protected]>
---
arch/riscv/kernel/probes/kprobes.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c
index 7e2c78e2ca6b..8c1f7a30aeed 100644
--- a/arch/riscv/kernel/probes/kprobes.c
+++ b/arch/riscv/kernel/probes/kprobes.c
@@ -84,6 +84,14 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
return 0;
}

+void *alloc_insn_page(void)
+{
+ return __vmalloc_node_range(PAGE_SIZE, 1, VMALLOC_START, VMALLOC_END,
+ GFP_KERNEL, PAGE_KERNEL_READ_EXEC,
+ VM_FLUSH_RESET_PERMS, NUMA_NO_NODE,
+ __builtin_return_address(0));
+}
+
/* install breakpoint in text */
void __kprobes arch_arm_kprobe(struct kprobe *p)
{
--
2.31.0


2021-03-31 16:36:49

by Jisheng Zhang

[permalink] [raw]
Subject: [PATCH v2 6/9] riscv: bpf: Write protect JIT code

From: Jisheng Zhang <[email protected]>

Call bpf_jit_binary_lock_ro() to write protect JIT code.

Signed-off-by: Jisheng Zhang <[email protected]>
---
arch/riscv/net/bpf_jit_core.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c
index 3630d447352c..40d5bf113fee 100644
--- a/arch/riscv/net/bpf_jit_core.c
+++ b/arch/riscv/net/bpf_jit_core.c
@@ -152,6 +152,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns);

if (!prog->is_func || extra_pass) {
+ bpf_jit_binary_lock_ro(jit_data->header);
out_offset:
kfree(ctx->offset);
kfree(jit_data);
--
2.31.0


2021-03-31 16:36:55

by Jisheng Zhang

[permalink] [raw]
Subject: [PATCH v2 9/9] riscv: Set ARCH_HAS_STRICT_MODULE_RWX if MMU

From: Jisheng Zhang <[email protected]>

Now we can set ARCH_HAS_STRICT_MODULE_RWX for MMU riscv platforms, this
is good from security perspective.

Signed-off-by: Jisheng Zhang <[email protected]>
---
arch/riscv/Kconfig | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 87d7b52f278f..9716be3674a2 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -28,6 +28,7 @@ config RISCV
select ARCH_HAS_SET_DIRECT_MAP
select ARCH_HAS_SET_MEMORY
select ARCH_HAS_STRICT_KERNEL_RWX if MMU
+ select ARCH_HAS_STRICT_MODULE_RWX if MMU
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
--
2.31.0


2021-04-02 04:08:45

by Anup Patel

[permalink] [raw]
Subject: Re: [PATCH v2 1/9] riscv: add __init section marker to some functions

On Wed, Mar 31, 2021 at 10:00 PM Jisheng Zhang
<[email protected]> wrote:
>
> From: Jisheng Zhang <[email protected]>
>
> They are not needed after booting, so mark them as __init to move them
> to the __init section.
>
> Signed-off-by: Jisheng Zhang <[email protected]>
> ---
> arch/riscv/kernel/traps.c | 2 +-
> arch/riscv/mm/init.c | 6 +++---
> arch/riscv/mm/kasan_init.c | 6 +++---
> arch/riscv/mm/ptdump.c | 2 +-
> 4 files changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
> index 1357abf79570..07fdded10c21 100644
> --- a/arch/riscv/kernel/traps.c
> +++ b/arch/riscv/kernel/traps.c
> @@ -197,6 +197,6 @@ int is_valid_bugaddr(unsigned long pc)
> #endif /* CONFIG_GENERIC_BUG */
>
> /* stvec & scratch is already set from head.S */
> -void trap_init(void)
> +void __init trap_init(void)
> {
> }

The trap_init() is unused currently so you can drop this change
and remove trap_init() as a separate patch.

> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> index 067583ab1bd7..76bf2de8aa59 100644
> --- a/arch/riscv/mm/init.c
> +++ b/arch/riscv/mm/init.c
> @@ -57,7 +57,7 @@ static void __init zone_sizes_init(void)
> free_area_init(max_zone_pfns);
> }
>
> -static void setup_zero_page(void)
> +static void __init setup_zero_page(void)
> {
> memset((void *)empty_zero_page, 0, PAGE_SIZE);
> }
> @@ -75,7 +75,7 @@ static inline void print_mlm(char *name, unsigned long b, unsigned long t)
> (((t) - (b)) >> 20));
> }
>
> -static void print_vm_layout(void)
> +static void __init print_vm_layout(void)
> {
> pr_notice("Virtual kernel memory layout:\n");
> print_mlk("fixmap", (unsigned long)FIXADDR_START,
> @@ -557,7 +557,7 @@ static inline void setup_vm_final(void)
> #endif /* CONFIG_MMU */
>
> #ifdef CONFIG_STRICT_KERNEL_RWX
> -void protect_kernel_text_data(void)
> +void __init protect_kernel_text_data(void)
> {
> unsigned long text_start = (unsigned long)_start;
> unsigned long init_text_start = (unsigned long)__init_text_begin;
> diff --git a/arch/riscv/mm/kasan_init.c b/arch/riscv/mm/kasan_init.c
> index 4f85c6d0ddf8..e1d041ac1534 100644
> --- a/arch/riscv/mm/kasan_init.c
> +++ b/arch/riscv/mm/kasan_init.c
> @@ -60,7 +60,7 @@ asmlinkage void __init kasan_early_init(void)
> local_flush_tlb_all();
> }
>
> -static void kasan_populate_pte(pmd_t *pmd, unsigned long vaddr, unsigned long end)
> +static void __init kasan_populate_pte(pmd_t *pmd, unsigned long vaddr, unsigned long end)
> {
> phys_addr_t phys_addr;
> pte_t *ptep, *base_pte;
> @@ -82,7 +82,7 @@ static void kasan_populate_pte(pmd_t *pmd, unsigned long vaddr, unsigned long en
> set_pmd(pmd, pfn_pmd(PFN_DOWN(__pa(base_pte)), PAGE_TABLE));
> }
>
> -static void kasan_populate_pmd(pgd_t *pgd, unsigned long vaddr, unsigned long end)
> +static void __init kasan_populate_pmd(pgd_t *pgd, unsigned long vaddr, unsigned long end)
> {
> phys_addr_t phys_addr;
> pmd_t *pmdp, *base_pmd;
> @@ -117,7 +117,7 @@ static void kasan_populate_pmd(pgd_t *pgd, unsigned long vaddr, unsigned long en
> set_pgd(pgd, pfn_pgd(PFN_DOWN(__pa(base_pmd)), PAGE_TABLE));
> }
>
> -static void kasan_populate_pgd(unsigned long vaddr, unsigned long end)
> +static void __init kasan_populate_pgd(unsigned long vaddr, unsigned long end)
> {
> phys_addr_t phys_addr;
> pgd_t *pgdp = pgd_offset_k(vaddr);
> diff --git a/arch/riscv/mm/ptdump.c b/arch/riscv/mm/ptdump.c
> index ace74dec7492..3b7b6e4d025e 100644
> --- a/arch/riscv/mm/ptdump.c
> +++ b/arch/riscv/mm/ptdump.c
> @@ -331,7 +331,7 @@ static int ptdump_show(struct seq_file *m, void *v)
>
> DEFINE_SHOW_ATTRIBUTE(ptdump);
>
> -static int ptdump_init(void)
> +static int __init ptdump_init(void)
> {
> unsigned int i, j;
>
> --
> 2.31.0
>
>
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv

Apart from above, looks good to me.

Reviewed-by: Anup Patel <[email protected]>

Regards,
Anup

2021-04-02 04:10:27

by Anup Patel

[permalink] [raw]
Subject: Re: [PATCH v2 2/9] riscv: Mark some global variables __ro_after_init

On Wed, Mar 31, 2021 at 10:01 PM Jisheng Zhang
<[email protected]> wrote:
>
> From: Jisheng Zhang <[email protected]>
>
> All of these are never modified after init, so they can be
> __ro_after_init.
>
> Signed-off-by: Jisheng Zhang <[email protected]>

Looks good to me.

Reviewed-by: Anup Patel <[email protected]>

Regards,
Anup

> ---
> arch/riscv/kernel/sbi.c | 8 ++++----
> arch/riscv/kernel/smp.c | 4 ++--
> arch/riscv/kernel/time.c | 2 +-
> arch/riscv/kernel/vdso.c | 4 ++--
> arch/riscv/mm/init.c | 6 +++---
> 5 files changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
> index d3bf756321a5..cbd94a72eaa7 100644
> --- a/arch/riscv/kernel/sbi.c
> +++ b/arch/riscv/kernel/sbi.c
> @@ -11,14 +11,14 @@
> #include <asm/smp.h>
>
> /* default SBI version is 0.1 */
> -unsigned long sbi_spec_version = SBI_SPEC_VERSION_DEFAULT;
> +unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
> EXPORT_SYMBOL(sbi_spec_version);
>
> -static void (*__sbi_set_timer)(uint64_t stime);
> -static int (*__sbi_send_ipi)(const unsigned long *hart_mask);
> +static void (*__sbi_set_timer)(uint64_t stime) __ro_after_init;
> +static int (*__sbi_send_ipi)(const unsigned long *hart_mask) __ro_after_init;
> static int (*__sbi_rfence)(int fid, const unsigned long *hart_mask,
> unsigned long start, unsigned long size,
> - unsigned long arg4, unsigned long arg5);
> + unsigned long arg4, unsigned long arg5) __ro_after_init;
>
> struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
> unsigned long arg1, unsigned long arg2,
> diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c
> index ea028d9e0d24..504284d49135 100644
> --- a/arch/riscv/kernel/smp.c
> +++ b/arch/riscv/kernel/smp.c
> @@ -30,7 +30,7 @@ enum ipi_message_type {
> IPI_MAX
> };
>
> -unsigned long __cpuid_to_hartid_map[NR_CPUS] = {
> +unsigned long __cpuid_to_hartid_map[NR_CPUS] __ro_after_init = {
> [0 ... NR_CPUS-1] = INVALID_HARTID
> };
>
> @@ -85,7 +85,7 @@ static void ipi_stop(void)
> wait_for_interrupt();
> }
>
> -static struct riscv_ipi_ops *ipi_ops;
> +static struct riscv_ipi_ops *ipi_ops __ro_after_init;
>
> void riscv_set_ipi_ops(struct riscv_ipi_ops *ops)
> {
> diff --git a/arch/riscv/kernel/time.c b/arch/riscv/kernel/time.c
> index 1b432264f7ef..8217b0f67c6c 100644
> --- a/arch/riscv/kernel/time.c
> +++ b/arch/riscv/kernel/time.c
> @@ -11,7 +11,7 @@
> #include <asm/processor.h>
> #include <asm/timex.h>
>
> -unsigned long riscv_timebase;
> +unsigned long riscv_timebase __ro_after_init;
> EXPORT_SYMBOL_GPL(riscv_timebase);
>
> void __init time_init(void)
> diff --git a/arch/riscv/kernel/vdso.c b/arch/riscv/kernel/vdso.c
> index 3f1d35e7c98a..25a3b8849599 100644
> --- a/arch/riscv/kernel/vdso.c
> +++ b/arch/riscv/kernel/vdso.c
> @@ -20,8 +20,8 @@
>
> extern char vdso_start[], vdso_end[];
>
> -static unsigned int vdso_pages;
> -static struct page **vdso_pagelist;
> +static unsigned int vdso_pages __ro_after_init;
> +static struct page **vdso_pagelist __ro_after_init;
>
> /*
> * The vDSO data page.
> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> index 76bf2de8aa59..719ec72ef069 100644
> --- a/arch/riscv/mm/init.c
> +++ b/arch/riscv/mm/init.c
> @@ -149,11 +149,11 @@ void __init setup_bootmem(void)
> }
>
> #ifdef CONFIG_MMU
> -static struct pt_alloc_ops pt_ops;
> +static struct pt_alloc_ops pt_ops __ro_after_init;
>
> -unsigned long va_pa_offset;
> +unsigned long va_pa_offset __ro_after_init;
> EXPORT_SYMBOL(va_pa_offset);
> -unsigned long pfn_base;
> +unsigned long pfn_base __ro_after_init;
> EXPORT_SYMBOL(pfn_base);
>
> pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
> --
> 2.31.0
>
>
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv

2021-04-02 04:11:53

by Anup Patel

[permalink] [raw]
Subject: Re: [PATCH v2 3/9] riscv: Constify sys_call_table

On Wed, Mar 31, 2021 at 10:01 PM Jisheng Zhang
<[email protected]> wrote:
>
> From: Jisheng Zhang <[email protected]>
>
> Constify the sys_call_table so that it will be placed in the .rodata
> section. This will cause attempts to modify the table to fail when
> strict page permissions are in place.
>
> Signed-off-by: Jisheng Zhang <[email protected]>

Looks good to me.

Reviewed-by: Anup Patel <[email protected]>

Regards,
Anup

> ---
> arch/riscv/include/asm/syscall.h | 2 +-
> arch/riscv/kernel/syscall_table.c | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/riscv/include/asm/syscall.h b/arch/riscv/include/asm/syscall.h
> index 49350c8bd7b0..b933b1583c9f 100644
> --- a/arch/riscv/include/asm/syscall.h
> +++ b/arch/riscv/include/asm/syscall.h
> @@ -15,7 +15,7 @@
> #include <linux/err.h>
>
> /* The array of function pointers for syscalls. */
> -extern void *sys_call_table[];
> +extern void * const sys_call_table[];
>
> /*
> * Only the low 32 bits of orig_r0 are meaningful, so we return int.
> diff --git a/arch/riscv/kernel/syscall_table.c b/arch/riscv/kernel/syscall_table.c
> index f1ead9df96ca..a63c667c27b3 100644
> --- a/arch/riscv/kernel/syscall_table.c
> +++ b/arch/riscv/kernel/syscall_table.c
> @@ -13,7 +13,7 @@
> #undef __SYSCALL
> #define __SYSCALL(nr, call) [nr] = (call),
>
> -void *sys_call_table[__NR_syscalls] = {
> +void * const sys_call_table[__NR_syscalls] = {
> [0 ... __NR_syscalls - 1] = sys_ni_syscall,
> #include <asm/unistd.h>
> };
> --
> 2.31.0
>
>
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv

2021-04-02 04:14:09

by Anup Patel

[permalink] [raw]
Subject: Re: [PATCH v2 4/9] riscv: Constify sbi_ipi_ops

On Wed, Mar 31, 2021 at 10:02 PM Jisheng Zhang
<[email protected]> wrote:
>
> From: Jisheng Zhang <[email protected]>
>
> Constify the sbi_ipi_ops so that it will be placed in the .rodata
> section. This will cause attempts to modify it to fail when strict
> page permissions are in place.
>
> Signed-off-by: Jisheng Zhang <[email protected]>

Looks good to me.

Reviewed-by: Anup Patel <[email protected]>

Regards,
Anup

> ---
> arch/riscv/include/asm/smp.h | 4 ++--
> arch/riscv/kernel/sbi.c | 2 +-
> arch/riscv/kernel/smp.c | 4 ++--
> 3 files changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h
> index df1f7c4cd433..a7d2811f3536 100644
> --- a/arch/riscv/include/asm/smp.h
> +++ b/arch/riscv/include/asm/smp.h
> @@ -46,7 +46,7 @@ int riscv_hartid_to_cpuid(int hartid);
> void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out);
>
> /* Set custom IPI operations */
> -void riscv_set_ipi_ops(struct riscv_ipi_ops *ops);
> +void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops);
>
> /* Clear IPI for current CPU */
> void riscv_clear_ipi(void);
> @@ -92,7 +92,7 @@ static inline void riscv_cpuid_to_hartid_mask(const struct cpumask *in,
> cpumask_set_cpu(boot_cpu_hartid, out);
> }
>
> -static inline void riscv_set_ipi_ops(struct riscv_ipi_ops *ops)
> +static inline void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops)
> {
> }
>
> diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
> index cbd94a72eaa7..cb848e80865e 100644
> --- a/arch/riscv/kernel/sbi.c
> +++ b/arch/riscv/kernel/sbi.c
> @@ -556,7 +556,7 @@ static void sbi_send_cpumask_ipi(const struct cpumask *target)
> sbi_send_ipi(cpumask_bits(&hartid_mask));
> }
>
> -static struct riscv_ipi_ops sbi_ipi_ops = {
> +static const struct riscv_ipi_ops sbi_ipi_ops = {
> .ipi_inject = sbi_send_cpumask_ipi
> };
>
> diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c
> index 504284d49135..e035124f06dc 100644
> --- a/arch/riscv/kernel/smp.c
> +++ b/arch/riscv/kernel/smp.c
> @@ -85,9 +85,9 @@ static void ipi_stop(void)
> wait_for_interrupt();
> }
>
> -static struct riscv_ipi_ops *ipi_ops __ro_after_init;
> +static const struct riscv_ipi_ops *ipi_ops __ro_after_init;
>
> -void riscv_set_ipi_ops(struct riscv_ipi_ops *ops)
> +void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops)
> {
> ipi_ops = ops;
> }
> --
> 2.31.0
>
>
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv

2021-04-02 04:17:10

by Anup Patel

[permalink] [raw]
Subject: Re: [PATCH v2 9/9] riscv: Set ARCH_HAS_STRICT_MODULE_RWX if MMU

On Wed, Mar 31, 2021 at 10:05 PM Jisheng Zhang
<[email protected]> wrote:
>
> From: Jisheng Zhang <[email protected]>
>
> Now we can set ARCH_HAS_STRICT_MODULE_RWX for MMU riscv platforms, this
> is good from security perspective.
>
> Signed-off-by: Jisheng Zhang <[email protected]>

Looks good to me.

Reviewed-by: Anup Patel <[email protected]>

Regards,
Anup

> ---
> arch/riscv/Kconfig | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index 87d7b52f278f..9716be3674a2 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -28,6 +28,7 @@ config RISCV
> select ARCH_HAS_SET_DIRECT_MAP
> select ARCH_HAS_SET_MEMORY
> select ARCH_HAS_STRICT_KERNEL_RWX if MMU
> + select ARCH_HAS_STRICT_MODULE_RWX if MMU
> select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
> select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
> select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
> --
> 2.31.0
>
>
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv

2021-04-02 04:17:26

by Anup Patel

[permalink] [raw]
Subject: Re: [PATCH v2 5/9] riscv: kprobes: Implement alloc_insn_page()

On Wed, Mar 31, 2021 at 10:02 PM Jisheng Zhang
<[email protected]> wrote:
>
> From: Jisheng Zhang <[email protected]>
>
> Allocate PAGE_KERNEL_READ_EXEC(read only, executable) page for kprobes
> insn page. This is to prepare for STRICT_MODULE_RWX.
>
> Signed-off-by: Jisheng Zhang <[email protected]>

Looks good to me.

Reviewed-by: Anup Patel <[email protected]>

Regards,
Anup

> ---
> arch/riscv/kernel/probes/kprobes.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c
> index 7e2c78e2ca6b..8c1f7a30aeed 100644
> --- a/arch/riscv/kernel/probes/kprobes.c
> +++ b/arch/riscv/kernel/probes/kprobes.c
> @@ -84,6 +84,14 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
> return 0;
> }
>
> +void *alloc_insn_page(void)
> +{
> + return __vmalloc_node_range(PAGE_SIZE, 1, VMALLOC_START, VMALLOC_END,
> + GFP_KERNEL, PAGE_KERNEL_READ_EXEC,
> + VM_FLUSH_RESET_PERMS, NUMA_NO_NODE,
> + __builtin_return_address(0));
> +}
> +
> /* install breakpoint in text */
> void __kprobes arch_arm_kprobe(struct kprobe *p)
> {
> --
> 2.31.0
>
>
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv

2021-04-02 04:19:29

by Anup Patel

[permalink] [raw]
Subject: Re: [PATCH v2 8/9] riscv: module: Create module allocations without exec permissions

On Wed, Mar 31, 2021 at 10:04 PM Jisheng Zhang
<[email protected]> wrote:
>
> From: Jisheng Zhang <[email protected]>
>
> The core code manages the executable permissions of code regions of
> modules explicitly, it is not necessary to create the module vmalloc
> regions with RWX permissions. Create them with RW- permissions instead.
>
> Signed-off-by: Jisheng Zhang <[email protected]>

Looks good to me.

Reviewed-by: Anup Patel <[email protected]>

Regards,
Anup

> ---
> arch/riscv/kernel/module.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c
> index 104fba889cf7..e89367bba7c9 100644
> --- a/arch/riscv/kernel/module.c
> +++ b/arch/riscv/kernel/module.c
> @@ -407,14 +407,20 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
> return 0;
> }
>
> -#if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
> +#ifdef CONFIG_MMU
> +
> +#ifdef CONFIG_64BIT
> #define VMALLOC_MODULE_START \
> max(PFN_ALIGN((unsigned long)&_end - SZ_2G), VMALLOC_START)
> +#else
> +#define VMALLOC_MODULE_START VMALLOC_START
> +#endif
> +
> void *module_alloc(unsigned long size)
> {
> return __vmalloc_node_range(size, 1, VMALLOC_MODULE_START,
> VMALLOC_END, GFP_KERNEL,
> - PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
> + PAGE_KERNEL, 0, NUMA_NO_NODE,
> __builtin_return_address(0));
> }
> #endif
> --
> 2.31.0
>
>
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv

2021-04-12 05:39:48

by Jisheng Zhang

[permalink] [raw]
Subject: Re: [PATCH v2 1/9] riscv: add __init section marker to some functions

On Fri, 2 Apr 2021 09:38:02 +0530
Anup Patel <[email protected]> wrote:


>
>
> On Wed, Mar 31, 2021 at 10:00 PM Jisheng Zhang
> <[email protected]> wrote:
> >
> > From: Jisheng Zhang <[email protected]>
> >
> > They are not needed after booting, so mark them as __init to move them
> > to the __init section.
> >
> > Signed-off-by: Jisheng Zhang <[email protected]>
> > ---
> > arch/riscv/kernel/traps.c | 2 +-
> > arch/riscv/mm/init.c | 6 +++---
> > arch/riscv/mm/kasan_init.c | 6 +++---
> > arch/riscv/mm/ptdump.c | 2 +-
> > 4 files changed, 8 insertions(+), 8 deletions(-)
> >
> > diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
> > index 1357abf79570..07fdded10c21 100644
> > --- a/arch/riscv/kernel/traps.c
> > +++ b/arch/riscv/kernel/traps.c
> > @@ -197,6 +197,6 @@ int is_valid_bugaddr(unsigned long pc)
> > #endif /* CONFIG_GENERIC_BUG */
> >
> > /* stvec & scratch is already set from head.S */
> > -void trap_init(void)
> > +void __init trap_init(void)
> > {
> > }
>
> The trap_init() is unused currently so you can drop this change
> and remove trap_init() as a separate patch.

the kernel init/main.c expects a trap_init() implementation in architecture
code. Some architecture's implementation is NULL, similar as riscv, for example,
arm, powerpc and so on. However I think you are right, the trap_init() can be
removed, we need a trivial series to provide a __weak but NULL trap_init()
implementation in init/main.c then remove all NULL implementation from
all arch. I can take the task to do the clean up.

>
> > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> > index 067583ab1bd7..76bf2de8aa59 100644
> > --- a/arch/riscv/mm/init.c
> > +++ b/arch/riscv/mm/init.c
> > @@ -57,7 +57,7 @@ static void __init zone_sizes_init(void)
> > free_area_init(max_zone_pfns);
> > }
> >
> > -static void setup_zero_page(void)
> > +static void __init setup_zero_page(void)
> > {
> > memset((void *)empty_zero_page, 0, PAGE_SIZE);

I think the zero page is already initialized as "0" because empty_zero_page
sits in .bss section. So this setup_zero_page() function can be removed. I
will send a newer version later.

thanks