Re: [RFC PATCH v8 18/18] SELinux: Add network ingress and egress control permission checks
On Monday 17 December 2007 3:05:37 pm Stephen Smalley wrote: On Sun, 2007-12-16 at 11:47 -0500, Paul Moore wrote: We should probably have different permissions for the interface and node cases. Take the example of an admin who is only interested in enforcing interface controls and not node controls. They would most likely write the following policy rule to nullify the node check ... allow unlabeled_t peer_t:peer egress; ... which would end up applying to both the interface and node checks because they use the same permission. I'm thinking we should split the permissions like this: allow netif_t peer_t:peer if_egress; allow netnode_t peer_t: peer node_egress; ... and do something similar for the ingress side. Thoughts? That starts to sound a lot like using netif and node classes instead of the peer class. allow peer_t netif_t:netif egress; allow peer_t netnode_t:node egress; Thinking about this some more ... egress/ingress make sense from an interface point of view but they sound out of place from a node point of view. After all, you are not egressing to a node, to are sending to a node. The same thing applies in the opposite direction, you don't ingress from a node, you receive from a node. With that in mind I'm thinking of going with the following: allow netif_t peer_t:peer { ingress egress }; allow netnode_t peer_t:peer { recv_from send_to }; Thoughts? Should I just forget all this and use the peer label as a subject label? -- paul moore linux security @ hp - To unsubscribe from this list: send the line unsubscribe linux-security-module in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v8 18/18] SELinux: Add network ingress and egress control permission checks
On Tue, 2007-12-18 at 08:59 -0500, Paul Moore wrote: On Monday 17 December 2007 3:05:37 pm Stephen Smalley wrote: On Sun, 2007-12-16 at 11:47 -0500, Paul Moore wrote: We should probably have different permissions for the interface and node cases. Take the example of an admin who is only interested in enforcing interface controls and not node controls. They would most likely write the following policy rule to nullify the node check ... allow unlabeled_t peer_t:peer egress; ... which would end up applying to both the interface and node checks because they use the same permission. I'm thinking we should split the permissions like this: allow netif_t peer_t:peer if_egress; allow netnode_t peer_t: peer node_egress; ... and do something similar for the ingress side. Thoughts? That starts to sound a lot like using netif and node classes instead of the peer class. allow peer_t netif_t:netif egress; allow peer_t netnode_t:node egress; Thinking about this some more ... egress/ingress make sense from an interface point of view but they sound out of place from a node point of view. After all, you are not egressing to a node, to are sending to a node. The same thing applies in the opposite direction, you don't ingress from a node, you receive from a node. With that in mind I'm thinking of going with the following: allow netif_t peer_t:peer { ingress egress }; allow netnode_t peer_t:peer { recv_from send_to }; nit: recvfrom and sendto don't really require an underscore to be readable, and we've already set a precedent for them in the socket and association classes. Thoughts? Should I just forget all this and use the peer label as a subject label? I'm not certain what we gain by using the peer as the object and class in these checks, and it seems to make their meaning less clear. It should be noted that we already use process labels as both subjects (when the actor) and objects (when the target/recipient of an action, as in signal delivery or IPC), and that process labels flow to sockets they create and socket labels flow to packets they send, and socket labels likewise serve dual roles as subjects (Can this socket send/recv this packet?) and objects (Can this process send/recv on this socket?). In the case of locally generated or destined traffic, we always have a local socket that we can use as the subject of the check, which I think is why we end up not using packet/peer as the subject generally - we essentially have two subjects to choose from, and we favor the local one. But in the forwarded case, the packet/peer is the only subject/actor in view really. OTOH, I'm not sure your original concern about unlabeled_t is well-founded now that I think about it; the netif and node type space is disjoint and they default to discrete initial SIDs and types (netif_t, node_t), not to unlabeled_t, right? So the types themselves encode the class there. -- Stephen Smalley National Security Agency - To unsubscribe from this list: send the line unsubscribe linux-security-module in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v8 18/18] SELinux: Add network ingress and egress control permission checks
On Tuesday 18 December 2007 10:14:41 am Stephen Smalley wrote: On Tue, 2007-12-18 at 08:59 -0500, Paul Moore wrote: Thoughts? Should I just forget all this and use the peer label as a subject label? I'm not certain what we gain by using the peer as the object and class in these checks, and it seems to make their meaning less clear. It should be noted that we already use process labels as both subjects (when the actor) and objects (when the target/recipient of an action, as in signal delivery or IPC), and that process labels flow to sockets they create and socket labels flow to packets they send, and socket labels likewise serve dual roles as subjects (Can this socket send/recv this packet?) and objects (Can this process send/recv on this socket?). In the case of locally generated or destined traffic, we always have a local socket that we can use as the subject of the check, which I think is why we end up not using packet/peer as the subject generally - we essentially have two subjects to choose from, and we favor the local one. But in the forwarded case, the packet/peer is the only subject/actor in view really. Yep, I think you are right and I'm just slow to realize it. As pointed out earlier in the discussion, the awkwardness of using the packet's peer label as an object should have clued me into the fact that this was a bad idea. So, my last question is what permissions do we want to use for the netif/node object classes? allow peer_t netif_t:netif { egress ingress }; allow peer_t netnode_t:node { sendto/send recvfrom/recv }; What I'd like to avoid if possible is the protocol specific permissions we currently have for the netif and node object classes; it requires extra work in the kernel, it doesn't work at all for the forwarding case, and I have my doubts about the usefulness of the distinction. I think the ingress/egress permissions still make sense when applied to the netif object class but it's a bit of a stretch when applied to the node object class. I personally like the sendto/recvfrom permissions but if that is too much of a violation from existing precedence I imagine send/recv would work. Thoughts? -- paul moore linux security @ hp - To unsubscribe from this list: send the line unsubscribe linux-security-module in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v8 18/18] SELinux: Add network ingress and egress control permission checks
On Monday 17 December 2007 3:05:37 pm Stephen Smalley wrote: On Sun, 2007-12-16 at 11:47 -0500, Paul Moore wrote: On Friday 14 December 2007 4:51:29 pm Paul Moore wrote: This patch implements packet ingress/egress controls for SELinux which allow SELinux security policy to control the flow of all IPv4 and IPv6 packets into and out of the system. Currently SELinux does not have proper control over forwarded packets and this patch corrects this problem. Special thanks to Venkat Yekkirala [EMAIL PROTECTED] whose earlier work on this topic eventually led to this patch. I've been thinking about this over the weekend and realized a few things ... {snip} +static int selinux_inet_sys_snd_skb(struct sk_buff *skb, int family) +{ + int err = 0; + + if (!selinux_policycap_netpeer) + return 0; + + if (netlbl_enabled() || selinux_xfrm_enabled()) { + u32 if_sid; + u32 node_sid; + u32 peer_sid; + char *addrp; + struct avc_audit_data ad; + + AVC_AUDIT_DATA_INIT(ad, NET); + ad.u.net.netif = skb-iif; + ad.u.net.family = family; + err = selinux_parse_skb(skb, ad, addrp, 0, NULL); + if (err) + return err; + + err = selinux_skb_peerlbl_sid(skb, family, peer_sid); + if (err) + return err; I realized I made a mistake here: we should check to see if the skb has a socket associated with it and if it does get the peer_sid from there instead. If there is no socket to be found then do what we are already going above. In what case do you expect the two SIDs to diverge? The case of CIPSO immediately springs to mind. If you query the packet directly you will get a SID similar to what you see on incoming packets: the netlabel_peer_t type plus the CIPSO MLS sensitivity label. If you query the socket which originated the packet you'll get the original, native SELinux label/SID. In my mind using the socket's label is a shortcut to get the full/true/original/etc. label quickly. There is most likely also a performance advantage in pulling the SID from the socket. What if we later provide an API to allow a sender to send a datagram with a particular label rather than always requiring them to be the same as the sending socket? Then we can transition from using a mix between socket and packet labels to just packet labels. I don't see any _significant_ barriers to that approach in the ingress/egress controls as proposed. If you do, let me know. + err = sel_netif_sid(skb-iif, if_sid); + if (err) + return err; + err = avc_has_perm(if_sid, peer_sid, +SECCLASS_PEER, PEER__EGRESS, ad); + if (err) + return err; + + err = sel_netnode_sid(addrp, family, node_sid); + if (err) + return err; + err = avc_has_perm(node_sid, peer_sid, +SECCLASS_PEER, PEER__EGRESS, ad); We should probably have different permissions for the interface and node cases. Take the example of an admin who is only interested in enforcing interface controls and not node controls. They would most likely write the following policy rule to nullify the node check ... allow unlabeled_t peer_t:peer egress; ... which would end up applying to both the interface and node checks because they use the same permission. I'm thinking we should split the permissions like this: allow netif_t peer_t:peer if_egress; allow netnode_t peer_t: peer node_egress; ... and do something similar for the ingress side. Thoughts? That starts to sound a lot like using netif and node classes instead of the peer class. allow peer_t netif_t:netif egress; allow peer_t netnode_t:node egress; I see you noticed that too :) I've been mulling this over and over in my head for some time and I'm not sure which is better. I'm leaning towards sticking with the peer object class just because it reinforces the decision to treat the packet as an object. Good or bad, that is how SELinux currently treats packets and I fear that using the packet's peer label as the subject here could get confusing. -- paul moore linux security @ hp - To unsubscribe from this list: send the line unsubscribe linux-security-module in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v8 18/18] SELinux: Add network ingress and egress control permission checks
On Friday 14 December 2007 4:51:29 pm Paul Moore wrote: This patch implements packet ingress/egress controls for SELinux which allow SELinux security policy to control the flow of all IPv4 and IPv6 packets into and out of the system. Currently SELinux does not have proper control over forwarded packets and this patch corrects this problem. Special thanks to Venkat Yekkirala [EMAIL PROTECTED] whose earlier work on this topic eventually led to this patch. I've been thinking about this over the weekend and realized a few things ... {snip} +static int selinux_inet_sys_snd_skb(struct sk_buff *skb, int family) +{ + int err = 0; + + if (!selinux_policycap_netpeer) + return 0; + + if (netlbl_enabled() || selinux_xfrm_enabled()) { + u32 if_sid; + u32 node_sid; + u32 peer_sid; + char *addrp; + struct avc_audit_data ad; + + AVC_AUDIT_DATA_INIT(ad, NET); + ad.u.net.netif = skb-iif; + ad.u.net.family = family; + err = selinux_parse_skb(skb, ad, addrp, 0, NULL); + if (err) + return err; + + err = selinux_skb_peerlbl_sid(skb, family, peer_sid); + if (err) + return err; I realized I made a mistake here: we should check to see if the skb has a socket associated with it and if it does get the peer_sid from there instead. If there is no socket to be found then do what we are already going above. + err = sel_netif_sid(skb-iif, if_sid); + if (err) + return err; + err = avc_has_perm(if_sid, peer_sid, +SECCLASS_PEER, PEER__EGRESS, ad); + if (err) + return err; + + err = sel_netnode_sid(addrp, family, node_sid); + if (err) + return err; + err = avc_has_perm(node_sid, peer_sid, +SECCLASS_PEER, PEER__EGRESS, ad); We should probably have different permissions for the interface and node cases. Take the example of an admin who is only interested in enforcing interface controls and not node controls. They would most likely write the following policy rule to nullify the node check ... allow unlabeled_t peer_t:peer egress; ... which would end up applying to both the interface and node checks because they use the same permission. I'm thinking we should split the permissions like this: allow netif_t peer_t:peer if_egress; allow netnode_t peer_t: peer node_egress; ... and do something similar for the ingress side. Thoughts? + } + + return err; +} -- paul moore linux security @ hp - To unsubscribe from this list: send the line unsubscribe linux-security-module in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html