*/
#include <dbus/dbus-internals.h>
#include <dbus/dbus-string.h>
+#include <dbus/dbus-userdb.h>
#include "selinux.h"
#include "services.h"
#include "policy.h"
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
+#include <grp.h>
#ifdef HAVE_LIBAUDIT
+#include <cap-ng.h>
#include <libaudit.h>
#endif /* HAVE_LIBAUDIT */
#endif /* HAVE_SELINUX */
#ifdef HAVE_LIBAUDIT
if (audit_fd >= 0)
{
- char buf[PATH_MAX*2];
+ capng_get_caps_process();
+ if (capng_have_capability(CAPNG_EFFECTIVE, CAP_AUDIT_WRITE))
+ {
+ char buf[PATH_MAX*2];
- /* FIXME: need to change this to show real user */
- vsnprintf(buf, sizeof(buf), fmt, ap);
- audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL,
+ /* FIXME: need to change this to show real user */
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL,
NULL, getuid());
- return;
+ return;
+ }
}
#endif /* HAVE_LIBAUDIT */
#endif /* HAVE_SELINUX */
}
+/**
+ * Changes the user and group the bus is running as.
+ *
+ * @param user the user to become
+ * @param error return location for errors
+ * @returns #FALSE on failure
+ */
+dbus_bool_t
+_dbus_change_to_daemon_user (const char *user,
+ DBusError *error)
+{
+ dbus_uid_t uid;
+ dbus_gid_t gid;
+ DBusString u;
+
+ _dbus_string_init_const (&u, user);
+
+ if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "User '%s' does not appear to exist?",
+ user);
+ return FALSE;
+ }
+
+#ifdef HAVE_LIBAUDIT
+ /* If we were root */
+ if (_dbus_geteuid () == 0)
+ {
+ int rc;
+
+ capng_clear (CAPNG_SELECT_BOTH);
+ capng_update (CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED,
+ CAP_AUDIT_WRITE);
+ rc = capng_change_id (uid, gid, 0);
+ if (rc)
+ {
+ switch (rc) {
+ default:
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Failed to drop capabilities: %s\n",
+ _dbus_strerror (errno));
+ break;
+ case -4:
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to set GID to %lu: %s", gid,
+ _dbus_strerror (errno));
+ break;
+ case -5:
+ _dbus_warn ("Failed to drop supplementary groups: %s\n",
+ _dbus_strerror (errno));
+ break;
+ case -6:
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to set UID to %lu: %s", uid,
+ _dbus_strerror (errno));
+ break;
+ case -7:
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to unset keep-capabilities: %s\n",
+ _dbus_strerror (errno));
+ break;
+ }
+ return FALSE;
+ }
+ }
+#else
+ /* setgroups() only works if we are a privileged process,
+ * so we don't return error on failure; the only possible
+ * failure is that we don't have perms to do it.
+ *
+ * not sure this is right, maybe if setuid()
+ * is going to work then setgroups() should also work.
+ */
+ if (setgroups (0, NULL) < 0)
+ _dbus_warn ("Failed to drop supplementary groups: %s\n",
+ _dbus_strerror (errno));
+
+ /* Set GID first, or the setuid may remove our permission
+ * to change the GID
+ */
+ if (setgid (gid) < 0)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to set GID to %lu: %s", gid,
+ _dbus_strerror (errno));
+ return FALSE;
+ }
+
+ if (setuid (uid) < 0)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to set UID to %lu: %s", uid,
+ _dbus_strerror (errno));
+ return FALSE;
+ }
+#endif /* !HAVE_LIBAUDIT */
+
+ return TRUE;
+}
+
void bus_selinux_audit_init(void);
+dbus_bool_t _dbus_change_to_daemon_user (const char *user,
+ DBusError *error);
#endif /* BUS_SELINUX_H */
AC_CHECK_LIB(audit, audit_log_user_avc_message,
have_libaudit=yes, have_libaudit=no)
if test x$have_libaudit = xyes ; then
- AC_CHECK_LIB(cap, cap_set_proc,
+ AC_CHECK_LIB(cap-ng, capng_clear,
have_libaudit=yes, have_libaudit=no)
fi
fi
AM_CONDITIONAL(HAVE_LIBAUDIT, test x$have_libaudit = xyes)
if test x$have_libaudit = xyes ; then
- SELINUX_LIBS="$SELINUX_LIBS -laudit"
- LIBS="-lcap $LIBS"
+ SELINUX_LIBS="$SELINUX_LIBS -laudit -lcap-ng"
AC_DEFINE(HAVE_LIBAUDIT,1,[audit daemon SELinux support])
fi
#include <dirent.h>
#include <sys/un.h>
#include <syslog.h>
-#ifdef HAVE_LIBAUDIT
-#include <sys/prctl.h>
-#include <sys/capability.h>
-#include <libaudit.h>
-#endif /* HAVE_LIBAUDIT */
#ifdef HAVE_SYS_SYSLIMITS_H
#include <sys/syslimits.h>
return _dbus_get_user_id_and_primary_group (&u, NULL, NULL);
}
-/**
- * Changes the user and group the bus is running as.
- *
- * @param user the user to become
- * @param error return location for errors
- * @returns #FALSE on failure
- */
-dbus_bool_t
-_dbus_change_to_daemon_user (const char *user,
- DBusError *error)
-{
- dbus_uid_t uid;
- dbus_gid_t gid;
- DBusString u;
-#ifdef HAVE_LIBAUDIT
- dbus_bool_t we_were_root;
- cap_t new_caps;
-#endif
-
- _dbus_string_init_const (&u, user);
-
- if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
- {
- dbus_set_error (error, DBUS_ERROR_FAILED,
- "User '%s' does not appear to exist?",
- user);
- return FALSE;
- }
-
-#ifdef HAVE_LIBAUDIT
- we_were_root = _dbus_geteuid () == 0;
- new_caps = NULL;
- /* 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.
- */
-
- if (we_were_root)
- {
- 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: %s\n",
- _dbus_strerror (errno));
-
- 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) == -1)
- {
- dbus_set_error (error, DBUS_ERROR_FAILED,
- "Failed to drop capabilities: %s\n",
- _dbus_strerror (errno));
- cap_free (tmp_caps);
- goto fail;
- }
- cap_free (tmp_caps);
- }
-#endif /* HAVE_LIBAUDIT */
-
- /* setgroups() only works if we are a privileged process,
- * so we don't return error on failure; the only possible
- * failure is that we don't have perms to do it.
- *
- * not sure this is right, maybe if setuid()
- * is going to work then setgroups() should also work.
- */
- if (setgroups (0, NULL) < 0)
- _dbus_warn ("Failed to drop supplementary groups: %s\n",
- _dbus_strerror (errno));
-
- /* Set GID first, or the setuid may remove our permission
- * to change the GID
- */
- if (setgid (gid) < 0)
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Failed to set GID to %lu: %s", gid,
- _dbus_strerror (errno));
- goto fail;
- }
-
- if (setuid (uid) < 0)
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Failed to set UID to %lu: %s", uid,
- _dbus_strerror (errno));
- goto fail;
- }
-
-#ifdef HAVE_LIBAUDIT
- if (we_were_root)
- {
- if (cap_set_proc (new_caps))
- {
- dbus_set_error (error, DBUS_ERROR_FAILED,
- "Failed to drop capabilities: %s\n",
- _dbus_strerror (errno));
- goto fail;
- }
- cap_free (new_caps);
-
- /* should always work, if it did above */
- if (prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0) == -1)
- {
- 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 (!we_were_root)
- {
- /* should always work, if it did above */
- prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0);
- cap_free (new_caps);
- }
-#endif
-
- return FALSE;
-}
-
void
_dbus_init_system_log (void)
{
dbus_bool_t keep_umask);
dbus_bool_t _dbus_verify_daemon_user (const char *user);
-dbus_bool_t _dbus_change_to_daemon_user (const char *user,
- DBusError *error);
dbus_bool_t _dbus_write_pid_to_file_and_pipe (const DBusString *pidfile,
DBusPipe *print_pid_pipe,