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