Skip to content

Commit

Permalink
[LibOS] Add loader.uid and loader.gid manifest options
Browse files Browse the repository at this point in the history
By default, Gramine uses the root user (uid = gid = 0), which may cause
some apps to refuse to run. This commit allows Gramine to run an app
with another user than root. We also set effective UID/GID to the same
value as UID/GID respectively.

Signed-off-by: Denis Zygann <[email protected]>
  • Loading branch information
Denis Zygann authored and Dmitrii Kuvaiskii committed Oct 5, 2021
1 parent f28deaf commit 299500a
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 1 deletion.
14 changes: 14 additions & 0 deletions Documentation/manifest-syntax.rst
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,20 @@ are "consumed" by ``insecure__use_host_env``).
because it's inherently insecure (doesn't provide any real security).
Gramine loudly fails if ``passthrough = false`` manifest options are set.
User ID and Group ID
^^^^^^^^^^^^^^^^^^^^

::

loader.uid = [NUM]
loader.gid = [NUM]
(Default: 0)

This specifies the initial, Gramine emulated user/group ID and effective
user/group ID. It must be non-negative. By default Gramine emulates the
user/group ID and effective user/group ID as the root user (uid = gid = 0).


Disabling ASLR
^^^^^^^^^^^^^^

Expand Down
33 changes: 32 additions & 1 deletion LibOS/shim/src/bookkeep/shim_thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,38 @@ static int init_main_thread(void) {
g_process.pid = cur_thread->tid;
__atomic_store_n(&g_process.pgid, g_process.pid, __ATOMIC_RELEASE);

/* Default user and group ids are `0` and already set. */
int64_t uid_int64;
ret = toml_int_in(g_manifest_root, "loader.uid", /*defaultval=*/0, &uid_int64);
if (ret < 0) {
log_error("Cannot parse 'loader.uid'");
put_thread(cur_thread);
return -EINVAL;
}

int64_t gid_int64;
ret = toml_int_in(g_manifest_root, "loader.gid", /*defaultval=*/0, &gid_int64);
if (ret < 0) {
log_error("Cannot parse 'loader.gid'");
put_thread(cur_thread);
return -EINVAL;
}

if (uid_int64 < 0 || uid_int64 > IDTYPE_MAX) {
log_error("'loader.uid' = %ld is negative or greater than %u", uid_int64, IDTYPE_MAX);
put_thread(cur_thread);
return -EINVAL;
}

if (gid_int64 < 0 || gid_int64 > IDTYPE_MAX) {
log_error("'loader.gid' = %ld is negative or greater than %u", gid_int64, IDTYPE_MAX);
put_thread(cur_thread);
return -EINVAL;
}

cur_thread->uid = uid_int64;
cur_thread->euid = uid_int64;
cur_thread->gid = gid_int64;
cur_thread->egid = gid_int64;

cur_thread->signal_dispositions = alloc_default_signal_dispositions();
if (!cur_thread->signal_dispositions) {
Expand Down
1 change: 1 addition & 0 deletions LibOS/shim/test/regression/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,6 @@
/tcp_msg_peek
/tmp
/udp
/uid_gid
/unix
/vfork_and_exec
1 change: 1 addition & 0 deletions LibOS/shim/test/regression/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ c_executables = \
tcp_ipv6_v6only \
tcp_msg_peek \
udp \
uid_gid \
unix \
vfork_and_exec \
$(c_executables-$(ARCH))
Expand Down
4 changes: 4 additions & 0 deletions LibOS/shim/test/regression/test_libos.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ def test_107_basic_bootstrapping_pie(self):
self.assertIn('Local Address in Executable: 0x', stdout)
self.assertIn('argv[0] = bootstrap_pie', stdout)

def test_108_uid_and_gid(self):
stdout, _ = self.run_binary(['uid_gid'])
self.assertIn('TEST OK', stdout)

@unittest.skipUnless(ON_X86, "x86-specific")
def test_110_basic_bootstrapping_cpp(self):
stdout, _ = self.run_binary(['bootstrap_cpp'])
Expand Down
24 changes: 24 additions & 0 deletions LibOS/shim/test/regression/uid_gid.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char** argv) {
uid_t uid = getuid();
uid_t euid = geteuid();

if (uid != 1338 || euid != 1338) {
errx(EXIT_FAILURE, "UID/effective UID are not equal to the value in the manifest");
}

uid_t gid = getgid();
uid_t egid = getegid();

if (gid != 1337 || egid != 1337) {
errx(EXIT_FAILURE, "GID/effective GID are not equal to the value in the manifest");
}

puts("TEST OK");
return 0;
}
19 changes: 19 additions & 0 deletions LibOS/shim/test/regression/uid_gid.manifest.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
loader.preload = "file:{{ gramine.libos }}"
libos.entrypoint = "uid_gid"
loader.env.LD_LIBRARY_PATH = "/lib:{{ arch_libdir }}:/usr/{{ arch_libdir }}"
loader.argv0_override = "uid_gid"

loader.uid = 1338
loader.gid = 1337

fs.mount.lib.type = "chroot"
fs.mount.lib.path = "/lib"
fs.mount.lib.uri = "file:{{ gramine.runtimedir() }}"

sgx.nonpie_binary = true
sgx.debug = true

sgx.trusted_files = [
"file:{{ gramine.runtimedir() }}/",
"file:uid_gid",
]

0 comments on commit 299500a

Please sign in to comment.