hc
2024-05-10 10ebd8556b7990499c896a550e3d416b444211e6
kernel/arch/powerpc/kernel/security.c
....@@ -7,6 +7,8 @@
77 #include <linux/cpu.h>
88 #include <linux/kernel.h>
99 #include <linux/device.h>
10
+#include <linux/nospec.h>
11
+#include <linux/prctl.h>
1012 #include <linux/seq_buf.h>
1113
1214 #include <asm/asm-prototypes.h>
....@@ -14,17 +16,18 @@
1416 #include <asm/debugfs.h>
1517 #include <asm/security_features.h>
1618 #include <asm/setup.h>
19
+#include <asm/inst.h>
1720
1821
19
-unsigned long powerpc_security_features __read_mostly = SEC_FTR_DEFAULT;
22
+u64 powerpc_security_features __read_mostly = SEC_FTR_DEFAULT;
2023
21
-enum count_cache_flush_type {
22
- COUNT_CACHE_FLUSH_NONE = 0x1,
23
- COUNT_CACHE_FLUSH_SW = 0x2,
24
- COUNT_CACHE_FLUSH_HW = 0x4,
24
+enum branch_cache_flush_type {
25
+ BRANCH_CACHE_FLUSH_NONE = 0x1,
26
+ BRANCH_CACHE_FLUSH_SW = 0x2,
27
+ BRANCH_CACHE_FLUSH_HW = 0x4,
2528 };
26
-static enum count_cache_flush_type count_cache_flush_type = COUNT_CACHE_FLUSH_NONE;
27
-static bool link_stack_flush_enabled;
29
+static enum branch_cache_flush_type count_cache_flush_type = BRANCH_CACHE_FLUSH_NONE;
30
+static enum branch_cache_flush_type link_stack_flush_type = BRANCH_CACHE_FLUSH_NONE;
2831
2932 bool barrier_nospec_enabled;
3033 static bool no_nospec;
....@@ -95,16 +98,25 @@
9598 return 0;
9699 }
97100
98
-DEFINE_SIMPLE_ATTRIBUTE(fops_barrier_nospec,
99
- barrier_nospec_get, barrier_nospec_set, "%llu\n");
101
+DEFINE_DEBUGFS_ATTRIBUTE(fops_barrier_nospec, barrier_nospec_get,
102
+ barrier_nospec_set, "%llu\n");
100103
101104 static __init int barrier_nospec_debugfs_init(void)
102105 {
103
- debugfs_create_file("barrier_nospec", 0600, powerpc_debugfs_root, NULL,
104
- &fops_barrier_nospec);
106
+ debugfs_create_file_unsafe("barrier_nospec", 0600,
107
+ powerpc_debugfs_root, NULL,
108
+ &fops_barrier_nospec);
105109 return 0;
106110 }
107111 device_initcall(barrier_nospec_debugfs_init);
112
+
113
+static __init int security_feature_debugfs_init(void)
114
+{
115
+ debugfs_create_x64("security_features", 0400, powerpc_debugfs_root,
116
+ &powerpc_security_features);
117
+ return 0;
118
+}
119
+device_initcall(security_feature_debugfs_init);
108120 #endif /* CONFIG_DEBUG_FS */
109121
110122 #if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_BOOK3S_64)
....@@ -207,22 +219,23 @@
207219 if (ccd)
208220 seq_buf_printf(&s, "Indirect branch cache disabled");
209221
210
- if (link_stack_flush_enabled)
211
- seq_buf_printf(&s, ", Software link stack flush");
212
-
213
- } else if (count_cache_flush_type != COUNT_CACHE_FLUSH_NONE) {
222
+ } else if (count_cache_flush_type != BRANCH_CACHE_FLUSH_NONE) {
214223 seq_buf_printf(&s, "Mitigation: Software count cache flush");
215224
216
- if (count_cache_flush_type == COUNT_CACHE_FLUSH_HW)
225
+ if (count_cache_flush_type == BRANCH_CACHE_FLUSH_HW)
217226 seq_buf_printf(&s, " (hardware accelerated)");
218
-
219
- if (link_stack_flush_enabled)
220
- seq_buf_printf(&s, ", Software link stack flush");
221227
222228 } else if (btb_flush_enabled) {
223229 seq_buf_printf(&s, "Mitigation: Branch predictor state flush");
224230 } else {
225231 seq_buf_printf(&s, "Vulnerable");
232
+ }
233
+
234
+ if (bcs || ccd || count_cache_flush_type != BRANCH_CACHE_FLUSH_NONE) {
235
+ if (link_stack_flush_type != BRANCH_CACHE_FLUSH_NONE)
236
+ seq_buf_printf(&s, ", Software link stack flush");
237
+ if (link_stack_flush_type == BRANCH_CACHE_FLUSH_HW)
238
+ seq_buf_printf(&s, " (hardware accelerated)");
226239 }
227240
228241 seq_buf_printf(&s, "\n");
....@@ -349,6 +362,40 @@
349362 return sprintf(buf, "Vulnerable\n");
350363 }
351364
365
+static int ssb_prctl_get(struct task_struct *task)
366
+{
367
+ if (stf_enabled_flush_types == STF_BARRIER_NONE)
368
+ /*
369
+ * We don't have an explicit signal from firmware that we're
370
+ * vulnerable or not, we only have certain CPU revisions that
371
+ * are known to be vulnerable.
372
+ *
373
+ * We assume that if we're on another CPU, where the barrier is
374
+ * NONE, then we are not vulnerable.
375
+ */
376
+ return PR_SPEC_NOT_AFFECTED;
377
+ else
378
+ /*
379
+ * If we do have a barrier type then we are vulnerable. The
380
+ * barrier is not a global or per-process mitigation, so the
381
+ * only value we can report here is PR_SPEC_ENABLE, which
382
+ * appears as "vulnerable" in /proc.
383
+ */
384
+ return PR_SPEC_ENABLE;
385
+
386
+ return -EINVAL;
387
+}
388
+
389
+int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
390
+{
391
+ switch (which) {
392
+ case PR_SPEC_STORE_BYPASS:
393
+ return ssb_prctl_get(task);
394
+ default:
395
+ return -ENODEV;
396
+ }
397
+}
398
+
352399 #ifdef CONFIG_DEBUG_FS
353400 static int stf_barrier_set(void *data, u64 val)
354401 {
....@@ -374,68 +421,105 @@
374421 return 0;
375422 }
376423
377
-DEFINE_SIMPLE_ATTRIBUTE(fops_stf_barrier, stf_barrier_get, stf_barrier_set, "%llu\n");
424
+DEFINE_DEBUGFS_ATTRIBUTE(fops_stf_barrier, stf_barrier_get, stf_barrier_set,
425
+ "%llu\n");
378426
379427 static __init int stf_barrier_debugfs_init(void)
380428 {
381
- debugfs_create_file("stf_barrier", 0600, powerpc_debugfs_root, NULL, &fops_stf_barrier);
429
+ debugfs_create_file_unsafe("stf_barrier", 0600, powerpc_debugfs_root,
430
+ NULL, &fops_stf_barrier);
382431 return 0;
383432 }
384433 device_initcall(stf_barrier_debugfs_init);
385434 #endif /* CONFIG_DEBUG_FS */
386435
387
-static void no_count_cache_flush(void)
436
+static void update_branch_cache_flush(void)
388437 {
389
- count_cache_flush_type = COUNT_CACHE_FLUSH_NONE;
390
- pr_info("count-cache-flush: software flush disabled.\n");
438
+ u32 *site;
439
+
440
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
441
+ site = &patch__call_kvm_flush_link_stack;
442
+ // This controls the branch from guest_exit_cont to kvm_flush_link_stack
443
+ if (link_stack_flush_type == BRANCH_CACHE_FLUSH_NONE) {
444
+ patch_instruction_site(site, ppc_inst(PPC_INST_NOP));
445
+ } else {
446
+ // Could use HW flush, but that could also flush count cache
447
+ patch_branch_site(site, (u64)&kvm_flush_link_stack, BRANCH_SET_LINK);
448
+ }
449
+#endif
450
+
451
+ // Patch out the bcctr first, then nop the rest
452
+ site = &patch__call_flush_branch_caches3;
453
+ patch_instruction_site(site, ppc_inst(PPC_INST_NOP));
454
+ site = &patch__call_flush_branch_caches2;
455
+ patch_instruction_site(site, ppc_inst(PPC_INST_NOP));
456
+ site = &patch__call_flush_branch_caches1;
457
+ patch_instruction_site(site, ppc_inst(PPC_INST_NOP));
458
+
459
+ // This controls the branch from _switch to flush_branch_caches
460
+ if (count_cache_flush_type == BRANCH_CACHE_FLUSH_NONE &&
461
+ link_stack_flush_type == BRANCH_CACHE_FLUSH_NONE) {
462
+ // Nothing to be done
463
+
464
+ } else if (count_cache_flush_type == BRANCH_CACHE_FLUSH_HW &&
465
+ link_stack_flush_type == BRANCH_CACHE_FLUSH_HW) {
466
+ // Patch in the bcctr last
467
+ site = &patch__call_flush_branch_caches1;
468
+ patch_instruction_site(site, ppc_inst(0x39207fff)); // li r9,0x7fff
469
+ site = &patch__call_flush_branch_caches2;
470
+ patch_instruction_site(site, ppc_inst(0x7d2903a6)); // mtctr r9
471
+ site = &patch__call_flush_branch_caches3;
472
+ patch_instruction_site(site, ppc_inst(PPC_INST_BCCTR_FLUSH));
473
+
474
+ } else {
475
+ patch_branch_site(site, (u64)&flush_branch_caches, BRANCH_SET_LINK);
476
+
477
+ // If we just need to flush the link stack, early return
478
+ if (count_cache_flush_type == BRANCH_CACHE_FLUSH_NONE) {
479
+ patch_instruction_site(&patch__flush_link_stack_return,
480
+ ppc_inst(PPC_INST_BLR));
481
+
482
+ // If we have flush instruction, early return
483
+ } else if (count_cache_flush_type == BRANCH_CACHE_FLUSH_HW) {
484
+ patch_instruction_site(&patch__flush_count_cache_return,
485
+ ppc_inst(PPC_INST_BLR));
486
+ }
487
+ }
391488 }
392489
393
-static void toggle_count_cache_flush(bool enable)
490
+static void toggle_branch_cache_flush(bool enable)
394491 {
395
- if (!security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE) &&
396
- !security_ftr_enabled(SEC_FTR_FLUSH_LINK_STACK))
397
- enable = false;
492
+ if (!enable || !security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) {
493
+ if (count_cache_flush_type != BRANCH_CACHE_FLUSH_NONE)
494
+ count_cache_flush_type = BRANCH_CACHE_FLUSH_NONE;
398495
399
- if (!enable) {
400
- patch_instruction_site(&patch__call_flush_count_cache, PPC_INST_NOP);
401
-#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
402
- patch_instruction_site(&patch__call_kvm_flush_link_stack, PPC_INST_NOP);
403
-#endif
404
- pr_info("link-stack-flush: software flush disabled.\n");
405
- link_stack_flush_enabled = false;
406
- no_count_cache_flush();
407
- return;
496
+ pr_info("count-cache-flush: flush disabled.\n");
497
+ } else {
498
+ if (security_ftr_enabled(SEC_FTR_BCCTR_FLUSH_ASSIST)) {
499
+ count_cache_flush_type = BRANCH_CACHE_FLUSH_HW;
500
+ pr_info("count-cache-flush: hardware flush enabled.\n");
501
+ } else {
502
+ count_cache_flush_type = BRANCH_CACHE_FLUSH_SW;
503
+ pr_info("count-cache-flush: software flush enabled.\n");
504
+ }
408505 }
409506
410
- // This enables the branch from _switch to flush_count_cache
411
- patch_branch_site(&patch__call_flush_count_cache,
412
- (u64)&flush_count_cache, BRANCH_SET_LINK);
507
+ if (!enable || !security_ftr_enabled(SEC_FTR_FLUSH_LINK_STACK)) {
508
+ if (link_stack_flush_type != BRANCH_CACHE_FLUSH_NONE)
509
+ link_stack_flush_type = BRANCH_CACHE_FLUSH_NONE;
413510
414
-#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
415
- // This enables the branch from guest_exit_cont to kvm_flush_link_stack
416
- patch_branch_site(&patch__call_kvm_flush_link_stack,
417
- (u64)&kvm_flush_link_stack, BRANCH_SET_LINK);
418
-#endif
419
-
420
- pr_info("link-stack-flush: software flush enabled.\n");
421
- link_stack_flush_enabled = true;
422
-
423
- // If we just need to flush the link stack, patch an early return
424
- if (!security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) {
425
- patch_instruction_site(&patch__flush_link_stack_return, PPC_INST_BLR);
426
- no_count_cache_flush();
427
- return;
511
+ pr_info("link-stack-flush: flush disabled.\n");
512
+ } else {
513
+ if (security_ftr_enabled(SEC_FTR_BCCTR_LINK_FLUSH_ASSIST)) {
514
+ link_stack_flush_type = BRANCH_CACHE_FLUSH_HW;
515
+ pr_info("link-stack-flush: hardware flush enabled.\n");
516
+ } else {
517
+ link_stack_flush_type = BRANCH_CACHE_FLUSH_SW;
518
+ pr_info("link-stack-flush: software flush enabled.\n");
519
+ }
428520 }
429521
430
- if (!security_ftr_enabled(SEC_FTR_BCCTR_FLUSH_ASSIST)) {
431
- count_cache_flush_type = COUNT_CACHE_FLUSH_SW;
432
- pr_info("count-cache-flush: full software flush sequence enabled.\n");
433
- return;
434
- }
435
-
436
- patch_instruction_site(&patch__flush_count_cache_return, PPC_INST_BLR);
437
- count_cache_flush_type = COUNT_CACHE_FLUSH_HW;
438
- pr_info("count-cache-flush: hardware assisted flush sequence enabled\n");
522
+ update_branch_cache_flush();
439523 }
440524
441525 void setup_count_cache_flush(void)
....@@ -459,7 +543,7 @@
459543 security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE))
460544 security_ftr_set(SEC_FTR_FLUSH_LINK_STACK);
461545
462
- toggle_count_cache_flush(enable);
546
+ toggle_branch_cache_flush(enable);
463547 }
464548
465549 #ifdef CONFIG_DEBUG_FS
....@@ -474,14 +558,14 @@
474558 else
475559 return -EINVAL;
476560
477
- toggle_count_cache_flush(enable);
561
+ toggle_branch_cache_flush(enable);
478562
479563 return 0;
480564 }
481565
482566 static int count_cache_flush_get(void *data, u64 *val)
483567 {
484
- if (count_cache_flush_type == COUNT_CACHE_FLUSH_NONE)
568
+ if (count_cache_flush_type == BRANCH_CACHE_FLUSH_NONE)
485569 *val = 0;
486570 else
487571 *val = 1;
....@@ -489,13 +573,14 @@
489573 return 0;
490574 }
491575
492
-DEFINE_SIMPLE_ATTRIBUTE(fops_count_cache_flush, count_cache_flush_get,
493
- count_cache_flush_set, "%llu\n");
576
+DEFINE_DEBUGFS_ATTRIBUTE(fops_count_cache_flush, count_cache_flush_get,
577
+ count_cache_flush_set, "%llu\n");
494578
495579 static __init int count_cache_flush_debugfs_init(void)
496580 {
497
- debugfs_create_file("count_cache_flush", 0600, powerpc_debugfs_root,
498
- NULL, &fops_count_cache_flush);
581
+ debugfs_create_file_unsafe("count_cache_flush", 0600,
582
+ powerpc_debugfs_root, NULL,
583
+ &fops_count_cache_flush);
499584 return 0;
500585 }
501586 device_initcall(count_cache_flush_debugfs_init);