diff options
author | Aleksa Sarai <cyphar@cyphar.com> | 2019-09-30 21:10:54 -0400 |
---|---|---|
committer | Christian Brauner <christian.brauner@ubuntu.com> | 2019-10-01 09:45:17 -0400 |
commit | dff3a85feceade213daf153556fd32a3b0a73c63 (patch) | |
tree | e532439d4ce82a284eeffc133e90ff18a6fc895f /kernel | |
parent | f14c234b4bc5184fd40d9a47830e5b32c3b36d49 (diff) |
sched_setattr: switch to copy_struct_from_user()
Switch sched_setattr() syscall from it's own copying struct sched_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. Ideally we could also
unify sched_getattr(2)-style syscalls as well, but unfortunately the
correct semantics for such syscalls are much less clear (see [1] for
more detail). In future we could come up with a more sane idea for how
the syscall interface should look.
[1]: commit 1251201c0d34 ("sched/core: Fix uclamp ABI bug, clean up and
robustify sched_read_attr() ABI logic and code")
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-4-cyphar@cyphar.com
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/sched/core.c | 43 |
1 files changed, 7 insertions, 36 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 7880f4f64d0e..dd05a378631a 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
@@ -5106,9 +5106,6 @@ static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *a | |||
5106 | u32 size; | 5106 | u32 size; |
5107 | int ret; | 5107 | int ret; |
5108 | 5108 | ||
5109 | if (!access_ok(uattr, SCHED_ATTR_SIZE_VER0)) | ||
5110 | return -EFAULT; | ||
5111 | |||
5112 | /* Zero the full structure, so that a short copy will be nice: */ | 5109 | /* Zero the full structure, so that a short copy will be nice: */ |
5113 | memset(attr, 0, sizeof(*attr)); | 5110 | memset(attr, 0, sizeof(*attr)); |
5114 | 5111 | ||
@@ -5116,45 +5113,19 @@ static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *a | |||
5116 | if (ret) | 5113 | if (ret) |
5117 | return ret; | 5114 | return ret; |
5118 | 5115 | ||
5119 | /* Bail out on silly large: */ | ||
5120 | if (size > PAGE_SIZE) | ||
5121 | goto err_size; | ||
5122 | |||
5123 | /* ABI compatibility quirk: */ | 5116 | /* ABI compatibility quirk: */ |
5124 | if (!size) | 5117 | if (!size) |
5125 | size = SCHED_ATTR_SIZE_VER0; | 5118 | size = SCHED_ATTR_SIZE_VER0; |
5126 | 5119 | if (size < SCHED_ATTR_SIZE_VER0 || size > PAGE_SIZE) | |
5127 | if (size < SCHED_ATTR_SIZE_VER0) | ||
5128 | goto err_size; | 5120 | goto err_size; |
5129 | 5121 | ||
5130 | /* | 5122 | ret = copy_struct_from_user(attr, sizeof(*attr), uattr, size); |
5131 | * If we're handed a bigger struct than we know of, | 5123 | if (ret) { |
5132 | * ensure all the unknown bits are 0 - i.e. new | 5124 | if (ret == -E2BIG) |
5133 | * user-space does not rely on any kernel feature | 5125 | goto err_size; |
5134 | * extensions we dont know about yet. | 5126 | return ret; |
5135 | */ | ||
5136 | if (size > sizeof(*attr)) { | ||
5137 | unsigned char __user *addr; | ||
5138 | unsigned char __user *end; | ||
5139 | unsigned char val; | ||
5140 | |||
5141 | addr = (void __user *)uattr + sizeof(*attr); | ||
5142 | end = (void __user *)uattr + size; | ||
5143 | |||
5144 | for (; addr < end; addr++) { | ||
5145 | ret = get_user(val, addr); | ||
5146 | if (ret) | ||
5147 | return ret; | ||
5148 | if (val) | ||
5149 | goto err_size; | ||
5150 | } | ||
5151 | size = sizeof(*attr); | ||
5152 | } | 5127 | } |
5153 | 5128 | ||
5154 | ret = copy_from_user(attr, uattr, size); | ||
5155 | if (ret) | ||
5156 | return -EFAULT; | ||
5157 | |||
5158 | if ((attr->sched_flags & SCHED_FLAG_UTIL_CLAMP) && | 5129 | if ((attr->sched_flags & SCHED_FLAG_UTIL_CLAMP) && |
5159 | size < SCHED_ATTR_SIZE_VER1) | 5130 | size < SCHED_ATTR_SIZE_VER1) |
5160 | return -EINVAL; | 5131 | return -EINVAL; |
@@ -5354,7 +5325,7 @@ sched_attr_copy_to_user(struct sched_attr __user *uattr, | |||
5354 | * sys_sched_getattr - similar to sched_getparam, but with sched_attr | 5325 | * sys_sched_getattr - similar to sched_getparam, but with sched_attr |
5355 | * @pid: the pid in question. | 5326 | * @pid: the pid in question. |
5356 | * @uattr: structure containing the extended parameters. | 5327 | * @uattr: structure containing the extended parameters. |
5357 | * @usize: sizeof(attr) that user-space knows about, for forwards and backwards compatibility. | 5328 | * @usize: sizeof(attr) for fwd/bwd comp. |
5358 | * @flags: for future extension. | 5329 | * @flags: for future extension. |
5359 | */ | 5330 | */ |
5360 | SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, | 5331 | SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, |