diff options
author | Arnd Bergmann <arnd@arndb.de> | 2019-02-02 10:34:44 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-02-03 14:17:30 -0500 |
commit | fe0c72f3db11be752e7c06efad9fa27af1327c47 (patch) | |
tree | d18ecf1c437ae64936226349ebaab124a1fb811a /net/compat.c | |
parent | a9bcfd1d176eb2109f74e1e4eeabdedf22321003 (diff) |
socket: move compat timeout handling into sock.c
This is a cleanup to prepare for the addition of 64-bit time_t
in O_SNDTIMEO/O_RCVTIMEO. The existing compat handler seems
unnecessarily complex and error-prone, moving it all into the
main setsockopt()/getsockopt() implementation requires half
as much code and is easier to extend.
32-bit user space can now use old_timeval32 on both 32-bit
and 64-bit machines, while 64-bit code can use
__old_kernel_timeval.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
Acked-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/compat.c')
-rw-r--r-- | net/compat.c | 66 |
1 files changed, 1 insertions, 65 deletions
diff --git a/net/compat.c b/net/compat.c index 959d1c51826d..ce8f6e8cdcd2 100644 --- a/net/compat.c +++ b/net/compat.c | |||
@@ -348,28 +348,6 @@ static int do_set_attach_filter(struct socket *sock, int level, int optname, | |||
348 | sizeof(struct sock_fprog)); | 348 | sizeof(struct sock_fprog)); |
349 | } | 349 | } |
350 | 350 | ||
351 | static int do_set_sock_timeout(struct socket *sock, int level, | ||
352 | int optname, char __user *optval, unsigned int optlen) | ||
353 | { | ||
354 | struct compat_timeval __user *up = (struct compat_timeval __user *)optval; | ||
355 | struct timeval ktime; | ||
356 | mm_segment_t old_fs; | ||
357 | int err; | ||
358 | |||
359 | if (optlen < sizeof(*up)) | ||
360 | return -EINVAL; | ||
361 | if (!access_ok(up, sizeof(*up)) || | ||
362 | __get_user(ktime.tv_sec, &up->tv_sec) || | ||
363 | __get_user(ktime.tv_usec, &up->tv_usec)) | ||
364 | return -EFAULT; | ||
365 | old_fs = get_fs(); | ||
366 | set_fs(KERNEL_DS); | ||
367 | err = sock_setsockopt(sock, level, optname, (char *)&ktime, sizeof(ktime)); | ||
368 | set_fs(old_fs); | ||
369 | |||
370 | return err; | ||
371 | } | ||
372 | |||
373 | static int compat_sock_setsockopt(struct socket *sock, int level, int optname, | 351 | static int compat_sock_setsockopt(struct socket *sock, int level, int optname, |
374 | char __user *optval, unsigned int optlen) | 352 | char __user *optval, unsigned int optlen) |
375 | { | 353 | { |
@@ -377,10 +355,6 @@ static int compat_sock_setsockopt(struct socket *sock, int level, int optname, | |||
377 | optname == SO_ATTACH_REUSEPORT_CBPF) | 355 | optname == SO_ATTACH_REUSEPORT_CBPF) |
378 | return do_set_attach_filter(sock, level, optname, | 356 | return do_set_attach_filter(sock, level, optname, |
379 | optval, optlen); | 357 | optval, optlen); |
380 | if (!COMPAT_USE_64BIT_TIME && | ||
381 | (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) | ||
382 | return do_set_sock_timeout(sock, level, optname, optval, optlen); | ||
383 | |||
384 | return sock_setsockopt(sock, level, optname, optval, optlen); | 358 | return sock_setsockopt(sock, level, optname, optval, optlen); |
385 | } | 359 | } |
386 | 360 | ||
@@ -417,44 +391,6 @@ COMPAT_SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, | |||
417 | return __compat_sys_setsockopt(fd, level, optname, optval, optlen); | 391 | return __compat_sys_setsockopt(fd, level, optname, optval, optlen); |
418 | } | 392 | } |
419 | 393 | ||
420 | static int do_get_sock_timeout(struct socket *sock, int level, int optname, | ||
421 | char __user *optval, int __user *optlen) | ||
422 | { | ||
423 | struct compat_timeval __user *up; | ||
424 | struct timeval ktime; | ||
425 | mm_segment_t old_fs; | ||
426 | int len, err; | ||
427 | |||
428 | up = (struct compat_timeval __user *) optval; | ||
429 | if (get_user(len, optlen)) | ||
430 | return -EFAULT; | ||
431 | if (len < sizeof(*up)) | ||
432 | return -EINVAL; | ||
433 | len = sizeof(ktime); | ||
434 | old_fs = get_fs(); | ||
435 | set_fs(KERNEL_DS); | ||
436 | err = sock_getsockopt(sock, level, optname, (char *) &ktime, &len); | ||
437 | set_fs(old_fs); | ||
438 | |||
439 | if (!err) { | ||
440 | if (put_user(sizeof(*up), optlen) || | ||
441 | !access_ok(up, sizeof(*up)) || | ||
442 | __put_user(ktime.tv_sec, &up->tv_sec) || | ||
443 | __put_user(ktime.tv_usec, &up->tv_usec)) | ||
444 | err = -EFAULT; | ||
445 | } | ||
446 | return err; | ||
447 | } | ||
448 | |||
449 | static int compat_sock_getsockopt(struct socket *sock, int level, int optname, | ||
450 | char __user *optval, int __user *optlen) | ||
451 | { | ||
452 | if (!COMPAT_USE_64BIT_TIME && | ||
453 | (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) | ||
454 | return do_get_sock_timeout(sock, level, optname, optval, optlen); | ||
455 | return sock_getsockopt(sock, level, optname, optval, optlen); | ||
456 | } | ||
457 | |||
458 | int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) | 394 | int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) |
459 | { | 395 | { |
460 | struct compat_timeval __user *ctv; | 396 | struct compat_timeval __user *ctv; |
@@ -527,7 +463,7 @@ static int __compat_sys_getsockopt(int fd, int level, int optname, | |||
527 | } | 463 | } |
528 | 464 | ||
529 | if (level == SOL_SOCKET) | 465 | if (level == SOL_SOCKET) |
530 | err = compat_sock_getsockopt(sock, level, | 466 | err = sock_getsockopt(sock, level, |
531 | optname, optval, optlen); | 467 | optname, optval, optlen); |
532 | else if (sock->ops->compat_getsockopt) | 468 | else if (sock->ops->compat_getsockopt) |
533 | err = sock->ops->compat_getsockopt(sock, level, | 469 | err = sock->ops->compat_getsockopt(sock, level, |