Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security

Pull SELinux fixes from James Morris.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
selinux: process labeled IPsec TCP SYN-ACK packets properly in selinux_ip_postroute()
selinux: look for IPsec labels on both inbound and outbound packets
selinux: handle TCP SYN-ACK packets correctly in selinux_ip_postroute()
selinux: handle TCP SYN-ACK packets correctly in selinux_ip_output()
selinux: fix possible memory leak

Changed files
+165 -42
security
selinux
+112 -25
security/selinux/hooks.c
··· 53 53 #include <net/ip.h> /* for local_port_range[] */ 54 54 #include <net/sock.h> 55 55 #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ 56 + #include <net/inet_connection_sock.h> 56 57 #include <net/net_namespace.h> 57 58 #include <net/netlabel.h> 58 59 #include <linux/uaccess.h> ··· 3825 3824 u32 nlbl_sid; 3826 3825 u32 nlbl_type; 3827 3826 3828 - err = selinux_skb_xfrm_sid(skb, &xfrm_sid); 3827 + err = selinux_xfrm_skb_sid(skb, &xfrm_sid); 3829 3828 if (unlikely(err)) 3830 3829 return -EACCES; 3831 3830 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); ··· 3841 3840 } 3842 3841 3843 3842 return 0; 3843 + } 3844 + 3845 + /** 3846 + * selinux_conn_sid - Determine the child socket label for a connection 3847 + * @sk_sid: the parent socket's SID 3848 + * @skb_sid: the packet's SID 3849 + * @conn_sid: the resulting connection SID 3850 + * 3851 + * If @skb_sid is valid then the user:role:type information from @sk_sid is 3852 + * combined with the MLS information from @skb_sid in order to create 3853 + * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy 3854 + * of @sk_sid. Returns zero on success, negative values on failure. 3855 + * 3856 + */ 3857 + static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid) 3858 + { 3859 + int err = 0; 3860 + 3861 + if (skb_sid != SECSID_NULL) 3862 + err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid); 3863 + else 3864 + *conn_sid = sk_sid; 3865 + 3866 + return err; 3844 3867 } 3845 3868 3846 3869 /* socket security operations */ ··· 4473 4448 struct sk_security_struct *sksec = sk->sk_security; 4474 4449 int err; 4475 4450 u16 family = sk->sk_family; 4476 - u32 newsid; 4451 + u32 connsid; 4477 4452 u32 peersid; 4478 4453 4479 4454 /* handle mapped IPv4 packets arriving via IPv6 sockets */ ··· 4483 4458 err = selinux_skb_peerlbl_sid(skb, family, &peersid); 4484 4459 if (err) 4485 4460 return err; 4486 - if (peersid == SECSID_NULL) { 4487 - req->secid = sksec->sid; 4488 - req->peer_secid = SECSID_NULL; 4489 - } else { 4490 - err = security_sid_mls_copy(sksec->sid, peersid, &newsid); 4491 - if (err) 4492 - return err; 4493 - req->secid = newsid; 4494 - req->peer_secid = peersid; 4495 - } 4461 + err = selinux_conn_sid(sksec->sid, peersid, &connsid); 4462 + if (err) 4463 + return err; 4464 + req->secid = connsid; 4465 + req->peer_secid = peersid; 4496 4466 4497 4467 return selinux_netlbl_inet_conn_request(req, family); 4498 4468 } ··· 4747 4727 static unsigned int selinux_ip_output(struct sk_buff *skb, 4748 4728 u16 family) 4749 4729 { 4730 + struct sock *sk; 4750 4731 u32 sid; 4751 4732 4752 4733 if (!netlbl_enabled()) ··· 4756 4735 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path 4757 4736 * because we want to make sure we apply the necessary labeling 4758 4737 * before IPsec is applied so we can leverage AH protection */ 4759 - if (skb->sk) { 4760 - struct sk_security_struct *sksec = skb->sk->sk_security; 4738 + sk = skb->sk; 4739 + if (sk) { 4740 + struct sk_security_struct *sksec; 4741 + 4742 + if (sk->sk_state == TCP_LISTEN) 4743 + /* if the socket is the listening state then this 4744 + * packet is a SYN-ACK packet which means it needs to 4745 + * be labeled based on the connection/request_sock and 4746 + * not the parent socket. unfortunately, we can't 4747 + * lookup the request_sock yet as it isn't queued on 4748 + * the parent socket until after the SYN-ACK is sent. 4749 + * the "solution" is to simply pass the packet as-is 4750 + * as any IP option based labeling should be copied 4751 + * from the initial connection request (in the IP 4752 + * layer). it is far from ideal, but until we get a 4753 + * security label in the packet itself this is the 4754 + * best we can do. */ 4755 + return NF_ACCEPT; 4756 + 4757 + /* standard practice, label using the parent socket */ 4758 + sksec = sk->sk_security; 4761 4759 sid = sksec->sid; 4762 4760 } else 4763 4761 sid = SECINITSID_KERNEL; ··· 4846 4806 * as fast and as clean as possible. */ 4847 4807 if (!selinux_policycap_netpeer) 4848 4808 return selinux_ip_postroute_compat(skb, ifindex, family); 4809 + 4810 + secmark_active = selinux_secmark_enabled(); 4811 + peerlbl_active = selinux_peerlbl_enabled(); 4812 + if (!secmark_active && !peerlbl_active) 4813 + return NF_ACCEPT; 4814 + 4815 + sk = skb->sk; 4816 + 4849 4817 #ifdef CONFIG_XFRM 4850 4818 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec 4851 4819 * packet transformation so allow the packet to pass without any checks 4852 4820 * since we'll have another chance to perform access control checks 4853 4821 * when the packet is on it's final way out. 4854 4822 * NOTE: there appear to be some IPv6 multicast cases where skb->dst 4855 - * is NULL, in this case go ahead and apply access control. */ 4856 - if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL) 4823 + * is NULL, in this case go ahead and apply access control. 4824 + * NOTE: if this is a local socket (skb->sk != NULL) that is in the 4825 + * TCP listening state we cannot wait until the XFRM processing 4826 + * is done as we will miss out on the SA label if we do; 4827 + * unfortunately, this means more work, but it is only once per 4828 + * connection. */ 4829 + if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL && 4830 + !(sk != NULL && sk->sk_state == TCP_LISTEN)) 4857 4831 return NF_ACCEPT; 4858 4832 #endif 4859 - secmark_active = selinux_secmark_enabled(); 4860 - peerlbl_active = selinux_peerlbl_enabled(); 4861 - if (!secmark_active && !peerlbl_active) 4862 - return NF_ACCEPT; 4863 4833 4864 - /* if the packet is being forwarded then get the peer label from the 4865 - * packet itself; otherwise check to see if it is from a local 4866 - * application or the kernel, if from an application get the peer label 4867 - * from the sending socket, otherwise use the kernel's sid */ 4868 - sk = skb->sk; 4869 4834 if (sk == NULL) { 4835 + /* Without an associated socket the packet is either coming 4836 + * from the kernel or it is being forwarded; check the packet 4837 + * to determine which and if the packet is being forwarded 4838 + * query the packet directly to determine the security label. */ 4870 4839 if (skb->skb_iif) { 4871 4840 secmark_perm = PACKET__FORWARD_OUT; 4872 4841 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) ··· 4884 4835 secmark_perm = PACKET__SEND; 4885 4836 peer_sid = SECINITSID_KERNEL; 4886 4837 } 4838 + } else if (sk->sk_state == TCP_LISTEN) { 4839 + /* Locally generated packet but the associated socket is in the 4840 + * listening state which means this is a SYN-ACK packet. In 4841 + * this particular case the correct security label is assigned 4842 + * to the connection/request_sock but unfortunately we can't 4843 + * query the request_sock as it isn't queued on the parent 4844 + * socket until after the SYN-ACK packet is sent; the only 4845 + * viable choice is to regenerate the label like we do in 4846 + * selinux_inet_conn_request(). See also selinux_ip_output() 4847 + * for similar problems. */ 4848 + u32 skb_sid; 4849 + struct sk_security_struct *sksec = sk->sk_security; 4850 + if (selinux_skb_peerlbl_sid(skb, family, &skb_sid)) 4851 + return NF_DROP; 4852 + /* At this point, if the returned skb peerlbl is SECSID_NULL 4853 + * and the packet has been through at least one XFRM 4854 + * transformation then we must be dealing with the "final" 4855 + * form of labeled IPsec packet; since we've already applied 4856 + * all of our access controls on this packet we can safely 4857 + * pass the packet. */ 4858 + if (skb_sid == SECSID_NULL) { 4859 + switch (family) { 4860 + case PF_INET: 4861 + if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) 4862 + return NF_ACCEPT; 4863 + break; 4864 + case PF_INET6: 4865 + if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) 4866 + return NF_ACCEPT; 4867 + default: 4868 + return NF_DROP_ERR(-ECONNREFUSED); 4869 + } 4870 + } 4871 + if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid)) 4872 + return NF_DROP; 4873 + secmark_perm = PACKET__SEND; 4887 4874 } else { 4875 + /* Locally generated packet, fetch the security label from the 4876 + * associated socket. */ 4888 4877 struct sk_security_struct *sksec = sk->sk_security; 4889 4878 peer_sid = sksec->sid; 4890 4879 secmark_perm = PACKET__SEND;
+5 -3
security/selinux/include/xfrm.h
··· 39 39 int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb, 40 40 struct common_audit_data *ad, u8 proto); 41 41 int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); 42 + int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid); 42 43 43 44 static inline void selinux_xfrm_notify_policyload(void) 44 45 { ··· 80 79 static inline void selinux_xfrm_notify_policyload(void) 81 80 { 82 81 } 83 - #endif 84 82 85 - static inline int selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid) 83 + static inline int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid) 86 84 { 87 - return selinux_xfrm_decode_session(skb, sid, 0); 85 + *sid = SECSID_NULL; 86 + return 0; 88 87 } 88 + #endif 89 89 90 90 #endif /* _SELINUX_XFRM_H_ */
+48 -14
security/selinux/xfrm.c
··· 209 209 NULL) ? 0 : 1); 210 210 } 211 211 212 - /* 213 - * LSM hook implementation that checks and/or returns the xfrm sid for the 214 - * incoming packet. 215 - */ 216 - int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) 212 + static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb) 213 + { 214 + struct dst_entry *dst = skb_dst(skb); 215 + struct xfrm_state *x; 216 + 217 + if (dst == NULL) 218 + return SECSID_NULL; 219 + x = dst->xfrm; 220 + if (x == NULL || !selinux_authorizable_xfrm(x)) 221 + return SECSID_NULL; 222 + 223 + return x->security->ctx_sid; 224 + } 225 + 226 + static int selinux_xfrm_skb_sid_ingress(struct sk_buff *skb, 227 + u32 *sid, int ckall) 217 228 { 218 229 u32 sid_session = SECSID_NULL; 219 - struct sec_path *sp; 230 + struct sec_path *sp = skb->sp; 220 231 221 - if (skb == NULL) 222 - goto out; 223 - 224 - sp = skb->sp; 225 232 if (sp) { 226 233 int i; 227 234 ··· 252 245 out: 253 246 *sid = sid_session; 254 247 return 0; 248 + } 249 + 250 + /* 251 + * LSM hook implementation that checks and/or returns the xfrm sid for the 252 + * incoming packet. 253 + */ 254 + int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) 255 + { 256 + if (skb == NULL) { 257 + *sid = SECSID_NULL; 258 + return 0; 259 + } 260 + return selinux_xfrm_skb_sid_ingress(skb, sid, ckall); 261 + } 262 + 263 + int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid) 264 + { 265 + int rc; 266 + 267 + rc = selinux_xfrm_skb_sid_ingress(skb, sid, 0); 268 + if (rc == 0 && *sid == SECSID_NULL) 269 + *sid = selinux_xfrm_skb_sid_egress(skb); 270 + 271 + return rc; 255 272 } 256 273 257 274 /* ··· 358 327 return rc; 359 328 360 329 ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC); 361 - if (!ctx) 362 - return -ENOMEM; 330 + if (!ctx) { 331 + rc = -ENOMEM; 332 + goto out; 333 + } 363 334 364 335 ctx->ctx_doi = XFRM_SC_DOI_LSM; 365 336 ctx->ctx_alg = XFRM_SC_ALG_SELINUX; 366 337 ctx->ctx_sid = secid; 367 338 ctx->ctx_len = str_len; 368 339 memcpy(ctx->ctx_str, ctx_str, str_len); 369 - kfree(ctx_str); 370 340 371 341 x->security = ctx; 372 342 atomic_inc(&selinux_xfrm_refcount); 373 - return 0; 343 + out: 344 + kfree(ctx_str); 345 + return rc; 374 346 } 375 347 376 348 /*