From 2966b66c25f81ad2b3298b651614c6a3be1a977f Mon Sep 17 00:00:00 2001 From: Kris Katterjohn Date: Mon, 23 Jan 2006 16:26:16 -0800 Subject: [NET]: more whitespace issues in net/core/filter.c This fixes some whitespace issues in net/core/filter.c Signed-off-by: Kris Katterjohn Signed-off-by: David S. Miller --- net/core/filter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/core/filter.c b/net/core/filter.c index 9540946a48f3..93fbd01d2259 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -64,7 +64,7 @@ static inline void *load_pointer(struct sk_buff *skb, int k, } /** - * sk_run_filter - run a filter on a socket + * sk_run_filter - run a filter on a socket * @skb: buffer to run the filter on * @filter: filter to apply * @flen: length of filter @@ -78,8 +78,8 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int { struct sock_filter *fentry; /* We walk down these */ void *ptr; - u32 A = 0; /* Accumulator */ - u32 X = 0; /* Index Register */ + u32 A = 0; /* Accumulator */ + u32 X = 0; /* Index Register */ u32 mem[BPF_MEMWORDS]; /* Scratch Memory Store */ u32 tmp; int k; -- cgit v1.2.3 From 8ae55f0489d9a3446fcdaf4ffedda249234b8572 Mon Sep 17 00:00:00 2001 From: Kris Katterjohn Date: Mon, 23 Jan 2006 16:28:02 -0800 Subject: [NET]: Fix some whitespace issues in af_packet.c Signed-off-by: Kris Katterjohn Signed-off-by: David S. Miller --- net/packet/af_packet.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index ee93abc71cb8..9db7dbdb16e6 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -365,7 +365,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, */ err = -EMSGSIZE; - if(len>dev->mtu+dev->hard_header_len) + if (len > dev->mtu + dev->hard_header_len) goto out_unlock; err = -ENOBUFS; @@ -935,7 +935,7 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, int add * Check legality */ - if(addr_len!=sizeof(struct sockaddr)) + if (addr_len != sizeof(struct sockaddr)) return -EINVAL; strlcpy(name,uaddr->sa_data,sizeof(name)); @@ -1092,7 +1092,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, * retries. */ - if(skb==NULL) + if (skb == NULL) goto out; /* @@ -1392,8 +1392,8 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, if (level != SOL_PACKET) return -ENOPROTOOPT; - if (get_user(len,optlen)) - return -EFAULT; + if (get_user(len, optlen)) + return -EFAULT; if (len < 0) return -EINVAL; @@ -1419,9 +1419,9 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, return -ENOPROTOOPT; } - if (put_user(len, optlen)) - return -EFAULT; - return 0; + if (put_user(len, optlen)) + return -EFAULT; + return 0; } -- cgit v1.2.3 From 8798b3fb714477f5c88dde102c149d2b3e1d8def Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 23 Jan 2006 16:32:45 -0800 Subject: [NET]: Fix skb fclone error path handling. On the error path if we allocated an fclone then we will free it in the wrong pool. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/skbuff.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/core/skbuff.c b/net/core/skbuff.c index d0732e9c8560..6766f118f070 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -135,13 +135,15 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here) struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, int fclone) { + kmem_cache_t *cache; struct skb_shared_info *shinfo; struct sk_buff *skb; u8 *data; + cache = fclone ? skbuff_fclone_cache : skbuff_head_cache; + /* Get the HEAD */ - skb = kmem_cache_alloc(fclone ? skbuff_fclone_cache : skbuff_head_cache, - gfp_mask & ~__GFP_DMA); + skb = kmem_cache_alloc(cache, gfp_mask & ~__GFP_DMA); if (!skb) goto out; @@ -180,7 +182,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, out: return skb; nodata: - kmem_cache_free(skbuff_head_cache, skb); + kmem_cache_free(cache, skb); skb = NULL; goto out; } -- cgit v1.2.3 From cabcac0b296cd9683bc168d60839729b720dc2b7 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 24 Jan 2006 12:46:33 -0800 Subject: [BONDING]: Remove CAP_NET_ADMIN requirement for INFOQUERY ioctl This information is already available via /proc/net/bonding/* therefore it doesn't make sense to require CAP_NET_ADMIN privileges. Original patch by Laurent Deniel Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/core/dev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/core/dev.c b/net/core/dev.c index fd070a098f20..ffb82073056e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2543,13 +2543,14 @@ int dev_ioctl(unsigned int cmd, void __user *arg) case SIOCBONDENSLAVE: case SIOCBONDRELEASE: case SIOCBONDSETHWADDR: - case SIOCBONDSLAVEINFOQUERY: - case SIOCBONDINFOQUERY: case SIOCBONDCHANGEACTIVE: case SIOCBRADDIF: case SIOCBRDELIF: if (!capable(CAP_NET_ADMIN)) return -EPERM; + /* fall through */ + case SIOCBONDSLAVEINFOQUERY: + case SIOCBONDINFOQUERY: dev_load(ifr.ifr_name); rtnl_lock(); ret = dev_ifsioc(&ifr, cmd); -- cgit v1.2.3 From 151bb0ffe51514979abf54063bb5c1dd49365137 Mon Sep 17 00:00:00 2001 From: Jerome Borsboom Date: Tue, 24 Jan 2006 12:57:19 -0800 Subject: [AF_KEY]: no message type set When returning a message to userspace in reply to a SADB_FLUSH or SADB_X_SPDFLUSH message, the type was not set for the returned PFKEY message. The patch below corrects this problem. Signed-off-by: Jerome Borsboom Signed-off-by: David S. Miller --- net/key/af_key.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net') diff --git a/net/key/af_key.c b/net/key/af_key.c index 43f1ce74187d..ae86d237a456 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1620,6 +1620,7 @@ static int key_notify_sa_flush(struct km_event *c) return -ENOBUFS; hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg)); hdr->sadb_msg_satype = pfkey_proto2satype(c->data.proto); + hdr->sadb_msg_type = SADB_FLUSH; hdr->sadb_msg_seq = c->seq; hdr->sadb_msg_pid = c->pid; hdr->sadb_msg_version = PF_KEY_V2; @@ -2385,6 +2386,7 @@ static int key_notify_policy_flush(struct km_event *c) if (!skb_out) return -ENOBUFS; hdr = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg)); + hdr->sadb_msg_type = SADB_X_SPDFLUSH; hdr->sadb_msg_seq = c->seq; hdr->sadb_msg_pid = c->pid; hdr->sadb_msg_version = PF_KEY_V2; -- cgit v1.2.3 From 7add2a439868d636910fb6a216b12c7392778956 Mon Sep 17 00:00:00 2001 From: David L Stevens Date: Tue, 24 Jan 2006 13:06:39 -0800 Subject: [IPV6] MLDv2: fix change records when transitioning to/from inactive The following patch fixes these problems in MLDv2: 1) Add/remove "delete" records for sending change reports when addition of a filter results in that filter transitioning to/from inactive. [same as recent IPv4 IGMPv3 fix] 2) Remove 2 redundant "group_type" checks (can't be IPV6_ADDR_ANY within that loop, so checks are always true) 3) change an is_in() "return 0" to "return type == MLD2_MODE_IS_INCLUDE". It should always be "0" to get here, but it improves code locality to not assume it, and if some race allowed otherwise, doing the check would return the correct result. Signed-off-by: David L Stevens Signed-off-by: David S. Miller --- net/ipv6/mcast.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 6c05c7978bef..4420948a1bfe 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1252,8 +1252,7 @@ int igmp6_event_query(struct sk_buff *skb) } } else { for (ma = idev->mc_list; ma; ma=ma->next) { - if (group_type != IPV6_ADDR_ANY && - !ipv6_addr_equal(group, &ma->mca_addr)) + if (!ipv6_addr_equal(group, &ma->mca_addr)) continue; spin_lock_bh(&ma->mca_lock); if (ma->mca_flags & MAF_TIMER_RUNNING) { @@ -1268,11 +1267,10 @@ int igmp6_event_query(struct sk_buff *skb) ma->mca_flags &= ~MAF_GSQUERY; } if (!(ma->mca_flags & MAF_GSQUERY) || - mld_marksources(ma, ntohs(mlh2->nsrcs), mlh2->srcs)) + mld_marksources(ma, ntohs(mlh2->nsrcs), mlh2->srcs)) igmp6_group_queried(ma, max_delay); spin_unlock_bh(&ma->mca_lock); - if (group_type != IPV6_ADDR_ANY) - break; + break; } } read_unlock_bh(&idev->lock); @@ -1351,7 +1349,7 @@ static int is_in(struct ifmcaddr6 *pmc, struct ip6_sf_list *psf, int type, * in all filters */ if (psf->sf_count[MCAST_INCLUDE]) - return 0; + return type == MLD2_MODE_IS_INCLUDE; return pmc->mca_sfcount[MCAST_EXCLUDE] == psf->sf_count[MCAST_EXCLUDE]; } @@ -1966,7 +1964,7 @@ static void sf_markstate(struct ifmcaddr6 *pmc) static int sf_setstate(struct ifmcaddr6 *pmc) { - struct ip6_sf_list *psf; + struct ip6_sf_list *psf, *dpsf; int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE]; int qrv = pmc->idev->mc_qrv; int new_in, rv; @@ -1978,8 +1976,48 @@ static int sf_setstate(struct ifmcaddr6 *pmc) !psf->sf_count[MCAST_INCLUDE]; } else new_in = psf->sf_count[MCAST_INCLUDE] != 0; - if (new_in != psf->sf_oldin) { - psf->sf_crcount = qrv; + if (new_in) { + if (!psf->sf_oldin) { + struct ip6_sf_list *prev = 0; + + for (dpsf=pmc->mca_tomb; dpsf; + dpsf=dpsf->sf_next) { + if (ipv6_addr_equal(&dpsf->sf_addr, + &psf->sf_addr)) + break; + prev = dpsf; + } + if (dpsf) { + if (prev) + prev->sf_next = dpsf->sf_next; + else + pmc->mca_tomb = dpsf->sf_next; + kfree(dpsf); + } + psf->sf_crcount = qrv; + rv++; + } + } else if (psf->sf_oldin) { + psf->sf_crcount = 0; + /* + * add or update "delete" records if an active filter + * is now inactive + */ + for (dpsf=pmc->mca_tomb; dpsf; dpsf=dpsf->sf_next) + if (ipv6_addr_equal(&dpsf->sf_addr, + &psf->sf_addr)) + break; + if (!dpsf) { + dpsf = (struct ip6_sf_list *) + kmalloc(sizeof(*dpsf), GFP_ATOMIC); + if (!dpsf) + continue; + *dpsf = *psf; + /* pmc->mca_lock held by callers */ + dpsf->sf_next = pmc->mca_tomb; + pmc->mca_tomb = dpsf; + } + dpsf->sf_crcount = qrv; rv++; } } -- cgit v1.2.3 From 81845c21dc1ec7ce2bf12845dbc01e4880f9ea9a Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Mon, 30 Jan 2006 15:59:54 -0800 Subject: [SCTP]: correct the number of INIT retransmissions We currently count the initial INIT/COOKIE_ECHO chunk toward the retransmit count and thus sends a total of sctp_max_retrans_init chunks. The correct behavior is to retransmit the chunk sctp_max_retrans_init in addition to sending the original. Signed-off-by: Vlad Yasevich Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller --- net/sctp/sm_statefuns.c | 6 +++--- net/sctp/socket.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 71c9a961c321..018f169a50e9 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -2122,7 +2122,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, struct sctp_bind_addr *bp; int attempts = asoc->init_err_counter + 1; - if (attempts >= asoc->max_init_attempts) { + if (attempts > asoc->max_init_attempts) { sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_U32(SCTP_ERROR_STALE_COOKIE)); return SCTP_DISPOSITION_DELETE_TCB; @@ -4640,7 +4640,7 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n"); - if (attempts < asoc->max_init_attempts) { + if (attempts <= asoc->max_init_attempts) { bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); if (!repl) @@ -4697,7 +4697,7 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n"); - if (attempts < asoc->max_init_attempts) { + if (attempts <= asoc->max_init_attempts) { repl = sctp_make_cookie_echo(asoc, NULL); if (!repl) return SCTP_DISPOSITION_NOMEM; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index fb1821d9f338..0ea947eb6813 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -5426,7 +5426,7 @@ out: return err; do_error: - if (asoc->init_err_counter + 1 >= asoc->max_init_attempts) + if (asoc->init_err_counter + 1 > asoc->max_init_attempts) err = -ETIMEDOUT; else err = -ECONNREFUSED; -- cgit v1.2.3 From e2c2fc2c8f3750e1f7ffbb3ac2b885a49416110c Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Mon, 30 Jan 2006 16:00:40 -0800 Subject: [SCTP]: heartbeats exceed maximum retransmssion limit The number of HEARTBEAT chunks that an association may transmit is limited by Association.Max.Retrans count; however, the code allows us to send one extra heartbeat. This patch limits the number of heartbeats to the maximum count. Signed-off-by: Vlad Yasevich Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller --- net/sctp/sm_statefuns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 018f169a50e9..2b9a832b29a7 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -884,7 +884,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep, { struct sctp_transport *transport = (struct sctp_transport *) arg; - if (asoc->overall_error_count > asoc->max_retrans) { + if (asoc->overall_error_count >= asoc->max_retrans) { /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_NO_ERROR)); -- cgit v1.2.3 From c5d90e000437a463440c1fe039011a02583a9ee5 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 30 Jan 2006 20:27:17 -0800 Subject: [IPV4] igmp: remove pointless printk This is easily triggerable by sending bogus packets, allowing a malicious user to flood remote logs. Signed-off-by: Dave Jones Signed-off-by: David S. Miller --- net/ipv4/igmp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'net') diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index d8ce7133cd8f..f70ba622c856 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -970,7 +970,6 @@ int igmp_rcv(struct sk_buff *skb) case IGMP_MTRACE_RESP: break; default: - NETDEBUG(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type); } drop: -- cgit v1.2.3 From 2c74088e4104a2a82bd773f79ae0344c22eceb8c Mon Sep 17 00:00:00 2001 From: Baruch Even Date: Mon, 30 Jan 2006 20:54:39 -0800 Subject: [TCP] H-TCP: Fix accounting This fixes the accounting in H-TCP, the ccount variable is also adjusted a few lines above this one. This line was not supposed to be there and wasn't there in the patches originally submitted, the four patches submitted were merged to one and in that merge the bug was introduced. Signed-Off-By: Baruch Even Signed-off-by: David S. Miller --- net/ipv4/tcp_htcp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'net') diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c index 3284cfb993e6..128de4d7c0b7 100644 --- a/net/ipv4/tcp_htcp.c +++ b/net/ipv4/tcp_htcp.c @@ -230,7 +230,6 @@ static void htcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, if (tp->snd_cwnd < tp->snd_cwnd_clamp) tp->snd_cwnd++; tp->snd_cwnd_cnt = 0; - ca->ccount++; } } } -- cgit v1.2.3 From dd1c1853e2742f4938b271dbe0cee735e2ffa3d9 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 31 Jan 2006 13:11:41 -0800 Subject: Fix ipv4/igmp.c compile with gcc-4 and IP_MULTICAST Modern versions of gcc do not like case statements at the end of a block statement: you need at least an empty statement. Using just a "break;" is preferred for visual style. Signed-off-by: Linus Torvalds --- net/ipv4/igmp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index f70ba622c856..0b4e95f93dad 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -970,6 +970,7 @@ int igmp_rcv(struct sk_buff *skb) case IGMP_MTRACE_RESP: break; default: + break; } drop: -- cgit v1.2.3 From 5d39a795bfa217b5f7637028c83ab5cb291f37bf Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 31 Jan 2006 17:35:35 -0800 Subject: [IPV4]: Always set fl.proto in ip_route_newports ip_route_newports uses the struct flowi from the struct rtable returned by ip_route_connect for the new route lookup and just replaces the port numbers if they have changed. If an IPsec policy exists which doesn't match port 0 the struct flowi won't have the proto field set and no xfrm lookup is done for the changed ports. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/route.h | 5 +++-- net/dccp/ipv4.c | 3 ++- net/ipv4/tcp_ipv4.c | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/include/net/route.h b/include/net/route.h index e3e5436f8017..9c04f15090d2 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -170,8 +170,8 @@ static inline int ip_route_connect(struct rtable **rp, u32 dst, return ip_route_output_flow(rp, &fl, sk, 0); } -static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport, - struct sock *sk) +static inline int ip_route_newports(struct rtable **rp, u8 protocol, + u16 sport, u16 dport, struct sock *sk) { if (sport != (*rp)->fl.fl_ip_sport || dport != (*rp)->fl.fl_ip_dport) { @@ -180,6 +180,7 @@ static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport, memcpy(&fl, &(*rp)->fl, sizeof(fl)); fl.fl_ip_sport = sport; fl.fl_ip_dport = dport; + fl.proto = protocol; ip_rt_put(*rp); *rp = NULL; return ip_route_output_flow(rp, &fl, sk, 0); diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 00f983226672..dc0487b5bace 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -119,7 +119,8 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (err != 0) goto failure; - err = ip_route_newports(&rt, inet->sport, inet->dport, sk); + err = ip_route_newports(&rt, IPPROTO_DCCP, inet->sport, inet->dport, + sk); if (err != 0) goto failure; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 6ea353907af5..1ac35a65b2e5 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -236,7 +236,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (err) goto failure; - err = ip_route_newports(&rt, inet->sport, inet->dport, sk); + err = ip_route_newports(&rt, IPPROTO_TCP, inet->sport, inet->dport, sk); if (err) goto failure; -- cgit v1.2.3 From 3f4cfc2d11c9e29709e6f0f3add54039614d847a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 31 Jan 2006 17:44:07 -0800 Subject: [BRIDGE]: Fix device delete race. This is a simpler fix for the two races in bridge device removal. The Xen race of delif and notify is managed now by a new deleted flag. No need for barriers or other locking because of rtnl mutex. The del_timer_sync()'s are unnecessary, because br_stp_disable_port delete's the timers, and they will finish running before RCU callback. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_if.c | 21 +++++++++++++++------ net/bridge/br_private.h | 1 + 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index ba442883e877..da687c8dc6ff 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -104,6 +104,7 @@ static void destroy_nbp(struct net_bridge_port *p) { struct net_device *dev = p->dev; + dev->br_port = NULL; p->br = NULL; p->dev = NULL; dev_put(dev); @@ -118,13 +119,24 @@ static void destroy_nbp_rcu(struct rcu_head *head) destroy_nbp(p); } -/* called with RTNL */ +/* Delete port(interface) from bridge is done in two steps. + * via RCU. First step, marks device as down. That deletes + * all the timers and stops new packets from flowing through. + * + * Final cleanup doesn't occur until after all CPU's finished + * processing packets. + * + * Protected from multiple admin operations by RTNL mutex + */ static void del_nbp(struct net_bridge_port *p) { struct net_bridge *br = p->br; struct net_device *dev = p->dev; - dev->br_port = NULL; + /* Race between RTNL notify and RCU callback */ + if (p->deleted) + return; + dev_set_promiscuity(dev, -1); cancel_delayed_work(&p->carrier_check); @@ -132,16 +144,13 @@ static void del_nbp(struct net_bridge_port *p) spin_lock_bh(&br->lock); br_stp_disable_port(p); + p->deleted = 1; spin_unlock_bh(&br->lock); br_fdb_delete_by_port(br, p); list_del_rcu(&p->list); - del_timer_sync(&p->message_age_timer); - del_timer_sync(&p->forward_delay_timer); - del_timer_sync(&p->hold_timer); - call_rcu(&p->rcu, destroy_nbp_rcu); } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index c5bd631ffcd5..e330b17b6d81 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -68,6 +68,7 @@ struct net_bridge_port /* STP */ u8 priority; u8 state; + u8 deleted; u16 port_no; unsigned char topology_change_ack; unsigned char config_pending; -- cgit v1.2.3 From f9d9516db71eb3a8547948cdddc139eb1c1b9aee Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Tue, 31 Jan 2006 17:47:02 -0800 Subject: [NET]: Do not export inet_bind_bucket_create twice. inet_bind_bucket_create was exported twice. Keep the export in the file where inet_bind_bucket_create is defined. Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 1 - 1 file changed, 1 deletion(-) (limited to 'net') diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1ac35a65b2e5..233bdf259965 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1845,7 +1845,6 @@ void __init tcp_v4_init(struct net_proto_family *ops) } EXPORT_SYMBOL(ipv4_specific); -EXPORT_SYMBOL(inet_bind_bucket_create); EXPORT_SYMBOL(tcp_hashinfo); EXPORT_SYMBOL(tcp_prot); EXPORT_SYMBOL(tcp_unhash); -- cgit v1.2.3 From 78b910429e2c037533d2a7bd9e95b4f94f905ef8 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 31 Jan 2006 17:51:44 -0800 Subject: [IPV6] tcp_v6_send_synack: release the destination This patch fix dst reference counting in tcp_v6_send_synack Analysis: Currently tcp_v6_send_synack is never called with a dst entry so dst always comes in as NULL. ip6_dst_lookup calls ip6_route_output which calls dst_hold before it returns the dst entry. Neither xfrm_lookup nor tcp_make_synack consume the dst entry so we still have a dst_entry with a bumped refrence count at the end of this function. Therefore we need to call dst_release just before we return just like tcp_v4_send_synack does. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 66d04004afda..ca9cf6853755 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -515,6 +515,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, done: if (opt && opt != np->opt) sock_kfree_s(sk, opt, opt->tot_len); + dst_release(dst); return err; } -- cgit v1.2.3 From 0cbd782507c502428c8ab3e91bee3940c19ac4d4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 31 Jan 2006 17:53:37 -0800 Subject: [DCCP] ipv6: dccp_v6_send_response() has a DST leak too. It was copy&pasted from tcp_v6_send_synack() which has a DST leak recently fixed by Eric W. Biederman. So dccp_v6_send_response() needs the same fix too. Signed-off-by: David S. Miller --- net/dccp/ipv6.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index df074259f9c3..80c4d048869e 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -468,6 +468,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, done: if (opt && opt != np->opt) sock_kfree_s(sk, opt, opt->tot_len); + dst_release(dst); return err; } -- cgit v1.2.3 From 99acf0442111cc452ac1b93868dde8f6ff37a989 Mon Sep 17 00:00:00 2001 From: Martin Waitz Date: Wed, 1 Feb 2006 03:06:56 -0800 Subject: [PATCH] DocBook: fix some kernel-doc comments in net/sunrpc Fix the syntax of some kernel-doc comments Signed-off-by: Martin Waitz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- net/sunrpc/sched.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 7415406aa1ae..802d4fe0f55c 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -908,10 +908,10 @@ void rpc_release_task(struct rpc_task *task) /** * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it - * @clnt - pointer to RPC client - * @flags - RPC flags - * @ops - RPC call ops - * @data - user call data + * @clnt: pointer to RPC client + * @flags: RPC flags + * @ops: RPC call ops + * @data: user call data */ struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *ops, @@ -930,6 +930,7 @@ EXPORT_SYMBOL(rpc_run_task); /** * rpc_find_parent - find the parent of a child task. * @child: child task + * @parent: parent task * * Checks that the parent task is still sleeping on the * queue 'childq'. If so returns a pointer to the parent. -- cgit v1.2.3 From 8a3177604b729ec3b80e43790ee978863ac7551b Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 1 Feb 2006 12:18:36 -0500 Subject: SUNRPC: Fix a lock recursion in the auth_gss downcall When we look up a new cred in the auth_gss downcall so that we can stuff the credcache, we do not want that lookup to queue up an upcall in order to initialise it. To do an upcall here not only redundant, but since we are already holding the inode->i_mutex, it will trigger a lock recursion. This patch allows rpcauth cache searches to indicate that they can cope with uninitialised credentials. Signed-off-by: Trond Myklebust --- include/linux/sunrpc/auth.h | 5 +++++ net/sunrpc/auth.c | 17 ++++++++++------- net/sunrpc/auth_gss/auth_gss.c | 25 +++++++++++++++++++------ net/sunrpc/auth_unix.c | 6 +++--- 4 files changed, 37 insertions(+), 16 deletions(-) (limited to 'net') diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index b68c11a2d6dd..bfc5fb279539 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h @@ -50,6 +50,7 @@ struct rpc_cred { }; #define RPCAUTH_CRED_LOCKED 0x0001 #define RPCAUTH_CRED_UPTODATE 0x0002 +#define RPCAUTH_CRED_NEW 0x0004 #define RPCAUTH_CRED_MAGIC 0x0f4aa4f0 @@ -87,6 +88,10 @@ struct rpc_auth { * uid/gid, fs[ug]id, gids) */ +/* Flags for rpcauth_lookupcred() */ +#define RPCAUTH_LOOKUP_NEW 0x01 /* Accept an uninitialised cred */ +#define RPCAUTH_LOOKUP_ROOTCREDS 0x02 /* This really ought to go! */ + /* * Client authentication ops */ diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 9ac1b8c26c01..1ca89c36da7a 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c @@ -184,7 +184,7 @@ rpcauth_gc_credcache(struct rpc_auth *auth, struct hlist_head *free) */ struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, - int taskflags) + int flags) { struct rpc_cred_cache *cache = auth->au_credcache; HLIST_HEAD(free); @@ -193,7 +193,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, *cred = NULL; int nr = 0; - if (!(taskflags & RPC_TASK_ROOTCREDS)) + if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) nr = acred->uid & RPC_CREDCACHE_MASK; retry: spin_lock(&rpc_credcache_lock); @@ -202,7 +202,7 @@ retry: hlist_for_each_safe(pos, next, &cache->hashtable[nr]) { struct rpc_cred *entry; entry = hlist_entry(pos, struct rpc_cred, cr_hash); - if (entry->cr_ops->crmatch(acred, entry, taskflags)) { + if (entry->cr_ops->crmatch(acred, entry, flags)) { hlist_del(&entry->cr_hash); cred = entry; break; @@ -224,7 +224,7 @@ retry: rpcauth_destroy_credlist(&free); if (!cred) { - new = auth->au_ops->crcreate(auth, acred, taskflags); + new = auth->au_ops->crcreate(auth, acred, flags); if (!IS_ERR(new)) { #ifdef RPC_DEBUG new->cr_magic = RPCAUTH_CRED_MAGIC; @@ -238,7 +238,7 @@ retry: } struct rpc_cred * -rpcauth_lookupcred(struct rpc_auth *auth, int taskflags) +rpcauth_lookupcred(struct rpc_auth *auth, int flags) { struct auth_cred acred = { .uid = current->fsuid, @@ -250,7 +250,7 @@ rpcauth_lookupcred(struct rpc_auth *auth, int taskflags) dprintk("RPC: looking up %s cred\n", auth->au_ops->au_name); get_group_info(acred.group_info); - ret = auth->au_ops->lookup_cred(auth, &acred, taskflags); + ret = auth->au_ops->lookup_cred(auth, &acred, flags); put_group_info(acred.group_info); return ret; } @@ -265,11 +265,14 @@ rpcauth_bindcred(struct rpc_task *task) .group_info = current->group_info, }; struct rpc_cred *ret; + int flags = 0; dprintk("RPC: %4d looking up %s cred\n", task->tk_pid, task->tk_auth->au_ops->au_name); get_group_info(acred.group_info); - ret = auth->au_ops->lookup_cred(auth, &acred, task->tk_flags); + if (task->tk_flags & RPC_TASK_ROOTCREDS) + flags |= RPCAUTH_LOOKUP_ROOTCREDS; + ret = auth->au_ops->lookup_cred(auth, &acred, flags); if (!IS_ERR(ret)) task->tk_msg.rpc_cred = ret; else diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 8d782282ec19..03affcbf6292 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -158,6 +158,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) old = gss_cred->gc_ctx; gss_cred->gc_ctx = ctx; cred->cr_flags |= RPCAUTH_CRED_UPTODATE; + cred->cr_flags &= ~RPCAUTH_CRED_NEW; write_unlock(&gss_ctx_lock); if (old) gss_put_ctx(old); @@ -580,7 +581,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) } else { struct auth_cred acred = { .uid = uid }; spin_unlock(&gss_auth->lock); - cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, 0); + cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW); if (IS_ERR(cred)) { err = PTR_ERR(cred); goto err_put_ctx; @@ -758,13 +759,13 @@ gss_destroy_cred(struct rpc_cred *rc) * Lookup RPCSEC_GSS cred for the current process */ static struct rpc_cred * -gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) +gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) { - return rpcauth_lookup_credcache(auth, acred, taskflags); + return rpcauth_lookup_credcache(auth, acred, flags); } static struct rpc_cred * -gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) +gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) { struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); struct gss_cred *cred = NULL; @@ -785,13 +786,17 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) */ cred->gc_flags = 0; cred->gc_base.cr_ops = &gss_credops; + cred->gc_base.cr_flags = RPCAUTH_CRED_NEW; cred->gc_service = gss_auth->service; + /* Is the caller prepared to initialise the credential? */ + if (flags & RPCAUTH_LOOKUP_NEW) + goto out; do { err = gss_create_upcall(gss_auth, cred); } while (err == -EAGAIN); if (err < 0) goto out_err; - +out: return &cred->gc_base; out_err: @@ -801,13 +806,21 @@ out_err: } static int -gss_match(struct auth_cred *acred, struct rpc_cred *rc, int taskflags) +gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) { struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); + /* + * If the searchflags have set RPCAUTH_LOOKUP_NEW, then + * we don't really care if the credential has expired or not, + * since the caller should be prepared to reinitialise it. + */ + if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW)) + goto out; /* Don't match with creds that have expired. */ if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) return 0; +out: return (rc->cr_uid == acred->uid); } diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 1b3ed4fd1987..df14b6bfbf10 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c @@ -75,7 +75,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) atomic_set(&cred->uc_count, 1); cred->uc_flags = RPCAUTH_CRED_UPTODATE; - if (flags & RPC_TASK_ROOTCREDS) { + if (flags & RPCAUTH_LOOKUP_ROOTCREDS) { cred->uc_uid = 0; cred->uc_gid = 0; cred->uc_gids[0] = NOGROUP; @@ -108,12 +108,12 @@ unx_destroy_cred(struct rpc_cred *cred) * request root creds (e.g. for NFS swapping). */ static int -unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags) +unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) { struct unx_cred *cred = (struct unx_cred *) rcred; int i; - if (!(taskflags & RPC_TASK_ROOTCREDS)) { + if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) { int groups; if (cred->uc_uid != acred->uid -- cgit v1.2.3 From 9842ef3557abf5ec2fd92bfa6e29ce0e271b3f6e Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 1 Feb 2006 12:18:44 -0500 Subject: SUNRPC: rpc_timeout_upcall_queue should not sleep The function rpc_timeout_upcall_queue runs from a workqueue, and hence sleeping is not recommended. Convert the protection of the upcall queue from being mutex-based to being spinlock-based. Signed-off-by: Trond Myklebust --- net/sunrpc/rpc_pipe.c | 96 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 38 deletions(-) (limited to 'net') diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 9764c80ab0b2..7281746e6532 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -38,44 +38,42 @@ static kmem_cache_t *rpc_inode_cachep __read_mostly; #define RPC_UPCALL_TIMEOUT (30*HZ) -static void -__rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, int err) +static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, + void (*destroy_msg)(struct rpc_pipe_msg *), int err) { struct rpc_pipe_msg *msg; - void (*destroy_msg)(struct rpc_pipe_msg *); - destroy_msg = rpci->ops->destroy_msg; - while (!list_empty(head)) { + if (list_empty(head)) + return; + do { msg = list_entry(head->next, struct rpc_pipe_msg, list); - list_del_init(&msg->list); + list_del(&msg->list); msg->errno = err; destroy_msg(msg); - } -} - -static void -__rpc_purge_upcall(struct inode *inode, int err) -{ - struct rpc_inode *rpci = RPC_I(inode); - - __rpc_purge_list(rpci, &rpci->pipe, err); - rpci->pipelen = 0; + } while (!list_empty(head)); wake_up(&rpci->waitq); } static void rpc_timeout_upcall_queue(void *data) { + LIST_HEAD(free_list); struct rpc_inode *rpci = (struct rpc_inode *)data; struct inode *inode = &rpci->vfs_inode; + void (*destroy_msg)(struct rpc_pipe_msg *); - mutex_lock(&inode->i_mutex); - if (rpci->ops == NULL) - goto out; - if (rpci->nreaders == 0 && !list_empty(&rpci->pipe)) - __rpc_purge_upcall(inode, -ETIMEDOUT); -out: - mutex_unlock(&inode->i_mutex); + spin_lock(&inode->i_lock); + if (rpci->ops == NULL) { + spin_unlock(&inode->i_lock); + return; + } + destroy_msg = rpci->ops->destroy_msg; + if (rpci->nreaders == 0) { + list_splice_init(&rpci->pipe, &free_list); + rpci->pipelen = 0; + } + spin_unlock(&inode->i_lock); + rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT); } int @@ -84,7 +82,7 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) struct rpc_inode *rpci = RPC_I(inode); int res = -EPIPE; - mutex_lock(&inode->i_mutex); + spin_lock(&inode->i_lock); if (rpci->ops == NULL) goto out; if (rpci->nreaders) { @@ -100,7 +98,7 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) res = 0; } out: - mutex_unlock(&inode->i_mutex); + spin_unlock(&inode->i_lock); wake_up(&rpci->waitq); return res; } @@ -115,21 +113,29 @@ static void rpc_close_pipes(struct inode *inode) { struct rpc_inode *rpci = RPC_I(inode); + struct rpc_pipe_ops *ops; mutex_lock(&inode->i_mutex); - if (rpci->ops != NULL) { + ops = rpci->ops; + if (ops != NULL) { + LIST_HEAD(free_list); + + spin_lock(&inode->i_lock); rpci->nreaders = 0; - __rpc_purge_list(rpci, &rpci->in_upcall, -EPIPE); - __rpc_purge_upcall(inode, -EPIPE); - rpci->nwriters = 0; - if (rpci->ops->release_pipe) - rpci->ops->release_pipe(inode); + list_splice_init(&rpci->in_upcall, &free_list); + list_splice_init(&rpci->pipe, &free_list); + rpci->pipelen = 0; rpci->ops = NULL; + spin_unlock(&inode->i_lock); + rpc_purge_list(rpci, &free_list, ops->destroy_msg, -EPIPE); + rpci->nwriters = 0; + if (ops->release_pipe) + ops->release_pipe(inode); + cancel_delayed_work(&rpci->queue_timeout); + flush_scheduled_work(); } rpc_inode_setowner(inode, NULL); mutex_unlock(&inode->i_mutex); - cancel_delayed_work(&rpci->queue_timeout); - flush_scheduled_work(); } static struct inode * @@ -177,16 +183,26 @@ rpc_pipe_release(struct inode *inode, struct file *filp) goto out; msg = (struct rpc_pipe_msg *)filp->private_data; if (msg != NULL) { + spin_lock(&inode->i_lock); msg->errno = -EAGAIN; - list_del_init(&msg->list); + list_del(&msg->list); + spin_unlock(&inode->i_lock); rpci->ops->destroy_msg(msg); } if (filp->f_mode & FMODE_WRITE) rpci->nwriters --; - if (filp->f_mode & FMODE_READ) + if (filp->f_mode & FMODE_READ) { rpci->nreaders --; - if (!rpci->nreaders) - __rpc_purge_upcall(inode, -EAGAIN); + if (rpci->nreaders == 0) { + LIST_HEAD(free_list); + spin_lock(&inode->i_lock); + list_splice_init(&rpci->pipe, &free_list); + rpci->pipelen = 0; + spin_unlock(&inode->i_lock); + rpc_purge_list(rpci, &free_list, + rpci->ops->destroy_msg, -EAGAIN); + } + } if (rpci->ops->release_pipe) rpci->ops->release_pipe(inode); out: @@ -209,6 +225,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) } msg = filp->private_data; if (msg == NULL) { + spin_lock(&inode->i_lock); if (!list_empty(&rpci->pipe)) { msg = list_entry(rpci->pipe.next, struct rpc_pipe_msg, @@ -218,6 +235,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) filp->private_data = msg; msg->copied = 0; } + spin_unlock(&inode->i_lock); if (msg == NULL) goto out_unlock; } @@ -225,7 +243,9 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) res = rpci->ops->upcall(filp, msg, buf, len); if (res < 0 || msg->len == msg->copied) { filp->private_data = NULL; - list_del_init(&msg->list); + spin_lock(&inode->i_lock); + list_del(&msg->list); + spin_unlock(&inode->i_lock); rpci->ops->destroy_msg(msg); } out_unlock: -- cgit v1.2.3 From adb12f63e0f837078c6832fa2c90649ddeaab54f Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 1 Feb 2006 12:19:13 -0500 Subject: SUNRPC: Remove the deprecated function lookup_hash() from rpc_pipefs code Signed-off-by: Trond Myklebust --- net/sunrpc/rpc_pipe.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 7281746e6532..a5c0c7b6e151 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -630,7 +630,7 @@ rpc_lookup_negative(char *path, struct nameidata *nd) return ERR_PTR(error); dir = nd->dentry->d_inode; mutex_lock(&dir->i_mutex); - dentry = lookup_hash(nd); + dentry = lookup_one_len(nd->last.name, nd->dentry, nd->last.len); if (IS_ERR(dentry)) goto out_err; if (dentry->d_inode) { @@ -692,7 +692,7 @@ rpc_rmdir(char *path) return error; dir = nd.dentry->d_inode; mutex_lock(&dir->i_mutex); - dentry = lookup_hash(&nd); + dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len); if (IS_ERR(dentry)) { error = PTR_ERR(dentry); goto out_release; @@ -753,7 +753,7 @@ rpc_unlink(char *path) return error; dir = nd.dentry->d_inode; mutex_lock(&dir->i_mutex); - dentry = lookup_hash(&nd); + dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len); if (IS_ERR(dentry)) { error = PTR_ERR(dentry); goto out_release; -- cgit v1.2.3 From fba3bad488a2eec2d76c067edb7a5ff92ef42431 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 1 Feb 2006 12:19:27 -0500 Subject: SUNRPC: Move upcall out of auth->au_ops->crcreate() This fixes a bug whereby if two processes try to look up the same auth_gss credential, they may end up creating two creds, and triggering two upcalls because the upcall is performed before the credential is added to the credcache. Signed-off-by: Trond Myklebust --- include/linux/sunrpc/auth.h | 1 + net/sunrpc/auth.c | 8 ++++++++ net/sunrpc/auth_gss/auth_gss.c | 23 ++++++++++++++--------- 3 files changed, 23 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index bfc5fb279539..2647798b72c7 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h @@ -110,6 +110,7 @@ struct rpc_authops { struct rpc_credops { const char * cr_name; /* Name of the auth flavour */ + int (*cr_init)(struct rpc_auth *, struct rpc_cred *); void (*crdestroy)(struct rpc_cred *); int (*crmatch)(struct auth_cred *, struct rpc_cred *, int); diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 1ca89c36da7a..8d6f1a176b15 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c @@ -232,6 +232,14 @@ retry: goto retry; } else cred = new; + } else if ((cred->cr_flags & RPCAUTH_CRED_NEW) + && cred->cr_ops->cr_init != NULL + && !(flags & RPCAUTH_LOOKUP_NEW)) { + int res = cred->cr_ops->cr_init(auth, cred); + if (res < 0) { + put_rpccred(cred); + cred = ERR_PTR(res); + } } return (struct rpc_cred *) cred; diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 03affcbf6292..bb46efd92e57 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -788,15 +788,6 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) cred->gc_base.cr_ops = &gss_credops; cred->gc_base.cr_flags = RPCAUTH_CRED_NEW; cred->gc_service = gss_auth->service; - /* Is the caller prepared to initialise the credential? */ - if (flags & RPCAUTH_LOOKUP_NEW) - goto out; - do { - err = gss_create_upcall(gss_auth, cred); - } while (err == -EAGAIN); - if (err < 0) - goto out_err; -out: return &cred->gc_base; out_err: @@ -805,6 +796,19 @@ out_err: return ERR_PTR(err); } +static int +gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred) +{ + struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); + struct gss_cred *gss_cred = container_of(cred,struct gss_cred, gc_base); + int err; + + do { + err = gss_create_upcall(gss_auth, gss_cred); + } while (err == -EAGAIN); + return err; +} + static int gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) { @@ -1254,6 +1258,7 @@ static struct rpc_authops authgss_ops = { static struct rpc_credops gss_credops = { .cr_name = "AUTH_GSS", .crdestroy = gss_destroy_cred, + .cr_init = gss_cred_init, .crmatch = gss_match, .crmarshal = gss_marshal, .crrefresh = gss_refresh, -- cgit v1.2.3 From 42c5e15f18d63c1ecf79d52bdaf4ea31cd22416d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 2 Feb 2006 16:53:26 -0800 Subject: [NET] snap: needs hardware checksum fix The SNAP code pops off it's 5 byte header, but doesn't adjust the checksum. This would cause problems when using device that does IP over SNAP and hardware receive checksums. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/802/psnap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net') diff --git a/net/802/psnap.c b/net/802/psnap.c index 4d638944d933..34e42968b477 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c @@ -59,8 +59,10 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev, proto = find_snap_client(skb->h.raw); if (proto) { /* Pass the frame on. */ + u8 *hdr = skb->data; skb->h.raw += 5; skb_pull(skb, 5); + skb_postpull_rcsum(skb, hdr, 5); rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev); } else { skb->sk = NULL; -- cgit v1.2.3 From 4641e7a334adf6856300a98e7296dfc886c446af Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 2 Feb 2006 16:55:45 -0800 Subject: [IPV6]: Don't hold extra ref count in ipv6_ifa_notify Currently the logic in ipv6_ifa_notify is to hold an extra reference count for addrconf dst's that get added to the routing table. Thus, when addrconf dst entries are taken out of the routing table, we need to drop that dst. However, addrconf dst entries may be removed from the routing table by means other than __ipv6_ifa_notify. So we're faced with the choice of either fixing up all places where addrconf dst entries are removed, or dropping the extra reference count altogether. I chose the latter because the ifp itself always holds a dst reference count of 1 while it's alive. This is dropped just before we kfree the ifp object. Therefore we know that in __ipv6_ifa_notify we will always hold that count. This bug was found by Eric W. Biederman. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'net') diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index d328d5986143..1db50487916b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3321,9 +3321,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) switch (event) { case RTM_NEWADDR: - dst_hold(&ifp->rt->u.dst); - if (ip6_ins_rt(ifp->rt, NULL, NULL, NULL)) - dst_release(&ifp->rt->u.dst); + ip6_ins_rt(ifp->rt, NULL, NULL, NULL); if (ifp->idev->cnf.forwarding) addrconf_join_anycast(ifp); break; @@ -3334,8 +3332,6 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) dst_hold(&ifp->rt->u.dst); if (ip6_del_rt(ifp->rt, NULL, NULL, NULL)) dst_free(&ifp->rt->u.dst); - else - dst_release(&ifp->rt->u.dst); break; } } -- cgit v1.2.3 From 27852c26baab8b95fc9a2b3e8a18770ecd553f10 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 2 Feb 2006 16:57:31 -0800 Subject: [SCTP]: Fix 'fast retransmit' to send a TSN only once. SCTP used to "fast retransmit" a TSN every time we hit the number of missing reports for the TSN. However the Implementers Guide specifies that we should only "fast retransmit" a given TSN once. Subsequent retransmits should be timeouts only. Also change the number of missing reports to 3 as per the latest IG(similar to TCP). Signed-off-by: Vlad Yasevich Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 2 +- net/sctp/output.c | 2 +- net/sctp/outqueue.c | 12 +++++++----- 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 8c522ae031bb..072f407848a6 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -700,7 +700,7 @@ struct sctp_chunk { __u8 ecn_ce_done; /* Have we processed the ECN CE bit? */ __u8 pdiscard; /* Discard the whole packet now? */ __u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */ - __u8 fast_retransmit; /* Is this chunk fast retransmitted? */ + __s8 fast_retransmit; /* Is this chunk fast retransmitted? */ __u8 tsn_missing_report; /* Data chunk missing counter. */ }; diff --git a/net/sctp/output.c b/net/sctp/output.c index a40991ef72c9..437cba7260a4 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -608,7 +608,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet, * When a Fast Retransmit is being performed the sender SHOULD * ignore the value of cwnd and SHOULD NOT delay retransmission. */ - if (!chunk->fast_retransmit) + if (chunk->fast_retransmit <= 0) if (transport->flight_size >= transport->cwnd) { retval = SCTP_XMIT_RWND_FULL; goto finish; diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index efb72faba20c..f148f9576dd2 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -406,7 +406,7 @@ void sctp_retransmit_mark(struct sctp_outq *q, * chunks that are not yet acked should be added to the * retransmit queue. */ - if ((fast_retransmit && chunk->fast_retransmit) || + if ((fast_retransmit && (chunk->fast_retransmit > 0)) || (!fast_retransmit && !chunk->tsn_gap_acked)) { /* RFC 2960 6.2.1 Processing a Received SACK * @@ -603,7 +603,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, /* Mark the chunk as ineligible for fast retransmit * after it is retransmitted. */ - chunk->fast_retransmit = 0; + if (chunk->fast_retransmit > 0) + chunk->fast_retransmit = -1; *start_timer = 1; q->empty = 0; @@ -621,7 +622,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, list_for_each(lchunk1, lqueue) { chunk1 = list_entry(lchunk1, struct sctp_chunk, transmitted_list); - chunk1->fast_retransmit = 0; + if (chunk1->fast_retransmit > 0) + chunk1->fast_retransmit = -1; } } } @@ -1562,11 +1564,11 @@ static void sctp_mark_missing(struct sctp_outq *q, /* * M4) If any DATA chunk is found to have a * 'TSN.Missing.Report' - * value larger than or equal to 4, mark that chunk for + * value larger than or equal to 3, mark that chunk for * retransmission and start the fast retransmit procedure. */ - if (chunk->tsn_missing_report >= 4) { + if (chunk->tsn_missing_report >= 3) { chunk->fast_retransmit = 1; do_fast_retransmit = 1; } -- cgit v1.2.3 From f8addb3215bf58154f189017d934dfc06b62c75e Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 2 Feb 2006 16:59:16 -0800 Subject: [IPV4] multipath_wrandom: Fix softirq-unsafe spin lock usage The spin locks in multipath_wrandom may be obtained from either process context or softirq context depending on whether the packet is locally or remotely generated. Therefore we need to disable BH processing when taking these locks. This bug was found by Ingo's lock validator. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/multipath_wrandom.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c index d34a9fa608e0..342d0b9098f5 100644 --- a/net/ipv4/multipath_wrandom.c +++ b/net/ipv4/multipath_wrandom.c @@ -228,7 +228,7 @@ static void wrandom_set_nhinfo(__u32 network, struct multipath_dest *d, *target_dest = NULL; /* store the weight information for a certain route */ - spin_lock(&state[state_idx].lock); + spin_lock_bh(&state[state_idx].lock); /* find state entry for gateway or add one if necessary */ list_for_each_entry_rcu(r, &state[state_idx].head, list) { @@ -276,7 +276,7 @@ static void wrandom_set_nhinfo(__u32 network, * we are finished */ - spin_unlock(&state[state_idx].lock); + spin_unlock_bh(&state[state_idx].lock); } static void __multipath_free(struct rcu_head *head) @@ -302,7 +302,7 @@ static void wrandom_flush(void) for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) { struct multipath_route *r; - spin_lock(&state[i].lock); + spin_lock_bh(&state[i].lock); list_for_each_entry_rcu(r, &state[i].head, list) { struct multipath_dest *d; list_for_each_entry_rcu(d, &r->dests, list) { @@ -315,7 +315,7 @@ static void wrandom_flush(void) __multipath_free); } - spin_unlock(&state[i].lock); + spin_unlock_bh(&state[i].lock); } } -- cgit v1.2.3 From 6f4b6ec1cffcbb12cc47244381496d59b6a5a790 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 2 Feb 2006 17:01:13 -0800 Subject: [IPV6]: Fix illegal dst locking in softirq context. On Tue, Jan 31, 2006 at 10:24:32PM +0100, Ingo Molnar wrote: > > [] _write_lock+0x8/0x10 > [] inet6_destroy_sock+0x25/0x100 > [] tcp_v6_destroy_sock+0x12/0x20 > [] inet_csk_destroy_sock+0x4a/0x150 > [] tcp_rcv_state_process+0xd4c/0xdd0 > [] tcp_v4_do_rcv+0xa9/0x340 > [] tcp_v4_rcv+0x8eb/0x9d0 OK this is definitely broken. We should never touch the dst lock in softirq context. Since inet6_destroy_sock may be called from that context due to the asynchronous nature of sockets, we can't take the lock there. In fact this sk_dst_reset is totally redundant since all IPv6 sockets use inet_sock_destruct as their socket destructor which always cleans up the dst anyway. So the solution is to simply remove the call. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv6/af_inet6.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'net') diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 064ffab82a9f..6c9711ac1c03 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -369,12 +369,6 @@ int inet6_destroy_sock(struct sock *sk) struct sk_buff *skb; struct ipv6_txoptions *opt; - /* - * Release destination entry - */ - - sk_dst_reset(sk); - /* Release rx options */ if ((skb = xchg(&np->pktoptions, NULL)) != NULL) -- cgit v1.2.3 From f00c401b9b5f0a90e2eb05705f5988fbda0b082b Mon Sep 17 00:00:00 2001 From: Horms Date: Thu, 2 Feb 2006 17:03:18 -0800 Subject: [IPV4]: Remove suprious use of goto out: in icmp_reply This seems to be an artifact of the follwoing commit in February '02. e7e173af42dbf37b1d946f9ee00219cb3b2bea6a In a nutshell, goto out and return actually do the same thing, and both are called in this function. This patch removes out. Signed-Off-By: Horms Signed-off-by: David S. Miller --- net/ipv4/icmp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 105039eb7629..6bc0887b0834 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -385,7 +385,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) u32 daddr; if (ip_options_echo(&icmp_param->replyopts, skb)) - goto out; + return; if (icmp_xmit_lock()) return; @@ -416,7 +416,6 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) ip_rt_put(rt); out_unlock: icmp_xmit_unlock(); -out:; } -- cgit v1.2.3 From 0dec456d1fe73e0539625f0973ee8ef8fb805943 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 2 Feb 2006 20:40:09 -0800 Subject: [NET]: Add CONFIG_NETDEBUG to suppress bad packet messages. If you are on a hostile network, or are running protocol tests, you can easily get the logged swamped by messages about bad UDP and ICMP packets. This turns those messages off unless a config option is enabled. Signed-off-by: Stephen Hemminger Acked-by: Dave Jones Signed-off-by: David S. Miller --- include/net/sock.h | 8 ++++---- net/Kconfig | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/include/net/sock.h b/include/net/sock.h index 1806e5b61419..30758035d616 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1354,12 +1354,12 @@ extern int sock_get_timestamp(struct sock *, struct timeval __user *); * Enable debug/info messages */ -#if 0 -#define NETDEBUG(fmt, args...) do { } while (0) -#define LIMIT_NETDEBUG(fmt, args...) do { } while(0) -#else +#ifdef CONFIG_NETDEBUG #define NETDEBUG(fmt, args...) printk(fmt,##args) #define LIMIT_NETDEBUG(fmt, args...) do { if (net_ratelimit()) printk(fmt,##args); } while(0) +#else +#define NETDEBUG(fmt, args...) do { } while (0) +#define LIMIT_NETDEBUG(fmt, args...) do { } while(0) #endif /* diff --git a/net/Kconfig b/net/Kconfig index bc603d9aea56..5126f58d9c44 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -27,6 +27,13 @@ if NET menu "Networking options" +config NETDEBUG + bool "Network packet debugging" + help + You can say Y here if you want to get additional messages useful in + debugging bad packets, but can overwhelm logs under denial of service + attacks. + source "net/packet/Kconfig" source "net/unix/Kconfig" source "net/xfrm/Kconfig" -- cgit v1.2.3 From fa60cf7f64a00c16e95717e8dccdb128877e342a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 4 Feb 2006 02:09:34 -0800 Subject: [ICMP]: Fix extra dst release when ip_options_echo fails When two ip_route_output_key lookups in icmp_send were combined I forgot to change the error path for ip_options_echo to not drop the dst reference since it now sits before the dst lookup. To fix it we simply jump past the ip_rt_put call. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/icmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 6bc0887b0834..4d1c40972a4b 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -524,7 +524,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info) iph->tos; if (ip_options_echo(&icmp_param.replyopts, skb_in)) - goto ende; + goto out_unlock; /* -- cgit v1.2.3 From b633ad5fbf9e534142208700c58a530a4091eaab Mon Sep 17 00:00:00 2001 From: Marcus Sundberg Date: Sat, 4 Feb 2006 02:11:09 -0800 Subject: [NETFILTER]: ctnetlink: Fix subsystem used for expectation events The ctnetlink expectation events should use the NFNL_SUBSYS_CTNETLINK_EXP subsystem, not NFNL_SUBSYS_CTNETLINK. Signed-off-by: Marcus Sundberg Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_netlink.c | 2 +- net/netfilter/nf_conntrack_netlink.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index c9ebbe0d2d9c..b62518b5fc88 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -1216,7 +1216,7 @@ static int ctnetlink_expect_event(struct notifier_block *this, b = skb->tail; - type |= NFNL_SUBSYS_CTNETLINK << 8; + type |= NFNL_SUBSYS_CTNETLINK_EXP << 8; nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg)); nfmsg = NLMSG_DATA(nlh); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 73ab16bc7d40..e98d00c536c9 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1232,7 +1232,7 @@ static int ctnetlink_expect_event(struct notifier_block *this, b = skb->tail; - type |= NFNL_SUBSYS_CTNETLINK << 8; + type |= NFNL_SUBSYS_CTNETLINK_EXP << 8; nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg)); nfmsg = NLMSG_DATA(nlh); -- cgit v1.2.3 From 34f9a2e4deb760ddcb94cd0cd4f9ce18070d53d9 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 4 Feb 2006 02:11:41 -0800 Subject: [NETFILTER]: ctnetlink: add MODULE_ALIAS for expectation subsystem Add load-on-demand support for expectation request. eg. conntrack -L expect Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_netlink.c | 1 + net/netfilter/nf_conntrack_netlink.c | 1 + 2 files changed, 2 insertions(+) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index b62518b5fc88..e0b5926c76f9 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -1567,6 +1567,7 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = { }; MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); +MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP); static int __init ctnetlink_init(void) { diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index e98d00c536c9..9ff3463037e1 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1589,6 +1589,7 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = { }; MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); +MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP); static int __init ctnetlink_init(void) { -- cgit v1.2.3 From ddc8d029ac6813827849801bce2d8c8813070db6 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sat, 4 Feb 2006 02:12:14 -0800 Subject: [NETFILTER]: nf_conntrack: check address family when finding protocol module __nf_conntrack_{l3}proto_find() doesn't check the passed protocol family, then it's possible to touch out of the array which has only AF_MAX items. Spotted by Pablo Neira Ayuso. Signed-off-by: Yasuyuki Kozakai Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack_l3proto.h | 15 +++++++++------ net/netfilter/nf_conntrack_core.c | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index 67856eb93b43..dac43b15a5b0 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -88,12 +88,6 @@ extern struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX]; extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto); extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto); -static inline struct nf_conntrack_l3proto * -__nf_ct_l3proto_find(u_int16_t l3proto) -{ - return nf_ct_l3protos[l3proto]; -} - extern struct nf_conntrack_l3proto * nf_ct_l3proto_find_get(u_int16_t l3proto); @@ -103,4 +97,13 @@ extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p); extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4; extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6; extern struct nf_conntrack_l3proto nf_conntrack_generic_l3proto; + +static inline struct nf_conntrack_l3proto * +__nf_ct_l3proto_find(u_int16_t l3proto) +{ + if (unlikely(l3proto >= AF_MAX)) + return &nf_conntrack_generic_l3proto; + return nf_ct_l3protos[l3proto]; +} + #endif /*_NF_CONNTRACK_L3PROTO_H*/ diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 62bb509f05d4..0ce337a1d974 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -188,7 +188,7 @@ extern struct nf_conntrack_protocol nf_conntrack_generic_protocol; struct nf_conntrack_protocol * __nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol) { - if (unlikely(nf_ct_protos[l3proto] == NULL)) + if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL)) return &nf_conntrack_generic_protocol; return nf_ct_protos[l3proto][protocol]; -- cgit v1.2.3 From c2db292438c20c3f13db6e5563e0ce5b449bedac Mon Sep 17 00:00:00 2001 From: Holger Eitzenberger Date: Sat, 4 Feb 2006 02:13:14 -0800 Subject: [NETFILTER]: ULOG/nfnetlink_log: Use better default value for 'nlbufsiz' Performance tests showed that ULOG may fail on heavy loaded systems because of failed order-N allocations (N >= 1). The default value of 4096 is not optimal in the sense that it actually allocates _two_ contigous physical pages. Reasoning: ULOG uses alloc_skb(), which adds another ~300 bytes for skb_shared_info. This patch sets the default value to NLMSG_GOODSIZE and adds some documentation at the top. Signed-off-by: Holger Eitzenberger Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/bridge/netfilter/ebt_ulog.c | 2 +- net/ipv4/netfilter/ipt_ULOG.c | 6 +++++- net/netfilter/nfnetlink_log.c | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index ce617b3dbbb8..dbbf9f673b55 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -46,7 +46,7 @@ #define PRINTR(format, args...) do { if (net_ratelimit()) \ printk(format , ## args); } while (0) -static unsigned int nlbufsiz = 4096; +static unsigned int nlbufsiz = NLMSG_GOODSIZE; module_param(nlbufsiz, uint, 0600); MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) " "(defaults to 4096)"); diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 641dbc477650..2fe64133bba3 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -35,6 +35,10 @@ * each nlgroup you are using, so the total kernel memory usage increases * by that factor. * + * Actually you should use nlbufsiz a bit smaller than PAGE_SIZE, since + * nlbufsiz is used with alloc_skb, which adds another + * sizeof(struct skb_shared_info). Use NLMSG_GOODSIZE instead. + * * flushtimeout: * Specify, after how many hundredths of a second the queue should be * flushed even if it is not full yet. @@ -76,7 +80,7 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG); #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0) -static unsigned int nlbufsiz = 4096; +static unsigned int nlbufsiz = NLMSG_GOODSIZE; module_param(nlbufsiz, uint, 0400); MODULE_PARM_DESC(nlbufsiz, "netlink buffer size"); diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index e10512e229b6..50787af86d7d 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -37,7 +37,7 @@ #include "../bridge/br_private.h" #endif -#define NFULNL_NLBUFSIZ_DEFAULT 4096 +#define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE #define NFULNL_TIMEOUT_DEFAULT 100 /* every second */ #define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */ -- cgit v1.2.3 From ad2ad0f96546d6d56b2665bcc863c33ae57c49c4 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 4 Feb 2006 02:13:57 -0800 Subject: [NETFILTER]: Fix undersized skb allocation in ipt_ULOG/ebt_ulog/nfnetlink_log The skb allocated is always of size nlbufsize, even if that is smaller than the size needed for the current packet. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/bridge/netfilter/ebt_ulog.c | 8 +++++--- net/ipv4/netfilter/ipt_ULOG.c | 20 ++++++++++++-------- net/netfilter/nfnetlink_log.c | 18 +++++++++++------- 3 files changed, 28 insertions(+), 18 deletions(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index dbbf9f673b55..802baf755ef4 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -98,12 +98,14 @@ static void ulog_timer(unsigned long data) static struct sk_buff *ulog_alloc_skb(unsigned int size) { struct sk_buff *skb; + unsigned int n; - skb = alloc_skb(nlbufsiz, GFP_ATOMIC); + n = max(size, nlbufsiz); + skb = alloc_skb(n, GFP_ATOMIC); if (!skb) { PRINTR(KERN_ERR "ebt_ulog: can't alloc whole buffer " - "of size %ub!\n", nlbufsiz); - if (size < nlbufsiz) { + "of size %ub!\n", n); + if (n > size) { /* try to allocate only as much as we need for * current packet */ skb = alloc_skb(size, GFP_ATOMIC); diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 2fe64133bba3..180a9ea57b69 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -147,22 +147,26 @@ static void ulog_timer(unsigned long data) static struct sk_buff *ulog_alloc_skb(unsigned int size) { struct sk_buff *skb; + unsigned int n; /* alloc skb which should be big enough for a whole * multipart message. WARNING: has to be <= 131000 * due to slab allocator restrictions */ - skb = alloc_skb(nlbufsiz, GFP_ATOMIC); + n = max(size, nlbufsiz); + skb = alloc_skb(n, GFP_ATOMIC); if (!skb) { - PRINTR("ipt_ULOG: can't alloc whole buffer %ub!\n", - nlbufsiz); + PRINTR("ipt_ULOG: can't alloc whole buffer %ub!\n", n); - /* try to allocate only as much as we need for - * current packet */ + if (n > size) { + /* try to allocate only as much as we need for + * current packet */ - skb = alloc_skb(size, GFP_ATOMIC); - if (!skb) - PRINTR("ipt_ULOG: can't even allocate %ub\n", size); + skb = alloc_skb(size, GFP_ATOMIC); + if (!skb) + PRINTR("ipt_ULOG: can't even allocate %ub\n", + size); + } } return skb; diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 50787af86d7d..3b3c781b40c0 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -314,24 +314,28 @@ static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size, unsigned int pkt_size) { struct sk_buff *skb; + unsigned int n; UDEBUG("entered (%u, %u)\n", inst_size, pkt_size); /* alloc skb which should be big enough for a whole multipart * message. WARNING: has to be <= 128k due to slab restrictions */ - skb = alloc_skb(inst_size, GFP_ATOMIC); + n = max(inst_size, pkt_size); + skb = alloc_skb(n, GFP_ATOMIC); if (!skb) { PRINTR("nfnetlink_log: can't alloc whole buffer (%u bytes)\n", inst_size); - /* try to allocate only as much as we need for current - * packet */ + if (n > pkt_size) { + /* try to allocate only as much as we need for current + * packet */ - skb = alloc_skb(pkt_size, GFP_ATOMIC); - if (!skb) - PRINTR("nfnetlink_log: can't even alloc %u bytes\n", - pkt_size); + skb = alloc_skb(pkt_size, GFP_ATOMIC); + if (!skb) + PRINTR("nfnetlink_log: can't even alloc %u " + "bytes\n", pkt_size); + } } return skb; -- cgit v1.2.3 From a706124d0a4d9daaf6b705d01de3aff18deecea8 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 4 Feb 2006 02:14:24 -0800 Subject: [NETFILTER]: nfnetlink_queue: fix packet marking over netlink The packet marked is the netlink skb, not the queued skb. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nfnetlink_queue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 18ed9c5d209c..cac38b2e147a 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -825,7 +825,8 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, } if (nfqa[NFQA_MARK-1]) - skb->nfmark = ntohl(*(u_int32_t *)NFA_DATA(nfqa[NFQA_MARK-1])); + entry->skb->nfmark = ntohl(*(u_int32_t *) + NFA_DATA(nfqa[NFQA_MARK-1])); issue_verdict(entry, verdict); instance_put(queue); -- cgit v1.2.3 From 6f169300787ddb07326cc0338434a162dbab8539 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 4 Feb 2006 02:14:51 -0800 Subject: [NETFILTER]: Fix missing src port initialization in tftp expectation mask Reported by David Ahern , netfilter bugzilla #426. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_tftp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c index d3c5a371f993..4ba4463cec28 100644 --- a/net/ipv4/netfilter/ip_conntrack_tftp.c +++ b/net/ipv4/netfilter/ip_conntrack_tftp.c @@ -71,6 +71,7 @@ static int tftp_help(struct sk_buff **pskb, exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; exp->mask.src.ip = 0xffffffff; + exp->mask.src.u.udp.port = 0; exp->mask.dst.ip = 0xffffffff; exp->mask.dst.u.udp.port = 0xffff; exp->mask.dst.protonum = 0xff; -- cgit v1.2.3 From df4e9574a36748c3a4d9b03ffca6b42321a797a9 Mon Sep 17 00:00:00 2001 From: Samir Bellabes Date: Sat, 4 Feb 2006 02:16:06 -0800 Subject: [NETFILTER]: nf_conntrack: fix incorrect memset() size in FTP helper This memset() is executing with a bad size. According to Yasuyuki Kozakai, this memset() can be deleted, as 'ftp' is declared in global area. Signed-off-by: Samir Bellabes Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_ftp.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'net') diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index ab0c920f0d30..6f210f399762 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -657,8 +657,6 @@ static int __init init(void) /* FIXME should be configurable whether IPv4 and IPv6 FTP connections are tracked or not - YK */ for (i = 0; i < ports_c; i++) { - memset(&ftp[i], 0, sizeof(struct nf_conntrack_helper)); - ftp[i][0].tuple.src.l3num = PF_INET; ftp[i][1].tuple.src.l3num = PF_INET6; for (j = 0; j < 2; j++) { -- cgit v1.2.3 From ee4bb818ae35f68d1f848eae0a7b150a38eb4168 Mon Sep 17 00:00:00 2001 From: Kirill Korotaev Date: Sat, 4 Feb 2006 02:16:56 -0800 Subject: [NETFILTER]: Fix possible overflow in netfilters do_replace() netfilter's do_replace() can overflow on addition within SMP_ALIGN() and/or on multiplication by NR_CPUS, resulting in a buffer overflow on the copy_from_user(). In practice, the overflow on addition is triggerable on all systems, whereas the multiplication one might require much physical memory to be present due to the check above. Either is sufficient to overwrite arbitrary amounts of kernel memory. I really hate adding the same check to all 4 versions of do_replace(), but the code is duplicate... Found by Solar Designer during security audit of OpenVZ.org Signed-Off-By: Kirill Korotaev Signed-Off-By: Solar Designer Signed-off-by: Patrck McHardy Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 7 +++++++ net/ipv4/netfilter/arp_tables.c | 7 +++++++ net/ipv4/netfilter/ip_tables.c | 7 +++++++ net/ipv6/netfilter/ip6_tables.c | 7 +++++++ 4 files changed, 28 insertions(+) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 00729b3604f8..cbd4020cc84d 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -934,6 +934,13 @@ static int do_replace(void __user *user, unsigned int len) BUGPRINT("Entries_size never zero\n"); return -EINVAL; } + /* overflow check */ + if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS - + SMP_CACHE_BYTES) / sizeof(struct ebt_counter)) + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter)) + return -ENOMEM; + countersize = COUNTER_OFFSET(tmp.nentries) * (highest_possible_processor_id()+1); newinfo = (struct ebt_table_info *) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index afe3d8f8177d..dd1048be8a01 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -807,6 +807,13 @@ static int do_replace(void __user *user, unsigned int len) if (len != sizeof(tmp) + tmp.size) return -ENOPROTOOPT; + /* overflow check */ + if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS - + SMP_CACHE_BYTES) + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) + return -ENOMEM; + newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) return -ENOMEM; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 2371b2062c2d..16f47c675fef 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -921,6 +921,13 @@ do_replace(void __user *user, unsigned int len) if (len != sizeof(tmp) + tmp.size) return -ENOPROTOOPT; + /* overflow check */ + if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS - + SMP_CACHE_BYTES) + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) + return -ENOMEM; + newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) return -ENOMEM; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 847068fd3367..74ff56c322f4 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -978,6 +978,13 @@ do_replace(void __user *user, unsigned int len) if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; + /* overflow check */ + if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS - + SMP_CACHE_BYTES) + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) + return -ENOMEM; + newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) return -ENOMEM; -- cgit v1.2.3 From e55f1bc5dcb60a47764f6eabd1501d2cb98fb2c4 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 4 Feb 2006 02:17:26 -0800 Subject: [NETFILTER]: Check policy length in policy match strict mode Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ipt_policy.c | 2 +- net/ipv6/netfilter/ip6t_policy.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ipt_policy.c b/net/ipv4/netfilter/ipt_policy.c index 18ca8258a1c5..a48949a3a750 100644 --- a/net/ipv4/netfilter/ipt_policy.c +++ b/net/ipv4/netfilter/ipt_policy.c @@ -89,7 +89,7 @@ match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info) return 0; } - return strict ? 1 : 0; + return strict ? i == info->len : 0; } static int match(const struct sk_buff *skb, diff --git a/net/ipv6/netfilter/ip6t_policy.c b/net/ipv6/netfilter/ip6t_policy.c index afe1cc4c18a5..9f38cd0a6489 100644 --- a/net/ipv6/netfilter/ip6t_policy.c +++ b/net/ipv6/netfilter/ip6t_policy.c @@ -91,7 +91,7 @@ match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info) return 0; } - return strict ? 1 : 0; + return strict ? i == info->len : 0; } static int match(const struct sk_buff *skb, -- cgit v1.2.3 From 878c41ce5747e1b417bdd92a694c33dc4bd6ec02 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 4 Feb 2006 02:17:55 -0800 Subject: [NETFILTER]: Fix ip6t_policy address matching Fix two bugs in ip6t_policy address matching: - misorder arguments to ip6_masked_addrcmp, mask must be the second argument - inversion incorrectly applied to the entire expression instead of just the address comparison Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv6/netfilter/ip6t_policy.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv6/netfilter/ip6t_policy.c b/net/ipv6/netfilter/ip6t_policy.c index 9f38cd0a6489..1d0f48276123 100644 --- a/net/ipv6/netfilter/ip6t_policy.c +++ b/net/ipv6/netfilter/ip6t_policy.c @@ -26,8 +26,9 @@ MODULE_LICENSE("GPL"); static inline int match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e) { -#define MATCH_ADDR(x,y,z) (!e->match.x || \ - ((ip6_masked_addrcmp((z), &e->x, &e->y)) == 0) ^ e->invert.x) +#define MATCH_ADDR(x,y,z) (!e->match.x || \ + ((!ip6_masked_addrcmp(&e->x, &e->y, z)) \ + ^ e->invert.x)) #define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) return MATCH_ADDR(saddr, smask, (struct in6_addr *)&x->props.saddr.a6) && -- cgit v1.2.3 From 0047c65a60fa3b6607b55e058ea6a89f39cb3f28 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 4 Feb 2006 02:19:09 -0800 Subject: [NETFILTER]: Prepare {ipt,ip6t}_policy match for x_tables unification The IPv4 and IPv6 version of the policy match are identical besides address comparison and the data structure used for userspace communication. Unify the data structures to break compatiblity now (before it is released), so we can port it to x_tables in 2.6.17. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter_ipv4/ipt_policy.h | 22 ++++++++++++++-------- include/linux/netfilter_ipv6/ip6t_policy.h | 22 ++++++++++++++-------- net/ipv4/netfilter/ipt_policy.c | 9 ++++++--- net/ipv6/netfilter/ip6t_policy.c | 4 ++-- 4 files changed, 36 insertions(+), 21 deletions(-) (limited to 'net') diff --git a/include/linux/netfilter_ipv4/ipt_policy.h b/include/linux/netfilter_ipv4/ipt_policy.h index 7fd1bec453f1..a3f6eff39d33 100644 --- a/include/linux/netfilter_ipv4/ipt_policy.h +++ b/include/linux/netfilter_ipv4/ipt_policy.h @@ -27,16 +27,22 @@ struct ipt_policy_spec reqid:1; }; +union ipt_policy_addr +{ + struct in_addr a4; + struct in6_addr a6; +}; + struct ipt_policy_elem { - u_int32_t saddr; - u_int32_t smask; - u_int32_t daddr; - u_int32_t dmask; - u_int32_t spi; - u_int32_t reqid; - u_int8_t proto; - u_int8_t mode; + union ipt_policy_addr saddr; + union ipt_policy_addr smask; + union ipt_policy_addr daddr; + union ipt_policy_addr dmask; + u_int32_t spi; + u_int32_t reqid; + u_int8_t proto; + u_int8_t mode; struct ipt_policy_spec match; struct ipt_policy_spec invert; diff --git a/include/linux/netfilter_ipv6/ip6t_policy.h b/include/linux/netfilter_ipv6/ip6t_policy.h index 5a93afcd2ff1..671bd818300f 100644 --- a/include/linux/netfilter_ipv6/ip6t_policy.h +++ b/include/linux/netfilter_ipv6/ip6t_policy.h @@ -27,16 +27,22 @@ struct ip6t_policy_spec reqid:1; }; +union ip6t_policy_addr +{ + struct in_addr a4; + struct in6_addr a6; +}; + struct ip6t_policy_elem { - struct in6_addr saddr; - struct in6_addr smask; - struct in6_addr daddr; - struct in6_addr dmask; - u_int32_t spi; - u_int32_t reqid; - u_int8_t proto; - u_int8_t mode; + union ip6t_policy_addr saddr; + union ip6t_policy_addr smask; + union ip6t_policy_addr daddr; + union ip6t_policy_addr dmask; + u_int32_t spi; + u_int32_t reqid; + u_int8_t proto; + u_int8_t mode; struct ip6t_policy_spec match; struct ip6t_policy_spec invert; diff --git a/net/ipv4/netfilter/ipt_policy.c b/net/ipv4/netfilter/ipt_policy.c index a48949a3a750..5a7a265280f9 100644 --- a/net/ipv4/netfilter/ipt_policy.c +++ b/net/ipv4/netfilter/ipt_policy.c @@ -26,10 +26,13 @@ MODULE_LICENSE("GPL"); static inline int match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e) { -#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) +#define MATCH_ADDR(x,y,z) (!e->match.x || \ + ((e->x.a4.s_addr == (e->y.a4.s_addr & (z))) \ + ^ e->invert.x)) +#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) - return MATCH(saddr, x->props.saddr.a4 & e->smask) && - MATCH(daddr, x->id.daddr.a4 & e->dmask) && + return MATCH_ADDR(saddr, smask, x->props.saddr.a4) && + MATCH_ADDR(daddr, dmask, x->id.daddr.a4) && MATCH(proto, x->id.proto) && MATCH(mode, x->props.mode) && MATCH(spi, x->id.spi) && diff --git a/net/ipv6/netfilter/ip6t_policy.c b/net/ipv6/netfilter/ip6t_policy.c index 1d0f48276123..3d39ec924041 100644 --- a/net/ipv6/netfilter/ip6t_policy.c +++ b/net/ipv6/netfilter/ip6t_policy.c @@ -26,8 +26,8 @@ MODULE_LICENSE("GPL"); static inline int match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e) { -#define MATCH_ADDR(x,y,z) (!e->match.x || \ - ((!ip6_masked_addrcmp(&e->x, &e->y, z)) \ +#define MATCH_ADDR(x,y,z) (!e->match.x || \ + ((!ip6_masked_addrcmp(&e->x.a6, &e->y.a6, z)) \ ^ e->invert.x)) #define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) -- cgit v1.2.3 From 7918d212df31fb7ddfb317c5a8dccdcec647d754 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 4 Feb 2006 02:19:46 -0800 Subject: [NETFILTER]: Fix check whether dst_entry needs to be released after NAT After DNAT the original dst_entry needs to be released if present so the packet doesn't skip input routing with its new address. The current check for DNAT in ip_nat_in is reversed and checks for SNAT. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_nat_standalone.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index ad438fb185b8..92c54999a19d 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -209,8 +209,8 @@ ip_nat_in(unsigned int hooknum, && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); - if (ct->tuplehash[dir].tuple.src.ip != - ct->tuplehash[!dir].tuple.dst.ip) { + if (ct->tuplehash[dir].tuple.dst.ip != + ct->tuplehash[!dir].tuple.src.ip) { dst_release((*pskb)->dst); (*pskb)->dst = NULL; } -- cgit v1.2.3 From 88a2a4ac6b671a4b0dd5d2d762418904c05f4104 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 4 Feb 2006 23:27:36 -0800 Subject: [PATCH] percpu data: only iterate over possible CPUs percpu_data blindly allocates bootmem memory to store NR_CPUS instances of cpudata, instead of allocating memory only for possible cpus. As a preparation for changing that, we need to convert various 0 -> NR_CPUS loops to use for_each_cpu(). (The above only applies to users of asm-generic/percpu.h. powerpc has gone it alone and is presently only allocating memory for present CPUs, so it's currently corrupting memory). Signed-off-by: Eric Dumazet Cc: "David S. Miller" Cc: James Bottomley Acked-by: Ingo Molnar Cc: Jens Axboe Cc: Anton Blanchard Acked-by: William Irwin Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/nmi.c | 2 +- block/ll_rw_blk.c | 2 +- drivers/scsi/scsi.c | 2 +- fs/file.c | 3 +-- kernel/sched.c | 2 +- mm/page_alloc.c | 10 ++++++---- net/core/dev.c | 2 +- net/core/utils.c | 4 ++-- net/ipv4/proc.c | 2 +- net/ipv6/proc.c | 2 +- net/socket.c | 2 +- 11 files changed, 17 insertions(+), 16 deletions(-) (limited to 'net') diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index d661703ac1cb..63f39a7e2c96 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -138,7 +138,7 @@ static int __init check_nmi_watchdog(void) if (nmi_watchdog == NMI_LOCAL_APIC) smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0); - for (cpu = 0; cpu < NR_CPUS; cpu++) + for_each_cpu(cpu) prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count; local_irq_enable(); mdelay((10*1000)/nmi_hz); // wait 10 ticks diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index f9fc07efd2da..e5aad8314585 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3453,7 +3453,7 @@ int __init blk_dev_init(void) iocontext_cachep = kmem_cache_create("blkdev_ioc", sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL); - for (i = 0; i < NR_CPUS; i++) + for_each_cpu(i) INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i)); open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 245ca99a641e..c551bb84dbfb 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -1245,7 +1245,7 @@ static int __init init_scsi(void) if (error) goto cleanup_sysctl; - for (i = 0; i < NR_CPUS; i++) + for_each_cpu(i) INIT_LIST_HEAD(&per_cpu(scsi_done_q, i)); devfs_mk_dir("scsi"); diff --git a/fs/file.c b/fs/file.c index fd066b261c75..cea7cbea11d0 100644 --- a/fs/file.c +++ b/fs/file.c @@ -379,7 +379,6 @@ static void __devinit fdtable_defer_list_init(int cpu) void __init files_defer_init(void) { int i; - /* Really early - can't use for_each_cpu */ - for (i = 0; i < NR_CPUS; i++) + for_each_cpu(i) fdtable_defer_list_init(i); } diff --git a/kernel/sched.c b/kernel/sched.c index f77f23f8f479..839466fdfb4c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -6109,7 +6109,7 @@ void __init sched_init(void) runqueue_t *rq; int i, j, k; - for (i = 0; i < NR_CPUS; i++) { + for_each_cpu(i) { prio_array_t *array; rq = cpu_rq(i); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 44b4eb4202d9..dde04ff4be31 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1213,18 +1213,21 @@ static void __get_page_state(struct page_state *ret, int nr, cpumask_t *cpumask) { int cpu = 0; - memset(ret, 0, sizeof(*ret)); + memset(ret, 0, nr * sizeof(unsigned long)); cpus_and(*cpumask, *cpumask, cpu_online_map); cpu = first_cpu(*cpumask); while (cpu < NR_CPUS) { unsigned long *in, *out, off; + if (!cpu_isset(cpu, *cpumask)) + continue; + in = (unsigned long *)&per_cpu(page_states, cpu); cpu = next_cpu(cpu, *cpumask); - if (cpu < NR_CPUS) + if (likely(cpu < NR_CPUS)) prefetch(&per_cpu(page_states, cpu)); out = (unsigned long *)ret; @@ -1886,8 +1889,7 @@ static void setup_pagelist_highmark(struct per_cpu_pageset *p, * not check if the processor is online before following the pageset pointer. * Other parts of the kernel may not check if the zone is available. */ -static struct per_cpu_pageset - boot_pageset[NR_CPUS]; +static struct per_cpu_pageset boot_pageset[NR_CPUS]; /* * Dynamically allocate memory for the diff --git a/net/core/dev.c b/net/core/dev.c index ffb82073056e..2afb0de95329 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3237,7 +3237,7 @@ static int __init net_dev_init(void) * Initialise the packet receive queues. */ - for (i = 0; i < NR_CPUS; i++) { + for_each_cpu(i) { struct softnet_data *queue; queue = &per_cpu(softnet_data, i); diff --git a/net/core/utils.c b/net/core/utils.c index ac1d1fcf8673..fdc4f38bc46c 100644 --- a/net/core/utils.c +++ b/net/core/utils.c @@ -121,7 +121,7 @@ void __init net_random_init(void) { int i; - for (i = 0; i < NR_CPUS; i++) { + for_each_cpu(i) { struct nrnd_state *state = &per_cpu(net_rand_state,i); __net_srandom(state, i+jiffies); } @@ -133,7 +133,7 @@ static int net_random_reseed(void) unsigned long seed[NR_CPUS]; get_random_bytes(seed, sizeof(seed)); - for (i = 0; i < NR_CPUS; i++) { + for_each_cpu(i) { struct nrnd_state *state = &per_cpu(net_rand_state,i); __net_srandom(state, seed[i]); } diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 39d49dc333a7..1b167c4bb3be 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -49,7 +49,7 @@ static int fold_prot_inuse(struct proto *proto) int res = 0; int cpu; - for (cpu = 0; cpu < NR_CPUS; cpu++) + for_each_cpu(cpu) res += proto->stats[cpu].inuse; return res; diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 50a13e75d70e..4238b1ed8860 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -38,7 +38,7 @@ static int fold_prot_inuse(struct proto *proto) int res = 0; int cpu; - for (cpu=0; cpustats[cpu].inuse; return res; diff --git a/net/socket.c b/net/socket.c index b38a263853c3..a00851f981db 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2078,7 +2078,7 @@ void socket_seq_show(struct seq_file *seq) int cpu; int counter = 0; - for (cpu = 0; cpu < NR_CPUS; cpu++) + for_each_cpu(cpu) counter += per_cpu(sockets_in_use, cpu); /* It can be negative, by the way. 8) */ -- cgit v1.2.3