Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
  [NET]: Fix possible dev_deactivate race condition
  [INET]: Justification for local port range robustness.
  [PACKET]: Kill unused pg_vec_endpage() function
  [NET]: QoS/Sched as menuconfig
  [NET]: Fix bug in sk_filter race cures.
  [PATCH] mac80211: make ieee802_11_parse_elems return void
This commit is contained in:
Linus Torvalds 2007-10-19 11:54:39 -07:00
commit 804b908adf
11 changed files with 48 additions and 71 deletions

View file

@ -2797,11 +2797,12 @@ static void cma_remove_one(struct ib_device *device)
static int cma_init(void) static int cma_init(void)
{ {
int ret, low, high; int ret, low, high, remaining;
get_random_bytes(&next_port, sizeof next_port); get_random_bytes(&next_port, sizeof next_port);
inet_get_local_port_range(&low, &high); inet_get_local_port_range(&low, &high);
next_port = ((unsigned int) next_port % (high - low)) + low; remaining = (high - low) + 1;
next_port = ((unsigned int) next_port % remaining) + low;
cma_wq = create_singlethread_workqueue("rdma_cm"); cma_wq = create_singlethread_workqueue("rdma_cm");
if (!cma_wq) if (!cma_wq)

View file

@ -447,7 +447,8 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
rcu_assign_pointer(sk->sk_filter, fp); rcu_assign_pointer(sk->sk_filter, fp);
rcu_read_unlock_bh(); rcu_read_unlock_bh();
sk_filter_delayed_uncharge(sk, old_fp); if (old_fp)
sk_filter_delayed_uncharge(sk, old_fp);
return 0; return 0;
} }

View file

@ -93,7 +93,7 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo,
int remaining, rover, low, high; int remaining, rover, low, high;
inet_get_local_port_range(&low, &high); inet_get_local_port_range(&low, &high);
remaining = high - low; remaining = (high - low) + 1;
rover = net_random() % remaining + low; rover = net_random() % remaining + low;
do { do {

View file

@ -286,7 +286,7 @@ int inet_hash_connect(struct inet_timewait_death_row *death_row,
struct inet_timewait_sock *tw = NULL; struct inet_timewait_sock *tw = NULL;
inet_get_local_port_range(&low, &high); inet_get_local_port_range(&low, &high);
remaining = high - low; remaining = (high - low) + 1;
local_bh_disable(); local_bh_disable();
for (i = 1; i <= remaining; i++) { for (i = 1; i <= remaining; i++) {

View file

@ -122,7 +122,7 @@ static int ipv4_local_port_range(ctl_table *table, int write, struct file *filp,
ret = proc_dointvec_minmax(&tmp, write, filp, buffer, lenp, ppos); ret = proc_dointvec_minmax(&tmp, write, filp, buffer, lenp, ppos);
if (write && ret == 0) { if (write && ret == 0) {
if (range[1] <= range[0]) if (range[1] < range[0])
ret = -EINVAL; ret = -EINVAL;
else else
set_local_port_range(range); set_local_port_range(range);
@ -150,7 +150,7 @@ static int ipv4_sysctl_local_port_range(ctl_table *table, int __user *name,
ret = sysctl_intvec(&tmp, name, nlen, oldval, oldlenp, newval, newlen); ret = sysctl_intvec(&tmp, name, nlen, oldval, oldlenp, newval, newlen);
if (ret == 0 && newval && newlen) { if (ret == 0 && newval && newlen) {
if (range[1] <= range[0]) if (range[1] < range[0])
ret = -EINVAL; ret = -EINVAL;
else else
set_local_port_range(range); set_local_port_range(range);

View file

@ -147,13 +147,14 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
write_lock_bh(&udp_hash_lock); write_lock_bh(&udp_hash_lock);
if (!snum) { if (!snum) {
int i, low, high; int i, low, high, remaining;
unsigned rover, best, best_size_so_far; unsigned rover, best, best_size_so_far;
inet_get_local_port_range(&low, &high); inet_get_local_port_range(&low, &high);
remaining = (high - low) + 1;
best_size_so_far = UINT_MAX; best_size_so_far = UINT_MAX;
best = rover = net_random() % (high - low) + low; best = rover = net_random() % remaining + low;
/* 1st pass: look for empty (or shortest) hash chain */ /* 1st pass: look for empty (or shortest) hash chain */
for (i = 0; i < UDP_HTABLE_SIZE; i++) { for (i = 0; i < UDP_HTABLE_SIZE; i++) {

View file

@ -261,7 +261,7 @@ int inet6_hash_connect(struct inet_timewait_death_row *death_row,
struct inet_timewait_sock *tw = NULL; struct inet_timewait_sock *tw = NULL;
inet_get_local_port_range(&low, &high); inet_get_local_port_range(&low, &high);
remaining = high - low; remaining = (high - low) + 1;
local_bh_disable(); local_bh_disable();
for (i = 1; i <= remaining; i++) { for (i = 1; i <= remaining; i++) {

View file

@ -108,14 +108,11 @@ struct ieee802_11_elems {
u8 wmm_param_len; u8 wmm_param_len;
}; };
enum ParseRes { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 }; static void ieee802_11_parse_elems(u8 *start, size_t len,
struct ieee802_11_elems *elems)
static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
struct ieee802_11_elems *elems)
{ {
size_t left = len; size_t left = len;
u8 *pos = start; u8 *pos = start;
int unknown = 0;
memset(elems, 0, sizeof(*elems)); memset(elems, 0, sizeof(*elems));
@ -126,15 +123,8 @@ static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
elen = *pos++; elen = *pos++;
left -= 2; left -= 2;
if (elen > left) { if (elen > left)
#if 0 return;
if (net_ratelimit())
printk(KERN_DEBUG "IEEE 802.11 element parse "
"failed (id=%d elen=%d left=%d)\n",
id, elen, left);
#endif
return ParseFailed;
}
switch (id) { switch (id) {
case WLAN_EID_SSID: case WLAN_EID_SSID:
@ -201,28 +191,15 @@ static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
elems->ext_supp_rates_len = elen; elems->ext_supp_rates_len = elen;
break; break;
default: default:
#if 0
printk(KERN_DEBUG "IEEE 802.11 element parse ignored "
"unknown element (id=%d elen=%d)\n",
id, elen);
#endif
unknown++;
break; break;
} }
left -= elen; left -= elen;
pos += elen; pos += elen;
} }
/* Do not trigger error if left == 1 as Apple Airport base stations
* send AssocResps that are one spurious byte too long. */
return unknown ? ParseUnknown : ParseOK;
} }
static int ecw2cw(int ecw) static int ecw2cw(int ecw)
{ {
int cw = 1; int cw = 1;
@ -931,12 +908,7 @@ static void ieee80211_auth_challenge(struct net_device *dev,
printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name); printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
pos = mgmt->u.auth.variable; pos = mgmt->u.auth.variable;
if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
== ParseFailed) {
printk(KERN_DEBUG "%s: failed to parse Auth(challenge)\n",
dev->name);
return;
}
if (!elems.challenge) { if (!elems.challenge) {
printk(KERN_DEBUG "%s: no challenge IE in shared key auth " printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
"frame\n", dev->name); "frame\n", dev->name);
@ -1230,12 +1202,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
aid &= ~(BIT(15) | BIT(14)); aid &= ~(BIT(15) | BIT(14));
pos = mgmt->u.assoc_resp.variable; pos = mgmt->u.assoc_resp.variable;
if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
== ParseFailed) {
printk(KERN_DEBUG "%s: failed to parse AssocResp\n",
dev->name);
return;
}
if (!elems.supp_rates) { if (!elems.supp_rates) {
printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
@ -1459,7 +1426,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee802_11_elems elems; struct ieee802_11_elems elems;
size_t baselen; size_t baselen;
int channel, invalid = 0, clen; int channel, clen;
struct ieee80211_sta_bss *bss; struct ieee80211_sta_bss *bss;
struct sta_info *sta; struct sta_info *sta;
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@ -1505,9 +1472,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
#endif /* CONFIG_MAC80211_IBSS_DEBUG */ #endif /* CONFIG_MAC80211_IBSS_DEBUG */
} }
if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
&elems) == ParseFailed)
invalid = 1;
if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates && if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
@ -1724,9 +1689,7 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
if (baselen > len) if (baselen > len)
return; return;
if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
&elems) == ParseFailed)
return;
if (elems.erp_info && elems.erp_info_len >= 1) if (elems.erp_info && elems.erp_info_len >= 1)
ieee80211_handle_erp_ie(dev, elems.erp_info[0]); ieee80211_handle_erp_ie(dev, elems.erp_info[0]);

View file

@ -1623,11 +1623,6 @@ static struct vm_operations_struct packet_mmap_ops = {
.close =packet_mm_close, .close =packet_mm_close,
}; };
static inline struct page *pg_vec_endpage(char *one_pg_vec, unsigned int order)
{
return virt_to_page(one_pg_vec + (PAGE_SIZE << order) - 1);
}
static void free_pg_vec(char **pg_vec, unsigned int order, unsigned int len) static void free_pg_vec(char **pg_vec, unsigned int order, unsigned int len)
{ {
int i; int i;

View file

@ -2,9 +2,7 @@
# Traffic control configuration. # Traffic control configuration.
# #
menu "QoS and/or fair queueing" menuconfig NET_SCHED
config NET_SCHED
bool "QoS and/or fair queueing" bool "QoS and/or fair queueing"
select NET_SCH_FIFO select NET_SCH_FIFO
---help--- ---help---
@ -41,9 +39,6 @@ config NET_SCHED
The available schedulers are listed in the following questions; you The available schedulers are listed in the following questions; you
can say Y to as many as you like. If unsure, say N now. can say Y to as many as you like. If unsure, say N now.
config NET_SCH_FIFO
bool
if NET_SCHED if NET_SCHED
comment "Queueing/Scheduling" comment "Queueing/Scheduling"
@ -500,4 +495,5 @@ config NET_CLS_IND
endif # NET_SCHED endif # NET_SCHED
endmenu config NET_SCH_FIFO
bool

View file

@ -556,6 +556,7 @@ void dev_deactivate(struct net_device *dev)
{ {
struct Qdisc *qdisc; struct Qdisc *qdisc;
struct sk_buff *skb; struct sk_buff *skb;
int running;
spin_lock_bh(&dev->queue_lock); spin_lock_bh(&dev->queue_lock);
qdisc = dev->qdisc; qdisc = dev->qdisc;
@ -571,12 +572,31 @@ void dev_deactivate(struct net_device *dev)
dev_watchdog_down(dev); dev_watchdog_down(dev);
/* Wait for outstanding dev_queue_xmit calls. */ /* Wait for outstanding qdisc-less dev_queue_xmit calls. */
synchronize_rcu(); synchronize_rcu();
/* Wait for outstanding qdisc_run calls. */ /* Wait for outstanding qdisc_run calls. */
while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state)) do {
yield(); while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
yield();
/*
* Double-check inside queue lock to ensure that all effects
* of the queue run are visible when we return.
*/
spin_lock_bh(&dev->queue_lock);
running = test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state);
spin_unlock_bh(&dev->queue_lock);
/*
* The running flag should never be set at this point because
* we've already set dev->qdisc to noop_qdisc *inside* the same
* pair of spin locks. That is, if any qdisc_run starts after
* our initial test it should see the noop_qdisc and then
* clear the RUNNING bit before dropping the queue lock. So
* if it is set here then we've found a bug.
*/
} while (WARN_ON_ONCE(running));
} }
void dev_init_scheduler(struct net_device *dev) void dev_init_scheduler(struct net_device *dev)