int add_rule(char *s, char *t, char *c, char *p, policydb_t *policy) {
	type_datum_t *src, *tgt;
	class_datum_t *cls;
	perm_datum_t *perm;
	avtab_datum_t *av;
	avtab_key_t key;

	src = hashtab_search(policy->p_types.table, s);
	if (src == NULL) {
		fprintf(stderr, "source type %s does not exist\n", s);
		return 2;
	}
	tgt = hashtab_search(policy->p_types.table, t);
	if (tgt == NULL) {
		fprintf(stderr, "target type %s does not exist\n", t);
		return 2;
	}
	cls = hashtab_search(policy->p_classes.table, c);
	if (cls == NULL) {
		fprintf(stderr, "class %s does not exist\n", c);
		return 2;
	}
	perm = hashtab_search(cls->permissions.table, p);
	if (perm == NULL) {
		if (cls->comdatum == NULL) {
			fprintf(stderr, "perm %s does not exist in class %s\n", p, c);
			return 2;
		}
		perm = hashtab_search(cls->comdatum->permissions.table, p);
		if (perm == NULL) {
			fprintf(stderr, "perm %s does not exist in class %s\n", p, c);
			return 2;
		}
	}

	// See if there is already a rule
	key.source_type = src->s.value;
	key.target_type = tgt->s.value;
	key.target_class = cls->s.value;
	key.specified = AVTAB_ALLOWED;
	av = avtab_search(&policy->te_avtab, &key);

	if (av == NULL) {
		int ret;

		av = cmalloc(sizeof av);
		av->data |= 1U << (perm->s.value - 1);
		ret = avtab_insert(&policy->te_avtab, &key, av);
		if (ret) {
			fprintf(stderr, "Error inserting into avtab\n");
			return 1;
		}	
	}

	av->data |= 1U << (perm->s.value - 1);

	return 0;
}
Esempio n. 2
0
static int security_compute_sid(u32 ssid,
				u32 tsid,
				u16 tclass,
				u32 specified,
				u32 *out_sid)
{
	struct context *scontext = 0, *tcontext = 0, newcontext;
	struct role_trans *roletr = 0;
	struct avtab_key avkey;
	struct avtab_datum *avdatum;
	unsigned int type_change = 0;
	int rc = 0;

	if (!ss_initialized) {
		switch (tclass) {
		case SECCLASS_PROCESS:
			*out_sid = ssid;
			break;
		default:
			*out_sid = tsid;
			break;
		}
		goto out;
	}

	POLICY_RDLOCK;

	scontext = sidtab_search(&sidtab, ssid);
	if (!scontext) {
		printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n",
		       ssid);
		rc = -EINVAL;
		goto out_unlock;
	}
	tcontext = sidtab_search(&sidtab, tsid);
	if (!tcontext) {
		printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n",
		       tsid);
		rc = -EINVAL;
		goto out_unlock;
	}

	context_init(&newcontext);

	/* Set the user identity. */
	switch (specified) {
	case AVTAB_TRANSITION:
	case AVTAB_CHANGE:
		/* Use the process user identity. */
		newcontext.user = scontext->user;
		break;
	case AVTAB_MEMBER:
		/* Use the related object owner. */
		newcontext.user = tcontext->user;
		break;
	}

	/* Set the role and type to default values. */
	switch (tclass) {
	case SECCLASS_PROCESS:
		/* Use the current role and type of process. */
		newcontext.role = scontext->role;
		newcontext.type = scontext->type;
		break;
	default:
		/* Use the well-defined object role. */
		newcontext.role = OBJECT_R_VAL;
		/* Use the type of the related object. */
		newcontext.type = tcontext->type;
	}

	/* Look for a type transition/member/change rule. */
	avkey.source_type = scontext->type;
	avkey.target_type = tcontext->type;
	avkey.target_class = tclass;
	avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_TYPE);
	type_change = (avdatum && (avdatum->specified & specified));
	if (type_change) {
		/* Use the type from the type transition/member/change rule. */
		switch (specified) {
		case AVTAB_TRANSITION:
			newcontext.type = avtab_transition(avdatum);
			break;
		case AVTAB_MEMBER:
			newcontext.type = avtab_member(avdatum);
			break;
		case AVTAB_CHANGE:
			newcontext.type = avtab_change(avdatum);
			break;
		}
	}

	/* Check for class-specific changes. */
	switch (tclass) {
	case SECCLASS_PROCESS:
		if (specified & AVTAB_TRANSITION) {
			/* Look for a role transition rule. */
			for (roletr = policydb.role_tr; roletr;
			     roletr = roletr->next) {
				if (roletr->role == scontext->role &&
				    roletr->type == tcontext->type) {
					/* Use the role transition rule. */
					newcontext.role = roletr->new_role;
					break;
				}
			}
		}

		if (!type_change && !roletr) {
			/* No change in process role or type. */
			*out_sid = ssid;
			goto out_unlock;

		}
		break;
	default:
		if (!type_change &&
		    (newcontext.user == tcontext->user) &&
		    mls_context_cmp(scontext, tcontext)) {
                        /* No change in object type, owner,
			   or MLS attributes. */
			*out_sid = tsid;
			goto out_unlock;
		}
		break;
	}

	/* Set the MLS attributes.
	   This is done last because it may allocate memory. */
	rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext);
	if (rc)
		goto out_unlock;

	/* Check the validity of the context. */
	if (!policydb_context_isvalid(&policydb, &newcontext)) {
		rc = compute_sid_handle_invalid_context(scontext,
							tcontext,
							tclass,
							&newcontext);
		if (rc)
			goto out_unlock;
	}
	/* Obtain the sid for the context. */
	rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
out_unlock:
	POLICY_RDUNLOCK;
	context_destroy(&newcontext);
out:
	return rc;
}
Esempio n. 3
0
// Based on public domain code from sepolicy-inject:
// https://bitbucket.org/joshua_brindle/sepolicy-inject/
// See the following commit about the hashtab_key_t casts:
// https://github.com/TresysTechnology/setools/commit/2994d1ca1da9e6f25f082c0dd1a49b5f958bd2ca
bool selinux_add_rule(policydb_t *pdb,
                      const std::string &source_str,
                      const std::string &target_str,
                      const std::string &class_str,
                      const std::string &perm_str)
{
    type_datum_t *source, *target;
    class_datum_t *clazz;
    perm_datum_t *perm;
    avtab_datum_t *av;
    avtab_key_t key;

    source = (type_datum_t *) hashtab_search(
            pdb->p_types.table, (hashtab_key_t) source_str.c_str());
    if (!source) {
        LOGE("Source type %s does not exist", source_str.c_str());
        return false;
    }
    target = (type_datum_t *) hashtab_search(
            pdb->p_types.table, (hashtab_key_t) target_str.c_str());
    if (!target) {
        LOGE("Target type %s does not exist", target_str.c_str());
        return false;
    }
    clazz = (class_datum_t *) hashtab_search(
            pdb->p_classes.table, (hashtab_key_t) class_str.c_str());
    if (!clazz) {
        LOGE("Class %s does not exist", class_str.c_str());
        return false;
    }
    perm = (perm_datum_t *) hashtab_search(
            clazz->permissions.table, (hashtab_key_t) perm_str.c_str());
    if (!perm) {
        if (clazz->comdatum == nullptr) {
            LOGE("Perm %s does not exist in class %s",
                 perm_str.c_str(), class_str.c_str());
            return false;
        }
        perm = (perm_datum_t *) hashtab_search(
                clazz->comdatum->permissions.table,
                (hashtab_key_t) perm_str.c_str());
        if (!perm) {
            LOGE("Perm %s does not exist in class %s",
                 perm_str.c_str(), class_str.c_str());
            return false;
        }
    }

    // See if there is already a rule
    key.source_type = source->s.value;
    key.target_type = target->s.value;
    key.target_class = clazz->s.value;
    key.specified = AVTAB_ALLOWED;
    av = avtab_search(&pdb->te_avtab, &key);

    bool exists = false;

    if (!av) {
        avtab_datum_t av_new;
        av_new.data = (1U << (perm->s.value - 1));
        if (avtab_insert(&pdb->te_avtab, &key, &av_new) != 0) {
            LOGE("Failed to add rule to avtab");
            return false;
        }
    } else {
        if (av->data & (1U << (perm->s.value - 1))) {
            exists = true;
        }
        av->data |= (1U << (perm->s.value - 1));
    }

    if (exists) {
        LOGD("Rule already exists: \"allow %s %s:%s %s;\"",
             source_str.c_str(), target_str.c_str(), class_str.c_str(),
             perm_str.c_str());
    } else {
        LOGD("Added rule: \"allow %s %s:%s %s;\"",
             source_str.c_str(), target_str.c_str(), class_str.c_str(),
             perm_str.c_str());
    }

    return true;
}
Esempio n. 4
0
/*
 * Compute access vectors based on a context structure pair for
 * the permissions in a particular class.
 */
static int context_struct_compute_av(struct context *scontext,
				     struct context *tcontext,
				     u16 tclass,
				     u32 requested,
				     struct av_decision *avd)
{
	struct constraint_node *constraint;
	struct role_allow *ra;
	struct avtab_key avkey;
	struct avtab_datum *avdatum;
	struct class_datum *tclass_datum;

	if (!tclass || tclass > policydb.p_classes.nprim) {
		printk(KERN_ERR "security_compute_av:  unrecognized class %d\n",
		       tclass);
		return -EINVAL;
	}
	tclass_datum = policydb.class_val_to_struct[tclass - 1];

	/*
	 * Initialize the access vectors to the default values.
	 */
	avd->allowed = 0;
	avd->decided = 0xffffffff;
	avd->auditallow = 0;
	avd->auditdeny = 0xffffffff;
	avd->seqno = latest_granting;

	/*
	 * If a specific type enforcement rule was defined for
	 * this permission check, then use it.
	 */
	avkey.source_type = scontext->type;
	avkey.target_type = tcontext->type;
	avkey.target_class = tclass;
	avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV);
	if (avdatum) {
		if (avdatum->specified & AVTAB_ALLOWED)
			avd->allowed = avtab_allowed(avdatum);
		if (avdatum->specified & AVTAB_AUDITDENY)
			avd->auditdeny = avtab_auditdeny(avdatum);
		if (avdatum->specified & AVTAB_AUDITALLOW)
			avd->auditallow = avtab_auditallow(avdatum);
	}

	/*
	 * Remove any permissions prohibited by the MLS policy.
	 */
	mls_compute_av(scontext, tcontext, tclass_datum, &avd->allowed);

	/*
	 * Remove any permissions prohibited by a constraint.
	 */
	constraint = tclass_datum->constraints;
	while (constraint) {
		if ((constraint->permissions & (avd->allowed)) &&
		    !constraint_expr_eval(scontext, tcontext,
					  constraint->expr)) {
			avd->allowed = (avd->allowed) & ~(constraint->permissions);
		}
		constraint = constraint->next;
	}

	/*
	 * If checking process transition permission and the
	 * role is changing, then check the (current_role, new_role)
	 * pair.
	 */
	if (tclass == SECCLASS_PROCESS &&
	    avd->allowed && PROCESS__TRANSITION &&
	    scontext->role != tcontext->role) {
		for (ra = policydb.role_allow; ra; ra = ra->next) {
			if (scontext->role == ra->role &&
			    tcontext->role == ra->new_role)
				break;
		}
		if (!ra)
			avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION);
	}

	return 0;
}