|
71 | 71 | #define RSEQ_BUILD_SLOW_PATH |
72 | 72 |
|
73 | 73 | #include <linux/debugfs.h> |
| 74 | +#include <linux/prctl.h> |
74 | 75 | #include <linux/ratelimit.h> |
75 | 76 | #include <linux/rseq_entry.h> |
76 | 77 | #include <linux/sched.h> |
@@ -501,6 +502,57 @@ SYSCALL_DEFINE4(rseq, struct rseq __user *, rseq, u32, rseq_len, int, flags, u32 |
501 | 502 | #ifdef CONFIG_RSEQ_SLICE_EXTENSION |
502 | 503 | DEFINE_STATIC_KEY_TRUE(rseq_slice_extension_key); |
503 | 504 |
|
| 505 | +int rseq_slice_extension_prctl(unsigned long arg2, unsigned long arg3) |
| 506 | +{ |
| 507 | + switch (arg2) { |
| 508 | + case PR_RSEQ_SLICE_EXTENSION_GET: |
| 509 | + if (arg3) |
| 510 | + return -EINVAL; |
| 511 | + return current->rseq.slice.state.enabled ? PR_RSEQ_SLICE_EXT_ENABLE : 0; |
| 512 | + |
| 513 | + case PR_RSEQ_SLICE_EXTENSION_SET: { |
| 514 | + u32 rflags, valid = RSEQ_CS_FLAG_SLICE_EXT_AVAILABLE; |
| 515 | + bool enable = !!(arg3 & PR_RSEQ_SLICE_EXT_ENABLE); |
| 516 | + |
| 517 | + if (arg3 & ~PR_RSEQ_SLICE_EXT_ENABLE) |
| 518 | + return -EINVAL; |
| 519 | + if (!rseq_slice_extension_enabled()) |
| 520 | + return -ENOTSUPP; |
| 521 | + if (!current->rseq.usrptr) |
| 522 | + return -ENXIO; |
| 523 | + |
| 524 | + /* No change? */ |
| 525 | + if (enable == !!current->rseq.slice.state.enabled) |
| 526 | + return 0; |
| 527 | + |
| 528 | + if (get_user(rflags, ¤t->rseq.usrptr->flags)) |
| 529 | + goto die; |
| 530 | + |
| 531 | + if (current->rseq.slice.state.enabled) |
| 532 | + valid |= RSEQ_CS_FLAG_SLICE_EXT_ENABLED; |
| 533 | + |
| 534 | + if ((rflags & valid) != valid) |
| 535 | + goto die; |
| 536 | + |
| 537 | + rflags &= ~RSEQ_CS_FLAG_SLICE_EXT_ENABLED; |
| 538 | + rflags |= RSEQ_CS_FLAG_SLICE_EXT_AVAILABLE; |
| 539 | + if (enable) |
| 540 | + rflags |= RSEQ_CS_FLAG_SLICE_EXT_ENABLED; |
| 541 | + |
| 542 | + if (put_user(rflags, ¤t->rseq.usrptr->flags)) |
| 543 | + goto die; |
| 544 | + |
| 545 | + current->rseq.slice.state.enabled = enable; |
| 546 | + return 0; |
| 547 | + } |
| 548 | + default: |
| 549 | + return -EINVAL; |
| 550 | + } |
| 551 | +die: |
| 552 | + force_sig(SIGSEGV); |
| 553 | + return -EFAULT; |
| 554 | +} |
| 555 | + |
504 | 556 | static int __init rseq_slice_cmdline(char *str) |
505 | 557 | { |
506 | 558 | bool on; |
|
0 commit comments