diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-08 13:21:10 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-08 13:21:10 -0400 |
| commit | 153d8a122e04d285aaee0ba00af7564182b7b6de (patch) | |
| tree | 6de586e234b4021464fd71930a7e7f60717c4430 | |
| parent | 2a50b2560ee956808da0b644cb529608dee65274 (diff) | |
| parent | 211a40c0870457b29100cffea0180fa5083caf96 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6:
smack: fixes for unlabeled host support
| -rw-r--r-- | security/smack/smack_lsm.c | 43 | ||||
| -rw-r--r-- | security/smack/smackfs.c | 64 |
2 files changed, 57 insertions, 50 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 0278bc083044..e7ded1326b0f 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -1498,58 +1498,31 @@ static int smack_socket_post_create(struct socket *sock, int family, | |||
| 1498 | * looks for host based access restrictions | 1498 | * looks for host based access restrictions |
| 1499 | * | 1499 | * |
| 1500 | * This version will only be appropriate for really small | 1500 | * This version will only be appropriate for really small |
| 1501 | * sets of single label hosts. Because of the masking | 1501 | * sets of single label hosts. |
| 1502 | * it cannot shortcut out on the first match. There are | ||
| 1503 | * numerious ways to address the problem, but none of them | ||
| 1504 | * have been applied here. | ||
| 1505 | * | 1502 | * |
| 1506 | * Returns the label of the far end or NULL if it's not special. | 1503 | * Returns the label of the far end or NULL if it's not special. |
| 1507 | */ | 1504 | */ |
| 1508 | static char *smack_host_label(struct sockaddr_in *sip) | 1505 | static char *smack_host_label(struct sockaddr_in *sip) |
| 1509 | { | 1506 | { |
| 1510 | struct smk_netlbladdr *snp; | 1507 | struct smk_netlbladdr *snp; |
| 1511 | char *bestlabel = NULL; | ||
| 1512 | struct in_addr *siap = &sip->sin_addr; | 1508 | struct in_addr *siap = &sip->sin_addr; |
| 1513 | struct in_addr *liap; | ||
| 1514 | struct in_addr *miap; | ||
| 1515 | struct in_addr bestmask; | ||
| 1516 | 1509 | ||
| 1517 | if (siap->s_addr == 0) | 1510 | if (siap->s_addr == 0) |
| 1518 | return NULL; | 1511 | return NULL; |
| 1519 | 1512 | ||
| 1520 | bestmask.s_addr = 0; | ||
| 1521 | |||
| 1522 | for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) { | 1513 | for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) { |
| 1523 | liap = &snp->smk_host.sin_addr; | ||
| 1524 | miap = &snp->smk_mask; | ||
| 1525 | /* | ||
| 1526 | * If the addresses match after applying the list entry mask | ||
| 1527 | * the entry matches the address. If it doesn't move along to | ||
| 1528 | * the next entry. | ||
| 1529 | */ | ||
| 1530 | if ((liap->s_addr & miap->s_addr) != | ||
| 1531 | (siap->s_addr & miap->s_addr)) | ||
| 1532 | continue; | ||
| 1533 | /* | 1514 | /* |
| 1534 | * If the list entry mask identifies a single address | 1515 | * we break after finding the first match because |
| 1535 | * it can't get any more specific. | 1516 | * the list is sorted from longest to shortest mask |
| 1517 | * so we have found the most specific match | ||
| 1536 | */ | 1518 | */ |
| 1537 | if (miap->s_addr == 0xffffffff) | 1519 | if ((&snp->smk_host.sin_addr)->s_addr == |
| 1520 | (siap->s_addr & (&snp->smk_mask)->s_addr)) { | ||
| 1538 | return snp->smk_label; | 1521 | return snp->smk_label; |
| 1539 | /* | 1522 | } |
| 1540 | * If the list entry mask is less specific than the best | ||
| 1541 | * already found this entry is uninteresting. | ||
| 1542 | */ | ||
| 1543 | if ((miap->s_addr | bestmask.s_addr) == bestmask.s_addr) | ||
| 1544 | continue; | ||
| 1545 | /* | ||
| 1546 | * This is better than any entry found so far. | ||
| 1547 | */ | ||
| 1548 | bestmask.s_addr = miap->s_addr; | ||
| 1549 | bestlabel = snp->smk_label; | ||
| 1550 | } | 1523 | } |
| 1551 | 1524 | ||
| 1552 | return bestlabel; | 1525 | return NULL; |
| 1553 | } | 1526 | } |
| 1554 | 1527 | ||
| 1555 | /** | 1528 | /** |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 8e42800878f4..51f0efc50dab 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
| @@ -650,10 +650,6 @@ static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos) | |||
| 650 | 650 | ||
| 651 | return skp; | 651 | return skp; |
| 652 | } | 652 | } |
| 653 | /* | ||
| 654 | #define BEMASK 0x80000000 | ||
| 655 | */ | ||
| 656 | #define BEMASK 0x00000001 | ||
| 657 | #define BEBITS (sizeof(__be32) * 8) | 653 | #define BEBITS (sizeof(__be32) * 8) |
| 658 | 654 | ||
| 659 | /* | 655 | /* |
| @@ -663,12 +659,10 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v) | |||
| 663 | { | 659 | { |
| 664 | struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v; | 660 | struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v; |
| 665 | unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr; | 661 | unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr; |
| 666 | __be32 bebits; | 662 | int maskn; |
| 667 | int maskn = 0; | 663 | u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr); |
| 668 | 664 | ||
| 669 | for (bebits = BEMASK; bebits != 0; maskn++, bebits <<= 1) | 665 | for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++); |
| 670 | if ((skp->smk_mask.s_addr & bebits) == 0) | ||
| 671 | break; | ||
| 672 | 666 | ||
| 673 | seq_printf(s, "%u.%u.%u.%u/%d %s\n", | 667 | seq_printf(s, "%u.%u.%u.%u/%d %s\n", |
| 674 | hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label); | 668 | hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label); |
| @@ -702,6 +696,42 @@ static int smk_open_netlbladdr(struct inode *inode, struct file *file) | |||
| 702 | } | 696 | } |
| 703 | 697 | ||
| 704 | /** | 698 | /** |
| 699 | * smk_netlbladdr_insert | ||
| 700 | * @new : netlabel to insert | ||
| 701 | * | ||
| 702 | * This helper insert netlabel in the smack_netlbladdrs list | ||
| 703 | * sorted by netmask length (longest to smallest) | ||
| 704 | */ | ||
| 705 | static void smk_netlbladdr_insert(struct smk_netlbladdr *new) | ||
| 706 | { | ||
| 707 | struct smk_netlbladdr *m; | ||
| 708 | |||
| 709 | if (smack_netlbladdrs == NULL) { | ||
| 710 | smack_netlbladdrs = new; | ||
| 711 | return; | ||
| 712 | } | ||
| 713 | |||
| 714 | /* the comparison '>' is a bit hacky, but works */ | ||
| 715 | if (new->smk_mask.s_addr > smack_netlbladdrs->smk_mask.s_addr) { | ||
| 716 | new->smk_next = smack_netlbladdrs; | ||
| 717 | smack_netlbladdrs = new; | ||
| 718 | return; | ||
| 719 | } | ||
| 720 | for (m = smack_netlbladdrs; m != NULL; m = m->smk_next) { | ||
| 721 | if (m->smk_next == NULL) { | ||
| 722 | m->smk_next = new; | ||
| 723 | return; | ||
| 724 | } | ||
| 725 | if (new->smk_mask.s_addr > m->smk_next->smk_mask.s_addr) { | ||
| 726 | new->smk_next = m->smk_next; | ||
| 727 | m->smk_next = new; | ||
| 728 | return; | ||
| 729 | } | ||
| 730 | } | ||
| 731 | } | ||
| 732 | |||
| 733 | |||
| 734 | /** | ||
| 705 | * smk_write_netlbladdr - write() for /smack/netlabel | 735 | * smk_write_netlbladdr - write() for /smack/netlabel |
| 706 | * @filp: file pointer, not actually used | 736 | * @filp: file pointer, not actually used |
| 707 | * @buf: where to get the data from | 737 | * @buf: where to get the data from |
| @@ -724,8 +754,9 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
| 724 | struct netlbl_audit audit_info; | 754 | struct netlbl_audit audit_info; |
| 725 | struct in_addr mask; | 755 | struct in_addr mask; |
| 726 | unsigned int m; | 756 | unsigned int m; |
| 727 | __be32 bebits = BEMASK; | 757 | u32 mask_bits = (1<<31); |
| 728 | __be32 nsa; | 758 | __be32 nsa; |
| 759 | u32 temp_mask; | ||
| 729 | 760 | ||
| 730 | /* | 761 | /* |
| 731 | * Must have privilege. | 762 | * Must have privilege. |
| @@ -761,10 +792,13 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
| 761 | if (sp == NULL) | 792 | if (sp == NULL) |
| 762 | return -EINVAL; | 793 | return -EINVAL; |
| 763 | 794 | ||
| 764 | for (mask.s_addr = 0; m > 0; m--) { | 795 | for (temp_mask = 0; m > 0; m--) { |
| 765 | mask.s_addr |= bebits; | 796 | temp_mask |= mask_bits; |
| 766 | bebits <<= 1; | 797 | mask_bits >>= 1; |
| 767 | } | 798 | } |
| 799 | mask.s_addr = cpu_to_be32(temp_mask); | ||
| 800 | |||
| 801 | newname.sin_addr.s_addr &= mask.s_addr; | ||
| 768 | /* | 802 | /* |
| 769 | * Only allow one writer at a time. Writes should be | 803 | * Only allow one writer at a time. Writes should be |
| 770 | * quite rare and small in any case. | 804 | * quite rare and small in any case. |
| @@ -772,6 +806,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
| 772 | mutex_lock(&smk_netlbladdr_lock); | 806 | mutex_lock(&smk_netlbladdr_lock); |
| 773 | 807 | ||
| 774 | nsa = newname.sin_addr.s_addr; | 808 | nsa = newname.sin_addr.s_addr; |
| 809 | /* try to find if the prefix is already in the list */ | ||
| 775 | for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next) | 810 | for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next) |
| 776 | if (skp->smk_host.sin_addr.s_addr == nsa && | 811 | if (skp->smk_host.sin_addr.s_addr == nsa && |
| 777 | skp->smk_mask.s_addr == mask.s_addr) | 812 | skp->smk_mask.s_addr == mask.s_addr) |
| @@ -787,9 +822,8 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
| 787 | rc = 0; | 822 | rc = 0; |
| 788 | skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr; | 823 | skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr; |
| 789 | skp->smk_mask.s_addr = mask.s_addr; | 824 | skp->smk_mask.s_addr = mask.s_addr; |
| 790 | skp->smk_next = smack_netlbladdrs; | ||
| 791 | skp->smk_label = sp; | 825 | skp->smk_label = sp; |
| 792 | smack_netlbladdrs = skp; | 826 | smk_netlbladdr_insert(skp); |
| 793 | } | 827 | } |
| 794 | } else { | 828 | } else { |
| 795 | rc = netlbl_cfg_unlbl_static_del(&init_net, NULL, | 829 | rc = netlbl_cfg_unlbl_static_del(&init_net, NULL, |
