projects/linux·blob master · refs

158 lines · 4.5 KiB

1// SPDX-License-Identifier: GPL-2.0
2/*
3 * An 'F' entry keeps its interpreter open for as long as the entry exists,
4 * and the entry only goes away when the binfmt_misc superblock is destroyed.
5 * An interpreter that lives on a mount which in turn keeps that superblock
6 * alive therefore pins the instance that owns it, and nothing can break the
7 * cycle. Check the two ways userspace could arrange for that: an interpreter
8 * on the binfmt_misc instance itself, and one on a filesystem stacked on it.
9 *
10 * Runs unprivileged in a user namespace; binfmt_misc is FS_USERNS_MOUNT.
11 */
12#define _GNU_SOURCE
13#include <fcntl.h>
14#include <limits.h>
15#include <sched.h>
16#include <sys/mount.h>
17#include <sys/stat.h>
18
19#include "../filesystems/utils.h"
20#include "kselftest_harness.h"
21
22#define MNT "/tmp/binfmt_selfpin"
23#define BACKING "/tmp/binfmt_selfpin_back"
24#define LOWER BACKING "/lower"
25#define MERGED "/tmp/binfmt_selfpin_merged"
26
27#define MAGIC "\\xde\\xad"
28#define RULE(interp) ":selfpin:M::" MAGIC "::" interp ":F"
29/* Not on the instance, and unlike /bin/true it always exists. */
30#define INTERP "/proc/self/exe"
31
32#define OPTS_MAX (3 * PATH_MAX + 64)
33
34static int ensure_dir(const char *path)
35{
36 if (mkdir(path, 0755) && errno != EEXIST)
37 return -1;
38 return 0;
39}
40
41/* Write @rule to this instance's register file, preserving write(2)'s errno. */
42static int register_at(struct __test_metadata *_metadata, const char *rule)
43{
44 int fd, saved;
45 ssize_t n;
46
47 fd = open(MNT "/register", O_WRONLY);
48 ASSERT_GE(fd, 0);
49 n = write(fd, rule, strlen(rule));
50 saved = errno;
51 close(fd);
52 errno = saved;
53 return n < 0 ? -1 : 0;
54}
55
56/*
57 * Mount an overlay over @lower using a private upper/work pair, so the two
58 * mounts this test performs cannot interfere with each other and neither
59 * overlaps the lower layer.
60 */
61static int mount_overlay(const char *lower, int nr)
62{
63 char opts[OPTS_MAX], upper[PATH_MAX], work[PATH_MAX];
64
65 snprintf(upper, sizeof(upper), "%s/upper%d", BACKING, nr);
66 snprintf(work, sizeof(work), "%s/work%d", BACKING, nr);
67 if (mkdir(upper, 0755) || mkdir(work, 0755))
68 return -1;
69
70 snprintf(opts, sizeof(opts), "lowerdir=%s,upperdir=%s,workdir=%s",
71 lower, upper, work);
72 return mount("ovl", MERGED, "overlay", 0, opts);
73}
74
75FIXTURE(selfpin) {
76};
77
78FIXTURE_SETUP(selfpin)
79{
80 /* setup_userns() exits rather than returns if this is not there. */
81 if (access("/proc/self/ns/user", F_OK))
82 SKIP(return, "kernel without user namespaces");
83 ASSERT_EQ(setup_userns(), 0);
84
85 ASSERT_EQ(ensure_dir(MNT), 0);
86 if (mount("binfmt_misc", MNT, "binfmt_misc", 0, NULL)) {
87 int saved = errno;
88
89 /* Teardown doesn't run when setup skips, so clean up here. */
90 rmdir(MNT);
91 SKIP(return, "no binfmt_misc: %s", strerror(saved));
92 }
93}
94
95FIXTURE_TEARDOWN(selfpin)
96{
97 /* The namespaces go with the process; just don't litter /tmp. */
98 umount2(MERGED, MNT_DETACH);
99 umount2(BACKING, MNT_DETACH);
100 umount2(MNT, MNT_DETACH);
101 rmdir(MERGED);
102 rmdir(BACKING);
103 rmdir(MNT);
104}
105
106/*
107 * The instance's own files are regular files the mounter owns, so they can be
108 * made executable. Opening one for exec still has to fail, otherwise the entry
109 * pins the very superblock it lives in.
110 */
111TEST_F(selfpin, interpreter_on_the_instance)
112{
113 ASSERT_EQ(chmod(MNT "/status", 0755), 0);
114
115 ASSERT_NE(register_at(_metadata, RULE(MNT "/status")), 0);
116 EXPECT_EQ(errno, EACCES);
117}
118
119/* Same for an entry file rather than one of the control files. */
120TEST_F(selfpin, interpreter_on_an_entry)
121{
122 ASSERT_EQ(register_at(_metadata, ":victim:M::" MAGIC "::" INTERP ":"), 0);
123 ASSERT_EQ(chmod(MNT "/victim", 0755), 0);
124
125 ASSERT_NE(register_at(_metadata, RULE(MNT "/victim")), 0);
126 EXPECT_EQ(errno, EACCES);
127}
128
129/*
130 * A stacking filesystem holds a private clone of each layer for its whole
131 * lifetime, so an instance used as a layer can be pinned by an interpreter
132 * that does not live on it at all. Refuse to be a layer.
133 */
134TEST_F(selfpin, refuses_to_be_stacked_on)
135{
136 ASSERT_EQ(ensure_dir(BACKING), 0);
137 ASSERT_EQ(mount("tmpfs", BACKING, "tmpfs", 0, NULL), 0);
138 ASSERT_EQ(mkdir(LOWER, 0755), 0);
139 ASSERT_EQ(ensure_dir(MERGED), 0);
140
141 /* Nothing to prove unless overlayfs works here at all. */
142 if (mount_overlay(LOWER, 1)) {
143 if (errno == ENODEV || errno == EPERM)
144 SKIP(return, "no unprivileged overlayfs");
145 SKIP(return, "overlayfs unusable here: %s", strerror(errno));
146 }
147 ASSERT_EQ(umount(MERGED), 0);
148
149 EXPECT_NE(mount_overlay(MNT, 2), 0);
150}
151
152/* An ordinary interpreter still registers with 'F'. */
153TEST_F(selfpin, ordinary_interpreter_still_works)
154{
155 EXPECT_EQ(register_at(_metadata, RULE(INTERP)), 0);
156}
157
158TEST_HARNESS_MAIN