Re: [PATCH v2 1/2] crypto: KEYS: convert public key to the akcipher api

2015-12-22 Thread Herbert Xu
On Tue, Dec 22, 2015 at 06:23:59AM -0800, Tadeusz Struk wrote:
>
> What about the first two. This one is completely unrelated.
> It only supposed to fix some random configuration issue
> reported by a build robot, which isn't really important now.
> The other two convert the module verifier to the new API.

No this compile breakage was introduced by your first two patches
because you changed crypto/public_key.h which is used by entities
outside of your patch.

So fix your first two patches by not breaking existing users
of it.

Cheers,
-- 
Email: Herbert Xu 
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH 16/17] calipso: Add validation of CALIPSO option.

2015-12-22 Thread Huw Davies
On Tue, Dec 22, 2015 at 10:47:43PM +0100, Hannes Frederic Sowa wrote:
> On 22.12.2015 17:59, Huw Davies wrote:
> > I'm confused about this one.  AFAICS, this will drop packets that we
> > can't process.  We don't send the icmp error, but I can certainly add
> > that.  Is that what you mean?
> 
> Actually, the implementation of calipso_validate will accept the packets
> because it defaults to return true if we don't compile the module. At
> least we should drop the packet if it is not loaded. I am in favor of
> adding the parameter problem icmp error. So, yes, I think it should be
> added.

Yet the option value is 0x07, i.e. the two highest bits are both zero
which according to:
https://tools.ietf.org/html/rfc2460#section-4.2
means we should just skip it.

https://tools.ietf.org/html/rfc5570#section-5.1.1
reaffirms that.

In terms of sending an icmp on error while validating:
https://tools.ietf.org/html/rfc5570#section-6.2.2
is pretty conservative in that case too.  Most errors
should just be silently dropped.

Huw.
--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] IMA: policy can be updated zero times

2015-12-22 Thread Petko Manolov
On December 22, 2015 9:56:28 PM GMT+02:00, Mimi Zohar 
 wrote:
>On Tue, 2015-12-22 at 08:51 -0500, Sasha Levin wrote:
>> Commit "IMA: policy can now be updated multiple times" assumed that
>the
>> policy would be updated at least once.
>> 
>> If there are zero updates, the temporary list head object will get
>added
>> to the policy list, and later dereferenced as an IMA policy object,
>which
>> means that invalid memory will be accessed.
>> 
>> Signed-off-by: Sasha Levin 
>> ---
>>  security/integrity/ima/ima_policy.c |3 +++
>>  1 file changed, 3 insertions(+)
>> 
>> diff --git a/security/integrity/ima/ima_policy.c
>b/security/integrity/ima/ima_policy.c
>> index ba5d2fc..9b958b8 100644
>> --- a/security/integrity/ima/ima_policy.c
>> +++ b/security/integrity/ima/ima_policy.c
>> @@ -431,6 +431,9 @@ void ima_update_policy(void)
>>  {
>>  struct list_head *first, *last, *policy;
>> 
>> +if (list_empty(_temp_rules))
>> +return;
>> +
>>  /* append current policy with the new rules */
>>  first = (_temp_rules)->next;
>>  last = (_temp_rules)->prev;
>
>Thanks, Sasha.  By the time ima_update_policy() is called
>ima_release_policy() has already output the policy update status
>message.  I guess an empty policy could be considered a valid policy.
>Could you add a msg indicating that the new policy was empty?


As far as I can say we can't get to ima_update_policy() with empty 
ima_temp_rules because ima_write_policy() will set valid_policy to 0 in case of 
an empty rule.  I'll double check it tomorrow, but please you do that too.


cheers,
Petko




--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] IMA: policy can be updated zero times

2015-12-22 Thread Sasha Levin
On 12/22/2015 04:40 PM, Petko Manolov wrote:
>> Thanks, Sasha.  By the time ima_update_policy() is called
>> >ima_release_policy() has already output the policy update status
>> >message.  I guess an empty policy could be considered a valid policy.
>> >Could you add a msg indicating that the new policy was empty?
> 
> As far as I can say we can't get to ima_update_policy() with empty 
> ima_temp_rules because ima_write_policy() will set valid_policy to 0 in case 
> of an empty rule.  I'll double check it tomorrow, but please you do that too.

This is based on an actual crash rather than code analysis.


Thanks,
Sasha
--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/2] crypto: KEYS: convert public key to the akcipher api

2015-12-22 Thread Tadeusz Struk
On 12/22/2015 06:33 PM, Herbert Xu wrote:
>> What about the first two. This one is completely unrelated.
>> > It only supposed to fix some random configuration issue
>> > reported by a build robot, which isn't really important now.
>> > The other two convert the module verifier to the new API.
> No this compile breakage was introduced by your first two patches
> because you changed crypto/public_key.h which is used by entities
> outside of your patch.
> 
> So fix your first two patches by not breaking existing users
> of it.
Ok I can see the problem now. I just don't should not include
the asymmetric-type.h in the public_key.h and it fixes it.
Will send v3 soon.
Thanks,
-- 
TS
--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 13/17] calipso: Allow request sockets to be relabelled by the lsm.

2015-12-22 Thread Huw Davies
Request sockets need to have a label that takes into account the
incoming connection as well as their parent's label.  This is used
for the outgoing SYN-ACK and for their child full-socket.

Signed-off-by: Huw Davies 
---
 include/net/netlabel.h  |  6 
 net/ipv6/calipso.c  | 78 +
 net/ipv6/exthdrs.c  | 16 ++---
 net/netlabel/netlabel_calipso.c | 40 +
 net/netlabel/netlabel_calipso.h |  4 +++
 net/netlabel/netlabel_kapi.c| 39 -
 security/selinux/netlabel.c |  2 +-
 7 files changed, 171 insertions(+), 14 deletions(-)

diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index b7ec76c..771a11c 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -229,6 +229,8 @@ struct netlbl_lsm_secattr {
  * @sock_getattr: retrieve the socket's attr
  * @sock_setattr: set the socket's attr
  * @sock_delattr: remove the socket's attr
+ * @req_setattr: set the req socket's attr
+ * @req_delattr: remove the req socket's attr
  *
  * Description:
  * This structure is filled out by the CALIPSO engine and passed
@@ -252,6 +254,10 @@ struct netlbl_calipso_ops {
const struct calipso_doi *doi_def,
const struct netlbl_lsm_secattr *secattr);
void (*sock_delattr)(struct sock *sk);
+   int (*req_setattr)(struct request_sock *req,
+  const struct calipso_doi *doi_def,
+  const struct netlbl_lsm_secattr *secattr);
+   void (*req_delattr)(struct request_sock *req);
 };
 
 /*
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index ce803e2..5d72669 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -886,6 +886,82 @@ done:
txopt_put(txopts);
 }
 
+/* request sock functions.
+ */
+
+/**
+ * calipso_req_setattr - Add a CALIPSO option to a connection request socket
+ * @req: the connection request socket
+ * @doi_def: the CALIPSO DOI to use
+ * @secattr: the specific security attributes of the socket
+ *
+ * Description:
+ * Set the CALIPSO option on the given socket using the DOI definition and
+ * security attributes passed to the function.  Returns zero on success and
+ * negative values on failure.
+ *
+ */
+static int calipso_req_setattr(struct request_sock *req,
+  const struct calipso_doi *doi_def,
+  const struct netlbl_lsm_secattr *secattr)
+{
+   struct ipv6_txoptions *txopts;
+   struct inet_request_sock *req_inet = inet_rsk(req);
+   struct ipv6_opt_hdr *old, *new;
+
+   if (req_inet->ipv6_opt && req_inet->ipv6_opt->hopopt)
+   old = req_inet->ipv6_opt->hopopt;
+   else
+   old = NULL;
+
+   new = calipso_opt_insert(old, doi_def, secattr);
+   if (IS_ERR(new))
+   return PTR_ERR(new);
+
+   txopts = ipv6_renew_options_kern(NULL, req_inet->ipv6_opt, IPV6_HOPOPTS,
+new, new ? ipv6_optlen(new) : 0);
+
+   kfree(new);
+
+   if (IS_ERR(txopts))
+   return PTR_ERR(txopts);
+
+   txopts = xchg(_inet->ipv6_opt, txopts);
+   txopt_put(txopts);
+
+   return 0;
+}
+
+/**
+ * calipso_req_delattr - Delete the CALIPSO option from a request socket
+ * @reg: the request socket
+ *
+ * Description:
+ * Removes the CALIPSO option from a request socket, if present.
+ *
+ */
+static void calipso_req_delattr(struct request_sock *req)
+{
+   struct inet_request_sock *req_inet = inet_rsk(req);
+   struct ipv6_opt_hdr *new;
+   struct ipv6_txoptions *txopts;
+
+   if (!req_inet->ipv6_opt || !req_inet->ipv6_opt->hopopt)
+   return;
+
+   if (calipso_opt_del(req_inet->ipv6_opt->hopopt, ))
+   return; /* Nothing to do */
+
+   txopts = ipv6_renew_options_kern(NULL, req_inet->ipv6_opt, IPV6_HOPOPTS,
+new, new ? ipv6_optlen(new) : 0);
+
+   if (!IS_ERR(txopts)) {
+   txopts = xchg(_inet->ipv6_opt, txopts);
+   txopt_put(txopts);
+   }
+   kfree(new);
+}
+
 static const struct netlbl_calipso_ops ops = {
.doi_add  = calipso_doi_add,
.doi_free = calipso_doi_free,
@@ -896,6 +972,8 @@ static const struct netlbl_calipso_ops ops = {
.sock_getattr = calipso_sock_getattr,
.sock_setattr = calipso_sock_setattr,
.sock_delattr = calipso_sock_delattr,
+   .req_setattr  = calipso_req_setattr,
+   .req_delattr  = calipso_req_delattr,
 };
 
 /**
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 9426b26..e87c89b 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -793,7 +793,7 @@ static int ipv6_renew_option(void *ohdr,
  * specified option type is not copied into the new set of options.
  *
  * The new set of options is allocated from the socket option 

[RFC PATCH 16/17] calipso: Add validation of CALIPSO option.

2015-12-22 Thread Huw Davies
We check lengths, checksum and the DOI.  We leave checking of the
level and categories for the socket layer.

Signed-off-by: Huw Davies 
---
 include/net/calipso.h |  6 ++
 net/ipv6/calipso.c| 43 +++
 net/ipv6/exthdrs.c| 27 +++
 3 files changed, 76 insertions(+)

diff --git a/include/net/calipso.h b/include/net/calipso.h
index ad4d653..99df89b 100644
--- a/include/net/calipso.h
+++ b/include/net/calipso.h
@@ -65,6 +65,7 @@ struct calipso_doi {
 #ifdef CONFIG_NETLABEL
 int __init calipso_init(void);
 void calipso_exit(void);
+bool calipso_validate(const struct sk_buff *skb, const unsigned char *option);
 #else
 static inline int __init calipso_init(void)
 {
@@ -74,6 +75,11 @@ static inline int __init calipso_init(void)
 static inline void calipso_exit(void)
 {
 }
+static inline bool calipso_validate(const struct sk_buff *skb,
+   const unsigned char *option)
+{
+   return true;
+}
 #endif /* CONFIG_NETLABEL */
 
 #endif /* _CALIPSO_H */
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index a91d71d..f3b7c43 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -315,6 +315,49 @@ doi_walk_return:
 }
 
 /**
+ * calipso_validate - Validate a CALIPSO option
+ * @skb: the packet
+ * @option: the start of the option
+ *
+ * Description:
+ * This routine is called to validate a CALIPSO option.
+ * If the option is valid then a zero value is returned.  If the
+ * option is invalid then a non-zero value is returned and
+ * representing the offset to the offending portion of the option.
+ *
+ * The caller should have already checked that the length of the
+ * option (including the TLV header) is >= 10 and that the catmap
+ * length is consistent with the option length.
+ *
+ * We leave checks on the level and categories to the socket layer.
+ */
+bool calipso_validate(const struct sk_buff *skb, const unsigned char *option)
+{
+   struct calipso_doi *doi_def;
+   int ret_val;
+   u16 crc, len = option[1] + 2;
+   static const u8 zero[2];
+
+   /* The original CRC runs over the option including the TLV header
+* with the CRC-16 field (at offset 8) zeroed out.
+*/
+   crc = crc_ccitt(0x, option, 8);
+   crc = crc_ccitt(crc, zero, sizeof(zero));
+   if (len > 10)
+   crc = crc_ccitt(crc, option + 10, len - 10);
+   crc = ~crc;
+   if (option[8] != (crc & 0xff) || option[9] != ((crc >> 8) & 0xff))
+   return false;
+
+   rcu_read_lock();
+   doi_def = calipso_doi_search(get_unaligned_be32(option + 2));
+   ret_val = !!doi_def;
+   rcu_read_unlock();
+
+   return ret_val;
+}
+
+/**
  * calipso_map_cat_hton - Perform a category mapping from host to network
  * @doi_def: the DOI definition
  * @secattr: the security attributes
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index e87c89b..3dc1d15 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 #if IS_ENABLED(CONFIG_IPV6_MIP6)
 #include 
 #endif
@@ -603,6 +604,28 @@ drop:
return false;
 }
 
+/* CALIPSO RFC 5570 */
+
+static bool ipv6_hop_calipso(struct sk_buff *skb, int optoff)
+{
+   const unsigned char *nh = skb_network_header(skb);
+
+   if (nh[optoff + 1] < 8)
+   goto drop;
+
+   if (nh[optoff + 6] * 4 + 8 > nh[optoff + 1])
+   goto drop;
+
+   if (!calipso_validate(skb, nh + optoff))
+   goto drop;
+
+   return true;
+
+drop:
+   kfree_skb(skb);
+   return false;
+}
+
 static const struct tlvtype_proc tlvprochopopt_lst[] = {
{
.type   = IPV6_TLV_ROUTERALERT,
@@ -612,6 +635,10 @@ static const struct tlvtype_proc tlvprochopopt_lst[] = {
.type   = IPV6_TLV_JUMBO,
.func   = ipv6_hop_jumbo,
},
+   {
+   .type   = IPV6_TLV_CALIPSO,
+   .func   = ipv6_hop_calipso,
+   },
{ -1, }
 };
 
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 03/17] netlabel: Initial support for the CALIPSO netlink protocol.

2015-12-22 Thread Huw Davies
CALIPSO is a packet labelling protocol for IPv6 which is very similar
to CIPSO.  It is specified in RFC 5570.  Much of the code is based on
the current CIPSO code.

This adds support for adding passthrough-type CALIPSO DOIs through the
NLBL_CALIPSO_C_ADD command.  It requires attributes:

 NLBL_CALIPSO_A_TYPE which must be CALIPSO_MAP_PASS.
 NLBL_CALIPSO_A_DOI.

In passthrough mode the CALIPSO engine will map MLS secattr levels
and categories directly to the packet label.

At this stage, the major difference between this and the CIPSO
code is that IPv6 may be compiled as a module.  To allow for
this the CALIPSO functions are registered at module init time.

Signed-off-by: Huw Davies 
---
 include/net/calipso.h   |  79 +++
 include/net/netlabel.h  |  22 
 include/uapi/linux/audit.h  |   2 +
 net/ipv6/Makefile   |   1 +
 net/ipv6/af_inet6.c |   9 +-
 net/ipv6/calipso.c  | 169 +++
 net/netlabel/Makefile   |   2 +-
 net/netlabel/netlabel_calipso.c | 219 
 net/netlabel/netlabel_calipso.h | 128 +++
 net/netlabel/netlabel_kapi.c|   1 +
 net/netlabel/netlabel_mgmt.c|   9 ++
 net/netlabel/netlabel_user.c|   5 +
 12 files changed, 644 insertions(+), 2 deletions(-)
 create mode 100644 include/net/calipso.h
 create mode 100644 net/ipv6/calipso.c
 create mode 100644 net/netlabel/netlabel_calipso.c
 create mode 100644 net/netlabel/netlabel_calipso.h

diff --git a/include/net/calipso.h b/include/net/calipso.h
new file mode 100644
index 000..ad4d653
--- /dev/null
+++ b/include/net/calipso.h
@@ -0,0 +1,79 @@
+/*
+ * CALIPSO - Common Architecture Label IPv6 Security Option
+ *
+ * This is an implementation of the CALIPSO protocol as specified in
+ * RFC 5570.
+ *
+ * Authors: Paul Moore 
+ *  Huw Davies 
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ * (c) Copyright Huw Davies , 2015
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, see .
+ *
+ */
+
+#ifndef _CALIPSO_H
+#define _CALIPSO_H
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* known doi values */
+#define CALIPSO_DOI_UNKNOWN  0x
+
+/* doi mapping types */
+#define CALIPSO_MAP_UNKNOWN  0
+#define CALIPSO_MAP_PASS 1
+
+/*
+ * CALIPSO DOI definitions
+ */
+
+/* DOI definition struct */
+struct calipso_doi {
+   u32 doi;
+   u32 type;
+
+   atomic_t refcount;
+   struct list_head list;
+   struct rcu_head rcu;
+};
+
+#ifdef CONFIG_NETLABEL
+int __init calipso_init(void);
+void calipso_exit(void);
+#else
+static inline int __init calipso_init(void)
+{
+   return 0;
+}
+
+static inline void calipso_exit(void)
+{
+}
+#endif /* CONFIG_NETLABEL */
+
+#endif /* _CALIPSO_H */
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 7b5a300..ced56b0 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -40,6 +40,7 @@
 #include 
 
 struct cipso_v4_doi;
+struct calipso_doi;
 
 /*
  * NetLabel - A management interface for maintaining network packet label
@@ -94,6 +95,8 @@ struct cipso_v4_doi;
 #define NETLBL_NLTYPE_UNLABELED_NAME"NLBL_UNLBL"
 #define NETLBL_NLTYPE_ADDRSELECT6
 #define NETLBL_NLTYPE_ADDRSELECT_NAME   "NLBL_ADRSEL"
+#define NETLBL_NLTYPE_CALIPSO   7
+#define NETLBL_NLTYPE_CALIPSO_NAME  "NLBL_CALIPSO"
 
 /*
  * NetLabel - Kernel API for accessing the network packet label mappings.
@@ -216,6 +219,23 @@ struct netlbl_lsm_secattr {
} attr;
 };
 
+/**
+ * struct netlbl_calipso_ops - NetLabel CALIPSO operations
+ * @doi_add: add a CALIPSO DOI
+ * @doi_free: free a CALIPSO DOI
+ *
+ * Description:
+ * This structure is filled out by the CALIPSO engine and passed
+ * to the NetLabel core via a call to netlbl_calipso_ops_register().
+ * It enables the CALIPSO engine (and hence IPv6) to be compiled
+ * as a module.
+ */
+struct netlbl_calipso_ops {
+   int (*doi_add)(struct calipso_doi *doi_def,
+  struct netlbl_audit *audit_info);
+   void (*doi_free)(struct calipso_doi *doi_def);
+};
+
 /*
  * LSM security attribute operations (inline)
  */
@@ -598,4 +618,6 @@ static 

[RFC PATCH 15/17] netlabel: Pass a family parameter to netlbl_skbuff_err().

2015-12-22 Thread Huw Davies
This makes it possible to route the error to the appropriate
labelling engine.  CALIPSO is far less verbose than CIPSO
when encountering a bogus packet, so there is no need for a
CALIPSO error handler.

Signed-off-by: Huw Davies 
---
 include/net/netlabel.h  |  2 +-
 net/netlabel/netlabel_kapi.c| 11 ---
 security/selinux/hooks.c|  6 +++---
 security/selinux/include/netlabel.h |  4 +++-
 security/selinux/netlabel.c |  6 +++---
 security/smack/smack_lsm.c  |  2 +-
 6 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index d88bf4a..1aed135 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -488,7 +488,7 @@ int netlbl_skbuff_setattr(struct sk_buff *skb,
 int netlbl_skbuff_getattr(const struct sk_buff *skb,
  u16 family,
  struct netlbl_lsm_secattr *secattr);
-void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway);
+void netlbl_skbuff_err(struct sk_buff *skb, u16 family, int error, int 
gateway);
 
 /*
  * LSM label mapping cache operations
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index bace474..35df8f5 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -1250,6 +1250,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
 /**
  * netlbl_skbuff_err - Handle a LSM error on a sk_buff
  * @skb: the packet
+ * @family: the family
  * @error: the error code
  * @gateway: true if host is acting as a gateway, false otherwise
  *
@@ -1259,10 +1260,14 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
  * according to the packet's labeling protocol.
  *
  */
-void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway)
+void netlbl_skbuff_err(struct sk_buff *skb, u16 family, int error, int gateway)
 {
-   if (cipso_v4_optptr(skb))
-   cipso_v4_error(skb, error, gateway);
+   switch (family) {
+   case AF_INET:
+   if (cipso_v4_optptr(skb))
+   cipso_v4_error(skb, error, gateway);
+   break;
+   }
 }
 
 /**
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 6124da6..5301c9f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4473,13 +4473,13 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, 
struct sk_buff *skb)
err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
   addrp, family, peer_sid, );
if (err) {
-   selinux_netlbl_err(skb, err, 0);
+   selinux_netlbl_err(skb, family, err, 0);
return err;
}
err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
   PEER__RECV, );
if (err) {
-   selinux_netlbl_err(skb, err, 0);
+   selinux_netlbl_err(skb, family, err, 0);
return err;
}
}
@@ -4843,7 +4843,7 @@ static unsigned int selinux_ip_forward(struct sk_buff 
*skb,
err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
   addrp, family, peer_sid, );
if (err) {
-   selinux_netlbl_err(skb, err, 1);
+   selinux_netlbl_err(skb, family, err, 1);
return NF_DROP;
}
}
diff --git a/security/selinux/include/netlabel.h 
b/security/selinux/include/netlabel.h
index 8c59b8f..75686d5 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -40,7 +40,8 @@
 #ifdef CONFIG_NETLABEL
 void selinux_netlbl_cache_invalidate(void);
 
-void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway);
+void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error,
+   int gateway);
 
 void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec);
 void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec);
@@ -72,6 +73,7 @@ static inline void selinux_netlbl_cache_invalidate(void)
 }
 
 static inline void selinux_netlbl_err(struct sk_buff *skb,
+ u16 family,
  int error,
  int gateway)
 {
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index ca220c3..dfca50d 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -151,9 +151,9 @@ void selinux_netlbl_cache_invalidate(void)
  * present on the packet, NetLabel is smart enough to only act when it should.
  *
  */
-void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway)
+void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int 
gateway)
 {
-   

[RFC PATCH 08/17] ipv6: Add ipv6_renew_options_kern() that accepts a kernel mem pointer.

2015-12-22 Thread Huw Davies
The functionality is equivalent to ipv6_renew_options() except
that the newopt pointer is in kernel, not user, memory

The kernel memory implementation will be used by the CALIPSO network
labelling engine, which needs to be able to set IPv6 hop-by-hop
options.

Signed-off-by: Huw Davies 
---
 include/net/ipv6.h |   6 +++
 net/ipv6/exthdrs.c | 131 -
 2 files changed, 125 insertions(+), 12 deletions(-)

diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 9a5c9f0..5a72ffd 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -304,6 +304,12 @@ struct ipv6_txoptions *ipv6_renew_options(struct sock *sk,
  int newtype,
  struct ipv6_opt_hdr __user *newopt,
  int newoptlen);
+struct ipv6_txoptions *
+ipv6_renew_options_kern(struct sock *sk,
+   struct ipv6_txoptions *opt,
+   int newtype,
+   struct ipv6_opt_hdr *newopt,
+   int newoptlen);
 struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
  struct ipv6_txoptions *opt);
 
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index ea7c4d6..9426b26 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -734,11 +734,16 @@ ipv6_dup_options(struct sock *sk, struct ipv6_txoptions 
*opt)
 EXPORT_SYMBOL_GPL(ipv6_dup_options);
 
 static int ipv6_renew_option(void *ohdr,
-struct ipv6_opt_hdr __user *newopt, int newoptlen,
+struct ipv6_opt_hdr __user *newopt_user,
+struct ipv6_opt_hdr *newopt,
+int newoptlen,
 int inherit,
 struct ipv6_opt_hdr **hdr,
 char **p)
 {
+   if (WARN_ON_ONCE(newopt_user && newopt))
+   return -EINVAL;
+
if (inherit) {
if (ohdr) {
memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr 
*)ohdr));
@@ -746,28 +751,65 @@ static int ipv6_renew_option(void *ohdr,
*p += CMSG_ALIGN(ipv6_optlen(*hdr));
}
} else {
-   if (newopt) {
-   if (copy_from_user(*p, newopt, newoptlen))
+   if (newopt_user) {
+   if (copy_from_user(*p, newopt_user, newoptlen))
return -EFAULT;
*hdr = (struct ipv6_opt_hdr *)*p;
if (ipv6_optlen(*hdr) > newoptlen)
return -EINVAL;
*p += CMSG_ALIGN(newoptlen);
+   } else if (newopt) {
+   memcpy(*p, newopt, newoptlen);
+   *hdr = (struct ipv6_opt_hdr *)*p;
+   if (ipv6_optlen(*hdr) > newoptlen)
+   return -EINVAL;
+   *p += CMSG_ALIGN(newoptlen);
}
}
return 0;
 }
 
-struct ipv6_txoptions *
-ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
-  int newtype,
-  struct ipv6_opt_hdr __user *newopt, int newoptlen)
+/**
+ * __ipv6_renew_options - replace a specific ext hdr with a new one.
+ *
+ * @sk: sock from which to allocate memory
+ * @opt: original options
+ * @newtype: option type to replace in @opt
+ * @newopt_user: new option of type @newtype to replace (user-mem)
+ * @newopt: new option of type @newtype to replace (kernel-mem)
+ * @newoptlen: length of @newopt_user or @newopt
+ *
+ * The implementation of ipv6_renew_options() and
+ * ipv6_renew_options_from_user().
+ *
+ * Returns a new set of options which is a copy of @opt with the
+ * option type @newtype replaced with either @newopt_user or @newopt.
+ * Only one of @newopt_user or @newopt may be non-NULL.
+ *
+ * @opt may be NULL, in which case a new set of options is returned
+ * containing just @newopt_user or @newopt.
+ *
+ * Both @newopt_user and @newopt may be NULL, in which case the
+ * specified option type is not copied into the new set of options.
+ *
+ * The new set of options is allocated from the socket option memory
+ * buffer of @sk.
+ */
+static struct ipv6_txoptions *
+__ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
+int newtype,
+struct ipv6_opt_hdr __user *newopt_user,
+struct ipv6_opt_hdr *newopt,
+int newoptlen)
 {
int tot_len = 0;
char *p;
struct ipv6_txoptions *opt2;
int err;
 
+   if (WARN_ON_ONCE(newopt_user && newopt))
+   return NULL;
+
if (opt) {
if (newtype != IPV6_HOPOPTS && opt->hopopt)
tot_len += 

[RFC PATCH 12/17] ipv6: Allow request socks to contain IPv6 options.

2015-12-22 Thread Huw Davies
If set, these will that precedence over the parent's options during
both sending and child creation.  If they're not set, the parent's
options (if any) will be used.

This is to allow the security_inet_conn_request() hook to modify the
IPv6 options in just the same way that it already may do for IPv4.

Signed-off-by: Huw Davies 
---
 include/net/inet_sock.h |  7 ++-
 net/dccp/ipv6.c | 12 +---
 net/ipv4/tcp_input.c|  3 +++
 net/ipv6/tcp_ipv6.c | 12 +---
 4 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 625bdf9..39bbe8d 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -96,7 +96,12 @@ struct inet_request_sock {
u32 ir_mark;
union {
struct ip_options_rcu   *opt;
-   struct sk_buff  *pktopts;
+#if IS_ENABLED(CONFIG_IPV6)
+   struct {
+   struct ipv6_txoptions   *ipv6_opt;
+   struct sk_buff  *pktopts;
+   };
+#endif
};
 };
 
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 9c6d050..8bb1c3a 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -216,14 +216,17 @@ static int dccp_v6_send_response(const struct sock *sk, 
struct request_sock *req
skb = dccp_make_response(sk, dst, req);
if (skb != NULL) {
struct dccp_hdr *dh = dccp_hdr(skb);
+   struct ipv6_txoptions *opt;
 
dh->dccph_checksum = dccp_v6_csum_finish(skb,
 >ir_v6_loc_addr,
 >ir_v6_rmt_addr);
fl6.daddr = ireq->ir_v6_rmt_addr;
rcu_read_lock();
-   err = ip6_xmit(sk, skb, , rcu_dereference(np->opt),
-  np->tclass);
+   opt = ireq->ipv6_opt;
+   if (!opt)
+   opt = rcu_dereference(np->opt);
+   err = ip6_xmit(sk, skb, , opt, np->tclass);
rcu_read_unlock();
err = net_xmit_eval(err);
}
@@ -236,6 +239,7 @@ done:
 static void dccp_v6_reqsk_destructor(struct request_sock *req)
 {
dccp_feat_list_purge(_rsk(req)->dreq_featneg);
+   kfree(inet_rsk(req)->ipv6_opt);
kfree_skb(inet_rsk(req)->pktopts);
 }
 
@@ -494,7 +498,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct 
sock *sk,
 * Yes, keeping reference count would be much more clever, but we make
 * one more one thing there: reattach optmem to newsk.
 */
-   opt = rcu_dereference(np->opt);
+   opt = ireq->ipv6_opt;
+   if (!opt)
+   opt = rcu_dereference(np->opt);
if (opt) {
opt = ipv6_dup_options(newsk, opt);
RCU_INIT_POINTER(newnp->opt, opt);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 2d656ee..af91a95 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -6094,6 +6094,9 @@ struct request_sock *inet_reqsk_alloc(const struct 
request_sock_ops *ops,
 
kmemcheck_annotate_bitfield(ireq, flags);
ireq->opt = NULL;
+#if IS_ENABLED(CONFIG_IPV6)
+   ireq->pktopts = NULL;
+#endif
atomic64_set(>ir_cookie, 0);
ireq->ireq_state = TCP_NEW_SYN_RECV;
write_pnet(>ireq_net, sock_net(sk_listener));
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 6b8a8a9..a9041b2 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -443,6 +443,7 @@ static int tcp_v6_send_synack(const struct sock *sk, struct 
dst_entry *dst,
 {
struct inet_request_sock *ireq = inet_rsk(req);
struct ipv6_pinfo *np = inet6_sk(sk);
+   struct ipv6_txoptions *opt;
struct flowi6 *fl6 = >u.ip6;
struct sk_buff *skb;
int err = -ENOMEM;
@@ -462,8 +463,10 @@ static int tcp_v6_send_synack(const struct sock *sk, 
struct dst_entry *dst,
if (np->repflow && ireq->pktopts)
fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts));
 
-   err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt),
-  np->tclass);
+   opt = ireq->ipv6_opt;
+   if (!opt)
+   opt = rcu_dereference(np->opt);
+   err = ip6_xmit(sk, skb, fl6, opt, np->tclass);
err = net_xmit_eval(err);
}
 
@@ -474,6 +477,7 @@ done:
 
 static void tcp_v6_reqsk_destructor(struct request_sock *req)
 {
+   kfree(inet_rsk(req)->ipv6_opt);
kfree_skb(inet_rsk(req)->pktopts);
 }
 
@@ -1101,7 +1105,9 @@ static struct sock *tcp_v6_syn_recv_sock(const struct 
sock *sk, struct sk_buff *
   but we make one more one thing there: reattach optmem
   to newsk.
 */
-   opt = rcu_dereference(np->opt);
+   opt 

[RFC PATCH 04/17] netlabel: Add support for querying a CALIPSO DOI.

2015-12-22 Thread Huw Davies
Query a specified DOI through the NLBL_CALIPSO_C_LIST command.
It requires the attribute:
 NLBL_CALIPSO_A_DOI.

The reply will contain:
 NLBL_CALIPSO_A_MTYPE

Signed-off-by: Huw Davies 
---
 include/net/netlabel.h  |   4 ++
 net/ipv6/calipso.c  |  68 +++
 net/netlabel/netlabel_calipso.c | 102 
 net/netlabel/netlabel_calipso.h |   2 +
 4 files changed, 176 insertions(+)

diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index ced56b0..e072350 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -223,6 +223,8 @@ struct netlbl_lsm_secattr {
  * struct netlbl_calipso_ops - NetLabel CALIPSO operations
  * @doi_add: add a CALIPSO DOI
  * @doi_free: free a CALIPSO DOI
+ * @doi_getdef: returns a reference to a DOI
+ * @doi_putdef: releases a reference of a DOI
  *
  * Description:
  * This structure is filled out by the CALIPSO engine and passed
@@ -234,6 +236,8 @@ struct netlbl_calipso_ops {
int (*doi_add)(struct calipso_doi *doi_def,
   struct netlbl_audit *audit_info);
void (*doi_free)(struct calipso_doi *doi_def);
+   struct calipso_doi *(*doi_getdef)(u32 doi);
+   void (*doi_putdef)(struct calipso_doi *doi_def);
 };
 
 /*
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index aa44310..128cc69 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -144,9 +144,77 @@ static void calipso_doi_free(struct calipso_doi *doi_def)
kfree(doi_def);
 }
 
+/**
+ * calipso_doi_free_rcu - Frees a DOI definition via the RCU pointer
+ * @entry: the entry's RCU field
+ *
+ * Description:
+ * This function is designed to be used as a callback to the call_rcu()
+ * function so that the memory allocated to the DOI definition can be released
+ * safely.
+ *
+ */
+static void calipso_doi_free_rcu(struct rcu_head *entry)
+{
+   struct calipso_doi *doi_def;
+
+   doi_def = container_of(entry, struct calipso_doi, rcu);
+   calipso_doi_free(doi_def);
+}
+
+/**
+ * calipso_doi_getdef - Returns a reference to a valid DOI definition
+ * @doi: the DOI value
+ *
+ * Description:
+ * Searches for a valid DOI definition and if one is found it is returned to
+ * the caller.  Otherwise NULL is returned.  The caller must ensure that
+ * calipso_doi_putdef() is called when the caller is done.
+ *
+ */
+static struct calipso_doi *calipso_doi_getdef(u32 doi)
+{
+   struct calipso_doi *doi_def;
+
+   rcu_read_lock();
+   doi_def = calipso_doi_search(doi);
+   if (!doi_def)
+   goto doi_getdef_return;
+   if (!atomic_inc_not_zero(_def->refcount))
+   doi_def = NULL;
+
+doi_getdef_return:
+   rcu_read_unlock();
+   return doi_def;
+}
+
+/**
+ * calipso_doi_putdef - Releases a reference for the given DOI definition
+ * @doi_def: the DOI definition
+ *
+ * Description:
+ * Releases a DOI definition reference obtained from calipso_doi_getdef().
+ *
+ */
+static void calipso_doi_putdef(struct calipso_doi *doi_def)
+{
+   if (!doi_def)
+   return;
+
+   if (!atomic_dec_and_test(_def->refcount))
+   return;
+   spin_lock(_doi_list_lock);
+   list_del_rcu(_def->list);
+   spin_unlock(_doi_list_lock);
+
+   call_rcu(_def->rcu, calipso_doi_free_rcu);
+}
+
 static const struct netlbl_calipso_ops ops = {
.doi_add  = calipso_doi_add,
.doi_free = calipso_doi_free,
+   .doi_getdef   = calipso_doi_getdef,
+   .doi_putdef   = calipso_doi_putdef,
 };
 
 /**
diff --git a/net/netlabel/netlabel_calipso.c b/net/netlabel/netlabel_calipso.c
index 013d1e2..1effc61 100644
--- a/net/netlabel/netlabel_calipso.c
+++ b/net/netlabel/netlabel_calipso.c
@@ -128,6 +128,65 @@ static int netlbl_calipso_add(struct sk_buff *skb, struct 
genl_info *info)
return ret_val;
 }
 
+/**
+ * netlbl_calipso_list - Handle a LIST message
+ * @skb: the NETLINK buffer
+ * @info: the Generic NETLINK info block
+ *
+ * Description:
+ * Process a user generated LIST message and respond accordingly.
+ * Returns zero on success and negative values on error.
+ *
+ */
+static int netlbl_calipso_list(struct sk_buff *skb, struct genl_info *info)
+{
+   int ret_val;
+   struct sk_buff *ans_skb = NULL;
+   void *data;
+   u32 doi;
+   struct calipso_doi *doi_def;
+
+   if (!info->attrs[NLBL_CALIPSO_A_DOI]) {
+   ret_val = -EINVAL;
+   goto list_failure;
+   }
+
+   doi = nla_get_u32(info->attrs[NLBL_CALIPSO_A_DOI]);
+
+   doi_def = calipso_doi_getdef(doi);
+   if (!doi_def) {
+   ret_val = -EINVAL;
+   goto list_failure;
+   }
+
+   ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+   if (!ans_skb) {
+   ret_val = -ENOMEM;
+   goto list_failure_put;
+   }
+   data = genlmsg_put_reply(ans_skb, info, _calipso_gnl_family,
+ 

[RFC PATCH 00/17] CALIPSO implementation

2015-12-22 Thread Huw Davies
This patch series implements RFC 5570 - Common Architecture Label IPv6
Security Option (CALIPSO).  Its goal is to set MLS sensitivity labels
on IPv6 packets using a hop-by-hop option.  CALIPSO very similar to
its IPv4 cousin CIPSO and much of this series is based on that code.

Most of this series involves adding support to NetLabel and adding a
CALIPSO module within IPv6, and as such is fairly self-contained.
There are however a few places where I've needed to add things to the
core networking stack, so I'd be particularly interested in hearing
comments about these:

[PATCH 08/17] ipv6: Add ipv6_renew_options_kern() that accepts a kernel mem 
pointer.
  Hopefully not too controversial - adds a kernel memory version of
  ipv6_renew_options()

[PATCH 12/17] ipv6: Allow request socks to contain IPv6 options.
  We need a way to set the IPv6 options on request sockets, just like
  we do for IPv4.  This is so that the LSM can ensure the SYN-ACK is
  correctly labelled.

The series is based off v4.4-rc6.

Thoughts about these and any of the other patches are most welcome.

If anybody actually wants to play with this, then you'll need some patches
to netlabel-tools that are currently available on the 'calipso' branch at:
https://github.com/hdmdavies/netlabel_tools.git

Thanks to Paul Moore for his guidance in getting this far.

Huw.
--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 01/17] netlabel: Mark rcu pointers with __rcu.

2015-12-22 Thread Huw Davies
This fixes sparse errors of the form:
 netlabel_domainhash.c:126:23: error: incompatible types in comparison 
expression (different address spaces)

This patch also removes unnecessary initialization of static variables
to NULL.

Signed-off-by: Huw Davies 
---
 net/netlabel/netlabel_domainhash.c | 4 ++--
 net/netlabel/netlabel_unlabeled.c  | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/netlabel/netlabel_domainhash.c 
b/net/netlabel/netlabel_domainhash.c
index f0cb92f..d4d6640 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -55,8 +55,8 @@ struct netlbl_domhsh_tbl {
 static DEFINE_SPINLOCK(netlbl_domhsh_lock);
 #define netlbl_domhsh_rcu_deref(p) \
rcu_dereference_check(p, lockdep_is_held(_domhsh_lock))
-static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL;
-static struct netlbl_dom_map *netlbl_domhsh_def = NULL;
+static struct netlbl_domhsh_tbl __rcu *netlbl_domhsh;
+static struct netlbl_dom_map __rcu *netlbl_domhsh_def;
 
 /*
  * Domain Hash Table Helper Functions
diff --git a/net/netlabel/netlabel_unlabeled.c 
b/net/netlabel/netlabel_unlabeled.c
index b038092..a323815 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -116,8 +116,8 @@ struct netlbl_unlhsh_walk_arg {
 static DEFINE_SPINLOCK(netlbl_unlhsh_lock);
 #define netlbl_unlhsh_rcu_deref(p) \
rcu_dereference_check(p, lockdep_is_held(_unlhsh_lock))
-static struct netlbl_unlhsh_tbl *netlbl_unlhsh = NULL;
-static struct netlbl_unlhsh_iface *netlbl_unlhsh_def = NULL;
+static struct netlbl_unlhsh_tbl __rcu *netlbl_unlhsh;
+static struct netlbl_unlhsh_iface __rcu *netlbl_unlhsh_def;
 
 /* Accept unlabeled packets flag */
 static u8 netlabel_unlabel_acceptflg = 0;
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 07/17] netlabel: Add support for removing a CALIPSO DOI.

2015-12-22 Thread Huw Davies
Remove a specified DOI through the NLBL_CALIPSO_C_REMOVE command.
It requires the attribute:
 NLBL_CALIPSO_A_DOI.

Signed-off-by: Huw Davies 
---
 include/net/netlabel.h  |  1 +
 net/ipv6/calipso.c  | 48 +
 net/netlabel/netlabel_calipso.c | 92 +
 net/netlabel/netlabel_calipso.h |  1 +
 4 files changed, 142 insertions(+)

diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index c6e1ce9..0ffe32f 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -237,6 +237,7 @@ struct netlbl_calipso_ops {
int (*doi_add)(struct calipso_doi *doi_def,
   struct netlbl_audit *audit_info);
void (*doi_free)(struct calipso_doi *doi_def);
+   int (*doi_remove)(u32 doi, struct netlbl_audit *audit_info);
struct calipso_doi *(*doi_getdef)(u32 doi);
void (*doi_putdef)(struct calipso_doi *doi_def);
int (*doi_walk)(u32 *skip_cnt,
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index fa17c7a..d7df7a4 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -163,6 +163,53 @@ static void calipso_doi_free_rcu(struct rcu_head *entry)
 }
 
 /**
+ * calipso_doi_remove - Remove an existing DOI from the CALIPSO protocol engine
+ * @doi: the DOI value
+ * @audit_secid: the LSM secid to use in the audit message
+ *
+ * Description:
+ * Removes a DOI definition from the CALIPSO engine.  The NetLabel routines 
will
+ * be called to release their own LSM domain mappings as well as our own
+ * domain list.  Returns zero on success and negative values on failure.
+ *
+ */
+static int calipso_doi_remove(u32 doi, struct netlbl_audit *audit_info)
+{
+   int ret_val;
+   struct calipso_doi *doi_def;
+   struct audit_buffer *audit_buf;
+
+   spin_lock(_doi_list_lock);
+   doi_def = calipso_doi_search(doi);
+   if (!doi_def) {
+   spin_unlock(_doi_list_lock);
+   ret_val = -ENOENT;
+   goto doi_remove_return;
+   }
+   if (!atomic_dec_and_test(_def->refcount)) {
+   spin_unlock(_doi_list_lock);
+   ret_val = -EBUSY;
+   goto doi_remove_return;
+   }
+   list_del_rcu(_def->list);
+   spin_unlock(_doi_list_lock);
+
+   call_rcu(_def->rcu, calipso_doi_free_rcu);
+   ret_val = 0;
+
+doi_remove_return:
+   audit_buf = netlbl_audit_start(AUDIT_MAC_CALIPSO_DEL, audit_info);
+   if (audit_buf) {
+   audit_log_format(audit_buf,
+" calipso_doi=%u res=%u",
+doi, ret_val == 0 ? 1 : 0);
+   audit_log_end(audit_buf);
+   }
+
+   return ret_val;
+}
+
+/**
  * calipso_doi_getdef - Returns a reference to a valid DOI definition
  * @doi: the DOI value
  *
@@ -253,6 +300,7 @@ doi_walk_return:
 static const struct netlbl_calipso_ops ops = {
.doi_add  = calipso_doi_add,
.doi_free = calipso_doi_free,
+   .doi_remove   = calipso_doi_remove,
.doi_getdef   = calipso_doi_getdef,
.doi_putdef   = calipso_doi_putdef,
.doi_walk = calipso_doi_walk,
diff --git a/net/netlabel/netlabel_calipso.c b/net/netlabel/netlabel_calipso.c
index a014ec2..2083b15 100644
--- a/net/netlabel/netlabel_calipso.c
+++ b/net/netlabel/netlabel_calipso.c
@@ -53,6 +53,12 @@ struct netlbl_calipso_doiwalk_arg {
u32 seq;
 };
 
+/* Argument struct for netlbl_domhsh_walk() */
+struct netlbl_domhsh_walk_arg {
+   struct netlbl_audit *audit_info;
+   u32 doi;
+};
+
 /* NetLabel Generic NETLINK CALIPSO family */
 static struct genl_family netlbl_calipso_gnl_family = {
.id = GENL_ID_GENERATE,
@@ -261,6 +267,64 @@ static int netlbl_calipso_listall(struct sk_buff *skb,
return skb->len;
 }
 
+/**
+ * netlbl_calipso_remove_cb - netlbl_calipso_remove() callback for REMOVE
+ * @entry: LSM domain mapping entry
+ * @arg: the netlbl_domhsh_walk_arg structure
+ *
+ * Description:
+ * This function is intended for use by netlbl_calipso_remove() as the callback
+ * for the netlbl_domhsh_walk() function; it removes LSM domain map entries
+ * which are associated with the CALIPSO DOI specified in @arg.  Returns zero 
on
+ * success, negative values on failure.
+ *
+ */
+static int netlbl_calipso_remove_cb(struct netlbl_dom_map *entry, void *arg)
+{
+   struct netlbl_domhsh_walk_arg *cb_arg = arg;
+
+   if (entry->def.type == NETLBL_NLTYPE_CALIPSO &&
+   entry->def.calipso->doi == cb_arg->doi)
+   return netlbl_domhsh_remove_entry(entry, cb_arg->audit_info);
+
+   return 0;
+}
+
+/**
+ * netlbl_calipso_remove - Handle a REMOVE message
+ * @skb: the NETLINK buffer
+ * @info: the Generic NETLINK info block
+ *
+ * Description:
+ * Process a user generated REMOVE message and respond accordingly.  Returns
+ * zero on success, negative values on failure.
+ *
+ */
+static int 

[RFC PATCH 10/17] calipso: Set the calipso socket label to match the secattr.

2015-12-22 Thread Huw Davies
CALIPSO is a hop-by-hop IPv6 option.  A lot of this patch is based on
the equivalent CISPO code.  The main difference is due to manipulating
the options in the hop-by-hop header.

Signed-off-by: Huw Davies 
---
 include/net/ipv6.h  |   2 +
 include/net/netlabel.h  |   9 +
 include/uapi/linux/in6.h|   1 +
 net/ipv6/calipso.c  | 592 
 net/ipv6/ipv6_sockglue.c|   1 -
 net/netlabel/Kconfig|   1 +
 net/netlabel/netlabel_calipso.c |  64 +
 net/netlabel/netlabel_calipso.h |   5 +
 net/netlabel/netlabel_kapi.c|  64 -
 security/selinux/netlabel.c |   2 +-
 10 files changed, 730 insertions(+), 11 deletions(-)

diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 5a72ffd..5f9c252 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -315,6 +315,8 @@ struct ipv6_txoptions *ipv6_fixup_options(struct 
ipv6_txoptions *opt_space,
 
 bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb,
   const struct inet6_skb_parm *opt);
+struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
+  struct ipv6_txoptions *opt);
 
 static inline bool ipv6_accept_ra(struct inet6_dev *idev)
 {
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index e6ac0da..b7ec76c 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -226,6 +226,9 @@ struct netlbl_lsm_secattr {
  * @doi_getdef: returns a reference to a DOI
  * @doi_putdef: releases a reference of a DOI
  * @doi_walk: enumerate the DOI list
+ * @sock_getattr: retrieve the socket's attr
+ * @sock_setattr: set the socket's attr
+ * @sock_delattr: remove the socket's attr
  *
  * Description:
  * This structure is filled out by the CALIPSO engine and passed
@@ -243,6 +246,12 @@ struct netlbl_calipso_ops {
int (*doi_walk)(u32 *skip_cnt,
int (*callback)(struct calipso_doi *doi_def, void *arg),
void *cb_arg);
+   int (*sock_getattr)(struct sock *sk,
+   struct netlbl_lsm_secattr *secattr);
+   int (*sock_setattr)(struct sock *sk,
+   const struct calipso_doi *doi_def,
+   const struct netlbl_lsm_secattr *secattr);
+   void (*sock_delattr)(struct sock *sk);
 };
 
 /*
diff --git a/include/uapi/linux/in6.h b/include/uapi/linux/in6.h
index 79b12b0..65d7192 100644
--- a/include/uapi/linux/in6.h
+++ b/include/uapi/linux/in6.h
@@ -143,6 +143,7 @@ struct in6_flowlabel_req {
 #define IPV6_TLV_PAD1  0
 #define IPV6_TLV_PADN  1
 #define IPV6_TLV_ROUTERALERT   5
+#define IPV6_TLV_CALIPSO   7   /* RFC 5570 */
 #define IPV6_TLV_JUMBO 194
 #define IPV6_TLV_HAO   201 /* home address option */
 
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index d7df7a4..ce803e2 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -44,6 +44,17 @@
 #include 
 #include 
 #include 
+#include 
+
+/* Maximium size of the calipso option including
+ * the two-byte TLV header.
+ */
+#define CALIPSO_OPT_LEN_MAX (2 + 252)
+
+/* Size of the minimum calipso option including
+ * the two-byte TLV header.
+ */
+#define CALIPSO_HDR_LEN (2 + 8)
 
 /* List of available DOI definitions */
 static DEFINE_SPINLOCK(calipso_doi_list_lock);
@@ -297,6 +308,584 @@ doi_walk_return:
return ret_val;
 }
 
+/**
+ * calipso_map_cat_hton - Perform a category mapping from host to network
+ * @doi_def: the DOI definition
+ * @secattr: the security attributes
+ * @net_cat: the zero'd out category bitmap in network/CIPSO format
+ * @net_cat_len: the length of the CALIPSO bitmap in bytes
+ *
+ * Description:
+ * Perform a label mapping to translate a local MLS category bitmap to the
+ * correct CIPSO bitmap using the given DOI definition.  Returns the minimum
+ * size in bytes of the network bitmap on success, negative values otherwise.
+ *
+ */
+static int calipso_map_cat_hton(const struct calipso_doi *doi_def,
+   const struct netlbl_lsm_secattr *secattr,
+   unsigned char *net_cat,
+   u32 net_cat_len)
+{
+   int spot = -1;
+   u32 net_spot_max = 0;
+   u32 net_clen_bits = net_cat_len * 8;
+
+   for (;;) {
+   spot = netlbl_catmap_walk(secattr->attr.mls.cat,
+ spot + 1);
+   if (spot < 0)
+   break;
+   if (spot >= net_clen_bits)
+   return -ENOSPC;
+   netlbl_bitmap_setbit(net_cat, spot, 1);
+
+   if (spot > net_spot_max)
+   net_spot_max = spot;
+   }
+
+   return (net_spot_max / 32 + 1) * 4;
+}
+
+/**
+ * calipso_map_cat_ntoh - Perform a category mapping from network to host
+ * @doi_def: the DOI definition
+ * @net_cat: the category bitmap in 

[RFC PATCH 17/17] calipso: Add a label cache.

2015-12-22 Thread Huw Davies
This works in exactly the same way as the CIPSO label cache.
The idea is to allow the lsm to cache the result of a secattr
lookup so that it doesn't need to perform the lookup for
every skbuff.

It introduces two sysctl controls:
 calipso_cache_enable - enables/disables the cache.
 calipso_cache_bucket_size - sets the size of a cache bucket.

Signed-off-by: Huw Davies 
---
 include/net/calipso.h   |   6 +
 include/net/netlabel.h  |   9 +-
 net/ipv6/calipso.c  | 264 +++-
 net/ipv6/sysctl_net_ipv6.c  |  19 +++
 net/netlabel/netlabel_calipso.c |  38 ++
 net/netlabel/netlabel_calipso.h |   3 +
 net/netlabel/netlabel_kapi.c|  24 +++-
 security/selinux/netlabel.c |   9 +-
 8 files changed, 360 insertions(+), 12 deletions(-)

diff --git a/include/net/calipso.h b/include/net/calipso.h
index 99df89b..dac6302 100644
--- a/include/net/calipso.h
+++ b/include/net/calipso.h
@@ -62,6 +62,12 @@ struct calipso_doi {
struct rcu_head rcu;
 };
 
+/*
+ * Sysctl Variables
+ */
+extern int calipso_cache_enabled;
+extern int calipso_cache_bucketsize;
+
 #ifdef CONFIG_NETLABEL
 int __init calipso_init(void);
 void calipso_exit(void);
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 1aed135..61e9c78 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -235,6 +235,8 @@ struct netlbl_lsm_secattr {
  * @getattr: retrieve attr from memory block
  * @skbuff_setattr: set the skbuff's attr
  * @skbuff_delattr: remove the skbuff's attr
+ * @cache_invalidate: invalidate cache
+ * @cache_add: add cache entry
  *
  * Description:
  * This structure is filled out by the CALIPSO engine and passed
@@ -269,6 +271,9 @@ struct netlbl_calipso_ops {
  const struct calipso_doi *doi_def,
  const struct netlbl_lsm_secattr *secattr);
int (*skbuff_delattr)(struct sk_buff *skb);
+   void (*cache_invalidate)(void);
+   int (*cache_add)(const unsigned char *calipso_ptr,
+const struct netlbl_lsm_secattr *secattr);
 };
 
 /*
@@ -494,7 +499,7 @@ void netlbl_skbuff_err(struct sk_buff *skb, u16 family, int 
error, int gateway);
  * LSM label mapping cache operations
  */
 void netlbl_cache_invalidate(void);
-int netlbl_cache_add(const struct sk_buff *skb,
+int netlbl_cache_add(const struct sk_buff *skb, u16 family,
 const struct netlbl_lsm_secattr *secattr);
 
 /*
@@ -647,7 +652,7 @@ static inline void netlbl_cache_invalidate(void)
 {
return;
 }
-static inline int netlbl_cache_add(const struct sk_buff *skb,
+static inline int netlbl_cache_add(const struct sk_buff *skb, u16 family,
   const struct netlbl_lsm_secattr *secattr)
 {
return 0;
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index f3b7c43..61979ee 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -66,6 +66,255 @@
 static DEFINE_SPINLOCK(calipso_doi_list_lock);
 static LIST_HEAD(calipso_doi_list);
 
+/* Label mapping cache */
+int calipso_cache_enabled = 1;
+int calipso_cache_bucketsize = 10;
+#define CALIPSO_CACHE_BUCKETBITS 7
+#define CALIPSO_CACHE_BUCKETSBIT(CALIPSO_CACHE_BUCKETBITS)
+#define CALIPSO_CACHE_REORDERLIMIT   10
+struct calipso_map_cache_bkt {
+   spinlock_t lock;
+   u32 size;
+   struct list_head list;
+};
+
+struct calipso_map_cache_entry {
+   u32 hash;
+   unsigned char *key;
+   size_t key_len;
+
+   struct netlbl_lsm_cache *lsm_data;
+
+   u32 activity;
+   struct list_head list;
+};
+
+static struct calipso_map_cache_bkt *calipso_cache;
+
+/* Label Mapping Cache Functions
+ */
+
+/**
+ * calipso_cache_entry_free - Frees a cache entry
+ * @entry: the entry to free
+ *
+ * Description:
+ * This function frees the memory associated with a cache entry including the
+ * LSM cache data if there are no longer any users, i.e. reference count == 0.
+ *
+ */
+static void calipso_cache_entry_free(struct calipso_map_cache_entry *entry)
+{
+   if (entry->lsm_data)
+   netlbl_secattr_cache_free(entry->lsm_data);
+   kfree(entry->key);
+   kfree(entry);
+}
+
+/**
+ * calipso_map_cache_hash - Hashing function for the CALIPSO cache
+ * @key: the hash key
+ * @key_len: the length of the key in bytes
+ *
+ * Description:
+ * The CALIPSO tag hashing function.  Returns a 32-bit hash value.
+ *
+ */
+static u32 calipso_map_cache_hash(const unsigned char *key, u32 key_len)
+{
+   return jhash(key, key_len, 0);
+}
+
+/**
+ * calipso_cache_init - Initialize the CALIPSO cache
+ *
+ * Description:
+ * Initializes the CALIPSO label mapping cache, this function should be called
+ * before any of the other functions defined in this file.  Returns zero on
+ * success, negative values on error.
+ *
+ */
+static int __init calipso_cache_init(void)
+{
+   u32 iter;
+
+   calipso_cache = 

[RFC PATCH 02/17] netlabel: Add an address family to domain hash entries.

2015-12-22 Thread Huw Davies
The reason is to allow different labelling protocols for
different address families with the same domain.

This requires the addition of an address family attribute
in the netlink communication protocol.  It is used in several
messages:

NLBL_MGMT_C_ADD and NLBL_MGMT_C_ADDDEF take it as an optional
attribute for the unlabelled protocol.  It may be one of AF_INET,
AF_INET6 and AF_UNSPEC (to specify both address families).  If is
it missing, it defaults to AF_UNSPEC.

NLBL_MGMT_C_LISTALL and NLBL_MGMT_C_LISTDEF return it as part of
the enumeration of each item.  Addtionally, it may be sent to
LISTDEF to specify which address family to return.

Signed-off-by: Huw Davies 
---
 net/netlabel/netlabel_domainhash.c | 173 -
 net/netlabel/netlabel_domainhash.h |   8 +-
 net/netlabel/netlabel_kapi.c   |   6 +-
 net/netlabel/netlabel_mgmt.c   |  29 ++-
 net/netlabel/netlabel_mgmt.h   |  24 +++--
 net/netlabel/netlabel_unlabeled.c  |   1 +
 6 files changed, 186 insertions(+), 55 deletions(-)

diff --git a/net/netlabel/netlabel_domainhash.c 
b/net/netlabel/netlabel_domainhash.c
index d4d6640..b14a1ed 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -56,7 +56,8 @@ static DEFINE_SPINLOCK(netlbl_domhsh_lock);
 #define netlbl_domhsh_rcu_deref(p) \
rcu_dereference_check(p, lockdep_is_held(_domhsh_lock))
 static struct netlbl_domhsh_tbl __rcu *netlbl_domhsh;
-static struct netlbl_dom_map __rcu *netlbl_domhsh_def;
+static struct netlbl_dom_map __rcu *netlbl_domhsh_def_ipv4;
+static struct netlbl_dom_map __rcu *netlbl_domhsh_def_ipv6;
 
 /*
  * Domain Hash Table Helper Functions
@@ -126,18 +127,26 @@ static u32 netlbl_domhsh_hash(const char *key)
return val & (netlbl_domhsh_rcu_deref(netlbl_domhsh)->size - 1);
 }
 
+static bool netlbl_family_match(u16 f1, u16 f2)
+{
+   return (f1 == f2) || (f1 == AF_UNSPEC) || (f2 == AF_UNSPEC);
+}
+
 /**
  * netlbl_domhsh_search - Search for a domain entry
  * @domain: the domain
+ * @family: the address family
  *
  * Description:
  * Searches the domain hash table and returns a pointer to the hash table
- * entry if found, otherwise NULL is returned.  The caller is responsible for
+ * entry if found, otherwise NULL is returned.  @family may be %AF_UNSPEC
+ * which matches any address family entries.  The caller is responsible for
  * ensuring that the hash table is protected with either a RCU read lock or the
  * hash table lock.
  *
  */
-static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain)
+static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain,
+  u16 family)
 {
u32 bkt;
struct list_head *bkt_list;
@@ -147,7 +156,9 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const 
char *domain)
bkt = netlbl_domhsh_hash(domain);
bkt_list = _domhsh_rcu_deref(netlbl_domhsh)->tbl[bkt];
list_for_each_entry_rcu(iter, bkt_list, list)
-   if (iter->valid && strcmp(iter->domain, domain) == 0)
+   if (iter->valid &&
+   netlbl_family_match(iter->family, family) &&
+   strcmp(iter->domain, domain) == 0)
return iter;
}
 
@@ -157,25 +168,35 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const 
char *domain)
 /**
  * netlbl_domhsh_search_def - Search for a domain entry
  * @domain: the domain
- * @def: return default if no match is found
+ * @family: the address family
  *
  * Description:
  * Searches the domain hash table and returns a pointer to the hash table
  * entry if an exact match is found, if an exact match is not present in the
  * hash table then the default entry is returned if valid otherwise NULL is
- * returned.  The caller is responsible ensuring that the hash table is
+ * returned.  @family may be %AF_UNSPEC which matches any address family
+ * entries.  The caller is responsible ensuring that the hash table is
  * protected with either a RCU read lock or the hash table lock.
  *
  */
-static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain)
+static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain,
+  u16 family)
 {
struct netlbl_dom_map *entry;
 
-   entry = netlbl_domhsh_search(domain);
+   entry = netlbl_domhsh_search(domain, family);
if (entry == NULL) {
-   entry = netlbl_domhsh_rcu_deref(netlbl_domhsh_def);
-   if (entry != NULL && !entry->valid)
-   entry = NULL;
+   if (family == AF_INET || family == AF_UNSPEC) {
+   entry = netlbl_domhsh_rcu_deref(netlbl_domhsh_def_ipv4);
+   if (entry != NULL && !entry->valid)
+   entry = NULL;
+ 

[RFC PATCH 06/17] netlabel: Add support for creating a CALIPSO protocol domain mapping.

2015-12-22 Thread Huw Davies
This extends the NLBL_MGMT_C_ADD and NLBL_MGMT_C_ADDDEF commands
to accept CALIPSO protocol DOIs.

Signed-off-by: Huw Davies 
---
 net/netlabel/netlabel_domainhash.c | 40 +--
 net/netlabel/netlabel_domainhash.h |  1 +
 net/netlabel/netlabel_mgmt.c   | 48 --
 net/netlabel/netlabel_mgmt.h   |  3 +++
 4 files changed, 88 insertions(+), 4 deletions(-)

diff --git a/net/netlabel/netlabel_domainhash.c 
b/net/netlabel/netlabel_domainhash.c
index b14a1ed..85abfb4 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -37,10 +37,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "netlabel_mgmt.h"
 #include "netlabel_addrlist.h"
+#include "netlabel_calipso.h"
 #include "netlabel_domainhash.h"
 #include "netlabel_user.h"
 
@@ -224,6 +226,7 @@ static void netlbl_domhsh_audit_add(struct netlbl_dom_map 
*entry,
 {
struct audit_buffer *audit_buf;
struct cipso_v4_doi *cipsov4 = NULL;
+   struct calipso_doi *calipso = NULL;
u32 type;
 
audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info);
@@ -242,12 +245,14 @@ static void netlbl_domhsh_audit_add(struct netlbl_dom_map 
*entry,
struct netlbl_domaddr6_map *map6;
map6 = netlbl_domhsh_addr6_entry(addr6);
type = map6->def.type;
+   calipso = map6->def.calipso;
netlbl_af6list_audit_addr(audit_buf, 0, NULL,
  >addr, >mask);
 #endif /* IPv6 */
} else {
type = entry->def.type;
cipsov4 = entry->def.cipso;
+   calipso = entry->def.calipso;
}
switch (type) {
case NETLBL_NLTYPE_UNLABELED:
@@ -259,6 +264,12 @@ static void netlbl_domhsh_audit_add(struct netlbl_dom_map 
*entry,
 " nlbl_protocol=cipsov4 cipso_doi=%u",
 cipsov4->doi);
break;
+   case NETLBL_NLTYPE_CALIPSO:
+   BUG_ON(calipso == NULL);
+   audit_log_format(audit_buf,
+" nlbl_protocol=calipso 
calipso_doi=%u",
+calipso->doi);
+   break;
}
audit_log_format(audit_buf, " res=%u", result == 0 ? 1 : 0);
audit_log_end(audit_buf);
@@ -300,6 +311,11 @@ static int netlbl_domhsh_validate(const struct 
netlbl_dom_map *entry)
entry->def.cipso == NULL)
return -EINVAL;
break;
+   case NETLBL_NLTYPE_CALIPSO:
+   if (entry->family != AF_INET6 ||
+   entry->def.calipso == NULL)
+   return -EINVAL;
+   break;
case NETLBL_NLTYPE_ADDRSELECT:
netlbl_af4list_foreach(iter4, >def.addrsel->list4) {
map4 = netlbl_domhsh_addr4_entry(iter4);
@@ -321,6 +337,12 @@ static int netlbl_domhsh_validate(const struct 
netlbl_dom_map *entry)
map6 = netlbl_domhsh_addr6_entry(iter6);
switch (map6->def.type) {
case NETLBL_NLTYPE_UNLABELED:
+   if (map6->def.calipso != NULL)
+   return -EINVAL;
+   break;
+   case NETLBL_NLTYPE_CALIPSO:
+   if (map6->def.calipso == NULL)
+   return -EINVAL;
break;
default:
return -EINVAL;
@@ -596,6 +618,10 @@ int netlbl_domhsh_remove_entry(struct netlbl_dom_map 
*entry,
if (ret_val == 0) {
struct netlbl_af4list *iter4;
struct netlbl_domaddr4_map *map4;
+#if IS_ENABLED(CONFIG_IPV6)
+   struct netlbl_af6list *iter6;
+   struct netlbl_domaddr6_map *map6;
+#endif /* IPv6 */
 
switch (entry->def.type) {
case NETLBL_NLTYPE_ADDRSELECT:
@@ -604,12 +630,22 @@ int netlbl_domhsh_remove_entry(struct netlbl_dom_map 
*entry,
map4 = netlbl_domhsh_addr4_entry(iter4);
cipso_v4_doi_putdef(map4->def.cipso);
}
-   /* no need to check the IPv6 list since we currently
-* support only unlabeled protocols for IPv6 */
+#if IS_ENABLED(CONFIG_IPV6)
+   netlbl_af6list_foreach_rcu(iter6,
+>def.addrsel->list6) {
+   map6 = netlbl_domhsh_addr6_entry(iter6);
+ 

[RFC PATCH 11/17] netlabel: Prevent setsockopt() from changing the hop-by-hop option.

2015-12-22 Thread Huw Davies
If a socket has a netlabel in place then don't let setsockopt() alter
the socket's IPv6 hop-by-hop option.  This is in the same spirit as
the existing check for IPv4.

Signed-off-by: Huw Davies 
---
 security/selinux/netlabel.c | 17 -
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 5470f32..2477a75 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -410,6 +410,21 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct 
*sksec,
 }
 
 /**
+ * selinux_netlbl_option - Is this a NetLabel option
+ * @level: the socket level or protocol
+ * @optname: the socket option name
+ *
+ * Description:
+ * Returns true if @level and @optname refer to a NetLabel option.
+ * Helper for selinux_netlbl_socket_setsockopt().
+ */
+static inline int selinux_netlbl_option(int level, int optname)
+{
+   return (level == IPPROTO_IP && optname == IP_OPTIONS) ||
+   (level == IPPROTO_IPV6 && optname == IPV6_HOPOPTS);
+}
+
+/**
  * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
  * @sock: the socket
  * @level: the socket level or protocol
@@ -431,7 +446,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
struct sk_security_struct *sksec = sk->sk_security;
struct netlbl_lsm_secattr secattr;
 
-   if (level == IPPROTO_IP && optname == IP_OPTIONS &&
+   if (selinux_netlbl_option(level, optname) &&
(sksec->nlbl_state == NLBL_LABELED ||
 sksec->nlbl_state == NLBL_CONNLABELED)) {
netlbl_secattr_init();
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 05/17] netlabel: Add support for enumerating the CALIPSO DOI list.

2015-12-22 Thread Huw Davies
Enumerate the DOI list through the NLBL_CALIPSO_C_LISTALL command.
It takes no attributes.

Signed-off-by: Huw Davies 
---
 include/net/netlabel.h  |   4 ++
 net/ipv6/calipso.c  |  41 
 net/netlabel/netlabel_calipso.c | 106 
 net/netlabel/netlabel_calipso.h |   3 ++
 4 files changed, 154 insertions(+)

diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index e072350..c6e1ce9 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -225,6 +225,7 @@ struct netlbl_lsm_secattr {
  * @doi_free: free a CALIPSO DOI
  * @doi_getdef: returns a reference to a DOI
  * @doi_putdef: releases a reference of a DOI
+ * @doi_walk: enumerate the DOI list
  *
  * Description:
  * This structure is filled out by the CALIPSO engine and passed
@@ -238,6 +239,9 @@ struct netlbl_calipso_ops {
void (*doi_free)(struct calipso_doi *doi_def);
struct calipso_doi *(*doi_getdef)(u32 doi);
void (*doi_putdef)(struct calipso_doi *doi_def);
+   int (*doi_walk)(u32 *skip_cnt,
+   int (*callback)(struct calipso_doi *doi_def, void *arg),
+   void *cb_arg);
 };
 
 /*
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index 128cc69..fa17c7a 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -210,11 +210,52 @@ static void calipso_doi_putdef(struct calipso_doi 
*doi_def)
call_rcu(_def->rcu, calipso_doi_free_rcu);
 }
 
+/**
+ * calipso_doi_walk - Iterate through the DOI definitions
+ * @skip_cnt: skip past this number of DOI definitions, updated
+ * @callback: callback for each DOI definition
+ * @cb_arg: argument for the callback function
+ *
+ * Description:
+ * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
+ * For each entry call @callback, if @callback returns a negative value stop
+ * 'walking' through the list and return.  Updates the value in @skip_cnt upon
+ * return.  Returns zero on success, negative values on failure.
+ *
+ */
+static int calipso_doi_walk(u32 *skip_cnt,
+   int (*callback)(struct calipso_doi *doi_def,
+   void *arg),
+   void *cb_arg)
+{
+   int ret_val = -ENOENT;
+   u32 doi_cnt = 0;
+   struct calipso_doi *iter_doi;
+
+   rcu_read_lock();
+   list_for_each_entry_rcu(iter_doi, _doi_list, list)
+   if (atomic_read(_doi->refcount) > 0) {
+   if (doi_cnt++ < *skip_cnt)
+   continue;
+   ret_val = callback(iter_doi, cb_arg);
+   if (ret_val < 0) {
+   doi_cnt--;
+   goto doi_walk_return;
+   }
+   }
+
+doi_walk_return:
+   rcu_read_unlock();
+   *skip_cnt = doi_cnt;
+   return ret_val;
+}
+
 static const struct netlbl_calipso_ops ops = {
.doi_add  = calipso_doi_add,
.doi_free = calipso_doi_free,
.doi_getdef   = calipso_doi_getdef,
.doi_putdef   = calipso_doi_putdef,
+   .doi_walk = calipso_doi_walk,
 };
 
 /**
diff --git a/net/netlabel/netlabel_calipso.c b/net/netlabel/netlabel_calipso.c
index 1effc61..a014ec2 100644
--- a/net/netlabel/netlabel_calipso.c
+++ b/net/netlabel/netlabel_calipso.c
@@ -46,6 +46,13 @@
 #include "netlabel_mgmt.h"
 #include "netlabel_domainhash.h"
 
+/* Argument struct for calipso_doi_walk() */
+struct netlbl_calipso_doiwalk_arg {
+   struct netlink_callback *nl_cb;
+   struct sk_buff *skb;
+   u32 seq;
+};
+
 /* NetLabel Generic NETLINK CALIPSO family */
 static struct genl_family netlbl_calipso_gnl_family = {
.id = GENL_ID_GENERATE,
@@ -187,6 +194,73 @@ list_failure:
return ret_val;
 }
 
+/**
+ * netlbl_calipso_listall_cb - calipso_v4_doi_walk() callback for LISTALL
+ * @doi_def: the CALIPSO DOI definition
+ * @arg: the netlbl_calipso_doiwalk_arg structure
+ *
+ * Description:
+ * This function is designed to be used as a callback to the
+ * calipso_doi_walk() function for use in generating a response for a LISTALL
+ * message.  Returns the size of the message on success, negative values on
+ * failure.
+ *
+ */
+static int netlbl_calipso_listall_cb(struct calipso_doi *doi_def, void *arg)
+{
+   int ret_val = -ENOMEM;
+   struct netlbl_calipso_doiwalk_arg *cb_arg = arg;
+   void *data;
+
+   data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
+  cb_arg->seq, _calipso_gnl_family,
+  NLM_F_MULTI, NLBL_CALIPSO_C_LISTALL);
+   if (!data)
+   goto listall_cb_failure;
+
+   ret_val = nla_put_u32(cb_arg->skb, NLBL_CALIPSO_A_DOI, doi_def->doi);
+   if (ret_val != 0)
+   goto listall_cb_failure;
+   ret_val = nla_put_u32(cb_arg->skb,
+

Re: [PATCH v2 1/2] crypto: KEYS: convert public key to the akcipher api

2015-12-22 Thread Herbert Xu
On Mon, Dec 21, 2015 at 12:59:59PM -0800, Tadeusz Struk wrote:
> 
> The previous patch was broken, re-sending again, sorry.
> 
> I think there is something missing in this configuration.
> cat .config | grep KEXEC_BZIMAGE_VERIFY_SIG gives nothing.
> Anyways, this patch should fix it.

No this is unacceptable.  Please fix it properly by making the
header file self-contained, e.g., by using a forward declaration.

Cheers,
-- 
Email: Herbert Xu 
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1 5/7] ima: measure and appraise firmware (improvement)

2015-12-22 Thread Mimi Zohar
On Mon, 2015-12-21 at 22:44 +0100, Luis R. Rodriguez wrote:
> 
> Eventually, once we generalize a common read perhaps we should stuff this
> into VFS common code and provide arguments to enable callers to provide 
> restrictions or requirements. Let's work together on that after the holidays.
> 
> Let's consolidate notes here:
> 
> http://kernelnewbies.org/KernelProjects/common-kernel-loader

Sounds good!

Mimi


--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 14/17] calipso: Allow the lsm to label the skbuff directly.

2015-12-22 Thread Huw Davies
In some cases, the lsm needs to add the label to the skbuff directly.
A NF_INET_LOCAL_OUT IPv6 hook is added to selinux to match the IPv4
behaviour.  This allows selinux to label the skbuffs that it requires.

Signed-off-by: Huw Davies 
---
 include/net/ipv6.h  |   2 +-
 include/net/netlabel.h  |  11 +++
 net/ipv6/calipso.c  | 180 
 net/ipv6/exthdrs_core.c |   2 +-
 net/netlabel/netlabel_calipso.c |  82 ++
 net/netlabel/netlabel_calipso.h |   7 ++
 net/netlabel/netlabel_kapi.c|  32 ++-
 security/selinux/hooks.c|  15 
 8 files changed, 325 insertions(+), 6 deletions(-)

diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 5f9c252..71b5045 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -920,7 +920,7 @@ enum {
 int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target,
  unsigned short *fragoff, int *fragflg);
 
-int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
+int ipv6_find_tlv(const struct sk_buff *skb, int offset, int type);
 
 struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
const struct ipv6_txoptions *opt,
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 771a11c..d88bf4a 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -231,6 +231,10 @@ struct netlbl_lsm_secattr {
  * @sock_delattr: remove the socket's attr
  * @req_setattr: set the req socket's attr
  * @req_delattr: remove the req socket's attr
+ * @optptr: find option in packet
+ * @getattr: retrieve attr from memory block
+ * @skbuff_setattr: set the skbuff's attr
+ * @skbuff_delattr: remove the skbuff's attr
  *
  * Description:
  * This structure is filled out by the CALIPSO engine and passed
@@ -258,6 +262,13 @@ struct netlbl_calipso_ops {
   const struct calipso_doi *doi_def,
   const struct netlbl_lsm_secattr *secattr);
void (*req_delattr)(struct request_sock *req);
+   unsigned char *(*optptr)(const struct sk_buff *skb);
+   int (*getattr)(const unsigned char *calipso,
+  struct netlbl_lsm_secattr *secattr);
+   int (*skbuff_setattr)(struct sk_buff *skb,
+ const struct calipso_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr);
+   int (*skbuff_delattr)(struct sk_buff *skb);
 };
 
 /*
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index 5d72669..a91d71d 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -56,6 +56,12 @@
  */
 #define CALIPSO_HDR_LEN (2 + 8)
 
+ /* Maximium size of u32 aligned buffer required to hold calipso
+  * option.  Max of 3 initial pad bytes starting from buffer + 3.
+  * i.e. the worst case is when the previous tlv finishes on 4n + 3.
+  */
+#define CALIPSO_MAX_BUFFER (6 + CALIPSO_OPT_LEN_MAX)
+
 /* List of available DOI definitions */
 static DEFINE_SPINLOCK(calipso_doi_list_lock);
 static LIST_HEAD(calipso_doi_list);
@@ -962,6 +968,176 @@ static void calipso_req_delattr(struct request_sock *req)
kfree(new);
 }
 
+/* skbuff functions.
+ */
+
+/**
+ * calipso_optptr - Find the CALIPSO option in the packet
+ * @skb: the packet
+ *
+ * Description:
+ * Parse the packet's IP header looking for a CALIPSO option.  Returns a 
pointer
+ * to the start of the CALIPSO option on success, NULL if one if not found.
+ *
+ */
+static unsigned char *calipso_optptr(const struct sk_buff *skb)
+{
+   const struct ipv6hdr *ip6_hdr = ipv6_hdr(skb);
+   int offset;
+
+   if (ip6_hdr->nexthdr != NEXTHDR_HOP)
+   return NULL;
+
+   offset = ipv6_find_tlv(skb, sizeof(*ip6_hdr), IPV6_TLV_CALIPSO);
+   if (offset >= 0)
+   return (unsigned char *)ip6_hdr + offset;
+
+   return NULL;
+}
+
+/**
+ * calipso_skbuff_setattr - Set the CALIPSO option on a packet
+ * @skb: the packet
+ * @doi_def: the CALIPSO DOI to use
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Set the CALIPSO option on the given packet based on the security attributes.
+ * Returns a pointer to the IP header on success and NULL on failure.
+ *
+ */
+static int calipso_skbuff_setattr(struct sk_buff *skb,
+ const struct calipso_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr)
+{
+   int ret_val;
+   struct ipv6hdr *ip6_hdr;
+   struct ipv6_opt_hdr *hop;
+   unsigned char buf[CALIPSO_MAX_BUFFER];
+   int len_delta;
+   unsigned int start, end, next_opt, pad;
+
+   ip6_hdr = ipv6_hdr(skb);
+   if (ip6_hdr->nexthdr == NEXTHDR_HOP) {
+   hop = (struct ipv6_opt_hdr *)(ip6_hdr + 1);
+   ret_val = calipso_opt_find(hop, , );
+   if (ret_val && ret_val != -ENOENT)
+   return ret_val;
+   if (end != 

[RFC PATCH 09/17] netlabel: Move bitmap manipulation functions to the NetLabel core.

2015-12-22 Thread Huw Davies
This is to allow the CALIPSO labelling engine to use these.

Signed-off-by: Huw Davies 
---
 include/net/netlabel.h   |  6 +++
 net/ipv4/cipso_ipv4.c| 88 +---
 net/netlabel/netlabel_kapi.c | 70 +++
 3 files changed, 85 insertions(+), 79 deletions(-)

diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 0ffe32f..e6ac0da 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -434,6 +434,12 @@ int netlbl_catmap_setlong(struct netlbl_lsm_catmap 
**catmap,
  unsigned long bitmap,
  gfp_t flags);
 
+/* Bitmap functions
+ */
+int netlbl_bitmap_walk(const unsigned char *bitmap, u32 bitmap_len,
+  u32 offset, u8 state);
+void netlbl_bitmap_setbit(unsigned char *bitmap, u32 bit, u8 state);
+
 /*
  * LSM protocol operations (NetLabel LSM/kernel API)
  */
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index bdb2a07..d710d4e 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -135,76 +135,6 @@ int cipso_v4_rbm_strictvalid = 1;
  */
 
 /**
- * cipso_v4_bitmap_walk - Walk a bitmap looking for a bit
- * @bitmap: the bitmap
- * @bitmap_len: length in bits
- * @offset: starting offset
- * @state: if non-zero, look for a set (1) bit else look for a cleared (0) bit
- *
- * Description:
- * Starting at @offset, walk the bitmap from left to right until either the
- * desired bit is found or we reach the end.  Return the bit offset, -1 if
- * not found, or -2 if error.
- */
-static int cipso_v4_bitmap_walk(const unsigned char *bitmap,
-   u32 bitmap_len,
-   u32 offset,
-   u8 state)
-{
-   u32 bit_spot;
-   u32 byte_offset;
-   unsigned char bitmask;
-   unsigned char byte;
-
-   /* gcc always rounds to zero when doing integer division */
-   byte_offset = offset / 8;
-   byte = bitmap[byte_offset];
-   bit_spot = offset;
-   bitmask = 0x80 >> (offset % 8);
-
-   while (bit_spot < bitmap_len) {
-   if ((state && (byte & bitmask) == bitmask) ||
-   (state == 0 && (byte & bitmask) == 0))
-   return bit_spot;
-
-   bit_spot++;
-   bitmask >>= 1;
-   if (bitmask == 0) {
-   byte = bitmap[++byte_offset];
-   bitmask = 0x80;
-   }
-   }
-
-   return -1;
-}
-
-/**
- * cipso_v4_bitmap_setbit - Sets a single bit in a bitmap
- * @bitmap: the bitmap
- * @bit: the bit
- * @state: if non-zero, set the bit (1) else clear the bit (0)
- *
- * Description:
- * Set a single bit in the bitmask.  Returns zero on success, negative values
- * on error.
- */
-static void cipso_v4_bitmap_setbit(unsigned char *bitmap,
-  u32 bit,
-  u8 state)
-{
-   u32 byte_spot;
-   u8 bitmask;
-
-   /* gcc always rounds to zero when doing integer division */
-   byte_spot = bit / 8;
-   bitmask = 0x80 >> (bit % 8);
-   if (state)
-   bitmap[byte_spot] |= bitmask;
-   else
-   bitmap[byte_spot] &= ~bitmask;
-}
-
-/**
  * cipso_v4_cache_entry_free - Frees a cache entry
  * @entry: the entry to free
  *
@@ -840,10 +770,10 @@ static int cipso_v4_map_cat_rbm_valid(const struct 
cipso_v4_doi *doi_def,
cipso_cat_size = doi_def->map.std->cat.cipso_size;
cipso_array = doi_def->map.std->cat.cipso;
for (;;) {
-   cat = cipso_v4_bitmap_walk(bitmap,
-  bitmap_len_bits,
-  cat + 1,
-  1);
+   cat = netlbl_bitmap_walk(bitmap,
+bitmap_len_bits,
+cat + 1,
+1);
if (cat < 0)
break;
if (cat >= cipso_cat_size ||
@@ -909,7 +839,7 @@ static int cipso_v4_map_cat_rbm_hton(const struct 
cipso_v4_doi *doi_def,
}
if (net_spot >= net_clen_bits)
return -ENOSPC;
-   cipso_v4_bitmap_setbit(net_cat, net_spot, 1);
+   netlbl_bitmap_setbit(net_cat, net_spot, 1);
 
if (net_spot > net_spot_max)
net_spot_max = net_spot;
@@ -951,10 +881,10 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct 
cipso_v4_doi *doi_def,
}
 
for (;;) {
-   net_spot = cipso_v4_bitmap_walk(net_cat,
-   net_clen_bits,
-   net_spot + 1,
-   

Re: [RFC PATCH 16/17] calipso: Add validation of CALIPSO option.

2015-12-22 Thread Huw Davies
On Tue, Dec 22, 2015 at 02:50:20PM +0100, Hannes Frederic Sowa wrote:
> On 22.12.2015 12:46, Huw Davies wrote:
> >  
> > +/* CALIPSO RFC 5570 */
> > +
> > +static bool ipv6_hop_calipso(struct sk_buff *skb, int optoff)
> > +{
> > +   const unsigned char *nh = skb_network_header(skb);
> > +
> > +   if (nh[optoff + 1] < 8)
> > +   goto drop;
> > +
> > +   if (nh[optoff + 6] * 4 + 8 > nh[optoff + 1])
> > +   goto drop;
> > +
> > +   if (!calipso_validate(skb, nh + optoff))
> > +   goto drop;
> > +
> > +   return true;
> > +
> > +drop:
> > +   kfree_skb(skb);
> > +   return false;
> > +}
> > +
> 
> Formally, if an extension header could not be processed, the packet
> should be discarded and an icmp error parameter extension should be
> send. I think we shouldn't let those packets pass here.

Thanks for your comments Hannes, I'm looking into your other
suggestions.

I'm confused about this one.  AFAICS, this will drop packets that we
can't process.  We don't send the icmp error, but I can certainly add
that.  Is that what you mean?

Thanks,
Huw.
--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] IMA: policy can be updated zero times

2015-12-22 Thread Sasha Levin
Commit "IMA: policy can now be updated multiple times" assumed that the
policy would be updated at least once.

If there are zero updates, the temporary list head object will get added
to the policy list, and later dereferenced as an IMA policy object, which
means that invalid memory will be accessed.

Signed-off-by: Sasha Levin 
---
 security/integrity/ima/ima_policy.c |3 +++
 1 file changed, 3 insertions(+)

diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index ba5d2fc..9b958b8 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -431,6 +431,9 @@ void ima_update_policy(void)
 {
struct list_head *first, *last, *policy;
 
+   if (list_empty(_temp_rules))
+   return;
+
/* append current policy with the new rules */
first = (_temp_rules)->next;
last = (_temp_rules)->prev;
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH 08/17] ipv6: Add ipv6_renew_options_kern() that accepts a kernel mem pointer.

2015-12-22 Thread Hannes Frederic Sowa
On 22.12.2015 12:46, Huw Davies wrote:
> The functionality is equivalent to ipv6_renew_options() except
> that the newopt pointer is in kernel, not user, memory
> 
> The kernel memory implementation will be used by the CALIPSO network
> labelling engine, which needs to be able to set IPv6 hop-by-hop
> options.
> 
> Signed-off-by: Huw Davies 
> ---
>  include/net/ipv6.h |   6 +++
>  net/ipv6/exthdrs.c | 131 
> -
>  2 files changed, 125 insertions(+), 12 deletions(-)
> 
> diff --git a/include/net/ipv6.h b/include/net/ipv6.h
> index 9a5c9f0..5a72ffd 100644
> --- a/include/net/ipv6.h
> +++ b/include/net/ipv6.h
> @@ -304,6 +304,12 @@ struct ipv6_txoptions *ipv6_renew_options(struct sock 
> *sk,
> int newtype,
> struct ipv6_opt_hdr __user *newopt,
> int newoptlen);
> +struct ipv6_txoptions *
> +ipv6_renew_options_kern(struct sock *sk,
> + struct ipv6_txoptions *opt,
> + int newtype,
> + struct ipv6_opt_hdr *newopt,
> + int newoptlen);
>  struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
> struct ipv6_txoptions *opt);
>  
> diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
> index ea7c4d6..9426b26 100644
> --- a/net/ipv6/exthdrs.c
> +++ b/net/ipv6/exthdrs.c
> @@ -734,11 +734,16 @@ ipv6_dup_options(struct sock *sk, struct ipv6_txoptions 
> *opt)
>  EXPORT_SYMBOL_GPL(ipv6_dup_options);
>  
>  static int ipv6_renew_option(void *ohdr,
> -  struct ipv6_opt_hdr __user *newopt, int newoptlen,
> +  struct ipv6_opt_hdr __user *newopt_user,
> +  struct ipv6_opt_hdr *newopt,
> +  int newoptlen,
>int inherit,
>struct ipv6_opt_hdr **hdr,
>char **p)


This looks quite ugly to me.

Wouldn't it be possible to do something like this:


ipv6_renew_option_kern(...)
{
int ret;
const mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
ret = ipv6_renew_option(...); // maybe you need to forcefully cast the
user away here
set_fs(old_fs);
return ret;
}

Bye,
Hannes

--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH 16/17] calipso: Add validation of CALIPSO option.

2015-12-22 Thread Hannes Frederic Sowa
On 22.12.2015 12:46, Huw Davies wrote:
>  
> +/* CALIPSO RFC 5570 */
> +
> +static bool ipv6_hop_calipso(struct sk_buff *skb, int optoff)
> +{
> + const unsigned char *nh = skb_network_header(skb);
> +
> + if (nh[optoff + 1] < 8)
> + goto drop;
> +
> + if (nh[optoff + 6] * 4 + 8 > nh[optoff + 1])
> + goto drop;
> +
> + if (!calipso_validate(skb, nh + optoff))
> + goto drop;
> +
> + return true;
> +
> +drop:
> + kfree_skb(skb);
> + return false;
> +}
> +

Formally, if an extension header could not be processed, the packet
should be discarded and an icmp error parameter extension should be
send. I think we shouldn't let those packets pass here.

Thanks,
Hannes

--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/2] crypto: KEYS: convert public key to the akcipher api

2015-12-22 Thread Tadeusz Struk
Hi Herbert
On 12/22/2015 04:09 AM, Herbert Xu wrote:
> On Mon, Dec 21, 2015 at 12:59:59PM -0800, Tadeusz Struk wrote:
>>
>> The previous patch was broken, re-sending again, sorry.
>>
>> I think there is something missing in this configuration.
>> cat .config | grep KEXEC_BZIMAGE_VERIFY_SIG gives nothing.
>> Anyways, this patch should fix it.
> 
> No this is unacceptable.  Please fix it properly by making the
> header file self-contained, e.g., by using a forward declaration.

What about the first two. This one is completely unrelated.
It only supposed to fix some random configuration issue
reported by a build robot, which isn't really important now.
The other two convert the module verifier to the new API.
Thanks,
-- 
TS
--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH 13/17] calipso: Allow request sockets to be relabelled by the lsm.

2015-12-22 Thread Hannes Frederic Sowa
On 22.12.2015 12:46, Huw Davies wrote:
>   tot_len += sizeof(*opt2);
> - opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
> + if (sk)
> + opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
> + else
> + opt2 = kmalloc(tot_len, GFP_ATOMIC);
>   if (!opt2)
>   return ERR_PTR(-ENOBUFS);

This change looks dangerous to me in terms of control of memory
depletion from a remote host. Could you use sk_to_full_sk and account
options towards the listener socket?

--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH 00/17] CALIPSO implementation

2015-12-22 Thread Huw Davies
On Tue, Dec 22, 2015 at 09:28:37AM -0800, Casey Schaufler wrote:
> On 12/22/2015 3:46 AM, Huw Davies wrote:
> > This patch series implements RFC 5570 - Common Architecture Label IPv6
> > Security Option (CALIPSO).  Its goal is to set MLS sensitivity labels
> > on IPv6 packets using a hop-by-hop option.  CALIPSO very similar to
> > its IPv4 cousin CIPSO and much of this series is based on that code.
> 
> There's a one line change to the Smack code in 15/17 due to
> a change in the api, but I assume that there has been no
> attempt to verify that this works with Smack. It's not 100%
> clear that this won't break a Smack kernel, but I haven't
> tried it.

That's correct, I've not looked into Smack at all.  I'll
see if I can figure out what's needed.

Huw.
--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 2/2] integrity: convert digsig to akcipher api

2015-12-22 Thread Tadeusz Struk
Convert asymmetric_verify to akcipher api.

Signed-off-by: Tadeusz Struk 
---
 security/integrity/Kconfig |1 +
 security/integrity/digsig_asymmetric.c |   10 +++---
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 73c457b..f0b2463 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -36,6 +36,7 @@ config INTEGRITY_ASYMMETRIC_KEYS
 select ASYMMETRIC_KEY_TYPE
 select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
 select PUBLIC_KEY_ALGO_RSA
+select CRYPTO_RSA
 select X509_CERTIFICATE_PARSER
help
  This option enables digital signature verification using
diff --git a/security/integrity/digsig_asymmetric.c 
b/security/integrity/digsig_asymmetric.c
index 4fec181..5629372 100644
--- a/security/integrity/digsig_asymmetric.c
+++ b/security/integrity/digsig_asymmetric.c
@@ -92,13 +92,9 @@ int asymmetric_verify(struct key *keyring, const char *sig,
pks.pkey_hash_algo = hdr->hash_algo;
pks.digest = (u8 *)data;
pks.digest_size = datalen;
-   pks.nr_mpi = 1;
-   pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen);
-
-   if (pks.rsa.s)
-   ret = verify_signature(key, );
-
-   mpi_free(pks.rsa.s);
+   pks.s = hdr->sig;
+   pks.s_size = siglen;
+   ret = verify_signature(key, );
key_put(key);
pr_debug("%s() = %d\n", __func__, ret);
return ret;

--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 1/2] crypto: KEYS: convert public key to the akcipher api

2015-12-22 Thread Tadeusz Struk
This patch converts the module verification code to the new akcipher API.

Signed-off-by: Tadeusz Struk 
---
 crypto/asymmetric_keys/Kconfig|2 
 crypto/asymmetric_keys/Makefile   |7 -
 crypto/asymmetric_keys/pkcs7_parser.c |   12 +-
 crypto/asymmetric_keys/pkcs7_trust.c  |2 
 crypto/asymmetric_keys/pkcs7_verify.c |2 
 crypto/asymmetric_keys/public_key.c   |   64 +++--
 crypto/asymmetric_keys/public_key.h   |   36 -
 crypto/asymmetric_keys/rsa.c  |  213 +++--
 crypto/asymmetric_keys/x509_cert_parser.c |   37 +
 crypto/asymmetric_keys/x509_public_key.c  |   17 +-
 crypto/asymmetric_keys/x509_rsakey.asn1   |4 -
 include/crypto/public_key.h   |   48 +--
 12 files changed, 135 insertions(+), 309 deletions(-)
 delete mode 100644 crypto/asymmetric_keys/public_key.h
 delete mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1

diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 4870f28..905d745 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -22,7 +22,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
 
 config PUBLIC_KEY_ALGO_RSA
tristate "RSA public-key algorithm"
-   select MPILIB
+   select CRYPTO_RSA
help
  This option enables support for the RSA algorithm (PKCS#1, RFC3447).
 
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index cd1406f..b78a194 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -16,21 +16,18 @@ obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o
 x509_key_parser-y := \
x509-asn1.o \
x509_akid-asn1.o \
-   x509_rsakey-asn1.o \
x509_cert_parser.o \
x509_public_key.o
 
 $(obj)/x509_cert_parser.o: \
$(obj)/x509-asn1.h \
-   $(obj)/x509_akid-asn1.h \
-   $(obj)/x509_rsakey-asn1.h
+   $(obj)/x509_akid-asn1.h
+
 $(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h
 $(obj)/x509_akid-asn1.o: $(obj)/x509_akid-asn1.c $(obj)/x509_akid-asn1.h
-$(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h
 
 clean-files+= x509-asn1.c x509-asn1.h
 clean-files+= x509_akid-asn1.c x509_akid-asn1.h
-clean-files+= x509_rsakey-asn1.c x509_rsakey-asn1.h
 
 #
 # PKCS#7 message handling
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c 
b/crypto/asymmetric_keys/pkcs7_parser.c
index 758acab..12912c1 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.c
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -15,7 +15,7 @@
 #include 
 #include 
 #include 
-#include "public_key.h"
+#include 
 #include "pkcs7_parser.h"
 #include "pkcs7-asn1.h"
 
@@ -44,7 +44,7 @@ struct pkcs7_parse_context {
 static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
 {
if (sinfo) {
-   mpi_free(sinfo->sig.mpi[0]);
+   kfree(sinfo->sig.s);
kfree(sinfo->sig.digest);
kfree(sinfo->signing_cert_id);
kfree(sinfo);
@@ -616,16 +616,14 @@ int pkcs7_sig_note_signature(void *context, size_t hdrlen,
 const void *value, size_t vlen)
 {
struct pkcs7_parse_context *ctx = context;
-   MPI mpi;
 
BUG_ON(ctx->sinfo->sig.pkey_algo != PKEY_ALGO_RSA);
 
-   mpi = mpi_read_raw_data(value, vlen);
-   if (!mpi)
+   ctx->sinfo->sig.s = kmemdup(value, vlen, GFP_KERNEL);
+   if (!ctx->sinfo->sig.s)
return -ENOMEM;
 
-   ctx->sinfo->sig.mpi[0] = mpi;
-   ctx->sinfo->sig.nr_mpi = 1;
+   ctx->sinfo->sig.s_size = vlen;
return 0;
 }
 
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c 
b/crypto/asymmetric_keys/pkcs7_trust.c
index 90d6d47..3bbdcc7 100644
--- a/crypto/asymmetric_keys/pkcs7_trust.c
+++ b/crypto/asymmetric_keys/pkcs7_trust.c
@@ -17,7 +17,7 @@
 #include 
 #include 
 #include 
-#include "public_key.h"
+#include 
 #include "pkcs7_parser.h"
 
 /**
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c 
b/crypto/asymmetric_keys/pkcs7_verify.c
index 325575c..f5db137 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -16,7 +16,7 @@
 #include 
 #include 
 #include 
-#include "public_key.h"
+#include 
 #include "pkcs7_parser.h"
 
 /*
diff --git a/crypto/asymmetric_keys/public_key.c 
b/crypto/asymmetric_keys/public_key.c
index 6db4c01..b383629 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -18,24 +18,16 @@
 #include 
 #include 
 #include 
-#include "public_key.h"
+#include 
 
 MODULE_LICENSE("GPL");
 
 const char *const pkey_algo_name[PKEY_ALGO__LAST] = {
-   [PKEY_ALGO_DSA] = "DSA",
-   [PKEY_ALGO_RSA] = "RSA",
+   [PKEY_ALGO_DSA] = "dsa",
+   [PKEY_ALGO_RSA] = "rsa",
 };
 EXPORT_SYMBOL_GPL(pkey_algo_name);
 
-const struct public_key_algorithm 

[PATCH v3 0/2] crypto: KEYS: convert public key to akcipher api

2015-12-22 Thread Tadeusz Struk
This patch set converts the module verification and digital signature
code to the new akcipher API.
RSA implementation has been removed from crypto/asymmetric_keys and the
new API is used for cryptographic primitives.
There is no need for MPI above the akcipher API anymore.
Modules can be verified with software as well as HW RSA implementations.

Patches generated against cryptodev-2.6

Changes in v3:
- Don't include keys/asymmetric-type.h in crypto/public_key.h

Changes in v2:
- Fix the whey public_key_signature is setup. The pointer s needs to
  point to the signature instread of the signature_v2_hdr.  
- Select CRYPTO_RSA when INTEGRITY_ASYMMETRIC_KEYS is selected.

---

Tadeusz Struk (2):
  crypto: KEYS: convert public key to the akcipher api
  integrity: convert digsig to akcipher api

 crypto/asymmetric_keys/Kconfig|2 
 crypto/asymmetric_keys/Makefile   |7 -
 crypto/asymmetric_keys/pkcs7_parser.c |   12 +-
 crypto/asymmetric_keys/pkcs7_trust.c  |2 
 crypto/asymmetric_keys/pkcs7_verify.c |2 
 crypto/asymmetric_keys/public_key.c   |   64 +++--
 crypto/asymmetric_keys/public_key.h   |   36 -
 crypto/asymmetric_keys/rsa.c  |  213 +++--
 crypto/asymmetric_keys/x509_cert_parser.c |   37 +
 crypto/asymmetric_keys/x509_public_key.c  |   17 +-
 crypto/asymmetric_keys/x509_rsakey.asn1   |4 -
 include/crypto/public_key.h   |   48 ++-
 security/integrity/Kconfig|1 
 security/integrity/digsig_asymmetric.c|   10 -
 14 files changed, 139 insertions(+), 316 deletions(-)
 delete mode 100644 crypto/asymmetric_keys/public_key.h
 delete mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1

--
TS
--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html