summaryrefslogtreecommitdiff
path: root/dbus/dbus-sysdeps.c
diff options
context:
space:
mode:
Diffstat (limited to 'dbus/dbus-sysdeps.c')
-rw-r--r--dbus/dbus-sysdeps.c95
1 files changed, 92 insertions, 3 deletions
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index 79f764d6..4092ae91 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -38,6 +38,13 @@
#include <sys/socket.h>
#include <dirent.h>
#include <sys/un.h>
+
+#ifdef HAVE_LIBAUDIT
+#include <sys/prctl.h>
+#include <sys/capability.h>
+#include <libaudit.h>
+#endif /* HAVE_LIBAUDIT */
+
#include <pwd.h>
#include <time.h>
#include <locale.h>
@@ -3281,6 +3288,55 @@ _dbus_change_identity (dbus_uid_t uid,
dbus_gid_t gid,
DBusError *error)
{
+ int priv = FALSE;
+
+#ifdef HAVE_LIBAUDIT
+ /* have a tmp set of caps that we use to transition to the usr/grp dbus should
+ * run as ... doesn't really help. But keeps people happy.
+ */
+ cap_t new_caps = NULL;
+
+ priv = !getuid();
+ if (priv)
+ {
+ cap_value_t new_cap_list[] = { CAP_AUDIT_WRITE };
+ cap_value_t tmp_cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID, CAP_SETGID };
+ cap_t tmp_caps = cap_init();
+
+ if (!tmp_caps || !(new_caps = cap_init()))
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Failed to initialize drop of capabilities\n");
+ if (tmp_caps)
+ cap_free(tmp_caps);
+ return FALSE;
+ }
+
+ /* assume these work... */
+ cap_set_flag(new_caps, CAP_PERMITTED, 1, new_cap_list, CAP_SET);
+ cap_set_flag(new_caps, CAP_EFFECTIVE, 1, new_cap_list, CAP_SET);
+ cap_set_flag(tmp_caps, CAP_PERMITTED, 3, tmp_cap_list, CAP_SET);
+ cap_set_flag(tmp_caps, CAP_EFFECTIVE, 3, tmp_cap_list, CAP_SET);
+
+ if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to set keep-capabilities: %s\n",
+ _dbus_strerror (errno));
+ cap_free(tmp_caps);
+ goto fail;
+ }
+ if (cap_set_proc(tmp_caps))
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Failed to drop capabilities\n");
+ cap_free(tmp_caps);
+ goto fail;
+ }
+ cap_free(tmp_caps);
+ }
+#endif /* HAVE_LIBAUDIT */
+
/* Set GID first, or the setuid may remove our permission
* to change the GID
*/
@@ -3289,7 +3345,7 @@ _dbus_change_identity (dbus_uid_t uid,
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to set GID to %lu: %s", gid,
_dbus_strerror (errno));
- return FALSE;
+ goto fail;
}
if (setuid (uid) < 0)
@@ -3297,10 +3353,43 @@ _dbus_change_identity (dbus_uid_t uid,
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to set UID to %lu: %s", uid,
_dbus_strerror (errno));
- return FALSE;
+ goto fail;
}
- return TRUE;
+#ifdef HAVE_LIBAUDIT
+ if (priv)
+ {
+ if (cap_set_proc(new_caps))
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Failed to drop capabilities\n");
+ goto fail;
+ }
+ cap_free(new_caps);
+
+ if (prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) == -1)
+ { /* should always work, if it did above */
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to unset keep-capabilities: %s\n",
+ _dbus_strerror (errno));
+ return FALSE;
+ }
+ }
+#endif
+
+ return TRUE;
+
+ fail:
+#ifdef HAVE_LIBAUDIT
+ if (priv)
+ {
+ /* should always work, if it did above */
+ prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
+ cap_free(new_caps);
+ }
+#endif
+ return FALSE;
+
}
/** Installs a UNIX signal handler