xref: /linux/tools/testing/selftests/exec/binfmt_misc_selfpin.c (revision 25757bc855e388eedf86c69c382857ef2c67b08e)
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 
34 static 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. */
42 static 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  */
61 static 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 
75 FIXTURE(selfpin) {
76 };
77 
78 FIXTURE_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 
95 FIXTURE_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  */
111 TEST_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. */
120 TEST_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  */
134 TEST_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'. */
153 TEST_F(selfpin, ordinary_interpreter_still_works)
154 {
155 	EXPECT_EQ(register_at(_metadata, RULE(INTERP)), 0);
156 }
157 
158 TEST_HARNESS_MAIN
159