From: David Zeuthen Date: Fri, 25 May 2012 16:40:42 +0000 (-0400) Subject: Run polkitd as an unprivileged user X-Git-Tag: 0.106~13 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8e0383cb9972f5b3b86e64f9b015f53671ce0323;p=platform%2Fupstream%2Fpolkit.git Run polkitd as an unprivileged user There's really no reason to run all this code as uid 0. Signed-off-by: David Zeuthen --- diff --git a/configure.ac b/configure.ac index d9559cc..b26b333 100644 --- a/configure.ac +++ b/configure.ac @@ -193,6 +193,20 @@ if test "x$with_systemdsystemunitdir" != "xno"; then fi AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$systemdsystemunitdir"]) +dnl --------------------------------------------------------------------------- +dnl - User for running polkitd +dnl --------------------------------------------------------------------------- + +AC_ARG_WITH(polkitd_user, AS_HELP_STRING([--with-polkitd-user=],[User for running polkitd (polkitd)])) + +if test -z "$with_polkitd_user" ; then + POLKITD_USER=polkitd +else + POLKITD_USER=$with_polkitd_user +fi +AC_SUBST(POLKITD_USER) +AC_DEFINE_UNQUOTED(POLKITD_USER,"$POLKITD_USER", [User for running polkitd]) + dnl --------------------------------------------------------------------------- dnl - Select which authentication framework to use dnl --------------------------------------------------------------------------- @@ -496,7 +510,8 @@ echo " Authentication framework: ${POLKIT_AUTHFW} Session tracking: ${SESSION_TRACKING} PAM support: ${have_pam} - systemdsystemunitdir: ${systemdsystemunitdir}" + systemdsystemunitdir: ${systemdsystemunitdir} + polkitd user: ${POLKITD_USER}" if test "$have_pam" = yes ; then echo " @@ -522,10 +537,10 @@ echo "NOTE: The file ${bindir}/pkexec must be owned by root and" echo " have mode 4755 (setuid root binary)" echo -echo "NOTE: The directory ${sysconfdir}/polkit-1/rules.d" -echo " should have mode 700" +echo "NOTE: The directory ${sysconfdir}/polkit-1/rules.d must be owned" +echo " by user '$POLKITD_USER' and have mode 700" echo -echo "NOTE: The directory ${datadir}/polkit-1/rules.d" -echo " should have mode 700" +echo "NOTE: The directory ${datadir}/polkit-1/rules.d must be owned" +echo " by user '$POLKITD_USER' and have mode 700" echo diff --git a/data/Makefile.am b/data/Makefile.am index 6623286..b2d0cde 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -4,6 +4,8 @@ NULL = libprivdir = $(prefix)/lib/polkit-1 +# ---------------------------------------------------------------------------------------------------- + servicedir = $(datadir)/dbus-1/system-services service_in_files = org.freedesktop.PolicyKit1.service.in service_DATA = $(service_in_files:.service.in=.service) @@ -11,17 +13,28 @@ service_DATA = $(service_in_files:.service.in=.service) $(service_DATA): $(service_in_files) Makefile @sed -e "s|\@libprivdir\@|$(libprivdir)|" $< > $@ +# ---------------------------------------------------------------------------------------------------- + dbusconfdir = $(sysconfdir)/dbus-1/system.d -dbusconf_DATA = org.freedesktop.PolicyKit1.conf +dbusconf_in_files = org.freedesktop.PolicyKit1.conf.in +dbusconf_DATA = $(dbusconf_in_files:.conf.in=.conf) + +$(dbusconf_DATA): $(dbusconf_in_files) Makefile + @sed -e "s|\@polkitd_user\@|$(POLKITD_USER)|" $< > $@ + +# ---------------------------------------------------------------------------------------------------- if POLKIT_AUTHFW_PAM pamdir = $(sysconfdir)/pam.d pam_DATA = polkit-1 endif +# ---------------------------------------------------------------------------------------------------- + pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = polkit-gobject-1.pc polkit-backend-1.pc polkit-agent-1.pc +# ---------------------------------------------------------------------------------------------------- systemdservice_in_files = polkit.service.in @@ -32,16 +45,18 @@ $(systemdservice_DATA): $(systemdservice_in_files) Makefile @sed -e "s|\@libprivdir\@|$(libprivdir)|" $< > $@ endif +# ---------------------------------------------------------------------------------------------------- + CLEANFILES = $(BUILT_SOURCES) EXTRA_DIST = \ org.freedesktop.PolicyKit1.Authority.xml \ org.freedesktop.PolicyKit1.AuthenticationAgent.xml \ $(service_in_files) \ + $(dbusconf_in_files) \ $(systemdservice_in_files) \ - $(dbusconf_DATA) \ $(NULL) clean-local : - rm -f *~ $(service_DATA) $(systemdservice_DATA) + rm -f *~ $(service_DATA) $(dbusconf_DATA) $(systemdservice_DATA) diff --git a/data/org.freedesktop.PolicyKit1.conf b/data/org.freedesktop.PolicyKit1.conf deleted file mode 100644 index c8ef513..0000000 --- a/data/org.freedesktop.PolicyKit1.conf +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/data/org.freedesktop.PolicyKit1.conf.in b/data/org.freedesktop.PolicyKit1.conf.in new file mode 100644 index 0000000..c749207 --- /dev/null +++ b/data/org.freedesktop.PolicyKit1.conf.in @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml index bd39299..b19b92c 100644 --- a/docs/man/polkit.xml +++ b/docs/man/polkit.xml @@ -31,7 +31,16 @@ untrusted. For every request from a subject, the mechanism needs to determine if the request is authorized or if it should refuse to service the subject. Using the polkit APIs, a mechanism can - offload this decision to a trusted party: The polkit Authority. + offload this decision to a trusted party: The polkit authority. + + + + The polkit authority is implemented as an system daemon, + polkitd8, + which itself has little privilege as it is running as the + polkitd system user. Mechanisms, subjects + and authentication agents communicate with the authority using + the system message bus. @@ -204,7 +213,7 @@ System Context | | DECLARING ACTIONS - A mechanism need to declare a set of ACTIONS in + A mechanism need to declare a set of actions in order to use polkit. Actions correspond to operations that clients can request the mechanism to carry out and are defined in XML files that the mechanism installs into the spawn() method should be used sparingly as helpers may take a very long or indeterminate amount of time to complete and no other authorization check can be handled - while the helper is running. + while the helper is running. Note that the spawned programs + will run as the unprivileged polkitd system + user. diff --git a/docs/man/polkitd.xml b/docs/man/polkitd.xml index 879da2d..5fee8d4 100644 --- a/docs/man/polkitd.xml +++ b/docs/man/polkitd.xml @@ -40,6 +40,12 @@ whenever an application calls into the service. + + polkitd must be started with superuser + privileges but drops privileges early by switching to the + unprivileged polkitd system user. + + See the polkit8 diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am index a173125..9f430d0 100644 --- a/src/polkitbackend/Makefile.am +++ b/src/polkitbackend/Makefile.am @@ -103,8 +103,10 @@ dist-hook : clean-local : rm -f *~ $(BUILT_SOURCES) -install-exec-hook: +install-data-hook: mkdir -p $(DESTDIR)$(sysconfdir)/polkit-1/rules.d -chmod 700 $(DESTDIR)$(sysconfdir)/polkit-1/rules.d + -chown $(POLKITD_USER) $(DESTDIR)$(sysconfdir)/polkit-1/rules.d mkdir -p $(DESTDIR)$(datadir)/polkit-1/rules.d -chmod 700 $(DESTDIR)$(datadir)/polkit-1/rules.d + -chown $(POLKITD_USER) $(DESTDIR)$(datadir)/polkit-1/rules.d diff --git a/src/polkitbackend/polkitd.c b/src/polkitbackend/polkitd.c index 0bb3f32..6a1bfb0 100644 --- a/src/polkitbackend/polkitd.c +++ b/src/polkitbackend/polkitd.c @@ -25,6 +25,9 @@ #include +#include +#include + #include #include @@ -94,6 +97,63 @@ on_sigint (gpointer user_data) return FALSE; } +static gboolean +become_user (const gchar *user, + GError **error) +{ + gboolean ret = FALSE; + struct passwd *pw; + + g_return_val_if_fail (user != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + pw = getpwnam (user); + if (pw == NULL) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Error calling getpwnam(): %m"); + goto out; + } + + if (setgroups (0, NULL) != 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Error clearing groups: %m"); + goto out; + } + if (initgroups (pw->pw_name, pw->pw_gid) != 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Error initializing groups: %m"); + goto out; + } + + setregid (pw->pw_gid, pw->pw_gid); + setreuid (pw->pw_uid, pw->pw_uid); + if ((geteuid () != pw->pw_uid) || (getuid () != pw->pw_uid) || + (getegid () != pw->pw_gid) || (getgid () != pw->pw_gid)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Error becoming real+effective uid %d and gid %d: %m", + (int) pw->pw_uid, (int) pw->pw_gid); + goto out; + } + + if (chdir (pw->pw_dir) != 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Error changing to home directory %s: %m", + pw->pw_dir); + goto out; + } + + + ret = TRUE; + + out: + return ret; +} + int main (int argc, char **argv) @@ -142,6 +202,19 @@ main (int argc, } } + error = NULL; + if (!become_user (POLKITD_USER, &error)) + { + g_printerr ("Error switcing to user %s: %s\n", + POLKITD_USER, error->message); + g_clear_error (&error); + goto out; + } + + g_print ("Successfully changed to user %s\n", POLKITD_USER); + + if (g_getenv ("PATH") == NULL) + g_setenv ("PATH", "/usr/bin:/bin:/usr/sbin:/sbin", TRUE); loop = g_main_loop_new (NULL, FALSE);