diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-27 13:26:03 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-27 13:26:03 -0700 |
commit | e22619a29fcdb513b7bc020e84225bb3b5914259 (patch) | |
tree | 1d1d72a4c8cebad4f2d2bf738395ca4ececa95ec /security/smack/smack_access.c | |
parent | Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus (diff) | |
parent | Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity into next (diff) | |
download | linux-dev-e22619a29fcdb513b7bc020e84225bb3b5914259.tar.xz linux-dev-e22619a29fcdb513b7bc020e84225bb3b5914259.zip |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
"The main change in this kernel is Casey's generalized LSM stacking
work, which removes the hard-coding of Capabilities and Yama stacking,
allowing multiple arbitrary "small" LSMs to be stacked with a default
monolithic module (e.g. SELinux, Smack, AppArmor).
See
https://lwn.net/Articles/636056/
This will allow smaller, simpler LSMs to be incorporated into the
mainline kernel and arbitrarily stacked by users. Also, this is a
useful cleanup of the LSM code in its own right"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (38 commits)
tpm, tpm_crb: fix le64_to_cpu conversions in crb_acpi_add()
vTPM: set virtual device before passing to ibmvtpm_reset_crq
tpm_ibmvtpm: remove unneccessary message level.
ima: update builtin policies
ima: extend "mask" policy matching support
ima: add support for new "euid" policy condition
ima: fix ima_show_template_data_ascii()
Smack: freeing an error pointer in smk_write_revoke_subj()
selinux: fix setting of security labels on NFS
selinux: Remove unused permission definitions
selinux: enable genfscon labeling for sysfs and pstore files
selinux: enable per-file labeling for debugfs files.
selinux: update netlink socket classes
signals: don't abuse __flush_signals() in selinux_bprm_committed_creds()
selinux: Print 'sclass' as string when unrecognized netlink message occurs
Smack: allow multiple labels in onlycap
Smack: fix seq operations in smackfs
ima: pass iint to ima_add_violation()
ima: wrap event related data to the new ima_event_data structure
integrity: add validity checks for 'path' parameter
...
Diffstat (limited to 'security/smack/smack_access.c')
-rw-r--r-- | security/smack/smack_access.c | 68 |
1 files changed, 57 insertions, 11 deletions
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 0f410fc56e33..00f6b38bffbd 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -425,7 +425,7 @@ void smk_insert_entry(struct smack_known *skp) * @string: a text string that might be a Smack label * * Returns a pointer to the entry in the label list that - * matches the passed string. + * matches the passed string or NULL if not found. */ struct smack_known *smk_find_entry(const char *string) { @@ -448,7 +448,7 @@ struct smack_known *smk_find_entry(const char *string) * @string: a text string that might contain a Smack label * @len: the maximum size, or zero if it is NULL terminated. * - * Returns a pointer to the clean label, or NULL + * Returns a pointer to the clean label or an error code. */ char *smk_parse_smack(const char *string, int len) { @@ -464,7 +464,7 @@ char *smk_parse_smack(const char *string, int len) * including /smack/cipso and /smack/cipso2 */ if (string[0] == '-') - return NULL; + return ERR_PTR(-EINVAL); for (i = 0; i < len; i++) if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' || @@ -472,11 +472,13 @@ char *smk_parse_smack(const char *string, int len) break; if (i == 0 || i >= SMK_LONGLABEL) - return NULL; + return ERR_PTR(-EINVAL); smack = kzalloc(i + 1, GFP_KERNEL); - if (smack != NULL) - strncpy(smack, string, i); + if (smack == NULL) + return ERR_PTR(-ENOMEM); + + strncpy(smack, string, i); return smack; } @@ -523,7 +525,8 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap, * @len: the maximum size, or zero if it is NULL terminated. * * Returns a pointer to the entry in the label list that - * matches the passed string, adding it if necessary. + * matches the passed string, adding it if necessary, + * or an error code. */ struct smack_known *smk_import_entry(const char *string, int len) { @@ -533,8 +536,8 @@ struct smack_known *smk_import_entry(const char *string, int len) int rc; smack = smk_parse_smack(string, len); - if (smack == NULL) - return NULL; + if (IS_ERR(smack)) + return ERR_CAST(smack); mutex_lock(&smack_known_lock); @@ -543,8 +546,10 @@ struct smack_known *smk_import_entry(const char *string, int len) goto freeout; skp = kzalloc(sizeof(*skp), GFP_KERNEL); - if (skp == NULL) + if (skp == NULL) { + skp = ERR_PTR(-ENOMEM); goto freeout; + } skp->smk_known = smack; skp->smk_secid = smack_next_secid++; @@ -577,7 +582,7 @@ struct smack_known *smk_import_entry(const char *string, int len) * smk_netlbl_mls failed. */ kfree(skp); - skp = NULL; + skp = ERR_PTR(rc); freeout: kfree(smack); unlockout: @@ -612,3 +617,44 @@ struct smack_known *smack_from_secid(const u32 secid) rcu_read_unlock(); return &smack_known_invalid; } + +/* + * Unless a process is running with one of these labels + * even having CAP_MAC_OVERRIDE isn't enough to grant + * privilege to violate MAC policy. If no labels are + * designated (the empty list case) capabilities apply to + * everyone. + */ +LIST_HEAD(smack_onlycap_list); +DEFINE_MUTEX(smack_onlycap_lock); + +/* + * Is the task privileged and allowed to be privileged + * by the onlycap rule. + * + * Returns 1 if the task is allowed to be privileged, 0 if it's not. + */ +int smack_privileged(int cap) +{ + struct smack_known *skp = smk_of_current(); + struct smack_onlycap *sop; + + if (!capable(cap)) + return 0; + + rcu_read_lock(); + if (list_empty(&smack_onlycap_list)) { + rcu_read_unlock(); + return 1; + } + + list_for_each_entry_rcu(sop, &smack_onlycap_list, list) { + if (sop->smk_label == skp) { + rcu_read_unlock(); + return 1; + } + } + rcu_read_unlock(); + + return 0; +} |