diff options
Diffstat (limited to 'net')
37 files changed, 240 insertions, 166 deletions
diff --git a/net/core/utils.c b/net/core/utils.c index 2030bb8c2d30..0bf17da40d52 100644 --- a/net/core/utils.c +++ b/net/core/utils.c @@ -25,6 +25,7 @@ #include <linux/random.h> #include <linux/percpu.h> #include <linux/init.h> +#include <net/sock.h> #include <asm/byteorder.h> #include <asm/system.h> diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index f13937bf9e8c..d054e9224b3e 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -74,8 +74,8 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, struct ieee80211softmac_auth_queue_item *authptr; int length = 0; +check_assoc_again: mutex_lock(&sm->associnfo.mutex); - /* Check if we're already associating to this or another network * If it's another network, cancel and start over with our new network * If it's our network, ignore the change, we're already doing it! @@ -98,13 +98,18 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, cancel_delayed_work(&authptr->work); sm->associnfo.bssvalid = 0; sm->associnfo.bssfixed = 0; - flush_scheduled_work(); sm->associnfo.associating = 0; sm->associnfo.associated = 0; + /* We must unlock to avoid deadlocks with the assoc workqueue + * on the associnfo.mutex */ + mutex_unlock(&sm->associnfo.mutex); + flush_scheduled_work(); + /* Avoid race! Check assoc status again. Maybe someone started an + * association while we flushed. */ + goto check_assoc_again; } } - sm->associnfo.static_essid = 0; sm->associnfo.assoc_wait = 0; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 06c08e5740fb..e68103475cca 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -831,7 +831,7 @@ const struct proto_ops inet_stream_ops = { .shutdown = inet_shutdown, .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, - .sendmsg = inet_sendmsg, + .sendmsg = tcp_sendmsg, .recvmsg = sock_common_recvmsg, .mmap = sock_no_mmap, .sendpage = tcp_sendpage, diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c index 321804315659..6d0c0f7364ad 100644 --- a/net/ipv4/netfilter/ipt_recent.c +++ b/net/ipv4/netfilter/ipt_recent.c @@ -387,12 +387,17 @@ static int recent_seq_open(struct inode *inode, struct file *file) st = kzalloc(sizeof(*st), GFP_KERNEL); if (st == NULL) return -ENOMEM; + ret = seq_open(file, &recent_seq_ops); - if (ret) + if (ret) { kfree(st); + goto out; + } + st->table = pde->data; seq = file->private_data; seq->private = st; +out: return ret; } diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 64552afd01cb..d9b5177989c6 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -509,3 +509,9 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void) module_init(nf_conntrack_l3proto_ipv4_init); module_exit(nf_conntrack_l3proto_ipv4_fini); + +void need_ipv4_conntrack(void) +{ + return; +} +EXPORT_SYMBOL_GPL(need_ipv4_conntrack); diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 27c7918e442a..b3dd5de9a258 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c @@ -294,15 +294,14 @@ static int exp_open(struct inode *inode, struct file *file) struct ct_expect_iter_state *st; int ret; - st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL); - if (st == NULL) + st = kzalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL); + if (!st) return -ENOMEM; ret = seq_open(file, &exp_seq_ops); if (ret) goto out_free; seq = file->private_data; seq->private = st; - memset(st, 0, sizeof(struct ct_expect_iter_state)); return ret; out_free: kfree(st); diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 332814dac503..46cc99def165 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -328,7 +328,7 @@ static int __init nf_nat_standalone_init(void) { int ret = 0; - need_conntrack(); + need_ipv4_conntrack(); #ifdef CONFIG_XFRM BUG_ON(ip_nat_decode_session != NULL); diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 24d7c9f31918..c6d71526f625 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -900,8 +900,9 @@ static int raw_seq_open(struct inode *inode, struct file *file) { struct seq_file *seq; int rc = -ENOMEM; - struct raw_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); + struct raw_iter_state *s; + s = kzalloc(sizeof(*s), GFP_KERNEL); if (!s) goto out; rc = seq_open(file, &raw_seq_ops); @@ -910,7 +911,6 @@ static int raw_seq_open(struct inode *inode, struct file *file) seq = file->private_data; seq->private = s; - memset(s, 0, sizeof(*s)); out: return rc; out_kfree: diff --git a/net/ipv4/route.c b/net/ipv4/route.c index df42b7fb3268..c7ca94bd152c 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -374,8 +374,9 @@ static int rt_cache_seq_open(struct inode *inode, struct file *file) { struct seq_file *seq; int rc = -ENOMEM; - struct rt_cache_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); + struct rt_cache_iter_state *s; + s = kzalloc(sizeof(*s), GFP_KERNEL); if (!s) goto out; rc = seq_open(file, &rt_cache_seq_ops); @@ -383,7 +384,6 @@ static int rt_cache_seq_open(struct inode *inode, struct file *file) goto out_kfree; seq = file->private_data; seq->private = s; - memset(s, 0, sizeof(*s)); out: return rc; out_kfree: diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index da4c0b6ab79a..7e740112b238 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -658,9 +658,10 @@ static inline int select_size(struct sock *sk) return tmp; } -int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, +int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size) { + struct sock *sk = sock->sk; struct iovec *iov; struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c index b66556c0a5bd..5215691f2760 100644 --- a/net/ipv4/tcp_htcp.c +++ b/net/ipv4/tcp_htcp.c @@ -79,7 +79,6 @@ static u32 htcp_cwnd_undo(struct sock *sk) static inline void measure_rtt(struct sock *sk, u32 srtt) { const struct inet_connection_sock *icsk = inet_csk(sk); - const struct tcp_sock *tp = tcp_sk(sk); struct htcp *ca = inet_csk_ca(sk); /* keep track of minimum RTT seen so far, minRTT is zero at first */ @@ -87,8 +86,7 @@ static inline void measure_rtt(struct sock *sk, u32 srtt) ca->minRTT = srtt; /* max RTT */ - if (icsk->icsk_ca_state == TCP_CA_Open - && tp->snd_ssthresh < 0xFFFF && htcp_ccount(ca) > 3) { + if (icsk->icsk_ca_state == TCP_CA_Open) { if (ca->maxRTT < ca->minRTT) ca->maxRTT = ca->minRTT; if (ca->maxRTT < srtt diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 378ca8a086a3..f030435e0eb4 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -102,11 +102,14 @@ int sysctl_tcp_abc __read_mostly; #define FLAG_DATA_LOST 0x80 /* SACK detected data lossage. */ #define FLAG_SLOWPATH 0x100 /* Do not skip RFC checks for window update.*/ #define FLAG_ONLY_ORIG_SACKED 0x200 /* SACKs only non-rexmit sent before RTO */ +#define FLAG_SND_UNA_ADVANCED 0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */ +#define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained DSACK info */ #define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED) #define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED) #define FLAG_CA_ALERT (FLAG_DATA_SACKED|FLAG_ECE) #define FLAG_FORWARD_PROGRESS (FLAG_ACKED|FLAG_DATA_SACKED) +#define FLAG_ANY_PROGRESS (FLAG_FORWARD_PROGRESS|FLAG_SND_UNA_ADVANCED) #define IsReno(tp) ((tp)->rx_opt.sack_ok == 0) #define IsFack(tp) ((tp)->rx_opt.sack_ok & 2) @@ -964,12 +967,14 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ /* Check for D-SACK. */ if (before(ntohl(sp[0].start_seq), TCP_SKB_CB(ack_skb)->ack_seq)) { + flag |= FLAG_DSACKING_ACK; found_dup_sack = 1; tp->rx_opt.sack_ok |= 4; NET_INC_STATS_BH(LINUX_MIB_TCPDSACKRECV); } else if (num_sacks > 1 && !after(ntohl(sp[0].end_seq), ntohl(sp[1].end_seq)) && !before(ntohl(sp[0].start_seq), ntohl(sp[1].start_seq))) { + flag |= FLAG_DSACKING_ACK; found_dup_sack = 1; tp->rx_opt.sack_ok |= 4; NET_INC_STATS_BH(LINUX_MIB_TCPDSACKOFORECV); @@ -1856,7 +1861,7 @@ static void tcp_cwnd_down(struct sock *sk, int flag) struct tcp_sock *tp = tcp_sk(sk); int decr = tp->snd_cwnd_cnt + 1; - if ((flag&FLAG_FORWARD_PROGRESS) || + if ((flag&(FLAG_ANY_PROGRESS|FLAG_DSACKING_ACK)) || (IsReno(tp) && !(flag&FLAG_NOT_DUP))) { tp->snd_cwnd_cnt = decr&1; decr >>= 1; @@ -2107,15 +2112,13 @@ static void tcp_mtup_probe_success(struct sock *sk, struct sk_buff *skb) * tcp_xmit_retransmit_queue(). */ static void -tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, - int prior_packets, int flag) +tcp_fastretrans_alert(struct sock *sk, int prior_packets, int flag) { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); - int is_dupack = (tp->snd_una == prior_snd_una && - (!(flag&FLAG_NOT_DUP) || - ((flag&FLAG_DATA_SACKED) && - (tp->fackets_out > tp->reordering)))); + int is_dupack = !(flag&(FLAG_SND_UNA_ADVANCED|FLAG_NOT_DUP)); + int do_lost = is_dupack || ((flag&FLAG_DATA_SACKED) && + (tp->fackets_out > tp->reordering)); /* Some technical things: * 1. Reno does not count dupacks (sacked_out) automatically. */ @@ -2192,14 +2195,14 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, /* F. Process state. */ switch (icsk->icsk_ca_state) { case TCP_CA_Recovery: - if (prior_snd_una == tp->snd_una) { + if (!(flag & FLAG_SND_UNA_ADVANCED)) { if (IsReno(tp) && is_dupack) tcp_add_reno_sack(sk); } else { int acked = prior_packets - tp->packets_out; if (IsReno(tp)) tcp_remove_reno_sacks(sk, acked); - is_dupack = tcp_try_undo_partial(sk, acked); + do_lost = tcp_try_undo_partial(sk, acked); } break; case TCP_CA_Loss: @@ -2215,7 +2218,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, /* Loss is undone; fall through to processing in Open state. */ default: if (IsReno(tp)) { - if (tp->snd_una != prior_snd_una) + if (flag & FLAG_SND_UNA_ADVANCED) tcp_reset_reno_sack(tp); if (is_dupack) tcp_add_reno_sack(sk); @@ -2264,7 +2267,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, tcp_set_ca_state(sk, TCP_CA_Recovery); } - if (is_dupack || tcp_head_timedout(sk)) + if (do_lost || tcp_head_timedout(sk)) tcp_update_scoreboard(sk); tcp_cwnd_down(sk, flag); tcp_xmit_retransmit_queue(sk); @@ -2684,7 +2687,7 @@ static void tcp_undo_spur_to_response(struct sock *sk, int flag) * to prove that the RTO is indeed spurious. It transfers the control * from F-RTO to the conventional RTO recovery */ -static int tcp_process_frto(struct sock *sk, u32 prior_snd_una, int flag) +static int tcp_process_frto(struct sock *sk, int flag) { struct tcp_sock *tp = tcp_sk(sk); @@ -2704,8 +2707,7 @@ static int tcp_process_frto(struct sock *sk, u32 prior_snd_una, int flag) * ACK isn't duplicate nor advances window, e.g., opposite dir * data, winupdate */ - if ((tp->snd_una == prior_snd_una) && (flag&FLAG_NOT_DUP) && - !(flag&FLAG_FORWARD_PROGRESS)) + if (!(flag&FLAG_ANY_PROGRESS) && (flag&FLAG_NOT_DUP)) return 1; if (!(flag&FLAG_DATA_ACKED)) { @@ -2785,6 +2787,9 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) if (before(ack, prior_snd_una)) goto old_ack; + if (after(ack, prior_snd_una)) + flag |= FLAG_SND_UNA_ADVANCED; + if (sysctl_tcp_abc) { if (icsk->icsk_ca_state < TCP_CA_CWR) tp->bytes_acked += ack - prior_snd_una; @@ -2837,14 +2842,14 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) flag |= tcp_clean_rtx_queue(sk, &seq_rtt); if (tp->frto_counter) - frto_cwnd = tcp_process_frto(sk, prior_snd_una, flag); + frto_cwnd = tcp_process_frto(sk, flag); if (tcp_ack_is_dubious(sk, flag)) { /* Advance CWND, if state allows this. */ if ((flag & FLAG_DATA_ACKED) && !frto_cwnd && tcp_may_raise_cwnd(sk, flag)) tcp_cong_avoid(sk, ack, prior_in_flight, 0); - tcp_fastretrans_alert(sk, prior_snd_una, prior_packets, flag); + tcp_fastretrans_alert(sk, prior_packets, flag); } else { if ((flag & FLAG_DATA_ACKED) && !frto_cwnd) tcp_cong_avoid(sk, ack, prior_in_flight, 1); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3f5f7423b95c..9c94627c8c7e 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2425,7 +2425,6 @@ struct proto tcp_prot = { .shutdown = tcp_shutdown, .setsockopt = tcp_setsockopt, .getsockopt = tcp_getsockopt, - .sendmsg = tcp_sendmsg, .recvmsg = tcp_recvmsg, .backlog_rcv = tcp_v4_do_rcv, .hash = tcp_v4_hash, diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index eed09373a45d..b5f96372ad73 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -484,7 +484,7 @@ const struct proto_ops inet6_stream_ops = { .shutdown = inet_shutdown, /* ok */ .setsockopt = sock_common_setsockopt, /* ok */ .getsockopt = sock_common_getsockopt, /* ok */ - .sendmsg = inet_sendmsg, /* ok */ + .sendmsg = tcp_sendmsg, /* ok */ .recvmsg = sock_common_recvmsg, /* ok */ .mmap = sock_no_mmap, .sendpage = tcp_sendpage, diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index f10f3689d671..cbdb78487915 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -2115,7 +2115,6 @@ struct proto tcpv6_prot = { .shutdown = tcp_shutdown, .setsockopt = tcp_setsockopt, .getsockopt = tcp_getsockopt, - .sendmsg = tcp_sendmsg, .recvmsg = tcp_recvmsg, .backlog_rcv = tcp_v6_do_rcv, .hash = tcp_v6_hash, diff --git a/net/key/af_key.c b/net/key/af_key.c index 7b0a95abe934..5502df115a63 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1206,6 +1206,9 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, x->sel.prefixlen_s = addr->sadb_address_prefixlen; } + if (!x->sel.family) + x->sel.family = x->props.family; + if (ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]) { struct sadb_x_nat_t_type* n_type; struct xfrm_encap_tmpl *natt; diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 799a9208c4b4..095be91829ca 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -271,9 +271,11 @@ static void add_files(struct ieee80211_sub_if_data *sdata) } } -#define DEBUGFS_DEL(name, type)\ - debugfs_remove(sdata->debugfs.type.name);\ - sdata->debugfs.type.name = NULL; +#define DEBUGFS_DEL(name, type) \ + do { \ + debugfs_remove(sdata->debugfs.type.name); \ + sdata->debugfs.type.name = NULL; \ + } while (0) static void del_sta_files(struct ieee80211_sub_if_data *sdata) { diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index d41e696f3980..da34ea70276f 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -157,7 +157,7 @@ static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf, struct sta_info *sta = file->private_data; for (i = 0; i < NUM_RX_DATA_QUEUES; i++) p += scnprintf(p, sizeof(buf)+buf-p, "%x ", - sta->last_seq_ctrl[i]); + le16_to_cpu(sta->last_seq_ctrl[i])); p += scnprintf(p, sizeof(buf)+buf-p, "\n"); return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); } diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index c944b17d0fc0..8ec5ed192b5d 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -1650,6 +1650,7 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb, if (skb_headroom(skb) < headroom) { if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) { dev_kfree_skb(skb); + dev_put(odev); return 0; } } diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index d0e1ab5589db..e7904db55325 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c @@ -697,17 +697,24 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev, if (!netif_running(dev)) return -ENETDOWN; - if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { - if (sdata->type == IEEE80211_IF_TYPE_STA || - sdata->type == IEEE80211_IF_TYPE_IBSS) { + switch (sdata->type) { + case IEEE80211_IF_TYPE_STA: + case IEEE80211_IF_TYPE_IBSS: + if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { ssid = sdata->u.sta.ssid; ssid_len = sdata->u.sta.ssid_len; - } else if (sdata->type == IEEE80211_IF_TYPE_AP) { + } + break; + case IEEE80211_IF_TYPE_AP: + if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { ssid = sdata->u.ap.ssid; ssid_len = sdata->u.ap.ssid_len; - } else - return -EINVAL; + } + break; + default: + return -EOPNOTSUPP; } + return ieee80211_sta_req_scan(dev, ssid, ssid_len); } diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index eb6695dcd73b..3ac64e25f10c 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -477,15 +477,14 @@ static int exp_open(struct inode *inode, struct file *file) struct ct_expect_iter_state *st; int ret; - st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL); - if (st == NULL) + st = kzalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL); + if (!st) return -ENOMEM; ret = seq_open(file, &exp_seq_ops); if (ret) goto out_free; seq = file->private_data; seq->private = st; - memset(st, 0, sizeof(struct ct_expect_iter_state)); return ret; out_free: kfree(st); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 6f89b105a205..2863e72b4091 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1052,17 +1052,18 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, } /* implicit 'else' */ - /* we only allow nat config for new conntracks */ - if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) { - err = -EINVAL; - goto out_unlock; - } - /* We manipulate the conntrack inside the global conntrack table lock, * so there's no need to increase the refcount */ err = -EEXIST; - if (!(nlh->nlmsg_flags & NLM_F_EXCL)) - err = ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h), cda); + if (!(nlh->nlmsg_flags & NLM_F_EXCL)) { + /* we only allow nat config for new conntracks */ + if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) { + err = -EINVAL; + goto out_unlock; + } + err = ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h), + cda); + } out_unlock: write_unlock_bh(&nf_conntrack_lock); diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index f46a0aeec44f..b6c844b7e1c1 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -126,7 +126,9 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def) if (domain != NULL) { bkt = netlbl_domhsh_hash(domain); - list_for_each_entry_rcu(iter, &netlbl_domhsh->tbl[bkt], list) + list_for_each_entry_rcu(iter, + &rcu_dereference(netlbl_domhsh)->tbl[bkt], + list) if (iter->valid && strcmp(iter->domain, domain) == 0) return iter; } @@ -227,7 +229,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, spin_lock(&netlbl_domhsh_lock); if (netlbl_domhsh_search(entry->domain, 0) == NULL) list_add_tail_rcu(&entry->list, - &netlbl_domhsh->tbl[bkt]); + &rcu_dereference(netlbl_domhsh)->tbl[bkt]); else ret_val = -EEXIST; spin_unlock(&netlbl_domhsh_lock); @@ -423,8 +425,8 @@ int netlbl_domhsh_walk(u32 *skip_bkt, iter_bkt < rcu_dereference(netlbl_domhsh)->size; iter_bkt++, chain_cnt = 0) { list_for_each_entry_rcu(iter_entry, - &netlbl_domhsh->tbl[iter_bkt], - list) + &rcu_dereference(netlbl_domhsh)->tbl[iter_bkt], + list) if (iter_entry->valid) { if (chain_cnt++ < *skip_chain) continue; diff --git a/net/sctp/input.c b/net/sctp/input.c index d57ff7f3c576..47e56017f4ce 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -590,7 +590,7 @@ out_unlock: * Return 0 - If further processing is needed. * Return 1 - If the packet can be discarded right away. */ -int sctp_rcv_ootb(struct sk_buff *skb) +static int sctp_rcv_ootb(struct sk_buff *skb) { sctp_chunkhdr_t *ch; __u8 *ch_end; diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 2c29394fd92e..f8aa23dda1c1 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -641,6 +641,8 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, newsctp6sk = (struct sctp6_sock *)newsk; inet_sk(newsk)->pinet6 = &newsctp6sk->inet6; + sctp_sk(newsk)->v4mapped = sctp_sk(sk)->v4mapped; + newinet = inet_sk(newsk); newnp = inet6_sk(newsk); diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 8d18f570c2e6..51c4d7fef1d2 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -65,8 +65,6 @@ #include <net/sctp/sctp.h> #include <net/sctp/sm.h> -extern struct kmem_cache *sctp_chunk_cachep; - SCTP_STATIC struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, __u8 type, __u8 flags, int paylen); @@ -115,15 +113,12 @@ void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, const void *payload, size_t paylen) { sctp_errhdr_t err; - int padlen; __u16 len; /* Cause code constants are now defined in network order. */ err.cause = cause_code; len = sizeof(sctp_errhdr_t) + paylen; - padlen = len % 4; err.length = htons(len); - len += padlen; chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err); sctp_addto_chunk(chunk, paylen, payload); } @@ -1454,7 +1449,6 @@ no_hmac: do_gettimeofday(&tv); if (!asoc && tv_lt(bear_cookie->expiration, tv)) { - __u16 len; /* * Section 3.3.10.3 Stale Cookie Error (3) * diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index fd2dfdd7d7fd..71cad56dd73f 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -97,6 +97,13 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, const struct sctp_association *asoc, struct sctp_transport *transport); +static sctp_disposition_t sctp_sf_abort_violation( + const struct sctp_association *asoc, + void *arg, + sctp_cmd_seq_t *commands, + const __u8 *payload, + const size_t paylen); + static sctp_disposition_t sctp_sf_violation_chunklen( const struct sctp_endpoint *ep, const struct sctp_association *asoc, @@ -104,6 +111,13 @@ static sctp_disposition_t sctp_sf_violation_chunklen( void *arg, sctp_cmd_seq_t *commands); +static sctp_disposition_t sctp_sf_violation_ctsn( + const struct sctp_endpoint *ep, + const struct sctp_association *asoc, + const sctp_subtype_t type, + void *arg, + sctp_cmd_seq_t *commands); + /* Small helper function that checks if the chunk length * is of the appropriate length. The 'required_length' argument * is set to be the size of a specific chunk we are testing. @@ -2880,6 +2894,13 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep, return SCTP_DISPOSITION_DISCARD; } + /* If Cumulative TSN Ack beyond the max tsn currently + * send, terminating the association and respond to the + * sender with an ABORT. + */ + if (!TSN_lt(ctsn, asoc->next_tsn)) + return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands); + /* Return this SACK for further processing. */ sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_SACKH(sackh)); @@ -3691,40 +3712,21 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep, return SCTP_DISPOSITION_VIOLATION; } - /* - * Handle a protocol violation when the chunk length is invalid. - * "Invalid" length is identified as smaller then the minimal length a - * given chunk can be. For example, a SACK chunk has invalid length - * if it's length is set to be smaller then the size of sctp_sack_chunk_t. - * - * We inform the other end by sending an ABORT with a Protocol Violation - * error code. - * - * Section: Not specified - * Verification Tag: Nothing to do - * Inputs - * (endpoint, asoc, chunk) - * - * Outputs - * (reply_msg, msg_up, counters) - * - * Generate an ABORT chunk and terminate the association. + * Common function to handle a protocol violation. */ -static sctp_disposition_t sctp_sf_violation_chunklen( - const struct sctp_endpoint *ep, +static sctp_disposition_t sctp_sf_abort_violation( const struct sctp_association *asoc, - const sctp_subtype_t type, void *arg, - sctp_cmd_seq_t *commands) + sctp_cmd_seq_t *commands, + const __u8 *payload, + const size_t paylen) { struct sctp_chunk *chunk = arg; struct sctp_chunk *abort = NULL; - char err_str[]="The following chunk had invalid length:"; /* Make the abort chunk. */ - abort = sctp_make_abort_violation(asoc, chunk, err_str, - sizeof(err_str)); + abort = sctp_make_abort_violation(asoc, chunk, payload, paylen); if (!abort) goto nomem; @@ -3756,6 +3758,57 @@ nomem: return SCTP_DISPOSITION_NOMEM; } +/* + * Handle a protocol violation when the chunk length is invalid. + * "Invalid" length is identified as smaller then the minimal length a + * given chunk can be. For example, a SACK chunk has invalid length + * if it's length is set to be smaller then the size of sctp_sack_chunk_t. + * + * We inform the other end by sending an ABORT with a Protocol Violation + * error code. + * + * Section: Not specified + * Verification Tag: Nothing to do + * Inputs + * (endpoint, asoc, chunk) + * + * Outputs + * (reply_msg, msg_up, counters) + * + * Generate an ABORT chunk and terminate the association. + */ +static sctp_disposition_t sctp_sf_violation_chunklen( + const struct sctp_endpoint *ep, + const struct sctp_association *asoc, + const sctp_subtype_t type, + void *arg, + sctp_cmd_seq_t *commands) +{ + char err_str[]="The following chunk had invalid length:"; + + return sctp_sf_abort_violation(asoc, arg, commands, err_str, + sizeof(err_str)); +} + +/* Handle a protocol violation when the peer trying to advance the + * cumulative tsn ack to a point beyond the max tsn currently sent. + * + * We inform the other end by sending an ABORT with a Protocol Violation + * error code. + */ +static sctp_disposition_t sctp_sf_violation_ctsn( + const struct sctp_endpoint *ep, + const struct sctp_association *asoc, + const sctp_subtype_t type, + void *arg, + sctp_cmd_seq_t *commands) +{ + char err_str[]="The cumulative tsn ack beyond the max tsn currently sent:"; + + return sctp_sf_abort_violation(asoc, arg, commands, err_str, + sizeof(err_str)); +} + /*************************************************************************** * These are the state functions for handling primitive (Section 10) events. ***************************************************************************/ diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ee88f2ea5101..01c6364245b7 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -107,8 +107,6 @@ static void sctp_sock_migrate(struct sock *, struct sock *, struct sctp_association *, sctp_socket_type_t); static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG; -extern struct kmem_cache *sctp_bucket_cachep; - /* Get the sndbuf space available at the time on the association. */ static inline int sctp_wspace(struct sctp_association *asoc) { @@ -433,7 +431,7 @@ out: * * Only sctp_setsockopt_bindx() is supposed to call this function. */ -int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt) +static int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt) { int cnt; int retval = 0; @@ -602,7 +600,7 @@ out: * * Only sctp_setsockopt_bindx() is supposed to call this function. */ -int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) +static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) { struct sctp_sock *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; @@ -977,7 +975,7 @@ static int __sctp_connect(struct sock* sk, int err = 0; int addrcnt = 0; int walk_size = 0; - union sctp_addr *sa_addr; + union sctp_addr *sa_addr = NULL; void *addr_buf; unsigned short port; unsigned int f_flags = 0; @@ -1011,7 +1009,10 @@ static int __sctp_connect(struct sock* sk, goto out_free; } - err = sctp_verify_addr(sk, sa_addr, af->sockaddr_len); + /* Save current address so we can work with it */ + memcpy(&to, sa_addr, af->sockaddr_len); + + err = sctp_verify_addr(sk, &to, af->sockaddr_len); if (err) goto out_free; @@ -1021,12 +1022,11 @@ static int __sctp_connect(struct sock* sk, if (asoc && asoc->peer.port && asoc->peer.port != port) goto out_free; - memcpy(&to, sa_addr, af->sockaddr_len); /* Check if there already is a matching association on the * endpoint (other than the one created here). */ - asoc2 = sctp_endpoint_lookup_assoc(ep, sa_addr, &transport); + asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport); if (asoc2 && asoc2 != asoc) { if (asoc2->state >= SCTP_STATE_ESTABLISHED) err = -EISCONN; @@ -1039,7 +1039,7 @@ static int __sctp_connect(struct sock* sk, * make sure that there is no peeled-off association matching * the peer address even on another socket. */ - if (sctp_endpoint_is_peeled_off(ep, sa_addr)) { + if (sctp_endpoint_is_peeled_off(ep, &to)) { err = -EADDRNOTAVAIL; goto out_free; } @@ -1070,7 +1070,7 @@ static int __sctp_connect(struct sock* sk, } } - scope = sctp_scope(sa_addr); + scope = sctp_scope(&to); asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); if (!asoc) { err = -ENOMEM; @@ -1079,7 +1079,7 @@ static int __sctp_connect(struct sock* sk, } /* Prime the peer's transport structures. */ - transport = sctp_assoc_add_peer(asoc, sa_addr, GFP_KERNEL, + transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN); if (!transport) { err = -ENOMEM; @@ -1103,8 +1103,8 @@ static int __sctp_connect(struct sock* sk, /* Initialize sk's dport and daddr for getpeername() */ inet_sk(sk)->dport = htons(asoc->peer.port); - af = sctp_get_af_specific(to.sa.sa_family); - af->to_sk_daddr(&to, sk); + af = sctp_get_af_specific(sa_addr->sa.sa_family); + af->to_sk_daddr(sa_addr, sk); sk->sk_err = 0; /* in-kernel sockets don't generally have a file allocated to them @@ -1531,7 +1531,6 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, goto out_unlock; } if (sinfo_flags & SCTP_ABORT) { - struct sctp_chunk *chunk; chunk = sctp_make_abort_user(asoc, msg, msg_len); if (!chunk) { @@ -4353,7 +4352,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, space_left, &bytes_copied); if (cnt < 0) { err = cnt; - goto error; + goto error_lock; } goto copy_getaddrs; } @@ -4367,7 +4366,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; if (space_left < addrlen) { err = -ENOMEM; /*fixme: right error?*/ - goto error; + goto error_lock; } memcpy(buf, &temp, addrlen); buf += addrlen; @@ -4381,15 +4380,21 @@ copy_getaddrs: if (copy_to_user(to, addrs, bytes_copied)) { err = -EFAULT; - goto error; + goto out; } if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) { err = -EFAULT; - goto error; + goto out; } if (put_user(bytes_copied, optlen)) err = -EFAULT; -error: + + goto out; + +error_lock: + sctp_read_unlock(addr_lock); + +out: kfree(addrs); return err; } @@ -5964,7 +5969,7 @@ static int sctp_wait_for_accept(struct sock *sk, long timeo) return err; } -void sctp_wait_for_close(struct sock *sk, long timeout) +static void sctp_wait_for_close(struct sock *sk, long timeout) { DEFINE_WAIT(wait); diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c index d3192a1babcc..1ff0daade304 100644 --- a/net/sctp/tsnmap.c +++ b/net/sctp/tsnmap.c @@ -161,7 +161,7 @@ SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, __u16 *start, __u16 *end) { int started, ended; - __u16 _start, _end, offset; + __u16 start_, end_, offset; /* We haven't found a gap yet. */ started = ended = 0; @@ -175,7 +175,7 @@ SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, offset = iter->start - map->base_tsn; sctp_tsnmap_find_gap_ack(map->tsn_map, offset, map->len, 0, - &started, &_start, &ended, &_end); + &started, &start_, &ended, &end_); } /* Do we need to check the overflow map? */ @@ -193,8 +193,8 @@ SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, offset, map->len, map->len, - &started, &_start, - &ended, &_end); + &started, &start_, + &ended, &end_); } /* The Gap Ack Block happens to end at the end of the @@ -202,7 +202,7 @@ SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, */ if (started && !ended) { ended++; - _end = map->len + map->len - 1; + end_ = map->len + map->len - 1; } /* If we found a Gap Ack Block, return the start and end and @@ -215,8 +215,8 @@ SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, int gap = map->cumulative_tsn_ack_point - map->base_tsn; - *start = _start - gap; - *end = _end - gap; + *start = start_ - gap; + *end = end_ - gap; /* Move the iterator forward. */ iter->start = map->cumulative_tsn_ack_point + *end + 1; diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 4bbc59cc237c..53995af9ca4b 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -736,9 +736,6 @@ gss_do_free_ctx(struct gss_cl_ctx *ctx) { dprintk("RPC: gss_free_ctx\n"); - if (ctx->gc_gss_ctx) - gss_delete_sec_context(&ctx->gc_gss_ctx); - kfree(ctx->gc_wire_ctx.data); kfree(ctx); } @@ -753,7 +750,13 @@ gss_free_ctx_callback(struct rcu_head *head) static void gss_free_ctx(struct gss_cl_ctx *ctx) { + struct gss_ctx *gc_gss_ctx; + + gc_gss_ctx = rcu_dereference(ctx->gc_gss_ctx); + rcu_assign_pointer(ctx->gc_gss_ctx, NULL); call_rcu(&ctx->gc_rcu, gss_free_ctx_callback); + if (gc_gss_ctx) + gss_delete_sec_context(&gc_gss_ctx); } static void diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 01c3c4105204..ebe344f34d1a 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -371,8 +371,7 @@ int cache_unregister(struct cache_detail *cd) } if (list_empty(&cache_list)) { /* module must be being unloaded so its safe to kill the worker */ - cancel_delayed_work(&cache_cleaner); - flush_scheduled_work(); + cancel_delayed_work_sync(&cache_cleaner); } return 0; } diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 650af064ff8d..669e12a4ed18 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -132,8 +132,7 @@ rpc_close_pipes(struct inode *inode) rpci->nwriters = 0; if (ops->release_pipe) ops->release_pipe(inode); - cancel_delayed_work(&rpci->queue_timeout); - flush_workqueue(rpciod_workqueue); + cancel_delayed_work_sync(&rpci->queue_timeout); } rpc_inode_setowner(inode, NULL); mutex_unlock(&inode->i_mutex); diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index b5723c262a3e..954d7ec86c7e 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -50,8 +50,6 @@ static RPC_WAITQ(delay_queue, "delayq"); /* * rpciod-related stuff */ -static DEFINE_MUTEX(rpciod_mutex); -static atomic_t rpciod_users = ATOMIC_INIT(0); struct workqueue_struct *rpciod_workqueue; /* @@ -961,60 +959,49 @@ void rpc_killall_tasks(struct rpc_clnt *clnt) spin_unlock(&clnt->cl_lock); } +int rpciod_up(void) +{ + return try_module_get(THIS_MODULE) ? 0 : -EINVAL; +} + +void rpciod_down(void) +{ + module_put(THIS_MODULE); +} + /* - * Start up the rpciod process if it's not already running. + * Start up the rpciod workqueue. */ -int -rpciod_up(void) +static int rpciod_start(void) { struct workqueue_struct *wq; - int error = 0; - - if (atomic_inc_not_zero(&rpciod_users)) - return 0; - - mutex_lock(&rpciod_mutex); - /* Guard against races with rpciod_down() */ - if (rpciod_workqueue != NULL) - goto out_ok; /* * Create the rpciod thread and wait for it to start. */ dprintk("RPC: creating workqueue rpciod\n"); - error = -ENOMEM; wq = create_workqueue("rpciod"); - if (wq == NULL) - goto out; - rpciod_workqueue = wq; - error = 0; -out_ok: - atomic_inc(&rpciod_users); -out: - mutex_unlock(&rpciod_mutex); - return error; + return rpciod_workqueue != NULL; } -void -rpciod_down(void) +static void rpciod_stop(void) { - if (!atomic_dec_and_test(&rpciod_users)) - return; + struct workqueue_struct *wq = NULL; - mutex_lock(&rpciod_mutex); + if (rpciod_workqueue == NULL) + return; dprintk("RPC: destroying workqueue rpciod\n"); - if (atomic_read(&rpciod_users) == 0 && rpciod_workqueue != NULL) { - destroy_workqueue(rpciod_workqueue); - rpciod_workqueue = NULL; - } - mutex_unlock(&rpciod_mutex); + wq = rpciod_workqueue; + rpciod_workqueue = NULL; + destroy_workqueue(wq); } void rpc_destroy_mempool(void) { + rpciod_stop(); if (rpc_buffer_mempool) mempool_destroy(rpc_buffer_mempool); if (rpc_task_mempool) @@ -1048,6 +1035,8 @@ rpc_init_mempool(void) rpc_buffer_slabp); if (!rpc_buffer_mempool) goto err_nomem; + if (!rpciod_start()) + goto err_nomem; return 0; err_nomem: rpc_destroy_mempool(); diff --git a/net/tipc/link.c b/net/tipc/link.c index 1d674e0848fa..1b17fecee747 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -2383,10 +2383,10 @@ void tipc_link_changeover(struct link *l_ptr) struct tipc_msg *msg = buf_msg(crs); if ((msg_user(msg) == MSG_BUNDLER) && split_bundles) { - u32 msgcount = msg_msgcnt(msg); struct tipc_msg *m = msg_get_wrapped(msg); unchar* pos = (unchar*)m; + msgcount = msg_msgcnt(msg); while (msgcount--) { msg_set_seqno(m,msg_seqno(msg)); tipc_link_tunnel(l_ptr, &tunnel_hdr, m, diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index d8473eefcd23..ac7dfdda7973 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -501,7 +501,7 @@ end_node: * sequence overlapping with the requested sequence */ -void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s) +static void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s) { struct sub_seq *sseq = nseq->sseqs; diff --git a/net/tipc/node.c b/net/tipc/node.c index e2e452a62ba1..598f4d3a0098 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -241,8 +241,6 @@ struct node *tipc_node_attach_link(struct link *l_ptr) char addr_string[16]; if (n_ptr->link_cnt >= 2) { - char addr_string[16]; - err("Attempt to create third link to %s\n", addr_string_fill(addr_string, n_ptr->addr)); return NULL; diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 849cc06bd914..9ab31a3ce3ad 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -46,7 +46,6 @@ #include <linux/capability.h> #include <linux/errno.h> /* return codes */ #include <linux/kernel.h> -#include <linux/init.h> #include <linux/module.h> /* support for loadable modules */ #include <linux/slab.h> /* kmalloc(), kfree() */ #include <linux/mm.h> |