fclog.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Author: Aleksa Sarai <cyphar@cyphar.com>
  4. * Copyright (C) 2025 SUSE LLC.
  5. */
  6. #include <assert.h>
  7. #include <errno.h>
  8. #include <sched.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include <sys/mount.h>
  14. #include "kselftest_harness.h"
  15. #define ASSERT_ERRNO(expected, _t, seen) \
  16. __EXPECT(expected, #expected, \
  17. ({__typeof__(seen) _tmp_seen = (seen); \
  18. _tmp_seen >= 0 ? _tmp_seen : -errno; }), #seen, _t, 1)
  19. #define ASSERT_ERRNO_EQ(expected, seen) \
  20. ASSERT_ERRNO(expected, ==, seen)
  21. #define ASSERT_SUCCESS(seen) \
  22. ASSERT_ERRNO(0, <=, seen)
  23. FIXTURE(ns)
  24. {
  25. int host_mntns;
  26. };
  27. FIXTURE_SETUP(ns)
  28. {
  29. /* Stash the old mntns. */
  30. self->host_mntns = open("/proc/self/ns/mnt", O_RDONLY|O_CLOEXEC);
  31. ASSERT_SUCCESS(self->host_mntns);
  32. /* Create a new mount namespace and make it private. */
  33. ASSERT_SUCCESS(unshare(CLONE_NEWNS));
  34. ASSERT_SUCCESS(mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL));
  35. }
  36. FIXTURE_TEARDOWN(ns)
  37. {
  38. ASSERT_SUCCESS(setns(self->host_mntns, CLONE_NEWNS));
  39. ASSERT_SUCCESS(close(self->host_mntns));
  40. }
  41. TEST_F(ns, fscontext_log_enodata)
  42. {
  43. int fsfd = fsopen("tmpfs", FSOPEN_CLOEXEC);
  44. ASSERT_SUCCESS(fsfd);
  45. /* A brand new fscontext has no log entries. */
  46. char buf[128] = {};
  47. for (int i = 0; i < 16; i++)
  48. ASSERT_ERRNO_EQ(-ENODATA, read(fsfd, buf, sizeof(buf)));
  49. ASSERT_SUCCESS(close(fsfd));
  50. }
  51. TEST_F(ns, fscontext_log_errorfc)
  52. {
  53. int fsfd = fsopen("tmpfs", FSOPEN_CLOEXEC);
  54. ASSERT_SUCCESS(fsfd);
  55. ASSERT_ERRNO_EQ(-EINVAL, fsconfig(fsfd, FSCONFIG_SET_STRING, "invalid-arg", "123", 0));
  56. char buf[128] = {};
  57. ASSERT_SUCCESS(read(fsfd, buf, sizeof(buf)));
  58. EXPECT_STREQ("e tmpfs: Unknown parameter 'invalid-arg'\n", buf);
  59. /* The message has been consumed. */
  60. ASSERT_ERRNO_EQ(-ENODATA, read(fsfd, buf, sizeof(buf)));
  61. ASSERT_SUCCESS(close(fsfd));
  62. }
  63. TEST_F(ns, fscontext_log_errorfc_after_fsmount)
  64. {
  65. int fsfd = fsopen("tmpfs", FSOPEN_CLOEXEC);
  66. ASSERT_SUCCESS(fsfd);
  67. ASSERT_ERRNO_EQ(-EINVAL, fsconfig(fsfd, FSCONFIG_SET_STRING, "invalid-arg", "123", 0));
  68. ASSERT_SUCCESS(fsconfig(fsfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0));
  69. int mfd = fsmount(fsfd, FSMOUNT_CLOEXEC, MOUNT_ATTR_NOEXEC | MOUNT_ATTR_NOSUID);
  70. ASSERT_SUCCESS(mfd);
  71. ASSERT_SUCCESS(move_mount(mfd, "", AT_FDCWD, "/tmp", MOVE_MOUNT_F_EMPTY_PATH));
  72. /*
  73. * The fscontext log should still contain data even after
  74. * FSCONFIG_CMD_CREATE and fsmount().
  75. */
  76. char buf[128] = {};
  77. ASSERT_SUCCESS(read(fsfd, buf, sizeof(buf)));
  78. EXPECT_STREQ("e tmpfs: Unknown parameter 'invalid-arg'\n", buf);
  79. /* The message has been consumed. */
  80. ASSERT_ERRNO_EQ(-ENODATA, read(fsfd, buf, sizeof(buf)));
  81. ASSERT_SUCCESS(close(fsfd));
  82. }
  83. TEST_F(ns, fscontext_log_emsgsize)
  84. {
  85. int fsfd = fsopen("tmpfs", FSOPEN_CLOEXEC);
  86. ASSERT_SUCCESS(fsfd);
  87. ASSERT_ERRNO_EQ(-EINVAL, fsconfig(fsfd, FSCONFIG_SET_STRING, "invalid-arg", "123", 0));
  88. char buf[128] = {};
  89. /*
  90. * Attempting to read a message with too small a buffer should not
  91. * result in the message getting consumed.
  92. */
  93. ASSERT_ERRNO_EQ(-EMSGSIZE, read(fsfd, buf, 0));
  94. ASSERT_ERRNO_EQ(-EMSGSIZE, read(fsfd, buf, 1));
  95. for (int i = 0; i < 16; i++)
  96. ASSERT_ERRNO_EQ(-EMSGSIZE, read(fsfd, buf, 16));
  97. ASSERT_SUCCESS(read(fsfd, buf, sizeof(buf)));
  98. EXPECT_STREQ("e tmpfs: Unknown parameter 'invalid-arg'\n", buf);
  99. /* The message has been consumed. */
  100. ASSERT_ERRNO_EQ(-ENODATA, read(fsfd, buf, sizeof(buf)));
  101. ASSERT_SUCCESS(close(fsfd));
  102. }
  103. TEST_HARNESS_MAIN