void drop_caps(const struct minijail *j) { cap_t caps = cap_get_proc(); cap_value_t flag[1]; const uint64_t one = 1; unsigned int i; if (!caps) die("can't get process caps"); if (cap_clear_flag(caps, CAP_INHERITABLE)) die("can't clear inheritable caps"); if (cap_clear_flag(caps, CAP_EFFECTIVE)) die("can't clear effective caps"); if (cap_clear_flag(caps, CAP_PERMITTED)) die("can't clear permitted caps"); for (i = 0; i < sizeof(j->caps) * 8 && run_cap_valid(i); ++i) { /* Keep CAP_SETPCAP for dropping bounding set bits. */ if (i != CAP_SETPCAP && !(j->caps & (one << i))) continue; flag[0] = i; if (cap_set_flag(caps, CAP_EFFECTIVE, 1, flag, CAP_SET)) die("can't add effective cap"); if (cap_set_flag(caps, CAP_PERMITTED, 1, flag, CAP_SET)) die("can't add permitted cap"); if (cap_set_flag(caps, CAP_INHERITABLE, 1, flag, CAP_SET)) die("can't add inheritable cap"); } if (cap_set_proc(caps)) die("can't apply initial cleaned capset"); /* * Instead of dropping bounding set first, do it here in case * the caller had a more permissive bounding set which could * have been used above to raise a capability that wasn't already * present. This requires CAP_SETPCAP, so we raised/kept it above. */ for (i = 0; i < sizeof(j->caps) * 8 && run_cap_valid(i); ++i) { if (j->caps & (one << i)) continue; if (prctl(PR_CAPBSET_DROP, i)) pdie("prctl(PR_CAPBSET_DROP)"); } /* If CAP_SETPCAP wasn't specifically requested, now we remove it. */ if ((j->caps & (one << CAP_SETPCAP)) == 0) { flag[0] = CAP_SETPCAP; if (cap_set_flag(caps, CAP_EFFECTIVE, 1, flag, CAP_CLEAR)) die("can't clear effective cap"); if (cap_set_flag(caps, CAP_PERMITTED, 1, flag, CAP_CLEAR)) die("can't clear permitted cap"); if (cap_set_flag(caps, CAP_INHERITABLE, 1, flag, CAP_CLEAR)) die("can't clear inheritable cap"); } if (cap_set_proc(caps)) die("can't apply final cleaned capset"); cap_free(caps); }
/* run during request cleanup */ static apr_status_t ruid_suidback (void *data) { request_rec *r = data; ruid_config_t *conf = ap_get_module_config (r->server->module_config, &ruid2_module); core_server_config *core = (core_server_config *) ap_get_module_config(r->server->module_config, &core_module); cap_t cap; cap_value_t capval[3]; if (cap_mode == RUID_CAP_MODE_KEEP) { cap=cap_get_proc(); capval[0]=CAP_SETUID; capval[1]=CAP_SETGID; capval[2]=CAP_SYS_CHROOT; cap_set_flag(cap, CAP_EFFECTIVE, (conf->chroot_dir ? 3 : 2), capval, CAP_SET); if (cap_set_proc(cap)!=0) { ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s CRITICAL ERROR %s:cap_set_proc failed before setuid", MODULE_NAME, __func__); } cap_free(cap); setgroups(startup_groupsnr, startup_groups); setgid(ap_unixd_config.group_id); setuid(ap_unixd_config.user_id); /* set httpd process dumpable after setuid */ if (coredump) { prctl(PR_SET_DUMPABLE,1); } /* jail break */ if (conf->chroot_dir) { if (fchdir(root_handle) < 0) { ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s failed to fchdir to root dir (%d) (%s)", MODULE_NAME, root_handle, strerror(errno)); } else { if (chroot(".") != 0) { ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s jail break failed", MODULE_NAME); } } core->ap_document_root = old_root; } cap=cap_get_proc(); capval[0]=CAP_SETUID; capval[1]=CAP_SETGID; capval[2]=CAP_SYS_CHROOT; cap_set_flag(cap, CAP_EFFECTIVE, 3, capval, CAP_CLEAR); if (cap_set_proc(cap)!=0) { ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s CRITICAL ERROR %s:cap_set_proc failed after setuid", MODULE_NAME, __func__); } cap_free(cap); } return DECLINED; }
/*-------------------------------------------------------------------*/ DLL_EXPORT int drop_privileges(int capa) { uid_t uid; gid_t gid; cap_t c; int rc; int failed; cap_value_t v; int have_capt; /* If *real* userid is root, no need to do all this */ uid=getuid(); if(!uid) return 0; failed=1; have_capt=0; do { c=cap_init(); if(!c) break; have_capt=1; v=capa; rc=cap_set_flag(c,CAP_EFFECTIVE,1,&v,CAP_SET); if(rc<0) break; rc=cap_set_flag(c,CAP_INHERITABLE,1,&v,CAP_SET); if(rc<0) break; rc=cap_set_flag(c,CAP_PERMITTED,1,&v,CAP_SET); if(rc<0) break; rc=cap_set_proc(c); if(rc<0) break; rc=prctl(PR_SET_KEEPCAPS,1); if(rc<0) break; failed=0; } while(0); gid=getgid(); setregid(gid,gid); setreuid(uid,uid); if(!failed) { rc=cap_set_proc(c); if(rc<0) failed=1; } if(have_capt) cap_free(c); return failed; }
int limit_capabilities(void) { cap_t cap_p; const cap_value_t caps[] = { CAP_NET_ADMIN, CAP_NET_RAW, }; int i; cap_p = cap_init(); if (!cap_p) { perror("cap_get_proc"); return -1; } for (i = 0; i < ARRAY_SIZE(caps); i++) { if (cap_clear(cap_p) < 0) { perror("cap_clear"); return -1; } if (cap_set_flag(cap_p, CAP_PERMITTED, ARRAY_SIZE(caps) - i, caps + i, CAP_SET) < 0) { perror("cap_set_flag"); return -1; } if (cap_set_proc(cap_p) < 0) continue; break; } if (i == ARRAY_SIZE(caps)) { perror("cap_set_proc"); if (errno != EPERM) return -1; } if (prctl(PR_SET_KEEPCAPS, 1) < 0) { perror("prctl"); return -1; } if (setuid(getuid()) < 0) { perror("setuid"); return -1; } if (prctl(PR_SET_KEEPCAPS, 0) < 0) { perror("prctl"); return -1; } cap_free(cap_p); uid = getuid(); euid = geteuid(); return 0; }
int modify_capability(cap_value_t cap, cap_flag_value_t on) { cap_t cap_p = cap_get_proc(); if (!cap_p) { perror("cap_get_proc"); return -1; } if (cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &cap, on) < 0) { perror("cap_set_flag"); return -1; } if (cap_set_proc(cap_p) < 0) { perror("cap_set_proc"); return -1; } if (cap_free(cap_p) < 0) { perror("cap_free"); return -1; } return 0; }
/************************************************************************** Try and abstract process capabilities (for systems that have them). ****************************************************************************/ static BOOL set_process_capability( uint32 cap_flag, BOOL enable ) { if(cap_flag == KERNEL_OPLOCK_CAPABILITY) { cap_t cap = cap_get_proc(); if (cap == NULL) { DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n", strerror(errno))); return False; } if(enable) cap->cap_effective |= CAP_NETWORK_MGT; else cap->cap_effective &= ~CAP_NETWORK_MGT; if (cap_set_proc(cap) == -1) { DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n", strerror(errno))); cap_free(cap); return False; } cap_free(cap); DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n")); } return True; }
void UnixMurmur::finalcap() { #ifdef Q_OS_LINUX cap_value_t caps[] = {CAP_SYS_RESOURCE}; struct rlimit r; if (! bRoot) return; if (getrlimit(RLIMIT_RTPRIO, &r) != 0) { qCritical("Failed to get priority limits."); } else { qWarning("Resource limits were %ld %ld", r.rlim_cur, r.rlim_max); r.rlim_cur = r.rlim_max = 1; if (setrlimit(RLIMIT_RTPRIO, &r) != 0) { qCritical("Failed to set priority limits."); } } int ncap = sizeof(caps)/sizeof(cap_value_t); cap_t c = cap_init(); cap_clear(c); cap_set_flag(c, CAP_EFFECTIVE, ncap, caps, CAP_SET); cap_set_flag(c, CAP_PERMITTED, ncap, caps, CAP_SET); if (cap_set_proc(c) != 0) { qCritical("Failed to set final capabilities"); } else { qWarning("Successfully dropped capabilities"); } cap_free(c); #endif }
static int bin_cap(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) { int ret = 0; cap_t caps; if(*argv) { unmetafy(*argv, NULL); caps = cap_from_text(*argv); if(!caps) { zwarnnam(nam, "invalid capability string"); return 1; } if(cap_set_proc(caps)) { zwarnnam(nam, "can't change capabilities: %e", errno); ret = 1; } } else { char *result = NULL; ssize_t length; caps = cap_get_proc(); if(caps) result = cap_to_text(caps, &length); if(!caps || !result) { zwarnnam(nam, "can't get capabilities: %e", errno); ret = 1; } else puts(result); } cap_free(caps); return ret; }
/*-------------------------------------------------------------------*/ DLL_EXPORT int drop_all_caps(void) { uid_t uid; cap_t c; int rc; int failed; int have_capt; /* If *real* userid is root, no need to do all this */ uid=getuid(); if(!uid) return 0; failed=1; have_capt=0; do { c=cap_from_text("all-eip"); if(!c) break; have_capt=1; rc=cap_set_proc(c); if(rc<0) break; failed=0; } while(0); if(have_capt) cap_free(c); return failed; }
static bool setMinimalCapabilities() { cap_t cap_d = cap_init(); if (cap_d != nullptr) { cap_value_t cap_list[] = {CAP_NET_BIND_SERVICE, CAP_SYS_RESOURCE, CAP_SYS_NICE}; cap_clear(cap_d); if (cap_set_flag(cap_d, CAP_PERMITTED, 3, cap_list, CAP_SET) < 0 || cap_set_flag(cap_d, CAP_EFFECTIVE, 3, cap_list, CAP_SET) < 0) { Logger::Error("cap_set_flag failed"); return false; } if (cap_set_proc(cap_d) == -1) { Logger::Error("cap_set_proc failed"); return false; } if (cap_free(cap_d) == -1) { Logger::Error("cap_free failed"); return false; } prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); return true; } return false; }
int avahi_caps_reduce2(void) { int ret = 0; cap_t caps; static cap_value_t cap_values[] = { CAP_SYS_CHROOT }; /* Reduce our caps to the bare minimum and tell Linux not to keep * them across setuid(). This is called after we drop * privileges. */ /* No longer retain caps across setuid() */ if (prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) < 0) { avahi_log_error("prctl(PR_SET_KEEPCAPS) failed: %s", strerror(errno)); ret = -1; } caps = cap_init(); assert(caps); cap_clear(caps); /* setuid() zeroed our effective caps, let's get them back */ cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_values, CAP_SET); cap_set_flag(caps, CAP_PERMITTED, 1, cap_values, CAP_SET); if (cap_set_proc(caps) < 0) { avahi_log_error("cap_set_proc() failed: %s", strerror(errno)); ret = -1; } cap_free(caps); return ret; }
int avahi_caps_reduce(void) { int ret = 0; cap_t caps; static cap_value_t cap_values[] = { CAP_SYS_CHROOT, CAP_SETUID, CAP_SETGID }; /* Let's reduce our caps to the minimum set and tell Linux to keep * them across setuid(). This is called before we drop * privileges. */ caps = cap_init(); assert(caps); cap_clear(caps); cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_values, CAP_SET); cap_set_flag(caps, CAP_PERMITTED, 3, cap_values, CAP_SET); if (cap_set_proc(caps) < 0) { avahi_log_error("cap_set_proc() failed: %s", strerror(errno)); ret = -1; } cap_free(caps); /* Retain capabilities across setuid() */ if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) { avahi_log_error("prctl(PR_SET_KEEPCAPS) failed: %s", strerror(errno)); ret = -1; } return ret; }
/** * cap_restore: * @r: capability set saved by cap_save() * * Restore the set of current capabilities specified by @r. * * Returns: whether the operation was successful. **/ void g_process_cap_restore(cap_t r) { gboolean rc; if (!process_opts.caps) return; rc = cap_set_proc(r) != -1; cap_free(r); if (!rc) { gchar *cap_text; cap_text = cap_to_text(r, NULL); msg_error("Error managing capability set, cap_set_proc returned an error", evt_tag_str("caps", cap_text), evt_tag_errno("error", errno), NULL); cap_free(cap_text); return; } return; }
// Setting linux capabilities (permitted, effective and inheritable) for the current process. // Permitted set indicates the capabilities what could be set for the process. // Effective set is a subset of permitted set, they are actually effective. // Inheritable set indicates the capabilities what the children will inherit from the current process. static bool setCapabilities(cap_value_t* capabilityList, int length) { // Capabilities should be initialized without flags. cap_t capabilities = cap_init(); if (!capabilities) { fprintf(stderr, "Failed to initialize process capabilities: %s.\n", strerror(errno)); return false; } if (cap_clear(capabilities) == -1) { fprintf(stderr, "Failed to clear process capabilities: %s.\n", strerror(errno)); return false; } if (capabilityList && length) { if (cap_set_flag(capabilities, CAP_EFFECTIVE, length, capabilityList, CAP_SET) == -1 || cap_set_flag(capabilities, CAP_INHERITABLE, length, capabilityList, CAP_SET) == -1 || cap_set_flag(capabilities, CAP_PERMITTED, length, capabilityList, CAP_SET) == -1) { fprintf(stderr, "Failed to set process capability flags: %s.\n", strerror(errno)); cap_free(capabilities); return false; } } if (cap_set_proc(capabilities) == -1) { fprintf(stderr, "Failed to set process capabilities: %s.\n", strerror(errno)); cap_free(capabilities); return false; } cap_free(capabilities); return true; }
void UnixMurmur::initialcap() { #ifdef Q_OS_LINUX cap_value_t caps[] = {CAP_NET_ADMIN, CAP_SETUID, CAP_SETGID, CAP_CHOWN, CAP_SYS_RESOURCE, CAP_DAC_OVERRIDE }; if (! bRoot) return; int ncap = sizeof(caps)/sizeof(cap_value_t); if (geteuid() != 0) ncap--; cap_t c = cap_init(); cap_clear(c); cap_set_flag(c, CAP_EFFECTIVE, ncap, caps, CAP_SET); cap_set_flag(c, CAP_INHERITABLE, ncap, caps, CAP_SET); cap_set_flag(c, CAP_PERMITTED, ncap, caps, CAP_SET); if (cap_set_proc(c) != 0) { qCritical("Failed to set initial capabilities"); } else { prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); } cap_free(c); #endif }
/** * g_process_change_caps: * * Change the current capset to the value specified by the user. causes the * startup process to fail if this function returns FALSE, but we only do * this if the capset cannot be parsed, otherwise a failure changing the * capabilities will not result in failure * * Returns: TRUE to indicate success **/ static gboolean g_process_change_caps(void) { if (g_process_is_cap_enabled()) { cap_t cap = cap_from_text(process_opts.caps); if (cap == NULL) { g_process_message("Error parsing capabilities: %s", process_opts.caps); process_opts.caps = NULL; process_opts.enable_caps = FALSE; return FALSE; } else { if (cap_set_proc(cap) == -1) { g_process_message("Error setting capabilities, capability management disabled; error='%s'", g_strerror(errno)); process_opts.caps = NULL; process_opts.enable_caps = FALSE; } cap_free(cap); } } return TRUE; }
int modify_cap (int capability, int setting) { cap_t caps; cap_value_t capList[1]; caps = cap_get_proc (); if (caps == NULL) return -1; capList[0] = capability; if (cap_set_flag (caps, CAP_EFFECTIVE, 1, capList, setting) == -1) { cap_free (caps); return -1; } if (cap_set_proc (caps) == -1) { cap_free (caps); return -1; } if (cap_free (caps) == -1) return -1; return 0; }
static int issueReinit() { cap_t caps = cap_init(); (void)cap_clear(caps); (void)cap_set_proc(caps); (void)cap_free(caps); int sock = TEMP_FAILURE_RETRY(socket_local_client( "logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM)); if (sock < 0) return -errno; static const char reinitStr[] = "reinit"; ssize_t ret = TEMP_FAILURE_RETRY(write(sock, reinitStr, sizeof(reinitStr))); if (ret < 0) return -errno; struct pollfd p; memset(&p, 0, sizeof(p)); p.fd = sock; p.events = POLLIN; ret = TEMP_FAILURE_RETRY(poll(&p, 1, 1000)); if (ret < 0) return -errno; if ((ret == 0) || !(p.revents & POLLIN)) return -ETIME; static const char success[] = "success"; char buffer[sizeof(success) - 1]; memset(buffer, 0, sizeof(buffer)); ret = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer))); if (ret < 0) return -errno; return strncmp(buffer, success, sizeof(success) - 1) != 0; }
static int sysnet_get_permissions() { cap_t caps = cap_get_proc(); if (caps == NULL) { perror("cap_get_proc()"); return errno; } cap_value_t cap_list = CAP_NET_ADMIN; int error = 0; if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_list, CAP_SET) == -1) { error = errno; perror("cap_set_flags(CAP_NET_ADMIN)"); } if (cap_set_proc(caps) == -1) { error = errno; perror("cap_set_proc(CAP_NET_ADMIN)"); } if (cap_free(caps) == -1) { error = errno; perror("cap_free()"); } return error; }
static bool set_inherited_process_capability( uint32_t cap_flag, bool enable ) { if(cap_flag == KERNEL_OPLOCK_CAPABILITY) { cap_t cap = cap_get_proc(); if (cap == NULL) { DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n", strerror(errno))); return false; } if(enable) cap->cap_inheritable |= CAP_NETWORK_MGT; else cap->cap_inheritable &= ~CAP_NETWORK_MGT; if (cap_set_proc(cap) == -1) { DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n", strerror(errno))); cap_free(cap); return false; } cap_free(cap); DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n")); } return true; }
/* Returns 1 if memory was locked, 0 if not. */ int secmem_init( size_t n ) { if( !n ) { #ifndef __riscos__ #ifdef USE_CAPABILITIES /* drop all capabilities */ cap_set_proc( cap_from_text("all-eip") ); #elif !defined(HAVE_DOSISH_SYSTEM) uid_t uid; disable_secmem=1; uid = getuid(); if( uid != geteuid() ) { if( setuid( uid ) || getuid() != geteuid() || !setuid(0) ) log_fatal("failed to drop setuid\n" ); } #endif #endif /* !__riscos__ */ } else { if( n < DEFAULT_POOLSIZE ) n = DEFAULT_POOLSIZE; if( !pool_okay ) init_pool(n); else log_error("Oops, secure memory pool already initialized\n"); } return !show_warning; }
int lxc_caps_down(void) { cap_t caps; int ret; /* when we are run as root, we don't want to play * with the capabilities */ if (!getuid()) return 0; caps = cap_get_proc(); if (!caps) { ERROR("failed to cap_get_proc: %m"); return -1; } ret = cap_clear_flag(caps, CAP_EFFECTIVE); if (ret) { ERROR("failed to cap_clear_flag: %m"); goto out; } ret = cap_set_proc(caps); if (ret) { ERROR("failed to cap_set_proc: %m"); goto out; } out: cap_free(caps); return 0; }
void vsf_sysdep_adopt_capabilities(unsigned int caps) { int retval; cap_value_t cap_value; cap_t adopt_caps = cap_init(); if (caps & kCapabilityCAP_CHOWN) { cap_value = CAP_CHOWN; cap_set_flag(adopt_caps, CAP_EFFECTIVE, 1, &cap_value, CAP_SET); cap_set_flag(adopt_caps, CAP_PERMITTED, 1, &cap_value, CAP_SET); } if (caps & kCapabilityCAP_NET_BIND_SERVICE) { cap_value = CAP_NET_BIND_SERVICE; cap_set_flag(adopt_caps, CAP_EFFECTIVE, 1, &cap_value, CAP_SET); cap_set_flag(adopt_caps, CAP_PERMITTED, 1, &cap_value, CAP_SET); } retval = cap_set_proc(adopt_caps); if (retval != 0) { die("cap_set_proc"); } cap_free(adopt_caps); }
PyObject* do_set_cap(PyObject *self, PyObject *args) { const char *cap_text; cap_t caps; if (!PyArg_ParseTuple(args, "s", &cap_text)) { return NULL; } caps = cap_from_text(cap_text); if (!caps) { PyErr_SetFromErrno(ImmunityException); return NULL; } if (cap_set_proc(caps) == -1) { PyErr_SetFromErrno(ImmunityException); return NULL; } if (cap_free(caps)) { PyErr_SetFromErrno(ImmunityException); return NULL; } Py_INCREF(Py_None); return Py_None; }
int modify_capability(cap_value_t cap, cap_flag_value_t on) { cap_t cap_p = cap_get_proc(); cap_flag_value_t cap_ok; int rc = -1; if (!cap_p) { perror("ping: cap_get_proc"); goto out; } cap_ok = CAP_CLEAR; cap_get_flag(cap_p, cap, CAP_PERMITTED, &cap_ok); if (cap_ok == CAP_CLEAR) { rc = on ? -1 : 0; goto out; } cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &cap, on); if (cap_set_proc(cap_p) < 0) { perror("ping: cap_set_proc"); goto out; } cap_free(cap_p); rc = 0; out: if (cap_p) cap_free(cap_p); return rc; }
/* run in map_to_storage hook */ static int ruid_uiiii (request_rec *r) { if (!ap_is_initial_req(r)) { return DECLINED; } int retval = ruid_set_perm(r, __func__); int ncap; cap_t cap; cap_value_t capval[4]; /* clear capabilities from permitted set (permanent) */ if (cap_mode == RUID_CAP_MODE_DROP) { cap=cap_get_proc(); capval[0]=CAP_SETUID; capval[1]=CAP_SETGID; capval[2]=CAP_DAC_READ_SEARCH; ncap = 2; if (root_handle == UNSET) capval[ncap++] = CAP_SYS_CHROOT; cap_set_flag(cap,CAP_PERMITTED,ncap,capval,CAP_CLEAR); if (cap_set_proc(cap)!=0) { ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s CRITICAL ERROR %s:cap_set_proc failed after setuid", MODULE_NAME, __func__); retval = HTTP_FORBIDDEN; } cap_free(cap); } return retval; }
int drop_capabilities(void) { cap_t cap = cap_init(); if (cap_set_proc(cap) < 0) { perror("cap_set_proc"); return -1; } cap_free(cap); return 0; }
static void set_caps() { if (capsText != NULL) { cap_t caps = cap_from_text(capsText); if (caps == NULL) errx(50, "Failed to parse capabilities: %s", capsText); if (cap_set_proc(caps) < 0) err(50, "Failed to set capabilities"); cap_free(caps); } }
void *chg_uid_gid(void *arg) { cap_t newcaps; cap_t mycaps; int ret; test_msg("Aux thread runs as UID: %d; GID: %d\n", getuid(), getgid()); newcaps = cap_from_text("cap_setgid,cap_setuid=+eip"); if (!newcaps) { pr_perror("Failed to get capability struct\n"); exit(1); } ret = cap_set_proc(newcaps); if (ret) { pr_perror("Failed to set capabilities for the process\n"); exit(1); } mycaps = cap_get_proc(); if (!mycaps) { pr_perror("Failed to get child thread capabilities\n"); exit_group(2); } test_msg("Child capabilities: %s\n", cap_to_text(mycaps, NULL)); test_msg("Changing UID/GID in child thread to %d:%d\n", uid, gid); ret = syscall(SYS_setresgid, gid, gid, gid); if (ret >= 0) { syscall(SYS_setresuid, uid, uid, uid); } else if (ret < 0) { pr_perror("Failed to change UID/GID\n"); exit_group(2); } gid = getgid(); uid = getuid(); test_msg("Now aux thread runs as UID: %d; GID: %d\n", uid, gid); test_msg("Child thread is waiting for main thread's signal\n"); task_waiter_complete(&t, 1); pthread_mutex_lock(&mutex); while (!done) { pthread_cond_wait(&cond, &mutex); } pthread_mutex_unlock(&mutex); test_msg("Child thread returns\n"); return NULL; }
/* run after child init we are uid User and gid Group */ static void ruid_child_init (apr_pool_t *p, server_rec *s) { UNUSED(s); int ncap; cap_t cap; cap_value_t capval[4]; /* detect default supplementary group IDs */ if ((startup_groupsnr = getgroups(RUID_MAXGROUPS, startup_groups)) == -1) { startup_groupsnr = 0; ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s ERROR getgroups() failed on child init, ignoring supplementary group IDs", MODULE_NAME); } /* setup chroot jailbreak */ if (chroot_used == RUID_CHROOT_USED && cap_mode == RUID_CAP_MODE_KEEP) { if ((root_handle = open("/.", O_RDONLY)) < 0) { root_handle = UNSET; ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "%s CRITICAL ERROR opening root file descriptor failed (%s)", MODULE_NAME, strerror(errno)); } else if (fcntl(root_handle, F_SETFD, FD_CLOEXEC) < 0) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "%s CRITICAL ERROR unable to set close-on-exec flag on root file descriptor (%s)", MODULE_NAME, strerror(errno)); if (close(root_handle) < 0) ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s CRITICAL ERROR closing root file descriptor (%d) failed", MODULE_NAME, root_handle); root_handle = UNSET; } else { /* register cleanup function */ apr_pool_cleanup_register(p, (void*)((long)root_handle), ruid_child_exit, apr_pool_cleanup_null); } } else { root_handle = (chroot_used == RUID_CHROOT_USED ? NONE : UNSET); } /* init cap with all zeros */ cap = cap_init(); capval[0] = CAP_SETUID; capval[1] = CAP_SETGID; ncap = 2; if (mode_stat_used == RUID_MODE_STAT_USED) { capval[ncap++] = CAP_DAC_READ_SEARCH; } if (root_handle != UNSET) { capval[ncap++] = CAP_SYS_CHROOT; } cap_set_flag(cap, CAP_PERMITTED, ncap, capval, CAP_SET); if (cap_set_proc(cap) != 0) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "%s CRITICAL ERROR %s:cap_set_proc failed", MODULE_NAME, __func__); } cap_free(cap); /* check if process is dumpable */ coredump = prctl(PR_GET_DUMPABLE); }