Skip to content

Commit 95e6d3b

Browse files
committed
Merge tag 'loongarch-fixes-7.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
Pull LoongArch fixes from Huacai Chen: "Rework KASLR to avoid initrd overlap, remove some unused code to avoid a build warning, fix some bugs in kprobes and KVM" * tag 'loongarch-fixes-7.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson: LoongArch: KVM: Move some variable declarations to paravirt.h LoongArch: kprobes: Fix handling of fatal unrecoverable recursions LoongArch: kprobes: Use larch_insn_text_copy() to patch instructions LoongArch: Remove unused code to avoid build warning LoongArch: Avoid initrd overlap during kernel relocation LoongArch: Skip relocation-time KASLR if already applied efi/loongarch: Randomize kernel preferred address for KASLR
2 parents c8561c7 + 4a09f4a commit 95e6d3b

8 files changed

Lines changed: 88 additions & 15 deletions

File tree

arch/loongarch/include/asm/efi.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ static inline unsigned long efi_get_kimg_min_align(void)
3030
return SZ_2M;
3131
}
3232

33-
#define EFI_KIMG_PREFERRED_ADDRESS PHYSADDR(VMLINUX_LOAD_ADDRESS)
33+
unsigned long efi_get_kimg_kaslr_address(void);
34+
35+
#define EFI_KIMG_PREFERRED_ADDRESS efi_get_kimg_kaslr_address()
3436

3537
#endif /* _ASM_LOONGARCH_EFI_H */

arch/loongarch/include/asm/paravirt.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44

55
#ifdef CONFIG_PARAVIRT
66

7+
#include <linux/jump_label.h>
8+
9+
DECLARE_STATIC_KEY_FALSE(virt_preempt_key);
10+
DECLARE_STATIC_KEY_FALSE(virt_spin_lock_key);
11+
DECLARE_PER_CPU(struct kvm_steal_time, steal_time);
12+
713
int __init pv_ipi_init(void);
814
int __init pv_time_init(void);
915
int __init pv_spinlock_init(void);

arch/loongarch/include/asm/qspinlock.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@
33
#define _ASM_LOONGARCH_QSPINLOCK_H
44

55
#include <asm/kvm_para.h>
6-
#include <linux/jump_label.h>
6+
#include <asm/paravirt.h>
77

88
#ifdef CONFIG_PARAVIRT
9-
DECLARE_STATIC_KEY_FALSE(virt_preempt_key);
10-
DECLARE_STATIC_KEY_FALSE(virt_spin_lock_key);
11-
DECLARE_PER_CPU(struct kvm_steal_time, steal_time);
129

1310
#define virt_spin_lock virt_spin_lock
1411

arch/loongarch/kernel/kprobes.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,18 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
6060
/* Install breakpoint in text */
6161
void arch_arm_kprobe(struct kprobe *p)
6262
{
63-
*p->addr = KPROBE_BP_INSN;
64-
flush_insn_slot(p);
63+
u32 insn = KPROBE_BP_INSN;
64+
65+
larch_insn_text_copy(p->addr, &insn, LOONGARCH_INSN_SIZE);
6566
}
6667
NOKPROBE_SYMBOL(arch_arm_kprobe);
6768

6869
/* Remove breakpoint from text */
6970
void arch_disarm_kprobe(struct kprobe *p)
7071
{
71-
*p->addr = p->opcode;
72-
flush_insn_slot(p);
72+
u32 insn = p->opcode;
73+
74+
larch_insn_text_copy(p->addr, &insn, LOONGARCH_INSN_SIZE);
7375
}
7476
NOKPROBE_SYMBOL(arch_disarm_kprobe);
7577

@@ -184,16 +186,16 @@ static bool reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
184186
struct kprobe_ctlblk *kcb)
185187
{
186188
switch (kcb->kprobe_status) {
187-
case KPROBE_HIT_SS:
188189
case KPROBE_HIT_SSDONE:
189190
case KPROBE_HIT_ACTIVE:
190191
kprobes_inc_nmissed_count(p);
191192
setup_singlestep(p, regs, kcb, 1);
192193
break;
194+
case KPROBE_HIT_SS:
193195
case KPROBE_REENTER:
194196
pr_warn("Failed to recover from reentered kprobes.\n");
195197
dump_kprobe(p);
196-
WARN_ON_ONCE(1);
198+
BUG();
197199
break;
198200
default:
199201
WARN_ON(1);

arch/loongarch/kernel/relocate.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,23 @@ early_param("nokaslr", nokaslr);
134134

135135
#define KASLR_DISABLED_MESSAGE "KASLR is disabled by %s in %s cmdline.\n"
136136

137+
/*
138+
* Note: strictly-defined KASLR means the kernel's final runtime address
139+
* has a random offset from the kernel's load address, which is implemented
140+
* in relocate.c; broadly-defined KALSR means the kernel's final runtime
141+
* address has a random offset from the kernel's link address (a.k.a.
142+
* VMLINUX_LOAD_ADDRESS), which also include the efistlub implementation,
143+
* kexec_file implementation and QEMU direct kernel boot. kaslr_disabled()
144+
* return true only means strictly-defined KASLR is disabled.
145+
*/
137146
static inline __init bool kaslr_disabled(void)
138147
{
139148
char *str;
140149
const char *builtin_cmdline = CONFIG_CMDLINE;
141150

151+
if (kaslr_offset())
152+
return true; /* KASLR is performed during early boot. */
153+
142154
str = strstr(builtin_cmdline, "nokaslr");
143155
if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) {
144156
pr_info(KASLR_DISABLED_MESSAGE, "\'nokaslr\'", "built-in");
@@ -210,14 +222,52 @@ static inline void __init *determine_relocation_address(void)
210222
return RELOCATED_KASLR(destination);
211223
}
212224

225+
static unsigned long __init determine_initrd_address(unsigned long *size)
226+
{
227+
unsigned long start = 0;
228+
unsigned long key_length;
229+
char *p, *endp, *key = "initrd=";
230+
231+
key_length = strlen(key);
232+
p = strstr(boot_command_line, key);
233+
234+
if (!p) {
235+
key = "initrdmem=";
236+
key_length = strlen(key);
237+
p = strstr(boot_command_line, key);
238+
}
239+
240+
if (p == boot_command_line || (p > boot_command_line && *(p - 1) == ' ')) {
241+
p += key_length;
242+
start = memparse(p, &endp);
243+
if (*endp == ',')
244+
*size = memparse(endp + 1, NULL);
245+
}
246+
247+
return start;
248+
}
249+
213250
static inline int __init relocation_addr_valid(void *location_new)
214251
{
252+
unsigned long kernel_start, kernel_size;
253+
unsigned long initrd_start, initrd_size = 0;
254+
215255
if ((unsigned long)location_new & 0x00000ffff)
216256
return 0; /* Inappropriately aligned new location */
217257

218258
if ((unsigned long)location_new < (unsigned long)_end)
219259
return 0; /* New location overlaps original kernel */
220260

261+
initrd_start = determine_initrd_address(&initrd_size);
262+
if (initrd_start && initrd_size) {
263+
kernel_start = PHYSADDR(location_new);
264+
kernel_size = (unsigned long)_end - (unsigned long)_text;
265+
266+
if (kernel_start < (initrd_start + initrd_size) &&
267+
initrd_start < (kernel_start + kernel_size))
268+
return 0; /* initrd/initramfs overlaps kernel */
269+
}
270+
221271
return 1;
222272
}
223273
#endif

arch/loongarch/mm/init.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,7 @@ void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
123123
{
124124
unsigned long start_pfn = start >> PAGE_SHIFT;
125125
unsigned long nr_pages = size >> PAGE_SHIFT;
126-
struct page *page = pfn_to_page(start_pfn);
127126

128-
/* With altmap the first mapped page is offset from @start */
129-
if (altmap)
130-
page += vmem_altmap_offset(altmap);
131127
__remove_pages(start_pfn, nr_pages, altmap);
132128
}
133129
#endif

drivers/firmware/efi/libstub/efi-stub-helper.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ efi_status_t efi_parse_options(char const *cmdline)
7979
efi_noinitrd = true;
8080
} else if (IS_ENABLED(CONFIG_X86_64) && !strcmp(param, "no5lvl")) {
8181
efi_no5lvl = true;
82+
} else if (IS_ENABLED(CONFIG_LOONGARCH) &&
83+
IS_ENABLED(CONFIG_HIBERNATION) &&
84+
!strcmp(param, "resume") && val) {
85+
efi_nokaslr = true; /* LoongArch can't KASLR for hibernation */
8286
} else if (IS_ENABLED(CONFIG_ARCH_HAS_MEM_ENCRYPT) &&
8387
!strcmp(param, "mem_encrypt") && val) {
8488
if (parse_option_str(val, "on"))

drivers/firmware/efi/libstub/loongarch.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,22 @@ void efi_cache_sync_image(unsigned long image_base, unsigned long alloc_size)
2323
asm volatile ("ibar 0" ::: "memory");
2424
}
2525

26+
unsigned long efi_get_kimg_kaslr_address(void)
27+
{
28+
unsigned int random_offset = 0;
29+
30+
#ifdef CONFIG_RANDOMIZE_BASE
31+
if (!efi_nokaslr) {
32+
efi_get_random_bytes(sizeof(random_offset), (u8 *)&random_offset);
33+
random_offset ^= (random_get_entropy() << 16);
34+
random_offset &= (CONFIG_RANDOMIZE_BASE_MAX_OFFSET - 1);
35+
random_offset = ALIGN(random_offset + SZ_64K, SZ_64K);
36+
}
37+
#endif
38+
39+
return PHYSADDR(VMLINUX_LOAD_ADDRESS) + random_offset;
40+
}
41+
2642
struct exit_boot_struct {
2743
efi_memory_desc_t *runtime_map;
2844
int runtime_entry_count;

0 commit comments

Comments
 (0)