|
19 | 19 | #include <linux/kernel.h> |
20 | 20 | #include <linux/mm.h> |
21 | 21 | #include <linux/stddef.h> |
| 22 | +#include <linux/sysctl.h> |
22 | 23 | #include <linux/unistd.h> |
23 | 24 | #include <linux/user.h> |
24 | 25 | #include <linux/delay.h> |
|
38 | 39 | #include <trace/events/power.h> |
39 | 40 | #include <linux/percpu.h> |
40 | 41 | #include <linux/thread_info.h> |
| 42 | +#include <linux/prctl.h> |
41 | 43 |
|
42 | 44 | #include <asm/alternative.h> |
43 | 45 | #include <asm/arch_gicv3.h> |
@@ -307,11 +309,18 @@ static void tls_thread_flush(void) |
307 | 309 | } |
308 | 310 | } |
309 | 311 |
|
| 312 | +static void flush_tagged_addr_state(void) |
| 313 | +{ |
| 314 | + if (IS_ENABLED(CONFIG_ARM64_TAGGED_ADDR_ABI)) |
| 315 | + clear_thread_flag(TIF_TAGGED_ADDR); |
| 316 | +} |
| 317 | + |
310 | 318 | void flush_thread(void) |
311 | 319 | { |
312 | 320 | fpsimd_flush_thread(); |
313 | 321 | tls_thread_flush(); |
314 | 322 | flush_ptrace_hw_breakpoint(current); |
| 323 | + flush_tagged_addr_state(); |
315 | 324 | } |
316 | 325 |
|
317 | 326 | void release_thread(struct task_struct *dead_task) |
@@ -565,3 +574,67 @@ void arch_setup_new_exec(void) |
565 | 574 |
|
566 | 575 | ptrauth_thread_init_user(current); |
567 | 576 | } |
| 577 | + |
| 578 | +#ifdef CONFIG_ARM64_TAGGED_ADDR_ABI |
| 579 | +/* |
| 580 | + * Control the relaxed ABI allowing tagged user addresses into the kernel. |
| 581 | + */ |
| 582 | +static unsigned int tagged_addr_prctl_allowed = 1; |
| 583 | + |
| 584 | +long set_tagged_addr_ctrl(unsigned long arg) |
| 585 | +{ |
| 586 | + if (!tagged_addr_prctl_allowed) |
| 587 | + return -EINVAL; |
| 588 | + if (is_compat_task()) |
| 589 | + return -EINVAL; |
| 590 | + if (arg & ~PR_TAGGED_ADDR_ENABLE) |
| 591 | + return -EINVAL; |
| 592 | + |
| 593 | + update_thread_flag(TIF_TAGGED_ADDR, arg & PR_TAGGED_ADDR_ENABLE); |
| 594 | + |
| 595 | + return 0; |
| 596 | +} |
| 597 | + |
| 598 | +long get_tagged_addr_ctrl(void) |
| 599 | +{ |
| 600 | + if (!tagged_addr_prctl_allowed) |
| 601 | + return -EINVAL; |
| 602 | + if (is_compat_task()) |
| 603 | + return -EINVAL; |
| 604 | + |
| 605 | + if (test_thread_flag(TIF_TAGGED_ADDR)) |
| 606 | + return PR_TAGGED_ADDR_ENABLE; |
| 607 | + |
| 608 | + return 0; |
| 609 | +} |
| 610 | + |
| 611 | +/* |
| 612 | + * Global sysctl to disable the tagged user addresses support. This control |
| 613 | + * only prevents the tagged address ABI enabling via prctl() and does not |
| 614 | + * disable it for tasks that already opted in to the relaxed ABI. |
| 615 | + */ |
| 616 | +static int zero; |
| 617 | +static int one = 1; |
| 618 | + |
| 619 | +static struct ctl_table tagged_addr_sysctl_table[] = { |
| 620 | + { |
| 621 | + .procname = "tagged_addr", |
| 622 | + .mode = 0644, |
| 623 | + .data = &tagged_addr_prctl_allowed, |
| 624 | + .maxlen = sizeof(int), |
| 625 | + .proc_handler = proc_dointvec_minmax, |
| 626 | + .extra1 = &zero, |
| 627 | + .extra2 = &one, |
| 628 | + }, |
| 629 | + { } |
| 630 | +}; |
| 631 | + |
| 632 | +static int __init tagged_addr_init(void) |
| 633 | +{ |
| 634 | + if (!register_sysctl("abi", tagged_addr_sysctl_table)) |
| 635 | + return -EINVAL; |
| 636 | + return 0; |
| 637 | +} |
| 638 | + |
| 639 | +core_initcall(tagged_addr_init); |
| 640 | +#endif /* CONFIG_ARM64_TAGGED_ADDR_ABI */ |
0 commit comments