diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/smack/Kconfig | 16 | ||||
-rw-r--r-- | security/smack/smack.h | 39 | ||||
-rw-r--r-- | security/smack/smack_access.c | 118 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 545 | ||||
-rw-r--r-- | security/smack/smackfs.c | 76 |
5 files changed, 520 insertions, 274 deletions
diff --git a/security/smack/Kconfig b/security/smack/Kconfig index e69de9c642b7..b065f9789418 100644 --- a/security/smack/Kconfig +++ b/security/smack/Kconfig @@ -12,3 +12,19 @@ config SECURITY_SMACK of other mandatory security schemes. If you are unsure how to answer this question, answer N. +config SECURITY_SMACK_BRINGUP + bool "Reporting on access granted by Smack rules" + depends on SECURITY_SMACK + default n + help + Enable the bring-up ("b") access mode in Smack rules. + When access is granted by a rule with the "b" mode a + message about the access requested is generated. The + intention is that a process can be granted a wide set + of access initially with the bringup mode set on the + rules. The developer can use the information to + identify which rules are necessary and what accesses + may be inappropriate. The developer can reduce the + access rule set once the behavior is well understood. + This is a superior mechanism to the oft abused + "permissive" mode of other systems. diff --git a/security/smack/smack.h b/security/smack/smack.h index 020307ef0972..b828a379377c 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -71,11 +71,11 @@ struct smack_known { #define SMK_CIPSOLEN 24 struct superblock_smack { - char *smk_root; - char *smk_floor; - char *smk_hat; - char *smk_default; - int smk_initialized; + struct smack_known *smk_root; + struct smack_known *smk_floor; + struct smack_known *smk_hat; + struct smack_known *smk_default; + int smk_initialized; }; struct socket_smack { @@ -88,7 +88,7 @@ struct socket_smack { * Inode smack data */ struct inode_smack { - char *smk_inode; /* label of the fso */ + struct smack_known *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 */ @@ -112,7 +112,7 @@ struct task_smack { struct smack_rule { struct list_head list; struct smack_known *smk_subject; - char *smk_object; + struct smack_known *smk_object; int smk_access; }; @@ -123,7 +123,7 @@ struct smk_netlbladdr { struct list_head list; struct sockaddr_in smk_host; /* network address */ struct in_addr smk_mask; /* network mask */ - char *smk_label; /* label */ + struct smack_known *smk_label; /* label */ }; /* @@ -191,6 +191,7 @@ struct smk_port_label { */ #define MAY_TRANSMUTE 0x00001000 /* Controls directory labeling */ #define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */ +#define MAY_BRINGUP 0x00004000 /* Report use of this rule */ /* * Just to make the common cases easier to deal with @@ -200,9 +201,9 @@ struct smk_port_label { #define MAY_NOT 0 /* - * Number of access types used by Smack (rwxatl) + * Number of access types used by Smack (rwxatlb) */ -#define SMK_NUM_ACCESS_TYPE 6 +#define SMK_NUM_ACCESS_TYPE 7 /* SMACK data */ struct smack_audit_data { @@ -226,23 +227,23 @@ struct smk_audit_info { /* * These functions are in smack_lsm.c */ -struct inode_smack *new_inode_smack(char *); +struct inode_smack *new_inode_smack(struct smack_known *); /* * These functions are in smack_access.c */ int smk_access_entry(char *, char *, struct list_head *); -int smk_access(struct smack_known *, char *, int, struct smk_audit_info *); -int smk_tskacc(struct task_smack *, char *, u32, struct smk_audit_info *); -int smk_curacc(char *, u32, struct smk_audit_info *); +int smk_access(struct smack_known *, struct smack_known *, + int, struct smk_audit_info *); +int smk_tskacc(struct task_smack *, struct smack_known *, + u32, struct smk_audit_info *); +int smk_curacc(struct smack_known *, u32, struct smk_audit_info *); 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); struct smack_known *smk_import_entry(const char *, int); void smk_insert_entry(struct smack_known *skp); struct smack_known *smk_find_entry(const char *); -u32 smack_to_secid(const char *); /* * Shared data. @@ -252,7 +253,7 @@ extern int smack_cipso_mapped; extern struct smack_known *smack_net_ambient; extern struct smack_known *smack_onlycap; extern struct smack_known *smack_syslog_label; -extern const char *smack_cipso_option; +extern struct smack_known smack_cipso_option; extern int smack_ptrace_rule; extern struct smack_known smack_known_floor; @@ -281,9 +282,9 @@ static inline int smk_inode_transmutable(const struct inode *isp) } /* - * Present a pointer to the smack label in an inode blob. + * Present a pointer to the smack label entry in an inode blob. */ -static inline char *smk_of_inode(const struct inode *isp) +static inline struct smack_known *smk_of_inode(const struct inode *isp) { struct inode_smack *sip = isp->i_security; return sip->smk_inode; diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index f97d0842e621..5b970ffde024 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -94,7 +94,7 @@ int smk_access_entry(char *subject_label, char *object_label, struct smack_rule *srp; list_for_each_entry_rcu(srp, rule_list, list) { - if (srp->smk_object == object_label && + if (srp->smk_object->smk_known == object_label && srp->smk_subject->smk_known == subject_label) { may = srp->smk_access; break; @@ -111,8 +111,8 @@ int smk_access_entry(char *subject_label, char *object_label, /** * smk_access - determine if a subject has a specific access to an object - * @subject_known: a pointer to the subject's Smack label entry - * @object_label: a pointer to the object's Smack label + * @subject: a pointer to the subject's Smack label entry + * @object: a pointer to the object's Smack label entry * @request: the access requested, in "MAY" format * @a : a pointer to the audit data * @@ -122,8 +122,8 @@ int smk_access_entry(char *subject_label, char *object_label, * * Smack labels are shared on smack_list */ -int smk_access(struct smack_known *subject_known, char *object_label, - int request, struct smk_audit_info *a) +int smk_access(struct smack_known *subject, struct smack_known *object, + int request, struct smk_audit_info *a) { int may = MAY_NOT; int rc = 0; @@ -133,7 +133,7 @@ int smk_access(struct smack_known *subject_known, char *object_label, * * A star subject can't access any object. */ - if (subject_known == &smack_known_star) { + if (subject == &smack_known_star) { rc = -EACCES; goto out_audit; } @@ -142,28 +142,28 @@ int smk_access(struct smack_known *subject_known, char *object_label, * Tasks cannot be assigned the internet label. * An internet subject can access any object. */ - if (object_label == smack_known_web.smk_known || - subject_known == &smack_known_web) + if (object == &smack_known_web || + subject == &smack_known_web) goto out_audit; /* * A star object can be accessed by any subject. */ - if (object_label == smack_known_star.smk_known) + if (object == &smack_known_star) goto out_audit; /* * An object can be accessed in any way by a subject * with the same label. */ - if (subject_known->smk_known == object_label) + if (subject->smk_known == object->smk_known) goto out_audit; /* * A hat subject can read any object. * A floor object can be read by any subject. */ if ((request & MAY_ANYREAD) == request) { - if (object_label == smack_known_floor.smk_known) + if (object == &smack_known_floor) goto out_audit; - if (subject_known == &smack_known_hat) + if (subject == &smack_known_hat) goto out_audit; } /* @@ -174,27 +174,38 @@ int smk_access(struct smack_known *subject_known, char *object_label, * indicates there is no entry for this pair. */ rcu_read_lock(); - may = smk_access_entry(subject_known->smk_known, object_label, - &subject_known->smk_rules); + may = smk_access_entry(subject->smk_known, object->smk_known, + &subject->smk_rules); rcu_read_unlock(); - if (may > 0 && (request & may) == request) + if (may <= 0 || (request & may) != request) { + rc = -EACCES; goto out_audit; + } +#ifdef CONFIG_SECURITY_SMACK_BRINGUP + /* + * Return a positive value if using bringup mode. + * This allows the hooks to identify checks that + * succeed because of "b" rules. + */ + if (may & MAY_BRINGUP) + rc = MAY_BRINGUP; +#endif - rc = -EACCES; out_audit: #ifdef CONFIG_AUDIT if (a) - smack_log(subject_known->smk_known, object_label, request, - rc, a); + smack_log(subject->smk_known, object->smk_known, + request, rc, a); #endif + return rc; } /** * smk_tskacc - determine if a task has a specific access to an object - * @tsp: a pointer to the subject task - * @obj_label: a pointer to the object's Smack label + * @tsp: a pointer to the subject's task + * @obj_known: a pointer to the object's label entry * @mode: the access requested, in "MAY" format * @a : common audit data * @@ -203,24 +214,25 @@ out_audit: * non zero otherwise. It allows that the task may have the capability * to override the rules. */ -int smk_tskacc(struct task_smack *subject, char *obj_label, +int smk_tskacc(struct task_smack *tsp, struct smack_known *obj_known, u32 mode, struct smk_audit_info *a) { - struct smack_known *skp = smk_of_task(subject); + struct smack_known *sbj_known = smk_of_task(tsp); int may; int rc; /* * Check the global rule list */ - rc = smk_access(skp, obj_label, mode, NULL); - if (rc == 0) { + rc = smk_access(sbj_known, obj_known, 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(skp->smk_known, obj_label, - &subject->smk_rules); + may = smk_access_entry(sbj_known->smk_known, + obj_known->smk_known, + &tsp->smk_rules); if (may < 0) goto out_audit; if ((mode & may) == mode) @@ -237,14 +249,15 @@ int smk_tskacc(struct task_smack *subject, char *obj_label, out_audit: #ifdef CONFIG_AUDIT if (a) - smack_log(skp->smk_known, obj_label, mode, rc, a); + smack_log(sbj_known->smk_known, obj_known->smk_known, + mode, rc, a); #endif return rc; } /** * smk_curacc - determine if current has a specific access to an object - * @obj_label: a pointer to the object's Smack label + * @obj_known: a pointer to the object's Smack label entry * @mode: the access requested, in "MAY" format * @a : common audit data * @@ -253,11 +266,12 @@ out_audit: * non zero otherwise. It allows that current may have the capability * to override the rules. */ -int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) +int smk_curacc(struct smack_known *obj_known, + u32 mode, struct smk_audit_info *a) { struct task_smack *tsp = current_security(); - return smk_tskacc(tsp, obj_label, mode, a); + return smk_tskacc(tsp, obj_known, mode, a); } #ifdef CONFIG_AUDIT @@ -328,6 +342,13 @@ void smack_log(char *subject_label, char *object_label, int request, struct smack_audit_data *sad; struct common_audit_data *a = &ad->a; +#ifdef CONFIG_SECURITY_SMACK_BRINGUP + /* + * The result may be positive in bringup mode. + */ + if (result > 0) + result = 0; +#endif /* check if we have to log the current event */ if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0) return; @@ -544,27 +565,6 @@ unlockout: } /** - * smk_import - import a smack label - * @string: a text string that might be a Smack label - * @len: the maximum size, or zero if it is NULL terminated. - * - * Returns a pointer to the label in the label list that - * matches the passed string, adding it if necessary. - */ -char *smk_import(const char *string, int len) -{ - struct smack_known *skp; - - /* labels cannot begin with a '-' */ - if (string[0] == '-') - return NULL; - skp = smk_import_entry(string, len); - if (skp == NULL) - return NULL; - return skp->smk_known; -} - -/** * smack_from_secid - find the Smack label associated with a secid * @secid: an integer that might be associated with a Smack label * @@ -590,19 +590,3 @@ struct smack_known *smack_from_secid(const u32 secid) rcu_read_unlock(); return &smack_known_invalid; } - -/** - * smack_to_secid - find the secid associated with a Smack label - * @smack: the Smack label - * - * Returns the appropriate secid if there is one, - * otherwise 0 - */ -u32 smack_to_secid(const char *smack) -{ - struct smack_known *skp = smk_find_entry(smack); - - if (skp == NULL) - return 0; - return skp->smk_secid; -} diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index e6ab307ce86e..93dc876734a4 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -54,6 +54,151 @@ LIST_HEAD(smk_ipv6_port_list); +#ifdef CONFIG_SECURITY_SMACK_BRINGUP +static void smk_bu_mode(int mode, char *s) +{ + int i = 0; + + if (mode & MAY_READ) + s[i++] = 'r'; + if (mode & MAY_WRITE) + s[i++] = 'w'; + if (mode & MAY_EXEC) + s[i++] = 'x'; + if (mode & MAY_APPEND) + s[i++] = 'a'; + if (mode & MAY_TRANSMUTE) + s[i++] = 't'; + if (mode & MAY_LOCK) + s[i++] = 'l'; + if (i == 0) + s[i++] = '-'; + s[i] = '\0'; +} +#endif + +#ifdef CONFIG_SECURITY_SMACK_BRINGUP +static int smk_bu_note(char *note, struct smack_known *sskp, + struct smack_known *oskp, int mode, int rc) +{ + char acc[SMK_NUM_ACCESS_TYPE + 1]; + + if (rc <= 0) + return rc; + + smk_bu_mode(mode, acc); + pr_info("Smack Bringup: (%s %s %s) %s\n", + sskp->smk_known, oskp->smk_known, acc, note); + return 0; +} +#else +#define smk_bu_note(note, sskp, oskp, mode, RC) (RC) +#endif + +#ifdef CONFIG_SECURITY_SMACK_BRINGUP +static int smk_bu_current(char *note, struct smack_known *oskp, + int mode, int rc) +{ + struct task_smack *tsp = current_security(); + char acc[SMK_NUM_ACCESS_TYPE + 1]; + + if (rc <= 0) + return rc; + + smk_bu_mode(mode, acc); + pr_info("Smack Bringup: (%s %s %s) %s %s\n", + tsp->smk_task->smk_known, oskp->smk_known, + acc, current->comm, note); + return 0; +} +#else +#define smk_bu_current(note, oskp, mode, RC) (RC) +#endif + +#ifdef CONFIG_SECURITY_SMACK_BRINGUP +static int smk_bu_task(struct task_struct *otp, int mode, int rc) +{ + struct task_smack *tsp = current_security(); + struct task_smack *otsp = task_security(otp); + char acc[SMK_NUM_ACCESS_TYPE + 1]; + + if (rc <= 0) + return rc; + + smk_bu_mode(mode, acc); + pr_info("Smack Bringup: (%s %s %s) %s to %s\n", + tsp->smk_task->smk_known, otsp->smk_task->smk_known, acc, + current->comm, otp->comm); + return 0; +} +#else +#define smk_bu_task(otp, mode, RC) (RC) +#endif + +#ifdef CONFIG_SECURITY_SMACK_BRINGUP +static int smk_bu_inode(struct inode *inode, int mode, int rc) +{ + struct task_smack *tsp = current_security(); + char acc[SMK_NUM_ACCESS_TYPE + 1]; + + if (rc <= 0) + return rc; + + smk_bu_mode(mode, acc); + pr_info("Smack Bringup: (%s %s %s) inode=(%s %ld) %s\n", + tsp->smk_task->smk_known, smk_of_inode(inode)->smk_known, acc, + inode->i_sb->s_id, inode->i_ino, current->comm); + return 0; +} +#else +#define smk_bu_inode(inode, mode, RC) (RC) +#endif + +#ifdef CONFIG_SECURITY_SMACK_BRINGUP +static int smk_bu_file(struct file *file, int mode, int rc) +{ + struct task_smack *tsp = current_security(); + struct smack_known *sskp = tsp->smk_task; + struct inode *inode = file->f_inode; + char acc[SMK_NUM_ACCESS_TYPE + 1]; + + if (rc <= 0) + return rc; + + smk_bu_mode(mode, acc); + pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %s) %s\n", + sskp->smk_known, (char *)file->f_security, acc, + inode->i_sb->s_id, inode->i_ino, file->f_dentry->d_name.name, + current->comm); + return 0; +} +#else +#define smk_bu_file(file, mode, RC) (RC) +#endif + +#ifdef CONFIG_SECURITY_SMACK_BRINGUP +static int smk_bu_credfile(const struct cred *cred, struct file *file, + int mode, int rc) +{ + struct task_smack *tsp = cred->security; + struct smack_known *sskp = tsp->smk_task; + struct inode *inode = file->f_inode; + char acc[SMK_NUM_ACCESS_TYPE + 1]; + + if (rc <= 0) + return rc; + + smk_bu_mode(mode, acc); + pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %s) %s\n", + sskp->smk_known, smk_of_inode(inode)->smk_known, acc, + inode->i_sb->s_id, inode->i_ino, file->f_dentry->d_name.name, + current->comm); + return 0; +} +#else +#define smk_bu_credfile(cred, file, mode, RC) (RC) +#endif + /** * smk_fetch - Fetch the smack label from a file. * @ip: a pointer to the inode @@ -87,11 +232,11 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip, /** * new_inode_smack - allocate an inode security blob - * @smack: a pointer to the Smack label to use in the blob + * @skp: a pointer to the Smack label entry to use in the blob * * Returns the new blob or NULL if there's no memory available */ -struct inode_smack *new_inode_smack(char *smack) +struct inode_smack *new_inode_smack(struct smack_known *skp) { struct inode_smack *isp; @@ -99,7 +244,7 @@ struct inode_smack *new_inode_smack(char *smack) if (isp == NULL) return NULL; - isp->smk_inode = smack; + isp->smk_inode = skp; isp->smk_flags = 0; mutex_init(&isp->smk_lock); @@ -178,20 +323,20 @@ static inline unsigned int smk_ptrace_mode(unsigned int mode) /** * smk_ptrace_rule_check - helper for ptrace access * @tracer: tracer process - * @tracee_label: label of the process that's about to be traced, - * the pointer must originate from smack structures + * @tracee_known: label entry of the process that's about to be traced * @mode: ptrace attachment mode (PTRACE_MODE_*) * @func: name of the function that called us, used for audit * * Returns 0 on access granted, -error on error */ -static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label, +static int smk_ptrace_rule_check(struct task_struct *tracer, + struct smack_known *tracee_known, unsigned int mode, const char *func) { int rc; struct smk_audit_info ad, *saip = NULL; struct task_smack *tsp; - struct smack_known *skp; + struct smack_known *tracer_known; if ((mode & PTRACE_MODE_NOAUDIT) == 0) { smk_ad_init(&ad, func, LSM_AUDIT_DATA_TASK); @@ -200,12 +345,12 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label, } tsp = task_security(tracer); - skp = smk_of_task(tsp); + tracer_known = smk_of_task(tsp); if ((mode & PTRACE_MODE_ATTACH) && (smack_ptrace_rule == SMACK_PTRACE_EXACT || smack_ptrace_rule == SMACK_PTRACE_DRACONIAN)) { - if (skp->smk_known == tracee_label) + if (tracer_known->smk_known == tracee_known->smk_known) rc = 0; else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN) rc = -EACCES; @@ -215,13 +360,15 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label, rc = -EACCES; if (saip) - smack_log(skp->smk_known, tracee_label, 0, rc, saip); + smack_log(tracer_known->smk_known, + tracee_known->smk_known, + 0, rc, saip); return rc; } /* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */ - rc = smk_tskacc(tsp, tracee_label, smk_ptrace_mode(mode), saip); + rc = smk_tskacc(tsp, tracee_known, smk_ptrace_mode(mode), saip); return rc; } @@ -250,7 +397,7 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) skp = smk_of_task(task_security(ctp)); - rc = smk_ptrace_rule_check(current, skp->smk_known, mode, __func__); + rc = smk_ptrace_rule_check(current, skp, mode, __func__); return rc; } @@ -273,8 +420,7 @@ static int smack_ptrace_traceme(struct task_struct *ptp) skp = smk_of_task(current_security()); - rc = smk_ptrace_rule_check(ptp, skp->smk_known, - PTRACE_MODE_ATTACH, __func__); + rc = smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__); return rc; } @@ -318,10 +464,10 @@ static int smack_sb_alloc_security(struct super_block *sb) if (sbsp == NULL) return -ENOMEM; - sbsp->smk_root = smack_known_floor.smk_known; - sbsp->smk_default = smack_known_floor.smk_known; - sbsp->smk_floor = smack_known_floor.smk_known; - sbsp->smk_hat = smack_known_hat.smk_known; + sbsp->smk_root = &smack_known_floor; + sbsp->smk_default = &smack_known_floor; + sbsp->smk_floor = &smack_known_floor; + sbsp->smk_hat = &smack_known_hat; /* * smk_initialized will be zero from kzalloc. */ @@ -405,7 +551,6 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) struct smack_known *skp; char *op; char *commap; - char *nsp; int transmute = 0; int specified = 0; @@ -421,38 +566,38 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { op += strlen(SMK_FSHAT); - nsp = smk_import(op, 0); - if (nsp != NULL) { - sp->smk_hat = nsp; + skp = smk_import_entry(op, 0); + if (skp != NULL) { + sp->smk_hat = skp; specified = 1; } } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { op += strlen(SMK_FSFLOOR); - nsp = smk_import(op, 0); - if (nsp != NULL) { - sp->smk_floor = nsp; + skp = smk_import_entry(op, 0); + if (skp != NULL) { + sp->smk_floor = skp; specified = 1; } } else if (strncmp(op, SMK_FSDEFAULT, strlen(SMK_FSDEFAULT)) == 0) { op += strlen(SMK_FSDEFAULT); - nsp = smk_import(op, 0); - if (nsp != NULL) { - sp->smk_default = nsp; + skp = smk_import_entry(op, 0); + if (skp != NULL) { + sp->smk_default = skp; specified = 1; } } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { op += strlen(SMK_FSROOT); - nsp = smk_import(op, 0); - if (nsp != NULL) { - sp->smk_root = nsp; + skp = smk_import_entry(op, 0); + if (skp != NULL) { + sp->smk_root = skp; specified = 1; } } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { op += strlen(SMK_FSTRANS); - nsp = smk_import(op, 0); - if (nsp != NULL) { - sp->smk_root = nsp; + skp = smk_import_entry(op, 0); + if (skp != NULL) { + sp->smk_root = skp; transmute = 1; specified = 1; } @@ -469,8 +614,8 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) * Unprivileged mounts get root and default from the caller. */ skp = smk_of_current(); - sp->smk_root = skp->smk_known; - sp->smk_default = skp->smk_known; + sp->smk_root = skp; + sp->smk_default = skp; } /* * Initialize the root inode. @@ -507,6 +652,7 @@ static int smack_sb_statfs(struct dentry *dentry) smk_ad_setfield_u_fs_path_dentry(&ad, dentry); rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad); + rc = smk_bu_current("statfs", sbp->smk_floor, MAY_READ, rc); return rc; } @@ -546,7 +692,7 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) tracer = ptrace_parent(current); if (likely(tracer != NULL)) rc = smk_ptrace_rule_check(tracer, - isp->smk_task->smk_known, + isp->smk_task, PTRACE_MODE_ATTACH, __func__); rcu_read_unlock(); @@ -607,7 +753,7 @@ static int smack_inode_alloc_security(struct inode *inode) { struct smack_known *skp = smk_of_current(); - inode->i_security = new_inode_smack(skp->smk_known); + inode->i_security = new_inode_smack(skp); if (inode->i_security == NULL) return -ENOMEM; return 0; @@ -627,8 +773,8 @@ static void smack_inode_free_security(struct inode *inode) /** * smack_inode_init_security - copy out the smack from an inode - * @inode: the inode - * @dir: unused + * @inode: the newly created inode + * @dir: containing directory object * @qstr: unused * @name: where to put the attribute name * @value: where to put the attribute value @@ -642,8 +788,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, { struct inode_smack *issp = inode->i_security; struct smack_known *skp = smk_of_current(); - char *isp = smk_of_inode(inode); - char *dsp = smk_of_inode(dir); + struct smack_known *isp = smk_of_inode(inode); + struct smack_known *dsp = smk_of_inode(dir); int may; if (name) @@ -651,7 +797,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, if (value) { rcu_read_lock(); - may = smk_access_entry(skp->smk_known, dsp, &skp->smk_rules); + may = smk_access_entry(skp->smk_known, dsp->smk_known, + &skp->smk_rules); rcu_read_unlock(); /* @@ -666,13 +813,13 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, issp->smk_flags |= SMK_INODE_CHANGED; } - *value = kstrdup(isp, GFP_NOFS); + *value = kstrdup(isp->smk_known, GFP_NOFS); if (*value == NULL) return -ENOMEM; } if (len) - *len = strlen(isp) + 1; + *len = strlen(isp->smk_known); return 0; } @@ -688,7 +835,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) { - char *isp; + struct smack_known *isp; struct smk_audit_info ad; int rc; @@ -697,11 +844,13 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, isp = smk_of_inode(old_dentry->d_inode); rc = smk_curacc(isp, MAY_WRITE, &ad); + rc = smk_bu_inode(old_dentry->d_inode, MAY_WRITE, rc); if (rc == 0 && new_dentry->d_inode != NULL) { isp = smk_of_inode(new_dentry->d_inode); smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry); rc = smk_curacc(isp, MAY_WRITE, &ad); + rc = smk_bu_inode(new_dentry->d_inode, MAY_WRITE, rc); } return rc; @@ -728,6 +877,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) * You need write access to the thing you're unlinking */ rc = smk_curacc(smk_of_inode(ip), MAY_WRITE, &ad); + rc = smk_bu_inode(ip, MAY_WRITE, rc); if (rc == 0) { /* * You also need write access to the containing directory @@ -735,6 +885,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); smk_ad_setfield_u_fs_inode(&ad, dir); rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); + rc = smk_bu_inode(dir, MAY_WRITE, rc); } return rc; } @@ -759,6 +910,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) * You need write access to the thing you're removing */ rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); + rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc); if (rc == 0) { /* * You also need write access to the containing directory @@ -766,6 +918,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); smk_ad_setfield_u_fs_inode(&ad, dir); rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); + rc = smk_bu_inode(dir, MAY_WRITE, rc); } return rc; @@ -773,10 +926,10 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) /** * smack_inode_rename - Smack check on rename - * @old_inode: the old directory - * @old_dentry: unused - * @new_inode: the new directory - * @new_dentry: unused + * @old_inode: unused + * @old_dentry: the old object + * @new_inode: unused + * @new_dentry: the new object * * Read and write access is required on both the old and * new directories. @@ -789,7 +942,7 @@ static int smack_inode_rename(struct inode *old_inode, struct dentry *new_dentry) { int rc; - char *isp; + struct smack_known *isp; struct smk_audit_info ad; smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); @@ -797,11 +950,13 @@ static int smack_inode_rename(struct inode *old_inode, isp = smk_of_inode(old_dentry->d_inode); rc = smk_curacc(isp, MAY_READWRITE, &ad); + rc = smk_bu_inode(old_dentry->d_inode, MAY_READWRITE, rc); if (rc == 0 && new_dentry->d_inode != NULL) { isp = smk_of_inode(new_dentry->d_inode); smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry); rc = smk_curacc(isp, MAY_READWRITE, &ad); + rc = smk_bu_inode(new_dentry->d_inode, MAY_READWRITE, rc); } return rc; } @@ -819,6 +974,7 @@ static int smack_inode_permission(struct inode *inode, int mask) { struct smk_audit_info ad; int no_block = mask & MAY_NOT_BLOCK; + int rc; mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); /* @@ -832,7 +988,9 @@ static int smack_inode_permission(struct inode *inode, int mask) return -ECHILD; smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); smk_ad_setfield_u_fs_inode(&ad, inode); - return smk_curacc(smk_of_inode(inode), mask, &ad); + rc = smk_curacc(smk_of_inode(inode), mask, &ad); + rc = smk_bu_inode(inode, mask, rc); + return rc; } /** @@ -845,6 +1003,8 @@ static int smack_inode_permission(struct inode *inode, int mask) static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) { struct smk_audit_info ad; + int rc; + /* * Need to allow for clearing the setuid bit. */ @@ -853,12 +1013,14 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); smk_ad_setfield_u_fs_path_dentry(&ad, dentry); - return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); + rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); + rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc); + return rc; } /** * smack_inode_getattr - Smack check for getting attributes - * @mnt: unused + * @mnt: vfsmount of the object * @dentry: the object * * Returns 0 if access is permitted, an error code otherwise @@ -867,21 +1029,24 @@ static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) { struct smk_audit_info ad; struct path path; + int rc; path.dentry = dentry; path.mnt = mnt; smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); smk_ad_setfield_u_fs_path(&ad, path); - return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); + rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); + rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc); + return rc; } /** * smack_inode_setxattr - Smack check for setting xattrs * @dentry: the object * @name: name of the attribute - * @value: unused - * @size: unused + * @value: value of the attribute + * @size: size of the value * @flags: unused * * This protects the Smack attribute explicitly. @@ -923,7 +1088,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, rc = -EPERM; if (rc == 0 && check_import) { - skp = smk_import_entry(value, size); + skp = size ? smk_import_entry(value, size) : NULL; if (skp == NULL || (check_star && (skp == &smack_known_star || skp == &smack_known_web))) rc = -EINVAL; @@ -932,8 +1097,10 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); smk_ad_setfield_u_fs_path_dentry(&ad, dentry); - if (rc == 0) + if (rc == 0) { rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); + rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc); + } return rc; } @@ -963,9 +1130,9 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, if (strcmp(name, XATTR_NAME_SMACK) == 0) { skp = smk_import_entry(value, size); if (skp != NULL) - isp->smk_inode = skp->smk_known; + isp->smk_inode = skp; else - isp->smk_inode = smack_known_invalid.smk_known; + isp->smk_inode = &smack_known_invalid; } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { skp = smk_import_entry(value, size); if (skp != NULL) @@ -993,11 +1160,14 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, static int smack_inode_getxattr(struct dentry *dentry, const char *name) { struct smk_audit_info ad; + int rc; smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); smk_ad_setfield_u_fs_path_dentry(&ad, dentry); - return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); + rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); + rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc); + return rc; } /** @@ -1033,6 +1203,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) smk_ad_setfield_u_fs_path_dentry(&ad, dentry); rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); + rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc); if (rc != 0) return rc; @@ -1070,14 +1241,14 @@ static int smack_inode_getsecurity(const struct inode *inode, struct socket *sock; struct super_block *sbp; struct inode *ip = (struct inode *)inode; - char *isp; + struct smack_known *isp; int ilen; int rc = 0; if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { isp = smk_of_inode(inode); - ilen = strlen(isp) + 1; - *buffer = isp; + ilen = strlen(isp->smk_known); + *buffer = isp->smk_known; return ilen; } @@ -1095,15 +1266,15 @@ static int smack_inode_getsecurity(const struct inode *inode, ssp = sock->sk->sk_security; if (strcmp(name, XATTR_SMACK_IPIN) == 0) - isp = ssp->smk_in->smk_known; + isp = ssp->smk_in; else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) - isp = ssp->smk_out->smk_known; + isp = ssp->smk_out; else return -EOPNOTSUPP; - ilen = strlen(isp) + 1; + ilen = strlen(isp->smk_known); if (rc == 0) { - *buffer = isp; + *buffer = isp->smk_known; rc = ilen; } @@ -1122,13 +1293,12 @@ static int smack_inode_getsecurity(const struct inode *inode, static int smack_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) { - int len = strlen |