aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorAleksa Sarai <cyphar@cyphar.com>2019-09-30 21:10:55 -0400
committerChristian Brauner <christian.brauner@ubuntu.com>2019-10-01 09:45:22 -0400
commitc2ba8f41ad366dc12840dd87d8f1565185845126 (patch)
tree7e6407dae5d248995ecbc56b808f49d8b687fd70 /kernel
parentdff3a85feceade213daf153556fd32a3b0a73c63 (diff)
perf_event_open: switch to copy_struct_from_user()
Switch perf_event_open() syscall from it's own copying struct perf_event_attr from userspace to the new dedicated copy_struct_from_user() helper. The change is very straightforward, and helps unify the syscall interface for struct-from-userspace syscalls. Signed-off-by: Aleksa Sarai <cyphar@cyphar.com> Reviewed-by: Kees Cook <keescook@chromium.org> Reviewed-by: Christian Brauner <christian.brauner@ubuntu.com> [christian.brauner@ubuntu.com: improve commit message] Link: https://lore.kernel.org/r/20191001011055.19283-5-cyphar@cyphar.com Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/events/core.c47
1 files changed, 9 insertions, 38 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 4655adbbae10..3f0cb82e4fbc 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -10586,55 +10586,26 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr,
10586 u32 size; 10586 u32 size;
10587 int ret; 10587 int ret;
10588 10588
10589 if (!access_ok(uattr, PERF_ATTR_SIZE_VER0)) 10589 /* Zero the full structure, so that a short copy will be nice. */
10590 return -EFAULT;
10591
10592 /*
10593 * zero the full structure, so that a short copy will be nice.
10594 */
10595 memset(attr, 0, sizeof(*attr)); 10590 memset(attr, 0, sizeof(*attr));
10596 10591
10597 ret = get_user(size, &uattr->size); 10592 ret = get_user(size, &uattr->size);
10598 if (ret) 10593 if (ret)
10599 return ret; 10594 return ret;
10600 10595
10601 if (size > PAGE_SIZE) /* silly large */ 10596 /* ABI compatibility quirk: */
10602 goto err_size; 10597 if (!size)
10603
10604 if (!size) /* abi compat */
10605 size = PERF_ATTR_SIZE_VER0; 10598 size = PERF_ATTR_SIZE_VER0;
10606 10599 if (size < PERF_ATTR_SIZE_VER0 || size > PAGE_SIZE)
10607 if (size < PERF_ATTR_SIZE_VER0)
10608 goto err_size; 10600 goto err_size;
10609 10601
10610 /* 10602 ret = copy_struct_from_user(attr, sizeof(*attr), uattr, size);
10611 * If we're handed a bigger struct than we know of, 10603 if (ret) {
10612 * ensure all the unknown bits are 0 - i.e. new 10604 if (ret == -E2BIG)
10613 * user-space does not rely on any kernel feature 10605 goto err_size;
10614 * extensions we dont know about yet. 10606 return ret;
10615 */
10616 if (size > sizeof(*attr)) {
10617 unsigned char __user *addr;
10618 unsigned char __user *end;
10619 unsigned char val;
10620
10621 addr = (void __user *)uattr + sizeof(*attr);
10622 end = (void __user *)uattr + size;
10623
10624 for (; addr < end; addr++) {
10625 ret = get_user(val, addr);
10626 if (ret)
10627 return ret;
10628 if (val)
10629 goto err_size;
10630 }
10631 size = sizeof(*attr);
10632 } 10607 }
10633 10608
10634 ret = copy_from_user(attr, uattr, size);
10635 if (ret)
10636 return -EFAULT;
10637
10638 attr->size = size; 10609 attr->size = size;
10639 10610
10640 if (attr->__reserved_1) 10611 if (attr->__reserved_1)