diff options
author | rwatson <rwatson@FreeBSD.org> | 2002-10-21 16:35:54 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2002-10-21 16:35:54 +0000 |
commit | ec031d49239e57b45533903e045aebb509b6f768 (patch) | |
tree | 1ed000b2251ff148931fbb75fec374d060b72638 /sys/security/mac_mls | |
parent | ee934c85cbcd0b6f9e9c0dd6f6aa74ad30ba6439 (diff) | |
download | FreeBSD-src-ec031d49239e57b45533903e045aebb509b6f768.zip FreeBSD-src-ec031d49239e57b45533903e045aebb509b6f768.tar.gz |
Cleanup of relabel authorization checks -- almost identical logic,
we just break out some of the tests better. Minor change in that
we now better support incremental update of labels.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, Network Associates Laboratories
Diffstat (limited to 'sys/security/mac_mls')
-rw-r--r-- | sys/security/mac_mls/mac_mls.c | 264 |
1 files changed, 204 insertions, 60 deletions
diff --git a/sys/security/mac_mls/mac_mls.c b/sys/security/mac_mls/mac_mls.c index 752a7ad..345592b 100644 --- a/sys/security/mac_mls/mac_mls.c +++ b/sys/security/mac_mls/mac_mls.c @@ -131,6 +131,15 @@ mls_free(struct mac_mls *mac_mls) } static int +mls_atmostflags(struct mac_mls *mac_mls, int flags) +{ + + if ((mac_mls->mm_flags & flags) != mac_mls->mm_flags) + return (EINVAL); + return (0); +} + +static int mac_mls_dominate_element(struct mac_mls_element *a, struct mac_mls_element *b) { @@ -239,6 +248,49 @@ mac_mls_equal_single(struct mac_mls *a, struct mac_mls *b) } static int +mac_mls_contains_equal(struct mac_mls *mac_mls) +{ + + if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) + if (mac_mls->mm_single.mme_type == MAC_MLS_TYPE_EQUAL) + return (1); + + if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) { + if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL) + return (1); + if (mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL) + return (1); + } + + return (0); +} + +static int +mac_mls_subject_equal_ok(struct mac_mls *mac_mls) +{ + + KASSERT((mac_mls->mm_flags & MAC_MLS_FLAGS_BOTH) == MAC_MLS_FLAGS_BOTH, + ("mac_mls_subject_equal_ok: subject doesn't have both labels")); + + /* If the single is EQUAL, it's ok. */ + if (mac_mls->mm_single.mme_type == MAC_MLS_TYPE_EQUAL) + return (0); + + /* If either range endpoint is EQUAL, it's ok. */ + if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL || + mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL) + return (0); + + /* If the range is low-high, it's ok. */ + if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW && + mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH) + return (0); + + /* It's not ok. */ + return (EPERM); +} + +static int mac_mls_valid(struct mac_mls *mac_mls) { @@ -985,41 +1037,59 @@ static int mac_mls_check_cred_relabel(struct ucred *cred, struct label *newlabel) { struct mac_mls *subj, *new; + int error; subj = SLOT(&cred->cr_label); new = SLOT(newlabel); - if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAGS_BOTH) - return (EINVAL); - - /* - * XXX: Allow processes with root privilege to set labels outside - * their range, so suid things like "su" work. This WILL go away - * when we figure out the 'correct' solution... - */ - if (!suser_cred(cred, 0)) - return (0); - /* - * The new single must be in the old range. + * If there is an MLS label update for the credential, it may be + * an update of single, range, or both. */ - if (!mac_mls_single_in_range(new, subj)) - return (EPERM); + error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH); + if (error) + return (error); /* - * The new range must be in the old range. + * If the MLS label is to be changed, authorize as appropriate. */ - if (!mac_mls_range_in_range(new, subj)) - return (EPERM); + if (new->mm_flags & MAC_MLS_FLAGS_BOTH) { + /* + * To change the MLS single label on a credential, the + * new single label must be in the current range. + */ + if (new->mm_flags & MAC_MLS_FLAG_SINGLE && + !mac_mls_single_in_range(new, subj)) + return (EPERM); + + /* + * To change the MLS range label on a credential, the + * new range label must be in the current range. + */ + if (new->mm_flags & MAC_MLS_FLAG_RANGE && + !mac_mls_range_in_range(new, subj)) + return (EPERM); + + /* + * To have EQUAL in any component of the new credential + * MLS label, the subject must already have EQUAL in + * their label. + */ + if (mac_mls_contains_equal(new)) { + error = mac_mls_subject_equal_ok(subj); + if (error) + return (error); + } - /* - * XXX: Don't permit EQUAL in a label unless the subject has EQUAL. - */ + /* + * XXXMAC: Additional consistency tests regarding the single + * and range of the new label might be performed here. + */ + } return (0); } - static int mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2) { @@ -1043,16 +1113,39 @@ mac_mls_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet, struct label *ifnetlabel, struct label *newlabel) { struct mac_mls *subj, *new; + int error; subj = SLOT(&cred->cr_label); new = SLOT(newlabel); - if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAGS_BOTH) - return (EINVAL); + /* + * If there is an MLS label update for the interface, it may + * be an update of single, range, or both. + */ + error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH); + if (error) + return (error); - /* XXX: privilege model here? */ + /* + * If the MLS label is to be changed, authorize as appropriate. + */ + if (new->mm_flags & MAC_MLS_FLAGS_BOTH) { + /* + * Rely on traditional superuser status for the MLS + * interface relabel requirements. XXX: This will go + * away. + */ + error = suser_cred(cred, 0); + if (error) + return (EPERM); + + /* + * XXXMAC: Additional consistency tests regarding the single + * and the range of the new label might be performed here. + */ + } - return (suser_cred(cred, 0)); + return (0); } static int @@ -1142,31 +1235,48 @@ mac_mls_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, struct label *pipelabel, struct label *newlabel) { struct mac_mls *subj, *obj, *new; + int error; new = SLOT(newlabel); subj = SLOT(&cred->cr_label); obj = SLOT(pipelabel); - if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE) - return (EINVAL); - /* - * To relabel a pipe, the old pipe label must be in the subject - * range. + * If there is an MLS label update for a pipe, it must be a + * single update. */ - if (!mac_mls_single_in_range(obj, subj)) - return (EPERM); + error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE); + if (error) + return (error); /* - * To relabel a pipe, the new pipe label must be in the subject - * range. + * To perform a relabel of a pipe (MLS label or not), MLS must + * authorize the relabel. */ - if (!mac_mls_single_in_range(new, subj)) + if (!mac_mls_single_in_range(obj, subj)) return (EPERM); /* - * XXX: Don't permit EQUAL in a label unless the subject has EQUAL. + * If the MLS label is to be changed, authorize as appropriate. */ + if (new->mm_flags & MAC_MLS_FLAG_SINGLE) { + /* + * To change the MLS label on a pipe, the new pipe label + * must be in the subject range. + */ + if (!mac_mls_single_in_range(new, subj)) + return (EPERM); + + /* + * To change the MLS label on a pipe to be EQUAL, the + * subject must have appropriate privilege. + */ + if (mac_mls_contains_equal(new)) { + error = mac_mls_subject_equal_ok(subj); + if (error) + return (error); + } + } return (0); } @@ -1287,31 +1397,48 @@ mac_mls_check_socket_relabel(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct label *newlabel) { struct mac_mls *subj, *obj, *new; + int error; new = SLOT(newlabel); subj = SLOT(&cred->cr_label); obj = SLOT(socketlabel); - if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE) - return (EINVAL); - /* - * To relabel a socket, the old socket label must be in the subject - * range. + * If there is an MLS label update for the socket, it may be + * an update of single. */ - if (!mac_mls_single_in_range(obj, subj)) - return (EPERM); + error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE); + if (error) + return (error); /* - * To relabel a socket, the new socket label must be in the subject + * To relabel a socket, the old socket single must be in the subject * range. */ - if (!mac_mls_single_in_range(new, subj)) + if (!mac_mls_single_in_range(obj, subj)) return (EPERM); /* - * XXX: Don't permit EQUAL in a label unless the subject has EQUAL. + * If the MLS label is to be changed, authorize as appropriate. */ + if (new->mm_flags & MAC_MLS_FLAG_SINGLE) { + /* + * To relabel a socket, the new socket single must be in + * the subject range. + */ + if (!mac_mls_single_in_range(new, subj)) + return (EPERM); + + /* + * To change the MLS label on the socket to contain EQUAL, + * the subject must have appropriate privilege. + */ + if (mac_mls_contains_equal(new)) { + error = mac_mls_subject_equal_ok(subj); + if (error) + return (error); + } + } return (0); } @@ -1492,7 +1619,7 @@ mac_mls_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, return (0); } -static int +static int mac_mls_check_vnode_link(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp) @@ -1558,7 +1685,7 @@ mac_mls_check_vnode_mmap(struct ucred *cred, struct vnode *vp, return (EACCES); } - return (0); + return (0); } static int @@ -1663,33 +1790,50 @@ mac_mls_check_vnode_relabel(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct label *newlabel) { struct mac_mls *old, *new, *subj; + int error; old = SLOT(vnodelabel); new = SLOT(newlabel); subj = SLOT(&cred->cr_label); - if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE) - return (EINVAL); - /* - * To relabel a vnode, the old vnode label must be in the subject - * range. + * If there is an MLS label update for the vnode, it must be a + * single label. */ - if (!mac_mls_single_in_range(old, subj)) - return (EPERM); + error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE); + if (error) + return (error); /* - * To relabel a vnode, the new vnode label must be in the subject - * range. + * To perform a relabel of the vnode (MLS label or not), MLS must + * authorize the relabel. */ - if (!mac_mls_single_in_range(new, subj)) + if (!mac_mls_single_in_range(old, subj)) return (EPERM); /* - * XXX: Don't permit EQUAL in a label unless the subject has EQUAL. + * If the MLS label is to be changed, authorize as appropriate. */ + if (new->mm_flags & MAC_MLS_FLAG_SINGLE) { + /* + * To change the MLS label on a vnode, the new vnode label + * must be in the subject range. + */ + if (!mac_mls_single_in_range(new, subj)) + return (EPERM); + + /* + * To change the MLS label on the vnode to be EQUAL, + * the subject must have appropriate privilege. + */ + if (mac_mls_contains_equal(new)) { + error = mac_mls_subject_equal_ok(subj); + if (error) + return (error); + } + } - return (suser_cred(cred, 0)); + return (0); } |