Updated from Linux LTS 3.10.24 to 3.10.25
This commit is contained in:
@@ -53,6 +53,7 @@
|
||||
#include <net/ip.h> /* for local_port_range[] */
|
||||
#include <net/sock.h>
|
||||
#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
|
||||
#include <net/inet_connection_sock.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/netlabel.h>
|
||||
#include <linux/uaccess.h>
|
||||
@@ -3736,6 +3737,30 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* selinux_conn_sid - Determine the child socket label for a connection
|
||||
* @sk_sid: the parent socket's SID
|
||||
* @skb_sid: the packet's SID
|
||||
* @conn_sid: the resulting connection SID
|
||||
*
|
||||
* If @skb_sid is valid then the user:role:type information from @sk_sid is
|
||||
* combined with the MLS information from @skb_sid in order to create
|
||||
* @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
|
||||
* of @sk_sid. Returns zero on success, negative values on failure.
|
||||
*
|
||||
*/
|
||||
static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (skb_sid != SECSID_NULL)
|
||||
err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
|
||||
else
|
||||
*conn_sid = sk_sid;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* socket security operations */
|
||||
|
||||
static int socket_sockcreate_sid(const struct task_security_struct *tsec,
|
||||
@@ -4342,7 +4367,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
||||
struct sk_security_struct *sksec = sk->sk_security;
|
||||
int err;
|
||||
u16 family = sk->sk_family;
|
||||
u32 newsid;
|
||||
u32 connsid;
|
||||
u32 peersid;
|
||||
|
||||
/* handle mapped IPv4 packets arriving via IPv6 sockets */
|
||||
@@ -4352,16 +4377,11 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
||||
err = selinux_skb_peerlbl_sid(skb, family, &peersid);
|
||||
if (err)
|
||||
return err;
|
||||
if (peersid == SECSID_NULL) {
|
||||
req->secid = sksec->sid;
|
||||
req->peer_secid = SECSID_NULL;
|
||||
} else {
|
||||
err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
|
||||
if (err)
|
||||
return err;
|
||||
req->secid = newsid;
|
||||
req->peer_secid = peersid;
|
||||
}
|
||||
err = selinux_conn_sid(sksec->sid, peersid, &connsid);
|
||||
if (err)
|
||||
return err;
|
||||
req->secid = connsid;
|
||||
req->peer_secid = peersid;
|
||||
|
||||
return selinux_netlbl_inet_conn_request(req, family);
|
||||
}
|
||||
@@ -4621,6 +4641,7 @@ static unsigned int selinux_ipv6_forward(unsigned int hooknum,
|
||||
static unsigned int selinux_ip_output(struct sk_buff *skb,
|
||||
u16 family)
|
||||
{
|
||||
struct sock *sk;
|
||||
u32 sid;
|
||||
|
||||
if (!netlbl_enabled())
|
||||
@@ -4629,8 +4650,27 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
|
||||
/* we do this in the LOCAL_OUT path and not the POST_ROUTING path
|
||||
* because we want to make sure we apply the necessary labeling
|
||||
* before IPsec is applied so we can leverage AH protection */
|
||||
if (skb->sk) {
|
||||
struct sk_security_struct *sksec = skb->sk->sk_security;
|
||||
sk = skb->sk;
|
||||
if (sk) {
|
||||
struct sk_security_struct *sksec;
|
||||
|
||||
if (sk->sk_state == TCP_LISTEN)
|
||||
/* if the socket is the listening state then this
|
||||
* packet is a SYN-ACK packet which means it needs to
|
||||
* be labeled based on the connection/request_sock and
|
||||
* not the parent socket. unfortunately, we can't
|
||||
* lookup the request_sock yet as it isn't queued on
|
||||
* the parent socket until after the SYN-ACK is sent.
|
||||
* the "solution" is to simply pass the packet as-is
|
||||
* as any IP option based labeling should be copied
|
||||
* from the initial connection request (in the IP
|
||||
* layer). it is far from ideal, but until we get a
|
||||
* security label in the packet itself this is the
|
||||
* best we can do. */
|
||||
return NF_ACCEPT;
|
||||
|
||||
/* standard practice, label using the parent socket */
|
||||
sksec = sk->sk_security;
|
||||
sid = sksec->sid;
|
||||
} else
|
||||
sid = SECINITSID_KERNEL;
|
||||
@@ -4715,12 +4755,12 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
|
||||
if (!secmark_active && !peerlbl_active)
|
||||
return NF_ACCEPT;
|
||||
|
||||
/* if the packet is being forwarded then get the peer label from the
|
||||
* packet itself; otherwise check to see if it is from a local
|
||||
* application or the kernel, if from an application get the peer label
|
||||
* from the sending socket, otherwise use the kernel's sid */
|
||||
sk = skb->sk;
|
||||
if (sk == NULL) {
|
||||
/* Without an associated socket the packet is either coming
|
||||
* from the kernel or it is being forwarded; check the packet
|
||||
* to determine which and if the packet is being forwarded
|
||||
* query the packet directly to determine the security label. */
|
||||
if (skb->skb_iif) {
|
||||
secmark_perm = PACKET__FORWARD_OUT;
|
||||
if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
|
||||
@@ -4729,7 +4769,26 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
|
||||
secmark_perm = PACKET__SEND;
|
||||
peer_sid = SECINITSID_KERNEL;
|
||||
}
|
||||
} else if (sk->sk_state == TCP_LISTEN) {
|
||||
/* Locally generated packet but the associated socket is in the
|
||||
* listening state which means this is a SYN-ACK packet. In
|
||||
* this particular case the correct security label is assigned
|
||||
* to the connection/request_sock but unfortunately we can't
|
||||
* query the request_sock as it isn't queued on the parent
|
||||
* socket until after the SYN-ACK packet is sent; the only
|
||||
* viable choice is to regenerate the label like we do in
|
||||
* selinux_inet_conn_request(). See also selinux_ip_output()
|
||||
* for similar problems. */
|
||||
u32 skb_sid;
|
||||
struct sk_security_struct *sksec = sk->sk_security;
|
||||
if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
|
||||
return NF_DROP;
|
||||
if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
|
||||
return NF_DROP;
|
||||
secmark_perm = PACKET__SEND;
|
||||
} else {
|
||||
/* Locally generated packet, fetch the security label from the
|
||||
* associated socket. */
|
||||
struct sk_security_struct *sksec = sk->sk_security;
|
||||
peer_sid = sksec->sid;
|
||||
secmark_perm = PACKET__SEND;
|
||||
|
||||
Reference in New Issue
Block a user