On 10/14/2015 5:42 AM, Lukasz Pawelczyk wrote: > This patch adds two new functions that provide an abstraction layer for > two common internal Smack operations: > > smk_find_label_name() - returns a label name (char*) from a struct > smack_known pointer > smk_get_label() - either finds or imports a label from a raw label > name (char*) and returns struct smack_known > pointer > > This patch also simplifies some pieces of code due to addition of those > 2 functions (e.g. smack_inode_post_setxattr, smk_fill_rule, > smk_write_revoke_subj). > > It is meant as a preparation for namespaces patches. Those 2 functions > will serve as entry points for namespace operations. > > This patch should not change the Smack behaviour in any way. > > Signed-off-by: Lukasz Pawelczyk <l.pawelczyk@xxxxxxxxxxx> > Reviewed-by: Casey Schaufler <casey@xxxxxxxxxxxxxxxx> Acked-by: Casey Schaufler <casey@xxxxxxxxxxxxxxxx> > --- > security/smack/smack.h | 2 + > security/smack/smack_access.c | 41 ++++++++++++ > security/smack/smack_lsm.c | 78 +++++++++++----------- > security/smack/smackfs.c | 147 +++++++++++++++++++++++------------------- > 4 files changed, 166 insertions(+), 102 deletions(-) > > diff --git a/security/smack/smack.h b/security/smack/smack.h > index ca8fb7c..091efc2 100644 > --- a/security/smack/smack.h > +++ b/security/smack/smack.h > @@ -306,6 +306,8 @@ int smack_has_ns_privilege(struct task_struct *task, > int smack_has_privilege(struct task_struct *task, int cap); > int smack_ns_privileged(struct user_namespace *user_ns, int cap); > int smack_privileged(int cap); > +char *smk_find_label_name(struct smack_known *skp); > +struct smack_known *smk_get_label(const char *string, int len, bool import); > > /* > * Shared data. > diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c > index 72f848e..131c742 100644 > --- a/security/smack/smack_access.c > +++ b/security/smack/smack_access.c > @@ -716,3 +716,44 @@ int smack_privileged(int cap) > { > return smack_ns_privileged(&init_user_ns, cap); > } > + > +/** > + * smk_find_label_name - A helper to get a string value of a label > + * @skp: a label we want a string value from > + * > + * Returns a pointer to a label name or NULL if label name not found. > + */ > +char *smk_find_label_name(struct smack_known *skp) > +{ > + return skp->smk_known; > +} > + > +/** > + * smk_get_label - A helper to get the smack_known value from a string using > + * either import or find functions if it already exists > + * @string: a name of a label we look for or want to import > + * @len: the string size, or zero if it is NULL terminated > + * @import: whether we should import the label if not found > + * > + * Returns a smack_known label that is either imported or found. > + * NULL if label not found (only when import == false). > + * Error code otherwise. > + */ > +struct smack_known *smk_get_label(const char *string, int len, bool import) > +{ > + struct smack_known *skp; > + char *cp; > + > + if (import) { > + skp = smk_import_entry(string, len); > + } else { > + cp = smk_parse_smack(string, len); > + if (IS_ERR(cp)) > + return ERR_CAST(cp); > + > + skp = smk_find_entry(cp); > + kfree(cp); > + } > + > + return skp; > +} > diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c > index 198d3d6..7303c37 100644 > --- a/security/smack/smack_lsm.c > +++ b/security/smack/smack_lsm.c > @@ -746,31 +746,31 @@ static int smack_set_mnt_opts(struct super_block *sb, > for (i = 0; i < num_opts; i++) { > switch (opts->mnt_opts_flags[i]) { > case FSDEFAULT_MNT: > - skp = smk_import_entry(opts->mnt_opts[i], 0); > + skp = smk_get_label(opts->mnt_opts[i], 0, true); > if (IS_ERR(skp)) > return PTR_ERR(skp); > sp->smk_default = skp; > break; > case FSFLOOR_MNT: > - skp = smk_import_entry(opts->mnt_opts[i], 0); > + skp = smk_get_label(opts->mnt_opts[i], 0, true); > if (IS_ERR(skp)) > return PTR_ERR(skp); > sp->smk_floor = skp; > break; > case FSHAT_MNT: > - skp = smk_import_entry(opts->mnt_opts[i], 0); > + skp = smk_get_label(opts->mnt_opts[i], 0, true); > if (IS_ERR(skp)) > return PTR_ERR(skp); > sp->smk_hat = skp; > break; > case FSROOT_MNT: > - skp = smk_import_entry(opts->mnt_opts[i], 0); > + skp = smk_get_label(opts->mnt_opts[i], 0, true); > if (IS_ERR(skp)) > return PTR_ERR(skp); > sp->smk_root = skp; > break; > case FSTRANS_MNT: > - skp = smk_import_entry(opts->mnt_opts[i], 0); > + skp = smk_get_label(opts->mnt_opts[i], 0, true); > if (IS_ERR(skp)) > return PTR_ERR(skp); > sp->smk_root = skp; > @@ -1288,7 +1288,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, > rc = -EPERM; > > if (rc == 0 && check_import) { > - skp = size ? smk_import_entry(value, size) : NULL; > + skp = size ? smk_get_label(value, size, true) : NULL; > if (IS_ERR(skp)) > rc = PTR_ERR(skp); > else if (skp == NULL || (check_star && > @@ -1322,6 +1322,7 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, > const void *value, size_t size, int flags) > { > struct smack_known *skp; > + struct smack_known **skpp = NULL; > struct inode_smack *isp = d_backing_inode(dentry)->i_security; > > if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { > @@ -1329,27 +1330,21 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, > return; > } > > - if (strcmp(name, XATTR_NAME_SMACK) == 0) { > - skp = smk_import_entry(value, size); > - if (!IS_ERR(skp)) > - isp->smk_inode = skp; > - else > - isp->smk_inode = &smack_known_invalid; > - } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { > - skp = smk_import_entry(value, size); > - if (!IS_ERR(skp)) > - isp->smk_task = skp; > - else > - isp->smk_task = &smack_known_invalid; > - } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { > - skp = smk_import_entry(value, size); > + if (strcmp(name, XATTR_NAME_SMACK) == 0) > + skpp = &isp->smk_inode; > + else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) > + skpp = &isp->smk_task; > + else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) > + skpp = &isp->smk_mmap; > + > + if (skpp) { > + skp = smk_get_label(value, size, true); > + > if (!IS_ERR(skp)) > - isp->smk_mmap = skp; > + *skpp = skp; > else > - isp->smk_mmap = &smack_known_invalid; > + *skpp = &smack_known_invalid; > } > - > - return; > } > > /** > @@ -1443,15 +1438,17 @@ static int smack_inode_getsecurity(const struct inode *inode, > struct socket *sock; > struct super_block *sbp; > struct inode *ip = (struct inode *)inode; > - struct smack_known *isp; > - int ilen; > + struct smack_known *isp = NULL; > int rc = 0; > > - if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { > + if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) > isp = smk_of_inode(inode); > - ilen = strlen(isp->smk_known); > - *buffer = isp->smk_known; > - return ilen; > + > + if (isp) { > + *buffer = smk_find_label_name(isp); > + if (*buffer == NULL) > + *buffer = smack_known_huh.smk_known; > + return strlen(*buffer); > } > > /* > @@ -1474,10 +1471,11 @@ static int smack_inode_getsecurity(const struct inode *inode, > else > return -EOPNOTSUPP; > > - ilen = strlen(isp->smk_known); > if (rc == 0) { > - *buffer = isp->smk_known; > - rc = ilen; > + *buffer = smk_find_label_name(isp); > + if (*buffer == NULL) > + *buffer = smack_known_huh.smk_known; > + rc = strlen(*buffer); > } > > return rc; > @@ -2658,7 +2656,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, > if (value == NULL || size > SMK_LONGLABEL || size == 0) > return -EINVAL; > > - skp = smk_import_entry(value, size); > + skp = smk_get_label(value, size, true); > if (IS_ERR(skp)) > return PTR_ERR(skp); > > @@ -3528,7 +3526,10 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) > if (strcmp(name, "current") != 0) > return -EINVAL; > > - cp = kstrdup(skp->smk_known, GFP_KERNEL); > + cp = smk_find_label_name(skp); > + if (cp == NULL) > + cp = smack_known_huh.smk_known; > + cp = kstrdup(cp, GFP_KERNEL); > if (cp == NULL) > return -ENOMEM; > > @@ -3572,7 +3573,7 @@ static int smack_setprocattr(struct task_struct *p, const struct cred *f_cred, > if (strcmp(name, "current") != 0) > return -EINVAL; > > - skp = smk_import_entry(value, size); > + skp = smk_get_label(value, size, true); > if (IS_ERR(skp)) > return PTR_ERR(skp); > > @@ -4311,7 +4312,10 @@ static int smack_key_getsecurity(struct key *key, char **_buffer) > return 0; > } > > - copy = kstrdup(skp->smk_known, GFP_KERNEL); > + copy = smk_find_label_name(skp); > + if (copy == NULL) > + copy = smack_known_huh.smk_known; > + copy = kstrdup(copy, GFP_KERNEL); > if (copy == NULL) > return -ENOMEM; > length = strlen(copy) + 1; > diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c > index 05e09ee2..e5fb555 100644 > --- a/security/smack/smackfs.c > +++ b/security/smack/smackfs.c > @@ -340,36 +340,17 @@ static int smk_fill_rule(const char *subject, const char *object, > struct smack_parsed_rule *rule, int import, > int len) > { > - const char *cp; > - struct smack_known *skp; > - > - if (import) { > - rule->smk_subject = smk_import_entry(subject, len); > - if (IS_ERR(rule->smk_subject)) > - return PTR_ERR(rule->smk_subject); > - > - rule->smk_object = smk_import_entry(object, len); > - if (IS_ERR(rule->smk_object)) > - return PTR_ERR(rule->smk_object); > - } else { > - cp = smk_parse_smack(subject, len); > - if (IS_ERR(cp)) > - return PTR_ERR(cp); > - skp = smk_find_entry(cp); > - kfree(cp); > - if (skp == NULL) > - return -ENOENT; > - rule->smk_subject = skp; > - > - cp = smk_parse_smack(object, len); > - if (IS_ERR(cp)) > - return PTR_ERR(cp); > - skp = smk_find_entry(cp); > - kfree(cp); > - if (skp == NULL) > - return -ENOENT; > - rule->smk_object = skp; > - } > + rule->smk_subject = smk_get_label(subject, len, import); > + if (IS_ERR(rule->smk_subject)) > + return PTR_ERR(rule->smk_subject); > + if (rule->smk_subject == NULL) > + return -ENOENT; > + > + rule->smk_object = smk_get_label(object, len, import); > + if (IS_ERR(rule->smk_object)) > + return PTR_ERR(rule->smk_object); > + if (rule->smk_object == NULL) > + return -ENOENT; > > rule->smk_access1 = smk_perm_from_str(access1); > if (access2) > @@ -592,6 +573,9 @@ static void smk_seq_stop(struct seq_file *s, void *v) > > static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) > { > + char *sbj; > + char *obj; > + > /* > * Don't show any rules with label names too long for > * interface file (/smack/load or /smack/load2) > @@ -605,9 +589,13 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) > if (srp->smk_access == 0) > return; > > - seq_printf(s, "%s %s", > - srp->smk_subject->smk_known, > - srp->smk_object->smk_known); > + sbj = smk_find_label_name(srp->smk_subject); > + obj = smk_find_label_name(srp->smk_object); > + > + if (sbj == NULL || obj == NULL) > + return; > + > + seq_printf(s, "%s %s", sbj, obj); > > seq_putc(s, ' '); > > @@ -798,6 +786,7 @@ static int cipso_seq_show(struct seq_file *s, void *v) > list_entry_rcu(list, struct smack_known, list); > struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat; > char sep = '/'; > + char *cp; > int i; > > /* > @@ -811,7 +800,11 @@ static int cipso_seq_show(struct seq_file *s, void *v) > if (strlen(skp->smk_known) >= SMK_LABELLEN) > return 0; > > - seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl); > + cp = smk_find_label_name(skp); > + if (cp == NULL) > + return 0; > + > + seq_printf(s, "%s %3d", cp, skp->smk_netlabel.attr.mls.lvl); > > for (i = netlbl_catmap_walk(cmp, 0); i >= 0; > i = netlbl_catmap_walk(cmp, i + 1)) { > @@ -900,7 +893,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, > */ > mutex_lock(&smack_cipso_lock); > > - skp = smk_import_entry(rule, 0); > + skp = smk_get_label(rule, 0, true); > if (IS_ERR(skp)) { > rc = PTR_ERR(skp); > goto out; > @@ -989,9 +982,14 @@ static int cipso2_seq_show(struct seq_file *s, void *v) > list_entry_rcu(list, struct smack_known, list); > struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat; > char sep = '/'; > + char *cp; > int i; > > - seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl); > + cp = smk_find_label_name(skp); > + if (cp == NULL) > + return 0; > + > + seq_printf(s, "%s %3d", cp, skp->smk_netlabel.attr.mls.lvl); > > for (i = netlbl_catmap_walk(cmp, 0); i >= 0; > i = netlbl_catmap_walk(cmp, i + 1)) { > @@ -1072,8 +1070,12 @@ static int net4addr_seq_show(struct seq_file *s, void *v) > list_entry_rcu(list, struct smk_net4addr, list); > char *kp = SMACK_CIPSO_OPTION; > > - if (skp->smk_label != NULL) > - kp = skp->smk_label->smk_known; > + if (skp->smk_label != NULL) { > + kp = smk_find_label_name(skp->smk_label); > + if (kp == NULL) > + kp = smack_known_huh.smk_known; > + } > + > seq_printf(s, "%pI4/%d %s\n", &skp->smk_host.s_addr, > skp->smk_masks, kp); > > @@ -1224,7 +1226,7 @@ static ssize_t smk_write_net4addr(struct file *file, const char __user *buf, > * If smack begins with '-', it is an option, don't import it > */ > if (smack[0] != '-') { > - skp = smk_import_entry(smack, 0); > + skp = smk_get_label(smack, 0, true); > if (IS_ERR(skp)) { > rc = PTR_ERR(skp); > goto free_out; > @@ -1343,10 +1345,16 @@ static int net6addr_seq_show(struct seq_file *s, void *v) > struct list_head *list = v; > struct smk_net6addr *skp = > list_entry(list, struct smk_net6addr, list); > + char *kp; > > - if (skp->smk_label != NULL) > - seq_printf(s, "%pI6/%d %s\n", &skp->smk_host, skp->smk_masks, > - skp->smk_label->smk_known); > + if (skp->smk_label != NULL) { > + kp = smk_find_label_name(skp->smk_label); > + if (kp == NULL) > + kp = smack_known_huh.smk_known; > + > + seq_printf(s, "%pI6/%d %s\n", &skp->smk_host, > + skp->smk_masks, kp); > + } > > return 0; > } > @@ -1500,7 +1508,7 @@ static ssize_t smk_write_net6addr(struct file *file, const char __user *buf, > * If smack begins with '-', it is an option, don't import it > */ > if (smack[0] != '-') { > - skp = smk_import_entry(smack, 0); > + skp = smk_get_label(smack, 0, true); > if (IS_ERR(skp)) { > rc = PTR_ERR(skp); > goto free_out; > @@ -1820,6 +1828,7 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf, > size_t cn, loff_t *ppos) > { > ssize_t rc; > + char *cp; > int asize; > > if (*ppos != 0) > @@ -1830,12 +1839,14 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf, > */ > mutex_lock(&smack_ambient_lock); > > - asize = strlen(smack_net_ambient->smk_known) + 1; > + cp = smk_find_label_name(smack_net_ambient); > + if (cp == NULL) > + cp = smack_known_huh.smk_known; > + > + asize = strlen(cp) + 1; > > if (cn >= asize) > - rc = simple_read_from_buffer(buf, cn, ppos, > - smack_net_ambient->smk_known, > - asize); > + rc = simple_read_from_buffer(buf, cn, ppos, cp, asize); > else > rc = -EINVAL; > > @@ -1873,7 +1884,7 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf, > goto out; > } > > - skp = smk_import_entry(data, count); > + skp = smk_get_label(data, count, true); > if (IS_ERR(skp)) { > rc = PTR_ERR(skp); > goto out; > @@ -1913,11 +1924,16 @@ static void *onlycap_seq_next(struct seq_file *s, void *v, loff_t *pos) > > static int onlycap_seq_show(struct seq_file *s, void *v) > { > + char *smack; > struct list_head *list = v; > struct smack_onlycap *sop = > list_entry_rcu(list, struct smack_onlycap, list); > > - seq_puts(s, sop->smk_label->smk_known); > + smack = smk_find_label_name(sop->smk_label); > + if (smack == NULL) > + smack = smack_known_huh.smk_known; > + > + seq_puts(s, smack); > seq_putc(s, ' '); > > return 0; > @@ -2011,7 +2027,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, > if (!*tok) > continue; > > - skp = smk_import_entry(tok, 0); > + skp = smk_get_label(tok, 0, true); > if (IS_ERR(skp)) { > rc = PTR_ERR(skp); > break; > @@ -2081,8 +2097,11 @@ static ssize_t smk_read_unconfined(struct file *filp, char __user *buf, > if (*ppos != 0) > return 0; > > - if (smack_unconfined != NULL) > - smack = smack_unconfined->smk_known; > + if (smack_unconfined != NULL) { > + smack = smk_find_label_name(smack_unconfined); > + if (smack == NULL) > + smack = smack_known_huh.smk_known; > + } > > asize = strlen(smack) + 1; > > @@ -2129,7 +2148,7 @@ static ssize_t smk_write_unconfined(struct file *file, const char __user *buf, > * > * But do so only on invalid label, not on system errors. > */ > - skp = smk_import_entry(data, count); > + skp = smk_get_label(data, count, true); > if (PTR_ERR(skp) == -EINVAL) > skp = NULL; > else if (IS_ERR(skp)) { > @@ -2526,7 +2545,6 @@ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf, > size_t count, loff_t *ppos) > { > char *data; > - const char *cp; > struct smack_known *skp; > struct smack_rule *sp; > struct list_head *rule_list; > @@ -2551,15 +2569,13 @@ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf, > goto out_data; > } > > - cp = smk_parse_smack(data, count); > - if (IS_ERR(cp)) { > - rc = PTR_ERR(cp); > + skp = smk_get_label(data, count, false); > + if (IS_ERR(skp)) { > + rc = PTR_ERR(skp); > goto out_data; > } > - > - skp = smk_find_entry(cp); > if (skp == NULL) > - goto out_cp; > + goto out_data; > > rule_list = &skp->smk_rules; > rule_lock = &skp->smk_rules_lock; > @@ -2571,8 +2587,6 @@ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf, > > mutex_unlock(rule_lock); > > -out_cp: > - kfree(cp); > out_data: > kfree(data); > > @@ -2641,8 +2655,11 @@ static ssize_t smk_read_syslog(struct file *filp, char __user *buf, > if (*ppos != 0) > return 0; > > - if (smack_syslog_label != NULL) > - smack = smack_syslog_label->smk_known; > + if (smack_syslog_label != NULL) { > + smack = smk_find_label_name(smack_syslog_label); > + if (smack == NULL) > + smack = smack_known_huh.smk_known; > + } > > asize = strlen(smack) + 1; > > @@ -2689,7 +2706,7 @@ static ssize_t smk_write_syslog(struct file *file, const char __user *buf, > * > * But do so only on invalid label, not on system errors. > */ > - skp = smk_import_entry(data, count); > + skp = smk_get_label(data, count, true); > if (PTR_ERR(skp) == -EINVAL) > skp = NULL; > else if (IS_ERR(skp)) { -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html