From 0a6a3a23ea6efde079a5b77688541a98bf202721 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Fri, 28 Aug 2015 07:07:48 +0200 Subject: netlink: add NETLINK_CAP_ACK socket option Since commit c05cdb1b864f ("netlink: allow large data transfers from user-space"), the kernel may fail to allocate the necessary room for the acknowledgment message back to userspace. This patch introduces a new socket option that trims off the payload of the original netlink message. The netlink message header is still included, so the user can guess from the sequence number what is the message that has triggered the acknowledgment. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Christophe Ricard Signed-off-by: David S. Miller --- include/uapi/linux/netlink.h | 1 + net/netlink/af_netlink.c | 27 ++++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h index cf6a65cccbdf..6f3fe16cd22a 100644 --- a/include/uapi/linux/netlink.h +++ b/include/uapi/linux/netlink.h @@ -110,6 +110,7 @@ struct nlmsgerr { #define NETLINK_TX_RING 7 #define NETLINK_LISTEN_ALL_NSID 8 #define NETLINK_LIST_MEMBERSHIPS 9 +#define NETLINK_CAP_ACK 10 struct nl_pktinfo { __u32 group; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index a774985489e2..3eea0b2a3239 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -84,6 +84,7 @@ struct listeners { #define NETLINK_F_BROADCAST_SEND_ERROR 0x4 #define NETLINK_F_RECV_NO_ENOBUFS 0x8 #define NETLINK_F_LISTEN_ALL_NSID 0x10 +#define NETLINK_F_CAP_ACK 0x20 static inline int netlink_is_kernel(struct sock *sk) { @@ -2258,6 +2259,13 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, nlk->flags &= ~NETLINK_F_LISTEN_ALL_NSID; err = 0; break; + case NETLINK_CAP_ACK: + if (val) + nlk->flags |= NETLINK_F_CAP_ACK; + else + nlk->flags &= ~NETLINK_F_CAP_ACK; + err = 0; + break; default: err = -ENOPROTOOPT; } @@ -2332,6 +2340,16 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname, netlink_table_ungrab(); break; } + case NETLINK_CAP_ACK: + if (len < sizeof(int)) + return -EINVAL; + len = sizeof(int); + val = nlk->flags & NETLINK_F_CAP_ACK ? 1 : 0; + if (put_user(len, optlen) || + put_user(val, optval)) + return -EFAULT; + err = 0; + break; default: err = -ENOPROTOOPT; } @@ -2873,9 +2891,12 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) struct nlmsghdr *rep; struct nlmsgerr *errmsg; size_t payload = sizeof(*errmsg); + struct netlink_sock *nlk = nlk_sk(NETLINK_CB(in_skb).sk); - /* error messages get the original request appened */ - if (err) + /* Error messages get the original request appened, unless the user + * requests to cap the error message. + */ + if (!(nlk->flags & NETLINK_F_CAP_ACK) && err) payload += nlmsg_len(nlh); skb = netlink_alloc_skb(in_skb->sk, nlmsg_total_size(payload), @@ -2898,7 +2919,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) NLMSG_ERROR, payload, 0); errmsg = nlmsg_data(rep); errmsg->error = err; - memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(*nlh)); + memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh)); netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).portid, MSG_DONTWAIT); } EXPORT_SYMBOL(netlink_ack); -- cgit v1.2.3-59-g8ed1b From 7084a315897715776d1764f5fd9250609e515beb Mon Sep 17 00:00:00 2001 From: Ken-ichirou MATSUZAWA Date: Fri, 28 Aug 2015 16:05:20 +0900 Subject: netlink: mmap: fix lookup frame position __netlink_lookup_frame() was always called with the same "pos" value in netlink_forward_ring(). It will look at the same ring entry header over and over again, every time through this loop. Then cycle through the whole ring, advancing ring->head, not "pos" until it equals the "ring->head != head" loop test fails. Signed-off-by: Ken-ichirou MATSUZAWA Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 3eea0b2a3239..7965ca7c461d 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -611,11 +611,11 @@ static void netlink_increment_head(struct netlink_ring *ring) static void netlink_forward_ring(struct netlink_ring *ring) { - unsigned int head = ring->head, pos = head; + unsigned int head = ring->head; const struct nl_mmap_hdr *hdr; do { - hdr = __netlink_lookup_frame(ring, pos); + hdr = __netlink_lookup_frame(ring, ring->head); if (hdr->nm_status == NL_MMAP_STATUS_UNUSED) break; if (hdr->nm_status != NL_MMAP_STATUS_SKIP) -- cgit v1.2.3-59-g8ed1b From 7c5a9461812b21e1a1b7a09a83e97530b8867459 Mon Sep 17 00:00:00 2001 From: lucien Date: Fri, 28 Aug 2015 17:45:58 +0800 Subject: sctp: ASCONF-ACK with Unresolvable Address should be sent RFC 5061: This is an opaque integer assigned by the sender to identify each request parameter. The receiver of the ASCONF Chunk will copy this 32-bit value into the ASCONF Response Correlation ID field of the ASCONF-ACK response parameter. The sender of the ASCONF can use this same value in the ASCONF-ACK to find which request the response is for. Note that the receiver MUST NOT change this 32-bit value. Address Parameter: TLV This field contains an IPv4 or IPv6 address parameter, as described in Section 3.3.2.1 of [RFC4960]. ASCONF chunk with Error Cause Indication Parameter (Unresolvable Address) should be sent if the Delete IP Address is not part of the association. Endpoint A Endpoint B (ESTABLISHED) (ESTABLISHED) ASCONF -----------------> (Delete IP Address) <----------------- ASCONF-ACK (Unresolvable Address) Signed-off-by: Xin Long Acked-by: Vlad Yasevich Acked-by: Marcelo Ricardo Leitner Signed-off-by: David S. Miller --- net/sctp/sm_make_chunk.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index a655ddc3f353..7954c52e1794 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -3090,8 +3090,19 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, sctp_assoc_set_primary(asoc, asconf->transport); sctp_assoc_del_nonprimary_peers(asoc, asconf->transport); - } else - sctp_assoc_del_peer(asoc, &addr); + return SCTP_ERROR_NO_ERROR; + } + + /* If the address is not part of the association, the + * ASCONF-ACK with Error Cause Indication Parameter + * which including cause of Unresolvable Address should + * be sent. + */ + peer = sctp_assoc_lookup_paddr(asoc, &addr); + if (!peer) + return SCTP_ERROR_DNS_FAILED; + + sctp_assoc_rm_peer(asoc, peer); break; case SCTP_PARAM_SET_PRIMARY: /* ADDIP Section 4.2.4 -- cgit v1.2.3-59-g8ed1b From f375339e497582ea0bc8806a0552add1cabb6d4e Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 28 Aug 2015 16:55:10 +0300 Subject: ravb: propagate platform_get_irq() error upstream The driver overrides the error returned by platform_get_irq() with -ENODEV which e.g. precludes the deferred probing from working. Propagate the real error code to the driver core instead. Signed-off-by: Sergei Shtylyov Acked-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 78849dd4ef8e..44b37141d125 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1643,7 +1643,7 @@ static int ravb_probe(struct platform_device *pdev) ndev->dma = -1; irq = platform_get_irq(pdev, 0); if (irq < 0) { - error = -ENODEV; + error = irq; goto out_release; } ndev->irq = irq; -- cgit v1.2.3-59-g8ed1b From 7a468ac624c80bda76957d8cbc28024f4f68e316 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 28 Aug 2015 16:56:01 +0300 Subject: sh_eth: propagate platform_get_irq() error upstream The driver overrides the error returned by platform_get_irq() with -ENODEV which e.g. precludes the deferred probing from working. Propagate the real error code to the driver core instead. Signed-off-by: Sergei Shtylyov Acked-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 7fb244f565b2..257ea713b4c1 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -3089,10 +3089,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev) ndev->dma = -1; ret = platform_get_irq(pdev, 0); - if (ret < 0) { - ret = -ENODEV; + if (ret < 0) goto out_release; - } ndev->irq = ret; SET_NETDEV_DEV(ndev, &pdev->dev); -- cgit v1.2.3-59-g8ed1b From b0d4943eec9a42c7ba2065f6cfa949894204dd4a Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Fri, 28 Aug 2015 15:05:32 -0700 Subject: bonding: fix bond_poll_controller bh_enable warning The problem is rcu_read_unlock_bh() which triggers a warning when irqs are disabled. ndo_poll_controller should run with irqs disabled always so we can drop the rcu_read_lock_bh. [ 98.502922] bond0: making interface eth1 the new active one [ 98.503039] ------------[ cut here ]------------ [ 98.503039] WARNING: CPU: 0 PID: 1744 at kernel/softirq.c:150 __local_bh_enable_ip+0x96/0xc0() [ 98.503039] Modules linked in: bonding(OE) rpcsec_gss_krb5 nfsv4 dns_resolver nfs fscache netconsole ppdev joydev parport_pc serio_raw parport i2c_piix4 video acpi_cpufreq nfsd auth_rpcgss nfs_acl lockd grace sunrpc virtio_net e1000 ata_generic pcnet32 mii virtio_pci virtio_ring virtio pata_acpi [ 98.503039] CPU: 0 PID: 1744 Comm: ifenslave Tainted: G OE 4.2.0-rc7+ #56 [ 98.503039] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 98.503039] 0000000000000000 00000000e96ba230 ffff880020c236b8 ffffffff8183f105 [ 98.503039] 0000000000000000 0000000000000000 ffff880020c236f8 ffffffff810a9496 [ 98.503039] ffff88002ea99e08 0000000000000200 ffffffffa02a8e06 ffff88002ea99e08 [ 98.503039] Call Trace: [ 98.503039] [] dump_stack+0x4c/0x65 [ 98.503039] [] warn_slowpath_common+0x86/0xc0 [ 98.503039] [] ? bond_poll_controller+0x146/0x250 [bonding] [ 98.503039] [] warn_slowpath_null+0x1a/0x20 [ 98.503039] [] __local_bh_enable_ip+0x96/0xc0 [ 98.503039] [] bond_poll_controller+0x16f/0x250 [bonding] [ 98.503039] [] ? bond_poll_controller+0x33/0x250 [bonding] [ 98.503039] [] ? trace_hardirqs_off+0xd/0x10 [ 98.503039] [] ? _raw_spin_unlock_irqrestore+0x5b/0x60 [ 98.503039] [] netpoll_poll_dev+0x6e/0x350 [ 98.503039] [] ? netpoll_start_xmit+0x137/0x1d0 [ 98.503039] [] ? __alloc_skb+0x5b/0x210 [ 98.503039] [] netpoll_send_skb_on_dev+0x12d/0x2a0 [ 98.503039] [] netpoll_send_udp+0x2ce/0x430 [ 98.503039] [] write_msg+0xb0/0xf0 [netconsole] [ 98.503039] [] call_console_drivers.constprop.25+0x133/0x260 [ 98.503039] [] console_unlock+0x2f4/0x580 [ 98.503039] [] ? vprintk_emit+0x2e5/0x630 [ 98.503039] [] vprintk_emit+0x325/0x630 [ 98.503039] [] vprintk_default+0x29/0x40 [ 98.503039] [] printk+0x55/0x6b [ 98.503039] [] __netdev_printk+0x16c/0x260 [ 98.503039] [] netdev_info+0x62/0x80 [ 98.503039] [] bond_change_active_slave+0x134/0x6a0 [bonding] [ 98.503039] [] bond_select_active_slave+0xc5/0x310 [bonding] [ 98.503039] [] bond_enslave+0x1088/0x10c0 [bonding] [ 98.503039] [] bond_do_ioctl+0x37b/0x400 [bonding] [ 98.503039] [] ? trace_hardirqs_on+0xd/0x10 [ 98.503039] [] ? rtnl_lock+0x17/0x20 [ 98.503039] [] dev_ifsioc+0x331/0x3e0 [ 98.503039] [] dev_ioctl+0xec/0x6c0 [ 98.503039] [] sock_do_ioctl+0x4a/0x60 [ 98.503039] [] sock_ioctl+0x1c0/0x250 [ 98.503039] [] do_vfs_ioctl+0x2ee/0x540 [ 98.503039] [] ? up_read+0x23/0x40 [ 98.503039] [] ? __do_page_fault+0x1d3/0x420 [ 98.503039] [] ? __fget_light+0x66/0x90 [ 98.503039] [] SyS_ioctl+0x79/0x90 [ 98.503039] [] entry_SYSCALL_64_fastpath+0x12/0x76 [ 98.503039] ---[ end trace 00cfa804b0670051 ]--- Fixes: 616f45416ca0 ("bonding: implement bond_poll_controller()") Signed-off-by: Nikolay Aleksandrov Acked-by: Mahesh Bandewar Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index a98dd4f1b0e3..7ab72692d7fd 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -979,7 +979,6 @@ static void bond_poll_controller(struct net_device *bond_dev) if (bond_3ad_get_active_agg_info(bond, &ad_info)) return; - rcu_read_lock_bh(); bond_for_each_slave_rcu(bond, slave, iter) { ops = slave->dev->netdev_ops; if (!bond_slave_is_up(slave) || !ops->ndo_poll_controller) @@ -1000,7 +999,6 @@ static void bond_poll_controller(struct net_device *bond_dev) ops->ndo_poll_controller(slave->dev); up(&ni->dev_lock); } - rcu_read_unlock_bh(); } static void bond_netpoll_cleanup(struct net_device *bond_dev) -- cgit v1.2.3-59-g8ed1b From 73e6742027f5cb5a7c747d9abab5351b01fd4c74 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Fri, 28 Aug 2015 21:23:39 -0400 Subject: sctp: Do not try to search for the transport twice When removing an non-primary transport during ASCONF processing, we end up traversing the transport list twice: once in sctp_cmd_del_non_primary, and once in sctp_assoc_del_peer. We can avoid the second search and call sctp_assoc_rm_peer() instead. Found by code inspection during code reviews. Signed-off-by: Vladislav Yasevich Signed-off-by: David S. Miller --- net/sctp/sm_sideeffect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 85e6f03aeb70..35df1266bf07 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -954,7 +954,7 @@ static void sctp_cmd_del_non_primary(struct sctp_association *asoc) t = list_entry(pos, struct sctp_transport, transports); if (!sctp_cmp_addr_exact(&t->ipaddr, &asoc->peer.primary_addr)) { - sctp_assoc_del_peer(asoc, &t->ipaddr); + sctp_assoc_rm_peer(asoc, t); } } } -- cgit v1.2.3-59-g8ed1b From f892a84cc890aaaba7bc42daf2e2ee86b0961884 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 28 Aug 2015 11:50:15 -0700 Subject: net/smsc911x: Fix deferred probe for interrupt The interrupt handler may not be available when smsc911x probes if the interrupt handler is a GPIO controller for example. Let's fix that by adding handling for -EPROBE_DEFER. Cc: Steve Glendinning Signed-off-by: Tony Lindgren Signed-off-by: David S. Miller --- drivers/net/ethernet/smsc/smsc911x.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 959aeeade0c9..cb9f166f907e 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -2435,7 +2435,10 @@ static int smsc911x_drv_probe(struct platform_device *pdev) res_size = resource_size(res); irq = platform_get_irq(pdev, 0); - if (irq <= 0) { + if (irq == -EPROBE_DEFER) { + retval = -EPROBE_DEFER; + goto out_0; + } else if (irq <= 0) { pr_warn("Could not allocate irq resource\n"); retval = -ENODEV; goto out_0; -- cgit v1.2.3-59-g8ed1b