0002-linux-user-fix-to-handle-variably-sized-SIOCGSTAMP-with-new-kernels.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. From 6d5d5dde9adb5acb32e6b8e3dfbf47fff0f308d2 Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
  3. Date: Thu, 18 Jul 2019 15:06:41 +0200
  4. Subject: [PATCH] linux-user: fix to handle variably sized SIOCGSTAMP with new
  5. kernels
  6. MIME-Version: 1.0
  7. Content-Type: text/plain; charset=UTF-8
  8. Content-Transfer-Encoding: 8bit
  9. The SIOCGSTAMP symbol was previously defined in the
  10. asm-generic/sockios.h header file. QEMU sees that header
  11. indirectly via sys/socket.h
  12. In linux kernel commit 0768e17073dc527ccd18ed5f96ce85f9985e9115
  13. the asm-generic/sockios.h header no longer defines SIOCGSTAMP.
  14. Instead it provides only SIOCGSTAMP_OLD, which only uses a
  15. 32-bit time_t on 32-bit architectures.
  16. The linux/sockios.h header then defines SIOCGSTAMP using
  17. either SIOCGSTAMP_OLD or SIOCGSTAMP_NEW as appropriate. If
  18. SIOCGSTAMP_NEW is used, then the tv_sec field is 64-bit even
  19. on 32-bit architectures
  20. To cope with this we must now convert the old and new type from
  21. the target to the host one.
  22. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
  23. Signed-off-by: Laurent Vivier <laurent@vivier.eu>
  24. Reviewed-by: Arnd Bergmann <arnd@arndb.de>
  25. Message-Id: <20190718130641.15294-1-laurent@vivier.eu>
  26. Signed-off-by: Laurent Vivier <laurent@vivier.eu>
  27. [Retrieved (and backported to 3.1.0) from:
  28. https://github.com/qemu/qemu/commit/6d5d5dde9adb5acb32e6b8e3dfbf47fff0f308d2]
  29. Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
  30. ---
  31. linux-user/ioctls.h | 21 +++++-
  32. linux-user/syscall.c | 140 +++++++++++++++++++++++++++++--------
  33. linux-user/syscall_defs.h | 30 +++++++-
  34. linux-user/syscall_types.h | 6 --
  35. 4 files changed, 159 insertions(+), 38 deletions(-)
  36. diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
  37. index 5e84dc7c3a7..3281c97ca26 100644
  38. --- a/linux-user/ioctls.h
  39. +++ b/linux-user/ioctls.h
  40. @@ -222,8 +222,25 @@
  41. IOCTL(SIOCGIWNAME, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_char_ifreq)))
  42. IOCTL(SIOCSPGRP, IOC_W, MK_PTR(TYPE_INT)) /* pid_t */
  43. IOCTL(SIOCGPGRP, IOC_R, MK_PTR(TYPE_INT)) /* pid_t */
  44. - IOCTL(SIOCGSTAMP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_timeval)))
  45. - IOCTL(SIOCGSTAMPNS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_timespec)))
  46. +
  47. + /*
  48. + * We can't use IOCTL_SPECIAL() because it will set
  49. + * host_cmd to XXX_OLD and XXX_NEW and these macros
  50. + * are not defined with kernel prior to 5.2.
  51. + * We must set host_cmd to the same value as in target_cmd
  52. + * otherwise the consistency check in syscall_init()
  53. + * will trigger an error.
  54. + * host_cmd is ignored by the do_ioctl_XXX() helpers.
  55. + * FIXME: create a macro to define this kind of entry
  56. + */
  57. + { TARGET_SIOCGSTAMP_OLD, TARGET_SIOCGSTAMP_OLD,
  58. + "SIOCGSTAMP_OLD", IOC_R, do_ioctl_SIOCGSTAMP },
  59. + { TARGET_SIOCGSTAMPNS_OLD, TARGET_SIOCGSTAMPNS_OLD,
  60. + "SIOCGSTAMPNS_OLD", IOC_R, do_ioctl_SIOCGSTAMPNS },
  61. + { TARGET_SIOCGSTAMP_NEW, TARGET_SIOCGSTAMP_NEW,
  62. + "SIOCGSTAMP_NEW", IOC_R, do_ioctl_SIOCGSTAMP },
  63. + { TARGET_SIOCGSTAMPNS_NEW, TARGET_SIOCGSTAMPNS_NEW,
  64. + "SIOCGSTAMPNS_NEW", IOC_R, do_ioctl_SIOCGSTAMPNS },
  65. IOCTL(RNDGETENTCNT, IOC_R, MK_PTR(TYPE_INT))
  66. IOCTL(RNDADDTOENTCNT, IOC_W, MK_PTR(TYPE_INT))
  67. diff --git a/linux-user/syscall.c b/linux-user/syscall.c
  68. index 39a37496fed..8367cb138df 100644
  69. --- a/linux-user/syscall.c
  70. +++ b/linux-user/syscall.c
  71. @@ -37,6 +37,7 @@
  72. #include <sched.h>
  73. #include <sys/timex.h>
  74. #include <sys/socket.h>
  75. +#include <linux/sockios.h>
  76. #include <sys/un.h>
  77. #include <sys/uio.h>
  78. #include <poll.h>
  79. @@ -1126,8 +1127,9 @@ static inline abi_long copy_from_user_timeval(struct timeval *tv,
  80. {
  81. struct target_timeval *target_tv;
  82. - if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
  83. + if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
  84. return -TARGET_EFAULT;
  85. + }
  86. __get_user(tv->tv_sec, &target_tv->tv_sec);
  87. __get_user(tv->tv_usec, &target_tv->tv_usec);
  88. @@ -1142,8 +1144,26 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
  89. {
  90. struct target_timeval *target_tv;
  91. - if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
  92. + if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
  93. + return -TARGET_EFAULT;
  94. + }
  95. +
  96. + __put_user(tv->tv_sec, &target_tv->tv_sec);
  97. + __put_user(tv->tv_usec, &target_tv->tv_usec);
  98. +
  99. + unlock_user_struct(target_tv, target_tv_addr, 1);
  100. +
  101. + return 0;
  102. +}
  103. +
  104. +static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr,
  105. + const struct timeval *tv)
  106. +{
  107. + struct target__kernel_sock_timeval *target_tv;
  108. +
  109. + if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
  110. return -TARGET_EFAULT;
  111. + }
  112. __put_user(tv->tv_sec, &target_tv->tv_sec);
  113. __put_user(tv->tv_usec, &target_tv->tv_usec);
  114. @@ -1153,6 +1173,48 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
  115. return 0;
  116. }
  117. +static inline abi_long target_to_host_timespec(struct timespec *host_ts,
  118. + abi_ulong target_addr)
  119. +{
  120. + struct target_timespec *target_ts;
  121. +
  122. + if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
  123. + return -TARGET_EFAULT;
  124. + }
  125. + __get_user(host_ts->tv_sec, &target_ts->tv_sec);
  126. + __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
  127. + unlock_user_struct(target_ts, target_addr, 0);
  128. + return 0;
  129. +}
  130. +
  131. +static inline abi_long host_to_target_timespec(abi_ulong target_addr,
  132. + struct timespec *host_ts)
  133. +{
  134. + struct target_timespec *target_ts;
  135. +
  136. + if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
  137. + return -TARGET_EFAULT;
  138. + }
  139. + __put_user(host_ts->tv_sec, &target_ts->tv_sec);
  140. + __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
  141. + unlock_user_struct(target_ts, target_addr, 1);
  142. + return 0;
  143. +}
  144. +
  145. +static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
  146. + struct timespec *host_ts)
  147. +{
  148. + struct target__kernel_timespec *target_ts;
  149. +
  150. + if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
  151. + return -TARGET_EFAULT;
  152. + }
  153. + __put_user(host_ts->tv_sec, &target_ts->tv_sec);
  154. + __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
  155. + unlock_user_struct(target_ts, target_addr, 1);
  156. + return 0;
  157. +}
  158. +
  159. static inline abi_long copy_from_user_timezone(struct timezone *tz,
  160. abi_ulong target_tz_addr)
  161. {
  162. @@ -4899,6 +4961,54 @@ static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
  163. return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
  164. }
  165. +static abi_long do_ioctl_SIOCGSTAMP(const IOCTLEntry *ie, uint8_t *buf_temp,
  166. + int fd, int cmd, abi_long arg)
  167. +{
  168. + struct timeval tv;
  169. + abi_long ret;
  170. +
  171. + ret = get_errno(safe_ioctl(fd, SIOCGSTAMP, &tv));
  172. + if (is_error(ret)) {
  173. + return ret;
  174. + }
  175. +
  176. + if (cmd == (int)TARGET_SIOCGSTAMP_OLD) {
  177. + if (copy_to_user_timeval(arg, &tv)) {
  178. + return -TARGET_EFAULT;
  179. + }
  180. + } else {
  181. + if (copy_to_user_timeval64(arg, &tv)) {
  182. + return -TARGET_EFAULT;
  183. + }
  184. + }
  185. +
  186. + return ret;
  187. +}
  188. +
  189. +static abi_long do_ioctl_SIOCGSTAMPNS(const IOCTLEntry *ie, uint8_t *buf_temp,
  190. + int fd, int cmd, abi_long arg)
  191. +{
  192. + struct timespec ts;
  193. + abi_long ret;
  194. +
  195. + ret = get_errno(safe_ioctl(fd, SIOCGSTAMPNS, &ts));
  196. + if (is_error(ret)) {
  197. + return ret;
  198. + }
  199. +
  200. + if (cmd == (int)TARGET_SIOCGSTAMPNS_OLD) {
  201. + if (host_to_target_timespec(arg, &ts)) {
  202. + return -TARGET_EFAULT;
  203. + }
  204. + } else{
  205. + if (host_to_target_timespec64(arg, &ts)) {
  206. + return -TARGET_EFAULT;
  207. + }
  208. + }
  209. +
  210. + return ret;
  211. +}
  212. +
  213. #ifdef TIOCGPTPEER
  214. static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
  215. int fd, int cmd, abi_long arg)
  216. @@ -6271,32 +6381,6 @@ static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
  217. }
  218. #endif
  219. -static inline abi_long target_to_host_timespec(struct timespec *host_ts,
  220. - abi_ulong target_addr)
  221. -{
  222. - struct target_timespec *target_ts;
  223. -
  224. - if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
  225. - return -TARGET_EFAULT;
  226. - __get_user(host_ts->tv_sec, &target_ts->tv_sec);
  227. - __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
  228. - unlock_user_struct(target_ts, target_addr, 0);
  229. - return 0;
  230. -}
  231. -
  232. -static inline abi_long host_to_target_timespec(abi_ulong target_addr,
  233. - struct timespec *host_ts)
  234. -{
  235. - struct target_timespec *target_ts;
  236. -
  237. - if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
  238. - return -TARGET_EFAULT;
  239. - __put_user(host_ts->tv_sec, &target_ts->tv_sec);
  240. - __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
  241. - unlock_user_struct(target_ts, target_addr, 1);
  242. - return 0;
  243. -}
  244. -
  245. static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec,
  246. abi_ulong target_addr)
  247. {
  248. diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
  249. index fffa89f2564..06622703008 100644
  250. --- a/linux-user/syscall_defs.h
  251. +++ b/linux-user/syscall_defs.h
  252. @@ -209,16 +209,34 @@ struct target_linger {
  253. abi_int l_linger; /* How long to linger for */
  254. };
  255. +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
  256. +struct target_timeval {
  257. + abi_long tv_sec;
  258. + abi_int tv_usec;
  259. +};
  260. +#define target__kernel_sock_timeval target_timeval
  261. +#else
  262. struct target_timeval {
  263. abi_long tv_sec;
  264. abi_long tv_usec;
  265. };
  266. +struct target__kernel_sock_timeval {
  267. + abi_llong tv_sec;
  268. + abi_llong tv_usec;
  269. +};
  270. +#endif
  271. +
  272. struct target_timespec {
  273. abi_long tv_sec;
  274. abi_long tv_nsec;
  275. };
  276. +struct target__kernel_timespec {
  277. + abi_llong tv_sec;
  278. + abi_llong tv_nsec;
  279. +};
  280. +
  281. struct target_timezone {
  282. abi_int tz_minuteswest;
  283. abi_int tz_dsttime;
  284. @@ -749,8 +767,16 @@ struct target_pollfd {
  285. #define TARGET_SIOCATMARK 0x8905
  286. #define TARGET_SIOCGPGRP 0x8904
  287. #endif
  288. -#define TARGET_SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
  289. -#define TARGET_SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
  290. +#if defined(TARGET_SH4)
  291. +#define TARGET_SIOCGSTAMP_OLD TARGET_IOR('s', 100, struct target_timeval)
  292. +#define TARGET_SIOCGSTAMPNS_OLD TARGET_IOR('s', 101, struct target_timespec)
  293. +#else
  294. +#define TARGET_SIOCGSTAMP_OLD 0x8906
  295. +#define TARGET_SIOCGSTAMPNS_OLD 0x8907
  296. +#endif
  297. +
  298. +#define TARGET_SIOCGSTAMP_NEW TARGET_IOR(0x89, 0x06, abi_llong[2])
  299. +#define TARGET_SIOCGSTAMPNS_NEW TARGET_IOR(0x89, 0x07, abi_llong[2])
  300. /* Networking ioctls */
  301. #define TARGET_SIOCADDRT 0x890B /* add routing table entry */
  302. diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
  303. index b98a23b0f1b..4e369838262 100644
  304. --- a/linux-user/syscall_types.h
  305. +++ b/linux-user/syscall_types.h
  306. @@ -14,12 +14,6 @@ STRUCT(serial_icounter_struct,
  307. STRUCT(sockaddr,
  308. TYPE_SHORT, MK_ARRAY(TYPE_CHAR, 14))
  309. -STRUCT(timeval,
  310. - MK_ARRAY(TYPE_LONG, 2))
  311. -
  312. -STRUCT(timespec,
  313. - MK_ARRAY(TYPE_LONG, 2))
  314. -
  315. STRUCT(rtentry,
  316. TYPE_ULONG, MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr),
  317. TYPE_SHORT, TYPE_SHORT, TYPE_ULONG, TYPE_PTRVOID, TYPE_SHORT, TYPE_PTRVOID,