Skip to content

Commit 3f20c45

Browse files
committed
nitro: Write rootfs tar archive to enclave
1 parent 2287faf commit 3f20c45

5 files changed

Lines changed: 236 additions & 9 deletions

File tree

init/nitro/main.c

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
#include <errno.h>
55
#include <fcntl.h>
66
#include <signal.h>
7+
#include <stddef.h>
78
#include <stdint.h>
89
#include <stdio.h>
910
#include <stdlib.h>
11+
#include <string.h>
1012
#include <unistd.h>
1113
#include <sys/mount.h>
1214
#include <sys/reboot.h>
@@ -16,6 +18,8 @@
1618
#include <sys/syscall.h>
1719
#include <linux/vm_sockets.h>
1820

21+
#include "rootfs_archive.h"
22+
1923
#define finit_module(fd, param_values, flags) (int)syscall(__NR_finit_module, fd, param_values, flags)
2024

2125
#define HEART_BEAT 0xb7
@@ -177,32 +181,74 @@ krun_signal()
177181
// communication is established.
178182
ret = write(sock_fd, buf, 1);
179183
if (ret != 1) {
184+
close(sock_fd);
180185
perror("vsock write");
181186
return -errno;
182187
}
183188

184189
ret = read(sock_fd, buf, 1);
185190
if (ret != 1) {
191+
close(sock_fd);
186192
perror("vsock read");
187193
return -errno;
188194
}
189195

190-
if (buf[0] != HEART_BEAT)
196+
if (buf[0] != HEART_BEAT) {
197+
close(sock_fd);
191198
return -1;
199+
}
192200

193-
ret = close(sock_fd);
194-
if (ret < 0) {
195-
perror("vsock close");
196-
return -errno;
201+
return sock_fd;
202+
}
203+
204+
int
205+
rootfs_rcv(int sock_fd, void **buf_ptr, size_t *size)
206+
{
207+
uint8_t len_b[8], *rootfs_archive;
208+
ssize_t read_len;
209+
uint64_t len, idx = 0;
210+
211+
read_len = read(sock_fd, len_b, 8);
212+
if (read_len < 8) {
213+
close(sock_fd);
214+
perror("vsock rootfs archive length read");
215+
return -1;
197216
}
198217

218+
memcpy(&len, len_b, sizeof(uint64_t));
219+
220+
*size = len;
221+
222+
rootfs_archive = (uint8_t *) malloc(len);
223+
if (rootfs_archive == NULL) {
224+
close(sock_fd);
225+
perror("rootfs archive malloc");
226+
return -1;
227+
}
228+
229+
while (len) {
230+
read_len = read(sock_fd, &rootfs_archive[idx], len);
231+
if (read_len <= 0) {
232+
close(sock_fd);
233+
free((void *) rootfs_archive);
234+
perror("vsock rootfs archive read");
235+
return -1;
236+
}
237+
idx += read_len;
238+
len -= read_len;
239+
}
240+
241+
*buf_ptr = (void *) rootfs_archive;
242+
199243
return 0;
200244
}
201245

202246
int
203247
main(int argc, char *argv[])
204248
{
205-
int ret;
249+
void *rootfs_archive;
250+
size_t archive_size;
251+
int ret, sock_fd;
206252

207253
// Block all signals.
208254
ret = sig_mask(SIG_BLOCK);
@@ -219,7 +265,11 @@ main(int argc, char *argv[])
219265
if (ret < 0)
220266
exit(ret);
221267

222-
ret = krun_signal();
268+
sock_fd = krun_signal();
269+
if (sock_fd < 0)
270+
exit(ret);
271+
272+
ret = rootfs_rcv(sock_fd, &rootfs_archive, &archive_size);
223273
if (ret < 0)
224274
exit(ret);
225275

init/nitro/rootfs_archive.c

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#include <stddef.h>
4+
#include <stdlib.h>
5+
6+
#include <archive.h>
7+
#include <archive_entry.h>
8+
9+
#include "rootfs_archive.h"
10+
11+
static
12+
struct archive *
13+
reader_init(void *buf, size_t size)
14+
{
15+
struct archive *r;
16+
int ret;
17+
18+
r = archive_read_new();
19+
if (r == NULL) {
20+
printf("init reader failed\n");
21+
return NULL;
22+
}
23+
24+
ret = archive_read_support_format_tar(r);
25+
if (ret != ARCHIVE_OK) {
26+
printf("reader cannot support tar format\n");
27+
return NULL;
28+
}
29+
30+
ret = archive_read_open_memory(r, buf, size);
31+
if (ret != ARCHIVE_OK) {
32+
printf("reader cannot open file\ncause: %s\n", archive_error_string(r));
33+
return NULL;
34+
}
35+
36+
return r;
37+
}
38+
39+
static
40+
struct archive *
41+
writer_init()
42+
{
43+
struct archive *w;
44+
int ret;
45+
46+
w = archive_write_disk_new();
47+
if (w == NULL) {
48+
printf("init writer failed\n");
49+
return NULL;
50+
}
51+
52+
ret = archive_write_disk_set_options(w, ARCHIVE_EXTRACT_TIME);
53+
if (ret < 0) {
54+
printf("error setting writer disk options\n");
55+
return NULL;
56+
}
57+
58+
return w;
59+
}
60+
61+
static
62+
int
63+
unzip(struct archive *r, struct archive *w)
64+
{
65+
struct archive_entry *entry;
66+
const void *buf;
67+
int64_t offset;
68+
size_t size;
69+
int ret;
70+
71+
while ((ret = archive_read_next_header(r, &entry)) != ARCHIVE_EOF) {
72+
if (ret != ARCHIVE_OK) {
73+
printf("error reading archive entry\ncause: %s\n", archive_error_string(r));
74+
return -1;
75+
}
76+
77+
ret = archive_write_header(w, entry);
78+
if (ret != ARCHIVE_OK) {
79+
printf("error writing %s entry\ncause: %s\n", archive_entry_pathname(entry), archive_error_string(w));
80+
return -1;
81+
}
82+
83+
while ((ret = archive_read_data_block(r, &buf, &size, &offset)) != ARCHIVE_EOF) {
84+
if (ret != ARCHIVE_OK) {
85+
printf("error reading archive data block\ncause: %s\n", archive_error_string(r));
86+
return -1;
87+
}
88+
89+
ret = archive_write_data_block(w, buf, size, offset);
90+
if (ret != ARCHIVE_OK) {
91+
printf("error writing archive data block\ncause: %s\n", archive_error_string(w));
92+
return -1;
93+
}
94+
}
95+
96+
ret = archive_write_finish_entry(w);
97+
if (ret != ARCHIVE_OK) {
98+
printf("error finishing %s entry\ncause: %s\n", archive_entry_pathname(entry), archive_error_string(w));
99+
return -1;
100+
}
101+
}
102+
103+
return 0;
104+
}
105+
106+
static
107+
void
108+
archive_cleanup(struct archive *r, struct archive *w)
109+
{
110+
archive_read_close(r);
111+
archive_read_free(r);
112+
113+
archive_write_close(w);
114+
archive_write_free(w);
115+
}
116+
117+
int
118+
archive_unzip(void *buf, size_t size)
119+
{
120+
struct archive *reader, *writer;
121+
int ret;
122+
123+
reader = reader_init(buf, size);
124+
if (reader == NULL)
125+
return -1;
126+
127+
writer = writer_init();
128+
if (writer == NULL)
129+
return -1;
130+
131+
ret = unzip(reader, writer);
132+
if (ret < 0)
133+
return -1;
134+
135+
archive_cleanup(reader, writer);
136+
137+
return 0;
138+
}

init/nitro/rootfs_archive.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#ifndef _ROOTFS_ARCHIVE_H
4+
#define _ROOTFS_ARCHIVE_H
5+
6+
#include <stddef.h>
7+
8+
int archive_unzip(void *, size_t);
9+
10+
#endif // _ROOTFS_ARCHIVE_H

src/nitro/src/enclaves.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ pub struct NitroEnclave {
4040
impl NitroEnclave {
4141
/// Run the enclave.
4242
pub fn run(&mut self) -> Result<u32> {
43-
let _rootfs_archive = self.rootfs_archive()?;
43+
let rootfs_archive = self.rootfs_archive()?;
4444

45-
let (cid, _stream) = self.start()?;
45+
let (cid, stream) = self.start()?;
46+
47+
self.write_rootfs(rootfs_archive, stream)?;
4648

4749
Ok(cid)
4850
}
@@ -124,4 +126,21 @@ impl NitroEnclave {
124126

125127
Ok((cid, stream.0))
126128
}
129+
130+
fn write_rootfs(&self, archive: Vec<u8>, mut stream: VsockStream) -> Result<()> {
131+
let len: u64 = archive
132+
.len()
133+
.try_into()
134+
.or(Err(NitroError::RootFsTooLarge))?;
135+
136+
stream
137+
.write_all(&len.to_ne_bytes())
138+
.map_err(NitroError::RootFsLenWrite)?;
139+
140+
stream
141+
.write_all(&archive)
142+
.map_err(NitroError::RootFsWrite)?;
143+
144+
Ok(())
145+
}
127146
}

src/nitro/src/error.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ pub enum NitroError {
2323
VsockSetTimeout,
2424
VsockConnect,
2525
IpcWrite(io::Error),
26+
RootFsLenWrite(io::Error),
27+
RootFsWrite(io::Error),
28+
RootFsTooLarge,
2629
}
2730

2831
impl fmt::Display for NitroError {
@@ -64,6 +67,13 @@ impl fmt::Display for NitroError {
6467
NitroError::IpcWrite(e) => {
6568
format!("unable to write enclave vsock data to UNIX IPC socket: {e}")
6669
}
70+
NitroError::RootFsLenWrite(e) => {
71+
format!("unable to write rootfs archive length to enclave: {e}")
72+
}
73+
NitroError::RootFsWrite(e) => {
74+
format!("unable to write rootfs archive to enclave: {e}")
75+
}
76+
NitroError::RootFsTooLarge => "rootfs size is larger than 64 bytes".to_string(),
6777
};
6878

6979
write!(f, "{}", msg)

0 commit comments

Comments
 (0)