tst-setuid2.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /* Copyright (C) 2014-2019 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <http://www.gnu.org/licenses/>. */
  14. #include <errno.h>
  15. #include <pthread.h>
  16. #include <signal.h>
  17. #include <stdbool.h>
  18. #include <stdio.h>
  19. #include <sys/syscall.h>
  20. #include <unistd.h>
  21. /* Check that a partial setuid failure aborts the process. */
  22. static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  23. static pthread_cond_t cond_send;
  24. static void (*func_sent) (void);
  25. static pthread_cond_t cond_recv;
  26. #define FAIL(fmt, ...) \
  27. do { printf ("FAIL: " fmt "\n", __VA_ARGS__); _exit (1); } while (0)
  28. static void *
  29. thread_func (void *ctx __attribute__ ((unused)))
  30. {
  31. int ret = pthread_mutex_lock (&mutex);
  32. if (ret != 0)
  33. FAIL ("pthread_mutex_lock (thread): %d", ret);
  34. while (true)
  35. {
  36. if (func_sent != NULL)
  37. {
  38. void (*func) (void) = func_sent;
  39. ret = pthread_mutex_unlock (&mutex);
  40. if (ret != 0)
  41. FAIL ("pthread_mutex_unlock (thread): %d", ret);
  42. func ();
  43. ret = pthread_mutex_lock (&mutex);
  44. if (ret != 0)
  45. FAIL ("pthread_mutex_lock (thread): %d", ret);
  46. func_sent = NULL;
  47. ret = pthread_cond_signal (&cond_recv);
  48. if (ret != 0)
  49. FAIL ("pthread_cond_signal (recv): %d", ret);
  50. }
  51. ret = pthread_cond_wait (&cond_send, &mutex);
  52. if (ret != 0)
  53. FAIL ("pthread_cond_wait (send): %d", ret);
  54. }
  55. return NULL;
  56. }
  57. static void
  58. run_on_thread (void (*func) (void))
  59. {
  60. int ret = pthread_mutex_lock (&mutex);
  61. if (ret != 0)
  62. FAIL ("pthread_mutex_lock (%s): %d", __func__, ret);
  63. func_sent = func;
  64. ret = pthread_mutex_unlock (&mutex);
  65. if (ret != 0)
  66. FAIL ("pthread_mutex_unlock (%s): %d", __func__, ret);
  67. ret = pthread_cond_signal (&cond_send);
  68. if (ret != 0)
  69. FAIL ("pthread_mutex_lock (%s): %d", __func__, ret);
  70. ret = pthread_mutex_lock (&mutex);
  71. if (ret != 0)
  72. FAIL ("pthread_mutex_lock (%s): %d", __func__, ret);
  73. while (func_sent != NULL)
  74. {
  75. ret = pthread_cond_wait (&cond_recv, &mutex);
  76. if (ret != 0)
  77. FAIL ("pthread_mutex_wait (%s): %d", __func__, ret);
  78. }
  79. ret = pthread_mutex_unlock (&mutex);
  80. if (ret != 0)
  81. FAIL ("pthread_mutex_unlock (%s): %d", __func__, ret);
  82. }
  83. static void
  84. change_thread_ids (void)
  85. {
  86. long ret = syscall (__NR_setresuid, 2001, 2002, 2003);
  87. if (ret != 0)
  88. FAIL ("setresuid (2001, 2002, 2003): %ld", ret);
  89. }
  90. static uid_t ruid, euid, suid;
  91. static void
  92. get_thread_ids (void)
  93. {
  94. if (getresuid (&ruid, &euid, &suid) < 0)
  95. FAIL ("getresuid: %m (%d)", errno);
  96. }
  97. static void
  98. abort_expected (int signal __attribute__ ((unused)))
  99. {
  100. _exit (0);
  101. }
  102. static int
  103. do_test (void)
  104. {
  105. pthread_t thread;
  106. int ret = pthread_create (&thread, NULL, thread_func, NULL);
  107. if (ret != 0)
  108. FAIL ("pthread_create: %d", ret);
  109. run_on_thread (change_thread_ids);
  110. signal (SIGABRT, &abort_expected);
  111. /* This should abort the process. */
  112. if (setresuid (1001, 1002, 1003) < 0)
  113. FAIL ("setresuid: %m (%d)", errno);
  114. signal (SIGABRT, SIG_DFL);
  115. /* If we get here, check that the kernel did the right thing. */
  116. run_on_thread (get_thread_ids);
  117. if (ruid != 1001 || euid != 1002 || suid != 1003)
  118. FAIL ("unexpected UIDs after setuid: %ld, %ld, %ld",
  119. (long) ruid, (long) euid, (long) suid);
  120. return 0;
  121. }
  122. #define TEST_FUNCTION do_test ()
  123. #include "../test-skeleton.c"