611-mips_syscall_error_argument.patch 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. commit 2952c70804b48bb5c87eea21df5e401969dc4ec1
  2. Author: Kevin Cernekee <cernekee@gmail.com>
  3. Date: Tue Jun 5 15:05:20 2012 -0700
  4. MIPS: Use $a0 instead of $v0 for __syscall_error() argument
  5. $a0 is saved across _dl_runtime_resolve(); $v0 is not. Unfortunately,
  6. __syscall_error() uses $v0 for its argument, not $a0 as is the MIPS ABI
  7. standard. This means that if lazy binding was used for __syscall_error(),
  8. the errno value in $v0 could get corrupted.
  9. The problem can be easily seen in testcases where syscalls in librt fail;
  10. when librt tries to call __syscall_error() in libc, the argument gets
  11. lost and errno gets set to a bogus value:
  12. # ./tst-mqueue1 ; echo $?
  13. mq_receive on O_WRONLY mqd_t did not fail with EBADF: Unknown error 2004684208
  14. 1
  15. # ./tst-mqueue2 ; echo $?
  16. mq_timedreceive with too small msg_len did not fail with EMSGSIZE: Unknown error 1997360560
  17. 1
  18. # ./tst-mqueue4 ; echo $?
  19. mq_timedsend did not fail with ETIMEDOUT: Unknown error 2008747440
  20. 1
  21. When _dl_runtime_resolve() was taken out of the equation, the same test
  22. cases passed:
  23. # LD_BIND_NOW=y ./tst-mqueue1 ; echo $?
  24. 0
  25. # LD_BIND_NOW=y ./tst-mqueue2 ; echo $?
  26. 0
  27. # LD_BIND_NOW=y ./tst-mqueue4 ; echo $?
  28. 0
  29. Changing __syscall_error() to look at $a0 instead of $v0 fixed the
  30. problem.
  31. (Note that there is also a "__syscall_error.c" file which presumably
  32. uses the standard C calling conventions, but I do not think it is used
  33. on MIPS.)
  34. Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
  35. Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
  36. commit 3c58d95d918c7e2fda374c37a52f81b34b81e4ca
  37. Author: Kevin Cernekee <cernekee@gmail.com>
  38. Date: Tue Jun 5 15:05:19 2012 -0700
  39. MIPS: Convert __syscall_error() callers to use $a0 for argument
  40. Some callers passed the first argument in $v0, while others used $a0.
  41. Change the callers to use $a0 consistently.
  42. Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
  43. Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
  44. --- a/libc/sysdeps/linux/mips/vfork.S
  45. +++ b/libc/sysdeps/linux/mips/vfork.S
  46. @@ -84,6 +84,7 @@ NESTED(__vfork,FRAMESZ,sp)
  47. /* Something bad happened -- no child created. */
  48. L(error):
  49. + move a0, v0
  50. #ifdef __PIC__
  51. PTR_LA t9, __syscall_error
  52. RESTORE_GP64
  53. --- a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h
  54. +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h
  55. @@ -31,7 +31,7 @@
  56. # undef PSEUDO
  57. # define PSEUDO(name, syscall_name, args) \
  58. .align 2; \
  59. - 99: \
  60. + 99: move a0, v0; \
  61. PTR_LA t9,__syscall_error; \
  62. /* manual cpreturn. */ \
  63. REG_L gp, STKOFF_GP(sp); \
  64. --- a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/vfork.S
  65. +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/vfork.S
  66. @@ -80,6 +80,7 @@ NESTED(__vfork,FRAMESZ,sp)
  67. /* Something bad happened -- no child created. */
  68. L(error):
  69. + move a0, v0
  70. #ifdef __PIC__
  71. PTR_LA t9, __syscall_error
  72. RESTORE_GP64
  73. --- a/libc/sysdeps/linux/mips/syscall_error.S
  74. +++ b/libc/sysdeps/linux/mips/syscall_error.S
  75. @@ -43,7 +43,7 @@ ENTRY(__syscall_error)
  76. #ifdef __PIC__
  77. SAVE_GP(GPOFF)
  78. #endif
  79. - REG_S v0, V0OFF(sp)
  80. + REG_S a0, V0OFF(sp)
  81. REG_S ra, RAOFF(sp)
  82. /* Find our per-thread errno address */