From 19f8e650789e23dfd0c6c20315a6f2c1da333c4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Borys=20Pop=C5=82awski?= Date: Thu, 9 Jun 2022 17:08:01 +0200 Subject: [PATCH] [LibOS] Add `O_PATH` support to `open` syscall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Borys Popławski --- LibOS/shim/include/shim_fs.h | 13 +-- LibOS/shim/include/shim_handle.h | 1 + LibOS/shim/src/bookkeep/shim_handle.c | 3 - LibOS/shim/src/fs/chroot/encrypted.c | 8 +- LibOS/shim/src/fs/shim_fs.c | 1 + LibOS/shim/src/fs/shim_fs_path.c | 25 ++++++ LibOS/shim/src/fs/shim_namei.c | 63 +++++++++------ LibOS/shim/src/meson.build | 1 + LibOS/shim/src/sys/shim_open.c | 9 ++- LibOS/shim/test/ltp/ltp.cfg | 8 +- LibOS/shim/test/regression/common.h | 22 +++++- LibOS/shim/test/regression/epoll_test.c | 10 +-- LibOS/shim/test/regression/groups.c | 4 +- LibOS/shim/test/regression/meson.build | 1 + LibOS/shim/test/regression/open_opath.c | 79 +++++++++++++++++++ .../test/regression/sigprocmask_pending.c | 31 +++----- LibOS/shim/test/regression/test_libos.py | 9 +++ LibOS/shim/test/regression/tests.toml | 1 + LibOS/shim/test/regression/tests_musl.toml | 1 + 19 files changed, 213 insertions(+), 77 deletions(-) create mode 100644 LibOS/shim/src/fs/shim_fs_path.c create mode 100644 LibOS/shim/test/regression/open_opath.c diff --git a/LibOS/shim/include/shim_fs.h b/LibOS/shim/include/shim_fs.h index 3042aa8fd5..8d1ef76217 100644 --- a/LibOS/shim/include/shim_fs.h +++ b/LibOS/shim/include/shim_fs.h @@ -152,10 +152,6 @@ struct shim_fs_ops { /* seek: the content from the file opened as handle */ file_off_t (*seek)(struct shim_handle* hdl, file_off_t offset, int whence); - /* move, copy: rename or duplicate the file */ - int (*move)(const char* trim_old_name, const char* trim_new_name); - int (*copy)(const char* trim_old_name, const char* trim_new_name); - /* Returns 0 on success, -errno on error */ int (*truncate)(struct shim_handle* hdl, file_off_t len); @@ -165,14 +161,6 @@ struct shim_fs_ops { /* setflags: set flags of the file */ int (*setflags)(struct shim_handle* hdl, int flags); - /* - * \brief Deallocate handle data. - * - * Deallocates any filesystem-specific resources associated with the handle. Called just before - * destroying the handle. - */ - void (*hdrop)(struct shim_handle* hdl); - /* lock and unlock the file */ int (*lock)(const char* trim_name); int (*unlock)(const char* trim_name); @@ -925,6 +913,7 @@ extern struct shim_fs socket_builtin_fs; extern struct shim_fs epoll_builtin_fs; extern struct shim_fs eventfd_builtin_fs; extern struct shim_fs synthetic_builtin_fs; +extern struct shim_fs path_builtin_fs; struct shim_fs* find_fs(const char* name); diff --git a/LibOS/shim/include/shim_handle.h b/LibOS/shim/include/shim_handle.h index 87008513fa..c4cb49ba46 100644 --- a/LibOS/shim/include/shim_handle.h +++ b/LibOS/shim/include/shim_handle.h @@ -37,6 +37,7 @@ enum shim_handle_type { TYPE_PSEUDO, /* pseudo nodes (currently directories), handled by `pseudo_*` functions */ TYPE_TMPFS, /* string-based files (with data inside dentry), used by `tmpfs` filesystem */ TYPE_SYNTHETIC, /* synthetic files, used by `synthetic` filesystem */ + TYPE_PATH, /* path to a file (the file is not actually opened) */ /* Pipes and sockets: */ TYPE_PIPE, /* pipes, used by `pipe` filesystem */ diff --git a/LibOS/shim/src/bookkeep/shim_handle.c b/LibOS/shim/src/bookkeep/shim_handle.c index 13ccf20e1d..7701ec7fb8 100644 --- a/LibOS/shim/src/bookkeep/shim_handle.c +++ b/LibOS/shim/src/bookkeep/shim_handle.c @@ -498,9 +498,6 @@ void put_handle(struct shim_handle* hdl) { if (hdl->fs && hdl->fs->fs_ops && hdl->fs->fs_ops->close) hdl->fs->fs_ops->close(hdl); - if (hdl->fs && hdl->fs->fs_ops && hdl->fs->fs_ops->hdrop) - hdl->fs->fs_ops->hdrop(hdl); - free(hdl->uri); if (hdl->pal_handle) { diff --git a/LibOS/shim/src/fs/chroot/encrypted.c b/LibOS/shim/src/fs/chroot/encrypted.c index bd33b0c51e..7deb4b8091 100644 --- a/LibOS/shim/src/fs/chroot/encrypted.c +++ b/LibOS/shim/src/fs/chroot/encrypted.c @@ -384,16 +384,18 @@ static int chroot_encrypted_flush(struct shim_handle* hdl) { return ret; } -static void chroot_encrypted_hdrop(struct shim_handle* hdl) { +static int chroot_encrypted_close(struct shim_handle* hdl) { assert(hdl->type == TYPE_CHROOT_ENCRYPTED); if (hdl->inode->type != S_IFREG) - return; + return 0; struct shim_encrypted_file* enc = hdl->inode->data; lock(&hdl->inode->lock); encrypted_file_put(enc); unlock(&hdl->inode->lock); + + return 0; } static ssize_t chroot_encrypted_read(struct shim_handle* hdl, void* buf, size_t count, @@ -473,7 +475,7 @@ struct shim_fs_ops chroot_encrypted_fs_ops = { .hstat = &generic_inode_hstat, .truncate = &chroot_encrypted_truncate, .poll = &generic_inode_poll, - .hdrop = &chroot_encrypted_hdrop, + .close = &chroot_encrypted_close, .checkpoint = &chroot_encrypted_checkpoint, .migrate = &chroot_encrypted_migrate, .mmap = &generic_emulated_mmap, diff --git a/LibOS/shim/src/fs/shim_fs.c b/LibOS/shim/src/fs/shim_fs.c index d295c3518c..ffc67345b3 100644 --- a/LibOS/shim/src/fs/shim_fs.c +++ b/LibOS/shim/src/fs/shim_fs.c @@ -30,6 +30,7 @@ struct shim_fs* builtin_fs[] = { &eventfd_builtin_fs, &pseudo_builtin_fs, &synthetic_builtin_fs, + &path_builtin_fs, }; static struct shim_lock mount_mgr_lock; diff --git a/LibOS/shim/src/fs/shim_fs_path.c b/LibOS/shim/src/fs/shim_fs_path.c new file mode 100644 index 0000000000..5eb5d4d919 --- /dev/null +++ b/LibOS/shim/src/fs/shim_fs_path.c @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* Copyright (C) 2022 Intel Corporation + * Borys Popławski + */ + +#include "shim_fs.h" + +static int hstat(struct shim_handle* handle, struct stat* buf) { + if (!handle->inode) { + return -EINVAL; + } + return generic_inode_hstat(handle, buf); +} + +static struct shim_fs_ops path_fs_ops = { + .hstat = hstat, +}; + +static struct shim_d_ops path_d_ops = {}; + +struct shim_fs path_builtin_fs = { + .name = "path", + .fs_ops = &path_fs_ops, + .d_ops = &path_d_ops, +}; diff --git a/LibOS/shim/src/fs/shim_namei.c b/LibOS/shim/src/fs/shim_namei.c index 6c7f3a44bb..3da9c59d73 100644 --- a/LibOS/shim/src/fs/shim_namei.c +++ b/LibOS/shim/src/fs/shim_namei.c @@ -445,13 +445,31 @@ int open_namei(struct shim_handle* hdl, struct shim_dentry* start, const char* p ret = path_lookupat(start, path, lookup_flags, &dent); if (ret < 0) - goto err; + goto out; + + if (flags & O_PATH) { + if (!dent->inode) { + ret = -ENOENT; + goto out; + } + + assoc_handle_with_dentry(hdl, dent, flags); + if (dent->inode->type == S_IFDIR) { + hdl->is_dir = true; + hdl->dir_info.dents = NULL; + } + + hdl->type = TYPE_PATH; + hdl->fs = &path_builtin_fs; + ret = 0; + goto out; + } if (dent->inode && dent->inode->type == S_IFDIR) { if (flags & O_WRONLY || flags & O_RDWR || ((flags & O_CREAT) && !(flags & O_DIRECTORY) && !(flags & O_EXCL))) { ret = -EISDIR; - goto err; + goto out; } } @@ -459,18 +477,16 @@ int open_namei(struct shim_handle* hdl, struct shim_dentry* start, const char* p /* * Can happen if user specified O_NOFOLLOW, or O_TRUNC | O_EXCL. Posix requires us to fail * with -ELOOP when trying to open a symlink. - * - * (Linux allows opening a symlink with O_PATH, but Gramine does not support it yet). */ ret = -ELOOP; - goto err; + goto out; } bool need_open = true; if (!dent->inode) { if (!(flags & O_CREAT)) { ret = -ENOENT; - goto err; + goto out; } /* Check the parent permission first */ @@ -478,7 +494,7 @@ int open_namei(struct shim_handle* hdl, struct shim_dentry* start, const char* p if (dir) { ret = check_permissions(dir, MAY_WRITE | MAY_EXEC); if (ret < 0) - goto err; + goto out; } struct shim_fs* fs = dent->mount->fs; @@ -487,19 +503,19 @@ int open_namei(struct shim_handle* hdl, struct shim_dentry* start, const char* p if (flags & O_DIRECTORY) { if (!fs->d_ops->mkdir) { ret = -EINVAL; - goto err; + goto out; } ret = fs->d_ops->mkdir(dent, mode & ~S_IFMT); if (ret < 0) - goto err; + goto out; } else { if (!fs->d_ops->creat) { ret = -EINVAL; - goto err; + goto out; } ret = fs->d_ops->creat(hdl, dent, flags, mode & ~S_IFMT); if (ret < 0) - goto err; + goto out; assoc_handle_with_dentry(hdl, dent, flags); need_open = false; } @@ -507,37 +523,38 @@ int open_namei(struct shim_handle* hdl, struct shim_dentry* start, const char* p /* The file exists. This is not permitted if both O_CREAT and O_EXCL are set. */ if ((flags & O_CREAT) && (flags & O_EXCL)) { ret = -EEXIST; - goto err; + goto out; } /* Check permissions. Note that we do it only if the file already exists: a newly created * file is allowed to have a mode that's incompatible with `acc_mode`. */ ret = check_permissions(dent, acc_mode); if (ret < 0) - goto err; + goto out; } if (hdl && need_open) { ret = dentry_open(hdl, dent, flags); if (ret < 0) - goto err; + goto out; } + ret = 0; + +out: if (found) { - *found = dent; - } else { - put_dentry(dent); + if (ret == 0) { + assert(dent); + get_dentry(dent); + *found = dent; + } else { + *found = NULL; + } } - unlock(&g_dcache_lock); - return 0; -err: if (dent) put_dentry(dent); - if (found) - *found = NULL; - unlock(&g_dcache_lock); return ret; } diff --git a/LibOS/shim/src/meson.build b/LibOS/shim/src/meson.build index 36eea6e8ed..0d603ace46 100644 --- a/LibOS/shim/src/meson.build +++ b/LibOS/shim/src/meson.build @@ -31,6 +31,7 @@ libos_sources = files( 'fs/shim_fs_hash.c', 'fs/shim_fs_lock.c', 'fs/shim_fs_mem.c', + 'fs/shim_fs_path.c', 'fs/shim_fs_pseudo.c', 'fs/shim_fs_synthetic.c', 'fs/shim_fs_util.c', diff --git a/LibOS/shim/src/sys/shim_open.c b/LibOS/shim/src/sys/shim_open.c index 3c44f93281..ca517dfe87 100644 --- a/LibOS/shim/src/sys/shim_open.c +++ b/LibOS/shim/src/sys/shim_open.c @@ -100,8 +100,15 @@ long shim_do_creat(const char* path, mode_t mode) { } long shim_do_openat(int dfd, const char* filename, int flags, int mode) { + /* Clear invalid flags. */ + flags &= O_ACCMODE | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECT | O_DIRECTORY | O_DSYNC | O_EXCL + | O_LARGEFILE | O_NOATIME | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_PATH | O_SYNC + | O_TMPFILE | O_TRUNC; + + /* TODO: fail explicitly on valid but unsupported flags. */ + if (flags & O_PATH) { - return -EINVAL; + flags &= O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW; } if (!is_user_string_readable(filename)) diff --git a/LibOS/shim/test/ltp/ltp.cfg b/LibOS/shim/test/ltp/ltp.cfg index aefff46e25..68ec895447 100644 --- a/LibOS/shim/test/ltp/ltp.cfg +++ b/LibOS/shim/test/ltp/ltp.cfg @@ -276,15 +276,15 @@ skip = yes [execve05] skip = yes -# copy child +# execveat not implemented [execveat01] skip = yes -# copy child +# execveat not implemented [execveat02] skip = yes -# copy child +# execveat not implemented [execveat03] skip = yes @@ -1294,7 +1294,7 @@ skip = yes [open12] skip = yes -# Requires touch() support +# Requires `utime*` syscall support [open13] skip = yes diff --git a/LibOS/shim/test/regression/common.h b/LibOS/shim/test/regression/common.h index 172fc3ef7f..338a9728e4 100644 --- a/LibOS/shim/test/regression/common.h +++ b/LibOS/shim/test/regression/common.h @@ -1,15 +1,35 @@ /* SPDX-License-Identifier: LGPL-3.0-or-later */ -/* Copyright (C) 2021 Intel Corporation +/* Copyright (C) 2022 Intel Corporation * Paweł Marczewski + * Borys Popławski */ #ifndef COMMON_H_ #define COMMON_H_ +#include +#include + #define OVERFLOWS(type, val) \ ({ \ type __dummy; \ __builtin_add_overflow((val), 0, &__dummy); \ }) +#define CHECK(x) ({ \ + __typeof__(x) _x = (x); \ + if (_x == -1) { \ + err(1, "error at %s (line %d)", #x, __LINE__); \ + } \ + _x; \ +}) + +#define SAME_TYPE(a, b) __builtin_types_compatible_p(__typeof__(a), __typeof__(b)) +#define IS_STATIC_ARRAY(a) (!SAME_TYPE(a, &*(a))) + +#define ARRAY_LEN(arr) ({ \ + static_assert(IS_STATIC_ARRAY(arr), "not a static array"); \ + sizeof(arr) / sizeof(arr[0]); \ +}) + #endif /* COMMON_H_ */ diff --git a/LibOS/shim/test/regression/epoll_test.c b/LibOS/shim/test/regression/epoll_test.c index 84d121170c..642d862524 100644 --- a/LibOS/shim/test/regression/epoll_test.c +++ b/LibOS/shim/test/regression/epoll_test.c @@ -7,19 +7,11 @@ #include #include -#define CHECK(x) ({ \ - __typeof__(x) _x = (x); \ - if (_x == -1) { \ - err(1, "error at line %d", __LINE__); \ - } \ - _x; \ -}) +#include "common.h" #define ERR(msg, args...) \ errx(1, "%d: " msg, __LINE__, ##args) -#define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0])) - static uint64_t wait_event(int epfd, struct epoll_event* possible_events, size_t possible_events_len) { struct epoll_event event = { 0 }; diff --git a/LibOS/shim/test/regression/groups.c b/LibOS/shim/test/regression/groups.c index a96e8e2725..9cb12f5ea1 100644 --- a/LibOS/shim/test/regression/groups.c +++ b/LibOS/shim/test/regression/groups.c @@ -7,7 +7,7 @@ #include #include -#define ARRAY_LEN(x) (sizeof(x) / sizeof(x[0])) +#include "common.h" static gid_t test_groups[] = { 0, 1337, 1337, 0 }; @@ -46,7 +46,7 @@ int main(void) { x = getgroups(ARRAY_LEN(groups), groups); if (x < 0) { err(1, "getgroups"); - } else if (x != ARRAY_LEN(groups)) { + } else if ((size_t)x != ARRAY_LEN(groups)) { errx(1, "getgroups returned invalid length: %d (expected: %zu)", x, ARRAY_LEN(groups)); } diff --git a/LibOS/shim/test/regression/meson.build b/LibOS/shim/test/regression/meson.build index 7c5c911321..be5b9a5678 100644 --- a/LibOS/shim/test/regression/meson.build +++ b/LibOS/shim/test/regression/meson.build @@ -63,6 +63,7 @@ tests = { 'mprotect_file_fork': {}, 'mprotect_prot_growsdown': {}, 'multi_pthread': {}, + 'open_opath': {}, 'openmp': { # NOTE: This will use `libgomp` in GCC and `libomp` in Clang. 'c_args': '-fopenmp', diff --git a/LibOS/shim/test/regression/open_opath.c b/LibOS/shim/test/regression/open_opath.c new file mode 100644 index 0000000000..486f383fbe --- /dev/null +++ b/LibOS/shim/test/regression/open_opath.c @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* Copyright (C) 2022 Intel Corporation + * Borys Popławski + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "rw_file.h" + +static char g_expected_buf[] = "XXXXX"; + +static void check_file_contents(const char* path) { + char buf[sizeof(g_expected_buf) * 2]; + ssize_t got = CHECK(posix_file_read(path, buf, sizeof(buf))); + if (got != sizeof(g_expected_buf)) { + errx(1, "short read from file \"%s\" - got %zd, expected %zu", path, got, + sizeof(g_expected_buf)); + } + if (memcmp(buf, g_expected_buf, sizeof(g_expected_buf))) { + errx(1, "got unexpected data"); + } +} + +static void write_expected_to_file(int dir_fd, const char* path) { + int fd = CHECK(openat(dir_fd, path, O_WRONLY | O_CREAT | O_EXCL, 0777)); + ssize_t got = CHECK(posix_fd_write(fd, g_expected_buf, sizeof(g_expected_buf))); + if (got != sizeof(g_expected_buf)) { + errx(1, "short write from file \"%s\" - got %zd, expected %zu", path, got, + sizeof(g_expected_buf)); + } + CHECK(close(fd)); +} + +int main(void) { + int root_fd = CHECK(open("/", O_PATH)); + int mnt_dir_fd = CHECK(openat(root_fd, "mnt", O_PATH | O_DIRECTORY | O_NOFOLLOW)); + CHECK(close(root_fd)); + + /* Test a file on Gramine built-in tmpfs. */ + write_expected_to_file(mnt_dir_fd, "tmpfs/A"); + check_file_contents("/mnt/tmpfs/A"); + /* File inside built-in tmpfs, no need to remove it. */ + + /* Test a file on the host fs. */ + write_expected_to_file(mnt_dir_fd, "../tmp/B"); + check_file_contents("/tmp/B"); + + CHECK(unlinkat(mnt_dir_fd, "../tmp/B", 0)); + + CHECK(close(mnt_dir_fd)); + + char path[0x100]; + int fd = CHECK(open("/exec_victim", O_PATH | O_CLOEXEC)); + int ret = snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); + if (ret < 0 || (size_t)ret >= sizeof(path)) { + errx(1, "snprintf failed; %d", ret); + } + + pid_t p = CHECK(fork()); + if (p == 0) { + execl(path, "exec_victim", NULL); + err(1, "execl"); + } + + int status = 0; + CHECK(wait(&status)); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + errx(1, "child died with status: %#x", status); + } + + puts("TEST OK"); + return 0; +} diff --git a/LibOS/shim/test/regression/sigprocmask_pending.c b/LibOS/shim/test/regression/sigprocmask_pending.c index 29380b7ebf..60d0838f45 100644 --- a/LibOS/shim/test/regression/sigprocmask_pending.c +++ b/LibOS/shim/test/regression/sigprocmask_pending.c @@ -7,13 +7,7 @@ #include #include -#define CHECK(x) \ - do { \ - if (x) { \ - perror(#x); \ - exit(1); \ - } \ - } while (0) +#include "common.h" static int seen_signal_cnt = 0; @@ -29,14 +23,14 @@ static void ignore_signal(int sig) { sigaddset(&newmask, sig); } - CHECK(sigprocmask(SIG_SETMASK, &newmask, NULL) < 0); + CHECK(sigprocmask(SIG_SETMASK, &newmask, NULL)); } static void set_signal_handler(int sig, void* handler) { struct sigaction act = { .sa_handler = handler, }; - CHECK(sigaction(sig, &act, NULL) < 0); + CHECK(sigaction(sig, &act, NULL)); } static void test_sigprocmask(void) { @@ -47,9 +41,9 @@ static void test_sigprocmask(void) { sigaddset(&newmask, SIGKILL); sigaddset(&newmask, SIGSTOP); - CHECK(sigprocmask(SIG_SETMASK, &newmask, NULL) < 0); + CHECK(sigprocmask(SIG_SETMASK, &newmask, NULL)); - CHECK(sigprocmask(SIG_SETMASK, NULL, &oldmask) < 0); + CHECK(sigprocmask(SIG_SETMASK, NULL, &oldmask)); if (sigismember(&oldmask, SIGKILL) || sigismember(&oldmask, SIGSTOP)) { printf("SIGKILL or SIGSTOP should be ignored, but is not.\n"); @@ -70,8 +64,8 @@ static void test_multiple_pending(void) { set_signal_handler(SIGALRM, signal_handler); - CHECK(kill(getpid(), SIGALRM) < 0); - CHECK(kill(getpid(), SIGALRM) < 0); + CHECK(kill(getpid(), SIGALRM)); + CHECK(kill(getpid(), SIGALRM)); if (__atomic_load_n(&seen_signal_cnt, __ATOMIC_RELAXED) != 0) { printf("Handled a blocked standard signal!\n"); @@ -90,8 +84,8 @@ static void test_multiple_pending(void) { int sig = SIGRTMIN; ignore_signal(sig); - CHECK(kill(getpid(), sig) < 0); - CHECK(kill(getpid(), sig) < 0); + CHECK(kill(getpid(), sig)); + CHECK(kill(getpid(), sig)); set_signal_handler(sig, signal_handler); @@ -113,10 +107,9 @@ static void test_fork(void) { set_signal_handler(SIGALRM, signal_handler); - CHECK(kill(getpid(), SIGALRM) < 0); + CHECK(kill(getpid(), SIGALRM)); - pid_t p = fork(); - CHECK(p < 0); + pid_t p = CHECK(fork()); if (p == 0) { ignore_signal(0); @@ -139,7 +132,7 @@ static void test_execve_start(char* self) { set_signal_handler(SIGALRM, SIG_DFL); - CHECK(kill(getpid(), SIGALRM) < 0); + CHECK(kill(getpid(), SIGALRM)); char* argv[] = {self, (char*)"cont", NULL}; CHECK(execve(self, argv, NULL)); diff --git a/LibOS/shim/test/regression/test_libos.py b/LibOS/shim/test/regression/test_libos.py index fb3b7e810d..68635e37b1 100644 --- a/LibOS/shim/test/regression/test_libos.py +++ b/LibOS/shim/test/regression/test_libos.py @@ -937,6 +937,15 @@ def test_010_path(self): stdout, _ = self.run_binary(['proc_path']) self.assertIn('proc path test success', stdout) + def test_011_open_opath(self): + try: + stdout, _ = self.run_binary(['open_opath']) + finally: + if os.path.exists("tmp/B"): + os.remove("tmp/B") + self.assertIn('Hello World (exec_victim)!', stdout) + self.assertIn('TEST OK', stdout) + def test_020_cpuinfo(self): stdout, _ = self.run_binary(['proc_cpuinfo']) diff --git a/LibOS/shim/test/regression/tests.toml b/LibOS/shim/test/regression/tests.toml index 6af503b445..9bb4e4322a 100644 --- a/LibOS/shim/test/regression/tests.toml +++ b/LibOS/shim/test/regression/tests.toml @@ -65,6 +65,7 @@ manifests = [ "mprotect_prot_growsdown", "multi_pthread", "multi_pthread_exitless", + "open_opath", "openmp", "pipe", "pipe_nonblocking", diff --git a/LibOS/shim/test/regression/tests_musl.toml b/LibOS/shim/test/regression/tests_musl.toml index 4f1dd147c9..69ac3fd9ed 100644 --- a/LibOS/shim/test/regression/tests_musl.toml +++ b/LibOS/shim/test/regression/tests_musl.toml @@ -67,6 +67,7 @@ manifests = [ "mprotect_prot_growsdown", "multi_pthread", "multi_pthread_exitless", + "open_opath", "openmp", "pipe", "pipe_nonblocking",