Advertisement
Guest User

Untitled

a guest
Jul 12th, 2018
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 13.43 KB | None | 0 0
  1. diff --git a/fs/aio.c b/fs/aio.c
  2. index e8623a5e8736..f86781a9cb79 100644
  3. --- a/fs/aio.c
  4. +++ b/fs/aio.c
  5. @@ -1865,6 +1865,7 @@ static long do_io_getevents(aio_context_t ctx_id,
  6.   * specifies an infinite timeout. Note that the timeout pointed to by
  7.   * timeout is relative.  Will fail with -ENOSYS if not implemented.
  8.   */
  9. +#if defined(CONFIG_COMPAT_32BIT_TIME) || defined(CONFIG_64BIT)
  10.  SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id,
  11.         long, min_nr,
  12.         long, nr,
  13. @@ -1882,6 +1883,7 @@ SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id,
  14.         ret = -EINTR;
  15.     return ret;
  16.  }
  17. +#endif
  18.  
  19.  SYSCALL_DEFINE6(io_pgetevents,
  20.         aio_context_t, ctx_id,
  21. @@ -1928,6 +1930,52 @@ SYSCALL_DEFINE6(io_pgetevents,
  22.     return ret;
  23.  }
  24.  
  25. +#if defined(CONFIG_COMPAT_32BIT_TIME) && !defined(CONFIG_64BIT)
  26. +SYSCALL_DEFINE6(io_pgetevents_time32,
  27. +       compat_aio_context_t, ctx_id,
  28. +       long, min_nr,
  29. +       long, nr,
  30. +       struct io_event __user *, events,
  31. +       struct __kernel_old_timespec __user *, timeout,
  32. +       const struct __aio_sigset __user *, usig)
  33. +{
  34. +   struct __aio_sigset ksig = { NULL, };
  35. +   sigset_t ksigmask, sigsaved;
  36. +   struct timespec64 t;
  37. +   int ret;
  38. +
  39. +   if (timeout && get_old_timespec(&t, timeout))
  40. +       return -EFAULT;
  41. +
  42. +   if (usig && copy_from_user(&ksig, usig, sizeof(ksig)))
  43. +       return -EFAULT;
  44. +
  45. +   if (ksig.sigmask) {
  46. +       if (ksig.sigsetsize != sizeof(ksig))
  47. +           return -EINVAL;
  48. +       if (copy_from_user(&ksigmask, ksig.sigmask, sizeof(ksigmask)))
  49. +           return -EFAULT;
  50. +       sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
  51. +       sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
  52. +   }
  53. +
  54. +   ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL);
  55. +   if (signal_pending(current)) {
  56. +       if (ksig.sigmask) {
  57. +           current->saved_sigmask = sigsaved;
  58. +           set_restore_sigmask();
  59. +       }
  60. +       if (!ret)
  61. +           ret = -ERESTARTNOHAND;
  62. +   } else {
  63. +       if (ksig.sigmask)
  64. +           sigprocmask(SIG_SETMASK, &sigsaved, NULL);
  65. +   }
  66. +
  67. +   return ret;
  68. +}
  69. +#endif
  70. +
  71.  #ifdef CONFIG_COMPAT
  72.  struct __compat_aio_sigset {
  73.     compat_sigset_t __user  *sigmask;
  74. @@ -1977,25 +2025,8 @@ COMPAT_SYSCALL_DEFINE6(io_pgetevents_time64,
  75.  
  76.     return ret;
  77.  }
  78. -#endif
  79. -
  80. -#ifdef CONFIG_COMPAT_32BIT_TIME
  81. -#ifndef CONFIG_COMPAT
  82. -#define compat_sigset_t sigset_t
  83. -struct __compat_aio_sigset {
  84. -   compat_sigset_t __user  *sigmask;
  85. -   compat_size_t       sigsetsize;
  86. -};
  87. -
  88. -static inline int get_compat_sigset(sigset_t *set, const sigset_t __user *compat)
  89. -{
  90. -        if (copy_from_user(set, compat, sizeof *set))
  91. -                return -EFAULT;
  92. -
  93. -        return 0;
  94. -}
  95. -#endif
  96.  
  97. +#if defined(CONFIG_COMPAT_32BIT_TIME)
  98.  COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id,
  99.                compat_long_t, min_nr,
  100.                compat_long_t, nr,
  101. @@ -2057,4 +2088,5 @@ COMPAT_SYSCALL_DEFINE6(io_pgetevents,
  102.  
  103.     return ret;
  104.  }
  105. -#endif
  106. +#endif /* CONFIG_COMPAT_32BIT_TIME */
  107. +#endif /* CONFIG_COMPAT */
  108. diff --git a/fs/select.c b/fs/select.c
  109. index ffea9a4d8dda..24293bd589ee 100644
  110. --- a/fs/select.c
  111. +++ b/fs/select.c
  112. @@ -1095,7 +1095,171 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
  113.     return ret;
  114.  }
  115.  
  116. -#if defined(CONFIG_COMPAT_32BIT_TIME) || defined(CONFIG_COMPAT)
  117. +#if defined(CONFIG_COMPAT_32BIT_TIME) && !defined(CONFIG_64BIT)
  118. +static
  119. +int poll_select_copy_remaining_time32(struct timespec64 *end_time, void __user *p,
  120. +                     int timeval, int ret)
  121. +{
  122. +   struct timespec64 ts;
  123. +
  124. +   if (!p)
  125. +       return ret;
  126. +
  127. +   if (current->personality & STICKY_TIMEOUTS)
  128. +       goto sticky;
  129. +
  130. +   /* No update for zero timeout */
  131. +   if (!end_time->tv_sec && !end_time->tv_nsec)
  132. +       return ret;
  133. +
  134. +   ktime_get_ts64(&ts);
  135. +   ts = timespec64_sub(*end_time, ts);
  136. +   if (ts.tv_sec < 0)
  137. +       ts.tv_sec = ts.tv_nsec = 0;
  138. +
  139. +   if (timeval) {
  140. +       struct __kernel_old_timeval rtv;
  141. +
  142. +       rtv.tv_sec = ts.tv_sec;
  143. +       rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
  144. +
  145. +       if (!copy_to_user(p, &rtv, sizeof(rtv)))
  146. +           return ret;
  147. +   } else {
  148. +       if (!put_old_timespec(&ts, p))
  149. +           return ret;
  150. +   }
  151. +   /*
  152. +    * If an application puts its timeval in read-only memory, we
  153. +    * don't want the Linux-specific update to the timeval to
  154. +    * cause a fault after the select has completed
  155. +    * successfully. However, because we're not updating the
  156. +    * timeval, we can't restart the system call.
  157. +    */
  158. +
  159. +sticky:
  160. +   if (ret == -ERESTARTNOHAND)
  161. +       ret = -EINTR;
  162. +   return ret;
  163. +}
  164. +
  165. +static long do_pselect_time32(int n, fd_set __user *inp,
  166. +   fd_set __user *outp, fd_set __user *exp,
  167. +   struct __kernel_old_timespec __user *tsp,
  168. +   const sigset_t __user *sigmask, size_t sigsetsize)
  169. +{
  170. +   sigset_t ksigmask, sigsaved;
  171. +   struct timespec64 ts, end_time, *to = NULL;
  172. +   int ret;
  173. +
  174. +   if (tsp) {
  175. +       if (get_old_timespec(&ts, tsp))
  176. +           return -EFAULT;
  177. +
  178. +       to = &end_time;
  179. +       if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
  180. +           return -EINVAL;
  181. +   }
  182. +
  183. +   if (sigmask) {
  184. +       if (sigsetsize != sizeof(sigset_t))
  185. +           return -EINVAL;
  186. +       if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
  187. +           return -EFAULT;
  188. +
  189. +       sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
  190. +       sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
  191. +   }
  192. +
  193. +   ret = core_sys_select(n, inp, outp, exp, to);
  194. +   ret = poll_select_copy_remaining_time32(&end_time, tsp, 0, ret);
  195. +
  196. +   if (ret == -ERESTARTNOHAND) {
  197. +       /*
  198. +        * Don't restore the signal mask yet. Let do_signal() deliver
  199. +        * the signal on the way back to userspace, before the signal
  200. +        * mask is restored.
  201. +        */
  202. +       if (sigmask) {
  203. +           memcpy(&current->saved_sigmask, &sigsaved,
  204. +                   sizeof(sigsaved));
  205. +           set_restore_sigmask();
  206. +       }
  207. +   } else if (sigmask)
  208. +       sigprocmask(SIG_SETMASK, &sigsaved, NULL);
  209. +
  210. +   return ret;
  211. +}
  212. +
  213. +SYSCALL_DEFINE6(pselect6_time32, int, n, fd_set __user *, inp,
  214. +   fd_set __user *, outp, fd_set __user *, exp,
  215. +   struct __kernel_old_timespec __user *, tsp, void __user *, sig)
  216. +{
  217. +   size_t sigsetsize = 0;
  218. +   sigset_t __user *up = NULL;
  219. +
  220. +   if (sig) {
  221. +       if (!access_ok(VERIFY_READ, sig, sizeof(void *)+sizeof(size_t))
  222. +           || __get_user(up, (sigset_t __user * __user *)sig)
  223. +           || __get_user(sigsetsize,
  224. +               (size_t __user *)(sig+sizeof(void *))))
  225. +           return -EFAULT;
  226. +   }
  227. +   return do_pselect_time32(n, inp, outp, exp, tsp, up, sigsetsize);
  228. +}
  229. +
  230. +SYSCALL_DEFINE5(ppoll_time32, struct pollfd __user *, ufds,
  231. +   unsigned int,  nfds, struct __kernel_old_timespec __user *, tsp,
  232. +   const sigset_t __user *, sigmask, size_t, sigsetsize)
  233. +{
  234. +   sigset_t ksigmask, sigsaved;
  235. +   struct timespec64 ts, end_time, *to = NULL;
  236. +   int ret;
  237. +
  238. +   if (tsp) {
  239. +       if (get_old_timespec(&ts, tsp))
  240. +           return -EFAULT;
  241. +
  242. +       to = &end_time;
  243. +       if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
  244. +           return -EINVAL;
  245. +   }
  246. +
  247. +   if (sigmask) {
  248. +       if (sigsetsize != sizeof(sigset_t))
  249. +           return -EINVAL;
  250. +       if (copy_from_user(&ksigmask, sigmask, sizeof (ksigmask)))
  251. +           return -EFAULT;
  252. +
  253. +       sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
  254. +       sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
  255. +   }
  256. +
  257. +   ret = do_sys_poll(ufds, nfds, to);
  258. +
  259. +   /* We can restart this syscall, usually */
  260. +   if (ret == -EINTR) {
  261. +       /*
  262. +        * Don't restore the signal mask yet. Let do_signal() deliver
  263. +        * the signal on the way back to userspace, before the signal
  264. +        * mask is restored.
  265. +        */
  266. +       if (sigmask) {
  267. +           memcpy(&current->saved_sigmask, &sigsaved,
  268. +               sizeof(sigsaved));
  269. +           set_restore_sigmask();
  270. +       }
  271. +       ret = -ERESTARTNOHAND;
  272. +   } else if (sigmask)
  273. +       sigprocmask(SIG_SETMASK, &sigsaved, NULL);
  274. +
  275. +   ret = poll_select_copy_remaining_time32(&end_time, tsp, 0, ret);
  276. +
  277. +   return ret;
  278. +}
  279. +#endif /* CONFIG_COMPAT_32BIT_TIME && !CONFIG_64BIT */
  280. +
  281. +#ifdef CONFIG_COMPAT
  282.  #define __COMPAT_NFDBITS       (8 * sizeof(compat_ulong_t))
  283.  
  284.  static
  285. @@ -1145,7 +1309,6 @@ int compat_poll_select_copy_remaining(struct timespec64 *end_time, void __user *
  286.     return ret;
  287.  }
  288.  
  289. -#ifdef CONFIG_COMPAT
  290.  /*
  291.   * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
  292.   * 64-bit unsigned longs.
  293. @@ -1170,18 +1333,6 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
  294.         return 0;
  295.     return compat_put_bitmap(ufdset, fdset, nr);
  296.  }
  297. -#else
  298. -#define compat_get_fd_set get_fd_set
  299. -#define compat_set_fd_set set_fd_set
  300. -#define compat_sigset_t sigset_t
  301. -static inline int get_compat_sigset(sigset_t *set, const sigset_t __user *compat)
  302. -{
  303. -        if (copy_from_user(set, compat, sizeof *set))
  304. -                return -EFAULT;
  305. -
  306. -        return 0;
  307. -}
  308. -#endif
  309.  
  310.  /*
  311.   * This is a virtual copy of sys_select from fs/select.c and probably
  312. @@ -1266,7 +1417,6 @@ static int compat_core_sys_select(int n, compat_ulong_t __user *inp,
  313.  out_nofds:
  314.     return ret;
  315.  }
  316. -#endif
  317.  
  318.  #ifdef CONFIG_COMPAT_32BIT_TIME
  319.  static int do_compat_select(int n, compat_ulong_t __user *inp,
  320. @@ -1437,7 +1587,6 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,
  321.  }
  322.  #endif
  323.  
  324. -#ifdef CONFIG_COMPAT
  325.  static long do_compat_pselect_time64(int n, compat_ulong_t __user *inp,
  326.     compat_ulong_t __user *outp, compat_ulong_t __user *exp,
  327.     struct __kernel_timespec __user *tsp, compat_sigset_t __user *sigmask,
  328. diff --git a/kernel/signal.c b/kernel/signal.c
  329. index 332f019dc421..d3e855a0dc45 100644
  330. --- a/kernel/signal.c
  331. +++ b/kernel/signal.c
  332. @@ -3140,6 +3140,40 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,
  333.     return ret;
  334.  }
  335.  
  336. +#if defined(CONFIG_COMPAT_32BIT_TIME) && !defined(CONFIG_64BIT)
  337. +SYSCALL_DEFINE4(rt_sigtimedwait_time32, sigset_t __user *, uthese,
  338. +       struct siginfo __user *, uinfo,
  339. +       struct __kernel_old_timespec __user *, uts,
  340. +       size_t, sigsetsize)
  341. +{
  342. +   sigset_t s;
  343. +   struct timespec64 t;
  344. +   siginfo_t info;
  345. +   long ret;
  346. +
  347. +   if (sigsetsize != sizeof(sigset_t))
  348. +       return -EINVAL;
  349. +
  350. +   if (copy_from_user(&s, uthese, sizeof(s)))
  351. +       return -EFAULT;
  352. +
  353. +   if (uts) {
  354. +       if (get_old_timespec(&t, uts))
  355. +           return -EFAULT;
  356. +   }
  357. +
  358. +   ret = do_sigtimedwait(&s, &info, uts ? &t : NULL);
  359. +
  360. +   if (ret > 0 && uinfo) {
  361. +       if (copy_siginfo_to_user(uinfo, &info))
  362. +           ret = -EFAULT;
  363. +   }
  364. +
  365. +   return ret;
  366. +}
  367. +#endif
  368. +
  369. +#ifdef CONFIG_COMPAT
  370.  #ifdef CONFIG_COMPAT_32BIT_TIME
  371.  COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
  372.         struct compat_siginfo __user *, uinfo,
  373. @@ -3172,7 +3206,6 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
  374.  }
  375.  #endif
  376.  
  377. -#ifdef CONFIG_COMPAT
  378.  COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait_time64, compat_sigset_t __user *, uthese,
  379.         struct compat_siginfo __user *, uinfo,
  380.         struct __kernel_timespec __user *, uts, compat_size_t, sigsetsize)
  381. diff --git a/net/compat.c b/net/compat.c
  382. index 5af2af1b9723..54d5f4e749e0 100644
  383. --- a/net/compat.c
  384. +++ b/net/compat.c
  385. @@ -841,6 +841,37 @@ COMPAT_SYSCALL_DEFINE5(recvmmsg_time64, int, fd, struct compat_mmsghdr __user *,
  386.     return __compat_sys_recvmmsg_time64(fd, mmsg, vlen, flags, timeout);
  387.  }
  388.  
  389. +#ifdef CONFIG_COMPAT_32BIT_TIME
  390. +int __compat_sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
  391. +             unsigned int vlen, unsigned int flags,
  392. +             struct compat_timespec __user *timeout)
  393. +{
  394. +   int datagrams;
  395. +   struct timespec64 ktspec;
  396. +
  397. +   if (timeout == NULL)
  398. +       return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
  399. +                     flags | MSG_CMSG_COMPAT, NULL);
  400. +
  401. +   if (compat_get_timespec64(&ktspec, timeout))
  402. +       return -EFAULT;
  403. +
  404. +   datagrams = __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
  405. +                  flags | MSG_CMSG_COMPAT, &ktspec);
  406. +   if (datagrams > 0 && compat_put_timespec64(&ktspec, timeout))
  407. +       datagrams = -EFAULT;
  408. +
  409. +   return datagrams;
  410. +}
  411. +
  412. +COMPAT_SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
  413. +              unsigned int, vlen, unsigned int, flags,
  414. +              struct compat_timespec __user *, timeout)
  415. +{
  416. +   return __compat_sys_recvmmsg(fd, mmsg, vlen, flags, timeout);
  417. +}
  418. +#endif
  419. +
  420.  COMPAT_SYSCALL_DEFINE2(socketcall, int, call, u32 __user *, args)
  421.  {
  422.     u32 a[AUDITSC_ARGS];
  423. diff --git a/net/socket.c b/net/socket.c
  424. index f4b6be81c6af..5d3e24e84974 100644
  425. --- a/net/socket.c
  426. +++ b/net/socket.c
  427. @@ -2474,33 +2474,36 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
  428.  }
  429.  
  430.  #ifdef CONFIG_COMPAT_32BIT_TIME
  431. -int __compat_sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
  432. +int __sys_recvmmsg_time32(int fd, struct mmsghdr __user *mmsg,
  433.               unsigned int vlen, unsigned int flags,
  434. -             struct compat_timespec __user *timeout)
  435. +             struct __kernel_old_timespec __user *timeout)
  436.  {
  437.     int datagrams;
  438.     struct timespec64 ktspec;
  439.  
  440. +   if (flags & MSG_CMSG_COMPAT)
  441. +       return -EINVAL;
  442. +
  443.     if (timeout == NULL)
  444.         return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
  445. -                     flags | MSG_CMSG_COMPAT, NULL);
  446. +                     flags, NULL);
  447.  
  448. -   if (compat_get_timespec64(&ktspec, timeout))
  449. +   if (get_old_timespec(&ktspec, timeout))
  450.         return -EFAULT;
  451.  
  452.     datagrams = __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
  453. -                  flags | MSG_CMSG_COMPAT, &ktspec);
  454. -   if (datagrams > 0 && compat_put_timespec64(&ktspec, timeout))
  455. +                  flags , &ktspec);
  456. +   if (datagrams > 0 && put_old_timespec(&ktspec, timeout))
  457.         datagrams = -EFAULT;
  458.  
  459.     return datagrams;
  460.  }
  461.  
  462. -COMPAT_SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
  463. +SYSCALL_DEFINE5(recvmmsg_time32, int, fd, struct mmsghdr __user *, mmsg,
  464.                unsigned int, vlen, unsigned int, flags,
  465. -              struct compat_timespec __user *, timeout)
  466. +              struct __kernel_old_timespec __user *, timeout)
  467.  {
  468. -   return __compat_sys_recvmmsg(fd, mmsg, vlen, flags, timeout);
  469. +   return __sys_recvmmsg_time32(fd, mmsg, vlen, flags, timeout);
  470.  }
  471.  #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement