Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6:
  tproxy: fixe a possible read from an invalid location in the socket match
  zd1211rw: use unaligned safe memcmp() in-place of compare_ether_addr()
  mac80211: use unaligned safe memcmp() in-place of compare_ether_addr()
  ipw2200: fix netif_*_queue() removal regression
  iwlwifi: clean key table in iwl_clear_stations_table function
  tcp: tcp_vegas ssthresh bug fix
  can: omit received RTR frames for single ID filter lists
  ATM: CVE-2008-5079: duplicate listen() on socket corrupts the vcc table
  netx-eth: initialize per device spinlock
  tcp: make urg+gso work for real this time
  enc28j60: Fix sporadic packet loss (corrected again)
  hysdn: fix writing outside the field on 64 bits
  b1isa: fix b1isa_exit() to really remove registered capi controllers
  can: Fix CAN_(EFF|RTR)_FLAG handling in can_filter
  Phonet: do not dump addresses from other namespaces
  netlabel: Fix a potential NULL pointer dereference
  bnx2: Add workaround to handle missed MSI.
  xfrm: Fix kernel panic when flush and dump SPD entries
This commit is contained in:
Linus Torvalds
2008-12-08 19:52:43 -08:00
21 changed files with 173 additions and 54 deletions
+5 -1
View File
@@ -293,7 +293,10 @@ static int svc_listen(struct socket *sock,int backlog)
error = -EINVAL;
goto out;
}
vcc_insert_socket(sk);
if (test_bit(ATM_VF_LISTEN, &vcc->flags)) {
error = -EADDRINUSE;
goto out;
}
set_bit(ATM_VF_WAITING, &vcc->flags);
prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local);
@@ -307,6 +310,7 @@ static int svc_listen(struct socket *sock,int backlog)
goto out;
}
set_bit(ATM_VF_LISTEN,&vcc->flags);
vcc_insert_socket(sk);
sk->sk_max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
error = -sk->sk_err;
out:
+52 -16
View File
@@ -319,23 +319,52 @@ static struct dev_rcv_lists *find_dev_rcv_lists(struct net_device *dev)
return n ? d : NULL;
}
/**
* find_rcv_list - determine optimal filterlist inside device filter struct
* @can_id: pointer to CAN identifier of a given can_filter
* @mask: pointer to CAN mask of a given can_filter
* @d: pointer to the device filter struct
*
* Description:
* Returns the optimal filterlist to reduce the filter handling in the
* receive path. This function is called by service functions that need
* to register or unregister a can_filter in the filter lists.
*
* A filter matches in general, when
*
* <received_can_id> & mask == can_id & mask
*
* so every bit set in the mask (even CAN_EFF_FLAG, CAN_RTR_FLAG) describe
* relevant bits for the filter.
*
* The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
* filter for error frames (CAN_ERR_FLAG bit set in mask). For error frames
* there is a special filterlist and a special rx path filter handling.
*
* Return:
* Pointer to optimal filterlist for the given can_id/mask pair.
* Constistency checked mask.
* Reduced can_id to have a preprocessed filter compare value.
*/
static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
struct dev_rcv_lists *d)
{
canid_t inv = *can_id & CAN_INV_FILTER; /* save flag before masking */
/* filter error frames */
/* filter for error frames in extra filterlist */
if (*mask & CAN_ERR_FLAG) {
/* clear CAN_ERR_FLAG in list entry */
/* clear CAN_ERR_FLAG in filter entry */
*mask &= CAN_ERR_MASK;
return &d->rx[RX_ERR];
}
/* ensure valid values in can_mask */
if (*mask & CAN_EFF_FLAG)
*mask &= (CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG);
else
*mask &= (CAN_SFF_MASK | CAN_RTR_FLAG);
/* with cleared CAN_ERR_FLAG we have a simple mask/value filterpair */
#define CAN_EFF_RTR_FLAGS (CAN_EFF_FLAG | CAN_RTR_FLAG)
/* ensure valid values in can_mask for 'SFF only' frame filtering */
if ((*mask & CAN_EFF_FLAG) && !(*can_id & CAN_EFF_FLAG))
*mask &= (CAN_SFF_MASK | CAN_EFF_RTR_FLAGS);
/* reduce condition testing at receive time */
*can_id &= *mask;
@@ -348,15 +377,19 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
if (!(*mask))
return &d->rx[RX_ALL];
/* use extra filterset for the subscription of exactly *ONE* can_id */
if (*can_id & CAN_EFF_FLAG) {
if (*mask == (CAN_EFF_MASK | CAN_EFF_FLAG)) {
/* RFC: a use-case for hash-tables in the future? */
return &d->rx[RX_EFF];
/* extra filterlists for the subscription of a single non-RTR can_id */
if (((*mask & CAN_EFF_RTR_FLAGS) == CAN_EFF_RTR_FLAGS)
&& !(*can_id & CAN_RTR_FLAG)) {
if (*can_id & CAN_EFF_FLAG) {
if (*mask == (CAN_EFF_MASK | CAN_EFF_RTR_FLAGS)) {
/* RFC: a future use-case for hash-tables? */
return &d->rx[RX_EFF];
}
} else {
if (*mask == (CAN_SFF_MASK | CAN_EFF_RTR_FLAGS))
return &d->rx_sff[*can_id];
}
} else {
if (*mask == CAN_SFF_MASK)
return &d->rx_sff[*can_id];
}
/* default: filter via can_id/can_mask */
@@ -589,7 +622,10 @@ static int can_rcv_filter(struct dev_rcv_lists *d, struct sk_buff *skb)
}
}
/* check CAN_ID specific entries */
/* check filterlists for single non-RTR can_ids */
if (can_id & CAN_RTR_FLAG)
return matches;
if (can_id & CAN_EFF_FLAG) {
hlist_for_each_entry_rcu(r, n, &d->rx[RX_EFF], list) {
if (r->can_id == can_id) {
+4 -3
View File
@@ -64,10 +64,11 @@
#define BCM_CAN_DLC_MASK 0x0F /* clean private flags in can_dlc by masking */
/* get best masking value for can_rx_register() for a given single can_id */
#define REGMASK(id) ((id & CAN_RTR_FLAG) | ((id & CAN_EFF_FLAG) ? \
(CAN_EFF_MASK | CAN_EFF_FLAG) : CAN_SFF_MASK))
#define REGMASK(id) ((id & CAN_EFF_FLAG) ? \
(CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG) : \
(CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG))
#define CAN_BCM_VERSION "20080415"
#define CAN_BCM_VERSION CAN_VERSION
static __initdata const char banner[] = KERN_INFO
"can: broadcast manager protocol (rev " CAN_BCM_VERSION ")\n";
+10 -12
View File
@@ -722,8 +722,7 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb)
static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb,
unsigned int mss_now)
{
if (skb->len <= mss_now || !sk_can_gso(sk) ||
tcp_urg_mode(tcp_sk(sk))) {
if (skb->len <= mss_now || !sk_can_gso(sk)) {
/* Avoid the costly divide in the normal
* non-TSO case.
*/
@@ -1029,10 +1028,6 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
/* Compute the current effective MSS, taking SACKs and IP options,
* and even PMTU discovery events into account.
*
* LARGESEND note: !tcp_urg_mode is overkill, only frames up to snd_up
* cannot be large. However, taking into account rare use of URG, this
* is not a big flaw.
*/
unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
{
@@ -1047,7 +1042,7 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
mss_now = tp->mss_cache;
if (large_allowed && sk_can_gso(sk) && !tcp_urg_mode(tp))
if (large_allowed && sk_can_gso(sk))
doing_tso = 1;
if (dst) {
@@ -1164,9 +1159,7 @@ static int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb,
{
int tso_segs = tcp_skb_pcount(skb);
if (!tso_segs ||
(tso_segs > 1 && (tcp_skb_mss(skb) != mss_now ||
tcp_urg_mode(tcp_sk(sk))))) {
if (!tso_segs || (tso_segs > 1 && tcp_skb_mss(skb) != mss_now)) {
tcp_set_skb_tso_segs(sk, skb, mss_now);
tso_segs = tcp_skb_pcount(skb);
}
@@ -1519,6 +1512,10 @@ static int tcp_mtu_probe(struct sock *sk)
* send_head. This happens as incoming acks open up the remote
* window for us.
*
* LARGESEND note: !tcp_urg_mode is overkill, only frames between
* snd_up-64k-mss .. snd_up cannot be large. However, taking into
* account rare use of URG, this is not a big flaw.
*
* Returns 1, if no segments are in flight and we have queued segments, but
* cannot send anything now because of SWS or another problem.
*/
@@ -1570,7 +1567,7 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
}
limit = mss_now;
if (tso_segs > 1)
if (tso_segs > 1 && !tcp_urg_mode(tp))
limit = tcp_mss_split_point(sk, skb, mss_now,
cwnd_quota);
@@ -1619,6 +1616,7 @@ void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
*/
void tcp_push_one(struct sock *sk, unsigned int mss_now)
{
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb = tcp_send_head(sk);
unsigned int tso_segs, cwnd_quota;
@@ -1633,7 +1631,7 @@ void tcp_push_one(struct sock *sk, unsigned int mss_now)
BUG_ON(!tso_segs);
limit = mss_now;
if (tso_segs > 1)
if (tso_segs > 1 && !tcp_urg_mode(tp))
limit = tcp_mss_split_point(sk, skb, mss_now,
cwnd_quota);
+2
View File
@@ -326,6 +326,8 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
tp->snd_cwnd = 2;
else if (tp->snd_cwnd > tp->snd_cwnd_clamp)
tp->snd_cwnd = tp->snd_cwnd_clamp;
tp->snd_ssthresh = tcp_current_ssthresh(sk);
}
/* Wipe the slate clean for the next RTT. */
+1 -1
View File
@@ -99,7 +99,7 @@ struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr)
sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]);
while (sta) {
if (compare_ether_addr(sta->sta.addr, addr) == 0)
if (memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
break;
sta = rcu_dereference(sta->hnext);
}
+1 -1
View File
@@ -141,7 +141,7 @@ socket_mt(const struct sk_buff *skb, const struct xt_match_param *par)
sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol,
saddr, daddr, sport, dport, par->in, false);
if (sk != NULL) {
bool wildcard = (inet_sk(sk)->rcv_saddr == 0);
bool wildcard = (sk->sk_state != TCP_TIME_WAIT && inet_sk(sk)->rcv_saddr == 0);
nf_tproxy_put_sock(sk);
if (wildcard)
+6 -4
View File
@@ -574,9 +574,10 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
&iface->addr4_list);
spin_unlock(&netlbl_unlhsh_lock);
if (list_entry == NULL)
if (list_entry != NULL)
entry = netlbl_unlhsh_addr4_entry(list_entry);
else
ret_val = -ENOENT;
entry = netlbl_unlhsh_addr4_entry(list_entry);
audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
audit_info);
@@ -634,9 +635,10 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
spin_lock(&netlbl_unlhsh_lock);
list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
spin_unlock(&netlbl_unlhsh_lock);
if (list_entry == NULL)
if (list_entry != NULL)
entry = netlbl_unlhsh_addr6_entry(list_entry);
else
ret_val = -ENOENT;
entry = netlbl_unlhsh_addr6_entry(list_entry);
audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
audit_info);
+3
View File
@@ -123,6 +123,7 @@ nla_put_failure:
static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
{
struct net *net = sock_net(skb->sk);
struct phonet_device *pnd;
int dev_idx = 0, dev_start_idx = cb->args[0];
int addr_idx = 0, addr_start_idx = cb->args[1];
@@ -131,6 +132,8 @@ static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
list_for_each_entry(pnd, &pndevs.list, list) {
u8 addr;
if (!net_eq(dev_net(pnd->netdev), net))
continue;
if (dev_idx > dev_start_idx)
addr_start_idx = 0;
if (dev_idx++ < dev_start_idx)
+1
View File
@@ -817,6 +817,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
continue;
hlist_del(&pol->bydst);
hlist_del(&pol->byidx);
list_del(&pol->walk.all);
write_unlock_bh(&xfrm_policy_lock);
xfrm_audit_policy_delete(pol, 1, audit_info->loginuid,