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

WIP Convert PalStreamOpen to return pal_error_t #1883

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
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
4 changes: 2 additions & 2 deletions Documentation/Doxyfile-pal
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@INCLUDE = Doxyfile
PROJECT_NAME = "PAL"
OUTPUT_DIRECTORY = _build/doxygen-pal
INPUT = ../pal/include/arch/x86_64 ../pal/include/pal ../pal/include ../common/include/iovec.h
INPUT = ../pal/include/arch/x86_64 ../pal/include/pal ../pal/include ../common/include/pal_error.h ../common/include/iovec.h
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
PREDEFINED = noreturn= __x86_64__=1
PREDEFINED = noreturn= __x86_64__=1 NODISCARD=
11 changes: 11 additions & 0 deletions Documentation/pal/host-abi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ Data types and variables
Data types
^^^^^^^^^^

Return type
"""""""""""

All new PAL functions should return an error of :type:`pal_error_t`.

.. doxygentypedef:: pal_error_t
:project: pal

.. doxygenenum:: _pal_error_t
:project: pal

PAL handles
"""""""""""

Expand Down
20 changes: 20 additions & 0 deletions common/include/nodiscard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/* Copyright (C) 2024 Intel Corporation
* Mariusz Zaborski <[email protected]>
*/

/*
* This file contains a definition for NODISCARD, a macro that wraps
* the nodiscard attribute introduced in C23. However, because Gramine supports
* older systems that might not have support for C23, we have to wrap it on our
* own and change it to a no-op on systems that don't support it.
* TODO: Remove this after dropping *EL8 and Ubuntu 20.04 support.
*/

#pragma once

#if GRAMINE_HAS_NODISCARD
#define NODISCARD [[nodiscard]]
#else
#define NODISCARD
#endif
3 changes: 2 additions & 1 deletion common/include/pal_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@

#pragma once

#include <nodiscard.h>
#include <stddef.h>

typedef enum _pal_error_t {
typedef enum NODISCARD _pal_error_t {
PAL_ERROR_SUCCESS = 0,
PAL_ERROR_NOTIMPLEMENTED,
PAL_ERROR_NOTDEFINED,
Expand Down
27 changes: 15 additions & 12 deletions libos/src/fs/chroot/encrypted.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,11 @@ static int chroot_encrypted_mkdir(struct libos_dentry* dent, mode_t perm) {

/* This opens a "dir:..." URI */
PAL_HANDLE palhdl;
ret = PalStreamOpen(uri, PAL_ACCESS_RDONLY, HOST_PERM(perm), PAL_CREATE_ALWAYS,
PAL_OPTION_PASSTHROUGH, &palhdl);
if (ret < 0) {
ret = pal_to_unix_errno(ret);
pal_error_t pret;
pret = PalStreamOpen(uri, PAL_ACCESS_RDONLY, HOST_PERM(perm), PAL_CREATE_ALWAYS,
PAL_OPTION_PASSTHROUGH, &palhdl);
if (pret != PAL_ERROR_SUCCESS) {
ret = -pal_to_unix_errno(pret);
goto out;
}
PalObjectDestroy(palhdl);
Expand Down Expand Up @@ -304,10 +305,11 @@ static int chroot_encrypted_unlink(struct libos_dentry* dent) {
return ret;

PAL_HANDLE palhdl;
ret = PalStreamOpen(uri, PAL_ACCESS_RDONLY, /*share_flags=*/0, PAL_CREATE_NEVER,
PAL_OPTION_PASSTHROUGH, &palhdl);
if (ret < 0) {
ret = pal_to_unix_errno(ret);
pal_error_t pret;
pret = PalStreamOpen(uri, PAL_ACCESS_RDONLY, /*share_flags=*/0, PAL_CREATE_NEVER,
PAL_OPTION_PASSTHROUGH, &palhdl);
if (pret != PAL_ERROR_SUCCESS) {
ret = -pal_to_unix_errno(pret);
goto out;
}

Expand Down Expand Up @@ -369,10 +371,11 @@ static int chroot_encrypted_chmod(struct libos_dentry* dent, mode_t perm) {
goto out;

PAL_HANDLE palhdl;
ret = PalStreamOpen(uri, PAL_ACCESS_RDONLY, /*share_flags=*/0, PAL_CREATE_NEVER,
PAL_OPTION_PASSTHROUGH, &palhdl);
if (ret < 0) {
ret = pal_to_unix_errno(ret);
pal_error_t pret;
pret = PalStreamOpen(uri, PAL_ACCESS_RDONLY, /*share_flags=*/0, PAL_CREATE_NEVER,
PAL_OPTION_PASSTHROUGH, &palhdl);
if (pret != PAL_ERROR_SUCCESS) {
ret = -pal_to_unix_errno(pret);
goto out;
}
mode_t host_perm = HOST_PERM(perm);
Expand Down
18 changes: 11 additions & 7 deletions libos/src/fs/chroot/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,16 @@ static int chroot_lookup(struct libos_dentry* dent) {
/* Open a temporary read-only PAL handle for a file (used by `unlink` etc.) */
static int chroot_temp_open(struct libos_dentry* dent, PAL_HANDLE* out_palhdl) {
char* uri;
pal_error_t pret;

int ret = dentry_uri(dent, dent->inode->type, &uri);
if (ret < 0)
return ret;

ret = PalStreamOpen(uri, PAL_ACCESS_RDONLY, /*share_flags=*/0, PAL_CREATE_NEVER,
/*options=*/0, out_palhdl);
pret = PalStreamOpen(uri, PAL_ACCESS_RDONLY, /*share_flags=*/0, PAL_CREATE_NEVER,
/*options=*/0, out_palhdl);
free(uri);
return pal_to_unix_errno(ret);
return -pal_to_unix_errno(pret);
}

/* Open a PAL handle, and associate it with a LibOS handle (if provided). */
Expand All @@ -130,8 +132,9 @@ static int chroot_do_open(struct libos_handle* hdl, struct libos_dentry* dent, m
assert(locked(&g_dcache_lock));

int ret;

pal_error_t pret;
char* uri;

ret = dentry_uri(dent, type, &uri);
if (ret < 0)
return ret;
Expand All @@ -141,9 +144,10 @@ static int chroot_do_open(struct libos_handle* hdl, struct libos_dentry* dent, m
enum pal_create_mode create = LINUX_OPEN_FLAGS_TO_PAL_CREATE(flags);
pal_stream_options_t options = LINUX_OPEN_FLAGS_TO_PAL_OPTIONS(flags);
mode_t host_perm = HOST_PERM(perm);
ret = PalStreamOpen(uri, access, host_perm, create, options, &palhdl);
if (ret < 0) {
ret = pal_to_unix_errno(ret);

pret = PalStreamOpen(uri, access, host_perm, create, options, &palhdl);
if (pret != PAL_ERROR_SUCCESS) {
ret = -pal_to_unix_errno(pret);
goto out;
}

Expand Down
9 changes: 5 additions & 4 deletions libos/src/fs/dev/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,12 @@ static int dev_tty_open(struct libos_handle* hdl, struct libos_dentry* dent, int
return -ENOMEM;

PAL_HANDLE palhdl;
int ret = PalStreamOpen(uri, LINUX_OPEN_FLAGS_TO_PAL_ACCESS(flags), PSEUDO_PERM_FILE_RW,
PAL_CREATE_NEVER, /*options=*/0, &palhdl);
if (ret < 0) {
pal_error_t pret = PalStreamOpen(uri, LINUX_OPEN_FLAGS_TO_PAL_ACCESS(flags),
PSEUDO_PERM_FILE_RW, PAL_CREATE_NEVER, /*options=*/0,
&palhdl);
if (pret != PAL_ERROR_SUCCESS) {
free(uri);
return pal_to_unix_errno(ret);
return -pal_to_unix_errno(pret);
}

assert(hdl);
Expand Down
10 changes: 5 additions & 5 deletions libos/src/fs/libos_fs_encrypted.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,11 @@ static int encrypted_file_internal_open(struct libos_encrypted_file* enc, PAL_HA

if (!pal_handle) {
enum pal_create_mode create_mode = create ? PAL_CREATE_ALWAYS : PAL_CREATE_NEVER;
ret = PalStreamOpen(enc->uri, PAL_ACCESS_RDWR, share_flags, create_mode,
PAL_OPTION_PASSTHROUGH, &pal_handle);
if (ret < 0) {
log_warning("PalStreamOpen failed: %s", pal_strerror(ret));
return pal_to_unix_errno(ret);
pal_error_t pret = PalStreamOpen(enc->uri, PAL_ACCESS_RDWR, share_flags, create_mode,
PAL_OPTION_PASSTHROUGH, &pal_handle);
if (pret != PAL_ERROR_SUCCESS) {
log_warning("PalStreamOpen failed: %s", pal_strerror(pret));
return -pal_to_unix_errno(pret);
}
}

Expand Down
7 changes: 4 additions & 3 deletions libos/src/fs/shm/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ static int shm_do_open(struct libos_handle* hdl, struct libos_dentry* dent, mode
assert(locked(&g_dcache_lock));

char* uri;
pal_error_t pret;
int ret = dentry_uri(dent, type, &uri);
if (ret < 0)
return ret;
Expand All @@ -66,9 +67,9 @@ static int shm_do_open(struct libos_handle* hdl, struct libos_dentry* dent, mode
enum pal_create_mode create = LINUX_OPEN_FLAGS_TO_PAL_CREATE(flags);
pal_stream_options_t options = LINUX_OPEN_FLAGS_TO_PAL_OPTIONS(flags);
mode_t host_perm = HOST_PERM(perm);
ret = PalStreamOpen(uri, access, host_perm, create, options, &palhdl);
if (ret < 0) {
ret = pal_to_unix_errno(ret);
pret = PalStreamOpen(uri, access, host_perm, create, options, &palhdl);
if (pret != PAL_ERROR_SUCCESS) {
ret = -pal_to_unix_errno(pret);
goto out;
}

Expand Down
11 changes: 6 additions & 5 deletions libos/src/ipc/libos_ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static int vmid_to_uri(IDTYPE vmid, char* uri, size_t uri_size) {
static int ipc_connect(IDTYPE dest, struct libos_ipc_connection** conn_ptr) {
struct libos_ipc_connection dummy = { .vmid = dest };
int ret = 0;
pal_error_t pret;

lock(&g_ipc_connections_lock);
struct libos_ipc_connection* conn = node2conn(avl_tree_find(&g_ipc_connections, &dummy.node));
Expand All @@ -128,11 +129,11 @@ static int ipc_connect(IDTYPE dest, struct libos_ipc_connection** conn_ptr) {
BUG();
}
do {
ret = PalStreamOpen(uri, PAL_ACCESS_RDONLY, /*share_flags=*/0, PAL_CREATE_IGNORED,
/*options=*/0, &conn->handle);
} while (ret == -PAL_ERROR_INTERRUPTED);
if (ret < 0) {
ret = pal_to_unix_errno(ret);
pret = PalStreamOpen(uri, PAL_ACCESS_RDONLY, /*share_flags=*/0, PAL_CREATE_IGNORED,
/*options=*/0, &conn->handle);
} while (pret == PAL_ERROR_INTERRUPTED);
if (pret != PAL_ERROR_SUCCESS) {
ret = -pal_to_unix_errno(pret);
goto out;
}
ret = write_exact(conn->handle, &g_process_ipc_ids.self_vmid,
Expand Down
11 changes: 6 additions & 5 deletions libos/src/libos_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ int create_pipe(char* name, char* uri, size_t size, PAL_HANDLE* hdl, bool use_vm
int ret;
size_t len;
char pipename[PIPE_URI_SIZE];
pal_error_t pret;
PAL_HANDLE pipe = NULL;

assert(hdl);
Expand All @@ -566,14 +567,14 @@ int create_pipe(char* name, char* uri, size_t size, PAL_HANDLE* hdl, bool use_vm
if (len >= size)
return -ERANGE;

ret = PalStreamOpen(uri, PAL_ACCESS_RDWR, /*share_flags=*/0, PAL_CREATE_IGNORED,
/*options=*/0, &pipe);
if (ret < 0) {
if (!use_vmid_for_name && ret == -PAL_ERROR_STREAMEXIST) {
pret = PalStreamOpen(uri, PAL_ACCESS_RDWR, /*share_flags=*/0, PAL_CREATE_IGNORED,
/*options=*/0, &pipe);
if (pret != PAL_ERROR_SUCCESS) {
if (!use_vmid_for_name && pret == PAL_ERROR_STREAMEXIST) {
/* tried to create a pipe with random name but it already exists */
continue;
}
return pal_to_unix_errno(ret);
return -pal_to_unix_errno(pret);
}

break; /* succeeded in creating the pipe with random/vmid name */
Expand Down
13 changes: 7 additions & 6 deletions libos/src/libos_pollable_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
int create_pollable_event(struct libos_pollable_event* event) {
char uri[PIPE_URI_SIZE];
PAL_HANDLE srv_handle;
pal_error_t pret;
int ret = create_pipe(/*name=*/NULL, uri, sizeof(uri), &srv_handle,
/*use_vmid_for_name=*/false);
if (ret < 0) {
Expand All @@ -22,12 +23,12 @@ int create_pollable_event(struct libos_pollable_event* event) {

PAL_HANDLE write_handle;
do {
ret = PalStreamOpen(uri, PAL_ACCESS_RDWR, /*share_flags=*/0, PAL_CREATE_IGNORED,
PAL_OPTION_NONBLOCK, &write_handle);
} while (ret == -PAL_ERROR_INTERRUPTED);
if (ret < 0) {
log_error("PalStreamOpen failed: %s", pal_strerror(ret));
ret = pal_to_unix_errno(ret);
pret = PalStreamOpen(uri, PAL_ACCESS_RDWR, /*share_flags=*/0, PAL_CREATE_IGNORED,
PAL_OPTION_NONBLOCK, &write_handle);
} while (pret == PAL_ERROR_INTERRUPTED);
if (pret != PAL_ERROR_SUCCESS) {
log_error("PalStreamOpen failed: %s", pal_strerror(pret));
ret = -pal_to_unix_errno(pret);
goto out;
}

Expand Down
16 changes: 8 additions & 8 deletions libos/src/net/unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,10 @@ static int bind(struct libos_handle* handle, void* addr, size_t addrlen) {
unlock(&handle->lock);

PAL_HANDLE pal_handle = NULL;
ret = PalStreamOpen(pipe_name, PAL_ACCESS_RDWR, /*share_flags=*/0, PAL_CREATE_IGNORED, options,
&pal_handle);
if (ret < 0) {
return (ret == -PAL_ERROR_STREAMEXIST) ? -EADDRINUSE : pal_to_unix_errno(ret);
pal_error_t pret = PalStreamOpen(pipe_name, PAL_ACCESS_RDWR, /*share_flags=*/0,
PAL_CREATE_IGNORED, options, &pal_handle);
if (pret != PAL_ERROR_SUCCESS) {
return (pret == PAL_ERROR_STREAMEXIST) ? -EADDRINUSE : -pal_to_unix_errno(pret);
}

__atomic_store_n(&handle->info.sock.pal_handle, pal_handle, __ATOMIC_RELEASE);
Expand Down Expand Up @@ -243,10 +243,10 @@ static int connect(struct libos_handle* handle, void* addr, size_t addrlen, bool
unlock(&handle->lock);

PAL_HANDLE pal_handle = NULL;
ret = PalStreamOpen(pipe_name, PAL_ACCESS_RDWR, /*share_flags=*/0, PAL_CREATE_IGNORED, options,
&pal_handle);
if (ret < 0) {
return (ret == -PAL_ERROR_CONNFAILED) ? -ENOENT : pal_to_unix_errno(ret);
pal_error_t pret = PalStreamOpen(pipe_name, PAL_ACCESS_RDWR, /*share_flags=*/0,
PAL_CREATE_IGNORED, options, &pal_handle);
if (pret != PAL_ERROR_SUCCESS) {
return (pret == PAL_ERROR_CONNFAILED) ? -ENOENT : -pal_to_unix_errno(pret);
}

assert(sock->pal_handle == NULL);
Expand Down
10 changes: 5 additions & 5 deletions libos/src/sys/libos_eventfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,18 @@ int init_eventfd_mode(void) {
static int create_eventfd_pal_handle(uint64_t initial_count, int flags,
PAL_HANDLE* out_pal_handle) {
int ret;

pal_error_t pret;
PAL_HANDLE hdl = NULL;

int pal_flags = 0;
pal_flags |= flags & EFD_NONBLOCK ? PAL_OPTION_NONBLOCK : 0;
pal_flags |= flags & EFD_SEMAPHORE ? PAL_OPTION_EFD_SEMAPHORE : 0;

ret = PalStreamOpen(URI_PREFIX_EVENTFD, PAL_ACCESS_RDWR, /*share_flags=*/0,
PAL_CREATE_IGNORED, pal_flags, &hdl);
if (ret < 0) {
pret = PalStreamOpen(URI_PREFIX_EVENTFD, PAL_ACCESS_RDWR, /*share_flags=*/0,
PAL_CREATE_IGNORED, pal_flags, &hdl);
if (pret != PAL_ERROR_SUCCESS) {
log_error("eventfd: creation failure");
return pal_to_unix_errno(ret);
return -pal_to_unix_errno(pret);
}

/* set the initial count */
Expand Down
9 changes: 5 additions & 4 deletions libos/src/sys/libos_pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

static int create_pipes(struct libos_handle* srv, struct libos_handle* cli, int flags, char* name) {
int ret = 0;
pal_error_t pret;
char uri[PIPE_URI_SIZE];

PAL_HANDLE hdl0 = NULL; /* server pipe (temporary, waits for connect from hdl2) */
Expand All @@ -34,10 +35,10 @@ static int create_pipes(struct libos_handle* srv, struct libos_handle* cli, int
return ret;
}

ret = PalStreamOpen(uri, PAL_ACCESS_RDWR, /*share_flags=*/0, PAL_CREATE_IGNORED,
LINUX_OPEN_FLAGS_TO_PAL_OPTIONS(flags), &hdl2);
if (ret < 0) {
ret = pal_to_unix_errno(ret);
pret = PalStreamOpen(uri, PAL_ACCESS_RDWR, /*share_flags=*/0, PAL_CREATE_IGNORED,
LINUX_OPEN_FLAGS_TO_PAL_OPTIONS(flags), &hdl2);
if (pret != PAL_ERROR_SUCCESS) {
ret = -pal_to_unix_errno(pret);
log_error("pipe connection failure");
goto out;
}
Expand Down
23 changes: 23 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,29 @@ project(
],
)

# If C23 (or experimetal C23 - C2x) is available, use it.
# TODO: Gramine supports older versions of gcc, so newer versions of compilers
# may not be available.
# We can change to c2x when we drop *EL8 and Ubuntu 20.04.
# We can't change to c23 for any supported versions yet (requires at
# leaast gcc 14).
nodiscard_code = '[[nodiscard]] int func() { return 0; }'
if meson.get_compiler('c').compiles(
nodiscard_code,
args : '-std=c23',
name : 'check for [[nodiscard]] and c23',
)
add_project_arguments('-std=c23', language: 'c')
add_global_arguments('-DGRAMINE_HAS_NODISCARD', language : 'c')
elif meson.get_compiler('c').compiles(
nodiscard_code,
args : '-std=c2x',
name : 'check for [[nodiscard]] and c2x',
)
add_project_arguments('-std=c2x', language: 'c')
add_global_arguments('-DGRAMINE_HAS_NODISCARD', language : 'c')
endif

# we need this subdir() early, because we need scripts defined there for setting up global vars
subdir('scripts')

Expand Down
Loading