aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-05-27 08:35:50 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2018-06-15 00:23:50 -0400
commit5ed0127fc3619890898f217098d073d8aabfbfdc (patch)
tree6ccd19440247454ab88a8fc58a1448190fd378bd
parent87a3002af9e30852ce90a028f8259c9e399fd888 (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.c50
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
259static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, 259static 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(&current->sighand->siglock); 297 spin_lock_irq(&current->sighand->siglock);
303 ctx->sigmask = sigmask; 298 ctx->sigmask = *mask;
304 spin_unlock_irq(&current->sighand->siglock); 299 spin_unlock_irq(&current->sighand->siglock);
305 300
306 wake_up(&current->sighand->signalfd_wqh); 301 wake_up(&current->sighand->signalfd_wqh);
@@ -313,46 +308,51 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
313SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask, 308SYSCALL_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
319SYSCALL_DEFINE3(signalfd, int, ufd, sigset_t __user *, user_mask, 319SYSCALL_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
326static long do_compat_signalfd4(int ufd, 331static 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
344COMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd, 344COMPAT_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
352COMPAT_SYSCALL_DEFINE3(signalfd, int, ufd, 352COMPAT_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