Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== The following patchset contains three netfilter fixes for your net tree, they are: * A couple of fixes to resolve info leak to userspace due to uninitialized memory area in ulogd, from Mathias Krause. * Fix instruction ordering issues that may lead to the access of uninitialized data in x_tables. The problem involves the table update (producer) and the main packet matching (consumer) routines. Detected in SMP ARMv7, from Will Deacon. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
afb14c7cb6
@ -181,6 +181,7 @@ static void ebt_ulog_packet(struct net *net, unsigned int hooknr,
|
|||||||
ub->qlen++;
|
ub->qlen++;
|
||||||
|
|
||||||
pm = nlmsg_data(nlh);
|
pm = nlmsg_data(nlh);
|
||||||
|
memset(pm, 0, sizeof(*pm));
|
||||||
|
|
||||||
/* Fill in the ulog data */
|
/* Fill in the ulog data */
|
||||||
pm->version = EBT_ULOG_VERSION;
|
pm->version = EBT_ULOG_VERSION;
|
||||||
@ -193,8 +194,6 @@ static void ebt_ulog_packet(struct net *net, unsigned int hooknr,
|
|||||||
pm->hook = hooknr;
|
pm->hook = hooknr;
|
||||||
if (uloginfo->prefix != NULL)
|
if (uloginfo->prefix != NULL)
|
||||||
strcpy(pm->prefix, uloginfo->prefix);
|
strcpy(pm->prefix, uloginfo->prefix);
|
||||||
else
|
|
||||||
*(pm->prefix) = '\0';
|
|
||||||
|
|
||||||
if (in) {
|
if (in) {
|
||||||
strcpy(pm->physindev, in->name);
|
strcpy(pm->physindev, in->name);
|
||||||
@ -204,16 +203,14 @@ static void ebt_ulog_packet(struct net *net, unsigned int hooknr,
|
|||||||
strcpy(pm->indev, br_port_get_rcu(in)->br->dev->name);
|
strcpy(pm->indev, br_port_get_rcu(in)->br->dev->name);
|
||||||
else
|
else
|
||||||
strcpy(pm->indev, in->name);
|
strcpy(pm->indev, in->name);
|
||||||
} else
|
}
|
||||||
pm->indev[0] = pm->physindev[0] = '\0';
|
|
||||||
|
|
||||||
if (out) {
|
if (out) {
|
||||||
/* If out exists, then out is a bridge port */
|
/* If out exists, then out is a bridge port */
|
||||||
strcpy(pm->physoutdev, out->name);
|
strcpy(pm->physoutdev, out->name);
|
||||||
/* rcu_read_lock()ed by nf_hook_slow */
|
/* rcu_read_lock()ed by nf_hook_slow */
|
||||||
strcpy(pm->outdev, br_port_get_rcu(out)->br->dev->name);
|
strcpy(pm->outdev, br_port_get_rcu(out)->br->dev->name);
|
||||||
} else
|
}
|
||||||
pm->outdev[0] = pm->physoutdev[0] = '\0';
|
|
||||||
|
|
||||||
if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0)
|
if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0)
|
||||||
BUG();
|
BUG();
|
||||||
|
@ -271,6 +271,11 @@ unsigned int arpt_do_table(struct sk_buff *skb,
|
|||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
addend = xt_write_recseq_begin();
|
addend = xt_write_recseq_begin();
|
||||||
private = table->private;
|
private = table->private;
|
||||||
|
/*
|
||||||
|
* Ensure we load private-> members after we've fetched the base
|
||||||
|
* pointer.
|
||||||
|
*/
|
||||||
|
smp_read_barrier_depends();
|
||||||
table_base = private->entries[smp_processor_id()];
|
table_base = private->entries[smp_processor_id()];
|
||||||
|
|
||||||
e = get_entry(table_base, private->hook_entry[hook]);
|
e = get_entry(table_base, private->hook_entry[hook]);
|
||||||
|
@ -327,6 +327,11 @@ ipt_do_table(struct sk_buff *skb,
|
|||||||
addend = xt_write_recseq_begin();
|
addend = xt_write_recseq_begin();
|
||||||
private = table->private;
|
private = table->private;
|
||||||
cpu = smp_processor_id();
|
cpu = smp_processor_id();
|
||||||
|
/*
|
||||||
|
* Ensure we load private-> members after we've fetched the base
|
||||||
|
* pointer.
|
||||||
|
*/
|
||||||
|
smp_read_barrier_depends();
|
||||||
table_base = private->entries[cpu];
|
table_base = private->entries[cpu];
|
||||||
jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
|
jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
|
||||||
stackptr = per_cpu_ptr(private->stackptr, cpu);
|
stackptr = per_cpu_ptr(private->stackptr, cpu);
|
||||||
|
@ -220,6 +220,7 @@ static void ipt_ulog_packet(struct net *net,
|
|||||||
ub->qlen++;
|
ub->qlen++;
|
||||||
|
|
||||||
pm = nlmsg_data(nlh);
|
pm = nlmsg_data(nlh);
|
||||||
|
memset(pm, 0, sizeof(*pm));
|
||||||
|
|
||||||
/* We might not have a timestamp, get one */
|
/* We might not have a timestamp, get one */
|
||||||
if (skb->tstamp.tv64 == 0)
|
if (skb->tstamp.tv64 == 0)
|
||||||
@ -238,8 +239,6 @@ static void ipt_ulog_packet(struct net *net,
|
|||||||
}
|
}
|
||||||
else if (loginfo->prefix[0] != '\0')
|
else if (loginfo->prefix[0] != '\0')
|
||||||
strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
|
strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
|
||||||
else
|
|
||||||
*(pm->prefix) = '\0';
|
|
||||||
|
|
||||||
if (in && in->hard_header_len > 0 &&
|
if (in && in->hard_header_len > 0 &&
|
||||||
skb->mac_header != skb->network_header &&
|
skb->mac_header != skb->network_header &&
|
||||||
@ -251,13 +250,9 @@ static void ipt_ulog_packet(struct net *net,
|
|||||||
|
|
||||||
if (in)
|
if (in)
|
||||||
strncpy(pm->indev_name, in->name, sizeof(pm->indev_name));
|
strncpy(pm->indev_name, in->name, sizeof(pm->indev_name));
|
||||||
else
|
|
||||||
pm->indev_name[0] = '\0';
|
|
||||||
|
|
||||||
if (out)
|
if (out)
|
||||||
strncpy(pm->outdev_name, out->name, sizeof(pm->outdev_name));
|
strncpy(pm->outdev_name, out->name, sizeof(pm->outdev_name));
|
||||||
else
|
|
||||||
pm->outdev_name[0] = '\0';
|
|
||||||
|
|
||||||
/* copy_len <= skb->len, so can't fail. */
|
/* copy_len <= skb->len, so can't fail. */
|
||||||
if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0)
|
if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0)
|
||||||
|
@ -349,6 +349,11 @@ ip6t_do_table(struct sk_buff *skb,
|
|||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
addend = xt_write_recseq_begin();
|
addend = xt_write_recseq_begin();
|
||||||
private = table->private;
|
private = table->private;
|
||||||
|
/*
|
||||||
|
* Ensure we load private-> members after we've fetched the base
|
||||||
|
* pointer.
|
||||||
|
*/
|
||||||
|
smp_read_barrier_depends();
|
||||||
cpu = smp_processor_id();
|
cpu = smp_processor_id();
|
||||||
table_base = private->entries[cpu];
|
table_base = private->entries[cpu];
|
||||||
jumpstack = (struct ip6t_entry **)private->jumpstack[cpu];
|
jumpstack = (struct ip6t_entry **)private->jumpstack[cpu];
|
||||||
|
@ -845,8 +845,13 @@ xt_replace_table(struct xt_table *table,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
table->private = newinfo;
|
|
||||||
newinfo->initial_entries = private->initial_entries;
|
newinfo->initial_entries = private->initial_entries;
|
||||||
|
/*
|
||||||
|
* Ensure contents of newinfo are visible before assigning to
|
||||||
|
* private.
|
||||||
|
*/
|
||||||
|
smp_wmb();
|
||||||
|
table->private = newinfo;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Even though table entries have now been swapped, other CPU's
|
* Even though table entries have now been swapped, other CPU's
|
||||||
|
Loading…
Reference in New Issue
Block a user