diff options
author | David Woodhouse <dwmw2@infradead.org> | 2006-05-06 19:59:18 +0100 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2006-05-06 19:59:18 +0100 |
commit | 5047f09b56d0bc3c21aec9cb16de60283da645c6 (patch) | |
tree | 09a07554b933c3bb912ce3bfc0ea7c7e1f16041c /net | |
parent | c0f1fe00c3923135b2c2f443448585482da8a53e (diff) | |
parent | 5528e568a760442e0ec8fd2dea1f0791875a066b (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'net')
42 files changed, 269 insertions, 176 deletions
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index dbf9b47681f..a2e0dd047e9 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -228,6 +228,8 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, return NULL; } +EXPORT_SYMBOL(ax25_find_cb); + void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto) { ax25_cb *s; @@ -424,6 +426,26 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg) return 0; } +static void ax25_fillin_cb_from_dev(ax25_cb *ax25, ax25_dev *ax25_dev) +{ + ax25->rtt = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]) / 2; + ax25->t1 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]); + ax25->t2 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T2]); + ax25->t3 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T3]); + ax25->n2 = ax25_dev->values[AX25_VALUES_N2]; + ax25->paclen = ax25_dev->values[AX25_VALUES_PACLEN]; + ax25->idle = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_IDLE]); + ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF]; + + if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) { + ax25->modulus = AX25_EMODULUS; + ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW]; + } else { + ax25->modulus = AX25_MODULUS; + ax25->window = ax25_dev->values[AX25_VALUES_WINDOW]; + } +} + /* * Fill in a created AX.25 created control block with the default * values for a particular device. @@ -433,39 +455,28 @@ void ax25_fillin_cb(ax25_cb *ax25, ax25_dev *ax25_dev) ax25->ax25_dev = ax25_dev; if (ax25->ax25_dev != NULL) { - ax25->rtt = ax25_dev->values[AX25_VALUES_T1] / 2; - ax25->t1 = ax25_dev->values[AX25_VALUES_T1]; - ax25->t2 = ax25_dev->values[AX25_VALUES_T2]; - ax25->t3 = ax25_dev->values[AX25_VALUES_T3]; - ax25->n2 = ax25_dev->values[AX25_VALUES_N2]; - ax25->paclen = ax25_dev->values[AX25_VALUES_PACLEN]; - ax25->idle = ax25_dev->values[AX25_VALUES_IDLE]; - ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF]; - - if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) { - ax25->modulus = AX25_EMODULUS; - ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW]; - } else { - ax25->modulus = AX25_MODULUS; - ax25->window = ax25_dev->values[AX25_VALUES_WINDOW]; - } + ax25_fillin_cb_from_dev(ax25, ax25_dev); + return; + } + + /* + * No device, use kernel / AX.25 spec default values + */ + ax25->rtt = msecs_to_jiffies(AX25_DEF_T1) / 2; + ax25->t1 = msecs_to_jiffies(AX25_DEF_T1); + ax25->t2 = msecs_to_jiffies(AX25_DEF_T2); + ax25->t3 = msecs_to_jiffies(AX25_DEF_T3); + ax25->n2 = AX25_DEF_N2; + ax25->paclen = AX25_DEF_PACLEN; + ax25->idle = msecs_to_jiffies(AX25_DEF_IDLE); + ax25->backoff = AX25_DEF_BACKOFF; + + if (AX25_DEF_AXDEFMODE) { + ax25->modulus = AX25_EMODULUS; + ax25->window = AX25_DEF_EWINDOW; } else { - ax25->rtt = AX25_DEF_T1 / 2; - ax25->t1 = AX25_DEF_T1; - ax25->t2 = AX25_DEF_T2; - ax25->t3 = AX25_DEF_T3; - ax25->n2 = AX25_DEF_N2; - ax25->paclen = AX25_DEF_PACLEN; - ax25->idle = AX25_DEF_IDLE; - ax25->backoff = AX25_DEF_BACKOFF; - - if (AX25_DEF_AXDEFMODE) { - ax25->modulus = AX25_EMODULUS; - ax25->window = AX25_DEF_EWINDOW; - } else { - ax25->modulus = AX25_MODULUS; - ax25->window = AX25_DEF_WINDOW; - } + ax25->modulus = AX25_MODULUS; + ax25->window = AX25_DEF_WINDOW; } } @@ -1979,24 +1990,6 @@ static struct notifier_block ax25_dev_notifier = { .notifier_call =ax25_device_event, }; -EXPORT_SYMBOL(ax25_hard_header); -EXPORT_SYMBOL(ax25_rebuild_header); -EXPORT_SYMBOL(ax25_findbyuid); -EXPORT_SYMBOL(ax25_find_cb); -EXPORT_SYMBOL(ax25_linkfail_register); -EXPORT_SYMBOL(ax25_linkfail_release); -EXPORT_SYMBOL(ax25_listen_register); -EXPORT_SYMBOL(ax25_listen_release); -EXPORT_SYMBOL(ax25_protocol_register); -EXPORT_SYMBOL(ax25_protocol_release); -EXPORT_SYMBOL(ax25_send_frame); -EXPORT_SYMBOL(ax25_uid_policy); -EXPORT_SYMBOL(ax25cmp); -EXPORT_SYMBOL(ax2asc); -EXPORT_SYMBOL(asc2ax); -EXPORT_SYMBOL(null_ax25_address); -EXPORT_SYMBOL(ax25_display_timer); - static int __init ax25_init(void) { int rc = proto_register(&ax25_proto, 0); diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c index 0164a155b8c..5f0896ad004 100644 --- a/net/ax25/ax25_addr.c +++ b/net/ax25/ax25_addr.c @@ -11,6 +11,7 @@ #include <linux/socket.h> #include <linux/in.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/sched.h> #include <linux/timer.h> #include <linux/string.h> @@ -33,6 +34,8 @@ */ ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}}; +EXPORT_SYMBOL(null_ax25_address); + /* * ax25 -> ascii conversion */ @@ -64,6 +67,8 @@ char *ax2asc(char *buf, ax25_address *a) } +EXPORT_SYMBOL(ax2asc); + /* * ascii -> ax25 conversion */ @@ -97,6 +102,8 @@ void asc2ax(ax25_address *addr, char *callsign) addr->ax25_call[6] &= 0x1E; } +EXPORT_SYMBOL(asc2ax); + /* * Compare two ax.25 addresses */ @@ -116,6 +123,8 @@ int ax25cmp(ax25_address *a, ax25_address *b) return 2; /* Partial match */ } +EXPORT_SYMBOL(ax25cmp); + /* * Compare two AX.25 digipeater paths. */ diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c index 061083efc1d..5961459935e 100644 --- a/net/ax25/ax25_ds_timer.c +++ b/net/ax25/ax25_ds_timer.c @@ -61,7 +61,8 @@ void ax25_ds_set_timer(ax25_dev *ax25_dev) return; del_timer(&ax25_dev->dama.slave_timer); - ax25_dev->dama.slave_timeout = ax25_dev->values[AX25_VALUES_DS_TIMEOUT] / 10; + ax25_dev->dama.slave_timeout = + msecs_to_jiffies(ax25_dev->values[AX25_VALUES_DS_TIMEOUT]) / 10; ax25_ds_add_timer(ax25_dev); } diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c index d68aff10072..3bb152710b7 100644 --- a/net/ax25/ax25_iface.c +++ b/net/ax25/ax25_iface.c @@ -12,6 +12,7 @@ #include <linux/socket.h> #include <linux/in.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/sched.h> #include <linux/spinlock.h> #include <linux/timer.h> @@ -74,6 +75,8 @@ int ax25_protocol_register(unsigned int pid, return 1; } +EXPORT_SYMBOL(ax25_protocol_register); + void ax25_protocol_release(unsigned int pid) { struct protocol_struct *s, *protocol; @@ -106,6 +109,8 @@ void ax25_protocol_release(unsigned int pid) write_unlock(&protocol_list_lock); } +EXPORT_SYMBOL(ax25_protocol_release); + int ax25_linkfail_register(void (*func)(ax25_cb *, int)) { struct linkfail_struct *linkfail; @@ -123,6 +128,8 @@ int ax25_linkfail_register(void (*func)(ax25_cb *, int)) return 1; } +EXPORT_SYMBOL(ax25_linkfail_register); + void ax25_linkfail_release(void (*func)(ax25_cb *, int)) { struct linkfail_struct *s, *linkfail; @@ -155,6 +162,8 @@ void ax25_linkfail_release(void (*func)(ax25_cb *, int)) spin_unlock_bh(&linkfail_lock); } +EXPORT_SYMBOL(ax25_linkfail_release); + int ax25_listen_register(ax25_address *callsign, struct net_device *dev) { struct listen_struct *listen; @@ -176,6 +185,8 @@ int ax25_listen_register(ax25_address *callsign, struct net_device *dev) return 1; } +EXPORT_SYMBOL(ax25_listen_register); + void ax25_listen_release(ax25_address *callsign, struct net_device *dev) { struct listen_struct *s, *listen; @@ -208,6 +219,8 @@ void ax25_listen_release(ax25_address *callsign, struct net_device *dev) spin_unlock_bh(&listen_lock); } +EXPORT_SYMBOL(ax25_listen_release); + int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *) { int (*res)(struct sk_buff *, ax25_cb *) = NULL; diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c index d643dac3ecc..a0b534f80f1 100644 --- a/net/ax25/ax25_ip.c +++ b/net/ax25/ax25_ip.c @@ -12,6 +12,7 @@ #include <linux/socket.h> #include <linux/in.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/sched.h> #include <linux/timer.h> #include <linux/string.h> @@ -221,3 +222,5 @@ int ax25_rebuild_header(struct sk_buff *skb) #endif +EXPORT_SYMBOL(ax25_hard_header); +EXPORT_SYMBOL(ax25_rebuild_header); diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c index 5fc048dcd39..5d99852b239 100644 --- a/net/ax25/ax25_out.c +++ b/net/ax25/ax25_out.c @@ -14,6 +14,7 @@ #include <linux/socket.h> #include <linux/in.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/sched.h> #include <linux/timer.h> #include <linux/string.h> @@ -104,6 +105,8 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax2 return ax25; /* We had to create it */ } +EXPORT_SYMBOL(ax25_send_frame); + /* * All outgoing AX.25 I frames pass via this routine. Therefore this is * where the fragmentation of frames takes place. If fragment is set to diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index f04f8630fd2..5ac98250797 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -360,7 +360,7 @@ struct file_operations ax25_route_fops = { /* * Find AX.25 route * - * Only routes with a refernce rout of zero can be destroyed. + * Only routes with a reference count of zero can be destroyed. */ static ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev) { diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.c index 7a6b50a1455..ec254057f21 100644 --- a/net/ax25/ax25_timer.c +++ b/net/ax25/ax25_timer.c @@ -18,6 +18,7 @@ #include <linux/socket.h> #include <linux/in.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/jiffies.h> #include <linux/timer.h> #include <linux/string.h> @@ -137,6 +138,8 @@ unsigned long ax25_display_timer(struct timer_list *timer) return timer->expires - jiffies; } +EXPORT_SYMBOL(ax25_display_timer); + static void ax25_heartbeat_expiry(unsigned long param) { int proto = AX25_PROTO_STD_SIMPLEX; diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index b8b5854bce9..5e9a81e8b21 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c @@ -49,6 +49,8 @@ static DEFINE_RWLOCK(ax25_uid_lock); int ax25_uid_policy = 0; +EXPORT_SYMBOL(ax25_uid_policy); + ax25_uid_assoc *ax25_findbyuid(uid_t uid) { ax25_uid_assoc *ax25_uid, *res = NULL; @@ -67,6 +69,8 @@ ax25_uid_assoc *ax25_findbyuid(uid_t uid) return res; } +EXPORT_SYMBOL(ax25_findbyuid); + int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) { ax25_uid_assoc *ax25_uid; diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c index 894a22558d9..bdb64c36df1 100644 --- a/net/ax25/sysctl_net_ax25.c +++ b/net/ax25/sysctl_net_ax25.c @@ -18,14 +18,14 @@ static int min_backoff[1], max_backoff[] = {2}; static int min_conmode[1], max_conmode[] = {2}; static int min_window[] = {1}, max_window[] = {7}; static int min_ewindow[] = {1}, max_ewindow[] = {63}; -static int min_t1[] = {1}, max_t1[] = {30 * HZ}; -static int min_t2[] = {1}, max_t2[] = {20 * HZ}; -static int min_t3[1], max_t3[] = {3600 * HZ}; -static int min_idle[1], max_idle[] = {65535 * HZ}; +static int min_t1[] = {1}, max_t1[] = {30000}; +static int min_t2[] = {1}, max_t2[] = {20000}; +static int min_t3[1], max_t3[] = {3600000}; +static int min_idle[1], max_idle[] = {65535000}; static int min_n2[] = {1}, max_n2[] = {31}; static int min_paclen[] = {1}, max_paclen[] = {512}; static int min_proto[1], max_proto[] = { AX25_PROTO_MAX }; -static int min_ds_timeout[1], max_ds_timeout[] = {65535 * HZ}; +static int min_ds_timeout[1], max_ds_timeout[] = {65535000}; static struct ctl_table_header *ax25_table_header; diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index b0b7f55c1ed..bfa4d8c333f 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -66,6 +66,7 @@ int br_handle_frame_finish(struct sk_buff *skb) } if (is_multicast_ether_addr(dest)) { + br->statistics.multicast++; br_flood_forward(br, skb, !passedup); if (!passedup) br_pass_frame_up(br, skb); diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 1ff7328b0e1..2e0ee8355c4 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -848,6 +848,7 @@ static int dccp_close_state(struct sock *sk) void dccp_close(struct sock *sk, long timeout) { struct sk_buff *skb; + int state; lock_sock(sk); @@ -882,6 +883,11 @@ void dccp_close(struct sock *sk, long timeout) sk_stream_wait_close(sk, timeout); adjudge_to_death: + state = sk->sk_state; + sock_hold(sk); + sock_orphan(sk); + atomic_inc(sk->sk_prot->orphan_count); + /* * It is the last release_sock in its life. It will remove backlog. */ @@ -894,8 +900,9 @@ adjudge_to_death: bh_lock_sock(sk); BUG_TRAP(!sock_owned_by_user(sk)); - sock_hold(sk); - sock_orphan(sk); + /* Have we already been destroyed by a softirq or backlog? */ + if (state != DCCP_CLOSED && sk->sk_state == DCCP_CLOSED) + goto out; /* * The last release_sock may have processed the CLOSE or RESET @@ -915,12 +922,12 @@ adjudge_to_death: #endif } - atomic_inc(sk->sk_prot->orphan_count); if (sk->sk_state == DCCP_CLOSED) inet_csk_destroy_sock(sk); /* Otherwise, socket is reprieved until protocol close. */ +out: bh_unlock_sock(sk); local_bh_enable(); sock_put(sk); diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index 7c8692c26bf..66e230c3b32 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c @@ -493,7 +493,6 @@ struct elist_cb_state { static void neigh_elist_cb(struct neighbour *neigh, void *_info) { struct elist_cb_state *s = _info; - struct dn_dev *dn_db; struct dn_neigh *dn; if (neigh->dev != s->dev) @@ -503,10 +502,6 @@ static void neigh_elist_cb(struct neighbour *neigh, void *_info) if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2))) return; - dn_db = (struct dn_dev *) s->dev->dn_ptr; - if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2)) - return; - if (s->t == s->n) s->rs = dn_find_slot(s->ptr, s->n, dn->priority); else diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index dc206f1f914..0a277453526 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1257,7 +1257,7 @@ out_unregister_udp_proto: goto out; } -module_init(inet_init); +fs_initcall(inet_init); /* ------------------------------------------------------------------------ */ diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c index 2c2fb700d83..518f581d39e 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c @@ -162,6 +162,8 @@ static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct, /* Validate TPKT length */ tpktlen = tpkt[2] * 256 + tpkt[3]; + if (tpktlen < 4) + goto clear_out; if (tpktlen > tcpdatalen) { if (tcpdatalen == 4) { /* Separate TPKT header */ /* Netmeeting sends TPKT header and data separately */ diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c index 48078002e45..355a53a5b6c 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c @@ -2,7 +2,7 @@ * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323 * conntrack/NAT module. * - * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com> + * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net> * * This source code is licensed under General Public License version 2. * @@ -703,6 +703,10 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level) type = get_bits(bs, f->sz); } + /* Write Type */ + if (base) + *(unsigned *) base = type; + /* Check Range */ if (type >= f->ub) { /* Newer version? */ BYTE_ALIGN(bs); @@ -712,10 +716,6 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level) return H323_ERROR_NONE; } - /* Write Type */ - if (base) - *(unsigned *) base = type; - /* Transfer to son level */ son = &f->fields[type]; if (son->attr & STOP) { diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c index 5259abd0fb4..0416073c560 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c @@ -235,12 +235,15 @@ static int do_basic_checks(struct ip_conntrack *conntrack, flag = 1; } - /* Cookie Ack/Echo chunks not the first OR - Init / Init Ack / Shutdown compl chunks not the only chunks */ - if ((sch->type == SCTP_CID_COOKIE_ACK + /* + * Cookie Ack/Echo chunks not the first OR + * Init / Init Ack / Shutdown compl chunks not the only chunks + * OR zero-length. + */ + if (((sch->type == SCTP_CID_COOKIE_ACK || sch->type == SCTP_CID_COOKIE_ECHO || flag) - && count !=0 ) { + && count !=0) || !sch->length) { DEBUGP("Basic checks failed\n"); return 1; } diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 8f760b28617..67e676783da 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -219,8 +219,10 @@ ip_nat_out(unsigned int hooknum, const struct net_device *out, int (*okfn)(struct sk_buff *)) { +#ifdef CONFIG_XFRM struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; +#endif unsigned int ret; /* root is playing with raw sockets. */ diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index d25ac8ba6eb..cee3397ec27 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -956,15 +956,16 @@ struct compat_ipt_standard_target compat_int_t verdict; }; -#define IPT_ST_OFFSET (sizeof(struct ipt_standard_target) - \ - sizeof(struct compat_ipt_standard_target)) - struct compat_ipt_standard { struct compat_ipt_entry entry; struct compat_ipt_standard_target target; }; +#define IPT_ST_LEN XT_ALIGN(sizeof(struct ipt_standard_target)) +#define IPT_ST_COMPAT_LEN COMPAT_XT_ALIGN(sizeof(struct compat_ipt_standard_target)) +#define IPT_ST_OFFSET (IPT_ST_LEN - IPT_ST_COMPAT_LEN) + static int compat_ipt_standard_fn(void *target, void **dstptr, int *size, int convert) { @@ -975,35 +976,29 @@ static int compat_ipt_standard_fn(void *target, ret = 0; switch (convert) { case COMPAT_TO_USER: - pst = (struct ipt_standard_target *)target; + pst = target; memcpy(&compat_st.target, &pst->target, - sizeof(struct ipt_entry_target)); + sizeof(compat_st.target)); compat_st.verdict = pst->verdict; if (compat_st.verdict > 0) compat_st.verdict -= compat_calc_jump(compat_st.verdict); - compat_st.target.u.user.target_size = - sizeof(struct compat_ipt_standard_target); - if (__copy_to_user(*dstptr, &compat_st, - sizeof(struct compat_ipt_standard_target))) + compat_st.target.u.user.target_size = IPT_ST_COMPAT_LEN; + if (copy_to_user(*dstptr, &compat_st, IPT_ST_COMPAT_LEN)) ret = -EFAULT; *size -= IPT_ST_OFFSET; - *dstptr += sizeof(struct compat_ipt_standard_target); + *dstptr += IPT_ST_COMPAT_LEN; break; case COMPAT_FROM_USER: - pcompat_st = - (struct compat_ipt_standard_target *)target; - memcpy(&st.target, &pcompat_st->target, - sizeof(struct ipt_entry_target)); + pcompat_st = target; + memcpy(&st.target, &pcompat_st->target, IPT_ST_COMPAT_LEN); st.verdict = pcompat_st->verdict; if (st.verdict > 0) st.verdict += compat_calc_jump(st.verdict); - st.target.u.user.target_size = - sizeof(struct ipt_standard_target); - memcpy(*dstptr, &st, - sizeof(struct ipt_standard_target)); + st.target.u.user.target_size = IPT_ST_LEN; + memcpy(*dstptr, &st, IPT_ST_LEN); *size += IPT_ST_OFFSET; - *dstptr += sizeof(struct ipt_standard_target); + *dstptr += IPT_ST_LEN; break; case COMPAT_CALC_SIZE: *size += IPT_ST_OFFSET; @@ -1446,7 +1441,7 @@ static int compat_copy_entry_to_user(struct ipt_entry *e, ret = -EFAULT; origsize = *size; ce = (struct compat_ipt_entry __user *)*dstptr; - if (__copy_to_user(ce, e, sizeof(struct ipt_entry))) + if (copy_to_user(ce, e, sizeof(struct ipt_entry))) goto out; *dstptr += sizeof(struct compat_ipt_entry); @@ -1464,9 +1459,9 @@ static int compat_copy_entry_to_user(struct ipt_entry *e, goto out; ret = -EFAULT; next_offset = e->next_offset - (origsize - *size); - if (__put_user(target_offset, &ce->target_offset)) + if (put_user(target_offset, &ce->target_offset)) goto out; - if (__put_user(next_offset, &ce->next_offset)) + if (put_user(next_offset, &ce->next_offset)) goto out; return 0; out: diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 87f68e787d0..e2b7b805503 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1468,6 +1468,7 @@ void tcp_close(struct sock *sk, long timeout) { struct sk_buff *skb; int data_was_unread = 0; + int state; lock_sock(sk); sk->sk_shutdown = SHUTDOWN_MASK; @@ -1544,6 +1545,11 @@ void tcp_close(struct sock *sk, long timeout) sk_stream_wait_close(sk, timeout); adjudge_to_death: + state = sk->sk_state; + sock_hold(sk); + sock_orphan(sk); + atomic_inc(sk->sk_prot->orphan_count); + /* It is the last release_sock in its life. It will remove backlog. */ release_sock(sk); @@ -1555,8 +1561,9 @@ adjudge_to_death: bh_lock_sock(sk); BUG_TRAP(!sock_owned_by_user(sk)); - sock_hold(sk); - sock_orphan(sk); + /* Have we already been destroyed by a softirq or backlog? */ + if (state != TCP_CLOSE && sk->sk_state == TCP_CLOSE) + goto out; /* This is a (useful) BSD violating of the RFC. There is a * problem with TCP as specified in that the other end could @@ -1584,7 +1591,6 @@ adjudge_to_death: if (tmo > TCP_TIMEWAIT_LEN) { inet_csk_reset_keepalive_timer(sk, tcp_fin_time(sk)); } else { - atomic_inc(sk->sk_prot->orphan_count); tcp_time_wait(sk, TCP_FIN_WAIT2, tmo); goto out; } @@ -1603,7 +1609,6 @@ adjudge_to_death: NET_INC_STATS_BH(LINUX_MIB_TCPABORTONMEMORY); } } - atomic_inc(sk->sk_prot->orphan_count); if (sk->sk_state == TCP_CLOSE) inet_csk_destroy_sock(sk); diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c index e0e9d1383c7..b72fa55dfb8 100644 --- a/net/ipv4/tcp_highspeed.c +++ b/net/ipv4/tcp_highspeed.c @@ -137,8 +137,8 @@ static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt, if (tp->snd_cwnd < tp->snd_cwnd_clamp) { tp->snd_cwnd_cnt += ca->ai; if (tp->snd_cwnd_cnt >= tp->snd_cwnd) { - tp->snd_cwnd++; tp->snd_cwnd_cnt -= tp->snd_cwnd; + tp->snd_cwnd++; } } } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index a28ae593b97..743016baa04 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -465,7 +465,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, TCP_INC_STATS(TCP_MIB_OUTSEGS); err = icsk->icsk_af_ops->queue_xmit(skb, 0); - if (unlikely(err <= 0)) + if (likely(err <= 0)) return err; tcp_enter_cwr(sk); diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 32ad229b4fe..4ef8efaf6a6 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -62,7 +62,7 @@ static void xfrm4_encap(struct sk_buff *skb) top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ? 0 : (iph->frag_off & htons(IP_DF)); if (!top_iph->frag_off) - __ip_select_ident(top_iph, dst, 0); + __ip_select_ident(top_iph, dst->child, 0); top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 79078747a64..0190e39096b 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -317,7 +317,7 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif, __FUNCTION__, head, head ? *head : NULL, oif); for (rt = rt0, metric = rt0->rt6i_metric; - rt && rt->rt6i_metric == metric; + rt && rt->rt6i_metric == metric && (!last || rt != rt0); rt = rt->u.next) { int m; @@ -343,9 +343,12 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif, (strict & RT6_SELECT_F_REACHABLE) && last && last != rt0) { /* no entries matched; do round-robin */ + static spinlock_t lock = SPIN_LOCK_UNLOCKED; + spin_lock(&lock); *head = rt0->u.next; rt0->u.next = last->u.next; last->u.next = rt0; + spin_unlock(&lock); } RT6_TRACE("%s() => %p, score=%d\n", diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 9cccc325b68..0c6da496cfa 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -240,12 +240,15 @@ static int do_basic_checks(struct nf_conn *conntrack, flag = 1; } - /* Cookie Ack/Echo chunks not the first OR - Init / Init Ack / Shutdown compl chunks not the only chunks */ - if ((sch->type == SCTP_CID_COOKIE_ACK + /* + * Cookie Ack/Echo chunks not the first OR + * Init / Init Ack / Shutdown compl chunks not the only chunks + * OR zero-length. + */ + if (((sch->type == SCTP_CID_COOKIE_ACK || sch->type == SCTP_CID_COOKIE_ECHO || flag) - && count !=0 ) { + && count !=0) || !sch->length) { DEBUGP("Basic checks failed\n"); return 1; } diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 17abf60f957..99293c63ff7 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -289,7 +289,7 @@ int xt_compat_match(void *match, void **dstptr, int *size, int convert) case COMPAT_TO_USER: pm = (struct xt_entry_match *)match; msize = pm->u.user.match_size; - if (__copy_to_user(*dstptr, pm, msize)) { + if (copy_to_user(*dstptr, pm, msize)) { ret = -EFAULT; break; } @@ -366,7 +366,7 @@ int xt_compat_target(void *target, void **dstptr, int *size, int convert) case COMPAT_TO_USER: pt = (struct xt_entry_target *)target; tsize = pt->u.user.target_size; - if (__copy_to_user(*dstptr, pt, tsize)) { + if (copy_to_user(*dstptr, pt, tsize)) { ret = -EFAULT; break; } diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 2a233ffcf61..3862e73d14d 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -56,12 +56,12 @@ #include <linux/mm.h> #include <linux/types.h> #include <linux/audit.h> +#include <linux/selinux.h> #include <net/sock.h> #include <net/scm.h> #include <net/netlink.h> -#define Nprintk(a...) #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) struct netlink_sock { @@ -1157,6 +1157,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, NETLINK_CB(skb).dst_pid = dst_pid; NETLINK_CB(skb).dst_group = dst_group; NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context); + selinux_get_task_sid(current, &(NETLINK_CB(skb).sid)); memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); /* What can I do? Netlink is asynchronous, so that diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index d44981f5a61..3669cb953e6 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -425,11 +425,16 @@ static int nr_create(struct socket *sock, int protocol) nr_init_timers(sk); - nr->t1 = sysctl_netrom_transport_timeout; - nr->t2 = sysctl_netrom_transport_acknowledge_delay; - nr->n2 = sysctl_netrom_transport_maximum_tries; - nr->t4 = sysctl_netrom_transport_busy_delay; - nr->idle = sysctl_netrom_transport_no_activity_timeout; + nr->t1 = + msecs_to_jiffies(sysctl_netrom_transport_timeout); + nr->t2 = + msecs_to_jiffies(sysctl_netrom_transport_acknowledge_delay); + nr->n2 = + msecs_to_jiffies(sysctl_netrom_transport_maximum_tries); + nr->t4 = + msecs_to_jiffies(sysctl_netrom_transport_busy_delay); + nr->idle = + msecs_to_jiffies(sysctl_netrom_transport_no_activity_timeout); nr->window = sysctl_netrom_transport_requested_window_size; nr->bpqext = 1; @@ -1365,8 +1370,6 @@ static struct notifier_block nr_dev_notifier = { static struct net_device **dev_nr; -static char banner[] __initdata = KERN_INFO "G4KLX NET/ROM for Linux. Version 0.7 for AX25.037 Linux 2.4\n"; - static int __init nr_proto_init(void) { int i; @@ -1414,7 +1417,6 @@ static int __init nr_proto_init(void) } register_netdevice_notifier(&nr_dev_notifier); - printk(banner); ax25_protocol_register(AX25_P_NETROM, nr_route_frame); ax25_linkfail_register(nr_link_failed); diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index 509afddae56..621e5586ab0 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c @@ -185,7 +185,6 @@ static struct net_device_stats *nr_get_stats(struct net_device *dev) void nr_setup(struct net_device *dev) { - SET_MODULE_OWNER(dev); dev->mtu = NR_MAX_PACKET_SIZE; dev->hard_start_xmit = nr_xmit; dev->open = nr_open; diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index ea65396d161..55564efccf1 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -518,11 +518,11 @@ static int rose_create(struct socket *sock, int protocol) init_timer(&rose->timer); init_timer(&rose->idletimer); - rose->t1 = sysctl_rose_call_request_timeout; - rose->t2 = sysctl_rose_reset_request_timeout; - rose->t3 = sysctl_rose_clear_request_timeout; - rose->hb = sysctl_rose_ack_hold_back_timeout; - rose->idle = sysctl_rose_no_activity_timeout; + rose->t1 = msecs_to_jiffies(sysctl_rose_call_request_timeout); + rose->t2 = msecs_to_jiffies(sysctl_rose_reset_request_timeout); + rose->t3 = msecs_to_jiffies(sysctl_rose_clear_request_timeout); + rose->hb = msecs_to_jiffies(sysctl_rose_ack_hold_back_timeout); + rose->idle = msecs_to_jiffies(sysctl_rose_no_activity_timeout); rose->state = ROSE_STATE_0; @@ -1469,8 +1469,6 @@ static struct notifier_block rose_dev_notifier = { static struct net_device **dev_rose; -static const char banner[] = KERN_INFO "F6FBB/G4KLX ROSE for Linux. Version 0.62 for AX25.037 Linux 2.4\n"; - static int __init rose_proto_init(void) { int i; @@ -1519,7 +1517,6 @@ static int __init rose_proto_init(void) sock_register(&rose_family_ops); register_netdevice_notifier(&rose_dev_notifier); - printk(banner); ax25_protocol_register(AX25_P_ROSE, rose_route_frame); ax25_linkfail_register(rose_link_failed); diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index d297af737d1..2a1bf8e119e 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -135,7 +135,6 @@ static struct net_device_stats *rose_get_stats(struct net_device *dev) void rose_setup(struct net_device *dev) { - SET_MODULE_OWNER(dev); dev->mtu = ROSE_MAX_PACKET_SIZE - 2; dev->hard_start_xmit = rose_xmit; dev->open = rose_open; diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c index 09e9e9d04d9..bd86a63960c 100644 --- a/net/rose/rose_link.c +++ b/net/rose/rose_link.c @@ -40,7 +40,8 @@ void rose_start_ftimer(struct rose_neigh *neigh) neigh->ftimer.data = (unsigned long)neigh; neigh->ftimer.function = &rose_ftimer_expiry; - neigh->ftimer.expires = jiffies + sysctl_rose_link_fail_timeout; + neigh->ftimer.expires = + jiffies + msecs_to_jiffies(sysctl_rose_link_fail_timeout); add_timer(&neigh->ftimer); } @@ -51,7 +52,8 @@ static void rose_start_t0timer(struct rose_neigh *neigh) neigh->t0timer.data = (unsigned long)neigh; neigh->t0timer.function = &rose_t0timer_expiry; - neigh->t0timer.expires = jiffies + sysctl_rose_restart_request_timeout; + neigh->t0timer.expires = + jiffies + msecs_to_jiffies(sysctl_rose_restart_request_timeout); add_timer(&neigh->t0timer); } diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 8631b65a731..a22542fa1bc 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -48,8 +48,6 @@ static DEFINE_SPINLOCK(rose_route_list_lock); struct rose_neigh *rose_loopback_neigh; -static void rose_remove_neigh(struct rose_neigh *); - /* * Add a new route to a node, and in the process add the node and the * neighbour if it is new. @@ -235,11 +233,8 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) skb_queue_purge(&rose_neigh->queue); - spin_lock_bh(&rose_neigh_list_lock); - if ((s = rose_neigh_list) == rose_neigh) { rose_neigh_list = rose_neigh->next; - spin_unlock_bh(&rose_neigh_list_lock); kfree(rose_neigh->digipeat); kfree(rose_neigh); return; @@ -248,7 +243,6 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) while (s != NULL && s->next != NULL) { if (s->next == rose_neigh) { s->next = rose_neigh->next; - spin_unlock_bh(&rose_neigh_list_lock); kfree(rose_neigh->digipeat); kfree(rose_neigh); return; @@ -256,7 +250,6 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) s = s->next; } - spin_unlock_bh(&rose_neigh_list_lock); } /* diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 7228d30512c..5a4a4d0ae50 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -167,7 +167,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) if (count == 0) { sch->qstats.drops++; kfree_skb(skb); - return NET_XMIT_DROP; + return NET_XMIT_BYPASS; } /* diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c index 297b8951463..cf0c767d43a 100644 --- a/net/sctp/inqueue.c +++ b/net/sctp/inqueue.c @@ -149,6 +149,7 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) /* This is the first chunk in the packet. */ chunk->singleton = 1; ch = (sctp_chunkhdr_t *) chunk->skb->data; + chunk->data_accepted = 0; } chunk->chunk_hdr = ch; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 2b9a832b29a..8cdba51ec07 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -636,8 +636,9 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, */ chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data; - skb_pull(chunk->skb, - ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t)); + if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - + sizeof(sctp_chunkhdr_t))) + goto nomem; /* 5.1 D) Upon reception of the COOKIE ECHO chunk, Endpoint * "Z" will reply with a COOKIE ACK chunk after building a TCB @@ -965,7 +966,8 @@ sctp_disposition_t sctp_sf_beat_8_3(const struct sctp_endpoint *ep, */ chunk->subh.hb_hdr = (sctp_heartbeathdr_t *) chunk->skb->data; paylen = ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t); - skb_pull(chunk->skb, paylen); + if (!pskb_pull(chunk->skb, paylen)) + goto nomem; reply = sctp_make_heartbeat_ack(asoc, chunk, chunk->subh.hb_hdr, paylen); @@ -1860,8 +1862,9 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep, * are in good shape. */ chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data; - skb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - - sizeof(sctp_chunkhdr_t)); + if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - + sizeof(sctp_chunkhdr_t))) + goto nomem; /* In RFC 2960 5.2.4 3, if both Verification Tags in the State Cookie * of a duplicate COOKIE ECHO match the Verification Tags of the @@ -5151,7 +5154,9 @@ static int sctp_eat_data(const struct sctp_association *asoc, int tmp; __u32 tsn; int account_value; + struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; struct sock *sk = asoc->base.sk; + int rcvbuf_over = 0; data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data; skb_pull(chunk->skb, sizeof(sctp_datahdr_t)); @@ -5162,10 +5167,16 @@ static int sctp_eat_data(const struct sctp_association *asoc, /* ASSERT: Now skb->data is really the user data. */ /* - * if we are established, and we have used up our receive - * buffer memory, drop the frame - */ - if (asoc->state == SCTP_STATE_ESTABLISHED) { + * If we are established, and we have used up our receive buffer + * memory, think about droping the frame. + * Note that we have an opportunity to improve performance here. + * If we accept one chunk from an skbuff, we have to keep all the + * memory of that skbuff around until the chunk is read into user + * space. Therefore, once we accept 1 chunk we may as well accept all + * remaining chunks in the skbuff. The data_accepted flag helps us do + * that. + */ + if ((asoc->state == SCTP_STATE_ESTABLISHED) && (!chunk->data_accepted)) { /* * If the receive buffer policy is 1, then each * association can allocate up to sk_rcvbuf bytes @@ -5176,9 +5187,25 @@ static int sctp_eat_data(const struct sctp_association *asoc, account_value = atomic_read(&asoc->rmem_alloc); else account_value = atomic_read(&sk->sk_rmem_alloc); - - if (account_value > sk->sk_rcvbuf) - return SCTP_IERROR_IGNORE_TSN; + if (account_value > sk->sk_rcvbuf) { + /* + * We need to make forward progress, even when we are + * under memory pressure, so we always allow the + * next tsn after the ctsn ack point to be accepted. + * This lets us avoid deadlocks in which we have to + * drop frames that would otherwise let us drain the + * receive queue. + */ + if ((sctp_tsnmap_get_ctsn(map) + 1) != tsn) + return SCTP_IERROR_IGNORE_TSN; + + /* + * We're going to accept the frame but we should renege + * to make space for it. This will send us down that + * path later in this function. + */ + rcvbuf_over = 1; + } } /* Process ECN based congestion. @@ -5226,6 +5253,7 @@ static int sctp_eat_data(const struct sctp_association *asoc, datalen -= sizeof(sctp_data_chunk_t); deliver = SCTP_CMD_CHUNK_ULP; + chunk->data_accepted = 1; /* Think about partial delivery. */ if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) { @@ -5242,7 +5270,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, * large spill over. */ if (!asoc->rwnd || asoc->rwnd_over || - (datalen > asoc->rwnd + asoc->frag_point)) { + (datalen > asoc->rwnd + asoc->frag_point) || + rcvbuf_over) { /* If this is the next TSN, consider reneging to make * room. Note: Playing nice with a confused sender. A @@ -5250,8 +5279,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, * space and in the future we may want to detect and * do more drastic reneging. */ - if (sctp_tsnmap_has_gap(&asoc->peer.tsn_map) && - (sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1) == tsn) { + if (sctp_tsnmap_has_gap(map) && + (sctp_tsnmap_get_ctsn(map) + 1) == tsn) { SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn); deliver = SCTP_CMD_RENEGE; } else { diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 75ef1040876..8bcca567615 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -366,9 +366,9 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, /* SCTP_STATE_EMPTY */ \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ /* SCTP_STATE_COOKIE_ECHOED */ \ {.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \ /* SCTP_STATE_ESTABLISHED */ \ @@ -380,7 +380,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ {.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ } /* TYPE_SCTP_ECN_ECNE */ #define TYPE_SCTP_ECN_CWR { \ @@ -401,7 +401,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ } /* TYPE_SCTP_ECN_CWR */ #define TYPE_SCTP_SHUTDOWN_COMPLETE { \ @@ -647,7 +647,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { /* SCTP_STATE_EMPTY */ \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \ /* SCTP_STATE_COOKIE_WAIT */ \ {.fn = sctp_sf_do_prm_requestheartbeat, \ .name = "sctp_sf_do_prm_requestheartbeat"}, \ diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 2080b2d28c9..575e556aeb3 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -279,6 +279,7 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq, static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *queue, struct sk_buff *f_frag, struct sk_buff *l_frag) { struct sk_buff *pos; + struct sk_buff *new = NULL; struct sctp_ulpevent *event; struct sk_buff *pnext, *last; struct sk_buff *list = skb_shinfo(f_frag)->frag_list; @@ -297,11 +298,33 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *qu */ if (last) last->next = pos; - else - skb_shinfo(f_frag)->frag_list = pos; + else { + if (skb_cloned(f_frag)) { + /* This is a cloned skb, we can't just modify + * the frag_list. We need a new skb to do that. + * Instead of calling skb_unshare(), we'll do it + * ourselves since we need to delay the free. + */ + new = skb_copy(f_frag, GFP_ATOMIC); + if (!new) + return NULL; /* try again later */ + + new->sk = f_frag->sk; + + skb_shinfo(new)->frag_list = pos; + } else + skb_shinfo(f_frag)->frag_list = pos; + } /* Remove the first fragment from the reassembly queue. */ __skb_unlink(f_frag, queue); + + /* if we did unshare, then free the old skb and re-assign */ + if (new) { + kfree_skb(f_frag); + f_frag = new; + } + while (pos) { pnext = pos->next; diff --git a/net/socket.c b/net/socket.c index 0ce12dfc7a7..02948b622bd 100644 --- a/net/socket.c +++ b/net/socket.c @@ -267,6 +267,8 @@ int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int __user *ule return -EINVAL; if(len) { + if (audit_sockaddr(klen, kaddr)) + return -ENOMEM; if(copy_to_user(uaddr,kaddr,len)) return -EFAULT; } diff --git a/net/x25/x25_timer.c b/net/x25/x25_timer.c index 0a92e1da392..71ff3088f6f 100644 --- a/net/x25/x25_timer.c +++ b/net/x25/x25_timer.c @@ -114,8 +114,9 @@ static void x25_heartbeat_expiry(unsigned long param) if (sock_flag(sk, SOCK_DESTROY) || (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) { + bh_unlock_sock(sk); x25_destroy_socket(sk); - goto unlock; + return; } break; @@ -128,7 +129,6 @@ static void x25_heartbeat_expiry(unsigned long param) } restart_heartbeat: x25_start_heartbeat(sk); -unlock: bh_unlock_sock(sk); } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index c3725fe2a8f..b469c8b5461 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -57,12 +57,12 @@ int xfrm_register_type(struct xfrm_type *type, unsigned short family) return -EAFNOSUPPORT; typemap = afinfo->type_map; - write_lock(&typemap->lock); + write_lock_bh(&typemap->lock); if (likely(typemap->map[type->proto] == NULL)) typemap->map[type->proto] = type; else err = -EEXIST; - write_unlock(&typemap->lock); + write_unlock_bh(&typemap->lock); xfrm_policy_put_afinfo(afinfo); return err; } @@ -78,12 +78,12 @@ int xfrm_unregister_type(struct xfrm_type *type, unsigned short family) return -EAFNOSUPPORT; typemap = afinfo->type_map; - write_lock(&typemap->lock); + write_lock_bh(&typemap->lock); if (unlikely(typemap->map[type->proto] != type)) err = -ENOENT; else typemap->map[type->proto] = NULL; - write_unlock(&typemap->lock); + write_unlock_bh(&typemap->lock); xfrm_policy_put_afinfo(afinfo); return err; } @@ -1251,7 +1251,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) return -EINVAL; if (unlikely(afinfo->family >= NPROTO)) return -EAFNOSUPPORT; - write_lock(&xfrm_policy_afinfo_lock); + write_lock_bh(&xfrm_policy_afinfo_lock); if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL)) err = -ENOBUFS; else { @@ -1268,7 +1268,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) afinfo->garbage_collect = __xfrm_garbage_collect; xfrm_policy_afinfo[afinfo->family] = afinfo; } - write_unlock(&xfrm_policy_afinfo_lock); + write_unlock_bh(&xfrm_policy_afinfo_lock); return err; } EXPORT_SYMBOL(xfrm_policy_register_afinfo); @@ -1280,7 +1280,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) return -EINVAL; if (unlikely(afinfo->family >= NPROTO)) return -EAFNOSUPPORT; - write_lock(&xfrm_policy_afinfo_lock); + write_lock_bh(&xfrm_policy_afinfo_lock); if (likely(xfrm_policy_afinfo[afinfo->family] != NULL)) { if (unlikely(xfrm_policy_afinfo[afinfo->family] != afinfo)) err = -EINVAL; @@ -1294,7 +1294,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) afinfo->garbage_collect = NULL; } } - write_unlock(&xfrm_policy_afinfo_lock); + write_unlock_bh(&xfrm_policy_afinfo_lock); return err; } EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 3dc3e1f3b7a..93a2f36ad3d 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1061,7 +1061,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo) return -EINVAL; if (unlikely(afinfo->family >= NPROTO)) return -EAFNOSUPPORT; - write_lock(&xfrm_state_afinfo_lock); + write_lock_bh(&xfrm_state_afinfo_lock); if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) err = -ENOBUFS; else { @@ -1069,7 +1069,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo) afinfo->state_byspi = xfrm_state_byspi; xfrm_state_afinfo[afinfo->family] = afinfo; } - write_unlock(&xfrm_state_afinfo_lock); + write_unlock_bh(&xfrm_state_afinfo_lock); return err; } EXPORT_SYMBOL(xfrm_state_register_afinfo); @@ -1081,7 +1081,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) return -EINVAL; if (unlikely(afinfo->family >= NPROTO)) return -EAFNOSUPPORT; - write_lock(&xfrm_state_afinfo_lock); + write_lock_bh(&xfrm_state_afinfo_lock); if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) { if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo)) err = -EINVAL; @@ -1091,7 +1091,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) afinfo->state_bydst = NULL; } } - write_unlock(&xfrm_state_afinfo_lock); + write_unlock_bh(&xfrm_state_afinfo_lock); return err; } EXPORT_SYMBOL(xfrm_state_unregister_afinfo); |