diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-07-15 03:32:22 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-07-15 03:32:22 +0000 |
commit | f1da2c3860e301527d56a1ef0b56c649ee7c4b1b (patch) | |
tree | 562b5d2e8b9cb62eb983d78ff6bcf9789e08fcf6 /net | |
parent | 00f11569ac8ca73cbcdef8822de1583e79aee571 (diff) |
Merge with Linux 2.4.0-test5-pre1. This works again on Origin UP.
The IP22 cache bugs which are plaguing some machines are still unfixed.
Diffstat (limited to 'net')
-rw-r--r-- | net/atm/mpoa_proc.c | 1 | ||||
-rw-r--r-- | net/core/netfilter.c | 12 | ||||
-rw-r--r-- | net/decnet/dn_route.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_core.c | 19 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_standalone.c | 11 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_fw_compat.c | 3 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_fw_compat_masq.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_core.c | 20 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_standalone.c | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_queue.c | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_tables.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_REJECT.c | 131 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 6 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 2 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 2 | ||||
-rw-r--r-- | net/irda/irmod.c | 6 | ||||
-rw-r--r-- | net/netlink/netlink_dev.c | 6 | ||||
-rw-r--r-- | net/sched/sch_cbq.c | 3 | ||||
-rw-r--r-- | net/socket.c | 2 | ||||
-rw-r--r-- | net/unix/garbage.c | 2 |
20 files changed, 210 insertions, 32 deletions
diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index 69d8b726d..1c79056bb 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c @@ -5,6 +5,7 @@ #include <linux/kernel.h> #include <linux/string.h> #include <linux/mm.h> +#include <linux/module.h> #include <linux/proc_fs.h> #include <linux/time.h> #include <asm/uaccess.h> diff --git a/net/core/netfilter.c b/net/core/netfilter.c index 7f9b9e82b..c372ab029 100644 --- a/net/core/netfilter.c +++ b/net/core/netfilter.c @@ -261,11 +261,11 @@ void nf_debug_ip_finish_output2(struct sk_buff *skb) if (skb->nf_debug != ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING))) { - /* Fragments will have no owners, but still - may be local */ - if (!(skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) - || skb->nf_debug != ((1 << NF_IP_LOCAL_OUT) - | (1 << NF_IP_POST_ROUTING))){ + /* Fragments, entunnelled packets, TCP RSTs + generated by ipt_REJECT will have no + owners, but still may be local */ + if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT) + | (1 << NF_IP_POST_ROUTING))){ printk("ip_finish_output:" " bad unowned skb = %p: ",skb); debug_print_hooks_ip(skb->nf_debug); @@ -512,7 +512,6 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, info->indev, info->outdev, &elem, info->okfn); } - br_read_unlock_bh(BR_NETPROTO_LOCK); switch (verdict) { case NF_ACCEPT: @@ -527,6 +526,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, kfree_skb(skb); break; } + br_read_unlock_bh(BR_NETPROTO_LOCK); /* Release those devices we held, or Alexey will kill me. */ if (info->indev) dev_put(info->indev); diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index d97558a24..a2bc39398 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -104,7 +104,7 @@ static void dn_run_flush(unsigned long dummy); static struct dn_rt_hash_bucket *dn_rt_hash_table; static unsigned dn_rt_hash_mask; -static struct timer_list dn_route_timer = { function: NULL }; +static struct timer_list dn_route_timer; static struct timer_list dn_rt_flush_timer = { function: dn_run_flush }; int decnet_dst_gc_interval = 2; diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 47e7fb01b..14ebb46e1 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -551,6 +551,7 @@ static inline struct ip_conntrack * resolve_normal_ct(struct sk_buff *skb, struct ip_conntrack_protocol *proto, int *set_reply, + unsigned int hooknum, enum ip_conntrack_info *ctinfo) { struct ip_conntrack_tuple tuple; @@ -573,6 +574,21 @@ resolve_normal_ct(struct sk_buff *skb, if (DIRECTION(h) == IP_CT_DIR_REPLY) { /* Reply on unconfirmed connection => unclassifiable */ if (!(h->ctrack->status & IPS_CONFIRMED)) { + /* Exception: local TCP RSTs (generated by + REJECT target). */ + if (hooknum == NF_IP_LOCAL_OUT + && h->tuple.dst.protonum == IPPROTO_TCP) { + const struct tcphdr *tcph + = (const struct tcphdr *) + ((u_int32_t *)skb->nh.iph + + skb->nh.iph->ihl); + if (tcph->rst) { + *ctinfo = IP_CT_ESTABLISHED + + IP_CT_IS_REPLY; + *set_reply = 0; + goto set_skb; + } + } DEBUGP("Reply on unconfirmed connection\n"); ip_conntrack_put(h->ctrack); return NULL; @@ -598,6 +614,7 @@ resolve_normal_ct(struct sk_buff *skb, } *set_reply = 0; } + set_skb: skb->nfct = &h->ctrack->infos[*ctinfo]; return h->ctrack; } @@ -669,7 +686,7 @@ unsigned int ip_conntrack_in(unsigned int hooknum, && icmp_error_track(*pskb, &ctinfo, hooknum)) return NF_ACCEPT; - if (!(ct = resolve_normal_ct(*pskb, proto, &set_reply, &ctinfo))) + if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo))) /* Not valid part of a connection */ return NF_ACCEPT; diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 77db6572f..486683bec 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -169,11 +169,15 @@ static unsigned int ip_confirm(unsigned int hooknum, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - /* We've seen it coming out the other side: confirm */ + /* We've seen it coming out the other side: confirm (only if + new packet: REJECT can generate TCP RESET response, or ICMP + errors) */ if ((*pskb)->nfct) { struct ip_conntrack *ct = (struct ip_conntrack *)(*pskb)->nfct->master; - if (!(ct->status & IPS_CONFIRMED)) + /* ctinfo is the index of the nfct inside the conntrack */ + if ((*pskb)->nfct - ct->infos == IP_CT_NEW + && !(ct->status & IPS_CONFIRMED)) ip_conntrack_confirm(ct); } return NF_ACCEPT; @@ -191,7 +195,8 @@ static unsigned int ip_refrag(unsigned int hooknum, if ((*pskb)->nfct) { struct ip_conntrack *ct = (struct ip_conntrack *)(*pskb)->nfct->master; - if (!(ct->status & IPS_CONFIRMED)) + if ((*pskb)->nfct - ct->infos == IP_CT_NEW + && !(ct->status & IPS_CONFIRMED)) ip_conntrack_confirm(ct); } diff --git a/net/ipv4/netfilter/ip_fw_compat.c b/net/ipv4/netfilter/ip_fw_compat.c index 6f0503e05..3c8c2e851 100644 --- a/net/ipv4/netfilter/ip_fw_compat.c +++ b/net/ipv4/netfilter/ip_fw_compat.c @@ -71,7 +71,8 @@ confirm_connection(struct sk_buff *skb) struct ip_conntrack *ct = (struct ip_conntrack *)skb->nfct->master; - if (!(ct->status & IPS_CONFIRMED)) + if (skb->nfct - ct->infos == IP_CT_NEW + && !(ct->status & IPS_CONFIRMED)) ip_conntrack_confirm(ct); } } diff --git a/net/ipv4/netfilter/ip_fw_compat_masq.c b/net/ipv4/netfilter/ip_fw_compat_masq.c index 1e6721174..ce3180d39 100644 --- a/net/ipv4/netfilter/ip_fw_compat_masq.c +++ b/net/ipv4/netfilter/ip_fw_compat_masq.c @@ -105,7 +105,7 @@ check_for_masq_error(struct sk_buff *skb) /* Wouldn't be here if not tracked already => masq'ed ICMP ping or error related to masq'd connection */ IP_NF_ASSERT(ct); - if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) { + if (ctinfo == IP_CT_RELATED) { icmp_reply_translation(skb, ct, NF_IP_PRE_ROUTING, CTINFO2DIR(ctinfo)); icmp_reply_translation(skb, ct, NF_IP_POST_ROUTING, diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index a07749ecb..c8bf259b9 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -735,7 +735,7 @@ do_bindings(struct ip_conntrack *ct, } else return NF_ACCEPT; } -void +unsigned int icmp_reply_translation(struct sk_buff *skb, struct ip_conntrack *conntrack, unsigned int hooknum, @@ -749,6 +749,22 @@ icmp_reply_translation(struct sk_buff *skb, struct ip_nat_info *info = &conntrack->nat.info; IP_NF_ASSERT(skb->len >= iph->ihl*4 + sizeof(struct icmphdr)); + /* Must be RELATED */ + IP_NF_ASSERT(skb->nfct - (struct ip_conntrack *)skb->nfct->master + == IP_CT_RELATED + || skb->nfct - (struct ip_conntrack *)skb->nfct->master + == IP_CT_RELATED+IP_CT_IS_REPLY); + + /* Redirects on non-null nats must be dropped, else they'll + start talking to each other without our translation, and be + confused... --RR */ + if (hdr->type == ICMP_REDIRECT) { + /* Don't care about races here. */ + if (info->initialized + != ((1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST)) + || info->num_manips != 0) + return NF_DROP; + } DEBUGP("icmp_reply_translation: translating error %p hook %u dir %s\n", skb, hooknum, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); @@ -810,6 +826,8 @@ icmp_reply_translation(struct sk_buff *skb, hdr->checksum = 0; hdr->checksum = ip_compute_csum((unsigned char *)hdr, sizeof(*hdr) + datalen); + + return NF_ACCEPT; } int ip_nat_helper_register(struct ip_nat_helper *me) diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 11e16e25e..3334a64c2 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -84,9 +84,8 @@ ip_nat_fn(unsigned int hooknum, case IP_CT_RELATED: case IP_CT_RELATED+IP_CT_IS_REPLY: if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) { - icmp_reply_translation(*pskb, ct, hooknum, - CTINFO2DIR(ctinfo)); - return NF_ACCEPT; + return icmp_reply_translation(*pskb, ct, hooknum, + CTINFO2DIR(ctinfo)); } /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */ case IP_CT_NEW: diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 792ae1552..39574b7d4 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -244,7 +244,7 @@ static int ipq_set_verdict(ipq_queue_t *q, { ipq_queue_element_t *e; - if (v->value < 0 || v->value > NF_MAX_VERDICT) + if (v->value > NF_MAX_VERDICT) return -EINVAL; e = ipq_dequeue(q, id_cmp, v->id); if (e == NULL) @@ -309,10 +309,9 @@ static inline int dev_cmp(ipq_queue_element_t *e, unsigned long ifindex) if (e->info->indev->ifindex == ifindex) return 1; if (e->info->outdev) - if (e->info->outdev->ifindex == ifindex); + if (e->info->outdev->ifindex == ifindex) return 1; return 0; - } /* Drop any queued packets associated with device ifindex */ diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 3105f5a18..40b19760b 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1029,7 +1029,7 @@ get_entries(const struct ipt_get_entries *entries, t->private->number); if (entries->size == t->private->size) ret = copy_entries_to_user(t->private->size, - t, uptr->entries); + t, uptr->entrytable); else { duprintf("get_entries: I've got %u not %u!\n", t->private->size, diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 220cdb568..c63e95fe8 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -7,6 +7,7 @@ #include <linux/ip.h> #include <net/icmp.h> #include <net/ip.h> +#include <net/tcp.h> struct in_device; #include <net/route.h> #include <linux/netfilter_ipv4/ip_tables.h> @@ -18,6 +19,113 @@ struct in_device; #define DEBUGP(format, args...) #endif +/* Send RST reply */ +static void send_reset(struct sk_buff *oldskb) +{ + struct sk_buff *nskb; + struct tcphdr *tcph; + struct rtable *rt; + unsigned int tcplen; + int needs_ack; + + /* Clone skb (skb is about to be dropped, so we don't care) */ + nskb = skb_clone(oldskb, GFP_ATOMIC); + if (!nskb) + return; + + /* This packet will not be the same as the other: clear nf fields */ + nf_conntrack_put(nskb->nfct); + nskb->nfct = NULL; + nskb->nfcache = 0; +#ifdef CONFIG_NETFILTER_DEBUG + nskb->nf_debug = 0; +#endif + + /* IP header checks: fragment, too short. */ + if (nskb->nh.iph->frag_off & htons(IP_OFFSET) + || nskb->len < (nskb->nh.iph->ihl<<2) + sizeof(struct tcphdr)) + goto free_nskb; + + tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); + tcplen = nskb->len - nskb->nh.iph->ihl*4; + + /* Check checksum. */ + if (tcp_v4_check(tcph, tcplen, nskb->nh.iph->saddr, + nskb->nh.iph->daddr, + csum_partial((char *)tcph, tcplen, 0)) != 0) + goto free_nskb; + + /* No RST for RST. */ + if (tcph->rst) + goto free_nskb; + + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr); + tcph->source = xchg(&tcph->dest, tcph->source); + + /* Truncate to length (no data) */ + tcph->doff = sizeof(struct tcphdr)/4; + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr)); + + if (tcph->ack) { + needs_ack = 0; + tcph->seq = tcph->ack_seq; + tcph->ack_seq = 0; + } else { + needs_ack = 1; + tcph->seq = 0; + tcph->ack_seq = htonl(ntohl(tcph->seq) + tcph->syn + tcph->fin + + tcplen - (tcph->doff<<2)); + } + + /* Reset flags */ + ((u_int8_t *)tcph)[13] = 0; + tcph->rst = 1; + if (needs_ack) + tcph->ack = 1; + + tcph->window = 0; + tcph->urg_ptr = 0; + + /* Adjust TCP checksum */ + tcph->check = 0; + tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), + nskb->nh.iph->saddr, + nskb->nh.iph->daddr, + csum_partial((char *)tcph, + sizeof(struct tcphdr), 0)); + + /* Adjust IP TTL, DF */ + nskb->nh.iph->ttl = MAXTTL; + /* Set DF, id = 0 */ + nskb->nh.iph->frag_off = htons(IP_DF); + nskb->nh.iph->id = 0; + + /* Adjust IP checksum */ + nskb->nh.iph->check = 0; + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, + nskb->nh.iph->ihl); + + /* Routing */ + if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr, + RT_TOS(nskb->nh.iph->tos) | RTO_CONN, + 0) != 0) + goto free_nskb; + + dst_release(nskb->dst); + nskb->dst = &rt->u.dst; + + /* "Never happens" */ + if (nskb->len > nskb->dst->pmtu) + goto free_nskb; + + NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev, + ip_finish_output); + return; + + free_nskb: + kfree_skb(nskb); +} + static unsigned int reject(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, @@ -43,6 +151,12 @@ static unsigned int reject(struct sk_buff **pskb, case IPT_ICMP_PORT_UNREACHABLE: icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); break; + case IPT_ICMP_NET_PROHIBITED: + icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0); + break; + case IPT_ICMP_HOST_PROHIBITED: + icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0); + break; case IPT_ICMP_ECHOREPLY: { struct icmphdr *icmph = (struct icmphdr *) ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl); @@ -64,6 +178,9 @@ static unsigned int reject(struct sk_buff **pskb, } } break; + case IPT_TCP_RESET: + send_reset(*pskb); + break; } return NF_DROP; @@ -96,7 +213,7 @@ static int check(const char *tablename, /* Only allow these for packet filtering. */ if (strcmp(tablename, "filter") != 0) { - DEBUGP("REJECT: bad table `%s'.\n", table); + DEBUGP("REJECT: bad table `%s'.\n", tablename); return 0; } if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) @@ -118,6 +235,18 @@ static int check(const char *tablename, DEBUGP("REJECT: ECHOREPLY illegal for non-ping\n"); return 0; } + } else if (rejinfo->with == IPT_TCP_RESET) { + /* Must specify that it's a TCP packet */ + if (e->ip.proto != IPPROTO_TCP + || (e->ip.invflags & IPT_INV_PROTO)) { + DEBUGP("REJECT: TCP_RESET illegal for non-tcp\n"); + return 0; + } + /* Only for local input. Rest is too dangerous. */ + if ((hook_mask & ~(1 << NF_IP_LOCAL_IN)) != 0) { + DEBUGP("REJECT: TCP_RESET only from INPUT\n"); + return 0; + } } return 1; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 282024cc9..46f5e57e8 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.208 2000/05/03 06:37:06 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.209 2000/07/12 03:49:30 davem Exp $ * * IPv4 specific functions * @@ -69,8 +69,8 @@ extern int sysctl_ip_dynaddr; #define ICMP_MIN_LENGTH 8 /* Socket used for sending RSTs */ -struct inode tcp_inode; -struct socket *tcp_socket=&tcp_inode.u.socket_i; +static struct inode tcp_inode; +static struct socket *tcp_socket=&tcp_inode.u.socket_i; void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len, struct sk_buff *skb); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index dea475feb..b3ba4383d 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1075,7 +1075,7 @@ get_entries(const struct ip6t_get_entries *entries, t->private->number); if (entries->size == t->private->size) ret = copy_entries_to_user(t->private->size, - t, uptr->entries); + t, uptr->entrytable); else { duprintf("get_entries: I've got %u not %u!\n", t->private->size, diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 190551d79..01000f862 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque <roque@di.fc.ul.pt> * - * $Id: reassembly.c,v 1.18 2000/07/07 22:29:42 davem Exp $ + * $Id: reassembly.c,v 1.19 2000/07/11 22:35:24 davem Exp $ * * Based on: net/ipv4/ip_fragment.c * diff --git a/net/irda/irmod.c b/net/irda/irmod.c index 5decebd98..fde6788c3 100644 --- a/net/irda/irmod.c +++ b/net/irda/irmod.c @@ -28,6 +28,7 @@ #include <linux/init.h> #include <linux/poll.h> #include <linux/proc_fs.h> +#include <linux/smp_lock.h> #include <asm/segment.h> @@ -389,12 +390,15 @@ static int irda_open( struct inode * inode, struct file *file) { IRDA_DEBUG( 4, __FUNCTION__ "()\n"); + lock_kernel(); if (irda.in_use) { + unlock_kernel(); IRDA_DEBUG(0, __FUNCTION__ "(), irmanager is already running!\n"); return -1; } irda.in_use = TRUE; + unlock_kernel(); return 0; } @@ -446,7 +450,9 @@ static int irda_close(struct inode *inode, struct file *file) { IRDA_DEBUG(4, __FUNCTION__ "()\n"); + lock_kernel(); irda.in_use = FALSE; + unlock_kernel(); return 0; } diff --git a/net/netlink/netlink_dev.c b/net/netlink/netlink_dev.c index d0e187aee..bc1b378fc 100644 --- a/net/netlink/netlink_dev.c +++ b/net/netlink/netlink_dev.c @@ -26,6 +26,7 @@ #include <linux/poll.h> #include <linux/init.h> #include <linux/devfs_fs_kernel.h> +#include <linux/smp_lock.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -138,10 +139,13 @@ out: static int netlink_release(struct inode * inode, struct file * file) { unsigned int minor = MINOR(inode->i_rdev); - struct socket *sock = netlink_user[minor]; + struct socket *sock; + lock_kernel(); + sock = netlink_user[minor]; netlink_user[minor] = NULL; open_map &= ~(1<<minor); + unlock_kernel(); sock_release(sock); return 0; } diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index bb6b3a291..dc9f11aa7 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -1751,11 +1751,12 @@ cbq_destroy(struct Qdisc* sch) static void cbq_put(struct Qdisc *sch, unsigned long arg) { - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; struct cbq_class *cl = (struct cbq_class*)arg; if (--cl->refcnt == 0) { #ifdef CONFIG_NET_CLS_POLICE + struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + spin_lock_bh(&sch->dev->queue_lock); if (q->rx_class == cl) q->rx_class = NULL; diff --git a/net/socket.c b/net/socket.c index 4cd725731..2b5426991 100644 --- a/net/socket.c +++ b/net/socket.c @@ -702,10 +702,8 @@ int sock_close(struct inode *inode, struct file *filp) printk(KERN_DEBUG "sock_close: NULL inode\n"); return 0; } - unlock_kernel(); sock_fasync(-1, filp, 0); sock_release(socki_lookup(inode)); - lock_kernel(); return 0; } diff --git a/net/unix/garbage.c b/net/unix/garbage.c index a4bba58e9..3fcf7464c 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -177,7 +177,7 @@ void unix_gc(void) * Avoid a recursive GC. */ - if(!down_trylock(&unix_gc_sem)) + if (down_trylock(&unix_gc_sem)) return; read_lock(&unix_table_lock); |