Skip to content

Commit c2ba8f4

Browse files
cypharChristian Brauner
authored andcommitted
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 <[email protected]> Reviewed-by: Kees Cook <[email protected]> Reviewed-by: Christian Brauner <[email protected]> [[email protected]: improve commit message] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Christian Brauner <[email protected]>
1 parent dff3a85 commit c2ba8f4

File tree

1 file changed

+9
-38
lines changed

1 file changed

+9
-38
lines changed

kernel/events/core.c

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -10586,55 +10586,26 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr,
1058610586
u32 size;
1058710587
int ret;
1058810588

10589-
if (!access_ok(uattr, PERF_ATTR_SIZE_VER0))
10590-
return -EFAULT;
10591-
10592-
/*
10593-
* zero the full structure, so that a short copy will be nice.
10594-
*/
10589+
/* Zero the full structure, so that a short copy will be nice. */
1059510590
memset(attr, 0, sizeof(*attr));
1059610591

1059710592
ret = get_user(size, &uattr->size);
1059810593
if (ret)
1059910594
return ret;
1060010595

10601-
if (size > PAGE_SIZE) /* silly large */
10602-
goto err_size;
10603-
10604-
if (!size) /* abi compat */
10596+
/* ABI compatibility quirk: */
10597+
if (!size)
1060510598
size = PERF_ATTR_SIZE_VER0;
10606-
10607-
if (size < PERF_ATTR_SIZE_VER0)
10599+
if (size < PERF_ATTR_SIZE_VER0 || size > PAGE_SIZE)
1060810600
goto err_size;
1060910601

10610-
/*
10611-
* If we're handed a bigger struct than we know of,
10612-
* ensure all the unknown bits are 0 - i.e. new
10613-
* user-space does not rely on any kernel feature
10614-
* extensions we dont know about yet.
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);
10602+
ret = copy_struct_from_user(attr, sizeof(*attr), uattr, size);
10603+
if (ret) {
10604+
if (ret == -E2BIG)
10605+
goto err_size;
10606+
return ret;
1063210607
}
1063310608

10634-
ret = copy_from_user(attr, uattr, size);
10635-
if (ret)
10636-
return -EFAULT;
10637-
1063810609
attr->size = size;
1063910610

1064010611
if (attr->__reserved_1)

0 commit comments

Comments
 (0)