/** * \brief Drop the previliges of the main thread */ void SCDropMainThreadCaps(uint32_t userid, uint32_t groupid) { if (sc_set_caps == FALSE) return; capng_clear(CAPNG_SELECT_BOTH); if (run_mode == MODE_PFRING || run_mode == MODE_NFQ) { capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_NET_RAW, /* needed for pcap live mode */ CAP_NET_ADMIN, /* needed for nfqueue inline mode */ -1); } else if (run_mode == MODE_PCAP_DEV) { capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_NET_RAW, /* needed for pcap live mode */ -1); } if (capng_change_id(userid, groupid, CAPNG_DROP_SUPP_GRP | CAPNG_CLEAR_BOUNDING) < 0) { SCLogError(SC_ERR_CHANGING_CAPS_FAILED, "capng_change_id for main thread" " failed"); exit(EXIT_FAILURE); } SCLogInfo("dropped the caps for main thread"); }
/* Linux specific implementation of daemon_become_new_user() * using libcap-ng. */ static void daemon_become_new_user_linux(bool access_datapath OVS_UNUSED) { #if defined __linux__ && HAVE_LIBCAPNG int ret; ret = capng_get_caps_process(); if (!ret) { if (capng_have_capabilities(CAPNG_SELECT_CAPS) > CAPNG_NONE) { const capng_type_t cap_sets = CAPNG_EFFECTIVE|CAPNG_PERMITTED; capng_clear(CAPNG_SELECT_BOTH); ret = capng_update(CAPNG_ADD, cap_sets, CAP_IPC_LOCK) || capng_update(CAPNG_ADD, cap_sets, CAP_NET_BIND_SERVICE); if (access_datapath && !ret) { ret = capng_update(CAPNG_ADD, cap_sets, CAP_NET_ADMIN) || capng_update(CAPNG_ADD, cap_sets, CAP_NET_RAW) || capng_update(CAPNG_ADD, cap_sets, CAP_NET_BROADCAST); } } else { ret = -1; } } if (!ret) { /* CAPNG_INIT_SUPP_GRP will be a better choice than * CAPNG_DROP_SUPP_GRP. However this enum value is only defined * with libcap-ng higher than version 0.7.4, which is not wildly * available on many Linux distributions yet. Taking a more * conservative approach to make sure OVS behaves consistently. * * XXX We may change this for future OVS releases. */ ret = capng_change_id(uid, gid, CAPNG_DROP_SUPP_GRP | CAPNG_CLEAR_BOUNDING); } if (ret) { VLOG_FATAL("%s: libcap-ng fail to switch to user and group " "%d:%d, aborting", pidfile, uid, gid); } #endif }
static void switch_environment(void) { #ifdef HAVE_GETEUID if ((runas_string || chroot_string) && geteuid() != 0) errx(1, "no running as root, can't switch user/chroot"); if (chroot_string) { if (chroot(chroot_string)) err(1, "chroot(%s) failed", chroot_string); if (chdir("/")) err(1, "chdir(/) after chroot failed"); } if (runas_string) { struct passwd *pw; pw = getpwnam(runas_string); if (pw == NULL) errx(1, "unknown user %s", runas_string); if (initgroups(pw->pw_name, pw->pw_gid) < 0) err(1, "initgroups failed"); #ifndef HAVE_CAPNG if (setgid(pw->pw_gid) < 0) err(1, "setgid(%s) failed", runas_string); if (setuid(pw->pw_uid) < 0) err(1, "setuid(%s)", runas_string); #else capng_clear (CAPNG_EFFECTIVE | CAPNG_PERMITTED); if (capng_updatev (CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_NET_BIND_SERVICE, CAP_SETPCAP, -1) < 0) err(1, "capng_updateev"); if (capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_CLEAR_BOUNDING) < 0) err(1, "capng_change_id(%s)", runas_string); #endif } #endif }
int switch_user(uid_t uid, gid_t gid) { capng_clear(CAPNG_SELECT_BOTH); return capng_change_id(uid, gid, CAPNG_INIT_SUPP_GRP | CAPNG_CLEAR_BOUNDING); }
/** * 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; } /* If we were root */ if (_dbus_geteuid () == 0) { int rc; int have_audit_write; have_audit_write = capng_have_capability (CAPNG_PERMITTED, CAP_AUDIT_WRITE); capng_clear (CAPNG_SELECT_BOTH); /* Only attempt to retain CAP_AUDIT_WRITE if we had it when * starting. See: * https://bugs.freedesktop.org/show_bug.cgi?id=49062#c9 */ if (have_audit_write) capng_update (CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_AUDIT_WRITE); rc = capng_change_id (uid, gid, CAPNG_DROP_SUPP_GRP); 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; } } return TRUE; }
int main(int argc, char *argv[]) { int which = 0, i; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--text") == 0) text = 1; else if (strcmp(argv[i], "--no-child") == 0) no_child = 1; else if (strcmp(argv[i], "--lock") == 0) lock = 1; else if (strcmp(argv[i], "--drop-all") == 0) which = 1; else if (strcmp(argv[i], "--drop-caps") == 0) which = 2; else if (strcmp(argv[i], "--id") == 0) which = 3; else if (strcmp(argv[i], "--init-grp") == 0) which = 4; else { usage(); return 0; } } switch (which) { case 1: capng_clear(CAPNG_SELECT_BOTH); if (lock) capng_lock(); capng_apply(CAPNG_SELECT_BOTH); report(); break; case 2: capng_clear(CAPNG_SELECT_CAPS); if (lock) capng_lock(); capng_apply(CAPNG_SELECT_CAPS); report(); break; case 3: case 4: { int rc; capng_clear(CAPNG_SELECT_BOTH); capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_CHOWN); if (which == 4) rc = capng_change_id(99, 99, CAPNG_INIT_SUPP_GRP | CAPNG_CLEAR_BOUNDING); else rc = capng_change_id(99, 99, CAPNG_DROP_SUPP_GRP | CAPNG_CLEAR_BOUNDING); if (rc < 0) { printf("Error changing uid: %d\n", rc); capng_print_caps_text(CAPNG_PRINT_STDOUT, CAPNG_EFFECTIVE); printf("\n"); exit(1); } printf("Keeping CAP_CHOWN to show capabilities across uid change.\n"); report(); } break; case 0: if (lock) capng_lock(); report(); break; } return 0; }