From 8e831d2224bb1c9c3fbaab693e7e4d581cebe77b Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 21 Nov 2012 16:50:51 +0100 Subject: [PATCH] base-linux: Support customization of UIDs and GIDs With this patch, custom UIDs and GIDs can be assigned to individual Genode processes or whole Genode subsystems. The new 'base-linux/run/lx_uid.run' script contains an example of how to use the feature. Fixes #510 --- base-linux/run/lx_uid.run | 101 ++++++++++++++++++ .../src/core/include/core_linux_syscalls.h | 17 ++- base-linux/src/core/pd_session_component.cc | 55 ++++++++-- os/src/test/chroot_loader/target.mk | 7 +- 4 files changed, 166 insertions(+), 14 deletions(-) create mode 100644 base-linux/run/lx_uid.run diff --git a/base-linux/run/lx_uid.run b/base-linux/run/lx_uid.run new file mode 100644 index 0000000000..2512e37157 --- /dev/null +++ b/base-linux/run/lx_uid.run @@ -0,0 +1,101 @@ +# +# \brief Test for assigning custom UIDs and GIDs to Genode processes +# \author Norman Feske +# \date 2012-11-21 +# + +build "core init test/printf" + +assert_spec linux + +create_boot_directory + +install_config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +# +# Copy boot modules into run directory +# +# We cannot use the predefined 'build_boot_image' function here because +# this would create mere symlinks. However, we need to enable the setuid +# and setgid capabilities for core, which won't work if core were a symlink. +# +foreach binary { core init } { + exec cp -H bin/$binary [run_dir] } + +# +# Allow core to set arbitrary UIDs and GIDs +# +exec sudo setcap cap_setuid,cap_setgid=ep [run_dir]/core + +# +# Execute Genode until the point where init_sub_77 is up +# +run_genode_until {\[init -> init_77 -> init_sub_77\].*No children to start.*\n} 10 + +# +# Obtain the list of Genode user processes starting with the name 'init' +# +set ps_output [exec ps -eo uid,gid,cmd | grep Genode | grep init] + +puts "Genode user processes:\n$ps_output" + +# +# Validate output of ps +# +# We are only interested in the lines for the init instances with the +# customized UIDs and GIDs. +# +if {![regexp {55\s*66 \[Genode\] init_55_66} $ps_output] + || ![regexp {77\s*77 \[Genode\] init_77} $ps_output] + || ![regexp {77\s*77 \[Genode\] init_77 -> init_sub_77} $ps_output]} { + puts stderr "Unexpected output of ps" + exit 1 +} + +puts "Test succeeded" + diff --git a/base-linux/src/core/include/core_linux_syscalls.h b/base-linux/src/core/include/core_linux_syscalls.h index 6897bb1ccd..2bf00b00d2 100644 --- a/base-linux/src/core/include/core_linux_syscalls.h +++ b/base-linux/src/core/include/core_linux_syscalls.h @@ -72,11 +72,6 @@ inline int lx_execve(const char *filename, char *const argv[], } -/** - * Send signal to process - * - * This function is used by core to kill processes. - */ inline int lx_kill(int pid, int signal) { return lx_syscall(SYS_kill, pid, signal); @@ -90,6 +85,18 @@ inline int lx_create_process(int (*entry)(void *), void *stack, void *arg) } +inline int lx_setuid(unsigned int uid) +{ + return lx_syscall(SYS_setuid, uid); +} + + +inline int lx_setgid(unsigned int gid) +{ + return lx_syscall(SYS_setgid, gid); +} + + /********************* ** Chroot handling ** *********************/ diff --git a/base-linux/src/core/pd_session_component.cc b/base-linux/src/core/pd_session_component.cc index 0ec0fc18a0..9c565a4ee0 100644 --- a/base-linux/src/core/pd_session_component.cc +++ b/base-linux/src/core/pd_session_component.cc @@ -195,11 +195,25 @@ static bool setup_chroot_environment(char const *chroot_path) */ struct Execve_args { - char const *filename; - char const *root; - char *const *argv; - char *const *envp; - int parent_sd; + char const *filename; + char const *root; + char * const *argv; + char * const *envp; + unsigned int const uid; + unsigned int const gid; + int const parent_sd; + + Execve_args(char const *filename, + char const *root, + char * const *argv, + char * const *envp, + unsigned int uid, + unsigned int gid, + int parent_sd) + : + filename(filename), root(root), argv(argv), envp(envp), + uid(uid), gid(gid), parent_sd(parent_sd) + { } }; @@ -242,6 +256,25 @@ static int _exec_child(Execve_args *arg) } } + /* + * Set UID and GID + * + * We must set the GID prior setting the UID because setting the GID won't + * be possible anymore once we set the UID to non-root. + */ + if (arg->gid) { + int const ret = lx_setgid(arg->gid); + if (ret) + PWRN("Could not set PID %d (%s) to GID %u (error %d)", + lx_getpid(), arg->filename, arg->gid, ret); + } + if (arg->uid) { + int const ret = lx_setuid(arg->uid); + if (ret) + PWRN("Could not set PID %d (%s) to UID %u (error %d)", + lx_getpid(), arg->filename, arg->uid, ret); + } + return lx_execve(arg->filename, arg->argv, arg->envp); } @@ -289,6 +322,15 @@ Pd_session_component::Pd_session_component(Rpc_entrypoint *ep, const char *args) bool const is_chroot = (Genode::strcmp(_root, "") != 0); + /* + * If a UID is specified but no GID, we use the UID as GID. This way, a + * configuration error where the UID is defined but the GID is left + * undefined won't result in the execution of the new process with the + * root user's GID. + */ + if (_gid == 0) + _gid = _uid; + /* * Print Linux-specific session arguments if specified * @@ -375,7 +417,8 @@ void Pd_session_component::start(Capability binary) * Argument frame as passed to 'clone'. Because, we can only pass a single * pointer, all arguments are embedded within the 'execve_args' struct. */ - Execve_args arg = { filename.buf, _root, argv_buf, env, _parent.dst().socket }; + Execve_args arg(filename.buf, _root, argv_buf, env, _uid, _gid, + _parent.dst().socket); _pid = lx_create_process((int (*)(void *))_exec_child, stack + STACK_SIZE - sizeof(umword_t), &arg); diff --git a/os/src/test/chroot_loader/target.mk b/os/src/test/chroot_loader/target.mk index b59705e964..0c2900720e 100644 --- a/os/src/test/chroot_loader/target.mk +++ b/os/src/test/chroot_loader/target.mk @@ -1,3 +1,4 @@ -TARGET = test-chroot_loader -SRC_CC = main.cc -LIBS += cxx env +TARGET = test-chroot_loader +REQUIRES += linux +SRC_CC = main.cc +LIBS += cxx env