aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2015-02-11 14:46:37 -0500
committerPaul Moore <pmoore@redhat.com>2015-02-11 14:46:37 -0500
commit04f81f0154e4bf002be6f4d85668ce1257efa4d9 (patch)
tree6572c58a65fe65aa738419e43e45e59c32538357 /net
parent6eb4e2b41b264f57ee02d16ee61683952945484d (diff)
cipso: don't use IPCB() to locate the CIPSO IP option
Using the IPCB() macro to get the IPv4 options is convenient, but unfortunately NetLabel often needs to examine the CIPSO option outside of the scope of the IP layer in the stack. While historically IPCB() worked above the IP layer, due to the inclusion of the inet_skb_param struct at the head of the {tcp,udp}_skb_cb structs, recent commit 971f10ec ("tcp: better TCP_SKB_CB layout to reduce cache line misses") reordered the tcp_skb_cb struct and invalidated this IPCB() trick. This patch fixes the problem by creating a new function, cipso_v4_optptr(), which locates the CIPSO option inside the IP header without calling IPCB(). Unfortunately, this isn't as fast as a simple lookup so some additional tweaks were made to limit the use of this new function. Cc: <stable@vger.kernel.org> # 3.18 Reported-by: Casey Schaufler <casey@schaufler-ca.com> Signed-off-by: Paul Moore <pmoore@redhat.com> Tested-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/cipso_ipv4.c51
-rw-r--r--net/netlabel/netlabel_kapi.c15
2 files changed, 40 insertions, 26 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 5160c710f2eb..e361ea6f3fc8 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -378,20 +378,18 @@ static int cipso_v4_cache_check(const unsigned char *key,
378 * negative values on failure. 378 * negative values on failure.
379 * 379 *
380 */ 380 */
381int cipso_v4_cache_add(const struct sk_buff *skb, 381int cipso_v4_cache_add(const unsigned char *cipso_ptr,
382 const struct netlbl_lsm_secattr *secattr) 382 const struct netlbl_lsm_secattr *secattr)
383{ 383{
384 int ret_val = -EPERM; 384 int ret_val = -EPERM;
385 u32 bkt; 385 u32 bkt;
386 struct cipso_v4_map_cache_entry *entry = NULL; 386 struct cipso_v4_map_cache_entry *entry = NULL;
387 struct cipso_v4_map_cache_entry *old_entry = NULL; 387 struct cipso_v4_map_cache_entry *old_entry = NULL;
388 unsigned char *cipso_ptr;
389 u32 cipso_ptr_len; 388 u32 cipso_ptr_len;
390 389
391 if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0) 390 if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0)
392 return 0; 391 return 0;
393 392
394 cipso_ptr = CIPSO_V4_OPTPTR(skb);
395 cipso_ptr_len = cipso_ptr[1]; 393 cipso_ptr_len = cipso_ptr[1];
396 394
397 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 395 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
@@ -1579,6 +1577,33 @@ static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def,
1579} 1577}
1580 1578
1581/** 1579/**
1580 * cipso_v4_optptr - Find the CIPSO option in the packet
1581 * @skb: the packet
1582 *
1583 * Description:
1584 * Parse the packet's IP header looking for a CIPSO option. Returns a pointer
1585 * to the start of the CIPSO option on success, NULL if one if not found.
1586 *
1587 */
1588unsigned char *cipso_v4_optptr(const struct sk_buff *skb)
1589{
1590 const struct iphdr *iph = ip_hdr(skb);
1591 unsigned char *optptr = (unsigned char *)&(ip_hdr(skb)[1]);
1592 int optlen;
1593 int taglen;
1594
1595 for (optlen = iph->ihl*4 - sizeof(struct iphdr); optlen > 0; ) {
1596 if (optptr[0] == IPOPT_CIPSO)
1597 return optptr;
1598 taglen = optptr[1];
1599 optlen -= taglen;
1600 optptr += taglen;
1601 }
1602
1603 return NULL;
1604}
1605
1606/**
1582 * cipso_v4_validate - Validate a CIPSO option 1607 * cipso_v4_validate - Validate a CIPSO option
1583 * @option: the start of the option, on error it is set to point to the error 1608 * @option: the start of the option, on error it is set to point to the error
1584 * 1609 *
@@ -2119,8 +2144,8 @@ void cipso_v4_req_delattr(struct request_sock *req)
2119 * on success and negative values on failure. 2144 * on success and negative values on failure.
2120 * 2145 *
2121 */ 2146 */
2122static int cipso_v4_getattr(const unsigned char *cipso, 2147int cipso_v4_getattr(const unsigned char *cipso,
2123 struct netlbl_lsm_secattr *secattr) 2148 struct netlbl_lsm_secattr *secattr)
2124{ 2149{
2125 int ret_val = -ENOMSG; 2150 int ret_val = -ENOMSG;
2126 u32 doi; 2151 u32 doi;
@@ -2305,22 +2330,6 @@ int cipso_v4_skbuff_delattr(struct sk_buff *skb)
2305 return 0; 2330 return 0;
2306} 2331}
2307 2332
2308/**
2309 * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
2310 * @skb: the packet
2311 * @secattr: the security attributes
2312 *
2313 * Description:
2314 * Parse the given packet's CIPSO option and return the security attributes.
2315 * Returns zero on success and negative values on failure.
2316 *
2317 */
2318int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
2319 struct netlbl_lsm_secattr *secattr)
2320{
2321 return cipso_v4_getattr(CIPSO_V4_OPTPTR(skb), secattr);
2322}
2323
2324/* 2333/*
2325 * Setup Functions 2334 * Setup Functions
2326 */ 2335 */
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index a845cd4cf21e..28cddc85b700 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -1065,10 +1065,12 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
1065 u16 family, 1065 u16 family,
1066 struct netlbl_lsm_secattr *secattr) 1066 struct netlbl_lsm_secattr *secattr)
1067{ 1067{
1068 unsigned char *ptr;
1069
1068 switch (family) { 1070 switch (family) {
1069 case AF_INET: 1071 case AF_INET:
1070 if (CIPSO_V4_OPTEXIST(skb) && 1072 ptr = cipso_v4_optptr(skb);
1071 cipso_v4_skbuff_getattr(skb, secattr) == 0) 1073 if (ptr && cipso_v4_getattr(ptr, secattr) == 0)
1072 return 0; 1074 return 0;
1073 break; 1075 break;
1074#if IS_ENABLED(CONFIG_IPV6) 1076#if IS_ENABLED(CONFIG_IPV6)
@@ -1094,7 +1096,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
1094 */ 1096 */
1095void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway) 1097void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway)
1096{ 1098{
1097 if (CIPSO_V4_OPTEXIST(skb)) 1099 if (cipso_v4_optptr(skb))
1098 cipso_v4_error(skb, error, gateway); 1100 cipso_v4_error(skb, error, gateway);
1099} 1101}
1100 1102
@@ -1126,11 +1128,14 @@ void netlbl_cache_invalidate(void)
1126int netlbl_cache_add(const struct sk_buff *skb, 1128int netlbl_cache_add(const struct sk_buff *skb,
1127 const struct netlbl_lsm_secattr *secattr) 1129 const struct netlbl_lsm_secattr *secattr)
1128{ 1130{
1131 unsigned char *ptr;
1132
1129 if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0) 1133 if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
1130 return -ENOMSG; 1134 return -ENOMSG;
1131 1135
1132 if (CIPSO_V4_OPTEXIST(skb)) 1136 ptr = cipso_v4_optptr(skb);
1133 return cipso_v4_cache_add(skb, secattr); 1137 if (ptr)
1138 return cipso_v4_cache_add(ptr, secattr);
1134 1139
1135 return -ENOMSG; 1140 return -ENOMSG;
1136} 1141}