summaryrefslogtreecommitdiff
path: root/security/selinux/netlabel.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/netlabel.c')
-rw-r--r--security/selinux/netlabel.c68
1 files changed, 66 insertions, 2 deletions
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 4053f7fc95fb..090404d6e512 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -9,7 +9,7 @@
*/
/*
- * (c) Copyright Hewlett-Packard Development Company, L.P., 2007
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2007, 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,6 +31,8 @@
#include <linux/rcupdate.h>
#include <net/sock.h>
#include <net/netlabel.h>
+#include <net/inet_sock.h>
+#include <net/inet_connection_sock.h>
#include "objsec.h"
#include "security.h"
@@ -77,6 +79,8 @@ static int selinux_netlbl_sock_setsid(struct sock *sk)
int rc;
struct sk_security_struct *sksec = sk->sk_security;
struct netlbl_lsm_secattr secattr;
+ struct inet_sock *sk_inet;
+ struct inet_connection_sock *sk_conn;
if (sksec->nlbl_state != NLBL_REQUIRE)
return 0;
@@ -87,8 +91,29 @@ static int selinux_netlbl_sock_setsid(struct sock *sk)
if (rc != 0)
goto sock_setsid_return;
rc = netlbl_sock_setattr(sk, &secattr);
- if (rc == 0)
+ switch (rc) {
+ case 0:
sksec->nlbl_state = NLBL_LABELED;
+ break;
+ case -EDESTADDRREQ:
+ /* we are going to possibly end up labeling the individual
+ * packets later which is problematic for stream sockets
+ * because of the additional IP header size, our solution is to
+ * allow for the maximum IP header length (40 bytes for IPv4,
+ * we don't have to worry about IPv6 yet) just in case */
+ sk_inet = inet_sk(sk);
+ if (sk_inet->is_icsk) {
+ sk_conn = inet_csk(sk);
+ if (sk_inet->opt)
+ sk_conn->icsk_ext_hdr_len -=
+ sk_inet->opt->optlen;
+ sk_conn->icsk_ext_hdr_len += 40;
+ sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
+ }
+ sksec->nlbl_state = NLBL_REQSKB;
+ rc = 0;
+ break;
+ }
sock_setsid_return:
netlbl_secattr_destroy(&secattr);
@@ -183,6 +208,45 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
}
/**
+ * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid
+ * @skb: the packet
+ * @family: protocol family
+ * @sid: the SID
+ *
+ * Description
+ * Call the NetLabel mechanism to set the label of a packet using @sid.
+ * Returns zero on auccess, negative values on failure.
+ *
+ */
+int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
+ u16 family,
+ u32 sid)
+{
+ int rc;
+ struct netlbl_lsm_secattr secattr;
+ struct sock *sk;
+
+ /* if this is a locally generated packet check to see if it is already
+ * being labeled by it's parent socket, if it is just exit */
+ sk = skb->sk;
+ if (sk != NULL) {
+ struct sk_security_struct *sksec = sk->sk_security;
+ if (sksec->nlbl_state != NLBL_REQSKB)
+ return 0;
+ }
+
+ netlbl_secattr_init(&secattr);
+ rc = security_netlbl_sid_to_secattr(sid, &secattr);
+ if (rc != 0)
+ goto skbuff_setsid_return;
+ rc = netlbl_skbuff_setattr(skb, family, &secattr);
+
+skbuff_setsid_return:
+ netlbl_secattr_destroy(&secattr);
+ return rc;
+}
+
+/**
* selinux_netlbl_sock_graft - Netlabel the new socket
* @sk: the new connection
* @sock: the new socket