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
This commit is contained in:
commit
153d8a122e
|
@ -1498,58 +1498,31 @@ static int smack_socket_post_create(struct socket *sock, int family,
|
||||||
* looks for host based access restrictions
|
* looks for host based access restrictions
|
||||||
*
|
*
|
||||||
* This version will only be appropriate for really small
|
* This version will only be appropriate for really small
|
||||||
* sets of single label hosts. Because of the masking
|
* sets of single label hosts.
|
||||||
* it cannot shortcut out on the first match. There are
|
|
||||||
* numerious ways to address the problem, but none of them
|
|
||||||
* have been applied here.
|
|
||||||
*
|
*
|
||||||
* Returns the label of the far end or NULL if it's not special.
|
* Returns the label of the far end or NULL if it's not special.
|
||||||
*/
|
*/
|
||||||
static char *smack_host_label(struct sockaddr_in *sip)
|
static char *smack_host_label(struct sockaddr_in *sip)
|
||||||
{
|
{
|
||||||
struct smk_netlbladdr *snp;
|
struct smk_netlbladdr *snp;
|
||||||
char *bestlabel = NULL;
|
|
||||||
struct in_addr *siap = &sip->sin_addr;
|
struct in_addr *siap = &sip->sin_addr;
|
||||||
struct in_addr *liap;
|
|
||||||
struct in_addr *miap;
|
|
||||||
struct in_addr bestmask;
|
|
||||||
|
|
||||||
if (siap->s_addr == 0)
|
if (siap->s_addr == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
bestmask.s_addr = 0;
|
|
||||||
|
|
||||||
for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) {
|
for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) {
|
||||||
liap = &snp->smk_host.sin_addr;
|
|
||||||
miap = &snp->smk_mask;
|
|
||||||
/*
|
/*
|
||||||
* If the addresses match after applying the list entry mask
|
* we break after finding the first match because
|
||||||
* the entry matches the address. If it doesn't move along to
|
* the list is sorted from longest to shortest mask
|
||||||
* the next entry.
|
* so we have found the most specific match
|
||||||
*/
|
*/
|
||||||
if ((liap->s_addr & miap->s_addr) !=
|
if ((&snp->smk_host.sin_addr)->s_addr ==
|
||||||
(siap->s_addr & miap->s_addr))
|
(siap->s_addr & (&snp->smk_mask)->s_addr)) {
|
||||||
continue;
|
|
||||||
/*
|
|
||||||
* If the list entry mask identifies a single address
|
|
||||||
* it can't get any more specific.
|
|
||||||
*/
|
|
||||||
if (miap->s_addr == 0xffffffff)
|
|
||||||
return snp->smk_label;
|
return snp->smk_label;
|
||||||
/*
|
}
|
||||||
* If the list entry mask is less specific than the best
|
|
||||||
* already found this entry is uninteresting.
|
|
||||||
*/
|
|
||||||
if ((miap->s_addr | bestmask.s_addr) == bestmask.s_addr)
|
|
||||||
continue;
|
|
||||||
/*
|
|
||||||
* This is better than any entry found so far.
|
|
||||||
*/
|
|
||||||
bestmask.s_addr = miap->s_addr;
|
|
||||||
bestlabel = snp->smk_label;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return bestlabel;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -650,10 +650,6 @@ static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
|
||||||
|
|
||||||
return skp;
|
return skp;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
#define BEMASK 0x80000000
|
|
||||||
*/
|
|
||||||
#define BEMASK 0x00000001
|
|
||||||
#define BEBITS (sizeof(__be32) * 8)
|
#define BEBITS (sizeof(__be32) * 8)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -663,12 +659,10 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v)
|
||||||
{
|
{
|
||||||
struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v;
|
struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v;
|
||||||
unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
|
unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
|
||||||
__be32 bebits;
|
int maskn;
|
||||||
int maskn = 0;
|
u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
|
||||||
|
|
||||||
for (bebits = BEMASK; bebits != 0; maskn++, bebits <<= 1)
|
for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++);
|
||||||
if ((skp->smk_mask.s_addr & bebits) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
seq_printf(s, "%u.%u.%u.%u/%d %s\n",
|
seq_printf(s, "%u.%u.%u.%u/%d %s\n",
|
||||||
hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label);
|
hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label);
|
||||||
|
@ -701,6 +695,42 @@ static int smk_open_netlbladdr(struct inode *inode, struct file *file)
|
||||||
return seq_open(file, &netlbladdr_seq_ops);
|
return seq_open(file, &netlbladdr_seq_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smk_netlbladdr_insert
|
||||||
|
* @new : netlabel to insert
|
||||||
|
*
|
||||||
|
* This helper insert netlabel in the smack_netlbladdrs list
|
||||||
|
* sorted by netmask length (longest to smallest)
|
||||||
|
*/
|
||||||
|
static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
|
||||||
|
{
|
||||||
|
struct smk_netlbladdr *m;
|
||||||
|
|
||||||
|
if (smack_netlbladdrs == NULL) {
|
||||||
|
smack_netlbladdrs = new;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the comparison '>' is a bit hacky, but works */
|
||||||
|
if (new->smk_mask.s_addr > smack_netlbladdrs->smk_mask.s_addr) {
|
||||||
|
new->smk_next = smack_netlbladdrs;
|
||||||
|
smack_netlbladdrs = new;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (m = smack_netlbladdrs; m != NULL; m = m->smk_next) {
|
||||||
|
if (m->smk_next == NULL) {
|
||||||
|
m->smk_next = new;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (new->smk_mask.s_addr > m->smk_next->smk_mask.s_addr) {
|
||||||
|
new->smk_next = m->smk_next;
|
||||||
|
m->smk_next = new;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smk_write_netlbladdr - write() for /smack/netlabel
|
* smk_write_netlbladdr - write() for /smack/netlabel
|
||||||
* @filp: file pointer, not actually used
|
* @filp: file pointer, not actually used
|
||||||
|
@ -724,8 +754,9 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
|
||||||
struct netlbl_audit audit_info;
|
struct netlbl_audit audit_info;
|
||||||
struct in_addr mask;
|
struct in_addr mask;
|
||||||
unsigned int m;
|
unsigned int m;
|
||||||
__be32 bebits = BEMASK;
|
u32 mask_bits = (1<<31);
|
||||||
__be32 nsa;
|
__be32 nsa;
|
||||||
|
u32 temp_mask;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Must have privilege.
|
* Must have privilege.
|
||||||
|
@ -761,10 +792,13 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
|
||||||
if (sp == NULL)
|
if (sp == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (mask.s_addr = 0; m > 0; m--) {
|
for (temp_mask = 0; m > 0; m--) {
|
||||||
mask.s_addr |= bebits;
|
temp_mask |= mask_bits;
|
||||||
bebits <<= 1;
|
mask_bits >>= 1;
|
||||||
}
|
}
|
||||||
|
mask.s_addr = cpu_to_be32(temp_mask);
|
||||||
|
|
||||||
|
newname.sin_addr.s_addr &= mask.s_addr;
|
||||||
/*
|
/*
|
||||||
* Only allow one writer at a time. Writes should be
|
* Only allow one writer at a time. Writes should be
|
||||||
* quite rare and small in any case.
|
* quite rare and small in any case.
|
||||||
|
@ -772,6 +806,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
|
||||||
mutex_lock(&smk_netlbladdr_lock);
|
mutex_lock(&smk_netlbladdr_lock);
|
||||||
|
|
||||||
nsa = newname.sin_addr.s_addr;
|
nsa = newname.sin_addr.s_addr;
|
||||||
|
/* try to find if the prefix is already in the list */
|
||||||
for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next)
|
for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next)
|
||||||
if (skp->smk_host.sin_addr.s_addr == nsa &&
|
if (skp->smk_host.sin_addr.s_addr == nsa &&
|
||||||
skp->smk_mask.s_addr == mask.s_addr)
|
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,
|
||||||
rc = 0;
|
rc = 0;
|
||||||
skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
|
skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
|
||||||
skp->smk_mask.s_addr = mask.s_addr;
|
skp->smk_mask.s_addr = mask.s_addr;
|
||||||
skp->smk_next = smack_netlbladdrs;
|
|
||||||
skp->smk_label = sp;
|
skp->smk_label = sp;
|
||||||
smack_netlbladdrs = skp;
|
smk_netlbladdr_insert(skp);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
|
rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
|
||||||
|
|
Loading…
Reference in New Issue