From 6e214b261604c4ab1ffc244272443a587bb59927 Mon Sep 17 00:00:00 2001 From: LinkTed Date: Sun, 13 Jun 2021 19:26:24 +0200 Subject: capabilities: Add support for Linux capabilities(7) This adds capabilities for start-stop-daemon by adding --capabilities option. As a result, the user can specify the inheritable, ambient and bounding set by define capabilities in the service script. This fixes #314. --- src/rc/meson.build | 8 ++++---- src/rc/start-stop-daemon.c | 35 +++++++++++++++++++++++++++++++++++ src/rc/supervise-daemon.c | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 4 deletions(-) (limited to 'src/rc') diff --git a/src/rc/meson.build b/src/rc/meson.build index e0603fd0..c76587c2 100644 --- a/src/rc/meson.build +++ b/src/rc/meson.build @@ -93,9 +93,9 @@ executable('runscript', executable('start-stop-daemon', ['start-stop-daemon.c', 'rc-pipes.c', rc_misc_c, rc_schedules_c, rc_selinux_c, usage_c, version_h], - c_args : [cc_audit_flags, cc_branding_flags, cc_pam_flags, cc_selinux_flags], + c_args : [cc_audit_flags, cc_branding_flags, cc_pam_flags, cc_cap_flags, cc_selinux_flags], link_with: [libeinfo, librc], - dependencies: [audit_dep, dl_dep, pam_dep, pam_misc_dep, util_dep, selinux_dep, crypt_dep], + dependencies: [audit_dep, dl_dep, pam_dep, cap_dep, pam_misc_dep, util_dep, selinux_dep, crypt_dep], include_directories: [incdir, einfo_incdir, rc_incdir], install: true, install_dir: sbindir) @@ -103,9 +103,9 @@ executable('start-stop-daemon', executable('supervise-daemon', ['supervise-daemon.c', rc_misc_c, rc_plugin_c, rc_schedules_c, usage_c, version_h], - c_args : [cc_branding_flags, cc_pam_flags, cc_selinux_flags], + c_args : [cc_branding_flags, cc_pam_flags, cc_cap_flags, cc_selinux_flags], link_with: [libeinfo, librc], - dependencies: [dl_dep, pam_dep, util_dep, selinux_dep], + dependencies: [dl_dep, pam_dep, cap_dep, util_dep, selinux_dep], include_directories: [incdir, einfo_incdir, rc_incdir], install: true, install_dir: sbindir) diff --git a/src/rc/start-stop-daemon.c b/src/rc/start-stop-daemon.c index 62e579d1..4d89b0b6 100644 --- a/src/rc/start-stop-daemon.c +++ b/src/rc/start-stop-daemon.c @@ -55,6 +55,10 @@ static struct pam_conv conv = { NULL, NULL}; #endif +#ifdef HAVE_CAP +#include +#endif + #include "einfo.h" #include "queue.h" #include "rc.h" @@ -69,6 +73,7 @@ const char *extraopts = NULL; const char getoptstring[] = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:3:4:" \ getoptstring_COMMON; const struct option longopts[] = { + { "capabilities", 1, NULL, 0x100}, { "ionice", 1, NULL, 'I'}, { "stop", 0, NULL, 'K'}, { "nicelevel", 1, NULL, 'N'}, @@ -101,6 +106,7 @@ const struct option longopts[] = { longopts_COMMON }; const char * const longopts_help[] = { + "Set the inheritable, ambient and bounding capabilities", "Set an ionice class:data when starting", "Stop daemon", "Set a nicelevel when starting", @@ -307,6 +313,9 @@ int main(int argc, char **argv) mode_t numask = 022; char **margv; unsigned int start_wait = 0; +#ifdef HAVE_CAP + cap_iab_t cap_iab = NULL; +#endif applet = basename_c(argv[0]); atexit(cleanup); @@ -353,6 +362,16 @@ int main(int argc, char **argv) while ((opt = getopt_long(argc, argv, getoptstring, longopts, (int *) 0)) != -1) switch (opt) { + case 0x100: +#ifdef HAVE_CAP + cap_iab = cap_iab_from_text(optarg); + if (cap_iab == NULL) + eerrorx("Could not parse iab: %s", strerror(errno)); +#else + eerrorx("Capabilities support not enabled"); +#endif + break; + case 'I': /* --ionice */ if (sscanf(optarg, "%d:%d", &ionicec, &ioniced) == 0) eerrorx("%s: invalid ionice `%s'", @@ -850,13 +869,29 @@ int main(int argc, char **argv) if (changeuser && initgroups(changeuser, gid)) eerrorx("%s: initgroups (%s, %d)", applet, changeuser, gid); +#ifdef HAVE_CAP + if (uid && cap_setuid(uid)) +#else if (uid && setuid(uid)) +#endif eerrorx ("%s: unable to set userid to %d", applet, uid); /* Close any fd's to the passwd database */ endpwent(); +#ifdef HAVE_CAP + if (cap_iab != NULL) { + i = cap_iab_set_proc(cap_iab); + + if (cap_free(cap_iab) != 0) + eerrorx("Could not releasable memory: %s", strerror(errno)); + + if (i != 0) + eerrorx("Could not set iab: %s", strerror(errno)); + } +#endif + #ifdef TIOCNOTTY ioctl(tty_fd, TIOCNOTTY, 0); close(tty_fd); diff --git a/src/rc/supervise-daemon.c b/src/rc/supervise-daemon.c index ddadb677..135fc902 100644 --- a/src/rc/supervise-daemon.c +++ b/src/rc/supervise-daemon.c @@ -57,6 +57,10 @@ static struct pam_conv conv = { NULL, NULL}; #endif +#ifdef HAVE_CAP +#include +#endif + #include "einfo.h" #include "queue.h" #include "rc.h" @@ -73,6 +77,7 @@ const char getoptstring[] = "A:a:D:d:e:g:H:I:Kk:m:N:p:R:r:s:Su:1:2:3" \ const struct option longopts[] = { { "healthcheck-timer", 1, NULL, 'a'}, { "healthcheck-delay", 1, NULL, 'A'}, + { "capabilities", 1, NULL, 0x100}, { "respawn-delay", 1, NULL, 'D'}, { "chdir", 1, NULL, 'd'}, { "env", 1, NULL, 'e'}, @@ -98,6 +103,7 @@ const struct option longopts[] = { const char * const longopts_help[] = { "set an initial health check delay", "set a health check timer", + "Set the inheritable, ambient and bounding capabilities", "Set a respawn delay", "Change the PWD", "Set an environment string", @@ -152,6 +158,9 @@ static int fifo_fd = 0; static char *pidfile = NULL; static char *svcname = NULL; static bool verbose = false; +#ifdef HAVE_CAP +static cap_iab_t cap_iab = NULL; +#endif extern char **environ; @@ -398,12 +407,28 @@ static void child_process(char *exec, char **argv) eerrorx("%s: unable to set groupid to %d", applet, gid); if (changeuser && initgroups(changeuser, gid)) eerrorx("%s: initgroups (%s, %d)", applet, changeuser, gid); +#ifdef HAVE_CAP + if (uid && cap_setuid(uid)) +#else if (uid && setuid(uid)) +#endif eerrorx ("%s: unable to set userid to %d", applet, uid); /* Close any fd's to the passwd database */ endpwent(); +#ifdef HAVE_CAP + if (cap_iab != NULL) { + i = cap_iab_set_proc(cap_iab); + + if (cap_free(cap_iab) != 0) + eerrorx("Could not releasable memory: %s", strerror(errno)); + + if (i != 0) + eerrorx("Could not set iab: %s", strerror(errno)); + } +#endif + /* remove the controlling tty */ #ifdef TIOCNOTTY ioctl(tty_fd, TIOCNOTTY, 0); @@ -797,6 +822,16 @@ int main(int argc, char **argv) eerrorx("%s: invalid health check delay %s", applet, optarg); break; + case 0x100: +#ifdef HAVE_CAP + cap_iab = cap_iab_from_text(optarg); + if (cap_iab == NULL) + eerrorx("Could not parse iab: %s", strerror(errno)); +#else + eerrorx("Capabilities support not enabled"); +#endif + break; + case 'D': /* --respawn-delay time */ n = sscanf(optarg, "%d", &respawn_delay); if (n != 1 || respawn_delay < 1) -- cgit v1.2.3