diff options
Diffstat (limited to 'net')
89 files changed, 342 insertions, 648 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index acc74ad..a292e80 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -86,6 +86,13 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) grp = &vlan_info->grp; + /* Take it out of our own structures, but be sure to interlock with + * HW accelerating devices or SW vlan input packet processing if + * VLAN is not 0 (leave it there for 802.1p). + */ + if (vlan_id) + vlan_vid_del(real_dev, vlan_id); + grp->nr_vlan_devs--; if (vlan->flags & VLAN_FLAG_GVRP) @@ -101,13 +108,6 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) if (grp->nr_vlan_devs == 0) vlan_gvrp_uninit_applicant(real_dev); - /* Take it out of our own structures, but be sure to interlock with - * HW accelerating devices or SW vlan input packet processing if - * VLAN is not 0 (leave it there for 802.1p). - */ - if (vlan_id) - vlan_vid_del(real_dev, vlan_id); - /* Get rid of the vlan's reference to real_dev */ dev_put(real_dev); } diff --git a/net/atm/common.c b/net/atm/common.c index cf4b7e6..806fc0a 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -532,8 +532,6 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, struct sk_buff *skb; int copied, error = -EINVAL; - msg->msg_namelen = 0; - if (sock->state != SS_CONNECTED) return -ENOTCONN; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index d53a123..779095d 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1647,7 +1647,6 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock, ax25_address src; const unsigned char *mac = skb_mac_header(skb); - memset(sax, 0, sizeof(struct full_sockaddr_ax25)); ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL, &digi, NULL, NULL); sax->sax25_family = AF_AX25; diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 1ee94d0..7d02ebd 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -1298,8 +1298,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff; /* unpack the aggregated packets and process them one by one */ - while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len, - batadv_ogm_packet->tt_num_changes)) { + do { tt_buff = packet_buff + buff_pos + BATADV_OGM_HLEN; batadv_iv_ogm_process(ethhdr, batadv_ogm_packet, tt_buff, @@ -1310,7 +1309,8 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, packet_pos = packet_buff + buff_pos; batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; - } + } while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len, + batadv_ogm_packet->tt_num_changes)); kfree_skb(skb); return NET_RX_SUCCESS; diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index b04795e..5355df6 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -230,8 +230,6 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags & (MSG_OOB)) return -EOPNOTSUPP; - msg->msg_namelen = 0; - skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) { if (sk->sk_shutdown & RCV_SHUTDOWN) @@ -239,6 +237,8 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, return err; } + msg->msg_namelen = 0; + copied = skb->len; if (len < copied) { msg->msg_flags |= MSG_TRUNC; diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 970fc13..ce3f665 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -610,7 +610,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { rfcomm_dlc_accept(d); - msg->msg_namelen = 0; return 0; } diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index cc16d1b..57f250c 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -361,7 +361,6 @@ static void __sco_sock_close(struct sock *sk) sco_chan_del(sk, ECONNRESET); break; - case BT_CONNECT2: case BT_CONNECT: case BT_DISCONN: sco_chan_del(sk, ECONNRESET); @@ -667,7 +666,6 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock, test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { hci_conn_accept(pi->conn->hcon, 0); sk->sk_state = BT_CONFIG; - msg->msg_namelen = 0; release_sock(sk); return 0; diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 2897e40..acc9f4c 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -82,7 +82,6 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, port = p->port; if (port) { struct br_mdb_entry e; - memset(&e, 0, sizeof(e)); e.ifindex = port->dev->ifindex; e.state = p->state; if (p->addr.proto == htons(ETH_P_IP)) @@ -139,7 +138,6 @@ static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb) break; bpm = nlmsg_data(nlh); - memset(bpm, 0, sizeof(*bpm)); bpm->ifindex = dev->ifindex; if (br_mdb_fill_info(skb, cb, dev) < 0) goto out; @@ -175,7 +173,6 @@ static int nlmsg_populate_mdb_fill(struct sk_buff *skb, return -EMSGSIZE; bpm = nlmsg_data(nlh); - memset(bpm, 0, sizeof(*bpm)); bpm->family = AF_BRIDGE; bpm->ifindex = dev->ifindex; nest = nla_nest_start(skb, MDBA_MDB); @@ -233,7 +230,6 @@ void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, { struct br_mdb_entry entry; - memset(&entry, 0, sizeof(entry)); entry.ifindex = port->dev->ifindex; entry.addr.proto = group->proto; entry.addr.u.ip4 = group->u.ip4; diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 580e176..5dc66ab 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -28,7 +28,6 @@ static inline size_t br_port_info_size(void) + nla_total_size(1) /* IFLA_BRPORT_MODE */ + nla_total_size(1) /* IFLA_BRPORT_GUARD */ + nla_total_size(1) /* IFLA_BRPORT_PROTECT */ - + nla_total_size(1) /* IFLA_BRPORT_FAST_LEAVE */ + 0; } diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index ff2ff3c..095259f 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -286,8 +286,6 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock, if (m->msg_flags&MSG_OOB) goto read_error; - m->msg_namelen = 0; - skb = skb_recv_datagram(sk, flags, 0 , &ret); if (!skb) goto read_error; diff --git a/net/can/gw.c b/net/can/gw.c index 28e7bdc..574dda78e 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -436,7 +436,7 @@ static int cgw_notifier(struct notifier_block *nb, if (gwj->src.dev == dev || gwj->dst.dev == dev) { hlist_del(&gwj->list); cgw_unregister_filter(gwj); - kmem_cache_free(cgw_cache, gwj); + kfree(gwj); } } } @@ -829,7 +829,7 @@ static void cgw_remove_all_jobs(void) hlist_for_each_entry_safe(gwj, n, nx, &cgw_list, list) { hlist_del(&gwj->list); cgw_unregister_filter(gwj); - kmem_cache_free(cgw_cache, gwj); + kfree(gwj); } } @@ -885,7 +885,7 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) hlist_del(&gwj->list); cgw_unregister_filter(gwj); - kmem_cache_free(cgw_cache, gwj); + kfree(gwj); err = 0; break; } diff --git a/net/core/dev.c b/net/core/dev.c index 67c8074..147a682 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -203,7 +203,7 @@ static struct list_head offload_base __read_mostly; DEFINE_RWLOCK(dev_base_lock); EXPORT_SYMBOL(dev_base_lock); -DEFINE_MUTEX(devnet_rename_mutex); +seqcount_t devnet_rename_seq; static inline void dev_base_seq_inc(struct net *net) { @@ -225,14 +225,14 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex) static inline void rps_lock(struct softnet_data *sd) { #ifdef CONFIG_RPS - raw_spin_lock(&sd->input_pkt_queue.raw_lock); + spin_lock(&sd->input_pkt_queue.lock); #endif } static inline void rps_unlock(struct softnet_data *sd) { #ifdef CONFIG_RPS - raw_spin_unlock(&sd->input_pkt_queue.raw_lock); + spin_unlock(&sd->input_pkt_queue.lock); #endif } @@ -1093,11 +1093,10 @@ int dev_change_name(struct net_device *dev, const char *newname) if (dev->flags & IFF_UP) return -EBUSY; - - mutex_lock(&devnet_rename_mutex); + write_seqcount_begin(&devnet_rename_seq); if (strncmp(newname, dev->name, IFNAMSIZ) == 0) { - mutex_unlock(&devnet_rename_mutex); + write_seqcount_end(&devnet_rename_seq); return 0; } @@ -1105,7 +1104,7 @@ int dev_change_name(struct net_device *dev, const char *newname) err = dev_get_valid_name(net, dev, newname); if (err < 0) { - mutex_unlock(&devnet_rename_mutex); + write_seqcount_end(&devnet_rename_seq); return err; } @@ -1113,11 +1112,11 @@ rollback: ret = device_rename(&dev->dev, dev->name); if (ret) { memcpy(dev->name, oldname, IFNAMSIZ); - mutex_unlock(&devnet_rename_mutex); + write_seqcount_end(&devnet_rename_seq); return ret; } - mutex_unlock(&devnet_rename_mutex); + write_seqcount_end(&devnet_rename_seq); write_lock_bh(&dev_base_lock); hlist_del_rcu(&dev->name_hlist); @@ -1136,7 +1135,7 @@ rollback: /* err >= 0 after dev_alloc_name() or stores the first errno */ if (err >= 0) { err = ret; - mutex_lock(&devnet_rename_mutex); + write_seqcount_begin(&devnet_rename_seq); memcpy(dev->name, oldname, IFNAMSIZ); goto rollback; } else { @@ -1592,6 +1591,7 @@ void net_enable_timestamp(void) return; } #endif + WARN_ON(in_interrupt()); static_key_slow_inc(&netstamp_needed); } EXPORT_SYMBOL(net_enable_timestamp); @@ -1738,7 +1738,6 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) skb->mark = 0; secpath_reset(skb); nf_reset(skb); - nf_reset_trace(skb); return netif_rx(skb); } EXPORT_SYMBOL_GPL(dev_forward_skb); @@ -1947,7 +1946,6 @@ static inline void __netif_reschedule(struct Qdisc *q) sd->output_queue_tailp = &q->next_sched; raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_restore(flags); - preempt_check_resched_rt(); } void __netif_schedule(struct Qdisc *q) @@ -1969,7 +1967,6 @@ void dev_kfree_skb_irq(struct sk_buff *skb) sd->completion_queue = skb; raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_restore(flags); - preempt_check_resched_rt(); } } EXPORT_SYMBOL(dev_kfree_skb_irq); @@ -2021,9 +2018,6 @@ static void skb_warn_bad_offload(const struct sk_buff *skb) struct net_device *dev = skb->dev; const char *driver = ""; - if (!net_ratelimit()) - return; - if (dev && dev->dev.parent) driver = dev_driver_string(dev->dev.parent); @@ -3084,7 +3078,6 @@ enqueue: rps_unlock(sd); local_irq_restore(flags); - preempt_check_resched_rt(); atomic_long_inc(&skb->dev->rx_dropped); kfree_skb(skb); @@ -3122,7 +3115,7 @@ int netif_rx(struct sk_buff *skb) struct rps_dev_flow voidflow, *rflow = &voidflow; int cpu; - migrate_disable(); + preempt_disable(); rcu_read_lock(); cpu = get_rps_cpu(skb->dev, skb, &rflow); @@ -3132,13 +3125,13 @@ int netif_rx(struct sk_buff *skb) ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail); rcu_read_unlock(); - migrate_enable(); + preempt_enable(); } else #endif { unsigned int qtail; - ret = enqueue_to_backlog(skb, get_cpu_light(), &qtail); - put_cpu_light(); + ret = enqueue_to_backlog(skb, get_cpu(), &qtail); + put_cpu(); } return ret; } @@ -3148,44 +3141,16 @@ int netif_rx_ni(struct sk_buff *skb) { int err; - local_bh_disable(); + preempt_disable(); err = netif_rx(skb); - local_bh_enable(); + if (local_softirq_pending()) + do_softirq(); + preempt_enable(); return err; } EXPORT_SYMBOL(netif_rx_ni); -#ifdef CONFIG_PREEMPT_RT_FULL -/* - * RT runs ksoftirqd as a real time thread and the root_lock is a - * "sleeping spinlock". If the trylock fails then we can go into an - * infinite loop when ksoftirqd preempted the task which actually - * holds the lock, because we requeue q and raise NET_TX softirq - * causing ksoftirqd to loop forever. - * - * It's safe to use spin_lock on RT here as softirqs run in thread - * context and cannot deadlock against the thread which is holding - * root_lock. - * - * On !RT the trylock might fail, but there we bail out from the - * softirq loop after 10 attempts which we can't do on RT. And the - * task holding root_lock cannot be preempted, so the only downside of - * that trylock is that we need 10 loops to decide that we should have - * given up in the first one :) - */ -static inline int take_root_lock(spinlock_t *lock) -{ - spin_lock(lock); - return 1; -} -#else -static inline int take_root_lock(spinlock_t *lock) -{ - return spin_trylock(lock); -} -#endif - static void net_tx_action(struct softirq_action *h) { struct softnet_data *sd = &__get_cpu_var(softnet_data); @@ -3224,7 +3189,7 @@ static void net_tx_action(struct softirq_action *h) head = head->next_sched; root_lock = qdisc_lock(q); - if (take_root_lock(root_lock)) { + if (spin_trylock(root_lock)) { smp_mb__before_clear_bit(); clear_bit(__QDISC_STATE_SCHED, &q->state); @@ -3338,7 +3303,6 @@ int netdev_rx_handler_register(struct net_device *dev, if (dev->rx_handler) return -EBUSY; - /* Note: rx_handler_data must be set before rx_handler */ rcu_assign_pointer(dev->rx_handler_data, rx_handler_data); rcu_assign_pointer(dev->rx_handler, rx_handler); @@ -3359,11 +3323,6 @@ void netdev_rx_handler_unregister(struct net_device *dev) ASSERT_RTNL(); RCU_INIT_POINTER(dev->rx_handler, NULL); - /* a reader seeing a non NULL rx_handler in a rcu_read_lock() - * section has a guarantee to see a non NULL rx_handler_data - * as well. - */ - synchronize_net(); RCU_INIT_POINTER(dev->rx_handler_data, NULL); } EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); @@ -3486,7 +3445,6 @@ ncls: } switch (rx_handler(&skb)) { case RX_HANDLER_CONSUMED: - ret = NET_RX_SUCCESS; goto unlock; case RX_HANDLER_ANOTHER: goto another_round; @@ -3595,7 +3553,7 @@ static void flush_backlog(void *arg) skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) { if (skb->dev == dev) { __skb_unlink(skb, &sd->input_pkt_queue); - __skb_queue_tail(&sd->tofree_queue, skb); + kfree_skb(skb); input_queue_head_incr(sd); } } @@ -3604,13 +3562,10 @@ static void flush_backlog(void *arg) skb_queue_walk_safe(&sd->process_queue, skb, tmp) { if (skb->dev == dev) { __skb_unlink(skb, &sd->process_queue); - __skb_queue_tail(&sd->tofree_queue, skb); + kfree_skb(skb); input_queue_head_incr(sd); } } - - if (!skb_queue_empty(&sd->tofree_queue)) - raise_softirq_irqoff(NET_RX_SOFTIRQ); } static int napi_gro_complete(struct sk_buff *skb) @@ -3969,7 +3924,6 @@ static void net_rps_action_and_irq_enable(struct softnet_data *sd) } else #endif local_irq_enable(); - preempt_check_resched_rt(); } static int process_backlog(struct napi_struct *napi, int quota) @@ -4042,7 +3996,6 @@ void __napi_schedule(struct napi_struct *n) local_irq_save(flags); ____napi_schedule(&__get_cpu_var(softnet_data), n); local_irq_restore(flags); - preempt_check_resched_rt(); } EXPORT_SYMBOL(__napi_schedule); @@ -4117,17 +4070,10 @@ static void net_rx_action(struct softirq_action *h) struct softnet_data *sd = &__get_cpu_var(softnet_data); unsigned long time_limit = jiffies + 2; int budget = netdev_budget; - struct sk_buff *skb; void *have; local_irq_disable(); - while ((skb = __skb_dequeue(&sd->tofree_queue))) { - local_irq_enable(); - kfree_skb(skb); - local_irq_disable(); - } - while (!list_empty(&sd->poll_list)) { struct napi_struct *n; int work, weight; @@ -4250,6 +4196,7 @@ static int dev_ifname(struct net *net, struct ifreq __user *arg) { struct net_device *dev; struct ifreq ifr; + unsigned seq; /* * Fetch the caller's info block. @@ -4258,18 +4205,19 @@ static int dev_ifname(struct net *net, struct ifreq __user *arg) if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) return -EFAULT; - mutex_lock(&devnet_rename_mutex); +retry: + seq = read_seqcount_begin(&devnet_rename_seq); rcu_read_lock(); dev = dev_get_by_index_rcu(net, ifr.ifr_ifindex); if (!dev) { rcu_read_unlock(); - mutex_unlock(&devnet_rename_mutex); return -ENODEV; } strcpy(ifr.ifr_name, dev->name); rcu_read_unlock(); - mutex_unlock(&devnet_rename_mutex); + if (read_seqcount_retry(&devnet_rename_seq, seq)) + goto retry; if (copy_to_user(arg, &ifr, sizeof(struct ifreq))) return -EFAULT; @@ -6597,7 +6545,6 @@ static int dev_cpu_callback(struct notifier_block *nfb, raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_enable(); - preempt_check_resched_rt(); /* Process offline CPU's input_pkt_queue */ while ((skb = __skb_dequeue(&oldsd->process_queue))) { @@ -6608,9 +6555,6 @@ static int dev_cpu_callback(struct notifier_block *nfb, netif_rx(skb); input_queue_head_incr(oldsd); } - while ((skb = __skb_dequeue(&oldsd->tofree_queue))) { - kfree_skb(skb); - } return NOTIFY_OK; } @@ -6883,9 +6827,8 @@ static int __init net_dev_init(void) struct softnet_data *sd = &per_cpu(softnet_data, i); memset(sd, 0, sizeof(*sd)); - skb_queue_head_init_raw(&sd->input_pkt_queue); - skb_queue_head_init_raw(&sd->process_queue); - skb_queue_head_init_raw(&sd->tofree_queue); + skb_queue_head_init(&sd->input_pkt_queue); + skb_queue_head_init(&sd->process_queue); sd->completion_queue = NULL; INIT_LIST_HEAD(&sd->poll_list); sd->output_queue = NULL; diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 7841d87..b079c7b 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -38,7 +38,7 @@ static int __hw_addr_create_ex(struct netdev_hw_addr_list *list, ha->type = addr_type; ha->refcount = 1; ha->global_use = global; - ha->synced = 0; + ha->synced = false; list_add_tail_rcu(&ha->list, &list->list); list->count++; @@ -166,7 +166,7 @@ int __hw_addr_sync(struct netdev_hw_addr_list *to_list, addr_len, ha->type); if (err) break; - ha->synced++; + ha->synced = true; ha->refcount++; } else if (ha->refcount == 1) { __hw_addr_del(to_list, ha->addr, addr_len, ha->type); @@ -187,7 +187,7 @@ void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, if (ha->synced) { __hw_addr_del(to_list, ha->addr, addr_len, ha->type); - ha->synced--; + ha->synced = false; __hw_addr_del(from_list, ha->addr, addr_len, ha->type); } diff --git a/net/core/dst.c b/net/core/dst.c index 35fd12f..ee6153e 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -179,7 +179,6 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev, dst_init_metrics(dst, dst_default_metrics, true); dst->expires = 0UL; dst->path = dst; - dst->from = NULL; #ifdef CONFIG_XFRM dst->xfrm = NULL; #endif diff --git a/net/core/flow.c b/net/core/flow.c index 3bad824..b0901ee 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -329,7 +329,7 @@ static void flow_cache_flush_per_cpu(void *data) struct flow_flush_info *info = data; struct tasklet_struct *tasklet; - tasklet = &this_cpu_ptr(info->cache->percpu)->flush_tasklet; + tasklet = this_cpu_ptr(&info->cache->percpu->flush_tasklet); tasklet->data = (unsigned long)info; tasklet_schedule(tasklet); } diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 055fb13..1868625 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -976,7 +976,6 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, * report anything. */ ivi.spoofchk = -1; - memset(ivi.mac, 0, sizeof(ivi.mac)); if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) break; vf_mac.vf = @@ -1068,7 +1067,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) rcu_read_lock(); cb->seq = net->dev_base_seq; - if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, + if (nlmsg_parse(cb->nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX, ifla_policy) >= 0) { if (tb[IFLA_EXT_MASK]) @@ -1924,7 +1923,7 @@ static u16 rtnl_calcit(struct sk_buff *skb, struct nlmsghdr *nlh) u32 ext_filter_mask = 0; u16 min_ifinfo_dump_size = 0; - if (nlmsg_parse(nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, + if (nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX, ifla_policy) >= 0) { if (tb[IFLA_EXT_MASK]) ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); @@ -2539,7 +2538,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len); while (RTA_OK(attr, attrlen)) { - unsigned int flavor = attr->rta_type & NLA_TYPE_MASK; + unsigned int flavor = attr->rta_type; if (flavor) { if (flavor > rta_max[sz_idx]) return -EINVAL; diff --git a/net/core/scm.c b/net/core/scm.c index 2dc6cda..905dcc6 100644 --- a/net/core/scm.c +++ b/net/core/scm.c @@ -24,7 +24,6 @@ #include <linux/interrupt.h> #include <linux/netdevice.h> #include <linux/security.h> -#include <linux/pid_namespace.h> #include <linux/pid.h> #include <linux/nsproxy.h> #include <linux/slab.h> @@ -53,8 +52,7 @@ static __inline__ int scm_check_creds(struct ucred *creds) if (!uid_valid(uid) || !gid_valid(gid)) return -EINVAL; - if ((creds->pid == task_tgid_vnr(current) || - ns_capable(current->nsproxy->pid_ns->user_ns, CAP_SYS_ADMIN)) && + if ((creds->pid == task_tgid_vnr(current) || nsown_capable(CAP_SYS_ADMIN)) && ((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) || uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) && ((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) || diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 1a9dda5..fe1a598 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -60,7 +60,6 @@ #include <linux/scatterlist.h> #include <linux/errqueue.h> #include <linux/prefetch.h> -#include <linux/locallock.h> #include <net/protocol.h> #include <net/dst.h> @@ -348,7 +347,6 @@ struct netdev_alloc_cache { unsigned int pagecnt_bias; }; static DEFINE_PER_CPU(struct netdev_alloc_cache, netdev_alloc_cache); -static DEFINE_LOCAL_IRQ_LOCK(netdev_alloc_lock); #define NETDEV_FRAG_PAGE_MAX_ORDER get_order(32768) #define NETDEV_FRAG_PAGE_MAX_SIZE (PAGE_SIZE << NETDEV_FRAG_PAGE_MAX_ORDER) @@ -361,7 +359,7 @@ static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask) int order; unsigned long flags; - local_lock_irqsave(netdev_alloc_lock, flags); + local_irq_save(flags); nc = &__get_cpu_var(netdev_alloc_cache); if (unlikely(!nc->frag.page)) { refill: @@ -395,7 +393,7 @@ recycle: nc->frag.offset += fragsz; nc->pagecnt_bias--; end: - local_unlock_irqrestore(netdev_alloc_lock, flags); + local_irq_restore(flags); return data; } diff --git a/net/core/sock.c b/net/core/sock.c index 2754c99..bc131d4 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -571,6 +571,7 @@ static int sock_getbindtodevice(struct sock *sk, char __user *optval, struct net *net = sock_net(sk); struct net_device *dev; char devname[IFNAMSIZ]; + unsigned seq; if (sk->sk_bound_dev_if == 0) { len = 0; @@ -581,19 +582,20 @@ static int sock_getbindtodevice(struct sock *sk, char __user *optval, if (len < IFNAMSIZ) goto out; - mutex_lock(&devnet_rename_mutex); +retry: + seq = read_seqcount_begin(&devnet_rename_seq); rcu_read_lock(); dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if); ret = -ENODEV; if (!dev) { rcu_read_unlock(); - mutex_unlock(&devnet_rename_mutex); goto out; } strcpy(devname, dev->name); rcu_read_unlock(); - mutex_unlock(&devnet_rename_mutex); + if (read_seqcount_retry(&devnet_rename_seq, seq)) + goto retry; len = strlen(devname) + 1; @@ -2285,11 +2287,12 @@ void lock_sock_nested(struct sock *sk, int subclass) if (sk->sk_lock.owned) __lock_sock(sk); sk->sk_lock.owned = 1; - spin_unlock_bh(&sk->sk_lock.slock); + spin_unlock(&sk->sk_lock.slock); /* * The sk_lock has mutex_lock() semantics here: */ mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_); + local_bh_enable(); } EXPORT_SYMBOL(lock_sock_nested); diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index 750f44f..602cd63 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c @@ -121,9 +121,6 @@ static int __sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (nlmsg_len(nlh) < sizeof(*req)) return -EINVAL; - if (req->sdiag_family >= AF_MAX) - return -EINVAL; - hndl = sock_diag_lock_handler(req->sdiag_family); if (hndl == NULL) err = -ENOENT; diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 21291f1..1b588e2 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -284,7 +284,6 @@ static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlmsghdr *nlh, if (!netdev->dcbnl_ops->getpermhwaddr) return -EOPNOTSUPP; - memset(perm_addr, 0, sizeof(perm_addr)); netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr); return nla_put(skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), perm_addr); @@ -1043,7 +1042,6 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) if (ops->ieee_getets) { struct ieee_ets ets; - memset(&ets, 0, sizeof(ets)); err = ops->ieee_getets(netdev, &ets); if (!err && nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets)) @@ -1052,7 +1050,6 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) if (ops->ieee_getmaxrate) { struct ieee_maxrate maxrate; - memset(&maxrate, 0, sizeof(maxrate)); err = ops->ieee_getmaxrate(netdev, &maxrate); if (!err) { err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE, @@ -1064,7 +1061,6 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) if (ops->ieee_getpfc) { struct ieee_pfc pfc; - memset(&pfc, 0, sizeof(pfc)); err = ops->ieee_getpfc(netdev, &pfc); if (!err && nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc)) @@ -1098,7 +1094,6 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) /* get peer info if available */ if (ops->ieee_peer_getets) { struct ieee_ets ets; - memset(&ets, 0, sizeof(ets)); err = ops->ieee_peer_getets(netdev, &ets); if (!err && nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets)) @@ -1107,7 +1102,6 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) if (ops->ieee_peer_getpfc) { struct ieee_pfc pfc; - memset(&pfc, 0, sizeof(pfc)); err = ops->ieee_peer_getpfc(netdev, &pfc); if (!err && nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc)) @@ -1286,7 +1280,6 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev) /* peer info if available */ if (ops->cee_peer_getpg) { struct cee_pg pg; - memset(&pg, 0, sizeof(pg)); err = ops->cee_peer_getpg(netdev, &pg); if (!err && nla_put(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg)) @@ -1295,7 +1288,6 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev) if (ops->cee_peer_getpfc) { struct cee_pfc pfc; - memset(&pfc, 0, sizeof(pfc)); err = ops->cee_peer_getpfc(netdev, &pfc); if (!err && nla_put(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc)) diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c index 76c3d0a..f651da6 100644 --- a/net/ieee802154/6lowpan.c +++ b/net/ieee802154/6lowpan.c @@ -1234,7 +1234,7 @@ static inline int __init lowpan_netlink_init(void) return rtnl_link_register(&lowpan_link_ops); } -static inline void lowpan_netlink_fini(void) +static inline void __init lowpan_netlink_fini(void) { rtnl_link_unregister(&lowpan_link_ops); } diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h index bba5f83..8c2251f 100644 --- a/net/ieee802154/6lowpan.h +++ b/net/ieee802154/6lowpan.h @@ -84,7 +84,7 @@ (memcmp(addr1, addr2, length >> 3) == 0) /* local link, i.e. FE80::/10 */ -#define is_addr_link_local(a) (((a)->s6_addr16[0]) == htons(0xFE80)) +#define is_addr_link_local(a) (((a)->s6_addr16[0]) == 0x80FE) /* * check whether we can compress the IID to 16 bits, diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index fcf104e..24b384b 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -248,12 +248,8 @@ EXPORT_SYMBOL(inet_listen); u32 inet_ehash_secret __read_mostly; EXPORT_SYMBOL(inet_ehash_secret); -u32 ipv6_hash_secret __read_mostly; -EXPORT_SYMBOL(ipv6_hash_secret); - /* - * inet_ehash_secret must be set exactly once, and to a non nul value - * ipv6_hash_secret must be set exactly once. + * inet_ehash_secret must be set exactly once */ void build_ehash_secret(void) { @@ -263,8 +259,7 @@ void build_ehash_secret(void) get_random_bytes(&rnd, sizeof(rnd)); } while (rnd == 0); - if (cmpxchg(&inet_ehash_secret, 0, rnd) == 0) - get_random_bytes(&ipv6_hash_secret, sizeof(ipv6_hash_secret)); + cmpxchg(&inet_ehash_secret, 0, rnd); } EXPORT_SYMBOL(build_ehash_secret); @@ -1595,7 +1590,7 @@ static const struct net_offload udp_offload = { static const struct net_protocol icmp_protocol = { .handler = icmp_rcv, - .err_handler = icmp_err, + .err_handler = ping_err, .no_policy = 1, .netns_ok = 1, }; diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 4cfe34d..3b4f0cd 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -139,6 +139,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) /* skb is pure payload to encrypt */ + err = -ENOMEM; + esp = x->data; aead = esp->aead; alen = crypto_aead_authsize(aead); @@ -174,10 +176,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) } tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen); - if (!tmp) { - err = -ENOMEM; + if (!tmp) goto error; - } seqhi = esp_tmp_seqhi(tmp); iv = esp_tmp_iv(aead, tmp, seqhilen); diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index d8bbe94..17ff9fd 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -69,7 +69,6 @@ #include <linux/jiffies.h> #include <linux/kernel.h> #include <linux/fcntl.h> -#include <linux/sysrq.h> #include <linux/socket.h> #include <linux/in.h> #include <linux/inet.h> @@ -769,30 +768,6 @@ static void icmp_redirect(struct sk_buff *skb) } /* - * 32bit and 64bit have different timestamp length, so we check for - * the cookie at offset 20 and verify it is repeated at offset 50 - */ -#define CO_POS0 20 -#define CO_POS1 50 -#define CO_SIZE sizeof(int) -#define ICMP_SYSRQ_SIZE 57 - -/* - * We got a ICMP_SYSRQ_SIZE sized ping request. Check for the cookie - * pattern and if it matches send the next byte as a trigger to sysrq. - */ -static void icmp_check_sysrq(struct net *net, struct sk_buff *skb) -{ - int cookie = htonl(net->ipv4.sysctl_icmp_echo_sysrq); - char *p = skb->data; - - if (!memcmp(&cookie, p + CO_POS0, CO_SIZE) && - !memcmp(&cookie, p + CO_POS1, CO_SIZE) && - p[CO_POS0 + CO_SIZE] == p[CO_POS1 + CO_SIZE]) - handle_sysrq(p[CO_POS0 + CO_SIZE]); -} - -/* * Handle ICMP_ECHO ("ping") requests. * * RFC 1122: 3.2.2.6 MUST have an echo server that answers ICMP echo @@ -819,11 +794,6 @@ static void icmp_echo(struct sk_buff *skb) icmp_param.data_len = skb->len; icmp_param.head_len = sizeof(struct icmphdr); icmp_reply(&icmp_param, skb); - - if (skb->len == ICMP_SYSRQ_SIZE && - net->ipv4.sysctl_icmp_echo_sysrq) { - icmp_check_sysrq(net, skb); - } } } @@ -964,29 +934,6 @@ error: goto drop; } -void icmp_err(struct sk_buff *skb, u32 info) -{ - struct iphdr *iph = (struct iphdr *)skb->data; - struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2)); - int type = icmp_hdr(skb)->type; - int code = icmp_hdr(skb)->code; - struct net *net = dev_net(skb->dev); - - /* - * Use ping_err to handle all icmp errors except those - * triggered by ICMP_ECHOREPLY which sent from kernel. - */ - if (icmph->type != ICMP_ECHOREPLY) { - ping_err(skb, info); - return; - } - - if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) - ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ICMP, 0); - else if (type == ICMP_REDIRECT) - ipv4_redirect(skb, net, 0, 0, IPPROTO_ICMP, 0); -} - /* * This table is the definition of how we handle ICMP. */ diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 03f5af7..4750d2b 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -21,7 +21,6 @@ #include <linux/rtnetlink.h> #include <linux/slab.h> -#include <net/sock.h> #include <net/inet_frag.h> static void inet_frag_secret_rebuild(unsigned long dummy) @@ -277,7 +276,6 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, { struct inet_frag_queue *q; struct hlist_node *n; - int depth = 0; hlist_for_each_entry(q, n, &f->hash[hash], list) { if (q->net == nf && f->match(q, key)) { @@ -285,25 +283,9 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, read_unlock(&f->lock); return q; } - depth++; } read_unlock(&f->lock); - if (depth <= INETFRAGS_MAXDEPTH) - return inet_frag_create(nf, f, key); - else - return ERR_PTR(-ENOBUFS); + return inet_frag_create(nf, f, key); } EXPORT_SYMBOL(inet_frag_find); - -void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q, - const char *prefix) -{ - static const char msg[] = "inet_frag_find: Fragment hash bucket" - " list length grew over limit " __stringify(INETFRAGS_MAXDEPTH) - ". Dropping fragment.\n"; - - if (PTR_ERR(q) == -ENOBUFS) - LIMIT_NETDEBUG(KERN_WARNING "%s%s", prefix, msg); -} -EXPORT_SYMBOL(inet_frag_maybe_warn_overflow); diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 0fcfee3..eb9d63a 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -255,7 +255,8 @@ static void ip_expire(unsigned long arg) if (!head->dev) goto out_rcu_unlock; - /* skb has no dst, perform route lookup again */ + /* skb dst is stale, drop it, and perform route lookup again */ + skb_dst_drop(head); iph = ip_hdr(head); err = ip_route_input_noref(head, iph->daddr, iph->saddr, iph->tos, head->dev); @@ -298,11 +299,14 @@ static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user) hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash); - if (IS_ERR_OR_NULL(q)) { - inet_frag_maybe_warn_overflow(q, pr_fmt()); - return NULL; - } + if (q == NULL) + goto out_nomem; + return container_of(q, struct ipq, q); + +out_nomem: + LIMIT_NETDEBUG(KERN_ERR pr_fmt("ip_frag_create: no memory left !\n")); + return NULL; } /* Is the fragment too far ahead to be part of ipq? */ @@ -524,16 +528,8 @@ found: qp->q.max_size = skb->len + ihl; if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && - qp->q.meat == qp->q.len) { - unsigned long orefdst = skb->_skb_refdst; - - skb->_skb_refdst = 0UL; - err = ip_frag_reasm(qp, prev, dev); - skb->_skb_refdst = orefdst; - return err; - } - - skb_dst_drop(skb); + qp->q.meat == qp->q.len) + return ip_frag_reasm(qp, prev, dev); write_lock(&ip4_frags.lock); list_move_tail(&qp->q.lru_list, &qp->q.net->lru_list); diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index a85062b..e81b1ca 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -761,7 +761,10 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev if (dev->header_ops && dev->type == ARPHRD_IPGRE) { gre_hlen = 0; - tiph = (const struct iphdr *)skb->data; + if (skb->protocol == htons(ETH_P_IP)) + tiph = (const struct iphdr *)skb->data; + else + tiph = &tunnel->parms.iph; } else { gre_hlen = tunnel->hlen; tiph = &tunnel->parms.iph; diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 8433ffe..a47fc1d 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -370,6 +370,7 @@ int ip_options_compile(struct net *net, } switch (optptr[3]&0xF) { case IPOPT_TS_TSONLY: + opt->ts = optptr - iph; if (skb) timeptr = &optptr[optptr[2]-1]; opt->ts_needtime = 1; @@ -380,6 +381,7 @@ int ip_options_compile(struct net *net, pp_ptr = optptr + 2; goto error; } + opt->ts = optptr - iph; if (rt) { spec_dst_fill(&spec_dst, skb); memcpy(&optptr[optptr[2]-1], &spec_dst, 4); @@ -394,6 +396,7 @@ int ip_options_compile(struct net *net, pp_ptr = optptr + 2; goto error; } + opt->ts = optptr - iph; { __be32 addr; memcpy(&addr, &optptr[optptr[2]-1], 4); @@ -426,12 +429,12 @@ int ip_options_compile(struct net *net, pp_ptr = optptr + 3; goto error; } + opt->ts = optptr - iph; if (skb) { optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4); opt->is_changed = 1; } } - opt->ts = optptr - iph; break; case IPOPT_RA: if (optlen < 4) { diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 253692b..3e98ed2 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1508,8 +1508,7 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, if (IS_ERR(rt)) return; - get_cpu_light(); - inet = &__get_cpu_var(unicast_sock); + inet = &get_cpu_var(unicast_sock); inet->tos = arg->tos; sk = &inet->sk; @@ -1533,7 +1532,7 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, ip_push_pending_frames(sk, &fl4); } - put_cpu_light(); + put_cpu_var(unicast_sock); ip_rt_put(rt); } diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c index c49dcd0..c301300 100644 --- a/net/ipv4/netfilter/ipt_rpfilter.c +++ b/net/ipv4/netfilter/ipt_rpfilter.c @@ -66,12 +66,6 @@ static bool rpfilter_lookup_reverse(struct flowi4 *fl4, return dev_match; } -static bool rpfilter_is_local(const struct sk_buff *skb) -{ - const struct rtable *rt = skb_rtable(skb); - return rt && (rt->rt_flags & RTCF_LOCAL); -} - static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) { const struct xt_rpfilter_info *info; @@ -82,7 +76,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) info = par->matchinfo; invert = info->flags & XT_RPFILTER_INVERT; - if (rpfilter_is_local(skb)) + if (par->in->flags & IFF_LOOPBACK) return true ^ invert; iph = ip_hdr(skb); diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index dc454cc..6f9c072 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -322,8 +322,8 @@ void ping_err(struct sk_buff *skb, u32 info) struct iphdr *iph = (struct iphdr *)skb->data; struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2)); struct inet_sock *inet_sock; - int type = icmp_hdr(skb)->type; - int code = icmp_hdr(skb)->code; + int type = icmph->type; + int code = icmph->code; struct net *net = dev_net(skb->dev); struct sock *sk; int harderr; diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index f962f19..b236ef0 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -348,8 +348,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, * hasn't changed since we received the original syn, but I see * no easy way to do this. */ - flowi4_init_output(&fl4, sk->sk_bound_dev_if, sk->sk_mark, - RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP, + flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk), + RT_SCOPE_UNIVERSE, IPPROTO_TCP, inet_sk_flowi_flags(sk), (opt && opt->srr) ? opt->faddr : ireq->rmt_addr, ireq->loc_addr, th->source, th->dest); diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 44bf3b0..d84400b 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -815,13 +815,6 @@ static struct ctl_table ipv4_net_table[] = { .proc_handler = proc_dointvec }, { - .procname = "icmp_echo_sysrq", - .data = &init_net.ipv4.sysctl_icmp_echo_sysrq, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, - { .procname = "icmp_ignore_bogus_error_responses", .data = &init_net.ipv4.sysctl_icmp_ignore_bogus_error_responses, .maxlen = sizeof(int), diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 45b63ca..2aa69c8 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -773,7 +773,7 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp) * Make sure that we have exactly size bytes * available to the caller, no more, no less. */ - skb->reserved_tailroom = skb->end - skb->tail - size; + skb->avail_size = size; return skb; } __kfree_skb(skb); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index b4e8b79..ad70a96 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -116,7 +116,6 @@ int sysctl_tcp_early_retrans __read_mostly = 2; #define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained D-SACK info */ #define FLAG_NONHEAD_RETRANS_ACKED 0x1000 /* Non-head rexmitted data was ACKed */ #define FLAG_SACK_RENEGING 0x2000 /* snd_una advanced to a sacked seq */ -#define FLAG_UPDATE_TS_RECENT 0x4000 /* tcp_replace_ts_recent() */ #define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED) #define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED) @@ -2065,8 +2064,11 @@ void tcp_enter_loss(struct sock *sk, int how) if (tcp_is_reno(tp)) tcp_reset_reno_sack(tp); - tp->undo_marker = tp->snd_una; - if (how) { + if (!how) { + /* Push undo marker, if it was plain RTO and nothing + * was retransmitted. */ + tp->undo_marker = tp->snd_una; + } else { tp->sacked_out = 0; tp->fackets_out = 0; } @@ -3573,27 +3575,6 @@ static void tcp_send_challenge_ack(struct sock *sk) } } -static void tcp_store_ts_recent(struct tcp_sock *tp) -{ - tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval; - tp->rx_opt.ts_recent_stamp = get_seconds(); -} - -static void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq) -{ - if (tp->rx_opt.saw_tstamp && !after(seq, tp->rcv_wup)) { - /* PAWS bug workaround wrt. ACK frames, the PAWS discard - * extra check below makes sure this can only happen - * for pure ACK frames. -DaveM - * - * Not only, also it occurs for expired timestamps. - */ - - if (tcp_paws_check(&tp->rx_opt, 0)) - tcp_store_ts_recent(tp); - } -} - /* This routine deals with incoming acks, but not outgoing ones. */ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) { @@ -3646,12 +3627,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) prior_fackets = tp->fackets_out; prior_in_flight = tcp_packets_in_flight(tp); - /* ts_recent update must be made after we are sure that the packet - * is in window. - */ - if (flag & FLAG_UPDATE_TS_RECENT) - tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); - if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) { /* Window is constant, pure forward advance. * No more checks are required. @@ -3968,6 +3943,27 @@ const u8 *tcp_parse_md5sig_option(const struct tcphdr *th) EXPORT_SYMBOL(tcp_parse_md5sig_option); #endif +static inline void tcp_store_ts_recent(struct tcp_sock *tp) +{ + tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval; + tp->rx_opt.ts_recent_stamp = get_seconds(); +} + +static inline void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq) +{ + if (tp->rx_opt.saw_tstamp && !after(seq, tp->rcv_wup)) { + /* PAWS bug workaround wrt. ACK frames, the PAWS discard + * extra check below makes sure this can only happen + * for pure ACK frames. -DaveM + * + * Not only, also it occurs for expired timestamps. + */ + + if (tcp_paws_check(&tp->rx_opt, 0)) + tcp_store_ts_recent(tp); + } +} + /* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM * * It is not fatal. If this ACK does _not_ change critical state (seqs, window) @@ -5502,9 +5498,6 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, if (tcp_checksum_complete_user(sk, skb)) goto csum_error; - if ((int)skb->truesize > sk->sk_forward_alloc) - goto step5; - /* Predicted packet is in window by definition. * seq == rcv_nxt and rcv_wup <= rcv_nxt. * Hence, check seq<=rcv_wup reduces to: @@ -5516,6 +5509,9 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, tcp_rcv_rtt_measure_ts(sk, skb); + if ((int)skb->truesize > sk->sk_forward_alloc) + goto step5; + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITS); /* Bulk data transfer: receiver */ @@ -5563,9 +5559,14 @@ slow_path: return 0; step5: - if (tcp_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT) < 0) + if (tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) goto discard; + /* ts_recent update must be made after we are sure that the packet + * is in window. + */ + tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); + tcp_rcv_rtt_measure_ts(sk, skb); /* Process urgent data. */ @@ -5999,8 +6000,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, /* step 5: check the ACK field */ if (true) { - int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH | - FLAG_UPDATE_TS_RECENT) > 0; + int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH) > 0; switch (sk->sk_state) { case TCP_SYN_RECV: @@ -6151,6 +6151,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, } } + /* ts_recent update must be made after we are sure that the packet + * is in window. + */ + tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); + /* step 6: check the URG bit */ tcp_urg(sk, skb, th); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index d9130a9..eadb693 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -274,6 +274,13 @@ static void tcp_v4_mtu_reduced(struct sock *sk) struct inet_sock *inet = inet_sk(sk); u32 mtu = tcp_sk(sk)->mtu_info; + /* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs + * send out by Linux are always <576bytes so they should go through + * unfragmented). + */ + if (sk->sk_state == TCP_LISTEN) + return; + dst = inet_csk_update_pmtu(sk, mtu); if (!dst) return; @@ -401,13 +408,6 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) goto out; if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ - /* We are not interested in TCP_LISTEN and open_requests - * (SYN-ACKs send out by Linux are always <576bytes so - * they should go through unfragmented). - */ - if (sk->sk_state == TCP_LISTEN) - goto out; - tp->mtu_info = info; if (!sock_owned_by_user(sk)) { tcp_v4_mtu_reduced(sk); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index a9f50ee..5d45159 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1298,6 +1298,7 @@ static void __pskb_trim_head(struct sk_buff *skb, int len) eat = min_t(int, len, skb_headlen(skb)); if (eat) { __skb_pull(skb, eat); + skb->avail_size -= eat; len -= eat; if (!len) return; @@ -1350,8 +1351,8 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) return 0; } -/* Calculate MSS not accounting any TCP options. */ -static inline int __tcp_mtu_to_mss(struct sock *sk, int pmtu) +/* Calculate MSS. Not accounting for SACKs here. */ +int tcp_mtu_to_mss(struct sock *sk, int pmtu) { const struct tcp_sock *tp = tcp_sk(sk); const struct inet_connection_sock *icsk = inet_csk(sk); @@ -1380,15 +1381,11 @@ static inline int __tcp_mtu_to_mss(struct sock *sk, int pmtu) /* Then reserve room for full set of TCP options and 8 bytes of data */ if (mss_now < 48) mss_now = 48; - return mss_now; -} -/* Calculate MSS. Not accounting for SACKs here. */ -int tcp_mtu_to_mss(struct sock *sk, int pmtu) -{ - /* Subtract TCP options size, not including SACKs */ - return __tcp_mtu_to_mss(sk, pmtu) - - (tcp_sk(sk)->tcp_header_len - sizeof(struct tcphdr)); + /* Now subtract TCP options size, not including SACKs */ + mss_now -= tp->tcp_header_len - sizeof(struct tcphdr); + + return mss_now; } /* Inverse of above */ @@ -1809,11 +1806,8 @@ static bool tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) goto send_now; } - /* Ok, it looks like it is advisable to defer. - * Do not rearm the timer if already set to not break TCP ACK clocking. - */ - if (!tp->tso_deferred) - tp->tso_deferred = 1 | (jiffies << 1); + /* Ok, it looks like it is advisable to defer. */ + tp->tso_deferred = 1 | (jiffies << 1); return true; @@ -2388,12 +2382,8 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) */ TCP_SKB_CB(skb)->when = tcp_time_stamp; - /* make sure skb->data is aligned on arches that require it - * and check if ack-trimming & collapsing extended the headroom - * beyond what csum_start can cover. - */ - if (unlikely((NET_IP_ALIGN && ((unsigned long)skb->data & 3)) || - skb_headroom(skb) >= 0xFFFF)) { + /* make sure skb->data is aligned on arches that require it */ + if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) { struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER, GFP_ATOMIC); return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : @@ -2940,7 +2930,7 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) */ if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < tp->rx_opt.mss_clamp) tp->rx_opt.mss_clamp = tp->rx_opt.user_mss; - space = __tcp_mtu_to_mss(sk, inet_csk(sk)->icsk_pmtu_cookie) - + space = tcp_mtu_to_mss(sk, inet_csk(sk)->icsk_pmtu_cookie) - MAX_TCP_OPTION_SPACE; syn_data = skb_copy_expand(syn, skb_headroom(syn), space, diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e8676c2..1b5d8cb 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2525,9 +2525,6 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) static void init_loopback(struct net_device *dev) { struct inet6_dev *idev; - struct net_device *sp_dev; - struct inet6_ifaddr *sp_ifa; - struct rt6_info *sp_rt; /* ::1 */ @@ -2539,30 +2536,6 @@ static void init_loopback(struct net_device *dev) } add_addr(idev, &in6addr_loopback, 128, IFA_HOST); - - /* Add routes to other interface's IPv6 addresses */ - for_each_netdev(dev_net(dev), sp_dev) { - if (!strcmp(sp_dev->name, dev->name)) - continue; - - idev = __in6_dev_get(sp_dev); - if (!idev) - continue; - - read_lock_bh(&idev->lock); - list_for_each_entry(sp_ifa, &idev->addr_list, if_list) { - - if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE)) - continue; - - sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0); - - /* Failure cases are ignored */ - if (!IS_ERR(sp_rt)) - ip6_ins_rt(sp_rt); - } - read_unlock_bh(&idev->lock); - } } static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr) @@ -4814,20 +4787,26 @@ static void addrconf_sysctl_unregister(struct inet6_dev *idev) static int __net_init addrconf_init_net(struct net *net) { - int err = -ENOMEM; + int err; struct ipv6_devconf *all, *dflt; - all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL); - if (all == NULL) - goto err_alloc_all; + err = -ENOMEM; + all = &ipv6_devconf; + dflt = &ipv6_devconf_dflt; - dflt = kmemdup(&ipv6_devconf_dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); - if (dflt == NULL) - goto err_alloc_dflt; + if (!net_eq(net, &init_net)) { + all = kmemdup(all, sizeof(ipv6_devconf), GFP_KERNEL); + if (all == NULL) + goto err_alloc_all; - /* these will be inherited by all namespaces */ - dflt->autoconf = ipv6_defaults.autoconf; - dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; + dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); + if (dflt == NULL) + goto err_alloc_dflt; + } else { + /* these will be inherited by all namespaces */ + dflt->autoconf = ipv6_defaults.autoconf; + dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; + } net->ipv6.devconf_all = all; net->ipv6.devconf_dflt = dflt; diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index dee9964..a52d864 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -118,27 +118,6 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ipv6_addr_loopback(&hdr->daddr)) goto err; - /* RFC4291 Errata ID: 3480 - * Interface-Local scope spans only a single interface on a - * node and is useful only for loopback transmission of - * multicast. Packets with interface-local scope received - * from another node must be discarded. - */ - if (!(skb->pkt_type == PACKET_LOOPBACK || - dev->flags & IFF_LOOPBACK) && - ipv6_addr_is_multicast(&hdr->daddr) && - IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1) - goto err; - - /* RFC4291 2.7 - * Nodes must not originate a packet to a multicast address whose scope - * field contains the reserved value 0; if such a packet is received, it - * must be silently dropped. - */ - if (ipv6_addr_is_multicast(&hdr->daddr) && - IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0) - goto err; - /* * RFC4291 2.7 * Multicast addresses must not be used as source addresses in IPv6 @@ -291,8 +270,7 @@ int ip6_mc_input(struct sk_buff *skb) * IPv6 multicast router mode is now supported ;) */ if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding && - !(ipv6_addr_type(&hdr->daddr) & - (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)) && + !(ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL) && likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) { /* * Okay, we try to forward - split and duplicate diff --git a/net/ipv6/netfilter/ip6t_NPT.c b/net/ipv6/netfilter/ip6t_NPT.c index 0ea43c7..83acc14 100644 --- a/net/ipv6/netfilter/ip6t_NPT.c +++ b/net/ipv6/netfilter/ip6t_NPT.c @@ -57,7 +57,7 @@ static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt, if (pfx_len - i >= 32) mask = 0; else - mask = htonl((1 << (i - pfx_len + 32)) - 1); + mask = htonl(~((1 << (pfx_len - i)) - 1)); idx = i / 32; addr->s6_addr32[idx] &= mask; diff --git a/net/ipv6/netfilter/ip6t_rpfilter.c b/net/ipv6/netfilter/ip6t_rpfilter.c index e0983f3..5060d54 100644 --- a/net/ipv6/netfilter/ip6t_rpfilter.c +++ b/net/ipv6/netfilter/ip6t_rpfilter.c @@ -71,12 +71,6 @@ static bool rpfilter_lookup_reverse6(const struct sk_buff *skb, return ret; } -static bool rpfilter_is_local(const struct sk_buff *skb) -{ - const struct rt6_info *rt = (const void *) skb_dst(skb); - return rt && (rt->rt6i_flags & RTF_LOCAL); -} - static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) { const struct xt_rpfilter_info *info = par->matchinfo; @@ -84,7 +78,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) struct ipv6hdr *iph; bool invert = info->flags & XT_RPFILTER_INVERT; - if (rpfilter_is_local(skb)) + if (par->in->flags & IFF_LOOPBACK) return true ^ invert; iph = ipv6_hdr(skb); diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 2f3a018..3dacecc 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -14,8 +14,6 @@ * 2 of the License, or (at your option) any later version. */ -#define pr_fmt(fmt) "IPv6-nf: " fmt - #include <linux/errno.h> #include <linux/types.h> #include <linux/string.h> @@ -182,11 +180,13 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id, q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash); local_bh_enable(); - if (IS_ERR_OR_NULL(q)) { - inet_frag_maybe_warn_overflow(q, pr_fmt()); - return NULL; - } + if (q == NULL) + goto oom; + return container_of(q, struct frag_queue, q); + +oom: + return NULL; } diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 7a610a6..e5253ec 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -26,9 +26,6 @@ * YOSHIFUJI,H. @USAGI Always remove fragment header to * calculate ICV correctly. */ - -#define pr_fmt(fmt) "IPv6: " fmt - #include <linux/errno.h> #include <linux/types.h> #include <linux/string.h> @@ -200,10 +197,9 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src, const struct in6 hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd); q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); - if (IS_ERR_OR_NULL(q)) { - inet_frag_maybe_warn_overflow(q, pr_fmt()); + if (q == NULL) return NULL; - } + return container_of(q, struct frag_queue, q); } @@ -342,17 +338,8 @@ found: } if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && - fq->q.meat == fq->q.len) { - int res; - unsigned long orefdst = skb->_skb_refdst; - - skb->_skb_refdst = 0UL; - res = ip6_frag_reasm(fq, prev, dev); - skb->_skb_refdst = orefdst; - return res; - } - - skb_dst_drop(skb); + fq->q.meat == fq->q.len) + return ip6_frag_reasm(fq, prev, dev); write_lock(&ip6_frags.lock); list_move_tail(&fq->q.lru_list, &fq->q.net->lru_list); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 59bf61d..1003ef5 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -304,7 +304,6 @@ static void ip6_dst_destroy(struct dst_entry *dst) { struct rt6_info *rt = (struct rt6_info *)dst; struct inet6_dev *idev = rt->rt6i_idev; - struct dst_entry *from = dst->from; if (rt->n) neigh_release(rt->n); @@ -317,8 +316,8 @@ static void ip6_dst_destroy(struct dst_entry *dst) in6_dev_put(idev); } - dst->from = NULL; - dst_release(from); + if (!(rt->rt6i_flags & RTF_EXPIRES) && dst->from) + dst_release(dst->from); if (rt6_has_peer(rt)) { struct inet_peer *peer = rt6_peer_ptr(rt); @@ -1065,6 +1064,7 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori rt->rt6i_gateway = ort->rt6i_gateway; rt->rt6i_flags = ort->rt6i_flags; + rt6_clean_expires(rt); rt->rt6i_metric = 0; memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); @@ -1875,6 +1875,8 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort, if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == (RTF_DEFAULT | RTF_ADDRCONF)) rt6_set_from(rt, ort); + else + rt6_clean_expires(rt); rt->rt6i_metric = 0; #ifdef CONFIG_IPV6_SUBTREES @@ -2006,8 +2008,7 @@ void rt6_purge_dflt_routers(struct net *net) restart: read_lock_bh(&table->tb6_lock); for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) { - if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) && - (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) { + if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { dst_hold(&rt->dst); read_unlock_bh(&table->tb6_lock); ip6_del_rt(rt); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 89dfedd..4f435371 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -386,17 +386,9 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (dst) dst->ops->redirect(dst, sk, skb); - goto out; } if (type == ICMPV6_PKT_TOOBIG) { - /* We are not interested in TCP_LISTEN and open_requests - * (SYN-ACKs send out by Linux are always <576bytes so - * they should go through unfragmented). - */ - if (sk->sk_state == TCP_LISTEN) - goto out; - tp->mtu_info = ntohl(info); if (!sock_owned_by_user(sk)) tcp_v6_mtu_reduced(sk); diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 8f32718..c984413 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -236,8 +236,6 @@ static void xfrm6_dst_destroy(struct dst_entry *dst) { struct xfrm_dst *xdst = (struct xfrm_dst *)dst; - if (likely(xdst->u.rt6.n)) - neigh_release(xdst->u.rt6.n); if (likely(xdst->u.rt6.rt6i_idev)) in6_dev_put(xdst->u.rt6.rt6i_idev); dst_destroy_metrics_generic(dst); diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 3c9bd59..b833677 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -1386,8 +1386,6 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, IRDA_DEBUG(4, "%s()\n", __func__); - msg->msg_namelen = 0; - skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &err); if (!skb) @@ -2586,10 +2584,8 @@ bed: NULL, NULL, NULL); /* Check if the we got some results */ - if (!self->cachedaddr) { - err = -EAGAIN; /* Didn't find any devices */ - goto out; - } + if (!self->cachedaddr) + return -EAGAIN; /* Didn't find any devices */ daddr = self->cachedaddr; /* Cleanup */ self->cachedaddr = 0; diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 625bc50..cd6f7a9 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -1331,8 +1331,6 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb, *rskb, *cskb; int err = 0; - msg->msg_namelen = 0; - if ((sk->sk_state == IUCV_DISCONN) && skb_queue_empty(&iucv->backlog_skb_q) && skb_queue_empty(&sk->sk_receive_queue) && diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index 9e1822e..8ee4a86 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -684,7 +684,6 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk, lsa->l2tp_addr = ipv6_hdr(skb)->saddr; lsa->l2tp_flowinfo = 0; lsa->l2tp_scope_id = 0; - lsa->l2tp_conn_id = 0; if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL) lsa->l2tp_scope_id = IP6CB(skb)->iif; } diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 044e9e1..716605c 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -355,7 +355,6 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh l2tp_xmit_skb(session, skb, session->hdr_len); sock_put(ps->tunnel_sock); - sock_put(sk); return error; diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 48aaa89..8870988 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -720,8 +720,6 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, int target; /* Read at least this many bytes */ long timeo; - msg->msg_namelen = 0; - lock_sock(sk); copied = -ENOTCONN; if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN)) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 49c48c6..0479c64 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2499,7 +2499,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, list_del(&dep->list); mutex_unlock(&local->mtx); - ieee80211_roc_notify_destroy(dep, true); + ieee80211_roc_notify_destroy(dep); return 0; } @@ -2539,7 +2539,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, ieee80211_start_next_roc(local); mutex_unlock(&local->mtx); - ieee80211_roc_notify_destroy(found, true); + ieee80211_roc_notify_destroy(found); } else { /* work may be pending so use it all the time */ found->abort = true; @@ -2549,8 +2549,6 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, /* work will clean up etc */ flush_delayed_work(&found->work); - WARN_ON(!found->to_be_freed); - kfree(found); } return 0; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 55d8f89..2ed065c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -346,7 +346,6 @@ struct ieee80211_roc_work { struct ieee80211_channel *chan; bool started, abort, hw_begun, notified; - bool to_be_freed; unsigned long hw_start_time; @@ -1364,7 +1363,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local); void ieee80211_roc_setup(struct ieee80211_local *local); void ieee80211_start_next_roc(struct ieee80211_local *local); void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata); -void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free); +void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc); void ieee80211_sw_roc_work(struct work_struct *work); void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a1a7997..5107248 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1812,8 +1812,6 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, transmit_frame, frame_buf); ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; - ieee80211_wake_queues_by_reason(&sdata->local->hw, - IEEE80211_QUEUE_STOP_REASON_CSA); mutex_unlock(&ifmgd->mtx); /* @@ -1858,6 +1856,8 @@ static void ieee80211_csa_connection_drop_work(struct work_struct *work) container_of(work, struct ieee80211_sub_if_data, u.mgd.csa_connection_drop_work); + ieee80211_wake_queues_by_reason(&sdata->local->hw, + IEEE80211_QUEUE_STOP_REASON_CSA); __ieee80211_disconnect(sdata, true); } @@ -3401,10 +3401,6 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ret = 0; out: - /* don't print the message below for VHT mismatch if VHT is disabled */ - if (ret & IEEE80211_STA_DISABLE_VHT) - vht_chandef = *chandef; - while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, IEEE80211_CHAN_DISABLED)) { if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { @@ -3723,16 +3719,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, /* prep auth_data so we don't go into idle on disassoc */ ifmgd->auth_data = auth_data; - if (ifmgd->associated) { - u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; - - ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, - WLAN_REASON_UNSPECIFIED, - false, frame_buf); - - __cfg80211_send_deauth(sdata->dev, frame_buf, - sizeof(frame_buf)); - } + if (ifmgd->associated) + ieee80211_set_disassoc(sdata, 0, 0, false, NULL); sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); @@ -3791,16 +3779,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, mutex_lock(&ifmgd->mtx); - if (ifmgd->associated) { - u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; - - ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, - WLAN_REASON_UNSPECIFIED, - false, frame_buf); - - __cfg80211_send_deauth(sdata->dev, frame_buf, - sizeof(frame_buf)); - } + if (ifmgd->associated) + ieee80211_set_disassoc(sdata, 0, 0, false, NULL); if (ifmgd->auth_data && !ifmgd->auth_data->done) { err = -EBUSY; @@ -4092,17 +4072,6 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - /* - * Make sure some work items will not run after this, - * they will not do anything but might not have been - * cancelled when disconnecting. - */ - cancel_work_sync(&ifmgd->monitor_work); - cancel_work_sync(&ifmgd->beacon_connection_loss_work); - cancel_work_sync(&ifmgd->request_smps_work); - cancel_work_sync(&ifmgd->csa_connection_drop_work); - cancel_work_sync(&ifmgd->chswitch_work); - mutex_lock(&ifmgd->mtx); if (ifmgd->assoc_data) ieee80211_destroy_assoc_data(sdata, false); diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 7acbdaa..a3ad4c3 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -299,13 +299,10 @@ void ieee80211_start_next_roc(struct ieee80211_local *local) } } -void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free) +void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) { struct ieee80211_roc_work *dep, *tmp; - if (WARN_ON(roc->to_be_freed)) - return; - /* was never transmitted */ if (roc->frame) { cfg80211_mgmt_tx_status(&roc->sdata->wdev, @@ -321,12 +318,9 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free) GFP_KERNEL); list_for_each_entry_safe(dep, tmp, &roc->dependents, list) - ieee80211_roc_notify_destroy(dep, true); + ieee80211_roc_notify_destroy(dep); - if (free) - kfree(roc); - else - roc->to_be_freed = true; + kfree(roc); } void ieee80211_sw_roc_work(struct work_struct *work) @@ -339,9 +333,6 @@ void ieee80211_sw_roc_work(struct work_struct *work) mutex_lock(&local->mtx); - if (roc->to_be_freed) - goto out_unlock; - if (roc->abort) goto finish; @@ -381,7 +372,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) finish: list_del(&roc->list); started = roc->started; - ieee80211_roc_notify_destroy(roc, !roc->abort); + ieee80211_roc_notify_destroy(roc); if (started) { drv_flush(local, false); @@ -421,7 +412,7 @@ static void ieee80211_hw_roc_done(struct work_struct *work) list_del(&roc->list); - ieee80211_roc_notify_destroy(roc, true); + ieee80211_roc_notify_destroy(roc); /* if there's another roc, start it now */ ieee80211_start_next_roc(local); @@ -471,14 +462,12 @@ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata) list_for_each_entry_safe(roc, tmp, &tmp_list, list) { if (local->ops->remain_on_channel) { list_del(&roc->list); - ieee80211_roc_notify_destroy(roc, true); + ieee80211_roc_notify_destroy(roc); } else { ieee80211_queue_delayed_work(&local->hw, &roc->work, 0); /* work will clean up etc */ flush_delayed_work(&roc->work); - WARN_ON(!roc->to_be_freed); - kfree(roc); } } diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 64619f4..79a48f3 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -52,8 +52,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) ieee80211_stop_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_SUSPEND); - /* flush out all packets and station cleanup call_rcu()s */ - rcu_barrier(); + /* flush out all packets */ + synchronize_net(); drv_flush(local, false); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c58f3cd..580704e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3144,7 +3144,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) struct ieee80211_supported_band *sband; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); - WARN_ON_ONCE_NONRT(softirq_count() == 0); + WARN_ON_ONCE(softirq_count() == 0); if (WARN_ON(status->band >= IEEE80211_NUM_BANDS)) goto drop; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index c8b32a0..ca9fde1 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -756,7 +756,6 @@ int __must_check __sta_info_destroy(struct sta_info *sta) struct ieee80211_local *local; struct ieee80211_sub_if_data *sdata; int ret, i; - bool have_key = false; might_sleep(); @@ -784,19 +783,12 @@ int __must_check __sta_info_destroy(struct sta_info *sta) list_del_rcu(&sta->list); mutex_lock(&local->key_mtx); - for (i = 0; i < NUM_DEFAULT_KEYS; i++) { + for (i = 0; i < NUM_DEFAULT_KEYS; i++) __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i])); - have_key = true; - } - if (sta->ptk) { + if (sta->ptk) __ieee80211_key_free(key_mtx_dereference(local, sta->ptk)); - have_key = true; - } mutex_unlock(&local->key_mtx); - if (!have_key) - synchronize_net(); - sta->dead = true; local->num_sta--; diff --git a/net/netfilter/core.c b/net/netfilter/core.c index c646ec8..a9c488b 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -20,17 +20,11 @@ #include <linux/proc_fs.h> #include <linux/mutex.h> #include <linux/slab.h> -#include <linux/locallock.h> #include <net/net_namespace.h> #include <net/sock.h> #include "nf_internals.h" -#ifdef CONFIG_PREEMPT_RT_BASE -DEFINE_LOCAL_IRQ_LOCK(xt_write_lock); -EXPORT_PER_CPU_SYMBOL(xt_write_lock); -#endif - static DEFINE_MUTEX(afinfo_mutex); const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly; diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index 38ca630..6d6d8f2 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -1470,8 +1470,7 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb, if (ret == -EAGAIN) ret = 1; - return (ret < 0 && ret != -ENOTEMPTY) ? ret : - ret > 0 ? 0 : -IPSET_ERR_EXIST; + return ret < 0 ? ret : ret > 0 ? 0 : -IPSET_ERR_EXIST; } /* Get headed data of a set */ diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c index 09c744a..8371c2b 100644 --- a/net/netfilter/ipset/ip_set_list_set.c +++ b/net/netfilter/ipset/ip_set_list_set.c @@ -174,13 +174,9 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id, { const struct set_elem *e = list_set_elem(map, i); - if (e->id != IPSET_INVALID_ID) { - const struct set_elem *x = list_set_elem(map, map->size - 1); - - /* Last element replaced or pushed off */ - if (x->id != IPSET_INVALID_ID) - ip_set_put_byindex(x->id); - } + if (i == map->size - 1 && e->id != IPSET_INVALID_ID) + /* Last element replaced: e.g. add new,before,last */ + ip_set_put_byindex(e->id); if (with_timeout(map->timeout)) list_elem_tadd(map, i, id, ip_set_timeout_set(timeout)); else diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c index e5920fb..12475ef 100644 --- a/net/netfilter/ipvs/ip_vs_pe_sip.c +++ b/net/netfilter/ipvs/ip_vs_pe_sip.c @@ -37,10 +37,14 @@ static int get_callid(const char *dptr, unsigned int dataoff, if (ret > 0) break; if (!ret) - return -EINVAL; + return 0; dataoff += *matchoff; } + /* Empty callid is useless */ + if (!*matchlen) + return -EINVAL; + /* Too large is useless */ if (*matchlen > IP_VS_PEDATA_MAXLEN) return -EINVAL; diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 91527d5..884f2b3 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -236,9 +236,7 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, /* We only allow helper re-assignment of the same sort since * we cannot reallocate the helper extension area. */ - struct nf_conntrack_helper *tmp = rcu_dereference(help->helper); - - if (tmp && tmp->help != helper->help) { + if (help->helper != helper) { RCU_INIT_POINTER(help->helper, NULL); goto out; } diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index a081915..627b0e5 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1705,9 +1705,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, if (nlh->nlmsg_flags & NLM_F_CREATE) { enum ip_conntrack_events events; - if (!cda[CTA_TUPLE_ORIG] || !cda[CTA_TUPLE_REPLY]) - return -EINVAL; - ct = ctnetlink_create_conntrack(net, zone, cda, &otuple, &rtuple, u3); if (IS_ERR(ct)) diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index b4e0d1c..df8f4f2 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -1547,7 +1547,7 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, msglen = origlen = end - dptr; if (msglen > datalen) - return NF_ACCEPT; + return NF_DROP; ret = process_sip_msg(skb, ct, protoff, dataoff, &dptr, &msglen); diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 4bc2aaf..5f2f910 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -468,22 +468,33 @@ EXPORT_SYMBOL_GPL(nf_nat_packet); struct nf_nat_proto_clean { u8 l3proto; u8 l4proto; + bool hash; }; -/* kill conntracks with affected NAT section */ -static int nf_nat_proto_remove(struct nf_conn *i, void *data) +/* Clear NAT section of all conntracks, in case we're loaded again. */ +static int nf_nat_proto_clean(struct nf_conn *i, void *data) { const struct nf_nat_proto_clean *clean = data; struct nf_conn_nat *nat = nfct_nat(i); if (!nat) return 0; - + if (!(i->status & IPS_SRC_NAT_DONE)) + return 0; if ((clean->l3proto && nf_ct_l3num(i) != clean->l3proto) || (clean->l4proto && nf_ct_protonum(i) != clean->l4proto)) return 0; - return i->status & IPS_NAT_MASK ? 1 : 0; + if (clean->hash) { + spin_lock_bh(&nf_nat_lock); + hlist_del_rcu(&nat->bysource); + spin_unlock_bh(&nf_nat_lock); + } else { + memset(nat, 0, sizeof(*nat)); + i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | + IPS_SEQ_ADJUST); + } + return 0; } static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto) @@ -495,8 +506,16 @@ static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto) struct net *net; rtnl_lock(); + /* Step 1 - remove from bysource hash */ + clean.hash = true; for_each_net(net) - nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean); + nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean); + synchronize_rcu(); + + /* Step 2 - clean NAT section */ + clean.hash = false; + for_each_net(net) + nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean); rtnl_unlock(); } @@ -508,9 +527,16 @@ static void nf_nat_l3proto_clean(u8 l3proto) struct net *net; rtnl_lock(); + /* Step 1 - remove from bysource hash */ + clean.hash = true; + for_each_net(net) + nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean); + synchronize_rcu(); + /* Step 2 - clean NAT section */ + clean.hash = false; for_each_net(net) - nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean); + nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean); rtnl_unlock(); } @@ -748,7 +774,7 @@ static void __net_exit nf_nat_net_exit(struct net *net) { struct nf_nat_proto_clean clean = {}; - nf_ct_iterate_cleanup(net, &nf_nat_proto_remove, &clean); + nf_ct_iterate_cleanup(net, &nf_nat_proto_clean, &clean); synchronize_rcu(); nf_ct_free_hashtable(net->ct.nat_bysource, net->ct.nat_htable_size); } diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 8a6c6ea..847d495 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -1189,6 +1189,8 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, struct netlbl_unlhsh_walk_arg cb_arg; u32 skip_bkt = cb->args[0]; u32 skip_chain = cb->args[1]; + u32 skip_addr4 = cb->args[2]; + u32 skip_addr6 = cb->args[3]; u32 iter_bkt; u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0; struct netlbl_unlhsh_iface *iface; @@ -1213,7 +1215,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, continue; netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) { - if (iter_addr4++ < cb->args[2]) + if (iter_addr4++ < skip_addr4) continue; if (netlbl_unlabel_staticlist_gen( NLBL_UNLABEL_C_STATICLIST, @@ -1229,7 +1231,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, #if IS_ENABLED(CONFIG_IPV6) netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) { - if (iter_addr6++ < cb->args[3]) + if (iter_addr6++ < skip_addr6) continue; if (netlbl_unlabel_staticlist_gen( NLBL_UNLABEL_C_STATICLIST, @@ -1248,10 +1250,10 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, unlabel_staticlist_return: rcu_read_unlock(); - cb->args[0] = iter_bkt; - cb->args[1] = iter_chain; - cb->args[2] = iter_addr4; - cb->args[3] = iter_addr6; + cb->args[0] = skip_bkt; + cb->args[1] = skip_chain; + cb->args[2] = skip_addr4; + cb->args[3] = skip_addr6; return skb->len; } @@ -1271,9 +1273,12 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, { struct netlbl_unlhsh_walk_arg cb_arg; struct netlbl_unlhsh_iface *iface; - u32 iter_addr4 = 0, iter_addr6 = 0; + u32 skip_addr4 = cb->args[0]; + u32 skip_addr6 = cb->args[1]; + u32 iter_addr4 = 0; struct netlbl_af4list *addr4; #if IS_ENABLED(CONFIG_IPV6) + u32 iter_addr6 = 0; struct netlbl_af6list *addr6; #endif @@ -1287,7 +1292,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, goto unlabel_staticlistdef_return; netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) { - if (iter_addr4++ < cb->args[0]) + if (iter_addr4++ < skip_addr4) continue; if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, iface, @@ -1300,7 +1305,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, } #if IS_ENABLED(CONFIG_IPV6) netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) { - if (iter_addr6++ < cb->args[1]) + if (iter_addr6++ < skip_addr6) continue; if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, iface, @@ -1315,8 +1320,8 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, unlabel_staticlistdef_return: rcu_read_unlock(); - cb->args[0] = iter_addr4; - cb->args[1] = iter_addr6; + cb->args[0] = skip_addr4; + cb->args[1] = skip_addr6; return skb->len; } diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 5a55be3..f2aabb6 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -142,7 +142,6 @@ int genl_register_mc_group(struct genl_family *family, int err = 0; BUG_ON(grp->name[0] == '\0'); - BUG_ON(memchr(grp->name, '\0', GENL_NAMSIZ) == NULL); genl_lock(); diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 14c106b..7261eb8 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1177,7 +1177,6 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, } if (sax != NULL) { - memset(sax, 0, sizeof(sax)); sax->sax25_family = AF_NETROM; skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call, AX25_ADDR_LEN); diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 48fb1de..fea22eb 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c @@ -644,8 +644,6 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, pr_debug("%p %zu\n", sk, len); - msg->msg_namelen = 0; - lock_sock(sk); if (sk->sk_state == LLCP_CLOSED && @@ -686,7 +684,6 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap); - memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.sa_family = AF_NFC; sockaddr.nfc_protocol = NFC_PROTO_NFC_DEP; sockaddr.dsap = ui_cb->dsap; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 92a2359..c111bd0 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -88,7 +88,6 @@ #include <linux/virtio_net.h> #include <linux/errqueue.h> #include <linux/net_tstamp.h> -#include <linux/delay.h> #ifdef CONFIG_INET #include <net/inet_common.h> @@ -554,7 +553,7 @@ static void prb_retire_rx_blk_timer_expired(unsigned long data) if (BLOCK_NUM_PKTS(pbd)) { while (atomic_read(&pkc->blk_fill_in_prog)) { /* Waiting for skb_copy_bits to finish... */ - cpu_chill(); + cpu_relax(); } } @@ -808,7 +807,7 @@ static void prb_retire_current_block(struct tpacket_kbdq_core *pkc, if (!(status & TP_STATUS_BLK_TMO)) { while (atomic_read(&pkc->blk_fill_in_prog)) { /* Waiting for skb_copy_bits to finish... */ - cpu_chill(); + cpu_relax(); } } prb_close_block(pkc, pbd, po, status); diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c index 5a44c6e..e8fdb17 100644 --- a/net/rds/ib_rdma.c +++ b/net/rds/ib_rdma.c @@ -34,7 +34,6 @@ #include <linux/slab.h> #include <linux/rculist.h> #include <linux/llist.h> -#include <linux/delay.h> #include "rds.h" #include "ib.h" @@ -287,7 +286,7 @@ static inline void wait_clean_list_grace(void) for_each_online_cpu(cpu) { flag = &per_cpu(clean_list_grace, cpu); while (test_bit(CLEAN_LIST_BUSY_BIT, flag)) - cpu_chill(); + cpu_relax(); } } diff --git a/net/rds/message.c b/net/rds/message.c index aff589c..f0a4658 100644 --- a/net/rds/message.c +++ b/net/rds/message.c @@ -197,9 +197,6 @@ struct rds_message *rds_message_alloc(unsigned int extra_len, gfp_t gfp) { struct rds_message *rm; - if (extra_len > KMALLOC_MAX_SIZE - sizeof(struct rds_message)) - return NULL; - rm = kzalloc(sizeof(struct rds_message) + extra_len, gfp); if (!rm) goto out; diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 7f645d1..c4719ce 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1257,7 +1257,6 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); if (srose != NULL) { - memset(srose, 0, msg->msg_namelen); srose->srose_family = AF_ROSE; srose->srose_addr = rose->dest_addr; srose->srose_call = rose->dest_call; diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index ced81a1..0e19948 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -962,11 +962,8 @@ cbq_dequeue(struct Qdisc *sch) cbq_update(q); if ((incr -= incr2) < 0) incr = 0; - q->now += incr; - } else { - if (now > q->now) - q->now = now; } + q->now += incr; q->now_rt = now; for (;;) { diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 5578628..4e606fc 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -195,7 +195,7 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch) flow->deficit = q->quantum; flow->dropped = 0; } - if (++sch->q.qlen <= sch->limit) + if (++sch->q.qlen < sch->limit) return NET_XMIT_SUCCESS; q->drop_overlimit++; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 67c6823..b45ed1f 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1080,7 +1080,7 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc, transports) { if (transport == active) - continue; + break; list_for_each_entry(chunk, &transport->transmitted, transmitted_list) { if (key == chunk->subh.data_hdr->tsn) { diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index de1a013..5131fcf 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -2082,7 +2082,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(struct net *net, } /* Delete the tempory new association. */ - sctp_add_cmd_sf(commands, SCTP_CMD_SET_ASOC, SCTP_ASOC(new_asoc)); + sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); /* Restore association pointer to provide SCTP command interpeter diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9ef5c73..cedd9bf 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -5653,9 +5653,6 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len, if (len < sizeof(sctp_assoc_t)) return -EINVAL; - /* Allow the struct to grow and fill in as much as possible */ - len = min_t(size_t, len, sizeof(sas)); - if (copy_from_user(&sas, optval, len)) return -EFAULT; @@ -5689,6 +5686,9 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len, /* Mark beginning of a new observation period */ asoc->stats.max_obs_rto = asoc->rto_min; + /* Allow the struct to grow and fill in as much as possible */ + len = min_t(size_t, len, sizeof(sas)); + if (put_user(len, optlen)) return -EFAULT; diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 716aa41..507b5e8 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -511,7 +511,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, new = rpc_new_client(args, xprt); if (IS_ERR(new)) { err = PTR_ERR(new); - goto out_err; + goto out_put; } atomic_inc(&clnt->cl_count); @@ -524,6 +524,8 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, new->cl_chatty = clnt->cl_chatty; return new; +out_put: + xprt_put(xprt); out_err: dprintk("RPC: %s: returned error %d\n", __func__, err); return ERR_PTR(err); diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index f8529fc..fb20f25 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -180,8 +180,6 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue, list_add_tail(&task->u.tk_wait.list, &queue->tasks[0]); task->tk_waitqueue = queue; queue->qlen++; - /* barrier matches the read in rpc_wake_up_task_queue_locked() */ - smp_wmb(); rpc_set_queued(task); dprintk("RPC: %5u added to queue %p \"%s\"\n", @@ -432,11 +430,8 @@ static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task */ static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct rpc_task *task) { - if (RPC_IS_QUEUED(task)) { - smp_rmb(); - if (task->tk_waitqueue == queue) - __rpc_do_wake_up_task(queue, task); - } + if (RPC_IS_QUEUED(task) && task->tk_waitqueue == queue) + __rpc_do_wake_up_task(queue, task); } /* diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 2d34b6b..dbf12ac 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -515,6 +515,15 @@ EXPORT_SYMBOL_GPL(svc_create_pooled); void svc_shutdown_net(struct svc_serv *serv, struct net *net) { + /* + * The set of xprts (contained in the sv_tempsocks and + * sv_permsocks lists) is now constant, since it is modified + * only by accepting new sockets (done by service threads in + * svc_recv) or aging old ones (done by sv_temptimer), or + * configuration changes (excluded by whatever locking the + * caller is using--nfsd_mutex in the case of nfsd). So it's + * safe to traverse those lists and shut everything down: + */ svc_close_net(serv, net); if (serv->sv_shutdown) diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index ca71056..b8e47fa 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -856,6 +856,7 @@ static void svc_age_temp_xprts(unsigned long closure) struct svc_serv *serv = (struct svc_serv *)closure; struct svc_xprt *xprt; struct list_head *le, *next; + LIST_HEAD(to_be_aged); dprintk("svc_age_temp_xprts\n"); @@ -876,15 +877,25 @@ static void svc_age_temp_xprts(unsigned long closure) if (atomic_read(&xprt->xpt_ref.refcount) > 1 || test_bit(XPT_BUSY, &xprt->xpt_flags)) continue; - list_del_init(le); + svc_xprt_get(xprt); + list_move(le, &to_be_aged); set_bit(XPT_CLOSE, &xprt->xpt_flags); set_bit(XPT_DETACHED, &xprt->xpt_flags); + } + spin_unlock_bh(&serv->sv_lock); + + while (!list_empty(&to_be_aged)) { + le = to_be_aged.next; + /* fiddling the xpt_list node is safe 'cos we're XPT_DETACHED */ + list_del_init(le); + xprt = list_entry(le, struct svc_xprt, xpt_list); + dprintk("queuing xprt %p for closing\n", xprt); /* a thread will dequeue and close it soon */ svc_xprt_enqueue(xprt); + svc_xprt_put(xprt); } - spin_unlock_bh(&serv->sv_lock); mod_timer(&serv->sv_temptimer, jiffies + svc_conn_age_period * HZ); } @@ -948,24 +959,21 @@ void svc_close_xprt(struct svc_xprt *xprt) } EXPORT_SYMBOL_GPL(svc_close_xprt); -static int svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) +static void svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) { struct svc_xprt *xprt; - int ret = 0; spin_lock(&serv->sv_lock); list_for_each_entry(xprt, xprt_list, xpt_list) { if (xprt->xpt_net != net) continue; - ret++; set_bit(XPT_CLOSE, &xprt->xpt_flags); - svc_xprt_enqueue(xprt); + set_bit(XPT_BUSY, &xprt->xpt_flags); } spin_unlock(&serv->sv_lock); - return ret; } -static struct svc_xprt *svc_dequeue_net(struct svc_serv *serv, struct net *net) +static void svc_clear_pools(struct svc_serv *serv, struct net *net) { struct svc_pool *pool; struct svc_xprt *xprt; @@ -980,46 +988,42 @@ static struct svc_xprt *svc_dequeue_net(struct svc_serv *serv, struct net *net) if (xprt->xpt_net != net) continue; list_del_init(&xprt->xpt_ready); - spin_unlock_bh(&pool->sp_lock); - return xprt; } spin_unlock_bh(&pool->sp_lock); } - return NULL; } -static void svc_clean_up_xprts(struct svc_serv *serv, struct net *net) +static void svc_clear_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) { struct svc_xprt *xprt; + struct svc_xprt *tmp; + LIST_HEAD(victims); - while ((xprt = svc_dequeue_net(serv, net))) { - set_bit(XPT_CLOSE, &xprt->xpt_flags); - svc_delete_xprt(xprt); + spin_lock(&serv->sv_lock); + list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { + if (xprt->xpt_net != net) + continue; + list_move(&xprt->xpt_list, &victims); } + spin_unlock(&serv->sv_lock); + + list_for_each_entry_safe(xprt, tmp, &victims, xpt_list) + svc_delete_xprt(xprt); } -/* - * Server threads may still be running (especially in the case where the - * service is still running in other network namespaces). - * - * So we shut down sockets the same way we would on a running server, by - * setting XPT_CLOSE, enqueuing, and letting a thread pick it up to do - * the close. In the case there are no such other threads, - * threads running, svc_clean_up_xprts() does a simple version of a - * server's main event loop, and in the case where there are other - * threads, we may need to wait a little while and then check again to - * see if they're done. - */ void svc_close_net(struct svc_serv *serv, struct net *net) { - int delay = 0; - - while (svc_close_list(serv, &serv->sv_permsocks, net) + - svc_close_list(serv, &serv->sv_tempsocks, net)) { + svc_close_list(serv, &serv->sv_tempsocks, net); + svc_close_list(serv, &serv->sv_permsocks, net); - svc_clean_up_xprts(serv, net); - msleep(delay++); - } + svc_clear_pools(serv, net); + /* + * At this point the sp_sockets lists will stay empty, since + * svc_xprt_enqueue will not add new entries without taking the + * sp_lock and checking XPT_BUSY. + */ + svc_clear_list(serv, &serv->sv_tempsocks, net); + svc_clear_list(serv, &serv->sv_permsocks, net); } /* diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index ab02588..33811db 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -485,17 +485,13 @@ EXPORT_SYMBOL_GPL(xprt_wake_pending_tasks); * xprt_wait_for_buffer_space - wait for transport output buffer to clear * @task: task to be put to sleep * @action: function pointer to be executed after wait - * - * Note that we only set the timer for the case of RPC_IS_SOFT(), since - * we don't in general want to force a socket disconnection due to - * an incomplete RPC call transmission. */ void xprt_wait_for_buffer_space(struct rpc_task *task, rpc_action action) { struct rpc_rqst *req = task->tk_rqstp; struct rpc_xprt *xprt = req->rq_xprt; - task->tk_timeout = RPC_IS_SOFT(task) ? req->rq_timeout : 0; + task->tk_timeout = req->rq_timeout; rpc_sleep_on(&xprt->pending, task, action); } EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index fc906d9..9b4e483 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -806,7 +806,6 @@ static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) if (addr) { addr->family = AF_TIPC; addr->addrtype = TIPC_ADDR_ID; - memset(&addr->addr, 0, sizeof(addr->addr)); addr->addr.id.ref = msg_origport(msg); addr->addr.id.node = msg_orignode(msg); addr->addr.name.domain = 0; /* could leave uninitialized */ @@ -921,9 +920,6 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, goto exit; } - /* will be updated in set_orig_addr() if needed */ - m->msg_namelen = 0; - timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); restart: @@ -1033,9 +1029,6 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, goto exit; } - /* will be updated in set_orig_addr() if needed */ - m->msg_namelen = 0; - target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index f347754..5b5c876 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -384,7 +384,7 @@ static void unix_sock_destructor(struct sock *sk) #endif } -static void unix_release_sock(struct sock *sk, int embrion) +static int unix_release_sock(struct sock *sk, int embrion) { struct unix_sock *u = unix_sk(sk); struct path path; @@ -453,6 +453,8 @@ static void unix_release_sock(struct sock *sk, int embrion) if (unix_tot_inflight) unix_gc(); /* Garbage collect fds */ + + return 0; } static void init_peercred(struct sock *sk) @@ -699,10 +701,9 @@ static int unix_release(struct socket *sock) if (!sk) return 0; - unix_release_sock(sk, 0); sock->sk = NULL; - return 0; + return unix_release_sock(sk, 0); } static int unix_autobind(struct socket *sock) @@ -1995,7 +1996,7 @@ again: if ((UNIXCB(skb).pid != siocb->scm->pid) || (UNIXCB(skb).cred != siocb->scm->cred)) break; - } else if (test_bit(SOCK_PASSCRED, &sock->flags)) { + } else { /* Copy credentials */ scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); check_creds = 1; diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 91ef82b..82c4fc7 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -883,7 +883,7 @@ static void handle_channel(struct wiphy *wiphy, return; REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq); - chan->flags |= IEEE80211_CHAN_DISABLED; + chan->flags = IEEE80211_CHAN_DISABLED; return; } |