tst-bz28213.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /* Bug 28213: test for NULL pointer dereference in mq_notify.
  2. Copyright The GNU Toolchain Authors.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #include <errno.h>
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <fcntl.h>
  19. #include <unistd.h>
  20. #include <mqueue.h>
  21. #include <signal.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <support/check.h>
  25. static mqd_t m = -1;
  26. static const char msg[] = "hello";
  27. static void
  28. check_bz28213_cb (union sigval sv)
  29. {
  30. char buf[sizeof (msg)];
  31. (void) sv;
  32. TEST_VERIFY_EXIT ((size_t) mq_receive (m, buf, sizeof (buf), NULL)
  33. == sizeof (buf));
  34. TEST_VERIFY_EXIT (memcmp (buf, msg, sizeof (buf)) == 0);
  35. exit (0);
  36. }
  37. static void
  38. check_bz28213 (void)
  39. {
  40. struct sigevent sev;
  41. memset (&sev, '\0', sizeof (sev));
  42. sev.sigev_notify = SIGEV_THREAD;
  43. sev.sigev_notify_function = check_bz28213_cb;
  44. /* Step 1: Register & unregister notifier.
  45. Helper thread should receive NOTIFY_REMOVED notification.
  46. In a vulnerable version of glibc, NULL pointer dereference follows. */
  47. TEST_VERIFY_EXIT (mq_notify (m, &sev) == 0);
  48. TEST_VERIFY_EXIT (mq_notify (m, NULL) == 0);
  49. /* Step 2: Once again, register notification.
  50. Try to send one message.
  51. Test is considered successful, if the callback does exit (0). */
  52. TEST_VERIFY_EXIT (mq_notify (m, &sev) == 0);
  53. TEST_VERIFY_EXIT (mq_send (m, msg, sizeof (msg), 1) == 0);
  54. /* Wait... */
  55. pause ();
  56. }
  57. static int
  58. do_test (void)
  59. {
  60. static const char m_name[] = "/bz28213_queue";
  61. struct mq_attr m_attr;
  62. memset (&m_attr, '\0', sizeof (m_attr));
  63. m_attr.mq_maxmsg = 1;
  64. m_attr.mq_msgsize = sizeof (msg);
  65. m = mq_open (m_name,
  66. O_RDWR | O_CREAT | O_EXCL,
  67. 0600,
  68. &m_attr);
  69. if (m < 0)
  70. {
  71. if (errno == ENOSYS)
  72. FAIL_UNSUPPORTED ("POSIX message queues are not implemented\n");
  73. FAIL_EXIT1 ("Failed to create POSIX message queue: %m\n");
  74. }
  75. TEST_VERIFY_EXIT (mq_unlink (m_name) == 0);
  76. check_bz28213 ();
  77. return 0;
  78. }
  79. #include <support/test-driver.c>