diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-12-15 14:28:02 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-12-15 14:28:02 -0500 |
| commit | b5745c59627854afb3cd3f3860ee6f4571e2b633 (patch) | |
| tree | df9f3bb37b4cf0f3c52c970927bed4a843234e29 /security | |
| parent | 29b1deb2a48a9dd02b93597aa4c055a24c0e989f (diff) | |
| parent | d93aca6050b10cd7d8b491637c3b5344c5680cac (diff) | |
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
Diffstat (limited to 'security')
| -rw-r--r-- | security/selinux/hooks.c | 137 | ||||
| -rw-r--r-- | security/selinux/include/xfrm.h | 8 | ||||
| -rw-r--r-- | security/selinux/xfrm.c | 62 |
3 files changed, 165 insertions, 42 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 98b1caa1c1d3..419491d8e7d2 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #include <net/ip.h> /* for local_port_range[] */ | 53 | #include <net/ip.h> /* for local_port_range[] */ |
| 54 | #include <net/sock.h> | 54 | #include <net/sock.h> |
| 55 | #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ | 55 | #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ |
| 56 | #include <net/inet_connection_sock.h> | ||
| 56 | #include <net/net_namespace.h> | 57 | #include <net/net_namespace.h> |
| 57 | #include <net/netlabel.h> | 58 | #include <net/netlabel.h> |
| 58 | #include <linux/uaccess.h> | 59 | #include <linux/uaccess.h> |
| @@ -3824,7 +3825,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) | |||
| 3824 | u32 nlbl_sid; | 3825 | u32 nlbl_sid; |
| 3825 | u32 nlbl_type; | 3826 | u32 nlbl_type; |
| 3826 | 3827 | ||
| 3827 | err = selinux_skb_xfrm_sid(skb, &xfrm_sid); | 3828 | err = selinux_xfrm_skb_sid(skb, &xfrm_sid); |
| 3828 | if (unlikely(err)) | 3829 | if (unlikely(err)) |
| 3829 | return -EACCES; | 3830 | return -EACCES; |
| 3830 | err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); | 3831 | err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); |
| @@ -3842,6 +3843,30 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) | |||
| 3842 | return 0; | 3843 | return 0; |
| 3843 | } | 3844 | } |
| 3844 | 3845 | ||
| 3846 | /** | ||
| 3847 | * selinux_conn_sid - Determine the child socket label for a connection | ||
| 3848 | * @sk_sid: the parent socket's SID | ||
| 3849 | * @skb_sid: the packet's SID | ||
| 3850 | * @conn_sid: the resulting connection SID | ||
| 3851 | * | ||
| 3852 | * If @skb_sid is valid then the user:role:type information from @sk_sid is | ||
| 3853 | * combined with the MLS information from @skb_sid in order to create | ||
| 3854 | * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy | ||
| 3855 | * of @sk_sid. Returns zero on success, negative values on failure. | ||
| 3856 | * | ||
| 3857 | */ | ||
| 3858 | static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid) | ||
| 3859 | { | ||
| 3860 | int err = 0; | ||
| 3861 | |||
| 3862 | if (skb_sid != SECSID_NULL) | ||
| 3863 | err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid); | ||
| 3864 | else | ||
| 3865 | *conn_sid = sk_sid; | ||
| 3866 | |||
| 3867 | return err; | ||
| 3868 | } | ||
| 3869 | |||
| 3845 | /* socket security operations */ | 3870 | /* socket security operations */ |
| 3846 | 3871 | ||
| 3847 | static int socket_sockcreate_sid(const struct task_security_struct *tsec, | 3872 | static int socket_sockcreate_sid(const struct task_security_struct *tsec, |
| @@ -4448,7 +4473,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
| 4448 | struct sk_security_struct *sksec = sk->sk_security; | 4473 | struct sk_security_struct *sksec = sk->sk_security; |
| 4449 | int err; | 4474 | int err; |
| 4450 | u16 family = sk->sk_family; | 4475 | u16 family = sk->sk_family; |
| 4451 | u32 newsid; | 4476 | u32 connsid; |
| 4452 | u32 peersid; | 4477 | u32 peersid; |
| 4453 | 4478 | ||
| 4454 | /* handle mapped IPv4 packets arriving via IPv6 sockets */ | 4479 | /* handle mapped IPv4 packets arriving via IPv6 sockets */ |
| @@ -4458,16 +4483,11 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
| 4458 | err = selinux_skb_peerlbl_sid(skb, family, &peersid); | 4483 | err = selinux_skb_peerlbl_sid(skb, family, &peersid); |
| 4459 | if (err) | 4484 | if (err) |
| 4460 | return err; | 4485 | return err; |
| 4461 | if (peersid == SECSID_NULL) { | 4486 | err = selinux_conn_sid(sksec->sid, peersid, &connsid); |
| 4462 | req->secid = sksec->sid; | 4487 | if (err) |
| 4463 | req->peer_secid = SECSID_NULL; | 4488 | return err; |
| 4464 | } else { | 4489 | req->secid = connsid; |
| 4465 | err = security_sid_mls_copy(sksec->sid, peersid, &newsid); | 4490 | req->peer_secid = peersid; |
| 4466 | if (err) | ||
| 4467 | return err; | ||
| 4468 | req->secid = newsid; | ||
| 4469 | req->peer_secid = peersid; | ||
| 4470 | } | ||
| 4471 | 4491 | ||
| 4472 | return selinux_netlbl_inet_conn_request(req, family); | 4492 | return selinux_netlbl_inet_conn_request(req, family); |
| 4473 | } | 4493 | } |
| @@ -4727,6 +4747,7 @@ static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops, | |||
| 4727 | static unsigned int selinux_ip_output(struct sk_buff *skb, | 4747 | static unsigned int selinux_ip_output(struct sk_buff *skb, |
| 4728 | u16 family) | 4748 | u16 family) |
| 4729 | { | 4749 | { |
| 4750 | struct sock *sk; | ||
| 4730 | u32 sid; | 4751 | u32 sid; |
| 4731 | 4752 | ||
| 4732 | if (!netlbl_enabled()) | 4753 | if (!netlbl_enabled()) |
| @@ -4735,8 +4756,27 @@ static unsigned int selinux_ip_output(struct sk_buff *skb, | |||
| 4735 | /* we do this in the LOCAL_OUT path and not the POST_ROUTING path | 4756 | /* we do this in the LOCAL_OUT path and not the POST_ROUTING path |
| 4736 | * because we want to make sure we apply the necessary labeling | 4757 | * because we want to make sure we apply the necessary labeling |
| 4737 | * before IPsec is applied so we can leverage AH protection */ | 4758 | * before IPsec is applied so we can leverage AH protection */ |
| 4738 | if (skb->sk) { | 4759 | sk = skb->sk; |
| 4739 | struct sk_security_struct *sksec = skb->sk->sk_security; | 4760 | if (sk) { |
| 4761 | struct sk_security_struct *sksec; | ||
| 4762 | |||
| 4763 | if (sk->sk_state == TCP_LISTEN) | ||
| 4764 | /* if the socket is the listening state then this | ||
| 4765 | * packet is a SYN-ACK packet which means it needs to | ||
| 4766 | * be labeled based on the connection/request_sock and | ||
| 4767 | * not the parent socket. unfortunately, we can't | ||
| 4768 | * lookup the request_sock yet as it isn't queued on | ||
| 4769 | * the parent socket until after the SYN-ACK is sent. | ||
| 4770 | * the "solution" is to simply pass the packet as-is | ||
| 4771 | * as any IP option based labeling should be copied | ||
| 4772 | * from the initial connection request (in the IP | ||
| 4773 | * layer). it is far from ideal, but until we get a | ||
| 4774 | * security label in the packet itself this is the | ||
| 4775 | * best we can do. */ | ||
| 4776 | return NF_ACCEPT; | ||
| 4777 | |||
| 4778 | /* standard practice, label using the parent socket */ | ||
| 4779 | sksec = sk->sk_security; | ||
| 4740 | sid = sksec->sid; | 4780 | sid = sksec->sid; |
| 4741 | } else | 4781 | } else |
| 4742 | sid = SECINITSID_KERNEL; | 4782 | sid = SECINITSID_KERNEL; |
| @@ -4806,27 +4846,36 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
| 4806 | * as fast and as clean as possible. */ | 4846 | * as fast and as clean as possible. */ |
| 4807 | if (!selinux_policycap_netpeer) | 4847 | if (!selinux_policycap_netpeer) |
| 4808 | return selinux_ip_postroute_compat(skb, ifindex, family); | 4848 | return selinux_ip_postroute_compat(skb, ifindex, family); |
| 4849 | |||
| 4850 | secmark_active = selinux_secmark_enabled(); | ||
| 4851 | peerlbl_active = selinux_peerlbl_enabled(); | ||
| 4852 | if (!secmark_active && !peerlbl_active) | ||
| 4853 | return NF_ACCEPT; | ||
| 4854 | |||
| 4855 | sk = skb->sk; | ||
| 4856 | |||
| 4809 | #ifdef CONFIG_XFRM | 4857 | #ifdef CONFIG_XFRM |
| 4810 | /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec | 4858 | /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec |
| 4811 | * packet transformation so allow the packet to pass without any checks | 4859 | * packet transformation so allow the packet to pass without any checks |
| 4812 | * since we'll have another chance to perform access control checks | 4860 | * since we'll have another chance to perform access control checks |
| 4813 | * when the packet is on it's final way out. | 4861 | * when the packet is on it's final way out. |
| 4814 | * NOTE: there appear to be some IPv6 multicast cases where skb->dst | 4862 | * NOTE: there appear to be some IPv6 multicast cases where skb->dst |
| 4815 | * is NULL, in this case go ahead and apply access control. */ | 4863 | * is NULL, in this case go ahead and apply access control. |
| 4816 | if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL) | 4864 | * NOTE: if this is a local socket (skb->sk != NULL) that is in the |
| 4865 | * TCP listening state we cannot wait until the XFRM processing | ||
| 4866 | * is done as we will miss out on the SA label if we do; | ||
| 4867 | * unfortunately, this means more work, but it is only once per | ||
| 4868 | * connection. */ | ||
| 4869 | if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL && | ||
| 4870 | !(sk != NULL && sk->sk_state == TCP_LISTEN)) | ||
| 4817 | return NF_ACCEPT; | 4871 | return NF_ACCEPT; |
| 4818 | #endif | 4872 | #endif |
| 4819 | secmark_active = selinux_secmark_enabled(); | ||
| 4820 | peerlbl_active = selinux_peerlbl_enabled(); | ||
| 4821 | if (!secmark_active && !peerlbl_active) | ||
| 4822 | return NF_ACCEPT; | ||
| 4823 | 4873 | ||
| 4824 | /* if the packet is being forwarded then get the peer label from the | ||
| 4825 | * packet itself; otherwise check to see if it is from a local | ||
| 4826 | * application or the kernel, if from an application get the peer label | ||
| 4827 | * from the sending socket, otherwise use the kernel's sid */ | ||
| 4828 | sk = skb->sk; | ||
| 4829 | if (sk == NULL) { | 4874 | if (sk == NULL) { |
| 4875 | /* Without an associated socket the packet is either coming | ||
| 4876 | * from the kernel or it is being forwarded; check the packet | ||
| 4877 | * to determine which and if the packet is being forwarded | ||
| 4878 | * query the packet directly to determine the security label. */ | ||
| 4830 | if (skb->skb_iif) { | 4879 | if (skb->skb_iif) { |
| 4831 | secmark_perm = PACKET__FORWARD_OUT; | 4880 | secmark_perm = PACKET__FORWARD_OUT; |
| 4832 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) | 4881 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) |
| @@ -4835,7 +4884,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
| 4835 | secmark_perm = PACKET__SEND; | 4884 | secmark_perm = PACKET__SEND; |
| 4836 | peer_sid = SECINITSID_KERNEL; | 4885 | peer_sid = SECINITSID_KERNEL; |
| 4837 | } | 4886 | } |
| 4887 | } else if (sk->sk_state == TCP_LISTEN) { | ||
| 4888 | /* Locally generated packet but the associated socket is in the | ||
| 4889 | * listening state which means this is a SYN-ACK packet. In | ||
| 4890 | * this particular case the correct security label is assigned | ||
| 4891 | * to the connection/request_sock but unfortunately we can't | ||
| 4892 | * query the request_sock as it isn't queued on the parent | ||
| 4893 | * socket until after the SYN-ACK packet is sent; the only | ||
| 4894 | * viable choice is to regenerate the label like we do in | ||
| 4895 | * selinux_inet_conn_request(). See also selinux_ip_output() | ||
| 4896 | * for similar problems. */ | ||
| 4897 | u32 skb_sid; | ||
| 4898 | struct sk_security_struct *sksec = sk->sk_security; | ||
| 4899 | if (selinux_skb_peerlbl_sid(skb, family, &skb_sid)) | ||
| 4900 | return NF_DROP; | ||
| 4901 | /* At this point, if the returned skb peerlbl is SECSID_NULL | ||
| 4902 | * and the packet has been through at least one XFRM | ||
| 4903 | * transformation then we must be dealing with the "final" | ||
| 4904 | * form of labeled IPsec packet; since we've already applied | ||
| 4905 | * all of our access controls on this packet we can safely | ||
| 4906 | * pass the packet. */ | ||
| 4907 | if (skb_sid == SECSID_NULL) { | ||
| 4908 | switch (family) { | ||
| 4909 | case PF_INET: | ||
| 4910 | if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) | ||
| 4911 | return NF_ACCEPT; | ||
| 4912 | break; | ||
| 4913 | case PF_INET6: | ||
| 4914 | if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) | ||
| 4915 | return NF_ACCEPT; | ||
| 4916 | default: | ||
| 4917 | return NF_DROP_ERR(-ECONNREFUSED); | ||
| 4918 | } | ||
| 4919 | } | ||
| 4920 | if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid)) | ||
| 4921 | return NF_DROP; | ||
| 4922 | secmark_perm = PACKET__SEND; | ||
| 4838 | } else { | 4923 | } else { |
| 4924 | /* Locally generated packet, fetch the security label from the | ||
| 4925 | * associated socket. */ | ||
| 4839 | struct sk_security_struct *sksec = sk->sk_security; | 4926 | struct sk_security_struct *sksec = sk->sk_security; |
| 4840 | peer_sid = sksec->sid; | 4927 | peer_sid = sksec->sid; |
| 4841 | secmark_perm = PACKET__SEND; | 4928 | secmark_perm = PACKET__SEND; |
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 0dec76c64cf5..48c3cc94c168 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h | |||
| @@ -39,6 +39,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb, | |||
| 39 | int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb, | 39 | int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb, |
| 40 | struct common_audit_data *ad, u8 proto); | 40 | struct common_audit_data *ad, u8 proto); |
| 41 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); | 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 | static inline void selinux_xfrm_notify_policyload(void) | 44 | static inline void selinux_xfrm_notify_policyload(void) |
| 44 | { | 45 | { |
| @@ -79,11 +80,12 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, | |||
| 79 | static inline void selinux_xfrm_notify_policyload(void) | 80 | static inline void selinux_xfrm_notify_policyload(void) |
| 80 | { | 81 | { |
| 81 | } | 82 | } |
| 82 | #endif | ||
| 83 | 83 | ||
| 84 | static inline int selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid) | 84 | static inline int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid) |
| 85 | { | 85 | { |
| 86 | return selinux_xfrm_decode_session(skb, sid, 0); | 86 | *sid = SECSID_NULL; |
| 87 | return 0; | ||
| 87 | } | 88 | } |
| 89 | #endif | ||
| 88 | 90 | ||
| 89 | #endif /* _SELINUX_XFRM_H_ */ | 91 | #endif /* _SELINUX_XFRM_H_ */ |
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index a91d205ec0c6..0462cb3ff0a7 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
| @@ -209,19 +209,26 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, | |||
| 209 | NULL) ? 0 : 1); | 209 | NULL) ? 0 : 1); |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | /* | 212 | static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb) |
| 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) | ||
| 217 | { | 213 | { |
| 218 | u32 sid_session = SECSID_NULL; | 214 | struct dst_entry *dst = skb_dst(skb); |
| 219 | struct sec_path *sp; | 215 | struct xfrm_state *x; |
| 220 | 216 | ||
| 221 | if (skb == NULL) | 217 | if (dst == NULL) |
| 222 | goto out; | 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) | ||
| 228 | { | ||
| 229 | u32 sid_session = SECSID_NULL; | ||
| 230 | struct sec_path *sp = skb->sp; | ||
| 223 | 231 | ||
| 224 | sp = skb->sp; | ||
| 225 | if (sp) { | 232 | if (sp) { |
| 226 | int i; | 233 | int i; |
| 227 | 234 | ||
| @@ -248,6 +255,30 @@ out: | |||
| 248 | } | 255 | } |
| 249 | 256 | ||
| 250 | /* | 257 | /* |
| 258 | * LSM hook implementation that checks and/or returns the xfrm sid for the | ||
| 259 | * incoming packet. | ||
| 260 | */ | ||
| 261 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) | ||
| 262 | { | ||
| 263 | if (skb == NULL) { | ||
| 264 | *sid = SECSID_NULL; | ||
| 265 | return 0; | ||
| 266 | } | ||
| 267 | return selinux_xfrm_skb_sid_ingress(skb, sid, ckall); | ||
| 268 | } | ||
| 269 | |||
| 270 | int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid) | ||
| 271 | { | ||
| 272 | int rc; | ||
| 273 | |||
| 274 | rc = selinux_xfrm_skb_sid_ingress(skb, sid, 0); | ||
| 275 | if (rc == 0 && *sid == SECSID_NULL) | ||
| 276 | *sid = selinux_xfrm_skb_sid_egress(skb); | ||
| 277 | |||
| 278 | return rc; | ||
| 279 | } | ||
| 280 | |||
| 281 | /* | ||
| 251 | * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy. | 282 | * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy. |
| 252 | */ | 283 | */ |
| 253 | int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, | 284 | int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, |
| @@ -327,19 +358,22 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x, | |||
| 327 | return rc; | 358 | return rc; |
| 328 | 359 | ||
| 329 | ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC); | 360 | ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC); |
| 330 | if (!ctx) | 361 | if (!ctx) { |
| 331 | return -ENOMEM; | 362 | rc = -ENOMEM; |
| 363 | goto out; | ||
| 364 | } | ||
| 332 | 365 | ||
| 333 | ctx->ctx_doi = XFRM_SC_DOI_LSM; | 366 | ctx->ctx_doi = XFRM_SC_DOI_LSM; |
| 334 | ctx->ctx_alg = XFRM_SC_ALG_SELINUX; | 367 | ctx->ctx_alg = XFRM_SC_ALG_SELINUX; |
| 335 | ctx->ctx_sid = secid; | 368 | ctx->ctx_sid = secid; |
| 336 | ctx->ctx_len = str_len; | 369 | ctx->ctx_len = str_len; |
| 337 | memcpy(ctx->ctx_str, ctx_str, str_len); | 370 | memcpy(ctx->ctx_str, ctx_str, str_len); |
| 338 | kfree(ctx_str); | ||
| 339 | 371 | ||
| 340 | x->security = ctx; | 372 | x->security = ctx; |
| 341 | atomic_inc(&selinux_xfrm_refcount); | 373 | atomic_inc(&selinux_xfrm_refcount); |
| 342 | return 0; | 374 | out: |
| 375 | kfree(ctx_str); | ||
| 376 | return rc; | ||
| 343 | } | 377 | } |
| 344 | 378 | ||
| 345 | /* | 379 | /* |
