Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LibOS] Add O_PATH support to open syscall #650

Merged
merged 1 commit into from
Jun 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 1 addition & 12 deletions LibOS/shim/include/shim_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions LibOS/shim/include/shim_handle.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
3 changes: 0 additions & 3 deletions LibOS/shim/src/bookkeep/shim_handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
8 changes: 5 additions & 3 deletions LibOS/shim/src/fs/chroot/encrypted.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions LibOS/shim/src/fs/shim_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
25 changes: 25 additions & 0 deletions LibOS/shim/src/fs/shim_fs_path.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/* Copyright (C) 2022 Intel Corporation
* Borys Popławski <[email protected]>
*/

#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,
};
63 changes: 40 additions & 23 deletions LibOS/shim/src/fs/shim_namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -445,40 +445,56 @@ 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;
}
}

if (dent->inode && dent->inode->type == S_IFLNK) {
/*
* 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 */
struct shim_dentry* dir = dentry_up(dent);
if (dir) {
ret = check_permissions(dir, MAY_WRITE | MAY_EXEC);
if (ret < 0)
goto err;
goto out;
}

struct shim_fs* fs = dent->mount->fs;
Expand All @@ -487,57 +503,58 @@ 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;
}
} else {
/* 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;
}
Expand Down
1 change: 1 addition & 0 deletions LibOS/shim/src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
9 changes: 8 additions & 1 deletion LibOS/shim/src/sys/shim_open.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
8 changes: 4 additions & 4 deletions LibOS/shim/test/ltp/ltp.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -1294,7 +1294,7 @@ skip = yes
[open12]
skip = yes

# Requires touch() support
# Requires `utime*` syscall support
[open13]
skip = yes

Expand Down
22 changes: 21 additions & 1 deletion LibOS/shim/test/regression/common.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,35 @@
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/* Copyright (C) 2021 Intel Corporation
/* Copyright (C) 2022 Intel Corporation
* Paweł Marczewski <[email protected]>
* Borys Popławski <[email protected]>
*/

#ifndef COMMON_H_
#define COMMON_H_

#include <assert.h>
#include <err.h>

#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_ */
10 changes: 1 addition & 9 deletions LibOS/shim/test/regression/epoll_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,11 @@
#include <sys/wait.h>
#include <unistd.h>

#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 };
Expand Down
4 changes: 2 additions & 2 deletions LibOS/shim/test/regression/groups.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include <sys/wait.h>
#include <unistd.h>

#define ARRAY_LEN(x) (sizeof(x) / sizeof(x[0]))
#include "common.h"

static gid_t test_groups[] = { 0, 1337, 1337, 0 };

Expand Down Expand Up @@ -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));
}

Expand Down
1 change: 1 addition & 0 deletions LibOS/shim/test/regression/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
Loading