From: paul.moore@hp.com
To: netdev@vger.kernel.org, selinux@tycho.nsa.gov
Cc: vyekkirala@TrustedCS.com, jmorris@namei.org, sds@tycho.nsa.gov
Subject: [PATCH 10/11] secid reconciliation: various fixes
Date: Mon, 09 Oct 2006 15:42:33 -0400 [thread overview]
Message-ID: <20061009195852.914941000@hp.com> (raw)
In-Reply-To: 20061009194223.402695000@hp.com
From: Venkat Yekkirala <vyekkirala@TrustedCS.com>
This fixes the secid reconciliation code in the following ways:
1. Null-out secmark on an outgoing packet after we are done with all
the checks. This has been necessitated by the fact that some packets
sent to a multicast address could arrive back on a non-loopback
interface but with the secmark intact. This would result in the
current flow_out control logic to use it as a security point context
when no explicit security points have been defined for the inbound
packet.
2. Label udp/raw packets with the label of the socket.
3. Label igmp traffic with the igmp_packet initial context.
4. Limit flow-controlling of loopback traffic to the socket.recv permission
check. This means that packet.flow_in/flow_out checks are no longer
applicable to loopback traffic. This is because of current implementation
constraints.
DOCUMENTATION OF SECID RECONCILIATION AND FLOW CONTROL FOR POLICY WRITERS:
ON INBOUND:
1. PACKETS ENTERING SYSTEM FROM A NON-LOOPBACK DEVICE:
Can a packet "carrying" external domain label x_t "flow_in" thru the
security point with the peer domain label p_d_t?
NOTE:
a. x_t defaults to unlabeled_t, if no external label.
b. p_d_t defaults to network_t in the absence of any applicable
[conn]secmark rules for the packet. If there are multiple
secmark rules applicable to a packet, the context on the LAST
rule will apply.
NO: Drop packet.
YES: If no external label, let packet "carry" p_d_t.
2. INPUT ONLY: Can a socket "recv" a packet from domain p_d_t?
NO: Drop packet.
YES: If setting up a tcp connection, set peer context to p_d_t.
ON OUTBOUND:
1. Let packet "carry" the originating socket domain label.
2. IPSEC Handling:
LABELED IPSEC: If packet "polmatch"es to an otherwise applicable and
labeled SPD entry, choose a Security Association (SA) with the SAME context
as the domain label being carried by packet.
NOTE: If no such SA present, call into IKE with context on packet.
NON-LABELED (PLAIN/TRADITIONAL) IPSEC: If there's an applicable SPD entry
that does NOT have an explicit context associated with it, an applicable SA
that does NOT have an explicit context associated with it is chosen.
NOTE: If no such SA present, call into IKE, but with NO context.
3. PACKETS DESTINED FOR NON-LOOPBACK DEVICE:
a. IPTABLES Processing:
As EACH applicable iptables [CONN]SECMARK rule with domain p_d_t is
encountered, do the following:
Can a packet carrying domain label a_t "flow_out" of the security point
with the domain label p_d_t?
NO: Drop packet.
YES: Replace the domain label a_t on the packet with the security point
label p_d_t.
b. Before a packet is let out of the system:
Can a packet with domain label p_d_t "flow_out" into the network domain
network_t?
NO: Drop packet.
YES: Let packet out.
NOTE: Ideally this check should be applicable only to packets that
didn't go thru [conn]secmark checks for outbound, but there's
currently no way to know this due to implementation constrains.
Hence a blanket check for ALL packets leaving the system.
FORWARDED TRAFFIC:
Forwarded Traffic will undergo the following:
1. Step 1 under ON INBOUND.
2. Steps 2 and 3 under ON OUTBOUND.
Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com>
---
include/linux/security.h | 24 +++++++++-------
include/net/ip.h | 13 ++++++++
include/net/request_sock.h | 11 +++++++
net/ipv4/igmp.c | 4 ++
net/ipv4/raw.c | 2 +
net/ipv4/udp.c | 2 +
net/netfilter/xt_CONNSECMARK.c | 21 ++++++++++----
net/netfilter/xt_SECMARK.c | 16 ++++++++--
security/dummy.c | 8 ++---
security/selinux/hooks.c | 61 +++++++++++++++++++++++++++++++++--------
10 files changed, 129 insertions(+), 33 deletions(-)
Index: net-2.6_secidfinal/include/linux/security.h
===================================================================
--- net-2.6_secidfinal.orig/include/linux/security.h
+++ net-2.6_secidfinal/include/linux/security.h
@@ -67,6 +67,7 @@ struct xfrm_selector;
struct xfrm_policy;
struct xfrm_state;
struct xfrm_user_sec_ctx;
+struct net_device;
extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
extern int cap_netlink_recv(struct sk_buff *skb, int cap);
@@ -828,8 +829,8 @@ struct request_sock;
* Sets the new child socket's sid to the openreq sid.
* @inet_conn_established:
* Sets the connection's peersid to the secmark on skb.
- * @req_classify_flow:
- * Sets the flow's sid to the openreq sid.
+ * @igmp_classify_skb:
+ * Classifies an skb representing an igmp packet.
* @skb_flow_in:
* Checks to see if security policy would allow skb into the system
* while also reconciling the xfrm secid, cipso, etc, if any, and
@@ -1383,9 +1384,10 @@ struct security_operations {
struct request_sock *req);
void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req);
void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb);
- void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl);
+ void (*igmp_classify_skb)(struct sk_buff *skb);
int (*skb_flow_in)(struct sk_buff *skb, unsigned short family);
- int (*skb_flow_out)(struct sk_buff *skb, u32 nf_secid);
+ int (*skb_flow_out)(struct sk_buff *skb, u32 nf_secid,
+ const struct net_device *out, unsigned short family);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -2956,9 +2958,9 @@ static inline void security_sk_classify_
security_ops->sk_getsecid(sk, &fl->secid);
}
-static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
+static inline void security_igmp_classify_skb(struct sk_buff *skb)
{
- security_ops->req_classify_flow(req, fl);
+ security_ops->igmp_classify_skb(skb);
}
static inline int security_skb_flow_in(struct sk_buff *skb,
@@ -2968,9 +2970,10 @@ static inline int security_skb_flow_in(s
}
static inline int security_skb_flow_out(struct sk_buff *skb,
- u32 nf_secid)
+ u32 nf_secid, const struct net_device *out,
+ unsigned short family)
{
- return security_ops->skb_flow_out(skb, nf_secid);
+ return security_ops->skb_flow_out(skb, nf_secid, out, family);
}
static inline void security_sock_graft(struct sock* sk, struct socket *parent)
@@ -3126,7 +3129,7 @@ static inline void security_sk_classify_
{
}
-static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
+static inline void security_igmp_classify_skb(struct sk_buff *skb)
{
}
@@ -3137,7 +3140,8 @@ static inline int security_skb_flow_in(s
}
static inline int security_skb_flow_out(struct sk_buff *skb,
- u32 nf_secid)
+ u32 nf_secid, const struct net_device *out,
+ unsigned short family)
{
return -ENOENT;
}
Index: net-2.6_secidfinal/include/net/ip.h
===================================================================
--- net-2.6_secidfinal.orig/include/net/ip.h
+++ net-2.6_secidfinal/include/net/ip.h
@@ -388,6 +388,14 @@ extern struct ctl_table ipv4_table[];
#ifdef CONFIG_SECURITY_NETWORK
+extern struct security_operations *security_ops;
+
+static inline void security_sk_classify_ipcm(struct sock *sk,
+ struct ipcm_cookie *ipc)
+{
+ security_ops->sk_getsecid(sk, &ipc->secid);
+}
+
static inline void security_skb_classify_ipcm(struct sk_buff *skb,
struct ipcm_cookie *ipc)
{
@@ -402,6 +410,11 @@ static inline void security_ipcm_classif
#else
+static inline void security_sk_classify_ipcm(struct sock *sk,
+ struct ipcm_cookie *ipc)
+{
+}
+
static inline void security_skb_classify_ipcm(struct sk_buff *skb,
struct ipcm_cookie *ipc)
{
Index: net-2.6_secidfinal/include/net/request_sock.h
===================================================================
--- net-2.6_secidfinal.orig/include/net/request_sock.h
+++ net-2.6_secidfinal/include/net/request_sock.h
@@ -262,6 +262,12 @@ static inline void reqsk_queue_hash_req(
#ifdef CONFIG_SECURITY_NETWORK
+static inline void security_req_classify_flow(const struct request_sock *req,
+ struct flowi *fl)
+{
+ fl->secid = req->secid;
+}
+
static inline void security_req_classify_skb(struct request_sock *req,
struct sk_buff *skb)
{
@@ -270,6 +276,11 @@ static inline void security_req_classify
#else
+static inline void security_req_classify_flow(const struct request_sock *req,
+ struct flowi *fl)
+{
+}
+
static inline void security_req_classify_skb(struct request_sock *req,
struct sk_buff *skb)
{
Index: net-2.6_secidfinal/net/ipv4/igmp.c
===================================================================
--- net-2.6_secidfinal.orig/net/ipv4/igmp.c
+++ net-2.6_secidfinal/net/ipv4/igmp.c
@@ -293,6 +293,8 @@ static struct sk_buff *igmpv3_newpack(st
if (skb == NULL)
return NULL;
+ security_igmp_classify_skb(skb);
+
{
struct flowi fl = { .oif = dev->ifindex,
.nl_u = { .ip4_u = {
@@ -658,6 +660,8 @@ static int igmp_send_report(struct in_de
return -1;
}
+ security_igmp_classify_skb(skb);
+
skb->dst = &rt->u.dst;
skb_reserve(skb, LL_RESERVED_SPACE(dev));
Index: net-2.6_secidfinal/net/ipv4/raw.c
===================================================================
--- net-2.6_secidfinal.orig/net/ipv4/raw.c
+++ net-2.6_secidfinal/net/ipv4/raw.c
@@ -433,6 +433,8 @@ static int raw_sendmsg(struct kiocb *ioc
ipc.opt = NULL;
ipc.oif = sk->sk_bound_dev_if;
+ security_sk_classify_ipcm(sk, &ipc);
+
if (msg->msg_controllen) {
err = ip_cmsg_send(msg, &ipc);
if (err)
Index: net-2.6_secidfinal/net/ipv4/udp.c
===================================================================
--- net-2.6_secidfinal.orig/net/ipv4/udp.c
+++ net-2.6_secidfinal/net/ipv4/udp.c
@@ -588,6 +588,8 @@ int udp_sendmsg(struct kiocb *iocb, stru
if (!ipc.opt)
ipc.opt = inet->opt;
+ security_sk_classify_ipcm(sk, &ipc);
+
saddr = ipc.addr;
ipc.addr = faddr = daddr;
Index: net-2.6_secidfinal/net/netfilter/xt_CONNSECMARK.c
===================================================================
--- net-2.6_secidfinal.orig/net/netfilter/xt_CONNSECMARK.c
+++ net-2.6_secidfinal/net/netfilter/xt_CONNSECMARK.c
@@ -68,7 +68,8 @@ static void secmark_save(struct sk_buff
* On the outbound, filter based on the current secmark.
*/
static unsigned int secmark_restore(struct sk_buff *skb, unsigned int hooknum,
- const struct net_device *in, unsigned short family)
+ const struct net_device *in, const struct net_device *out,
+ unsigned short family)
{
u32 *psecmark;
enum ip_conntrack_info ctinfo;
@@ -81,14 +82,24 @@ static unsigned int secmark_restore(stru
if (outbound(family, hooknum)) {
int err;
- err = security_skb_flow_out(skb, *psecmark);
+ /*
+ * We can't currently flow-control loopback traffic
+ * very well since we want to retain the secmark of
+ * the originating socket and if we do retain it,
+ * it will cause connsecmark save & restore to use this
+ * socket label and mess up the semantics of the "peer
+ * security point".
+ */
+ if (out == &loopback_dev)
+ goto out;
+
+ err = security_skb_flow_out(skb, *psecmark, out, family);
if (!err)
return NF_DROP;
} else
/*
* inbound:
- * loopback traffic should already be labeled
- * and any filtering on outbound should suffice
+ * No filtering of loopback traffic.
*/
if (in == &loopback_dev)
goto out;
@@ -119,7 +130,7 @@ static unsigned int target(struct sk_buf
break;
case CONNSECMARK_RESTORE:
- return secmark_restore(skb, hooknum, in, target->family);
+ return secmark_restore(skb, hooknum, in, out, target->family);
break;
default:
Index: net-2.6_secidfinal/net/netfilter/xt_SECMARK.c
===================================================================
--- net-2.6_secidfinal.orig/net/netfilter/xt_SECMARK.c
+++ net-2.6_secidfinal/net/netfilter/xt_SECMARK.c
@@ -70,14 +70,24 @@ static unsigned int target(struct sk_buf
if (outbound(target->family, hooknum)) {
int err;
- err = security_skb_flow_out(*pskb, secmark);
+ /*
+ * We can't currently flow-control loopback traffic
+ * very well since we want to retain the secmark of
+ * the originating socket and if we do retain it,
+ * it will cause connsecmark save & restore to use this
+ * socket label and mess up the semantics of the "peer
+ * security point".
+ */
+ if (out == &loopback_dev)
+ goto out;
+
+ err = security_skb_flow_out(*pskb, secmark, out, target->family);
if (!err)
return NF_DROP;
} else
/*
* inbound:
- * loopback traffic should already be labeled
- * and any filtering on outbound should suffice
+ * No filtering of loopback traffic.
*/
if (in == &loopback_dev)
goto out;
Index: net-2.6_secidfinal/security/dummy.c
===================================================================
--- net-2.6_secidfinal.orig/security/dummy.c
+++ net-2.6_secidfinal/security/dummy.c
@@ -833,8 +833,7 @@ static inline void dummy_inet_conn_estab
{
}
-static inline void dummy_req_classify_flow(const struct request_sock *req,
- struct flowi *fl)
+static inline void dummy_igmp_classify_skb(struct sk_buff *skb)
{
}
@@ -844,7 +843,8 @@ static inline int dummy_skb_flow_in(stru
return -ENOENT;
}
-static inline int dummy_skb_flow_out(struct sk_buff *skb, u32 nf_secid)
+static inline int dummy_skb_flow_out(struct sk_buff *skb, u32 nf_secid,
+ const struct net_device *out, unsigned short family)
{
return -ENOENT;
}
@@ -1124,7 +1124,7 @@ void security_fixup_ops (struct security
set_to_dummy_if_null(ops, inet_conn_request);
set_to_dummy_if_null(ops, inet_csk_clone);
set_to_dummy_if_null(ops, inet_conn_established);
- set_to_dummy_if_null(ops, req_classify_flow);
+ set_to_dummy_if_null(ops, igmp_classify_skb);
set_to_dummy_if_null(ops, skb_flow_in);
set_to_dummy_if_null(ops, skb_flow_out);
#endif /* CONFIG_SECURITY_NETWORK */
Index: net-2.6_secidfinal/security/selinux/hooks.c
===================================================================
--- net-2.6_secidfinal.orig/security/selinux/hooks.c
+++ net-2.6_secidfinal/security/selinux/hooks.c
@@ -3691,35 +3691,42 @@ static void selinux_inet_conn_establishe
sksec->peer_sid = skb->secmark;
}
-static void selinux_req_classify_flow(const struct request_sock *req,
- struct flowi *fl)
+static void selinux_igmp_classify_skb(struct sk_buff *skb)
{
- fl->secid = req->secid;
+ skb->secmark = SECINITSID_IGMP_PACKET;
}
static int selinux_skb_flow_in(struct sk_buff *skb, unsigned short family)
{
u32 xfrm_sid;
int err;
+ struct avc_audit_data ad;
+ char *addrp;
+ int len;
if (selinux_compat_net)
return 1;
/*
- * loopback traffic already labeled and
- * flow-controlled on outbound. We may
- * need to flow-control on the inbound
- * as well if there's ever a use-case for it.
+ * loopback traffic should already be labeled with
+ * the originating socket label.
*/
if (skb->dev == &loopback_dev)
return 1;
+ AVC_AUDIT_DATA_INIT(&ad, NET);
+ ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
+ ad.u.net.family = family;
+ err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
+ if (err)
+ goto out;
+
err = selinux_xfrm_decode_session(skb, &xfrm_sid, 0);
BUG_ON(err);
err = avc_has_perm(xfrm_sid, skb->secmark? : SECINITSID_NETMSG,
SECCLASS_PACKET,
- PACKET__FLOW_IN, NULL);
+ PACKET__FLOW_IN, &ad);
if (err)
goto out;
@@ -3732,9 +3739,14 @@ out:
return err ? 0 : 1;
};
-static int selinux_skb_flow_out(struct sk_buff *skb, u32 nf_secid)
+static int selinux_skb_flow_out(struct sk_buff *skb, u32 nf_secid,
+ const struct net_device *out, unsigned short family)
{
int err;
+ char *addrp;
+ int len;
+ struct net_device *dev = (struct net_device *)out;
+ struct avc_audit_data ad;
if (selinux_compat_net)
return 1;
@@ -3752,9 +3764,17 @@ static int selinux_skb_flow_out(struct s
}
}
+ AVC_AUDIT_DATA_INIT(&ad, NET);
+ ad.u.net.netif = dev->name;
+ ad.u.net.family = family;
+ err = selinux_parse_skb(skb, &ad, &addrp, &len, 0);
+ if (err)
+ goto out;
+
err = avc_has_perm(skb->secmark, nf_secid, SECCLASS_PACKET,
- PACKET__FLOW_OUT, NULL);
+ PACKET__FLOW_OUT, &ad);
+out:
return err ? 0 : 1;
}
@@ -3915,8 +3935,27 @@ static unsigned int selinux_ip_postroute
skb->secmark = sksec->sid;
}
}
+ if (out == &loopback_dev)
+ return NF_ACCEPT;
+
err = avc_has_perm(skb->secmark, SECINITSID_NETMSG,
SECCLASS_PACKET, PACKET__FLOW_OUT, &ad);
+
+ if (skb->secmark)
+ /*
+ * Our multicast packets could get copied back
+ * to us, arriving on a non-loopback device.
+ * Leaving the secmark intact here will cause it
+ * to be used as a security point context in
+ * the flow_in hook above while it's not in fact
+ * a security point context.
+ *
+ * We may be able to retain this marking if
+ * we can reliably determine that it was a local
+ * packet although it arrived on a non-loopback
+ * device, in the flow_in hook above.
+ */
+ skb->secmark = SECSID_NULL;
}
out:
return err ? NF_DROP : NF_ACCEPT;
@@ -4824,7 +4863,7 @@ static struct security_operations selinu
.inet_conn_request = selinux_inet_conn_request,
.inet_csk_clone = selinux_inet_csk_clone,
.inet_conn_established = selinux_inet_conn_established,
- .req_classify_flow = selinux_req_classify_flow,
+ .igmp_classify_skb = selinux_igmp_classify_skb,
.skb_flow_in = selinux_skb_flow_in,
.skb_flow_out = selinux_skb_flow_out,
--
paul moore
linux security @ hp
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
WARNING: multiple messages have this Message-ID (diff)
From: paul.moore@hp.com
To: netdev@vger.kernel.org, selinux@tycho.nsa.gov
Cc: vyekkirala@TrustedCS.com, jmorris@namei.org, sds@tycho.nsa.gov
Subject: [PATCH 10/11] secid reconciliation: various fixes
Date: Mon, 09 Oct 2006 15:42:33 -0400 [thread overview]
Message-ID: <20061009195852.914941000@hp.com> (raw)
In-Reply-To: 20061009194223.402695000@hp.com
[-- Attachment #1: secid-fix_1 --]
[-- Type: text/plain, Size: 17809 bytes --]
From: Venkat Yekkirala <vyekkirala@TrustedCS.com>
This fixes the secid reconciliation code in the following ways:
1. Null-out secmark on an outgoing packet after we are done with all
the checks. This has been necessitated by the fact that some packets
sent to a multicast address could arrive back on a non-loopback
interface but with the secmark intact. This would result in the
current flow_out control logic to use it as a security point context
when no explicit security points have been defined for the inbound
packet.
2. Label udp/raw packets with the label of the socket.
3. Label igmp traffic with the igmp_packet initial context.
4. Limit flow-controlling of loopback traffic to the socket.recv permission
check. This means that packet.flow_in/flow_out checks are no longer
applicable to loopback traffic. This is because of current implementation
constraints.
DOCUMENTATION OF SECID RECONCILIATION AND FLOW CONTROL FOR POLICY WRITERS:
ON INBOUND:
1. PACKETS ENTERING SYSTEM FROM A NON-LOOPBACK DEVICE:
Can a packet "carrying" external domain label x_t "flow_in" thru the
security point with the peer domain label p_d_t?
NOTE:
a. x_t defaults to unlabeled_t, if no external label.
b. p_d_t defaults to network_t in the absence of any applicable
[conn]secmark rules for the packet. If there are multiple
secmark rules applicable to a packet, the context on the LAST
rule will apply.
NO: Drop packet.
YES: If no external label, let packet "carry" p_d_t.
2. INPUT ONLY: Can a socket "recv" a packet from domain p_d_t?
NO: Drop packet.
YES: If setting up a tcp connection, set peer context to p_d_t.
ON OUTBOUND:
1. Let packet "carry" the originating socket domain label.
2. IPSEC Handling:
LABELED IPSEC: If packet "polmatch"es to an otherwise applicable and
labeled SPD entry, choose a Security Association (SA) with the SAME context
as the domain label being carried by packet.
NOTE: If no such SA present, call into IKE with context on packet.
NON-LABELED (PLAIN/TRADITIONAL) IPSEC: If there's an applicable SPD entry
that does NOT have an explicit context associated with it, an applicable SA
that does NOT have an explicit context associated with it is chosen.
NOTE: If no such SA present, call into IKE, but with NO context.
3. PACKETS DESTINED FOR NON-LOOPBACK DEVICE:
a. IPTABLES Processing:
As EACH applicable iptables [CONN]SECMARK rule with domain p_d_t is
encountered, do the following:
Can a packet carrying domain label a_t "flow_out" of the security point
with the domain label p_d_t?
NO: Drop packet.
YES: Replace the domain label a_t on the packet with the security point
label p_d_t.
b. Before a packet is let out of the system:
Can a packet with domain label p_d_t "flow_out" into the network domain
network_t?
NO: Drop packet.
YES: Let packet out.
NOTE: Ideally this check should be applicable only to packets that
didn't go thru [conn]secmark checks for outbound, but there's
currently no way to know this due to implementation constrains.
Hence a blanket check for ALL packets leaving the system.
FORWARDED TRAFFIC:
Forwarded Traffic will undergo the following:
1. Step 1 under ON INBOUND.
2. Steps 2 and 3 under ON OUTBOUND.
Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com>
---
include/linux/security.h | 24 +++++++++-------
include/net/ip.h | 13 ++++++++
include/net/request_sock.h | 11 +++++++
net/ipv4/igmp.c | 4 ++
net/ipv4/raw.c | 2 +
net/ipv4/udp.c | 2 +
net/netfilter/xt_CONNSECMARK.c | 21 ++++++++++----
net/netfilter/xt_SECMARK.c | 16 ++++++++--
security/dummy.c | 8 ++---
security/selinux/hooks.c | 61 +++++++++++++++++++++++++++++++++--------
10 files changed, 129 insertions(+), 33 deletions(-)
Index: net-2.6_secidfinal/include/linux/security.h
===================================================================
--- net-2.6_secidfinal.orig/include/linux/security.h
+++ net-2.6_secidfinal/include/linux/security.h
@@ -67,6 +67,7 @@ struct xfrm_selector;
struct xfrm_policy;
struct xfrm_state;
struct xfrm_user_sec_ctx;
+struct net_device;
extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
extern int cap_netlink_recv(struct sk_buff *skb, int cap);
@@ -828,8 +829,8 @@ struct request_sock;
* Sets the new child socket's sid to the openreq sid.
* @inet_conn_established:
* Sets the connection's peersid to the secmark on skb.
- * @req_classify_flow:
- * Sets the flow's sid to the openreq sid.
+ * @igmp_classify_skb:
+ * Classifies an skb representing an igmp packet.
* @skb_flow_in:
* Checks to see if security policy would allow skb into the system
* while also reconciling the xfrm secid, cipso, etc, if any, and
@@ -1383,9 +1384,10 @@ struct security_operations {
struct request_sock *req);
void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req);
void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb);
- void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl);
+ void (*igmp_classify_skb)(struct sk_buff *skb);
int (*skb_flow_in)(struct sk_buff *skb, unsigned short family);
- int (*skb_flow_out)(struct sk_buff *skb, u32 nf_secid);
+ int (*skb_flow_out)(struct sk_buff *skb, u32 nf_secid,
+ const struct net_device *out, unsigned short family);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -2956,9 +2958,9 @@ static inline void security_sk_classify_
security_ops->sk_getsecid(sk, &fl->secid);
}
-static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
+static inline void security_igmp_classify_skb(struct sk_buff *skb)
{
- security_ops->req_classify_flow(req, fl);
+ security_ops->igmp_classify_skb(skb);
}
static inline int security_skb_flow_in(struct sk_buff *skb,
@@ -2968,9 +2970,10 @@ static inline int security_skb_flow_in(s
}
static inline int security_skb_flow_out(struct sk_buff *skb,
- u32 nf_secid)
+ u32 nf_secid, const struct net_device *out,
+ unsigned short family)
{
- return security_ops->skb_flow_out(skb, nf_secid);
+ return security_ops->skb_flow_out(skb, nf_secid, out, family);
}
static inline void security_sock_graft(struct sock* sk, struct socket *parent)
@@ -3126,7 +3129,7 @@ static inline void security_sk_classify_
{
}
-static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
+static inline void security_igmp_classify_skb(struct sk_buff *skb)
{
}
@@ -3137,7 +3140,8 @@ static inline int security_skb_flow_in(s
}
static inline int security_skb_flow_out(struct sk_buff *skb,
- u32 nf_secid)
+ u32 nf_secid, const struct net_device *out,
+ unsigned short family)
{
return -ENOENT;
}
Index: net-2.6_secidfinal/include/net/ip.h
===================================================================
--- net-2.6_secidfinal.orig/include/net/ip.h
+++ net-2.6_secidfinal/include/net/ip.h
@@ -388,6 +388,14 @@ extern struct ctl_table ipv4_table[];
#ifdef CONFIG_SECURITY_NETWORK
+extern struct security_operations *security_ops;
+
+static inline void security_sk_classify_ipcm(struct sock *sk,
+ struct ipcm_cookie *ipc)
+{
+ security_ops->sk_getsecid(sk, &ipc->secid);
+}
+
static inline void security_skb_classify_ipcm(struct sk_buff *skb,
struct ipcm_cookie *ipc)
{
@@ -402,6 +410,11 @@ static inline void security_ipcm_classif
#else
+static inline void security_sk_classify_ipcm(struct sock *sk,
+ struct ipcm_cookie *ipc)
+{
+}
+
static inline void security_skb_classify_ipcm(struct sk_buff *skb,
struct ipcm_cookie *ipc)
{
Index: net-2.6_secidfinal/include/net/request_sock.h
===================================================================
--- net-2.6_secidfinal.orig/include/net/request_sock.h
+++ net-2.6_secidfinal/include/net/request_sock.h
@@ -262,6 +262,12 @@ static inline void reqsk_queue_hash_req(
#ifdef CONFIG_SECURITY_NETWORK
+static inline void security_req_classify_flow(const struct request_sock *req,
+ struct flowi *fl)
+{
+ fl->secid = req->secid;
+}
+
static inline void security_req_classify_skb(struct request_sock *req,
struct sk_buff *skb)
{
@@ -270,6 +276,11 @@ static inline void security_req_classify
#else
+static inline void security_req_classify_flow(const struct request_sock *req,
+ struct flowi *fl)
+{
+}
+
static inline void security_req_classify_skb(struct request_sock *req,
struct sk_buff *skb)
{
Index: net-2.6_secidfinal/net/ipv4/igmp.c
===================================================================
--- net-2.6_secidfinal.orig/net/ipv4/igmp.c
+++ net-2.6_secidfinal/net/ipv4/igmp.c
@@ -293,6 +293,8 @@ static struct sk_buff *igmpv3_newpack(st
if (skb == NULL)
return NULL;
+ security_igmp_classify_skb(skb);
+
{
struct flowi fl = { .oif = dev->ifindex,
.nl_u = { .ip4_u = {
@@ -658,6 +660,8 @@ static int igmp_send_report(struct in_de
return -1;
}
+ security_igmp_classify_skb(skb);
+
skb->dst = &rt->u.dst;
skb_reserve(skb, LL_RESERVED_SPACE(dev));
Index: net-2.6_secidfinal/net/ipv4/raw.c
===================================================================
--- net-2.6_secidfinal.orig/net/ipv4/raw.c
+++ net-2.6_secidfinal/net/ipv4/raw.c
@@ -433,6 +433,8 @@ static int raw_sendmsg(struct kiocb *ioc
ipc.opt = NULL;
ipc.oif = sk->sk_bound_dev_if;
+ security_sk_classify_ipcm(sk, &ipc);
+
if (msg->msg_controllen) {
err = ip_cmsg_send(msg, &ipc);
if (err)
Index: net-2.6_secidfinal/net/ipv4/udp.c
===================================================================
--- net-2.6_secidfinal.orig/net/ipv4/udp.c
+++ net-2.6_secidfinal/net/ipv4/udp.c
@@ -588,6 +588,8 @@ int udp_sendmsg(struct kiocb *iocb, stru
if (!ipc.opt)
ipc.opt = inet->opt;
+ security_sk_classify_ipcm(sk, &ipc);
+
saddr = ipc.addr;
ipc.addr = faddr = daddr;
Index: net-2.6_secidfinal/net/netfilter/xt_CONNSECMARK.c
===================================================================
--- net-2.6_secidfinal.orig/net/netfilter/xt_CONNSECMARK.c
+++ net-2.6_secidfinal/net/netfilter/xt_CONNSECMARK.c
@@ -68,7 +68,8 @@ static void secmark_save(struct sk_buff
* On the outbound, filter based on the current secmark.
*/
static unsigned int secmark_restore(struct sk_buff *skb, unsigned int hooknum,
- const struct net_device *in, unsigned short family)
+ const struct net_device *in, const struct net_device *out,
+ unsigned short family)
{
u32 *psecmark;
enum ip_conntrack_info ctinfo;
@@ -81,14 +82,24 @@ static unsigned int secmark_restore(stru
if (outbound(family, hooknum)) {
int err;
- err = security_skb_flow_out(skb, *psecmark);
+ /*
+ * We can't currently flow-control loopback traffic
+ * very well since we want to retain the secmark of
+ * the originating socket and if we do retain it,
+ * it will cause connsecmark save & restore to use this
+ * socket label and mess up the semantics of the "peer
+ * security point".
+ */
+ if (out == &loopback_dev)
+ goto out;
+
+ err = security_skb_flow_out(skb, *psecmark, out, family);
if (!err)
return NF_DROP;
} else
/*
* inbound:
- * loopback traffic should already be labeled
- * and any filtering on outbound should suffice
+ * No filtering of loopback traffic.
*/
if (in == &loopback_dev)
goto out;
@@ -119,7 +130,7 @@ static unsigned int target(struct sk_buf
break;
case CONNSECMARK_RESTORE:
- return secmark_restore(skb, hooknum, in, target->family);
+ return secmark_restore(skb, hooknum, in, out, target->family);
break;
default:
Index: net-2.6_secidfinal/net/netfilter/xt_SECMARK.c
===================================================================
--- net-2.6_secidfinal.orig/net/netfilter/xt_SECMARK.c
+++ net-2.6_secidfinal/net/netfilter/xt_SECMARK.c
@@ -70,14 +70,24 @@ static unsigned int target(struct sk_buf
if (outbound(target->family, hooknum)) {
int err;
- err = security_skb_flow_out(*pskb, secmark);
+ /*
+ * We can't currently flow-control loopback traffic
+ * very well since we want to retain the secmark of
+ * the originating socket and if we do retain it,
+ * it will cause connsecmark save & restore to use this
+ * socket label and mess up the semantics of the "peer
+ * security point".
+ */
+ if (out == &loopback_dev)
+ goto out;
+
+ err = security_skb_flow_out(*pskb, secmark, out, target->family);
if (!err)
return NF_DROP;
} else
/*
* inbound:
- * loopback traffic should already be labeled
- * and any filtering on outbound should suffice
+ * No filtering of loopback traffic.
*/
if (in == &loopback_dev)
goto out;
Index: net-2.6_secidfinal/security/dummy.c
===================================================================
--- net-2.6_secidfinal.orig/security/dummy.c
+++ net-2.6_secidfinal/security/dummy.c
@@ -833,8 +833,7 @@ static inline void dummy_inet_conn_estab
{
}
-static inline void dummy_req_classify_flow(const struct request_sock *req,
- struct flowi *fl)
+static inline void dummy_igmp_classify_skb(struct sk_buff *skb)
{
}
@@ -844,7 +843,8 @@ static inline int dummy_skb_flow_in(stru
return -ENOENT;
}
-static inline int dummy_skb_flow_out(struct sk_buff *skb, u32 nf_secid)
+static inline int dummy_skb_flow_out(struct sk_buff *skb, u32 nf_secid,
+ const struct net_device *out, unsigned short family)
{
return -ENOENT;
}
@@ -1124,7 +1124,7 @@ void security_fixup_ops (struct security
set_to_dummy_if_null(ops, inet_conn_request);
set_to_dummy_if_null(ops, inet_csk_clone);
set_to_dummy_if_null(ops, inet_conn_established);
- set_to_dummy_if_null(ops, req_classify_flow);
+ set_to_dummy_if_null(ops, igmp_classify_skb);
set_to_dummy_if_null(ops, skb_flow_in);
set_to_dummy_if_null(ops, skb_flow_out);
#endif /* CONFIG_SECURITY_NETWORK */
Index: net-2.6_secidfinal/security/selinux/hooks.c
===================================================================
--- net-2.6_secidfinal.orig/security/selinux/hooks.c
+++ net-2.6_secidfinal/security/selinux/hooks.c
@@ -3691,35 +3691,42 @@ static void selinux_inet_conn_establishe
sksec->peer_sid = skb->secmark;
}
-static void selinux_req_classify_flow(const struct request_sock *req,
- struct flowi *fl)
+static void selinux_igmp_classify_skb(struct sk_buff *skb)
{
- fl->secid = req->secid;
+ skb->secmark = SECINITSID_IGMP_PACKET;
}
static int selinux_skb_flow_in(struct sk_buff *skb, unsigned short family)
{
u32 xfrm_sid;
int err;
+ struct avc_audit_data ad;
+ char *addrp;
+ int len;
if (selinux_compat_net)
return 1;
/*
- * loopback traffic already labeled and
- * flow-controlled on outbound. We may
- * need to flow-control on the inbound
- * as well if there's ever a use-case for it.
+ * loopback traffic should already be labeled with
+ * the originating socket label.
*/
if (skb->dev == &loopback_dev)
return 1;
+ AVC_AUDIT_DATA_INIT(&ad, NET);
+ ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
+ ad.u.net.family = family;
+ err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
+ if (err)
+ goto out;
+
err = selinux_xfrm_decode_session(skb, &xfrm_sid, 0);
BUG_ON(err);
err = avc_has_perm(xfrm_sid, skb->secmark? : SECINITSID_NETMSG,
SECCLASS_PACKET,
- PACKET__FLOW_IN, NULL);
+ PACKET__FLOW_IN, &ad);
if (err)
goto out;
@@ -3732,9 +3739,14 @@ out:
return err ? 0 : 1;
};
-static int selinux_skb_flow_out(struct sk_buff *skb, u32 nf_secid)
+static int selinux_skb_flow_out(struct sk_buff *skb, u32 nf_secid,
+ const struct net_device *out, unsigned short family)
{
int err;
+ char *addrp;
+ int len;
+ struct net_device *dev = (struct net_device *)out;
+ struct avc_audit_data ad;
if (selinux_compat_net)
return 1;
@@ -3752,9 +3764,17 @@ static int selinux_skb_flow_out(struct s
}
}
+ AVC_AUDIT_DATA_INIT(&ad, NET);
+ ad.u.net.netif = dev->name;
+ ad.u.net.family = family;
+ err = selinux_parse_skb(skb, &ad, &addrp, &len, 0);
+ if (err)
+ goto out;
+
err = avc_has_perm(skb->secmark, nf_secid, SECCLASS_PACKET,
- PACKET__FLOW_OUT, NULL);
+ PACKET__FLOW_OUT, &ad);
+out:
return err ? 0 : 1;
}
@@ -3915,8 +3935,27 @@ static unsigned int selinux_ip_postroute
skb->secmark = sksec->sid;
}
}
+ if (out == &loopback_dev)
+ return NF_ACCEPT;
+
err = avc_has_perm(skb->secmark, SECINITSID_NETMSG,
SECCLASS_PACKET, PACKET__FLOW_OUT, &ad);
+
+ if (skb->secmark)
+ /*
+ * Our multicast packets could get copied back
+ * to us, arriving on a non-loopback device.
+ * Leaving the secmark intact here will cause it
+ * to be used as a security point context in
+ * the flow_in hook above while it's not in fact
+ * a security point context.
+ *
+ * We may be able to retain this marking if
+ * we can reliably determine that it was a local
+ * packet although it arrived on a non-loopback
+ * device, in the flow_in hook above.
+ */
+ skb->secmark = SECSID_NULL;
}
out:
return err ? NF_DROP : NF_ACCEPT;
@@ -4824,7 +4863,7 @@ static struct security_operations selinu
.inet_conn_request = selinux_inet_conn_request,
.inet_csk_clone = selinux_inet_csk_clone,
.inet_conn_established = selinux_inet_conn_established,
- .req_classify_flow = selinux_req_classify_flow,
+ .igmp_classify_skb = selinux_igmp_classify_skb,
.skb_flow_in = selinux_skb_flow_in,
.skb_flow_out = selinux_skb_flow_out,
--
paul moore
linux security @ hp
next prev parent reply other threads:[~2006-10-09 19:42 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-10-09 19:42 [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) paul.moore
2006-10-09 19:42 ` paul.moore
2006-10-09 19:42 ` [PATCH 01/11] secid reconciliation: new SELinux flask definitions paul.moore
2006-10-09 19:42 ` paul.moore
2006-10-09 19:42 ` [PATCH 02/11] secid reconciliation: Add LSM hooks paul.moore
2006-10-09 19:42 ` paul.moore
2006-10-09 19:42 ` [PATCH 03/11] secid reconciliation: Invoke LSM hook for inbound traffic paul.moore
2006-10-09 19:42 ` paul.moore
2006-10-09 19:42 ` [PATCH 04/11] secid reconciliation: Invoke LSM hook for outbound traffic paul.moore
2006-10-09 19:42 ` paul.moore
2006-10-09 19:42 ` [PATCH 05/11] secid reconciliation: Label locally generated IPv6 traffic paul.moore
2006-10-09 19:42 ` paul.moore
2006-10-09 19:42 ` [PATCH 06/11] secid reconciliation: Label locally generated IPv4 traffic paul.moore
2006-10-09 19:42 ` paul.moore
2006-10-09 19:42 ` [PATCH 07/11] secid reconciliation: Enforcement for SELinux paul.moore
2006-10-09 19:42 ` paul.moore
2006-10-09 19:42 ` [PATCH 08/11] secid reconciliation: Use secmark when classifying flow using skb paul.moore
2006-10-09 19:42 ` paul.moore
2006-10-09 19:42 ` [PATCH 09/11] secid reconciliation: Track peersecid at connection establishment paul.moore
2006-10-09 19:42 ` paul.moore
2006-10-09 19:42 ` paul.moore [this message]
2006-10-09 19:42 ` [PATCH 10/11] secid reconciliation: various fixes paul.moore
2006-10-09 19:42 ` [PATCH 11/11] secid reconciliation: support for NetLabel paul.moore
2006-10-09 19:42 ` paul.moore
2006-10-09 20:19 ` [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) James Morris
2006-10-09 20:19 ` James Morris
2006-10-09 20:30 ` Paul Moore
2006-10-09 20:30 ` Paul Moore
2006-10-09 20:36 ` James Morris
2006-10-09 20:36 ` James Morris
2006-10-11 19:20 ` Venkat Yekkirala
2006-10-11 19:20 ` Venkat Yekkirala
2006-10-12 7:26 ` James Morris
2006-10-12 7:26 ` James Morris
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20061009195852.914941000@hp.com \
--to=paul.moore@hp.com \
--cc=jmorris@namei.org \
--cc=netdev@vger.kernel.org \
--cc=sds@tycho.nsa.gov \
--cc=selinux@tycho.nsa.gov \
--cc=vyekkirala@TrustedCS.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.