diff options
author | Casey Schaufler <casey@schaufler-ca.com> | 2013-05-22 18:43:03 -0700 |
---|---|---|
committer | Casey Schaufler <casey@schaufler-ca.com> | 2013-05-28 10:08:32 -0700 |
commit | 2f823ff8bec03a1e6f9e11fd0c4d54e4c7d09532 (patch) | |
tree | 8ba448a6cc7b5cdc4d173390721eda3f83a3e012 /security/smack | |
parent | c673944347edfd4362b10eea11ac384a582b1cf5 (diff) |
Smack: Improve access check performance
Each Smack label that the kernel has seen is added to a
list of labels. The list of access rules for a given subject
label hangs off of the label list entry for the label.
This patch changes the structures that contain subject
labels to point at the label list entry rather that the
label itself. Doing so removes a label list lookup in
smk_access() that was accounting for the largest single
chunk of Smack overhead.
Targeted for git://git.gitorious.org/smack-next/kernel.git
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'security/smack')
-rw-r--r-- | security/smack/smack.h | 108 | ||||
-rw-r--r-- | security/smack/smack_access.c | 41 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 331 | ||||
-rw-r--r-- | security/smack/smackfs.c | 51 |
4 files changed, 282 insertions, 249 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h index bb28e099abfe..159f25bfcf45 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -29,6 +29,38 @@ #define SMK_LONGLABEL 256 /* + * This is the repository for labels seen so that it is + * not necessary to keep allocating tiny chuncks of memory + * and so that they can be shared. + * + * Labels are never modified in place. Anytime a label + * is imported (e.g. xattrset on a file) the list is checked + * for it and it is added if it doesn't exist. The address + * is passed out in either case. Entries are added, but + * never deleted. + * + * Since labels are hanging around anyway it doesn't + * hurt to maintain a secid for those awkward situations + * where kernel components that ought to use LSM independent + * interfaces don't. The secid should go away when all of + * these components have been repaired. + * + * The cipso value associated with the label gets stored here, too. + * + * Keep the access rules for this subject label here so that + * the entire set of rules does not need to be examined every + * time. + */ +struct smack_known { + struct list_head list; + char *smk_known; + u32 smk_secid; + struct netlbl_lsm_secattr smk_netlabel; /* on wire labels */ + struct list_head smk_rules; /* access rules */ + struct mutex smk_rules_lock; /* lock for rules */ +}; + +/* * Maximum number of bytes for the levels in a CIPSO IP option. * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is * bigger than can be used, and 24 is the next lower multiple @@ -46,25 +78,25 @@ struct superblock_smack { }; struct socket_smack { - char *smk_out; /* outbound label */ - char *smk_in; /* inbound label */ - char *smk_packet; /* TCP peer label */ + struct smack_known *smk_out; /* outbound label */ + char *smk_in; /* inbound label */ + char *smk_packet; /* TCP peer label */ }; /* * Inode smack data */ struct inode_smack { - char *smk_inode; /* label of the fso */ - char *smk_task; /* label of the task */ - char *smk_mmap; /* label of the mmap domain */ - struct mutex smk_lock; /* initialization lock */ - int smk_flags; /* smack inode flags */ + char *smk_inode; /* label of the fso */ + struct smack_known *smk_task; /* label of the task */ + struct smack_known *smk_mmap; /* label of the mmap domain */ + struct mutex smk_lock; /* initialization lock */ + int smk_flags; /* smack inode flags */ }; struct task_smack { - char *smk_task; /* label for access control */ - char *smk_forked; /* label when forked */ + struct smack_known *smk_task; /* label for access control */ + struct smack_known *smk_forked; /* label when forked */ struct list_head smk_rules; /* per task access rules */ struct mutex smk_rules_lock; /* lock for the rules */ }; @@ -78,7 +110,7 @@ struct task_smack { */ struct smack_rule { struct list_head list; - char *smk_subject; + struct smack_known *smk_subject; char *smk_object; int smk_access; }; @@ -101,39 +133,7 @@ struct smk_port_label { struct sock *smk_sock; /* socket initialized on */ unsigned short smk_port; /* the port number */ char *smk_in; /* incoming label */ - char *smk_out; /* outgoing label */ -}; - -/* - * This is the repository for labels seen so that it is - * not necessary to keep allocating tiny chuncks of memory - * and so that they can be shared. - * - * Labels are never modified in place. Anytime a label - * is imported (e.g. xattrset on a file) the list is checked - * for it and it is added if it doesn't exist. The address - * is passed out in either case. Entries are added, but - * never deleted. - * - * Since labels are hanging around anyway it doesn't - * hurt to maintain a secid for those awkward situations - * where kernel components that ought to use LSM independent - * interfaces don't. The secid should go away when all of - * these components have been repaired. - * - * The cipso value associated with the label gets stored here, too. - * - * Keep the access rules for this subject label here so that - * the entire set of rules does not need to be examined every - * time. - */ -struct smack_known { - struct list_head list; - char *smk_known; - u32 smk_secid; - struct netlbl_lsm_secattr smk_netlabel; /* on wire labels */ - struct list_head smk_rules; /* access rules */ - struct mutex smk_rules_lock; /* lock for rules */ + struct smack_known *smk_out; /* outgoing label */ }; /* @@ -214,9 +214,9 @@ struct inode_smack *new_inode_smack(char *); * These functions are in smack_access.c */ int smk_access_entry(char *, char *, struct list_head *); -int smk_access(char *, char *, int, struct smk_audit_info *); +int smk_access(struct smack_known *, char *, int, struct smk_audit_info *); int smk_curacc(char *, u32, struct smk_audit_info *); -char *smack_from_secid(const u32); +struct smack_known *smack_from_secid(const u32); char *smk_parse_smack(const char *string, int len); int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int); char *smk_import(const char *, int); @@ -229,7 +229,7 @@ u32 smack_to_secid(const char *); */ extern int smack_cipso_direct; extern int smack_cipso_mapped; -extern char *smack_net_ambient; +extern struct smack_known *smack_net_ambient; extern char *smack_onlycap; extern const char *smack_cipso_option; @@ -265,17 +265,17 @@ static inline char *smk_of_inode(const struct inode *isp) } /* - * Present a pointer to the smack label in an task blob. + * Present a pointer to the smack label entry in an task blob. */ -static inline char *smk_of_task(const struct task_smack *tsp) +static inline struct smack_known *smk_of_task(const struct task_smack *tsp) { return tsp->smk_task; } /* - * Present a pointer to the forked smack label in an task blob. + * Present a pointer to the forked smack label entry in an task blob. */ -static inline char *smk_of_forked(const struct task_smack *tsp) +static inline struct smack_known *smk_of_forked(const struct task_smack *tsp) { return tsp->smk_forked; } @@ -283,7 +283,7 @@ static inline char *smk_of_forked(const struct task_smack *tsp) /* * Present a pointer to the smack label in the current task blob. */ -static inline char *smk_of_current(void) +static inline struct smack_known *smk_of_current(void) { return smk_of_task(current_security()); } @@ -294,9 +294,11 @@ static inline char *smk_of_current(void) */ static inline int smack_privileged(int cap) { + struct smack_known *skp = smk_of_current(); + if (!capable(cap)) return 0; - if (smack_onlycap == NULL || smack_onlycap == smk_of_current()) + if (smack_onlycap == NULL || smack_onlycap == skp->smk_known) return 1; return 0; } diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 2e397a88d410..53f2327a592f 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -93,7 +93,7 @@ int smk_access_entry(char *subject_label, char *object_label, list_for_each_entry_rcu(srp, rule_list, list) { if (srp->smk_object == object_label && - srp->smk_subject == subject_label) { + srp->smk_subject->smk_known == subject_label) { may = srp->smk_access; break; } @@ -104,7 +104,7 @@ int smk_access_entry(char *subject_label, char *object_label, /** * smk_access - determine if a subject has a specific access to an object - * @subject_label: a pointer to the subject's Smack label + * @subject_known: a pointer to the subject's Smack label entry * @object_label: a pointer to the object's Smack label * @request: the access requested, in "MAY" format * @a : a pointer to the audit data @@ -115,10 +115,9 @@ int smk_access_entry(char *subject_label, char *object_label, * * Smack labels are shared on smack_list */ -int smk_access(char *subject_label, char *object_label, int request, - struct smk_audit_info *a) +int smk_access(struct smack_known *subject_known, char *object_label, + int request, struct smk_audit_info *a) { - struct smack_known *skp; int may = MAY_NOT; int rc = 0; @@ -127,7 +126,7 @@ int smk_access(char *subject_label, char *object_label, int request, * * A star subject can't access any object. */ - if (subject_label == smack_known_star.smk_known) { + if (subject_known == &smack_known_star) { rc = -EACCES; goto out_audit; } @@ -137,7 +136,7 @@ int smk_access(char *subject_label, char *object_label, int request, * An internet subject can access any object. */ if (object_label == smack_known_web.smk_known || - subject_label == smack_known_web.smk_known) + subject_known == &smack_known_web) goto out_audit; /* * A star object can be accessed by any subject. @@ -148,7 +147,7 @@ int smk_access(char *subject_label, char *object_label, int request, * An object can be accessed in any way by a subject * with the same label. */ - if (subject_label == object_label) + if (subject_known->smk_known == object_label) goto out_audit; /* * A hat subject can read any object. @@ -157,7 +156,7 @@ int smk_access(char *subject_label, char *object_label, int request, if ((request & MAY_ANYREAD) == request) { if (object_label == smack_known_floor.smk_known) goto out_audit; - if (subject_label == smack_known_hat.smk_known) + if (subject_known == &smack_known_hat) goto out_audit; } /* @@ -167,9 +166,9 @@ int smk_access(char *subject_label, char *object_label, int request, * good. A negative response from smk_access_entry() * indicates there is no entry for this pair. */ - skp = smk_find_entry(subject_label); rcu_read_lock(); - may = smk_access_entry(subject_label, object_label, &skp->smk_rules); + may = smk_access_entry(subject_known->smk_known, object_label, + &subject_known->smk_rules); rcu_read_unlock(); if (may > 0 && (request & may) == request) @@ -179,7 +178,8 @@ int smk_access(char *subject_label, char *object_label, int request, out_audit: #ifdef CONFIG_AUDIT if (a) - smack_log(subject_label, object_label, request, rc, a); + smack_log(subject_known->smk_known, object_label, request, + rc, a); #endif return rc; } @@ -198,20 +198,21 @@ out_audit: int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) { struct task_smack *tsp = current_security(); - char *sp = smk_of_task(tsp); + struct smack_known *skp = smk_of_task(tsp); int may; int rc; /* * Check the global rule list */ - rc = smk_access(sp, obj_label, mode, NULL); + rc = smk_access(skp, obj_label, mode, NULL); if (rc == 0) { /* * If there is an entry in the task's rule list * it can further restrict access. */ - may = smk_access_entry(sp, obj_label, &tsp->smk_rules); + may = smk_access_entry(skp->smk_known, obj_label, + &tsp->smk_rules); if (may < 0) goto out_audit; if ((mode & may) == mode) @@ -228,7 +229,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) out_audit: #ifdef CONFIG_AUDIT if (a) - smack_log(sp, obj_label, mode, rc, a); + smack_log(skp->smk_known, obj_label, mode, rc, a); #endif return rc; } @@ -513,10 +514,10 @@ char *smk_import(const char *string, int len) * smack_from_secid - find the Smack label associated with a secid * @secid: an integer that might be associated with a Smack label * - * Returns a pointer to the appropriate Smack label if there is one, + * Returns a pointer to the appropriate Smack label entry if there is one, * otherwise a pointer to the invalid Smack label. */ -char *smack_from_secid(const u32 secid) +struct smack_known *smack_from_secid(const u32 secid) { struct smack_known *skp; @@ -524,7 +525,7 @@ char *smack_from_secid(const u32 secid) list_for_each_entry_rcu(skp, &smack_known_list, list) { if (skp->smk_secid == secid) { rcu_read_unlock(); - return skp->smk_known; + return skp; } } @@ -533,7 +534,7 @@ char *smack_from_secid(const u32 secid) * of a secid that is not on the list. */ rcu_read_unlock(); - return smack_known_invalid.smk_known; + return &smack_known_invalid; } /** diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 609e89de3c24..3669d9f9824e 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -62,11 +62,12 @@ LIST_HEAD(smk_ipv6_port_list); * Returns a pointer to the master list entry for the Smack label * or NULL if there was no label to fetch. */ -static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp) +static struct smack_known *smk_fetch(const char *name, struct inode *ip, + struct dentry *dp) { int rc; char *buffer; - char *result = NULL; + struct smack_known *skp = NULL; if (ip->i_op->getxattr == NULL) return NULL; @@ -77,11 +78,11 @@ static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp) rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL); if (rc > 0) - result = smk_import(buffer, rc); + skp = smk_import_entry(buffer, rc); kfree(buffer); - return result; + return skp; } /** @@ -111,7 +112,8 @@ struct inode_smack *new_inode_smack(char *smack) * * Returns the new blob or NULL if there's no memory available */ -static struct task_smack *new_task_smack(char *task, char *forked, gfp_t gfp) +static struct task_smack *new_task_smack(struct smack_known *task, + struct smack_known *forked, gfp_t gfp) { struct task_smack *tsp; @@ -173,17 +175,17 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) { int rc; struct smk_audit_info ad; - char *tsp; + struct smack_known *skp; rc = cap_ptrace_access_check(ctp, mode); if (rc != 0) return rc; - tsp = smk_of_task(task_security(ctp)); + skp = smk_of_task(task_security(ctp)); smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, ctp); - rc = smk_curacc(tsp, MAY_READWRITE, &ad); + rc = smk_curacc(skp->smk_known, MAY_READWRITE, &ad); return rc; } @@ -199,17 +201,17 @@ static int smack_ptrace_traceme(struct task_struct *ptp) { int rc; struct smk_audit_info ad; - char *tsp; + struct smack_known *skp; rc = cap_ptrace_traceme(ptp); if (rc != 0) return rc; - tsp = smk_of_task(task_security(ptp)); + skp = smk_of_task(task_security(ptp)); smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, ptp); - rc = smk_curacc(tsp, MAY_READWRITE, &ad); + rc = smk_curacc(skp->smk_known, MAY_READWRITE, &ad); return rc; } @@ -224,12 +226,12 @@ static int smack_ptrace_traceme(struct task_struct *ptp) static int smack_syslog(int typefrom_file) { int rc = 0; - char *sp = smk_of_current(); + struct smack_known *skp = smk_of_current(); if (smack_privileged(CAP_MAC_OVERRIDE)) return 0; - if (sp != smack_known_floor.smk_known) + if (skp != &smack_known_floor) rc = -EACCES; return rc; @@ -533,7 +535,9 @@ static int smack_bprm_secureexec(struct linux_binprm *bprm) */ static int smack_inode_alloc_security(struct inode *inode) { - inode->i_security = new_inode_smack(smk_of_current()); + struct smack_known *skp = smk_of_current(); + + inode->i_security = new_inode_smack(skp->smk_known); if (inode->i_security == NULL) return -ENOMEM; return 0; @@ -566,9 +570,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, char **name, void **value, size_t *len) { - struct smack_known *skp; struct inode_smack *issp = inode->i_security; - char *csp = smk_of_current(); + struct smack_known *skp = smk_of_current(); char *isp = smk_of_inode(inode); char *dsp = smk_of_inode(dir); int may; @@ -580,9 +583,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, } if (value) { - skp = smk_find_entry(csp); rcu_read_lock(); - may = smk_access_entry(csp, dsp, &skp->smk_rules); + may = smk_access_entry(skp->smk_known, dsp, &skp->smk_rules); rcu_read_unlock(); /* @@ -871,29 +873,31 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { - char *nsp; + struct smack_known *skp; struct inode_smack *isp = dentry->d_inode->i_security; + if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { + isp->smk_flags |= SMK_INODE_TRANSMUTE; + return; + } + + skp = smk_import_entry(value, size); if (strcmp(name, XATTR_NAME_SMACK) == 0) { - nsp = smk_import(value, size); - if (nsp != NULL) - isp->smk_inode = nsp; + if (skp != NULL) + isp->smk_inode = skp->smk_known; else isp->smk_inode = smack_known_invalid.smk_known; } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { - nsp = smk_import(value, size); - if (nsp != NULL) - isp->smk_task = nsp; + if (skp != NULL) + isp->smk_task = skp; else - isp->smk_task = smack_known_invalid.smk_known; + isp->smk_task = &smack_known_invalid; } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { - nsp = smk_import(value, size); - if (nsp != NULL) - isp->smk_mmap = nsp; + if (skp != NULL) + isp->smk_mmap = skp; else - isp->smk_mmap = smack_known_invalid.smk_known; - } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) - isp->smk_flags |= SMK_INODE_TRANSMUTE; + isp->smk_mmap = &smack_known_invalid; + } return; } @@ -999,7 +1003,7 @@ static int smack_inode_getsecurity(const struct inode *inode, if (strcmp(name, XATTR_SMACK_IPIN) == 0) isp = ssp->smk_in; else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) - isp = ssp->smk_out; + isp = ssp->smk_out->smk_known; else return -EOPNOTSUPP; @@ -1079,7 +1083,9 @@ static int smack_file_permission(struct file *file, int mask) */ static int smack_file_alloc_security(struct file *file) { - file->f_security = smk_of_current(); + struct smack_known *skp = smk_of_current(); + + file->f_security = skp->smk_known; return 0; } @@ -1190,10 +1196,9 @@ static int smack_mmap_file(struct file *file, unsigned long flags) { struct smack_known *skp; + struct smack_known *mkp; struct smack_rule *srp; struct task_smack *tsp; - char *sp; - char *msmack; char *osmack; struct inode_smack *isp; int may; @@ -1207,11 +1212,10 @@ static int smack_mmap_file(struct file *file, isp = file_inode(file)->i_security; if (isp->smk_mmap == NULL) return 0; - msmack = isp->smk_mmap; + mkp = isp->smk_mmap; tsp = current_security(); - sp = smk_of_current(); - skp = smk_find_entry(sp); + skp = smk_of_current(); rc = 0; rcu_read_lock(); @@ -1225,13 +1229,13 @@ static int smack_mmap_file(struct file *file, /* * Matching labels always allows access. */ - if (msmack == osmack) + if (mkp->smk_known == osmack) continue; /* * If there is a matching local rule take * that into account as well. */ - may = smk_access_entry(srp->smk_subject, osmack, + may = smk_access_entry(srp->smk_subject->smk_known, osmack, &tsp->smk_rules); if (may == -ENOENT) may = srp->smk_access; @@ -1249,8 +1253,8 @@ static int smack_mmap_file(struct file *file, * If there isn't one a SMACK64MMAP subject * can't have as much access as current. */ - skp = smk_find_entry(msmack); - mmay = smk_access_entry(msmack, osmack, &skp->smk_rules); + mmay = smk_access_entry(mkp->smk_known, osmack, + &mkp->smk_rules); if (mmay == -ENOENT) { rc = -EACCES; break; @@ -1259,7 +1263,8 @@ static int smack_mmap_file(struct file *file, * If there is a local entry it modifies the * potential access, too. */ - tmay = smk_access_entry(msmack, osmack, &tsp->smk_rules); + tmay = smk_access_entry(mkp->smk_known, osmack, + &tsp->smk_rules); if (tmay != -ENOENT) mmay &= tmay; @@ -1288,7 +1293,9 @@ static int smack_mmap_file(struct file *file, */ static int smack_file_set_fowner(struct file *file) { - file->f_security = smk_of_current(); + struct smack_known *skp = smk_of_current(); + + file->f_security = skp->smk_known; return 0; } @@ -1306,9 +1313,10 @@ static int smack_file_set_fowner(struct file *file) static int smack_file_send_sigiotask(struct task_struct *tsk, struct fown_struct *fown, int signum) { + struct smack_known *skp; + struct smack_known *tkp = smk_of_task(tsk->cred->security); struct file *file; int rc; - char *tsp = smk_of_task(tsk->cred->security); struct smk_audit_info ad; /* @@ -1317,13 +1325,14 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, file = container_of(fown, struct file, f_owner); /* we don't log here as rc can be overriden */ - rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL); + skp = smk_find_entry(file->f_security); + rc = smk_access(skp, tkp->smk_known, MAY_WRITE, NULL); if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) rc = 0; smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, tsk); - smack_log(file->f_security, tsp, MAY_WRITE, rc, &ad); + smack_log(file->f_security, tkp->smk_known, MAY_WRITE, rc, &ad); return rc; } @@ -1478,12 +1487,12 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old) static int smack_kernel_act_as(struct cred *new, u32 secid) { struct task_smack *new_tsp = new->security; - char *smack = smack_from_secid(secid); + struct smack_known *skp = smack_from_secid(secid); - if (smack == NULL) + if (skp == NULL) return -EINVAL; - new_tsp->smk_task = smack; + new_tsp->smk_task = skp; return 0; } @@ -1501,8 +1510,8 @@ static int smack_kernel_create_files_as(struct cred *new, struct inode_smack *isp = inode->i_security; struct task_smack *tsp = new->security; - tsp->smk_forked = isp->smk_inode; - tsp->smk_task = isp->smk_inode; + tsp->smk_forked = smk_find_entry(isp->smk_inode); + tsp->smk_task = tsp->smk_forked; return 0; } @@ -1518,10 +1527,11 @@ static int smk_curacc_on_task(struct task_struct *p, int access, const char *caller) { struct smk_audit_info ad; + struct smack_known *skp = smk_of_task(task_security(p)); smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, p); - return smk_curacc(smk_of_task(task_security(p)), access, &ad); + return smk_curacc(skp->smk_known, access, &ad); } /** @@ -1567,7 +1577,9 @@ static int smack_task_getsid(struct task_struct *p) */ static void smack_task_getsecid(struct task_struct *p, u32 *secid) { - *secid = smack_to_secid(smk_of_task(task_security(p))); + struct smack_known *skp = smk_of_task(task_security(p)); + + *secid = skp->smk_secid; } /** @@ -1671,6 +1683,8 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, int sig, u32 secid) { struct smk_audit_info ad; + struct smack_known *skp; + struct smack_known *tkp = smk_of_task(task_security(p)); smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, p); @@ -1679,15 +1693,14 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, * can write the receiver. */ if (secid == 0) - return smk_curacc(smk_of_task(task_security(p)), MAY_WRITE, - &ad); + return smk_curacc(tkp->smk_known, MAY_WRITE, &ad); /* * If the secid isn't 0 we're dealing with some USB IO * specific behavior. This is not clean. For one thing * we can't take privilege into account. */ - return smk_access(smack_from_secid(secid), - smk_of_task(task_security(p)), MAY_WRITE, &ad); + skp = smack_from_secid(secid); + return smk_access(skp, tkp->smk_known, MAY_WRITE, &ad); } /** @@ -1719,7 +1732,9 @@ static int smack_task_wait(struct task_struct *p) static void smack_task_to_inode(struct task_struct *p, struct inode *inode) { struct inode_smack *isp = inode->i_security; - isp->smk_inode = smk_of_task(task_security(p)); + struct smack_known *skp = smk_of_task(task_security(p)); + + isp->smk_inode = skp->smk_known; } /* @@ -1738,15 +1753,15 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode) */ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) { - char *csp = smk_of_current(); + struct smack_known *skp = smk_of_current(); struct socket_smack *ssp; ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); if (ssp == NULL) return -ENOMEM; - ssp->smk_in = csp; - ssp->smk_out = csp; + ssp->smk_in = skp->smk_known; + ssp->smk_out = skp; ssp->smk_packet = NULL; sk->sk_security = ssp; @@ -1833,7 +1848,7 @@ static int smack_netlabel(struct sock *sk, int labeled) labeled == SMACK_UNLABELED_SOCKET) netlbl_sock_delattr(sk); else { - skp = smk_find_entry(ssp->smk_out); + skp = ssp->smk_out; rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel); } @@ -1856,6 +1871,7 @@ static int smack_netlabel(struct sock *sk, int labeled) */ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) { + struct smack_known *skp; int rc; int sk_lbl; char *hostsp; @@ -1874,7 +1890,8 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr; #endif sk_lbl = SMACK_UNLABELED_SOCKET; - rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad); + skp = ssp->smk_out; + rc = smk_access(skp, hostsp, MAY_WRITE, &ad); } else { sk_lbl = SMACK_CIPSO_SOCKET; rc = 0; @@ -1974,8 +1991,8 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address, struct sockaddr_in6 *addr6; struct smk_port_label *spp; struct socket_smack *ssp = sk->sk_security; + struct smack_known *skp; unsigned short port = 0; - char *subject; char *object; struct smk_audit_info ad; #ifdef CONFIG_AUDIT @@ -1983,11 +2000,11 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address, #endif if (act == SMK_RECEIVING) { - subject = smack_net_ambient; + skp = smack_net_ambient; object = ssp->smk_in; } else { - subject = ssp->smk_out; - object = smack_net_ambient; + skp = ssp->smk_out; + object = smack_net_ambient->smk_known; } /* @@ -2008,7 +2025,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address, * It's local so the send check has to have passed. */ if (act == SMK_RECEIVING) { - subject = smack_known_web.smk_known; + skp = &smack_known_web; goto auditout; } @@ -2017,7 +2034,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address, continue; object = spp->smk_in; if (act == SMK_CONNECTING) - ssp->smk_packet = spp->smk_out; + ssp->smk_packet = spp->smk_out->smk_known; break; } @@ -2032,7 +2049,7 @@ auditout: else ad.a.u.net->v6info.daddr = addr6->sin6_addr; #endif - return smk_access(subject, object, MAY_WRITE, &ad); + return smk_access(skp, object, MAY_WRITE, &ad); } /** @@ -2050,7 +2067,7 @@ auditout: static int smack_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) { - char *sp; + struct smack_known *skp; struct inode_smack *nsp = inode->i_security; struct socket_smack *ssp; struct socket *sock; @@ -2059,12 +2076,12 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, if (value == NULL || size > SMK_LONGLABEL || size == 0) return -EACCES; - sp = smk_import(value, size); - if (sp == NULL) + skp = smk_import_entry(value, size); + if (skp == NULL) return -EINVAL; if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { - nsp->smk_inode = sp; + nsp->smk_inode = skp->smk_known; nsp->smk_flags |= SMK_INODE_INSTANT; return 0; } @@ -2081,9 +2098,9 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, ssp = sock->sk->sk_security; if (strcmp(name, XATTR_SMACK_IPIN) == 0) - ssp->smk_in = sp; + ssp->smk_in = skp->smk_known; else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { - ssp->smk_out = sp; + ssp->smk_out = skp; if (sock->sk->sk_family == PF_INET) { rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); if (rc != 0) @@ -2203,7 +2220,9 @@ static int smack_flags_to_may(int flags) */ static int smack_msg_msg_alloc_security(struct msg_msg *msg) { - msg->security = smk_of_current(); + struct smack_known *skp = smk_of_current(); + + msg->security = skp->smk_known; return 0; } @@ -2238,8 +2257,9 @@ static char *smack_of_shm(struct shmid_kernel *shp) static int smack_shm_alloc_security(struct shmid_kernel *shp) { struct kern_ipc_perm *isp = &shp->shm_perm; + struct smack_known *skp = smk_of_current(); - isp->security = smk_of_current(); + isp->security = skp->smk_known; return 0; } @@ -2361,8 +2381,9 @@ static char *smack_of_sem(struct sem_array *sma) static int smack_sem_alloc_security(struct sem_array *sma) { struct kern_ipc_perm *isp = &sma->sem_perm; + struct smack_known *skp = smk_of_current(); - isp->security = smk_of_current(); + isp->security = skp->smk_known; return 0; } @@ -2479,8 +2500,9 @@ static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops, static int smack_msg_queue_alloc_security(struct msg_queue *msq) { struct kern_ipc_perm *kisp = &msq->q_perm; + struct smack_known *skp = smk_of_current(); - kisp->security = smk_of_current(); + kisp->security = skp->smk_known; return 0; } @@ -2652,8 +2674,8 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) struct super_block *sbp; struct superblock_smack *sbsp; struct inode_smack *isp; - char *csp = smk_of_current(); - char *fetched; + struct smack_known *skp; + struct smack_known *ckp = smk_of_current(); char *final; char trattr[TRANS_TRUE_SIZE]; int transflag = 0; @@ -2720,7 +2742,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) * Programs that change smack have to treat the * pty with respect. */ - final = csp; + final = ckp->smk_known; break; case SOCKFS_MAGIC: /* @@ -2775,9 +2797,9 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) * Get the dentry for xattr. */ dp = dget(opt_dentry); - fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp); - if (fetched != NULL) - final = fetched; + skp = smk_fetch(XATTR_NAME_SMACK, inode, dp); + if (skp != NULL) + final = skp->smk_known; /* * Transmuting directory @@ -2817,7 +2839,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) } if (final == NULL) - isp->smk_inode = csp; + isp->smk_inode = ckp->smk_known; else isp->smk_inode = final; @@ -2840,13 +2862,14 @@ unlockandout: */ static int smack_getprocattr(struct task_struct *p, char *name, char **value) { + struct smack_known *skp = smk_of_task(task_security(p)); char *cp; int slen; if (strcmp(name, "current") != 0) return -EINVAL; - cp = kstrdup(smk_of_task(task_security(p)), GFP_KERNEL); + cp = kstrdup(skp->smk_known, GFP_KERNEL); if (cp == NULL) return -ENOMEM; @@ -2872,7 +2895,7 @@ static int smack_setprocattr(struct task_struct *p, char *name, { struct task_smack *tsp; struct cred *new; - char *newsmack; + struct smack_known *skp; /* * Changing another process' Smack value is too dangerous @@ -2890,14 +2913,14 @@ static int smack_setprocattr(struct task_struct *p, char *name, if (strcmp(name, "current") != 0) return -EINVAL; - newsmack = smk_import(value, size); - if (newsmack == NULL) + skp = smk_import_entry(value, size); + if (skp == NULL) return -EINVAL; /* * No process is ever allowed the web ("@") label. */ - if (newsmack == smack_known_web.smk_known) + if (skp == &smack_known_web) return -EPERM; new = prepare_creds(); @@ -2905,7 +2928,7 @@ static int smack_setprocattr(struct task_struct *p, char *name, return -ENOMEM; tsp = new->security; - tsp->smk_task = newsmack; + tsp->smk_task = skp; commit_creds(new); return size; @@ -2923,6 +2946,7 @@ static int smack_setprocattr(struct task_struct *p, char *name, static int smack_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) { + struct smack_known *skp; struct socket_smack *ssp = sock->sk_security; struct socket_smack *osp = other->sk_security; struct socket_smack *nsp = newsk->sk_security; @@ -2936,15 +2960,17 @@ static int smack_unix_stream_connect(struct sock *sock, smk_ad_setfield_u_net_sk(&ad, other); #endif - if (!smack_privileged(CAP_MAC_OVERRIDE)) - rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); + if (!smack_privileged(CAP_MAC_OVERRIDE)) { + skp = ssp->smk_out; + rc = smk_access(skp, osp->smk_in, MAY_WRITE, &ad); + } /* * Cros |