Commit b4e0d5f0 authored by Casey Schaufler's avatar Casey Schaufler Committed by James Morris

Smack: UDS revision

This patch addresses a number of long standing issues
    with the way Smack treats UNIX domain sockets.

    All access control was being done based on the label of
    the file system object. This is inconsistant with the
    internet domain, in which access is done based on the
    IPIN and IPOUT attributes of the socket. As a result
    of the inode label policy it was not possible to use
    a UDS socket for label cognizant services, including
    dbus and the X11 server.

    Support for SCM_PEERSEC on UDS sockets is also provided.
Signed-off-by: default avatarCasey Schaufler <casey@schaufler-ca.com>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent 7e70cb49
......@@ -1667,10 +1667,13 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
ssp->smk_in = sp;
else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {
ssp->smk_out = sp;
rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
if (rc != 0)
printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n",
__func__, -rc);
if (sock->sk->sk_family != PF_UNIX) {
rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
if (rc != 0)
printk(KERN_WARNING
"Smack: \"%s\" netlbl error %d.\n",
__func__, -rc);
}
} else
return -EOPNOTSUPP;
......@@ -2267,9 +2270,10 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
break;
case SOCKFS_MAGIC:
/*
* Casey says sockets get the smack of the task.
* Socket access is controlled by the socket
* structures associated with the task involved.
*/
final = csp;
final = smack_known_star.smk_known;
break;
case PROC_SUPER_MAGIC:
/*
......@@ -2296,7 +2300,16 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
/*
* This isn't an understood special case.
* Get the value from the xattr.
*
*/
/*
* UNIX domain sockets use lower level socket data.
*/
if (S_ISSOCK(inode->i_mode)) {
final = smack_known_star.smk_known;
break;
}
/*
* No xattr support means, alas, no SMACK label.
* Use the aforeapplied default.
* It would be curious if the label of the task
......@@ -2418,14 +2431,18 @@ static int smack_setprocattr(struct task_struct *p, char *name,
static int smack_unix_stream_connect(struct socket *sock,
struct socket *other, struct sock *newsk)
{
struct inode *sp = SOCK_INODE(sock);
struct inode *op = SOCK_INODE(other);
struct socket_smack *ssp = sock->sk->sk_security;
struct socket_smack *osp = other->sk->sk_security;
struct smk_audit_info ad;
int rc = 0;
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
smk_ad_setfield_u_net_sk(&ad, other->sk);
return smk_access(smk_of_inode(sp), smk_of_inode(op),
MAY_READWRITE, &ad);
if (!capable(CAP_MAC_OVERRIDE))
rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
return rc;
}
/**
......@@ -2438,13 +2455,18 @@ static int smack_unix_stream_connect(struct socket *sock,
*/
static int smack_unix_may_send(struct socket *sock, struct socket *other)
{
struct inode *sp = SOCK_INODE(sock);
struct inode *op = SOCK_INODE(other);
struct socket_smack *ssp = sock->sk->sk_security;
struct socket_smack *osp = other->sk->sk_security;
struct smk_audit_info ad;
int rc = 0;
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
smk_ad_setfield_u_net_sk(&ad, other->sk);
return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_WRITE, &ad);
if (!capable(CAP_MAC_OVERRIDE))
rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
return rc;
}
/**
......@@ -2629,7 +2651,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock,
/**
* smack_socket_getpeersec_dgram - pull in packet label
* @sock: the socket
* @sock: the peer socket
* @skb: packet data
* @secid: pointer to where to put the secid of the packet
*
......@@ -2640,41 +2662,39 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
{
struct netlbl_lsm_secattr secattr;
struct sock *sk;
struct socket_smack *sp;
char smack[SMK_LABELLEN];
int family = PF_INET;
u32 s;
int family = PF_UNSPEC;
u32 s = 0; /* 0 is the invalid secid */
int rc;
/*
* Only works for families with packets.
*/
if (sock != NULL) {
sk = sock->sk;
if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
return 0;
family = sk->sk_family;
if (skb != NULL) {
if (skb->protocol == htons(ETH_P_IP))
family = PF_INET;
else if (skb->protocol == htons(ETH_P_IPV6))
family = PF_INET6;
}
/*
* Translate what netlabel gave us.
*/
netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, family, &secattr);
if (rc == 0)
smack_from_secattr(&secattr, smack);
netlbl_secattr_destroy(&secattr);
/*
* Give up if we couldn't get anything
*/
if (rc != 0)
return rc;
if (family == PF_UNSPEC && sock != NULL)
family = sock->sk->sk_family;
s = smack_to_secid(smack);
if (family == PF_UNIX) {
sp = sock->sk->sk_security;
s = smack_to_secid(sp->smk_out);
} else if (family == PF_INET || family == PF_INET6) {
/*
* Translate what netlabel gave us.
*/
netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, family, &secattr);
if (rc == 0) {
smack_from_secattr(&secattr, smack);
s = smack_to_secid(smack);
}
netlbl_secattr_destroy(&secattr);
}
*secid = s;
if (s == 0)
return -EINVAL;
*secid = s;
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment