diff options
Diffstat (limited to 'security/smack/smack_access.c')
| -rw-r--r-- | security/smack/smack_access.c | 141 | 
1 files changed, 126 insertions, 15 deletions
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index ac0a2707f6d..513dc1aa16d 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -59,11 +59,18 @@ LIST_HEAD(smack_known_list);   */  static u32 smack_next_secid = 10; +/* + * what events do we log + * can be overwritten at run-time by /smack/logging + */ +int log_policy = SMACK_AUDIT_DENIED; +  /**   * smk_access - determine if a subject has a specific access to an object   * @subject_label: a pointer to the subject's Smack label   * @object_label: a pointer to the object's Smack label   * @request: the access requested, in "MAY" format + * @a : a pointer to the audit data   *   * This function looks up the subject/object pair in the   * access rule list and returns 0 if the access is permitted, @@ -78,10 +85,12 @@ static u32 smack_next_secid = 10;   * will be on the list, so checking the pointers may be a worthwhile   * optimization.   */ -int smk_access(char *subject_label, char *object_label, int request) +int smk_access(char *subject_label, char *object_label, int request, +	       struct smk_audit_info *a)  {  	u32 may = MAY_NOT;  	struct smack_rule *srp; +	int rc = 0;  	/*  	 * Hardcoded comparisons. @@ -89,8 +98,10 @@ 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 || -	    strcmp(subject_label, smack_known_star.smk_known) == 0) -		return -EACCES; +	    strcmp(subject_label, smack_known_star.smk_known) == 0) { +		rc = -EACCES; +		goto out_audit; +	}  	/*  	 * An internet object can be accessed by any subject.  	 * Tasks cannot be assigned the internet label. @@ -100,20 +111,20 @@ int smk_access(char *subject_label, char *object_label, int request)  	    subject_label == smack_known_web.smk_known ||  	    strcmp(object_label, smack_known_web.smk_known) == 0 ||  	    strcmp(subject_label, smack_known_web.smk_known) == 0) -		return 0; +		goto out_audit;  	/*  	 * A star object can be accessed by any subject.  	 */  	if (object_label == smack_known_star.smk_known ||  	    strcmp(object_label, smack_known_star.smk_known) == 0) -		return 0; +		goto out_audit;  	/*  	 * An object can be accessed in any way by a subject  	 * with the same label.  	 */  	if (subject_label == object_label ||  	    strcmp(subject_label, object_label) == 0) -		return 0; +		goto out_audit;  	/*  	 * A hat subject can read any object.  	 * A floor object can be read by any subject. @@ -121,10 +132,10 @@ int smk_access(char *subject_label, char *object_label, int request)  	if ((request & MAY_ANYREAD) == request) {  		if (object_label == smack_known_floor.smk_known ||  		    strcmp(object_label, smack_known_floor.smk_known) == 0) -			return 0; +			goto out_audit;  		if (subject_label == smack_known_hat.smk_known ||  		    strcmp(subject_label, smack_known_hat.smk_known) == 0) -			return 0; +			goto out_audit;  	}  	/*  	 * Beyond here an explicit relationship is required. @@ -148,28 +159,36 @@ int smk_access(char *subject_label, char *object_label, int request)  	 * This is a bit map operation.  	 */  	if ((request & may) == request) -		return 0; +		goto out_audit; -	return -EACCES; +	rc = -EACCES; +out_audit: +#ifdef CONFIG_AUDIT +	if (a) +		smack_log(subject_label, object_label, request, 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   * @mode: the access requested, in "MAY" format + * @a : common audit data   *   * This function checks the current subject label/object label pair   * in the access rule list and returns 0 if the access is permitted,   * non zero otherwise. It allows that current may have the capability   * to override the rules.   */ -int smk_curacc(char *obj_label, u32 mode) +int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)  {  	int rc; +	char *sp = current_security(); -	rc = smk_access(current_security(), obj_label, mode); +	rc = smk_access(sp, obj_label, mode, NULL);  	if (rc == 0) -		return 0; +		goto out_audit;  	/*  	 * Return if a specific label has been designated as the @@ -177,14 +196,105 @@ int smk_curacc(char *obj_label, u32 mode)  	 * have that label.  	 */  	if (smack_onlycap != NULL && smack_onlycap != current->cred->security) -		return rc; +		goto out_audit;  	if (capable(CAP_MAC_OVERRIDE))  		return 0; +out_audit: +#ifdef CONFIG_AUDIT +	if (a) +		smack_log(sp, obj_label, mode, rc, a); +#endif  	return rc;  } +#ifdef CONFIG_AUDIT +/** + * smack_str_from_perm : helper to transalate an int to a + * readable string + * @string : the string to fill + * @access : the int + * + */ +static inline void smack_str_from_perm(char *string, int access) +{ +	int i = 0; +	if (access & MAY_READ) +		string[i++] = 'r'; +	if (access & MAY_WRITE) +		string[i++] = 'w'; +	if (access & MAY_EXEC) +		string[i++] = 'x'; +	if (access & MAY_APPEND) +		string[i++] = 'a'; +	string[i] = '\0'; +} +/** + * smack_log_callback - SMACK specific information + * will be called by generic audit code + * @ab : the audit_buffer + * @a  : audit_data + * + */ +static void smack_log_callback(struct audit_buffer *ab, void *a) +{ +	struct common_audit_data *ad = a; +	struct smack_audit_data *sad = &ad->lsm_priv.smack_audit_data; +	audit_log_format(ab, "lsm=SMACK fn=%s action=%s", ad->function, +			 sad->result ? "denied" : "granted"); +	audit_log_format(ab, " subject="); +	audit_log_untrustedstring(ab, sad->subject); +	audit_log_format(ab, " object="); +	audit_log_untrustedstring(ab, sad->object); +	audit_log_format(ab, " requested=%s", sad->request); +} + +/** + *  smack_log - Audit the granting or denial of permissions. + *  @subject_label : smack label of the requester + *  @object_label  : smack label of the object being accessed + *  @request: requested permissions + *  @result: result from smk_access + *  @a:  auxiliary audit data + * + * Audit the granting or denial of permissions in accordance + * with the policy. + */ +void smack_log(char *subject_label, char *object_label, int request, +	       int result, struct smk_audit_info *ad) +{ +	char request_buffer[SMK_NUM_ACCESS_TYPE + 1]; +	struct smack_audit_data *sad; +	struct common_audit_data *a = &ad->a; + +	/* check if we have to log the current event */ +	if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0) +		return; +	if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0) +		return; + +	if (a->function == NULL) +		a->function = "unknown"; + +	/* end preparing the audit data */ +	sad = &a->lsm_priv.smack_audit_data; +	smack_str_from_perm(request_buffer, request); +	sad->subject = subject_label; +	sad->object  = object_label; +	sad->request = request_buffer; +	sad->result  = result; +	a->lsm_pre_audit = smack_log_callback; + +	common_lsm_audit(a); +} +#else /* #ifdef CONFIG_AUDIT */ +void smack_log(char *subject_label, char *object_label, int request, +               int result, struct smk_audit_info *ad) +{ +} +#endif +  static DEFINE_MUTEX(smack_known_lock);  /** @@ -209,7 +319,8 @@ struct smack_known *smk_import_entry(const char *string, int len)  		if (found)  			smack[i] = '\0';  		else if (i >= len || string[i] > '~' || string[i] <= ' ' || -			 string[i] == '/') { +			 string[i] == '/' || string[i] == '"' || +			 string[i] == '\\' || string[i] == '\'') {  			smack[i] = '\0';  			found = 1;  		} else  |