/** * aa_setprocattr_changeprofile - handle procattr interface to changeprofile * @fqname: args received from writting to /proc/<pid>/attr/current (NOT NULL) * @onexec: true if change_profile should be delayed until exec * @test: true if this is a test of change_profile permissions * * Returns: %0 or error code if change_profile fails */ int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test) { char *name, *ns_name; name = aa_split_fqname(fqname, &ns_name); return aa_change_profile(ns_name, name, onexec, test); }
/* * apparmor_process_label_set: Set AppArmor process profile * * @label : the profile to set * @default : use the default profile if label is NULL * @on_exec : the new profile will take effect on exec(2) not immediately * * Returns 0 on success, < 0 on failure * * Notes: This relies on /proc being available. */ static int apparmor_process_label_set(const char *label, int use_default, int on_exec) { if (!aa_enabled) return 0; if (!label) { if (use_default) label = AA_DEF_PROFILE; else return 0; } if (strcmp(label, "unconfined") == 0 && apparmor_am_unconfined()) { INFO("apparmor profile unchanged"); return 0; } if (on_exec) { if (aa_change_onexec(label) < 0) { SYSERROR("failed to change exec apparmor profile to %s", label); return -1; } } else { if (aa_change_profile(label) < 0) { SYSERROR("failed to change apparmor profile to %s", label); return -1; } } INFO("changed apparmor%s profile to %s", on_exec ? " exec" : "", label); return 0; }
void aa_change_profile_wrapper (int *ret, char **profile, bool *verbose) { if(*verbose){ Rprintf("Switching profiles...\n"); } *ret = aa_change_profile (*profile); if(*ret != 0){ *ret = errno; } }
/* * apparmor_process_label_set: Set AppArmor process profile * * @label : the profile to set * @default : use the default profile if label is NULL * @on_exec : this is ignored. Apparmor profile will be changed immediately * * Returns 0 on success, < 0 on failure * * Notes: This relies on /proc being available. */ static int apparmor_process_label_set(const char *label, int use_default, int on_exec) { if (!aa_enabled) return 0; /* user may request that we just ignore apparmor */ if (label && strcmp(label, AA_UNCHANGED) == 0) { INFO("apparmor profile unchanged per user request"); return 0; } /* * If we are already confined and no profile was requested, * then default to unchanged */ if (in_aa_confined_container() && !aa_stacking_supported()) { if (label) { ERROR("already apparmor confined, but new label requested."); return -1; } return 0; } if (!label) { if (use_default) label = AA_DEF_PROFILE; else return 0; } if (strcmp(label, "unconfined") == 0 && apparmor_am_unconfined()) { INFO("apparmor profile unchanged"); return 0; } if (aa_change_profile(label) < 0) { SYSERROR("failed to change apparmor profile to %s", label); return -1; } INFO("changed apparmor profile to %s", label); return 0; }
/* * apparmor_process_label_set: Set AppArmor process profile * * @label : the profile to set * @conf : the container configuration to use @label is NULL * @default : use the default profile if label is NULL * @on_exec : this is ignored. Apparmor profile will be changed immediately * * Returns 0 on success, < 0 on failure * * Notes: This relies on /proc being available. */ static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf, int use_default, int on_exec) { const char *label = inlabel ? inlabel : conf->lsm_aa_profile; if (!aa_enabled) return 0; if (!label) { if (use_default) label = AA_DEF_PROFILE; else label = "unconfined"; } if (!check_mount_feature_enabled() && strcmp(label, "unconfined") != 0) { WARN("Incomplete AppArmor support in your kernel"); if (!conf->lsm_aa_allow_incomplete) { ERROR("If you really want to start this container, set"); ERROR("lxc.aa_allow_incomplete = 1"); ERROR("in your container configuration file"); return -1; } } if (strcmp(label, "unconfined") == 0 && apparmor_am_unconfined()) { INFO("apparmor profile unchanged"); return 0; } if (aa_change_profile(label) < 0) { SYSERROR("failed to change apparmor profile to %s", label); return -1; } INFO("changed apparmor profile to %s", label); return 0; }
/** * virDomainLxcEnterSecurityLabel: * @model: the security model to set * @label: the security label to apply * @oldlabel: filled with old security label * @flags: currently unused, pass 0 * * This API is LXC specific, so it will only work with hypervisor * connections to the LXC driver. * * Attaches the process to the security label specified * by @label. @label is interpreted relative to @model * Depending on the security driver, this may * not take effect until the next call to exec(). * * If @oldlabel is not NULL, it will be filled with info * about the current security label. This may let the * process be moved back to the previous label if no * exec() has yet been performed. * * Returns 0 on success, -1 on error */ int virDomainLxcEnterSecurityLabel(virSecurityModelPtr model, virSecurityLabelPtr label, virSecurityLabelPtr oldlabel, unsigned int flags) { VIR_DEBUG("model=%p, label=%p, oldlabel=%p, flags=%x", model, label, oldlabel, flags); virResetLastError(); virCheckFlagsGoto(0, error); virCheckNonNullArgGoto(model, error); virCheckNonNullArgGoto(label, error); if (oldlabel) memset(oldlabel, 0, sizeof(*oldlabel)); if (STREQ(model->model, "selinux")) { #ifdef WITH_SELINUX if (oldlabel) { security_context_t ctx; if (getcon(&ctx) < 0) { virReportSystemError(errno, _("unable to get PID %d security context"), getpid()); goto error; } if (strlen((char *) ctx) >= VIR_SECURITY_LABEL_BUFLEN) { virReportError(VIR_ERR_INTERNAL_ERROR, _("security label exceeds " "maximum length: %d"), VIR_SECURITY_LABEL_BUFLEN - 1); freecon(ctx); goto error; } strcpy(oldlabel->label, (char *) ctx); freecon(ctx); if ((oldlabel->enforcing = security_getenforce()) < 0) { virReportSystemError(errno, "%s", _("error calling security_getenforce()")); goto error; } } if (setexeccon(label->label) < 0) { virReportSystemError(errno, _("Cannot set context %s"), label->label); goto error; } #else virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", _("Support for SELinux is not enabled")); goto error; #endif } else if (STREQ(model->model, "apparmor")) { #ifdef WITH_APPARMOR if (aa_change_profile(label->label) < 0) { virReportSystemError(errno, _("error changing profile to %s"), label->label); goto error; } #else virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", _("Support for AppArmor is not enabled")); goto error; #endif } else if (STREQ(model->model, "none")) { /* nothing todo */ } else { virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, _("Security model %s cannot be entered"), model->model); goto error; } return 0; error: virDispatchError(NULL); return -1; }
/* * apparmor_process_label_set: Set AppArmor process profile * * @label : the profile to set * @conf : the container configuration to use @label is NULL * @default : use the default profile if label is NULL * @on_exec : this is ignored. Apparmor profile will be changed immediately * * Returns 0 on success, < 0 on failure * * Notes: This relies on /proc being available. */ static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf, int use_default, int on_exec) { const char *label = inlabel ? inlabel : conf->lsm_aa_profile; char *curlabel; if (!aa_enabled) return 0; /* user may request that we just ignore apparmor */ if (label && strcmp(label, AA_UNCHANGED) == 0) { INFO("apparmor profile unchanged per user request"); return 0; } curlabel = apparmor_process_label_get(getpid()); if (!aa_stacking_supported() && aa_needs_transition(curlabel)) { // we're already confined, and stacking isn't supported if (!label || strcmp(curlabel, label) == 0) { // no change requested free(curlabel); return 0; } ERROR("already apparmor confined, but new label requested."); free(curlabel); return -1; } free(curlabel); if (!label) { if (use_default) { if (cgns_supported()) label = AA_DEF_PROFILE_CGNS; else label = AA_DEF_PROFILE; } else label = "unconfined"; } if (!check_mount_feature_enabled() && strcmp(label, "unconfined") != 0) { WARN("Incomplete AppArmor support in your kernel"); if (!conf->lsm_aa_allow_incomplete) { ERROR("If you really want to start this container, set"); ERROR("lxc.aa_allow_incomplete = 1"); ERROR("in your container configuration file"); return -1; } } if (strcmp(label, "unconfined") == 0 && apparmor_am_unconfined()) { INFO("apparmor profile unchanged"); return 0; } if (aa_change_profile(label) < 0) { SYSERROR("failed to change apparmor profile to %s", label); return -1; } INFO("changed apparmor profile to %s", label); return 0; }
int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ { int is_root = !geteuid(); int made_chroot = 0; if (wp->config->rlimit_files) { struct rlimit r; r.rlim_max = r.rlim_cur = (rlim_t) wp->config->rlimit_files; if (0 > setrlimit(RLIMIT_NOFILE, &r)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to set rlimit_files for this pool. Please check your system limits or decrease rlimit_files. setrlimit(RLIMIT_NOFILE, %d)", wp->config->name, wp->config->rlimit_files); } } if (wp->config->rlimit_core) { struct rlimit r; r.rlim_max = r.rlim_cur = wp->config->rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) wp->config->rlimit_core; if (0 > setrlimit(RLIMIT_CORE, &r)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to set rlimit_core for this pool. Please check your system limits or decrease rlimit_core. setrlimit(RLIMIT_CORE, %d)", wp->config->name, wp->config->rlimit_core); } } if (is_root && wp->config->chroot && *wp->config->chroot) { if (0 > chroot(wp->config->chroot)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to chroot(%s)", wp->config->name, wp->config->chroot); return -1; } made_chroot = 1; } if (wp->config->chdir && *wp->config->chdir) { if (0 > chdir(wp->config->chdir)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to chdir(%s)", wp->config->name, wp->config->chdir); return -1; } } else if (made_chroot) { if (0 > chdir("/")) { zlog(ZLOG_WARNING, "[pool %s] failed to chdir(/)", wp->config->name); } } if (is_root) { if (wp->config->process_priority != 64) { if (setpriority(PRIO_PROCESS, 0, wp->config->process_priority) < 0) { zlog(ZLOG_SYSERROR, "[pool %s] Unable to set priority for this new process", wp->config->name); return -1; } } if (wp->set_gid) { if (0 > setgid(wp->set_gid)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to setgid(%d)", wp->config->name, wp->set_gid); return -1; } } if (wp->set_uid) { if (0 > initgroups(wp->config->user, wp->set_gid)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to initgroups(%s, %d)", wp->config->name, wp->config->user, wp->set_gid); return -1; } if (0 > setuid(wp->set_uid)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to setuid(%d)", wp->config->name, wp->set_uid); return -1; } } } #ifdef HAVE_PRCTL if (0 > prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to prctl(PR_SET_DUMPABLE)", wp->config->name); } #endif if (0 > fpm_clock_init()) { return -1; } #ifdef HAVE_APPARMOR if (wp->config->apparmor_hat) { char *con, *new_con; if (aa_getcon(&con, NULL) == -1) { zlog(ZLOG_SYSERROR, "[pool %s] failed to query apparmor confinement. Please check if \"/proc/*/attr/current\" is read and writeable.", wp->config->name); return -1; } new_con = malloc(strlen(con) + strlen(wp->config->apparmor_hat) + 3); // // + 0 Byte if (!new_con) { zlog(ZLOG_SYSERROR, "[pool %s] failed to allocate memory for apparmor hat change.", wp->config->name); return -1; } if (0 > sprintf(new_con, "%s//%s", con, wp->config->apparmor_hat)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to construct apparmor confinement.", wp->config->name); return -1; } if (0 > aa_change_profile(new_con)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to change to new confinement (%s). Please check if \"/proc/*/attr/current\" is read and writeable and \"change_profile -> %s//*\" is allowed.", wp->config->name, new_con, con); return -1; } free(con); free(new_con); } #endif return 0; }