aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/cipso_ipv4.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/cipso_ipv4.c')
-rw-r--r--net/ipv4/cipso_ipv4.c267
1 files changed, 65 insertions, 202 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 80a2a0911b49..e6ce0b3ba62a 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -259,7 +259,7 @@ void cipso_v4_cache_invalidate(void)
259 u32 iter; 259 u32 iter;
260 260
261 for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) { 261 for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) {
262 spin_lock(&cipso_v4_cache[iter].lock); 262 spin_lock_bh(&cipso_v4_cache[iter].lock);
263 list_for_each_entry_safe(entry, 263 list_for_each_entry_safe(entry,
264 tmp_entry, 264 tmp_entry,
265 &cipso_v4_cache[iter].list, list) { 265 &cipso_v4_cache[iter].list, list) {
@@ -267,7 +267,7 @@ void cipso_v4_cache_invalidate(void)
267 cipso_v4_cache_entry_free(entry); 267 cipso_v4_cache_entry_free(entry);
268 } 268 }
269 cipso_v4_cache[iter].size = 0; 269 cipso_v4_cache[iter].size = 0;
270 spin_unlock(&cipso_v4_cache[iter].lock); 270 spin_unlock_bh(&cipso_v4_cache[iter].lock);
271 } 271 }
272 272
273 return; 273 return;
@@ -309,7 +309,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
309 309
310 hash = cipso_v4_map_cache_hash(key, key_len); 310 hash = cipso_v4_map_cache_hash(key, key_len);
311 bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); 311 bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
312 spin_lock(&cipso_v4_cache[bkt].lock); 312 spin_lock_bh(&cipso_v4_cache[bkt].lock);
313 list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) { 313 list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) {
314 if (entry->hash == hash && 314 if (entry->hash == hash &&
315 entry->key_len == key_len && 315 entry->key_len == key_len &&
@@ -318,7 +318,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
318 secattr->cache.free = entry->lsm_data.free; 318 secattr->cache.free = entry->lsm_data.free;
319 secattr->cache.data = entry->lsm_data.data; 319 secattr->cache.data = entry->lsm_data.data;
320 if (prev_entry == NULL) { 320 if (prev_entry == NULL) {
321 spin_unlock(&cipso_v4_cache[bkt].lock); 321 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
322 return 0; 322 return 0;
323 } 323 }
324 324
@@ -333,12 +333,12 @@ static int cipso_v4_cache_check(const unsigned char *key,
333 &prev_entry->list); 333 &prev_entry->list);
334 } 334 }
335 335
336 spin_unlock(&cipso_v4_cache[bkt].lock); 336 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
337 return 0; 337 return 0;
338 } 338 }
339 prev_entry = entry; 339 prev_entry = entry;
340 } 340 }
341 spin_unlock(&cipso_v4_cache[bkt].lock); 341 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
342 342
343 return -ENOENT; 343 return -ENOENT;
344} 344}
@@ -387,7 +387,7 @@ int cipso_v4_cache_add(const struct sk_buff *skb,
387 entry->lsm_data.data = secattr->cache.data; 387 entry->lsm_data.data = secattr->cache.data;
388 388
389 bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); 389 bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
390 spin_lock(&cipso_v4_cache[bkt].lock); 390 spin_lock_bh(&cipso_v4_cache[bkt].lock);
391 if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) { 391 if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) {
392 list_add(&entry->list, &cipso_v4_cache[bkt].list); 392 list_add(&entry->list, &cipso_v4_cache[bkt].list);
393 cipso_v4_cache[bkt].size += 1; 393 cipso_v4_cache[bkt].size += 1;
@@ -398,7 +398,7 @@ int cipso_v4_cache_add(const struct sk_buff *skb,
398 list_add(&entry->list, &cipso_v4_cache[bkt].list); 398 list_add(&entry->list, &cipso_v4_cache[bkt].list);
399 cipso_v4_cache_entry_free(old_entry); 399 cipso_v4_cache_entry_free(old_entry);
400 } 400 }
401 spin_unlock(&cipso_v4_cache[bkt].lock); 401 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
402 402
403 return 0; 403 return 0;
404 404
@@ -530,197 +530,42 @@ struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
530} 530}
531 531
532/** 532/**
533 * cipso_v4_doi_dump_all - Dump all the CIPSO DOI definitions into a sk_buff 533 * cipso_v4_doi_walk - Iterate through the DOI definitions
534 * @headroom: the amount of headroom to allocate for the sk_buff 534 * @skip_cnt: skip past this number of DOI definitions, updated
535 * @callback: callback for each DOI definition
536 * @cb_arg: argument for the callback function
535 * 537 *
536 * Description: 538 * Description:
537 * Dump a list of all the configured DOI values into a sk_buff. The returned 539 * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
538 * sk_buff has room at the front of the sk_buff for @headroom bytes. See 540 * For each entry call @callback, if @callback returns a negative value stop
539 * net/netlabel/netlabel_cipso_v4.h for the LISTALL message format. This 541 * 'walking' through the list and return. Updates the value in @skip_cnt upon
540 * function may fail if another process is changing the DOI list at the same 542 * return. Returns zero on success, negative values on failure.
541 * time. Returns a pointer to a sk_buff on success, NULL on error.
542 * 543 *
543 */ 544 */
544struct sk_buff *cipso_v4_doi_dump_all(size_t headroom) 545int cipso_v4_doi_walk(u32 *skip_cnt,
546 int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
547 void *cb_arg)
545{ 548{
546 struct sk_buff *skb = NULL; 549 int ret_val = -ENOENT;
547 struct cipso_v4_doi *iter;
548 u32 doi_cnt = 0; 550 u32 doi_cnt = 0;
549 ssize_t buf_len; 551 struct cipso_v4_doi *iter_doi;
550 552
551 buf_len = NETLBL_LEN_U32;
552 rcu_read_lock(); 553 rcu_read_lock();
553 list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list) 554 list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list)
554 if (iter->valid) { 555 if (iter_doi->valid) {
555 doi_cnt += 1; 556 if (doi_cnt++ < *skip_cnt)
556 buf_len += 2 * NETLBL_LEN_U32; 557 continue;
557 } 558 ret_val = callback(iter_doi, cb_arg);
558 559 if (ret_val < 0) {
559 skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); 560 doi_cnt--;
560 if (skb == NULL) 561 goto doi_walk_return;
561 goto doi_dump_all_failure;
562
563 if (nla_put_u32(skb, NLA_U32, doi_cnt) != 0)
564 goto doi_dump_all_failure;
565 buf_len -= NETLBL_LEN_U32;
566 list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
567 if (iter->valid) {
568 if (buf_len < 2 * NETLBL_LEN_U32)
569 goto doi_dump_all_failure;
570 if (nla_put_u32(skb, NLA_U32, iter->doi) != 0)
571 goto doi_dump_all_failure;
572 if (nla_put_u32(skb, NLA_U32, iter->type) != 0)
573 goto doi_dump_all_failure;
574 buf_len -= 2 * NETLBL_LEN_U32;
575 }
576 rcu_read_unlock();
577
578 return skb;
579
580doi_dump_all_failure:
581 rcu_read_unlock();
582 kfree(skb);
583 return NULL;
584}
585
586/**
587 * cipso_v4_doi_dump - Dump a CIPSO DOI definition into a sk_buff
588 * @doi: the DOI value
589 * @headroom: the amount of headroom to allocate for the sk_buff
590 *
591 * Description:
592 * Lookup the DOI definition matching @doi and dump it's contents into a
593 * sk_buff. The returned sk_buff has room at the front of the sk_buff for
594 * @headroom bytes. See net/netlabel/netlabel_cipso_v4.h for the LIST message
595 * format. This function may fail if another process is changing the DOI list
596 * at the same time. Returns a pointer to a sk_buff on success, NULL on error.
597 *
598 */
599struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom)
600{
601 struct sk_buff *skb = NULL;
602 struct cipso_v4_doi *iter;
603 u32 tag_cnt = 0;
604 u32 lvl_cnt = 0;
605 u32 cat_cnt = 0;
606 ssize_t buf_len;
607 ssize_t tmp;
608
609 rcu_read_lock();
610 iter = cipso_v4_doi_getdef(doi);
611 if (iter == NULL)
612 goto doi_dump_failure;
613 buf_len = NETLBL_LEN_U32;
614 switch (iter->type) {
615 case CIPSO_V4_MAP_PASS:
616 buf_len += NETLBL_LEN_U32;
617 while(tag_cnt < CIPSO_V4_TAG_MAXCNT &&
618 iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) {
619 tag_cnt += 1;
620 buf_len += NETLBL_LEN_U8;
621 }
622 break;
623 case CIPSO_V4_MAP_STD:
624 buf_len += 3 * NETLBL_LEN_U32;
625 while (tag_cnt < CIPSO_V4_TAG_MAXCNT &&
626 iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) {
627 tag_cnt += 1;
628 buf_len += NETLBL_LEN_U8;
629 }
630 for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++)
631 if (iter->map.std->lvl.local[tmp] !=
632 CIPSO_V4_INV_LVL) {
633 lvl_cnt += 1;
634 buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U8;
635 }
636 for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++)
637 if (iter->map.std->cat.local[tmp] !=
638 CIPSO_V4_INV_CAT) {
639 cat_cnt += 1;
640 buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U16;
641 } 562 }
642 break;
643 }
644
645 skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
646 if (skb == NULL)
647 goto doi_dump_failure;
648
649 if (nla_put_u32(skb, NLA_U32, iter->type) != 0)
650 goto doi_dump_failure;
651 buf_len -= NETLBL_LEN_U32;
652 if (iter != cipso_v4_doi_getdef(doi))
653 goto doi_dump_failure;
654 switch (iter->type) {
655 case CIPSO_V4_MAP_PASS:
656 if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0)
657 goto doi_dump_failure;
658 buf_len -= NETLBL_LEN_U32;
659 for (tmp = 0;
660 tmp < CIPSO_V4_TAG_MAXCNT &&
661 iter->tags[tmp] != CIPSO_V4_TAG_INVALID;
662 tmp++) {
663 if (buf_len < NETLBL_LEN_U8)
664 goto doi_dump_failure;
665 if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0)
666 goto doi_dump_failure;
667 buf_len -= NETLBL_LEN_U8;
668 } 563 }
669 break;
670 case CIPSO_V4_MAP_STD:
671 if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0)
672 goto doi_dump_failure;
673 if (nla_put_u32(skb, NLA_U32, lvl_cnt) != 0)
674 goto doi_dump_failure;
675 if (nla_put_u32(skb, NLA_U32, cat_cnt) != 0)
676 goto doi_dump_failure;
677 buf_len -= 3 * NETLBL_LEN_U32;
678 for (tmp = 0;
679 tmp < CIPSO_V4_TAG_MAXCNT &&
680 iter->tags[tmp] != CIPSO_V4_TAG_INVALID;
681 tmp++) {
682 if (buf_len < NETLBL_LEN_U8)
683 goto doi_dump_failure;
684 if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0)
685 goto doi_dump_failure;
686 buf_len -= NETLBL_LEN_U8;
687 }
688 for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++)
689 if (iter->map.std->lvl.local[tmp] !=
690 CIPSO_V4_INV_LVL) {
691 if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U8)
692 goto doi_dump_failure;
693 if (nla_put_u32(skb, NLA_U32, tmp) != 0)
694 goto doi_dump_failure;
695 if (nla_put_u8(skb,
696 NLA_U8,
697 iter->map.std->lvl.local[tmp]) != 0)
698 goto doi_dump_failure;
699 buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U8;
700 }
701 for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++)
702 if (iter->map.std->cat.local[tmp] !=
703 CIPSO_V4_INV_CAT) {
704 if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U16)
705 goto doi_dump_failure;
706 if (nla_put_u32(skb, NLA_U32, tmp) != 0)
707 goto doi_dump_failure;
708 if (nla_put_u16(skb,
709 NLA_U16,
710 iter->map.std->cat.local[tmp]) != 0)
711 goto doi_dump_failure;
712 buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U16;
713 }
714 break;
715 }
716 rcu_read_unlock();
717
718 return skb;
719 564
720doi_dump_failure: 565doi_walk_return:
721 rcu_read_unlock(); 566 rcu_read_unlock();
722 kfree(skb); 567 *skip_cnt = doi_cnt;
723 return NULL; 568 return ret_val;
724} 569}
725 570
726/** 571/**
@@ -1486,43 +1331,40 @@ socket_setattr_failure:
1486} 1331}
1487 1332
1488/** 1333/**
1489 * cipso_v4_socket_getattr - Get the security attributes from a socket 1334 * cipso_v4_sock_getattr - Get the security attributes from a sock
1490 * @sock: the socket 1335 * @sk: the sock
1491 * @secattr: the security attributes 1336 * @secattr: the security attributes
1492 * 1337 *
1493 * Description: 1338 * Description:
1494 * Query @sock to see if there is a CIPSO option attached to the socket and if 1339 * Query @sk to see if there is a CIPSO option attached to the sock and if
1495 * there is return the CIPSO security attributes in @secattr. Returns zero on 1340 * there is return the CIPSO security attributes in @secattr. This function
1496 * success and negative values on failure. 1341 * requires that @sk be locked, or privately held, but it does not do any
1342 * locking itself. Returns zero on success and negative values on failure.
1497 * 1343 *
1498 */ 1344 */
1499int cipso_v4_socket_getattr(const struct socket *sock, 1345int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
1500 struct netlbl_lsm_secattr *secattr)
1501{ 1346{
1502 int ret_val = -ENOMSG; 1347 int ret_val = -ENOMSG;
1503 struct sock *sk;
1504 struct inet_sock *sk_inet; 1348 struct inet_sock *sk_inet;
1505 unsigned char *cipso_ptr; 1349 unsigned char *cipso_ptr;
1506 u32 doi; 1350 u32 doi;
1507 struct cipso_v4_doi *doi_def; 1351 struct cipso_v4_doi *doi_def;
1508 1352
1509 sk = sock->sk;
1510 lock_sock(sk);
1511 sk_inet = inet_sk(sk); 1353 sk_inet = inet_sk(sk);
1512 if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0) 1354 if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0)
1513 goto socket_getattr_return; 1355 return -ENOMSG;
1514 cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso - 1356 cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso -
1515 sizeof(struct iphdr); 1357 sizeof(struct iphdr);
1516 ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr); 1358 ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr);
1517 if (ret_val == 0) 1359 if (ret_val == 0)
1518 goto socket_getattr_return; 1360 return ret_val;
1519 1361
1520 doi = ntohl(*(u32 *)&cipso_ptr[2]); 1362 doi = ntohl(*(u32 *)&cipso_ptr[2]);
1521 rcu_read_lock(); 1363 rcu_read_lock();
1522 doi_def = cipso_v4_doi_getdef(doi); 1364 doi_def = cipso_v4_doi_getdef(doi);
1523 if (doi_def == NULL) { 1365 if (doi_def == NULL) {
1524 rcu_read_unlock(); 1366 rcu_read_unlock();
1525 goto socket_getattr_return; 1367 return -ENOMSG;
1526 } 1368 }
1527 switch (cipso_ptr[6]) { 1369 switch (cipso_ptr[6]) {
1528 case CIPSO_V4_TAG_RBITMAP: 1370 case CIPSO_V4_TAG_RBITMAP:
@@ -1533,8 +1375,29 @@ int cipso_v4_socket_getattr(const struct socket *sock,
1533 } 1375 }
1534 rcu_read_unlock(); 1376 rcu_read_unlock();
1535 1377
1536socket_getattr_return: 1378 return ret_val;
1537 release_sock(sk); 1379}
1380
1381/**
1382 * cipso_v4_socket_getattr - Get the security attributes from a socket
1383 * @sock: the socket
1384 * @secattr: the security attributes
1385 *
1386 * Description:
1387 * Query @sock to see if there is a CIPSO option attached to the socket and if
1388 * there is return the CIPSO security attributes in @secattr. Returns zero on
1389 * success and negative values on failure.
1390 *
1391 */
1392int cipso_v4_socket_getattr(const struct socket *sock,
1393 struct netlbl_lsm_secattr *secattr)
1394{
1395 int ret_val;
1396
1397 lock_sock(sock->sk);
1398 ret_val = cipso_v4_sock_getattr(sock->sk, secattr);
1399 release_sock(sock->sk);
1400
1538 return ret_val; 1401 return ret_val;
1539} 1402}
1540 1403