Skip to content

Commit d9552ad

Browse files
committed
init: Define specific initramfs for nitro enclaves
Signed-off-by: Tyler Fanelli <tfanelli@redhat.com>
1 parent bea9fef commit d9552ad

1 file changed

Lines changed: 222 additions & 0 deletions

File tree

init/nitro.c

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#include <errno.h>
4+
#include <signal.h>
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
#include <unistd.h>
8+
#include <sys/mount.h>
9+
#include <sys/reboot.h>
10+
#include <sys/socket.h>
11+
#include <sys/syscall.h>
12+
#include <linux/vm_sockets.h>
13+
14+
#define finit_module(fd, param_values, flags) (int)syscall(__NR_finit_module, fd, param_values, flags)
15+
16+
#define HEART_BEAT 0xb7
17+
#define VSOCK_CID 3
18+
#define VSOCK_PORT 9000
19+
20+
/*
21+
* Block or unblock signals.
22+
*
23+
* NOTE: All signals are blocked before the devies or console are set up.
24+
* Therefore, perror output may not be displayed if a failure occurs
25+
* during this setup.
26+
*/
27+
int
28+
sig_mask(int mask)
29+
{
30+
sigset_t set;
31+
int ret;
32+
33+
// Initialize the signal set to the complete set of supported signals.
34+
ret = sigfillset(&set);
35+
if (ret < 0) {
36+
perror("sigfillset");
37+
return ret;
38+
}
39+
40+
// Block/unblock the signals. This essentially blocks/unblocks all signals
41+
// to the process.
42+
ret = sigprocmask(mask, &set, 0);
43+
if (ret < 0) {
44+
perror("sigprocmask");
45+
return ret;
46+
}
47+
48+
return 0;
49+
}
50+
51+
/*
52+
* Initialize a devtpmfs at /dev.
53+
*/
54+
int
55+
dev_init()
56+
{
57+
int ret;
58+
59+
ret = mount("dev", "/dev", "devtpmfs", MS_NOSUID | MS_NOEXEC, NULL);
60+
if (ret < 0) {
61+
perror("mount");
62+
return ret;
63+
}
64+
65+
return 0;
66+
}
67+
68+
/*
69+
* Initialize /dev/console and redirect std{err, in, out} to it for early debug
70+
* output.
71+
*/
72+
int
73+
console_init()
74+
{
75+
const char *path = "/dev/console";
76+
FILE *file;
77+
int ret;
78+
79+
// Initialize /dev.
80+
ret = dev_init();
81+
if (ret < 0)
82+
return ret;
83+
84+
// Redirect stdin, stdout, and stderr to /dev/console.
85+
file = freopen(path, "r", stdin);
86+
if (file == NULL)
87+
return -1;
88+
89+
file = freopen(path, "w", stdout);
90+
if (file == NULL)
91+
return -1;
92+
93+
file = freopen(path, "w", stderr);
94+
if (file == NULL)
95+
return -1;
96+
97+
return 0;
98+
}
99+
100+
/*
101+
* Initialize/load the NSM kernel module.
102+
*/
103+
int
104+
nsm_init()
105+
{
106+
const char *file_name = "nsm.ko";
107+
int fd, ret;
108+
109+
fd = open(file_name, O_RDONLY | O_CLOEXEC);
110+
if (fd < 0 && errno == ENOENT)
111+
return 0;
112+
else if (fd < 0) {
113+
perror("nsm.ko open");
114+
return -errno;
115+
}
116+
117+
// Load the NSM module.
118+
ret = finit_module(fd, "", 0);
119+
if (ret < 0) {
120+
perror("nsm.ko finit_module");
121+
return -errno;
122+
}
123+
124+
// Close the file descriptor and remove the NSM module file.
125+
ret = close(fd);
126+
if (ret < 0) {
127+
perror("nsm.ko close");
128+
return -errno;
129+
}
130+
131+
ret = unlink(file_name);
132+
if (ret < 0) {
133+
perror("nsm.ko unlink");
134+
return -errno;
135+
}
136+
137+
return 0;
138+
}
139+
140+
/*
141+
* Signal to libkrun that the enclave is ready to receive the archived rootfs.
142+
*/
143+
int
144+
krun_signal()
145+
{
146+
uint8_t buf[1];
147+
struct sockaddr_vm saddr;
148+
int ret, sock_fd;
149+
150+
buf[1] = HEART_BEAT;
151+
errno = -EINVAL;
152+
153+
saddr.svm_family = AF_VSOCK;
154+
saddr.svm_cid = VSOCK_CID;
155+
saddr.svm_port = VSOCK_PORT;
156+
saddr.svm_reserved1 = 0;
157+
158+
sock_fd = socket(AF_VSOCK, SOCK_STREAM, 0);
159+
if (sock_fd < 0) {
160+
perror("vsock initialization");
161+
return -errno;
162+
}
163+
164+
ret = connect(sock_fd, (struct sockaddr *) &saddr, sizeof(saddr));
165+
if (ret < 0) {
166+
perror("vsock connect");
167+
return -errno;
168+
}
169+
170+
ret = write(sock_fd, buf, 1);
171+
if (ret != 1) {
172+
perror("vsock write");
173+
return -errno;
174+
}
175+
176+
ret = read(sock_fd, buf, 1);
177+
if (ret != 1) {
178+
perror("vsock read");
179+
return -errno;
180+
}
181+
182+
if (buf[0] != HEART_BEAT)
183+
return -1;
184+
185+
ret = close(sock_fd);
186+
if (ret < 0) {
187+
perror("vsock close");
188+
return -errno;
189+
}
190+
191+
return 0;
192+
}
193+
194+
int
195+
main(int argc, char *argv[])
196+
{
197+
int ret;
198+
199+
// Block all signals.
200+
ret = sig_mask(SIG_BLOCK);
201+
if (ret < 0)
202+
exit(ret);
203+
204+
// Initialize early debug output with /dev/console.
205+
ret = console_init();
206+
if (ret < 0)
207+
exit(ret);
208+
209+
// Initialize the NSM kernel module.
210+
ret = nsm_init();
211+
if (ret < 0)
212+
exit(ret);
213+
214+
ret = krun_signal();
215+
if (ret < 0)
216+
exit(ret);
217+
218+
reboot(RB_AUTOBOOT);
219+
220+
// Unreachable.
221+
return -1;
222+
}

0 commit comments

Comments
 (0)