9#include <sys/utsname.h>
11_Static_assert(
sizeof(
struct utsname) == 390,
"Linux utsname ABI");
13static int setter_contract(
int domain) {
15 int (*
setter)(
const char*, size_t) = domain ? setdomainname : sethostname;
16 unsigned char expected[65] = {0};
18 memset(full, domain ?
'd' :
'h', sizeof(full));
20 mmap(NULL, ns_page * 2, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
22 CHECK(mapping != MAP_FAILED);
23 CHECK(mprotect((
char*)mapping + ns_page, ns_page, PROT_NONE) == 0);
24 CHECK(
setter(full, 64) == 0);
25 CHECK(uname(&value) == 0);
26 memcpy(expected, full, 64);
27 CHECK(!memcmp(domain ? value.domainname : value.nodename, expected, 65));
29 CHECK(
setter(full, 65) == -1 && errno == EINVAL);
31 CHECK(
setter(full, SIZE_MAX) == -1 && errno == EINVAL);
32 char* edge = (
char*)mapping + ns_page - 2;
36 CHECK(
setter(edge, 4) == -1 && errno == EFAULT);
37 CHECK(uname(&value) == 0);
38 CHECK(!memcmp(domain ? value.domainname : value.nodename, expected, 65));
40 const unsigned char binary[] = {
'a', 0,
'b', 0xff};
41 memset(expected, 0,
sizeof(expected));
42 memcpy(expected, binary,
sizeof(binary));
43 CHECK(
setter((
const char*)binary,
sizeof(binary)) == 0);
44 CHECK(uname(&value) == 0);
45 CHECK(!memcmp(domain ? value.domainname : value.nodename, expected, 65));
47 CHECK(
setter(NULL, (
size_t)UINT64_C(0x100000000)) == 0);
48 CHECK(
setter(full, (
size_t)UINT64_C(0x100000002)) == 0);
49 memset(expected, 0,
sizeof(expected));
50 memcpy(expected, full, 2);
51 CHECK(uname(&value) == 0);
52 CHECK(!memcmp(domain ? value.domainname : value.nodename, expected, 65));
53 CHECK(
setter(NULL, 0) == 0);
54 memset(expected, 0,
sizeof(expected));
55 CHECK(uname(&value) == 0);
56 CHECK(!memcmp(domain ? value.domainname : value.nodename, expected, 65));
58 if (mapping != MAP_FAILED)
59 munmap(mapping, ns_page * 2);
64 pthread_barrier_t start;
65 char first[64], second[64];
68static void* replace_names(
void* argument) {
70 pthread_barrier_wait(&state->start);
71 for (
int i = 0; i < 128; ++i) {
72 if (sethostname(i & 1 ? state->first : state->second, 64)) {
80static int snapshots(
void) {
81 int failed = 0, initialized = 0, started = 0;
84 memset(state.first,
'a',
sizeof(state.first));
85 memset(state.second,
'b',
sizeof(state.second));
86 CHECK(ns_set(
"snapshot",
"fixed-domain") == 0);
87 CHECK(sethostname(state.first, 64) == 0);
88 CHECK(pthread_barrier_init(&state.start, NULL, 2) == 0);
90 CHECK(pthread_create(&
worker, NULL, replace_names, &state) == 0);
92 pthread_barrier_wait(&state.start);
93 for (
int i = 0; i < 128; ++i) {
95 CHECK(uname(&value) == 0);
96 CHECK((!memcmp(value.nodename, state.first, 64) || !memcmp(value.nodename, state.second, 64)) &&
97 value.nodename[64] == 0);
98 CHECK(!strcmp(value.domainname,
"fixed-domain"));
101 if (started && (pthread_join(
worker, NULL) || state.result))
104 pthread_barrier_destroy(&state.start);
110 struct utsname before, after;
111 unsigned char output[
sizeof(
struct utsname) + 2];
112 void* readonly = MAP_FAILED;
114 CHECK(uname(&before) == 0);
115 CHECK(ns_path_identity(
"/proc/thread-self/ns/uts", &first) == 0);
116 CHECK(unshare(0) == 0);
117 CHECK(ns_path_identity(
"/proc/thread-self/ns/uts", &second) == 0 && ns_same(first, second));
118 CHECK(setter_contract(0) == 0 && setter_contract(1) == 0);
119 CHECK(ns_set(
"alpha",
"domain") == 0);
120 char host[3] = {
'?',
'?',
'?'}, domain[7] = {0};
121 CHECK(gethostname(host, 2) == 0 && host[0] ==
'a' && host[1] == 0 && host[2] ==
'?');
122 CHECK(gethostname(host + 2, 0) == 0 && host[2] ==
'?');
124 CHECK(getdomainname(domain, 6) == -1 && errno == EINVAL);
126 CHECK(getdomainname(domain, 0) == -1 && errno == EINVAL);
127 CHECK(getdomainname(domain,
sizeof(domain)) == 0 && !strcmp(domain,
"domain"));
128 memset(output, 0xcc,
sizeof(output));
129 CHECK(uname((
struct utsname*)(output + 1)) == 0);
130 CHECK(output[0] == 0xcc && output[
sizeof(output) - 1] == 0xcc);
131 memcpy(&after, output + 1,
sizeof(after));
132 CHECK(!memcmp(before.sysname, after.sysname, 65) && !memcmp(before.release, after.release, 65) &&
133 !memcmp(before.version, after.version, 65) && !memcmp(before.machine, after.machine, 65));
134 CHECK(ns_expect(
"alpha",
"domain") == 0);
135 readonly = mmap(NULL, ns_page, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
136 CHECK(readonly != MAP_FAILED);
138 CHECK(uname(readonly) == -1 && errno == EFAULT);
139 CHECK(ns_expect(
"alpha",
"domain") == 0);
140 CHECK(snapshots() == 0);
142 if (readonly != MAP_FAILED)
143 munmap(readonly, ns_page);