Skip to content

Commit 04f81f0

Browse files
committed
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 971f10e ("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>
1 parent 6eb4e2b commit 04f81f0

File tree

3 files changed

+56
-35
lines changed

3 files changed

+56
-35
lines changed

include/net/cipso_ipv4.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,6 @@ extern int cipso_v4_rbm_optfmt;
120120
extern int cipso_v4_rbm_strictvalid;
121121
#endif
122122

123-
/*
124-
* Helper Functions
125-
*/
126-
127-
#define CIPSO_V4_OPTEXIST(x) (IPCB(x)->opt.cipso != 0)
128-
#define CIPSO_V4_OPTPTR(x) (skb_network_header(x) + IPCB(x)->opt.cipso)
129-
130123
/*
131124
* DOI List Functions
132125
*/
@@ -190,15 +183,15 @@ static inline int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
190183

191184
#ifdef CONFIG_NETLABEL
192185
void cipso_v4_cache_invalidate(void);
193-
int cipso_v4_cache_add(const struct sk_buff *skb,
186+
int cipso_v4_cache_add(const unsigned char *cipso_ptr,
194187
const struct netlbl_lsm_secattr *secattr);
195188
#else
196189
static inline void cipso_v4_cache_invalidate(void)
197190
{
198191
return;
199192
}
200193

201-
static inline int cipso_v4_cache_add(const struct sk_buff *skb,
194+
static inline int cipso_v4_cache_add(const unsigned char *cipso_ptr,
202195
const struct netlbl_lsm_secattr *secattr)
203196
{
204197
return 0;
@@ -211,6 +204,8 @@ static inline int cipso_v4_cache_add(const struct sk_buff *skb,
211204

212205
#ifdef CONFIG_NETLABEL
213206
void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
207+
int cipso_v4_getattr(const unsigned char *cipso,
208+
struct netlbl_lsm_secattr *secattr);
214209
int cipso_v4_sock_setattr(struct sock *sk,
215210
const struct cipso_v4_doi *doi_def,
216211
const struct netlbl_lsm_secattr *secattr);
@@ -226,6 +221,7 @@ int cipso_v4_skbuff_setattr(struct sk_buff *skb,
226221
int cipso_v4_skbuff_delattr(struct sk_buff *skb);
227222
int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
228223
struct netlbl_lsm_secattr *secattr);
224+
unsigned char *cipso_v4_optptr(const struct sk_buff *skb);
229225
int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option);
230226
#else
231227
static inline void cipso_v4_error(struct sk_buff *skb,
@@ -235,6 +231,12 @@ static inline void cipso_v4_error(struct sk_buff *skb,
235231
return;
236232
}
237233

234+
static inline int cipso_v4_getattr(const unsigned char *cipso,
235+
struct netlbl_lsm_secattr *secattr)
236+
{
237+
return -ENOSYS;
238+
}
239+
238240
static inline int cipso_v4_sock_setattr(struct sock *sk,
239241
const struct cipso_v4_doi *doi_def,
240242
const struct netlbl_lsm_secattr *secattr)
@@ -282,6 +284,11 @@ static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
282284
return -ENOSYS;
283285
}
284286

287+
static inline unsigned char *cipso_v4_optptr(const struct sk_buff *skb)
288+
{
289+
return NULL;
290+
}
291+
285292
static inline int cipso_v4_validate(const struct sk_buff *skb,
286293
unsigned char **option)
287294
{

net/ipv4/cipso_ipv4.c

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -378,20 +378,18 @@ static int cipso_v4_cache_check(const unsigned char *key,
378378
* negative values on failure.
379379
*
380380
*/
381-
int cipso_v4_cache_add(const struct sk_buff *skb,
381+
int cipso_v4_cache_add(const unsigned char *cipso_ptr,
382382
const struct netlbl_lsm_secattr *secattr)
383383
{
384384
int ret_val = -EPERM;
385385
u32 bkt;
386386
struct cipso_v4_map_cache_entry *entry = NULL;
387387
struct cipso_v4_map_cache_entry *old_entry = NULL;
388-
unsigned char *cipso_ptr;
389388
u32 cipso_ptr_len;
390389

391390
if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0)
392391
return 0;
393392

394-
cipso_ptr = CIPSO_V4_OPTPTR(skb);
395393
cipso_ptr_len = cipso_ptr[1];
396394

397395
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
@@ -1578,6 +1576,33 @@ static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def,
15781576
return 0;
15791577
}
15801578

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+
*/
1588+
unsigned 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+
15811606
/**
15821607
* cipso_v4_validate - Validate a CIPSO option
15831608
* @option: the start of the option, on error it is set to point to the error
@@ -2119,8 +2144,8 @@ void cipso_v4_req_delattr(struct request_sock *req)
21192144
* on success and negative values on failure.
21202145
*
21212146
*/
2122-
static int cipso_v4_getattr(const unsigned char *cipso,
2123-
struct netlbl_lsm_secattr *secattr)
2147+
int cipso_v4_getattr(const unsigned char *cipso,
2148+
struct netlbl_lsm_secattr *secattr)
21242149
{
21252150
int ret_val = -ENOMSG;
21262151
u32 doi;
@@ -2305,22 +2330,6 @@ int cipso_v4_skbuff_delattr(struct sk_buff *skb)
23052330
return 0;
23062331
}
23072332

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-
*/
2318-
int 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-
23242333
/*
23252334
* Setup Functions
23262335
*/

net/netlabel/netlabel_kapi.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,10 +1065,12 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
10651065
u16 family,
10661066
struct netlbl_lsm_secattr *secattr)
10671067
{
1068+
unsigned char *ptr;
1069+
10681070
switch (family) {
10691071
case AF_INET:
1070-
if (CIPSO_V4_OPTEXIST(skb) &&
1071-
cipso_v4_skbuff_getattr(skb, secattr) == 0)
1072+
ptr = cipso_v4_optptr(skb);
1073+
if (ptr && cipso_v4_getattr(ptr, secattr) == 0)
10721074
return 0;
10731075
break;
10741076
#if IS_ENABLED(CONFIG_IPV6)
@@ -1094,7 +1096,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
10941096
*/
10951097
void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway)
10961098
{
1097-
if (CIPSO_V4_OPTEXIST(skb))
1099+
if (cipso_v4_optptr(skb))
10981100
cipso_v4_error(skb, error, gateway);
10991101
}
11001102

@@ -1126,11 +1128,14 @@ void netlbl_cache_invalidate(void)
11261128
int netlbl_cache_add(const struct sk_buff *skb,
11271129
const struct netlbl_lsm_secattr *secattr)
11281130
{
1131+
unsigned char *ptr;
1132+
11291133
if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
11301134
return -ENOMSG;
11311135

1132-
if (CIPSO_V4_OPTEXIST(skb))
1133-
return cipso_v4_cache_add(skb, secattr);
1136+
ptr = cipso_v4_optptr(skb);
1137+
if (ptr)
1138+
return cipso_v4_cache_add(ptr, secattr);
11341139

11351140
return -ENOMSG;
11361141
}

0 commit comments

Comments
 (0)