Skip to content

Commit 113a0e4

Browse files
ccie6798James Morris
authored andcommitted
smack: fixes for unlabeled host support
The following patch (against 2.6.29rc5) fixes a few issues in the smack/netlabel "unlabeled host support" functionnality that was added in 2.6.29rc. It should go in before -final. 1) smack_host_label disregard a "0.0.0.0/0 @" rule (or other label), preventing 'tagged' tasks to access Internet (many systems drop packets with IP options) 2) netmasks were not handled correctly, they were stored in a way _not equivalent_ to conversion to be32 (it was equivalent for /0, /8, /16, /24, /32 masks but not other masks) 3) smack_netlbladdr prefixes (IP/mask) were not consistent (mask&IP was not done), so there could have been different list entries for the same IP prefix; if those entries had different labels, well ... 4) they were not sorted 1) 2) 3) are bugs, 4) is a more cosmetic issue. The patch : -creates a new helper smk_netlbladdr_insert to insert a smk_netlbladdr, -sorted by netmask length -use the new sorted nature of smack_netlbladdrs list to simplify smack_host_label : the first match _will_ be the more specific -corrects endianness issues in smk_write_netlbladdr & netlbladdr_seq_show Signed-off-by: <etienne.basset@numericable.fr> Acked-by: Casey Schaufler <casey@schaufler-ca.com> Reviewed-by: Paul Moore <paul.moore@hp.com> Signed-off-by: James Morris <jmorris@namei.org>
1 parent 454804a commit 113a0e4

File tree

1 file changed

+49
-15
lines changed

1 file changed

+49
-15
lines changed

security/smack/smackfs.c

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -651,10 +651,6 @@ static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
651651

652652
return skp;
653653
}
654-
/*
655-
#define BEMASK 0x80000000
656-
*/
657-
#define BEMASK 0x00000001
658654
#define BEBITS (sizeof(__be32) * 8)
659655

660656
/*
@@ -664,12 +660,10 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v)
664660
{
665661
struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v;
666662
unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
667-
__be32 bebits;
668-
int maskn = 0;
663+
int maskn;
664+
u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
669665

670-
for (bebits = BEMASK; bebits != 0; maskn++, bebits <<= 1)
671-
if ((skp->smk_mask.s_addr & bebits) == 0)
672-
break;
666+
for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++);
673667

674668
seq_printf(s, "%u.%u.%u.%u/%d %s\n",
675669
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)
702696
return seq_open(file, &netlbladdr_seq_ops);
703697
}
704698

699+
/**
700+
* smk_netlbladdr_insert
701+
* @new : netlabel to insert
702+
*
703+
* This helper insert netlabel in the smack_netlbladdrs list
704+
* sorted by netmask length (longest to smallest)
705+
*/
706+
static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
707+
{
708+
struct smk_netlbladdr *m;
709+
710+
if (smack_netlbladdrs == NULL) {
711+
smack_netlbladdrs = new;
712+
return;
713+
}
714+
715+
/* the comparison '>' is a bit hacky, but works */
716+
if (new->smk_mask.s_addr > smack_netlbladdrs->smk_mask.s_addr) {
717+
new->smk_next = smack_netlbladdrs;
718+
smack_netlbladdrs = new;
719+
return;
720+
}
721+
for (m = smack_netlbladdrs; m != NULL; m = m->smk_next) {
722+
if (m->smk_next == NULL) {
723+
m->smk_next = new;
724+
return;
725+
}
726+
if (new->smk_mask.s_addr > m->smk_next->smk_mask.s_addr) {
727+
new->smk_next = m->smk_next;
728+
m->smk_next = new;
729+
return;
730+
}
731+
}
732+
}
733+
734+
705735
/**
706736
* smk_write_netlbladdr - write() for /smack/netlabel
707737
* @file: file pointer, not actually used
@@ -725,8 +755,9 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
725755
struct netlbl_audit audit_info;
726756
struct in_addr mask;
727757
unsigned int m;
728-
__be32 bebits = BEMASK;
758+
u32 mask_bits = (1<<31);
729759
__be32 nsa;
760+
u32 temp_mask;
730761

731762
/*
732763
* Must have privilege.
@@ -762,17 +793,21 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
762793
if (sp == NULL)
763794
return -EINVAL;
764795

765-
for (mask.s_addr = 0; m > 0; m--) {
766-
mask.s_addr |= bebits;
767-
bebits <<= 1;
796+
for (temp_mask = 0; m > 0; m--) {
797+
temp_mask |= mask_bits;
798+
mask_bits >>= 1;
768799
}
800+
mask.s_addr = cpu_to_be32(temp_mask);
801+
802+
newname.sin_addr.s_addr &= mask.s_addr;
769803
/*
770804
* Only allow one writer at a time. Writes should be
771805
* quite rare and small in any case.
772806
*/
773807
mutex_lock(&smk_netlbladdr_lock);
774808

775809
nsa = newname.sin_addr.s_addr;
810+
/* try to find if the prefix is already in the list */
776811
for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next)
777812
if (skp->smk_host.sin_addr.s_addr == nsa &&
778813
skp->smk_mask.s_addr == mask.s_addr)
@@ -788,9 +823,8 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
788823
rc = 0;
789824
skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
790825
skp->smk_mask.s_addr = mask.s_addr;
791-
skp->smk_next = smack_netlbladdrs;
792826
skp->smk_label = sp;
793-
smack_netlbladdrs = skp;
827+
smk_netlbladdr_insert(skp);
794828
}
795829
} else {
796830
rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,

0 commit comments

Comments
 (0)