diff options
Diffstat (limited to 'security/smack/smack_lsm.c')
| -rw-r--r-- | security/smack/smack_lsm.c | 112 | 
1 files changed, 96 insertions, 16 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index c934311812f1..69fdc384af30 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -57,6 +57,13 @@ static struct kmem_cache *smack_inode_cache;  int smack_enabled;  #ifdef CONFIG_SECURITY_SMACK_BRINGUP +static char *smk_bu_mess[] = { +	"Bringup Error",	/* Unused */ +	"Bringup",		/* SMACK_BRINGUP_ALLOW */ +	"Unconfined Subject",	/* SMACK_UNCONFINED_SUBJECT */ +	"Unconfined Object",	/* SMACK_UNCONFINED_OBJECT */ +}; +  static void smk_bu_mode(int mode, char *s)  {  	int i = 0; @@ -87,9 +94,11 @@ static int smk_bu_note(char *note, struct smack_known *sskp,  	if (rc <= 0)  		return rc; +	if (rc > SMACK_UNCONFINED_OBJECT) +		rc = 0;  	smk_bu_mode(mode, acc); -	pr_info("Smack Bringup: (%s %s %s) %s\n", +	pr_info("Smack %s: (%s %s %s) %s\n", smk_bu_mess[rc],  		sskp->smk_known, oskp->smk_known, acc, note);  	return 0;  } @@ -106,9 +115,11 @@ static int smk_bu_current(char *note, struct smack_known *oskp,  	if (rc <= 0)  		return rc; +	if (rc > SMACK_UNCONFINED_OBJECT) +		rc = 0;  	smk_bu_mode(mode, acc); -	pr_info("Smack Bringup: (%s %s %s) %s %s\n", +	pr_info("Smack %s: (%s %s %s) %s %s\n", smk_bu_mess[rc],  		tsp->smk_task->smk_known, oskp->smk_known,  		acc, current->comm, note);  	return 0; @@ -126,9 +137,11 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)  	if (rc <= 0)  		return rc; +	if (rc > SMACK_UNCONFINED_OBJECT) +		rc = 0;  	smk_bu_mode(mode, acc); -	pr_info("Smack Bringup: (%s %s %s) %s to %s\n", +	pr_info("Smack %s: (%s %s %s) %s to %s\n", smk_bu_mess[rc],  		tsp->smk_task->smk_known, smk_task->smk_known, acc,  		current->comm, otp->comm);  	return 0; @@ -141,14 +154,25 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)  static int smk_bu_inode(struct inode *inode, int mode, int rc)  {  	struct task_smack *tsp = current_security(); +	struct inode_smack *isp = inode->i_security;  	char acc[SMK_NUM_ACCESS_TYPE + 1]; +	if (isp->smk_flags & SMK_INODE_IMPURE) +		pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n", +			inode->i_sb->s_id, inode->i_ino, current->comm); +  	if (rc <= 0)  		return rc; +	if (rc > SMACK_UNCONFINED_OBJECT) +		rc = 0; +	if (rc == SMACK_UNCONFINED_SUBJECT && +	    (mode & (MAY_WRITE | MAY_APPEND))) +		isp->smk_flags |= SMK_INODE_IMPURE;  	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, + +	pr_info("Smack %s: (%s %s %s) inode=(%s %ld) %s\n", smk_bu_mess[rc], +		tsp->smk_task->smk_known, isp->smk_inode->smk_known, acc,  		inode->i_sb->s_id, inode->i_ino, current->comm);  	return 0;  } @@ -162,13 +186,20 @@ 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_inode(file); +	struct inode_smack *isp = inode->i_security;  	char acc[SMK_NUM_ACCESS_TYPE + 1]; +	if (isp->smk_flags & SMK_INODE_IMPURE) +		pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n", +			inode->i_sb->s_id, inode->i_ino, current->comm); +  	if (rc <= 0)  		return rc; +	if (rc > SMACK_UNCONFINED_OBJECT) +		rc = 0;  	smk_bu_mode(mode, acc); -	pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n", +	pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],  		sskp->smk_known, smk_of_inode(inode)->smk_known, acc,  		inode->i_sb->s_id, inode->i_ino, file,  		current->comm); @@ -185,13 +216,20 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,  	struct task_smack *tsp = cred->security;  	struct smack_known *sskp = tsp->smk_task;  	struct inode *inode = file->f_inode; +	struct inode_smack *isp = inode->i_security;  	char acc[SMK_NUM_ACCESS_TYPE + 1]; +	if (isp->smk_flags & SMK_INODE_IMPURE) +		pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n", +			inode->i_sb->s_id, inode->i_ino, current->comm); +  	if (rc <= 0)  		return rc; +	if (rc > SMACK_UNCONFINED_OBJECT) +		rc = 0;  	smk_bu_mode(mode, acc); -	pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n", +	pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],  		sskp->smk_known, smk_of_inode(inode)->smk_known, acc,  		inode->i_sb->s_id, inode->i_ino, file,  		current->comm); @@ -1034,19 +1072,16 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)   *   * Returns 0 if access is permitted, an error code otherwise   */ -static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) +static int smack_inode_getattr(const struct path *path)  {  	struct smk_audit_info ad; -	struct path path; +	struct inode *inode = path->dentry->d_inode;  	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); -	rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); -	rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc); +	smk_ad_setfield_u_fs_path(&ad, *path); +	rc = smk_curacc(smk_of_inode(inode), MAY_READ, &ad); +	rc = smk_bu_inode(inode, MAY_READ, rc);  	return rc;  } @@ -2452,7 +2487,21 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,  static int smack_socket_post_create(struct socket *sock, int family,  				    int type, int protocol, int kern)  { -	if (family != PF_INET || sock->sk == NULL) +	struct socket_smack *ssp; + +	if (sock->sk == NULL) +		return 0; + +	/* +	 * Sockets created by kernel threads receive web label. +	 */ +	if (unlikely(current->flags & PF_KTHREAD)) { +		ssp = sock->sk->sk_security; +		ssp->smk_in = &smack_known_web; +		ssp->smk_out = &smack_known_web; +	} + +	if (family != PF_INET)  		return 0;  	/*  	 * Set the outbound netlbl. @@ -3986,6 +4035,36 @@ static int smack_key_permission(key_ref_t key_ref,  	rc = smk_bu_note("key access", tkp, keyp->security, request, rc);  	return rc;  } + +/* + * smack_key_getsecurity - Smack label tagging the key + * @key points to the key to be queried + * @_buffer points to a pointer that should be set to point to the + * resulting string (if no label or an error occurs). + * Return the length of the string (including terminating NUL) or -ve if + * an error. + * May also return 0 (and a NULL buffer pointer) if there is no label. + */ +static int smack_key_getsecurity(struct key *key, char **_buffer) +{ +	struct smack_known *skp = key->security; +	size_t length; +	char *copy; + +	if (key->security == NULL) { +		*_buffer = NULL; +		return 0; +	} + +	copy = kstrdup(skp->smk_known, GFP_KERNEL); +	if (copy == NULL) +		return -ENOMEM; +	length = strlen(copy) + 1; + +	*_buffer = copy; +	return length; +} +  #endif /* CONFIG_KEYS */  /* @@ -4310,6 +4389,7 @@ struct security_operations smack_ops = {  	.key_alloc = 			smack_key_alloc,  	.key_free = 			smack_key_free,  	.key_permission = 		smack_key_permission, +	.key_getsecurity =		smack_key_getsecurity,  #endif /* CONFIG_KEYS */   /* Audit hooks */  |