projects/linux·blob master · refs

127 lines · 2.8 KiB

1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Test which characters may delimit the fields of a register string.
4 */
5#define _GNU_SOURCE
6#include <stdio.h>
7#include <stdlib.h>
8
9#include "binfmt_misc_common.h"
10#include "kselftest_harness.h"
11
12#define ENTRY "bmdelim"
13/* Shares no character with the sets below, or a refusal proves nothing. */
14#define MAGIC "bmmagic"
15#define INTERP "/bin/true"
16
17/*
18 * ASCII punctuation without '\' and '/'. The backslash is refused because
19 * it would cut a magic that uses \x to escape short. '/' is accepted
20 * but cannot delimit a rule that names an absolute interpreter.
21 */
22#define PUNCTUATION "!\"#$%&'()*+,-.:;<=>?@[]^_`{|}~"
23
24/* 'M', 'E' and 'B' name types, 'P' through 'D' are the flags. */
25#define LETTERS "MEBPOCFTLDqz"
26#define DIGITS "0157"
27#define WHITESPACE " \t\n"
28#define CONTROL "\001\033\177"
29#define NON_ASCII "\200\244\377"
30
31/* ':bmdelim:E::bmmagic::/bin/true:' with @del in place of every ':'. */
32static int register_with(char del)
33{
34 char rule[128];
35
36 snprintf(rule, sizeof(rule), "%c%s%cE%c%c%s%c%c%s%c", del, ENTRY, del,
37 del, del, MAGIC, del, del, INTERP, del);
38 return write_reg(rule);
39}
40
41/* No character of @set may delimit a register string. */
42static void expect_refused(struct __test_metadata *_metadata, const char *set)
43{
44 const char *d;
45
46 for (d = set; *d; d++) {
47 int rc = register_with(*d);
48
49 EXPECT_EQ(rc, -1)
50 TH_LOG("%#x delimited a register string",
51 (unsigned char)*d);
52 if (rc == 0) {
53 unregister(ENTRY);
54 continue;
55 }
56 EXPECT_EQ(errno, EINVAL);
57 }
58}
59
60FIXTURE(delim) {
61};
62
63FIXTURE_SETUP(delim)
64{
65 if (getuid() != 0)
66 SKIP(return, "test must be run as root");
67 if (!binfmt_misc_available())
68 SKIP(return, "no binfmt_misc");
69
70 /* A kernel without the allow-list takes any character but a flag. */
71 if (register_with('q') == 0) {
72 unregister(ENTRY);
73 SKIP(return, "kernel without the delimiter allow-list");
74 }
75}
76
77FIXTURE_TEARDOWN(delim)
78{
79 unregister(ENTRY);
80}
81
82/* Punctuation delimits, which is all anything deployed ever uses. */
83TEST_F(delim, punctuation_accepted)
84{
85 const char *d;
86
87 for (d = PUNCTUATION; *d; d++) {
88 EXPECT_EQ(register_with(*d), 0)
89 TH_LOG("'%c' refused with errno %d", *d, errno);
90 unregister(ENTRY);
91 }
92}
93
94/* Letters name the types and the flags, so none of them can delimit. */
95TEST_F(delim, letters_refused)
96{
97 expect_refused(_metadata, LETTERS);
98}
99
100/* The offset field is written in digits. */
101TEST_F(delim, digits_refused)
102{
103 expect_refused(_metadata, DIGITS);
104}
105
106TEST_F(delim, whitespace_refused)
107{
108 expect_refused(_metadata, WHITESPACE);
109}
110
111TEST_F(delim, control_refused)
112{
113 expect_refused(_metadata, CONTROL);
114}
115
116TEST_F(delim, non_ascii_refused)
117{
118 expect_refused(_metadata, NON_ASCII);
119}
120
121/* The escape character would cut every magic that uses one short. */
122TEST_F(delim, backslash_refused)
123{
124 expect_refused(_metadata, "\\");
125}
126
127TEST_HARNESS_MAIN