From 1ad669404ed271ae34f9217dd82c8dce3c707d8c Mon Sep 17 00:00:00 2001 From: Andrei Tatar Date: Tue, 23 Jan 2024 19:44:06 +0100 Subject: [PATCH] lib/posix-fdtab: Handle fdtab duplication on clone This change adds logic to handle fdtab references on clone: - if CLONE_FILES: child inherits a reference to parent's tab - if !CLONE_FILES: child allocates new fdtab duplicate of parent's, populated with new references to the same open file descriptions hosted by the parent fdtab. The initial duplication logic is rudimentary and does not provide any ordering guarantees w.r.t. syscalls modifying the original table (open, dup, close), under the assumption that it won't trigger race conditions in the wild. Please revisit if this turns out to be overly optimistic. Signed-off-by: Andrei Tatar Approved-by: Michalis Pappas Reviewed-by: Michalis Pappas GitHub-Closes: #1278 --- lib/posix-fdtab/Config.uk | 1 + lib/posix-fdtab/fdtab.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/lib/posix-fdtab/Config.uk b/lib/posix-fdtab/Config.uk index 4f18491f2..12116f7dd 100644 --- a/lib/posix-fdtab/Config.uk +++ b/lib/posix-fdtab/Config.uk @@ -12,6 +12,7 @@ if LIBPOSIX_FDTAB # Hidden, will autoselect when required config LIBPOSIX_FDTAB_MULTITAB bool + default y if LIBPOSIX_PROCESS_CLONE select LIBUKSCHED # Hidden, selected by core components when needed diff --git a/lib/posix-fdtab/fdtab.c b/lib/posix-fdtab/fdtab.c index 39bbcb50c..c7f04f88a 100644 --- a/lib/posix-fdtab/fdtab.c +++ b/lib/posix-fdtab/fdtab.c @@ -27,6 +27,10 @@ #include #endif /* CONFIG_LIBPOSIX_FDTAB_LEGACY_SHIM */ +#if CONFIG_LIBPOSIX_PROCESS_CLONE +#include +#endif /* CONFIG_LIBPOSIX_PROCESS_CLONE */ + #if CONFIG_LIBPOSIX_PROCESS_EXECVE #include #include @@ -503,6 +507,38 @@ static void fdtab_thread_term(struct uk_thread *child) UK_THREAD_INIT(fdtab_thread_init, fdtab_thread_term); +#if CONFIG_LIBPOSIX_PROCESS_CLONE +static int fdtab_clone(const struct clone_args *cl_args, + size_t cl_args_len __unused, + struct uk_thread *child, + struct uk_thread *parent) +{ + struct uk_fdtab *tab = uk_thread_uktls_var(parent, active_fdtab); + struct uk_fdtab *newtab; + + UK_ASSERT(tab); /* Do not call clone from raw threads */ + if (cl_args->flags & CLONE_FILES) { + /* Inherit parent's fdtab */ + /* As a compat stop-gap, the raw thread already inherited the + * parent's fdtab ref; we don't need to do anything. + * + * TODO: move inheritance here once stopgap is removed. + */ + UK_ASSERT(uk_thread_uktls_var(child, active_fdtab) == tab); + return 0; + } else { + /* Duplicate parent's fdtab */ + newtab = fdtab_duplicate(tab); + if (unlikely(!newtab)) + return -ENOMEM; + } + uk_thread_uktls_var(child, active_fdtab) = newtab; + return 0; +} + +UK_POSIX_CLONE_HANDLER(CLONE_FILES, 0, fdtab_clone, 0); + +#endif /* CONFIG_LIBPOSIX_PROCESS_CLONE */ #endif /* CONFIG_LIBPOSIX_FDTAB_MULTITAB */ /* Init fdtab as early as possible, to enable functions that rely on fds */ -- 2.39.5