diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-05-27 08:35:50 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-06-15 00:23:50 -0400 |
commit | 5ed0127fc3619890898f217098d073d8aabfbfdc (patch) | |
tree | 6ccd19440247454ab88a8fc58a1448190fd378bd | |
parent | 87a3002af9e30852ce90a028f8259c9e399fd888 (diff) |
signalfd: lift sigmask copyin and size checks to callers of do_signalfd4()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/signalfd.c | 50 |
1 files changed, 25 insertions, 25 deletions
diff --git a/fs/signalfd.c b/fs/signalfd.c index d2187a813376..46e9de097507 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c | |||
@@ -256,10 +256,8 @@ static const struct file_operations signalfd_fops = { | |||
256 | .llseek = noop_llseek, | 256 | .llseek = noop_llseek, |
257 | }; | 257 | }; |
258 | 258 | ||
259 | static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, | 259 | static int do_signalfd4(int ufd, sigset_t *mask, int flags) |
260 | int flags) | ||
261 | { | 260 | { |
262 | sigset_t sigmask; | ||
263 | struct signalfd_ctx *ctx; | 261 | struct signalfd_ctx *ctx; |
264 | 262 | ||
265 | /* Check the SFD_* constants for consistency. */ | 263 | /* Check the SFD_* constants for consistency. */ |
@@ -269,18 +267,15 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, | |||
269 | if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK)) | 267 | if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK)) |
270 | return -EINVAL; | 268 | return -EINVAL; |
271 | 269 | ||
272 | if (sizemask != sizeof(sigset_t) || | 270 | sigdelsetmask(mask, sigmask(SIGKILL) | sigmask(SIGSTOP)); |
273 | copy_from_user(&sigmask, user_mask, sizeof(sigmask))) | 271 | signotset(mask); |
274 | return -EINVAL; | ||
275 | sigdelsetmask(&sigmask, sigmask(SIGKILL) | sigmask(SIGSTOP)); | ||
276 | signotset(&sigmask); | ||
277 | 272 | ||
278 | if (ufd == -1) { | 273 | if (ufd == -1) { |
279 | ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); | 274 | ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); |
280 | if (!ctx) | 275 | if (!ctx) |
281 | return -ENOMEM; | 276 | return -ENOMEM; |
282 | 277 | ||
283 | ctx->sigmask = sigmask; | 278 | ctx->sigmask = *mask; |
284 | 279 | ||
285 | /* | 280 | /* |
286 | * When we call this, the initialization must be complete, since | 281 | * When we call this, the initialization must be complete, since |
@@ -300,7 +295,7 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, | |||
300 | return -EINVAL; | 295 | return -EINVAL; |
301 | } | 296 | } |
302 | spin_lock_irq(¤t->sighand->siglock); | 297 | spin_lock_irq(¤t->sighand->siglock); |
303 | ctx->sigmask = sigmask; | 298 | ctx->sigmask = *mask; |
304 | spin_unlock_irq(¤t->sighand->siglock); | 299 | spin_unlock_irq(¤t->sighand->siglock); |
305 | 300 | ||
306 | wake_up(¤t->sighand->signalfd_wqh); | 301 | wake_up(¤t->sighand->signalfd_wqh); |
@@ -313,46 +308,51 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, | |||
313 | SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask, | 308 | SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask, |
314 | size_t, sizemask, int, flags) | 309 | size_t, sizemask, int, flags) |
315 | { | 310 | { |
316 | return do_signalfd4(ufd, user_mask, sizemask, flags); | 311 | sigset_t mask; |
312 | |||
313 | if (sizemask != sizeof(sigset_t) || | ||
314 | copy_from_user(&mask, user_mask, sizeof(mask))) | ||
315 | return -EINVAL; | ||
316 | return do_signalfd4(ufd, &mask, flags); | ||
317 | } | 317 | } |
318 | 318 | ||
319 | SYSCALL_DEFINE3(signalfd, int, ufd, sigset_t __user *, user_mask, | 319 | SYSCALL_DEFINE3(signalfd, int, ufd, sigset_t __user *, user_mask, |
320 | size_t, sizemask) | 320 | size_t, sizemask) |
321 | { | 321 | { |
322 | return do_signalfd4(ufd, user_mask, sizemask, 0); | 322 | sigset_t mask; |
323 | |||
324 | if (sizemask != sizeof(sigset_t) || | ||
325 | copy_from_user(&mask, user_mask, sizeof(mask))) | ||
326 | return -EINVAL; | ||
327 | return do_signalfd4(ufd, &mask, 0); | ||
323 | } | 328 | } |
324 | 329 | ||
325 | #ifdef CONFIG_COMPAT | 330 | #ifdef CONFIG_COMPAT |
326 | static long do_compat_signalfd4(int ufd, | 331 | static long do_compat_signalfd4(int ufd, |
327 | const compat_sigset_t __user *sigmask, | 332 | const compat_sigset_t __user *user_mask, |
328 | compat_size_t sigsetsize, int flags) | 333 | compat_size_t sigsetsize, int flags) |
329 | { | 334 | { |
330 | sigset_t tmp; | 335 | sigset_t mask; |
331 | sigset_t __user *ksigmask; | ||
332 | 336 | ||
333 | if (sigsetsize != sizeof(compat_sigset_t)) | 337 | if (sigsetsize != sizeof(compat_sigset_t)) |
334 | return -EINVAL; | 338 | return -EINVAL; |
335 | if (get_compat_sigset(&tmp, sigmask)) | 339 | if (get_compat_sigset(&mask, user_mask)) |
336 | return -EFAULT; | ||
337 | ksigmask = compat_alloc_user_space(sizeof(sigset_t)); | ||
338 | if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t))) | ||
339 | return -EFAULT; | 340 | return -EFAULT; |
340 | 341 | return do_signalfd4(ufd, &mask, flags); | |
341 | return do_signalfd4(ufd, ksigmask, sizeof(sigset_t), flags); | ||
342 | } | 342 | } |
343 | 343 | ||
344 | COMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd, | 344 | COMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd, |
345 | const compat_sigset_t __user *, sigmask, | 345 | const compat_sigset_t __user *, user_mask, |
346 | compat_size_t, sigsetsize, | 346 | compat_size_t, sigsetsize, |
347 | int, flags) | 347 | int, flags) |
348 | { | 348 | { |
349 | return do_compat_signalfd4(ufd, sigmask, sigsetsize, flags); | 349 | return do_compat_signalfd4(ufd, user_mask, sigsetsize, flags); |
350 | } | 350 | } |
351 | 351 | ||
352 | COMPAT_SYSCALL_DEFINE3(signalfd, int, ufd, | 352 | COMPAT_SYSCALL_DEFINE3(signalfd, int, ufd, |
353 | const compat_sigset_t __user *,sigmask, | 353 | const compat_sigset_t __user *, user_mask, |
354 | compat_size_t, sigsetsize) | 354 | compat_size_t, sigsetsize) |
355 | { | 355 | { |
356 | return do_compat_signalfd4(ufd, sigmask, sigsetsize, 0); | 356 | return do_compat_signalfd4(ufd, user_mask, sigsetsize, 0); |
357 | } | 357 | } |
358 | #endif | 358 | #endif |