Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1880eff7 authored by Casey Schaufler's avatar Casey Schaufler
Browse files

Smack: onlycap limits on CAP_MAC_ADMIN

Smack is integrated with the POSIX capabilities scheme,
using the capabilities CAP_MAC_OVERRIDE and CAP_MAC_ADMIN to
determine if a process is allowed to ignore Smack checks or
change Smack related data respectively. Smack provides an
additional restriction that if an onlycap value is set
by writing to /smack/onlycap only tasks with that Smack
label are allowed to use CAP_MAC_OVERRIDE.

This change adds CAP_MAC_ADMIN as a capability that is affected
by the onlycap mechanism.

Targeted for git://git.gitorious.org/smack-next/kernel.git



Signed-off-by: default avatarCasey Schaufler <casey@schaufler-ca.com>
parent eb982cb4
Loading
Loading
Loading
Loading
+13 −0
Original line number Original line Diff line number Diff line
@@ -282,6 +282,19 @@ static inline char *smk_of_current(void)
	return smk_of_task(current_security());
	return smk_of_task(current_security());
}
}


/*
 * Is the task privileged and allowed to be privileged
 * by the onlycap rule.
 */
static inline int smack_privileged(int cap)
{
	if (!capable(cap))
		return 0;
	if (smack_onlycap == NULL || smack_onlycap == smk_of_current())
		return 1;
	return 0;
}

/*
/*
 * logging functions
 * logging functions
 */
 */
+2 −7
Original line number Original line Diff line number Diff line
@@ -220,14 +220,9 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
	}
	}


	/*
	/*
	 * Return if a specific label has been designated as the
	 * Allow for priviliged to override policy.
	 * only one that gets privilege and current does not
	 * have that label.
	 */
	 */
	if (smack_onlycap != NULL && smack_onlycap != sp)
	if (rc != 0 && smack_privileged(CAP_MAC_OVERRIDE))
		goto out_audit;

	if (capable(CAP_MAC_OVERRIDE))
		rc = 0;
		rc = 0;


out_audit:
out_audit:
+9 −8
Original line number Original line Diff line number Diff line
@@ -217,7 +217,7 @@ static int smack_syslog(int typefrom_file)
	int rc = 0;
	int rc = 0;
	char *sp = smk_of_current();
	char *sp = smk_of_current();


	if (capable(CAP_MAC_OVERRIDE))
	if (smack_privileged(CAP_MAC_OVERRIDE))
		return 0;
		return 0;


	 if (sp != smack_known_floor.smk_known)
	 if (sp != smack_known_floor.smk_known)
@@ -821,7 +821,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
	    strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
	    strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
	    strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
	    strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
	    strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
	    strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
		if (!capable(CAP_MAC_ADMIN))
		if (!smack_privileged(CAP_MAC_ADMIN))
			rc = -EPERM;
			rc = -EPERM;
		/*
		/*
		 * check label validity here so import wont fail on
		 * check label validity here so import wont fail on
@@ -831,7 +831,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
		    smk_import(value, size) == NULL)
		    smk_import(value, size) == NULL)
			rc = -EINVAL;
			rc = -EINVAL;
	} else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
	} else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
		if (!capable(CAP_MAC_ADMIN))
		if (!smack_privileged(CAP_MAC_ADMIN))
			rc = -EPERM;
			rc = -EPERM;
		if (size != TRANS_TRUE_SIZE ||
		if (size != TRANS_TRUE_SIZE ||
		    strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
		    strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
@@ -927,7 +927,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
	    strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
	    strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
	    strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 ||
	    strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 ||
	    strcmp(name, XATTR_NAME_SMACKMMAP)) {
	    strcmp(name, XATTR_NAME_SMACKMMAP)) {
		if (!capable(CAP_MAC_ADMIN))
		if (!smack_privileged(CAP_MAC_ADMIN))
			rc = -EPERM;
			rc = -EPERM;
	} else
	} else
		rc = cap_inode_removexattr(dentry, name);
		rc = cap_inode_removexattr(dentry, name);
@@ -1716,7 +1716,8 @@ static int smack_task_wait(struct task_struct *p)
	 * state into account in the decision as well as
	 * state into account in the decision as well as
	 * the smack value.
	 * the smack value.
	 */
	 */
	if (capable(CAP_MAC_OVERRIDE) || has_capability(p, CAP_MAC_OVERRIDE))
	if (smack_privileged(CAP_MAC_OVERRIDE) ||
	    has_capability(p, CAP_MAC_OVERRIDE))
		rc = 0;
		rc = 0;
	/* we log only if we didn't get overriden */
	/* we log only if we didn't get overriden */
 out_log:
 out_log:
@@ -2717,7 +2718,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
	if (p != current)
	if (p != current)
		return -EPERM;
		return -EPERM;


	if (!capable(CAP_MAC_ADMIN))
	if (!smack_privileged(CAP_MAC_ADMIN))
		return -EPERM;
		return -EPERM;


	if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
	if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
@@ -2780,7 +2781,7 @@ static int smack_unix_stream_connect(struct sock *sock,
	smk_ad_setfield_u_net_sk(&ad, other);
	smk_ad_setfield_u_net_sk(&ad, other);
#endif
#endif


	if (!capable(CAP_MAC_OVERRIDE))
	if (!smack_privileged(CAP_MAC_OVERRIDE))
		rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
		rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);


	/*
	/*
@@ -2816,7 +2817,7 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
	smk_ad_setfield_u_net_sk(&ad, other->sk);
	smk_ad_setfield_u_net_sk(&ad, other->sk);
#endif
#endif


	if (!capable(CAP_MAC_OVERRIDE))
	if (!smack_privileged(CAP_MAC_OVERRIDE))
		rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
		rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);


	return rc;
	return rc;
+10 −11
Original line number Original line Diff line number Diff line
@@ -595,13 +595,12 @@ static int smk_open_load(struct inode *inode, struct file *file)
static ssize_t smk_write_load(struct file *file, const char __user *buf,
static ssize_t smk_write_load(struct file *file, const char __user *buf,
			      size_t count, loff_t *ppos)
			      size_t count, loff_t *ppos)
{
{

	/*
	/*
	 * Must have privilege.
	 * Must have privilege.
	 * No partial writes.
	 * No partial writes.
	 * Enough data must be present.
	 * Enough data must be present.
	 */
	 */
	if (!capable(CAP_MAC_ADMIN))
	if (!smack_privileged(CAP_MAC_ADMIN))
		return -EPERM;
		return -EPERM;


	return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
	return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
@@ -787,7 +786,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
	 * No partial writes.
	 * No partial writes.
	 * Enough data must be present.
	 * Enough data must be present.
	 */
	 */
	if (!capable(CAP_MAC_ADMIN))
	if (!smack_privileged(CAP_MAC_ADMIN))
		return -EPERM;
		return -EPERM;
	if (*ppos != 0)
	if (*ppos != 0)
		return -EINVAL;
		return -EINVAL;
@@ -1090,7 +1089,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
	 * "<addr/mask, as a.b.c.d/e><space><label>"
	 * "<addr/mask, as a.b.c.d/e><space><label>"
	 * "<addr, as a.b.c.d><space><label>"
	 * "<addr, as a.b.c.d><space><label>"
	 */
	 */
	if (!capable(CAP_MAC_ADMIN))
	if (!smack_privileged(CAP_MAC_ADMIN))
		return -EPERM;
		return -EPERM;
	if (*ppos != 0)
	if (*ppos != 0)
		return -EINVAL;
		return -EINVAL;
@@ -1267,7 +1266,7 @@ static ssize_t smk_write_doi(struct file *file, const char __user *buf,
	char temp[80];
	char temp[80];
	int i;
	int i;


	if (!capable(CAP_MAC_ADMIN))
	if (!smack_privileged(CAP_MAC_ADMIN))
		return -EPERM;
		return -EPERM;


	if (count >= sizeof(temp) || count == 0)
	if (count >= sizeof(temp) || count == 0)
@@ -1334,7 +1333,7 @@ static ssize_t smk_write_direct(struct file *file, const char __user *buf,
	char temp[80];
	char temp[80];
	int i;
	int i;


	if (!capable(CAP_MAC_ADMIN))
	if (!smack_privileged(CAP_MAC_ADMIN))
		return -EPERM;
		return -EPERM;


	if (count >= sizeof(temp) || count == 0)
	if (count >= sizeof(temp) || count == 0)
@@ -1412,7 +1411,7 @@ static ssize_t smk_write_mapped(struct file *file, const char __user *buf,
	char temp[80];
	char temp[80];
	int i;
	int i;


	if (!capable(CAP_MAC_ADMIN))
	if (!smack_privileged(CAP_MAC_ADMIN))
		return -EPERM;
		return -EPERM;


	if (count >= sizeof(temp) || count == 0)
	if (count >= sizeof(temp) || count == 0)
@@ -1503,7 +1502,7 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
	char *data;
	char *data;
	int rc = count;
	int rc = count;


	if (!capable(CAP_MAC_ADMIN))
	if (!smack_privileged(CAP_MAC_ADMIN))
		return -EPERM;
		return -EPERM;


	data = kzalloc(count + 1, GFP_KERNEL);
	data = kzalloc(count + 1, GFP_KERNEL);
@@ -1586,7 +1585,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
	char *sp = smk_of_task(current->cred->security);
	char *sp = smk_of_task(current->cred->security);
	int rc = count;
	int rc = count;


	if (!capable(CAP_MAC_ADMIN))
	if (!smack_privileged(CAP_MAC_ADMIN))
		return -EPERM;
		return -EPERM;


	/*
	/*
@@ -1664,7 +1663,7 @@ static ssize_t smk_write_logging(struct file *file, const char __user *buf,
	char temp[32];
	char temp[32];
	int i;
	int i;


	if (!capable(CAP_MAC_ADMIN))
	if (!smack_privileged(CAP_MAC_ADMIN))
		return -EPERM;
		return -EPERM;


	if (count >= sizeof(temp) || count == 0)
	if (count >= sizeof(temp) || count == 0)
@@ -1885,7 +1884,7 @@ static ssize_t smk_write_load2(struct file *file, const char __user *buf,
	/*
	/*
	 * Must have privilege.
	 * Must have privilege.
	 */
	 */
	if (!capable(CAP_MAC_ADMIN))
	if (!smack_privileged(CAP_MAC_ADMIN))
		return -EPERM;
		return -EPERM;


	return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
	return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,