projects
/
powerpc.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
NetLabel: add tag verification when adding new CIPSOv4 DOI definitions
[powerpc.git]
/
net
/
ipv4
/
cipso_ipv4.c
diff --git
a/net/ipv4/cipso_ipv4.c
b/net/ipv4/cipso_ipv4.c
index
a8e2e87
..
23a968f
100644
(file)
--- a/
net/ipv4/cipso_ipv4.c
+++ b/
net/ipv4/cipso_ipv4.c
@@
-43,6
+43,7
@@
#include <net/tcp.h>
#include <net/netlabel.h>
#include <net/cipso_ipv4.h>
#include <net/tcp.h>
#include <net/netlabel.h>
#include <net/cipso_ipv4.h>
+#include <asm/atomic.h>
#include <asm/bug.h>
struct cipso_v4_domhsh_entry {
#include <asm/bug.h>
struct cipso_v4_domhsh_entry {
@@
-79,7
+80,7
@@
struct cipso_v4_map_cache_entry {
unsigned char *key;
size_t key_len;
unsigned char *key;
size_t key_len;
- struct netlbl_lsm_cache lsm_data;
+ struct netlbl_lsm_cache
*
lsm_data;
u32 activity;
struct list_head list;
u32 activity;
struct list_head list;
@@
-188,13
+189,14
@@
static void cipso_v4_doi_domhsh_free(struct rcu_head *entry)
* @entry: the entry to free
*
* Description:
* @entry: the entry to free
*
* Description:
- * This function frees the memory associated with a cache entry.
+ * 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 cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry)
{
*
*/
static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry)
{
- if (entry->lsm_data
.free
)
-
entry->lsm_data.free(entry->lsm_data.
data);
+ if (entry->lsm_data)
+
netlbl_secattr_cache_free(entry->lsm_
data);
kfree(entry->key);
kfree(entry);
}
kfree(entry->key);
kfree(entry);
}
@@
-315,8
+317,9
@@
static int cipso_v4_cache_check(const unsigned char *key,
entry->key_len == key_len &&
memcmp(entry->key, key, key_len) == 0) {
entry->activity += 1;
entry->key_len == key_len &&
memcmp(entry->key, key, key_len) == 0) {
entry->activity += 1;
- secattr->cache.free = entry->lsm_data.free;
- secattr->cache.data = entry->lsm_data.data;
+ atomic_inc(&entry->lsm_data->refcount);
+ secattr->cache = entry->lsm_data;
+ secattr->flags |= NETLBL_SECATTR_CACHE;
if (prev_entry == NULL) {
spin_unlock_bh(&cipso_v4_cache[bkt].lock);
return 0;
if (prev_entry == NULL) {
spin_unlock_bh(&cipso_v4_cache[bkt].lock);
return 0;
@@
-375,16
+378,15
@@
int cipso_v4_cache_add(const struct sk_buff *skb,
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
if (entry == NULL)
return -ENOMEM;
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
if (entry == NULL)
return -ENOMEM;
- entry->key = km
alloc(
cipso_ptr_len, GFP_ATOMIC);
+ entry->key = km
emdup(cipso_ptr,
cipso_ptr_len, GFP_ATOMIC);
if (entry->key == NULL) {
ret_val = -ENOMEM;
goto cache_add_failure;
}
if (entry->key == NULL) {
ret_val = -ENOMEM;
goto cache_add_failure;
}
- memcpy(entry->key, cipso_ptr, cipso_ptr_len);
entry->key_len = cipso_ptr_len;
entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
entry->key_len = cipso_ptr_len;
entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
-
entry->lsm_data.free = secattr->cache.free
;
- entry->lsm_data
.data = secattr->cache.data
;
+
atomic_inc(&secattr->cache->refcount)
;
+ entry->lsm_data
= secattr->cache
;
bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
spin_lock_bh(&cipso_v4_cache[bkt].lock);
bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
spin_lock_bh(&cipso_v4_cache[bkt].lock);
@@
-445,8
+447,22
@@
static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
*/
int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
{
*/
int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
{
+ u32 iter;
+
if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN)
return -EINVAL;
if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN)
return -EINVAL;
+ for (iter = 0; iter < CIPSO_V4_TAG_MAXCNT; iter++) {
+ switch (doi_def->tags[iter]) {
+ case CIPSO_V4_TAG_RBITMAP:
+ break;
+ case CIPSO_V4_TAG_INVALID:
+ if (iter == 0)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
doi_def->valid = 1;
INIT_RCU_HEAD(&doi_def->rcu);
doi_def->valid = 1;
INIT_RCU_HEAD(&doi_def->rcu);
@@
-771,13
+787,15
@@
static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
{
int cat = -1;
u32 bitmap_len_bits = bitmap_len * 8;
{
int cat = -1;
u32 bitmap_len_bits = bitmap_len * 8;
- u32 cipso_cat_size
= doi_def->map.std->cat.cipso_size
;
- u32 *cipso_array
= doi_def->map.std->cat.cipso
;
+ u32 cipso_cat_size;
+ u32 *cipso_array;
switch (doi_def->type) {
case CIPSO_V4_MAP_PASS:
return 0;
case CIPSO_V4_MAP_STD:
switch (doi_def->type) {
case CIPSO_V4_MAP_PASS:
return 0;
case CIPSO_V4_MAP_STD:
+ 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,
for (;;) {
cat = cipso_v4_bitmap_walk(bitmap,
bitmap_len_bits,
@@
-823,19
+841,21
@@
static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
u32 net_spot_max = 0;
u32 host_clen_bits = host_cat_len * 8;
u32 net_clen_bits = net_cat_len * 8;
u32 net_spot_max = 0;
u32 host_clen_bits = host_cat_len * 8;
u32 net_clen_bits = net_cat_len * 8;
- u32 host_cat_size
= doi_def->map.std->cat.local_size
;
- u32 *host_cat_array
= doi_def->map.std->cat.local
;
+ u32 host_cat_size;
+ u32 *host_cat_array;
switch (doi_def->type) {
case CIPSO_V4_MAP_PASS:
switch (doi_def->type) {
case CIPSO_V4_MAP_PASS:
- net_spot_max = host_cat_len
- 1
;
- while (net_spot_max > 0 && host_cat[net_spot_max] == 0)
+ net_spot_max = host_cat_len;
+ while (net_spot_max > 0 && host_cat[net_spot_max
- 1
] == 0)
net_spot_max--;
if (net_spot_max > net_cat_len)
return -EINVAL;
memcpy(net_cat, host_cat, net_spot_max);
return net_spot_max;
case CIPSO_V4_MAP_STD:
net_spot_max--;
if (net_spot_max > net_cat_len)
return -EINVAL;
memcpy(net_cat, host_cat, net_spot_max);
return net_spot_max;
case CIPSO_V4_MAP_STD:
+ host_cat_size = doi_def->map.std->cat.local_size;
+ host_cat_array = doi_def->map.std->cat.local;
for (;;) {
host_spot = cipso_v4_bitmap_walk(host_cat,
host_clen_bits,
for (;;) {
host_spot = cipso_v4_bitmap_walk(host_cat,
host_clen_bits,
@@
-891,8
+911,8
@@
static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
int net_spot = -1;
u32 net_clen_bits = net_cat_len * 8;
u32 host_clen_bits = host_cat_len * 8;
int net_spot = -1;
u32 net_clen_bits = net_cat_len * 8;
u32 host_clen_bits = host_cat_len * 8;
- u32 net_cat_size
= doi_def->map.std->cat.cipso_size
;
- u32 *net_cat_array
= doi_def->map.std->cat.cipso
;
+ u32 net_cat_size;
+ u32 *net_cat_array;
switch (doi_def->type) {
case CIPSO_V4_MAP_PASS:
switch (doi_def->type) {
case CIPSO_V4_MAP_PASS:
@@
-901,6
+921,8
@@
static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
memcpy(host_cat, net_cat, net_cat_len);
return net_cat_len;
case CIPSO_V4_MAP_STD:
memcpy(host_cat, net_cat, net_cat_len);
return net_cat_len;
case CIPSO_V4_MAP_STD:
+ net_cat_size = doi_def->map.std->cat.cipso_size;
+ net_cat_array = doi_def->map.std->cat.cipso;
for (;;) {
net_spot = cipso_v4_bitmap_walk(net_cat,
net_clen_bits,
for (;;) {
net_spot = cipso_v4_bitmap_walk(net_cat,
net_clen_bits,
@@
-958,7
+980,7
@@
static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
buf[0] = IPOPT_CIPSO;
buf[1] = CIPSO_V4_HDR_LEN + len;
buf[0] = IPOPT_CIPSO;
buf[1] = CIPSO_V4_HDR_LEN + len;
- *(
u
32 *)&buf[2] = htonl(doi_def->doi);
+ *(
__be
32 *)&buf[2] = htonl(doi_def->doi);
return 0;
}
return 0;
}
@@
-984,12
+1006,15
@@
static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
unsigned char **buffer,
u32 *buffer_len)
{
unsigned char **buffer,
u32 *buffer_len)
{
- int ret_val
= -EPERM
;
+ int ret_val;
unsigned char *buf = NULL;
u32 buf_len;
u32 level;
unsigned char *buf = NULL;
u32 buf_len;
u32 level;
- if (secattr->mls_cat) {
+ if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0)
+ return -EPERM;
+
+ if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN,
GFP_ATOMIC);
if (buf == NULL)
buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN,
GFP_ATOMIC);
if (buf == NULL)
@@
-1006,10
+1031,10
@@
static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
/* This will send packets using the "optimized" format when
* possibile as specified in section 3.4.2.6 of the
* CIPSO draft. */
/* This will send packets using the "optimized" format when
* possibile as specified in section 3.4.2.6 of the
* CIPSO draft. */
- if (cipso_v4_rbm_optfmt &&
(ret_val > 0 && ret_val < 10)
)
-
ret_val = 10
;
-
- buf_len = 4 + ret_val;
+ if (cipso_v4_rbm_optfmt &&
ret_val > 0 && ret_val <= 10
)
+
buf_len = 14
;
+ else
+
buf_len = 4 + ret_val;
} else {
buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC);
if (buf == NULL)
} else {
buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC);
if (buf == NULL)
@@
-1063,7
+1088,7
@@
static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
if (ret_val != 0)
return ret_val;
secattr->mls_lvl = level;
if (ret_val != 0)
return ret_val;
secattr->mls_lvl = level;
- secattr->
mls_lvl_vld = 1
;
+ secattr->
flags |= NETLBL_SECATTR_MLS_LVL
;
if (tag_len > 4) {
switch (doi_def->type) {
if (tag_len > 4) {
switch (doi_def->type) {
@@
-1087,8
+1112,10
@@
static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
if (ret_val < 0) {
kfree(secattr->mls_cat);
return ret_val;
if (ret_val < 0) {
kfree(secattr->mls_cat);
return ret_val;
+ } else if (ret_val > 0) {
+ secattr->mls_cat_len = ret_val;
+ secattr->flags |= NETLBL_SECATTR_MLS_CAT;
}
}
- secattr->mls_cat_len = ret_val;
}
return 0;
}
return 0;
@@
-1132,7
+1159,7
@@
int cipso_v4_validate(unsigned char **option)
}
rcu_read_lock();
}
rcu_read_lock();
- doi_def = cipso_v4_doi_getdef(ntohl(*((
u
32 *)&opt[2])));
+ doi_def = cipso_v4_doi_getdef(ntohl(*((
__be
32 *)&opt[2])));
if (doi_def == NULL) {
err_offset = 2;
goto validate_return_locked;
if (doi_def == NULL) {
err_offset = 2;
goto validate_return_locked;
@@
-1299,7
+1326,8
@@
int cipso_v4_socket_setattr(const struct socket *sock,
/* We can't use ip_options_get() directly because it makes a call to
* ip_options_get_alloc() which allocates memory with GFP_KERNEL and
/* We can't use ip_options_get() directly because it makes a call to
* ip_options_get_alloc() which allocates memory with GFP_KERNEL and
- * we can't block here. */
+ * we won't always have CAP_NET_RAW even though we _always_ want to
+ * set the IPOPT_CIPSO option. */
opt_len = (buf_len + 3) & ~3;
opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
if (opt == NULL) {
opt_len = (buf_len + 3) & ~3;
opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
if (opt == NULL) {
@@
-1309,11
+1337,9
@@
int cipso_v4_socket_setattr(const struct socket *sock,
memcpy(opt->__data, buf, buf_len);
opt->optlen = opt_len;
opt->is_data = 1;
memcpy(opt->__data, buf, buf_len);
opt->optlen = opt_len;
opt->is_data = 1;
+ opt->cipso = sizeof(struct iphdr);
kfree(buf);
buf = NULL;
kfree(buf);
buf = NULL;
- ret_val = ip_options_compile(opt, NULL);
- if (ret_val != 0)
- goto socket_setattr_failure;
sk_inet = inet_sk(sk);
if (sk_inet->is_icsk) {
sk_inet = inet_sk(sk);
if (sk_inet->is_icsk) {
@@
-1363,7
+1389,7
@@
int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
if (ret_val == 0)
return ret_val;
if (ret_val == 0)
return ret_val;
- doi = ntohl(*(
u
32 *)&cipso_ptr[2]);
+ doi = ntohl(*(
__be
32 *)&cipso_ptr[2]);
rcu_read_lock();
doi_def = cipso_v4_doi_getdef(doi);
if (doi_def == NULL) {
rcu_read_lock();
doi_def = cipso_v4_doi_getdef(doi);
if (doi_def == NULL) {
@@
-1423,13
+1449,11
@@
int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
u32 doi;
struct cipso_v4_doi *doi_def;
u32 doi;
struct cipso_v4_doi *doi_def;
- if (!CIPSO_V4_OPTEXIST(skb))
- return -ENOMSG;
cipso_ptr = CIPSO_V4_OPTPTR(skb);
if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0)
return 0;
cipso_ptr = CIPSO_V4_OPTPTR(skb);
if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0)
return 0;
- doi = ntohl(*(
u
32 *)&cipso_ptr[2]);
+ doi = ntohl(*(
__be
32 *)&cipso_ptr[2]);
rcu_read_lock();
doi_def = cipso_v4_doi_getdef(doi);
if (doi_def == NULL)
rcu_read_lock();
doi_def = cipso_v4_doi_getdef(doi);
if (doi_def == NULL)