[NetLabel]: protect the CIPSOv4 socket option from setsockopt()

This patch makes two changes to protect applications from either removing or
tampering with the CIPSOv4 IP option on a socket.  The first is the requirement
that applications have the CAP_NET_RAW capability to set an IPOPT_CIPSO option
on a socket; this prevents untrusted applications from setting their own
CIPSOv4 security attributes on the packets they send.  The second change is to
SELinux and it prevents applications from setting any IPv4 options when there
is an IPOPT_CIPSO option already present on the socket; this prevents
applications from removing CIPSOv4 security attributes from the packets they
send.

Signed-off-by: Paul Moore <paul.moore@hp.com>
Signed-off-by: James Morris <jmorris@namei.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index e2077a3..6460233 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -1307,7 +1307,8 @@
 
 	/* We can't use ip_options_get() directly because it makes a call to
 	 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
-	 * we can't block here. */
+	 * we won't always have CAP_NET_RAW even though we _always_ want to
+	 * set the IPOPT_CIPSO option. */
 	opt_len = (buf_len + 3) & ~3;
 	opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
 	if (opt == NULL) {
@@ -1317,11 +1318,9 @@
 	memcpy(opt->__data, buf, buf_len);
 	opt->optlen = opt_len;
 	opt->is_data = 1;
+	opt->cipso = sizeof(struct iphdr);
 	kfree(buf);
 	buf = NULL;
-	ret_val = ip_options_compile(opt, NULL);
-	if (ret_val != 0)
-		goto socket_setattr_failure;
 
 	sk_inet = inet_sk(sk);
 	if (sk_inet->is_icsk) {