From: Ron Nazarov Date: Wed, 27 Nov 2024 00:41:20 +0000 (+0000) Subject: Add support for Linux namespaces X-Git-Tag: v1.6.1-roc-dev~11 X-Git-Url: https://skyeroc.xyz/gitweb/?a=commitdiff_plain;h=52cf6045c0ce521228ea893748189fca8dc42199;p=dgamelaunch Add support for Linux namespaces If compiled with --enable-namespaces, dgamelaunch will now create new user and network namespaces before chrooting. This means that it works without root (if unprivileged user namespaces are enabled) and cannot access the network. Without namespaces: -chroot -setgroups/setgid/setuid to shed_gid/shed_uid With namespaces: -unshare to create a new user and network namespace -write to /proc/self/{uid,gid}_map to set uid/gid to shed_uid/shed_gid -chroot -drop all capabilities --- diff --git a/configure.ac b/configure.ac index 5008dc9..8935a2d 100644 --- a/configure.ac +++ b/configure.ac @@ -165,6 +165,19 @@ if test "$enable_shmem" = yes; then fi +AC_ARG_ENABLE(namespaces, +[AS_HELP_STRING([--enable-namespaces],[Use Linux namespaces.])], +[enable_namespaces=yes], []) + +if test "$enable_namespaces" = yes; then + AC_CHECK_HEADERS([sched.h], [], [AC_MSG_ERROR([sched.h not found.])], []) + AC_CHECK_HEADERS([sys/capability.h], [], [AC_MSG_ERROR([sys/capability.h not found.])], []) + AC_CHECK_LIB(cap, cap_get_proc, [LIBS+=" -lcap"], [AC_MSG_ERROR([Cannot find libcap.])]) + AC_MSG_RESULT([Enabled Linux namespace support.]) + AC_DEFINE(USE_NAMESPACES,1,[Use Linux namespaces]) +fi + + AC_ARG_WITH(config-file, [AS_HELP_STRING([--with-config-file=PATH],[Define the path to the default configuration file.])], [configfile=$withval], [configfile="/etc/dgamelaunch.conf"]) diff --git a/dgamelaunch.c b/dgamelaunch.c index 2a6dfd8..3165280 100644 --- a/dgamelaunch.c +++ b/dgamelaunch.c @@ -80,6 +80,11 @@ # include #endif +#ifdef USE_NAMESPACES +# include +# include +#endif + #include #include #include @@ -2949,6 +2954,32 @@ runmenuloop(struct dg_menu *menu) } } +#ifdef USE_NAMESPACES +void +write_proc_maps(uid_t uid, gid_t gid) +{ + FILE *fp; + + fp = fopen("/proc/self/setgroups", "w"); + if (fp) { + fprintf(fp, "deny"); + fclose(fp); + } else perror("fopen setgroups"); + + fp = fopen("/proc/self/uid_map", "w"); + if (fp) { + fprintf(fp, "%d %d 1", globalconfig.shed_uid, uid); + fclose(fp); + } else perror("fopen uid_map"); + + fp = fopen("/proc/self/gid_map", "w"); + if (fp) { + fprintf(fp, "%d %d 1", globalconfig.shed_gid, gid); + fclose(fp); + } else perror("fopen gid_map"); +} +#endif + int main (int argc, char** argv) { @@ -3114,7 +3145,21 @@ main (int argc, char** argv) #endif #endif +#ifdef USE_NAMESPACES + { + uid_t uid = geteuid(); + gid_t gid = getegid(); + if (unshare(CLONE_NEWUSER | CLONE_NEWNET)) { + perror("unshare"); + graceful_exit(14); + } + write_proc_maps(uid, gid); + } +#endif + +#ifndef USE_NAMESPACES if (geteuid () != globalconfig.shed_uid) +#endif { /* chroot */ if (chroot (globalconfig.chroot)) @@ -3134,6 +3179,15 @@ main (int argc, char** argv) } /* shed privs. this is done immediately after chroot. */ +#ifdef USE_NAMESPACES + { + /* drop all capabilities */ + cap_t cap = cap_get_proc(); + cap_clear(cap); + cap_set_proc(cap); + cap_free(cap); + } +#else if (setgroups (1, &globalconfig.shed_gid) == -1) { perror ("setgroups"); @@ -3151,6 +3205,7 @@ main (int argc, char** argv) perror ("setuid"); graceful_exit (6); } +#endif } if (globalconfig.locale) {