Skip to content

Commit 69acf8f

Browse files
authored
[WasmFS] Implement /dev/random and /dev/urandom (#16896)
1 parent 1a7d709 commit 69acf8f

File tree

7 files changed

+74
-3
lines changed

7 files changed

+74
-3
lines changed

system/lib/standalone/standalone.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,13 @@ __attribute__((__weak__)) int __syscall_fcntl64(int fd, int cmd, ...) {
116116
return -ENOSYS;
117117
}
118118

119+
// There is no good source of entropy without an import. Make this weak so that
120+
// it can be replaced with a pRNG or a proper import.
121+
__attribute__((__weak__))
122+
int getentropy(void* buffer, size_t length) {
123+
abort();
124+
}
125+
119126
// Emscripten additions
120127

121128
extern void emscripten_notify_memory_growth(size_t memory_index);

system/lib/wasmfs/special_files.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
// See https://github.com/emscripten-core/emscripten/issues/15041.
88

99
#include <emscripten/html5.h>
10+
#include <unistd.h>
1011
#include <vector>
1112
#include <wasi/api.h>
1213

@@ -113,6 +114,31 @@ class StderrFile : public WritingStdFile {
113114
StderrFile() {}
114115
};
115116

117+
class RandomFile : public DataFile {
118+
void open(oflags_t) override {}
119+
void close() override {}
120+
121+
ssize_t write(const uint8_t* buf, size_t len, off_t offset) override {
122+
return -__WASI_ERRNO_INVAL;
123+
}
124+
125+
ssize_t read(uint8_t* buf, size_t len, off_t offset) override {
126+
uint8_t* end = buf + len;
127+
for (; buf < end; buf += 256) {
128+
int err = getentropy(buf, std::min(end - buf, 256l));
129+
assert(err == 0);
130+
}
131+
return len;
132+
};
133+
134+
void flush() override {}
135+
size_t getSize() override { return 0; }
136+
void setSize(size_t size) override {}
137+
138+
public:
139+
RandomFile() : DataFile(S_IRUGO, NullBackend, S_IFCHR) { seekable = false; }
140+
};
141+
116142
} // anonymous namespace
117143

118144
std::shared_ptr<DataFile> getStdin() {
@@ -130,4 +156,14 @@ std::shared_ptr<DataFile> getStderr() {
130156
return stderr;
131157
}
132158

159+
std::shared_ptr<DataFile> getRandom() {
160+
static auto random = std::make_shared<RandomFile>();
161+
return random;
162+
}
163+
164+
std::shared_ptr<DataFile> getURandom() {
165+
static auto urandom = std::make_shared<RandomFile>();
166+
return urandom;
167+
}
168+
133169
} // namespace wasmfs::SpecialFiles

system/lib/wasmfs/special_files.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,10 @@ std::shared_ptr<DataFile> getStdout();
1818
// /dev/stderr
1919
std::shared_ptr<DataFile> getStderr();
2020

21+
// /dev/random
22+
std::shared_ptr<DataFile> getRandom();
23+
24+
// /dev/urandom
25+
std::shared_ptr<DataFile> getURandom();
26+
2127
} // namespace wasmfs::SpecialFiles

system/lib/wasmfs/wasmfs.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ std::shared_ptr<Directory> WasmFS::initRootDirectory() {
7474
lockedDev.mountChild("stdin", SpecialFiles::getStdin());
7575
lockedDev.mountChild("stdout", SpecialFiles::getStdout());
7676
lockedDev.mountChild("stderr", SpecialFiles::getStderr());
77+
lockedDev.mountChild("random", SpecialFiles::getRandom());
78+
lockedDev.mountChild("urandom", SpecialFiles::getURandom());
7779

7880
return rootDirectory;
7981
}

tests/filesystem/dev_random.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,24 @@
33
// University of Illinois/NCSA Open Source License. Both these licenses can be
44
// found in the LICENSE file.
55

6+
#include <assert.h>
67
#include <stdio.h>
8+
79
int main() {
8-
int byte_count = 64;
9-
char data[64];
10+
int byte_count = 500;
11+
char data[500];
1012
FILE *fp;
13+
int nread;
14+
1115
fp = fopen("/dev/random", "r");
12-
fread(&data, 1, byte_count, fp);
16+
nread = fread(&data, 1, byte_count, fp);
17+
assert(nread == byte_count);
1318
fclose(fp);
19+
20+
fp = fopen("/dev/urandom", "r");
21+
nread = fread(&data, 1, byte_count, fp);
22+
assert(nread == byte_count);
23+
fclose(fp);
24+
1425
return 0;
1526
}

tests/test_browser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,7 @@ def test():
702702
# create_file('shell.html', read_file(path_from_root('src/shell.html')).replace('var Module = {', 'var Module = { locateFile: function (path) {return "http:/localhost:8888/cdn/" + path;}, '))
703703
# test()
704704

705+
@also_with_wasmfs
705706
def test_dev_random(self):
706707
self.btest_exit(Path('filesystem/dev_random.cpp'))
707708

tests/wasmfs/wasmfs_getdents.out

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ d.d_name = ..
2424
d.d_reclen = 280
2525
d.d_type = directory
2626

27+
d.d_name = random
28+
d.d_reclen = 280
29+
d.d_type = regular
30+
2731
d.d_name = stderr
2832
d.d_reclen = 280
2933
d.d_type = regular
@@ -36,6 +40,10 @@ d.d_name = stdout
3640
d.d_reclen = 280
3741
d.d_type = regular
3842

43+
d.d_name = urandom
44+
d.d_reclen = 280
45+
d.d_type = regular
46+
3947
/root/working file position is: 1
4048
------------- Reading one from /root/working Directory -------------
4149
d.d_name = ..

0 commit comments

Comments
 (0)