示例#1
0
int
secadm_vnode_check_open(struct ucred *ucred, struct vnode *vp,
    struct label *label, accmode_t accmode)
{
	struct rm_priotracker tracker;
	struct secadm_prison_entry *entry;
	secadm_rule_t *rule;
	struct vattr vap;
	int err, res;

	if (!(accmode & (VWRITE | VAPPEND)))
		return (0);

	res = 0;

	entry = get_prison_list_entry(ucred->cr_prison->pr_name, 0);
	if (entry == NULL)
		return (0);

	err = VOP_GETATTR(vp, &vap, ucred);
	if (err)
		return (err);

	SPL_RLOCK(entry, tracker);
	for (rule = entry->spl_rules; rule != NULL; rule = rule->sr_next) {
		if (vap.va_fileid != rule->sr_inode)
			continue;

		if (strcmp(vp->v_mount->mnt_stat.f_mntonname,
		    rule->sr_mount))
			continue;

		if (lookup_integriforce_feature(rule) != NULL) {
			KASSERT(rule != NULL && rule->sr_path != NULL,
			    ("%s: failed ...", __func__));
			printf("[SECADM] Warning: A process tried to modify "
			    "file %s, which is protected by a secadm rule. "
			    "Returning EPERM.\n", rule->sr_path);
			res=EPERM;
		}
		break;
	}
	SPL_RUNLOCK(entry, tracker);

	return (res);
}
示例#2
0
int
secadm_vnode_check_unlink(struct ucred *ucred, struct vnode *dvp,
    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
    struct componentname *cnp)
{

	struct rm_priotracker tracker;
	struct secadm_prison_entry *entry;
	secadm_rule_t *rule;
	struct vattr vap;
	int err, res=0;

	entry = get_prison_list_entry(ucred->cr_prison->pr_name, 0);
	if (entry == NULL)
		return (0);

	err = VOP_GETATTR(vp, &vap, ucred);
	if (err)
		return (err);

	SPL_RLOCK(entry, tracker);
	for (rule = entry->spl_rules; rule != NULL; rule = rule->sr_next) {
		if (vap.va_fileid != rule->sr_inode)
			continue;

		if (strcmp(vp->v_mount->mnt_stat.f_mntonname,
		    rule->sr_mount))
			continue;

		KASSERT(rule != NULL && rule->sr_path != NULL,
		    ("%s: failed ...", __func__));
		printf("[SECADM] Prevented to unlink %s: protected by a secadm rule.\n",
		    rule->sr_path);
		res=EPERM;
		break;
	}
	SPL_RUNLOCK(entry, tracker);

	return (res);
}
示例#3
0
static int
sysctl_integriforce_so(SYSCTL_HANDLER_ARGS)
{
    integriforce_so_check_t *integriforce_so;
    secadm_prison_entry_t *entry;
    secadm_rule_t r, *rule;
    struct nameidata nd;
    struct vattr vap;
    secadm_key_t key;
    int err;

    if (!(req->newptr) || req->newlen != sizeof(integriforce_so_check_t))
        return (EINVAL);

    if (!(req->oldptr) || req->oldlen != sizeof(integriforce_so_check_t))
        return (EINVAL);

    integriforce_so = malloc(sizeof(integriforce_so_check_t), M_SECADM, M_WAITOK);

    err = SYSCTL_IN(req, integriforce_so, sizeof(integriforce_so_check_t));
    if (err) {
        free(integriforce_so, M_SECADM);
        return (err);
    }

    NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, integriforce_so->isc_path, req->td);
    err = namei(&nd);
    if (err) {
        free(integriforce_so, M_SECADM);
        NDFREE(&nd, 0);
        return (err);
    }

    if ((err = vn_lock(nd.ni_vp, LK_SHARED | LK_RETRY)) != 0) {
        free(integriforce_so, M_SECADM);
        NDFREE(&nd, 0);
        return (err);
    }

    err = VOP_GETATTR(nd.ni_vp, &vap, req->td->td_ucred);
    if (err) {
        free(integriforce_so, M_SECADM);
        NDFREE(&nd, 0);
        return (err);
    }

    VOP_UNLOCK(nd.ni_vp, 0);

    key.sk_jid = req->td->td_ucred->cr_prison->pr_id;
    key.sk_type = secadm_integriforce_rule;
    key.sk_fileid = vap.va_fileid;
    strncpy(key.sk_mntonname,
            nd.ni_vp->v_mount->mnt_stat.f_mntonname, MNAMELEN);
    r.sr_key = fnv_32_buf(&key, sizeof(secadm_key_t), FNV1_32_INIT);

    entry = get_prison_list_entry(
                req->td->td_ucred->cr_prison->pr_id);

    PE_RLOCK(entry);
    rule = RB_FIND(secadm_rules_tree, &(entry->sp_rules), &r);

    if (rule) {
        integriforce_so->isc_result =
            do_integriforce_check(rule, &vap, nd.ni_vp,
                                  req->td->td_ucred);
    }

    PE_RUNLOCK(entry);

    SYSCTL_OUT(req, integriforce_so, sizeof(integriforce_so_check_t));
    free(integriforce_so, M_SECADM);

    NDFREE(&nd, 0);

    return (0);
}
示例#4
0
int
secadm_vnode_check_exec(struct ucred *ucred, struct vnode *vp,
    struct label *vplabel, struct image_params *imgp,
    struct label *execlabel)
{
	struct rm_priotracker tracker;
	struct secadm_prison_entry *entry;
	secadm_rule_t *rule;
	struct vattr vap;
	size_t i;
	int err=0, flags=0;

	entry = get_prison_list_entry(ucred->cr_prison->pr_name, 0);
	if (entry == NULL)
		return (0);

	err = VOP_GETATTR(imgp->vp, &vap, ucred);
	if (err)
		return (err);

	SPL_RLOCK(entry, tracker);
	for (rule = entry->spl_rules; rule != NULL; rule = rule->sr_next) {
		if (vap.va_fileid != rule->sr_inode)
			continue;

		if (strcmp(imgp->vp->v_mount->mnt_stat.f_mntonname,
		    rule->sr_mount))
			continue;

		for (i=0; i < rule->sr_nfeatures; i++) {
			switch(rule->sr_features[i].sf_type) {
			case pageexec_enabled:
				flags |= PAX_NOTE_PAGEEXEC;
				break;
			case pageexec_disabled:
				flags |= PAX_NOTE_NOPAGEEXEC;
				break;
			case mprotect_enabled:
				flags |= PAX_NOTE_MPROTECT;
				break;
			case mprotect_disabled:
				flags |= PAX_NOTE_NOMPROTECT;
				break;
			case segvguard_enabled:
				flags |= PAX_NOTE_SEGVGUARD;
				break;
			case segvguard_disabled:
				flags |= PAX_NOTE_NOSEGVGUARD;
				break;
			case aslr_enabled:
				flags |= PAX_NOTE_ASLR;
				break;
			case aslr_disabled:
				flags |= PAX_NOTE_NOASLR;
				break;
			case integriforce:
				err = do_integriforce_check(rule, &vap, imgp->vp, ucred);
				break;
#if __HardenedBSD_version > 21
			case shlibrandom_enabled:
				flags |= PAX_NOTE_SHLIBRANDOM;
				break;
			case shlibrandom_disabled:
				flags |= PAX_NOTE_NOSHLIBRANDOM;
				break;
#endif
			default:
				break;
			}
		}

		break;
	}

	SPL_RUNLOCK(entry, tracker);

	if (err == 0 && flags)
		err = pax_elf(imgp, flags);

	return (err);
}
示例#5
0
static secadm_error_t
handle_add_rule(struct thread *td, secadm_command_t *cmd, secadm_reply_t *reply)
{
	secadm_rule_t *rule, *next, *tail;
	struct secadm_prison_entry *entry;
	size_t maxid=0;
	secadm_error_t res=secadm_success;
	int err;

	entry = get_prison_list_entry(td->td_ucred->cr_prison->pr_name, 1);

	rule = malloc(sizeof(secadm_rule_t), M_SECADM, M_WAITOK);
	if ((err = copyin(cmd->sc_metadata, rule, sizeof(secadm_rule_t))) != 0) {
		free(rule, M_SECADM);
		reply->sr_code = secadm_fail;
		reply->sr_errno = err;
		return (secadm_fail);
	}

	if (read_rule_from_userland(td, rule)) {
		reply->sr_errno = EINVAL;
		rule->sr_next = NULL;
		goto error;
	}

	rule->sr_id = maxid++;

	tail = rule;
	while (tail->sr_next != NULL) {
		next = malloc(sizeof(secadm_rule_t), M_SECADM, M_WAITOK);
		if ((err = copyin(tail->sr_next, next, sizeof(secadm_rule_t))) != 0) {
			reply->sr_errno = err;
			free(next, M_SECADM);
			tail->sr_next = NULL;
			goto error;
		}

		if (read_rule_from_userland(td, next)) {
			res=secadm_fail;
			reply->sr_errno = EINVAL;
			free_rule(next, 1);
			tail->sr_next = NULL;
			goto error;
		}

		next->sr_id = maxid++;

		tail->sr_next = next;
		tail = next;
	}

	if (validate_ruleset(td, rule)) {
		res = secadm_fail;
		reply->sr_errno = EINVAL;
		goto error;
	}

	flush_rules(td);

	SPL_WLOCK(entry);
	entry->spl_rules = rule;
	entry->spl_max_id = maxid;
	SPL_WUNLOCK(entry);

	reply->sr_code = secadm_success;
	reply->sr_errno = 0;

	return (0);

error:
	while (rule != NULL) {
		next = rule->sr_next;
		free_rule(rule, 1);
		rule = next;
	}

	reply->sr_code = secadm_fail;

	return (res);
}