Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
7#include <assert.h>
8#include <errno.h>
9#include <sched.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <unistd.h>
14#include <sys/mount.h>
15
16#include "kselftest_harness.h"
17
18#define ASSERT_ERRNO(expected, _t, seen) \
19 __EXPECT(expected, #expected, \
20 ({__typeof__(seen) _tmp_seen = (seen); \
21 _tmp_seen >= 0 ? _tmp_seen : -errno; }), #seen, _t, 1)
22
23#define ASSERT_ERRNO_EQ(expected, seen) \
24 ASSERT_ERRNO(expected, ==, seen)
25
26#define ASSERT_SUCCESS(seen) \
27 ASSERT_ERRNO(0, <=, seen)
28
29FIXTURE(ns)
30{
31 int host_mntns;
32};
33
34FIXTURE_SETUP(ns)
35{
36 /* Stash the old mntns. */
37 self->host_mntns = open("/proc/self/ns/mnt", O_RDONLY|O_CLOEXEC);
38 ASSERT_SUCCESS(self->host_mntns);
39
40 /* Create a new mount namespace and make it private. */
41 ASSERT_SUCCESS(unshare(CLONE_NEWNS));
42 ASSERT_SUCCESS(mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL));
43}
44
45FIXTURE_TEARDOWN(ns)
46{
47 ASSERT_SUCCESS(setns(self->host_mntns, CLONE_NEWNS));
48 ASSERT_SUCCESS(close(self->host_mntns));
49}
50
51TEST_F(ns, fscontext_log_enodata)
52{
53 int fsfd = fsopen("tmpfs", FSOPEN_CLOEXEC);
54 ASSERT_SUCCESS(fsfd);
55
56 /* A brand new fscontext has no log entries. */
57 char buf[128] = {};
58 for (int i = 0; i < 16; i++)
59 ASSERT_ERRNO_EQ(-ENODATA, read(fsfd, buf, sizeof(buf)));
60
61 ASSERT_SUCCESS(close(fsfd));
62}
63
64TEST_F(ns, fscontext_log_errorfc)
65{
66 int fsfd = fsopen("tmpfs", FSOPEN_CLOEXEC);
67 ASSERT_SUCCESS(fsfd);
68
69 ASSERT_ERRNO_EQ(-EINVAL, fsconfig(fsfd, FSCONFIG_SET_STRING, "invalid-arg", "123", 0));
70
71 char buf[128] = {};
72 ASSERT_SUCCESS(read(fsfd, buf, sizeof(buf)));
73 EXPECT_STREQ("e tmpfs: Unknown parameter 'invalid-arg'\n", buf);
74
75 /* The message has been consumed. */
76 ASSERT_ERRNO_EQ(-ENODATA, read(fsfd, buf, sizeof(buf)));
77 ASSERT_SUCCESS(close(fsfd));
78}
79
80TEST_F(ns, fscontext_log_errorfc_after_fsmount)
81{
82 int fsfd = fsopen("tmpfs", FSOPEN_CLOEXEC);
83 ASSERT_SUCCESS(fsfd);
84
85 ASSERT_ERRNO_EQ(-EINVAL, fsconfig(fsfd, FSCONFIG_SET_STRING, "invalid-arg", "123", 0));
86
87 ASSERT_SUCCESS(fsconfig(fsfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0));
88 int mfd = fsmount(fsfd, FSMOUNT_CLOEXEC, MOUNT_ATTR_NOEXEC | MOUNT_ATTR_NOSUID);
89 ASSERT_SUCCESS(mfd);
90 ASSERT_SUCCESS(move_mount(mfd, "", AT_FDCWD, "/tmp", MOVE_MOUNT_F_EMPTY_PATH));
91
92 /*
93 * The fscontext log should still contain data even after
94 * FSCONFIG_CMD_CREATE and fsmount().
95 */
96 char buf[128] = {};
97 ASSERT_SUCCESS(read(fsfd, buf, sizeof(buf)));
98 EXPECT_STREQ("e tmpfs: Unknown parameter 'invalid-arg'\n", buf);
99
100 /* The message has been consumed. */
101 ASSERT_ERRNO_EQ(-ENODATA, read(fsfd, buf, sizeof(buf)));
102 ASSERT_SUCCESS(close(fsfd));
103}
104
105TEST_F(ns, fscontext_log_emsgsize)
106{
107 int fsfd = fsopen("tmpfs", FSOPEN_CLOEXEC);
108 ASSERT_SUCCESS(fsfd);
109
110 ASSERT_ERRNO_EQ(-EINVAL, fsconfig(fsfd, FSCONFIG_SET_STRING, "invalid-arg", "123", 0));
111
112 char buf[128] = {};
113 /*
114 * Attempting to read a message with too small a buffer should not
115 * result in the message getting consumed.
116 */
117 ASSERT_ERRNO_EQ(-EMSGSIZE, read(fsfd, buf, 0));
118 ASSERT_ERRNO_EQ(-EMSGSIZE, read(fsfd, buf, 1));
119 for (int i = 0; i < 16; i++)
120 ASSERT_ERRNO_EQ(-EMSGSIZE, read(fsfd, buf, 16));
121
122 ASSERT_SUCCESS(read(fsfd, buf, sizeof(buf)));
123 EXPECT_STREQ("e tmpfs: Unknown parameter 'invalid-arg'\n", buf);
124
125 /* The message has been consumed. */
126 ASSERT_ERRNO_EQ(-ENODATA, read(fsfd, buf, sizeof(buf)));
127 ASSERT_SUCCESS(close(fsfd));
128}
129
130TEST_HARNESS_MAIN