From 0506eb01f70bd4d7e999c11488a6a892e01c42e2 Mon Sep 17 00:00:00 2001 From: Eugene Crosser Date: Fri, 11 Dec 2015 12:27:50 +0100 Subject: [PATCH 1/8] iucv: prevent information leak in iucv_message Initialize storage for the future IUCV header that will be included in the transmitted packet. Some of the header fields are unused with HiperSockets transport, and will contain data left from some other functions. Signed-off-by: Eugene Crosser Signed-off-by: Ursula Braun Reviewed-by: Thomas Richter Signed-off-by: David S. Miller --- net/iucv/af_iucv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 3ea4c98d94dc..5bc473b01a00 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -1031,7 +1031,7 @@ static int iucv_sock_sendmsg(struct socket *sock, struct msghdr *msg, struct sock *sk = sock->sk; struct iucv_sock *iucv = iucv_sk(sk); struct sk_buff *skb; - struct iucv_message txmsg; + struct iucv_message txmsg = {0}; struct cmsghdr *cmsg; int cmsg_done; long timeo; From 979f66b32dbbf928635dbf44fd9843d27c4ed8f9 Mon Sep 17 00:00:00 2001 From: Eugene Crosser Date: Fri, 11 Dec 2015 12:27:51 +0100 Subject: [PATCH 2/8] iucv: call skb_linearize() when needed When the linear buffer of the received sk_buff is shorter than the header, use skb_linearize(). sk_buffs with short linear buffer happen on the sending side under high traffic, and some kernel configurations, when allocated buffer starts just before page boundary, and IUCV transport has to send it as two separate QDIO buffer elements, with fist element shorter than the header. Signed-off-by: Eugene Crosser Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- net/iucv/af_iucv.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 5bc473b01a00..ef50a94d3eb7 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -2084,11 +2084,7 @@ static int afiucv_hs_callback_rx(struct sock *sk, struct sk_buff *skb) return NET_RX_SUCCESS; } - /* write stuff from iucv_msg to skb cb */ - if (skb->len < sizeof(struct af_iucv_trans_hdr)) { - kfree_skb(skb); - return NET_RX_SUCCESS; - } + /* write stuff from iucv_msg to skb cb */ skb_pull(skb, sizeof(struct af_iucv_trans_hdr)); skb_reset_transport_header(skb); skb_reset_network_header(skb); @@ -2119,6 +2115,20 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, char nullstring[8]; int err = 0; + if (skb->len < (ETH_HLEN + sizeof(struct af_iucv_trans_hdr))) { + WARN_ONCE(1, "AF_IUCV too short skb, len=%d, min=%d", + (int)skb->len, + (int)(ETH_HLEN + sizeof(struct af_iucv_trans_hdr))); + kfree_skb(skb); + return NET_RX_SUCCESS; + } + if (skb_headlen(skb) < (ETH_HLEN + sizeof(struct af_iucv_trans_hdr))) + if (skb_linearize(skb)) { + WARN_ONCE(1, "AF_IUCV skb_linearize failed, len=%d", + (int)skb->len); + kfree_skb(skb); + return NET_RX_SUCCESS; + } skb_pull(skb, ETH_HLEN); trans_hdr = (struct af_iucv_trans_hdr *)skb->data; EBCASC(trans_hdr->destAppName, sizeof(trans_hdr->destAppName)); From f0c59aff88c0ff58f290fee55b9552fcd953d410 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Fri, 11 Dec 2015 12:27:52 +0100 Subject: [PATCH 3/8] MAINTAINERS: switch to alternate IBM mail address Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 8eba565b2b46..ab79736f32cd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9125,7 +9125,7 @@ F: drivers/s390/block/dasd* F: block/partitions/ibm.c S390 NETWORK DRIVERS -M: Ursula Braun +M: Ursula Braun L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported @@ -9155,7 +9155,7 @@ S: Supported F: drivers/s390/scsi/zfcp_* S390 IUCV NETWORK LAYER -M: Ursula Braun +M: Ursula Braun L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported From e043046a5a29bebe7e9a68b92c4580e2888f8ed3 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 11 Dec 2015 12:27:53 +0100 Subject: [PATCH 4/8] s390-ctcm: Delete unnecessary checks before the function call "channel_remove" The channel_remove() function tests whether its argument is NULL and then returns immediately. Thus the test around the calls is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/ctcm_main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 05c37d6d4afe..c3e22523faf3 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -1677,11 +1677,8 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev) ccw_device_set_offline(cgdev->cdev[1]); ccw_device_set_offline(cgdev->cdev[0]); - - if (priv->channel[CTCM_READ]) - channel_remove(priv->channel[CTCM_READ]); - if (priv->channel[CTCM_WRITE]) - channel_remove(priv->channel[CTCM_WRITE]); + channel_remove(priv->channel[CTCM_READ]); + channel_remove(priv->channel[CTCM_WRITE]); priv->channel[CTCM_READ] = priv->channel[CTCM_WRITE] = NULL; return 0; From b475e3161ce74a7e2ee72322585ed5f39985c06a Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Fri, 11 Dec 2015 12:27:54 +0100 Subject: [PATCH 5/8] qeth use common function qeth_get_setassparms_cmd There have been 2 identical versions of function qeth_get_setassparms_cmd() for layer 2 and layer 3. Remove the layer 3 function qeth_l3_get_setassparms_cmd() and call the common one named qeth_get_setassparms_cmd() located in qeth_core_main.c Signed-off-by: Thomas Richter Signed-off-by: Ursula Braun Reviewed-by: Eugene Crosser Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 4 ++++ drivers/s390/net/qeth_core_main.c | 9 ++++---- drivers/s390/net/qeth_l3_main.c | 37 +++++++------------------------ 3 files changed, 17 insertions(+), 33 deletions(-) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 1766a20ebcb1..ec2e014e885c 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -981,6 +981,10 @@ int qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *, __u16, int (*reply_cb)(struct qeth_card *, struct qeth_reply *, unsigned long), void *); +struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *, + enum qeth_ipa_funcs, + __u16, __u16, + enum qeth_prot_versions); int qeth_start_ipa_tx_checksum(struct qeth_card *); int qeth_set_rx_csum(struct qeth_card *, int); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 31ac53fa5cee..fe1845acf560 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -5297,10 +5297,10 @@ static int qeth_setassparms_cb(struct qeth_card *card, return 0; } -static struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card, - enum qeth_ipa_funcs ipa_func, - __u16 cmd_code, __u16 len, - enum qeth_prot_versions prot) +struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card, + enum qeth_ipa_funcs ipa_func, + __u16 cmd_code, __u16 len, + enum qeth_prot_versions prot) { struct qeth_cmd_buffer *iob; struct qeth_ipa_cmd *cmd; @@ -5319,6 +5319,7 @@ static struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card, return iob; } +EXPORT_SYMBOL_GPL(qeth_get_setassparms_cmd); int qeth_send_setassparms(struct qeth_card *card, struct qeth_cmd_buffer *iob, __u16 len, long data, diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 543960e96b42..e2eb88c0d41d 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1043,28 +1043,6 @@ static int qeth_l3_default_setassparms_cb(struct qeth_card *card, return 0; } -static struct qeth_cmd_buffer *qeth_l3_get_setassparms_cmd( - struct qeth_card *card, enum qeth_ipa_funcs ipa_func, __u16 cmd_code, - __u16 len, enum qeth_prot_versions prot) -{ - struct qeth_cmd_buffer *iob; - struct qeth_ipa_cmd *cmd; - - QETH_CARD_TEXT(card, 4, "getasscm"); - iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETASSPARMS, prot); - - if (iob) { - cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); - cmd->data.setassparms.hdr.assist_no = ipa_func; - cmd->data.setassparms.hdr.length = 8 + len; - cmd->data.setassparms.hdr.command_code = cmd_code; - cmd->data.setassparms.hdr.return_code = 0; - cmd->data.setassparms.hdr.seq_no = 0; - } - - return iob; -} - #ifdef CONFIG_QETH_IPV6 static int qeth_l3_send_simple_setassparms_ipv6(struct qeth_card *card, enum qeth_ipa_funcs ipa_func, __u16 cmd_code) @@ -1073,7 +1051,7 @@ static int qeth_l3_send_simple_setassparms_ipv6(struct qeth_card *card, struct qeth_cmd_buffer *iob; QETH_CARD_TEXT(card, 4, "simassp6"); - iob = qeth_l3_get_setassparms_cmd(card, ipa_func, cmd_code, + iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code, 0, QETH_PROT_IPV6); if (!iob) return -ENOMEM; @@ -2344,10 +2322,11 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card, QETH_CARD_TEXT_(card, 3, "qarpipv%i", prot); - iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING, - IPA_CMD_ASS_ARP_QUERY_INFO, - sizeof(struct qeth_arp_query_data) - sizeof(char), - prot); + iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, + IPA_CMD_ASS_ARP_QUERY_INFO, + sizeof(struct qeth_arp_query_data) + - sizeof(char), + prot); if (!iob) return -ENOMEM; cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); @@ -2439,7 +2418,7 @@ static int qeth_l3_arp_add_entry(struct qeth_card *card, return -EOPNOTSUPP; } - iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING, + iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, IPA_CMD_ASS_ARP_ADD_ENTRY, sizeof(struct qeth_arp_cache_entry), QETH_PROT_IPV4); @@ -2480,7 +2459,7 @@ static int qeth_l3_arp_remove_entry(struct qeth_card *card, return -EOPNOTSUPP; } memcpy(buf, entry, 12); - iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING, + iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, IPA_CMD_ASS_ARP_REMOVE_ENTRY, 12, QETH_PROT_IPV4); From e5ebe63214d44d4dcf43df02edf3613e04d671b9 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Fri, 11 Dec 2015 12:27:55 +0100 Subject: [PATCH 6/8] qeth: initialize net_device with carrier off /sys/class/net//operstate for an active qeth network interface offen shows "unknown", which translates to "state UNKNOWN in output of "ip link show". It is caused by a missing initialization of the __LINK_STATE_NOCARRIER bit in the net_device state field. This patch adds a netif_carrier_off() invocation when creating the net_device for a qeth device. Signed-off-by: Ursula Braun Acked-by: Hendrik Brueckner Reference-ID: Bugzilla 133209 Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l2_main.c | 1 + drivers/s390/net/qeth_l3_main.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 8f1b091e1732..80b1979e8d95 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -1126,6 +1126,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) qeth_l2_request_initial_mac(card); SET_NETDEV_DEV(card->dev, &card->gdev->dev); netif_napi_add(card->dev, &card->napi, qeth_l2_poll, QETH_NAPI_WEIGHT); + netif_carrier_off(card->dev); return register_netdev(card->dev); } diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index e2eb88c0d41d..10d9d3eefd20 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -3199,6 +3199,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) SET_NETDEV_DEV(card->dev, &card->gdev->dev); netif_napi_add(card->dev, &card->napi, qeth_l3_poll, QETH_NAPI_WEIGHT); + netif_carrier_off(card->dev); return register_netdev(card->dev); } From 577777359e1f47d0cb7dfc23aac0da867a14af00 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Fri, 11 Dec 2015 12:27:56 +0100 Subject: [PATCH 7/8] qeth: repair SBAL elements calculation When sending skbs, qeth determines the number of qdio SBAL elements required. If qeth sends a fragmented skb, the SBAL element number calculation is wrong, because the fragmented data part is added twice in qeth_l3_tso_elements(). This patch makes sure fragmented data is handled in qeth_elements_for_frags() only, while qeth_l3_tso_elements() starts calculation of qdio SBAL elements just with the linear data part of the skb. Signed-off-by: Ursula Braun Reviewed-by: Thomas Richter Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l3_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 10d9d3eefd20..7c8c68c26540 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2797,7 +2797,7 @@ static inline int qeth_l3_tso_elements(struct sk_buff *skb) { unsigned long tcpd = (unsigned long)tcp_hdr(skb) + tcp_hdr(skb)->doff * 4; - int tcpd_len = skb->len - (tcpd - (unsigned long)skb->data); + int tcpd_len = skb_headlen(skb) - (tcpd - (unsigned long)skb->data); int elements = PFN_UP(tcpd + tcpd_len - 1) - PFN_DOWN(tcpd); elements += qeth_get_elements_for_frags(skb); From 476933ce9fedaa723f13c2aabd2aa26dfcdceb15 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Fri, 11 Dec 2015 12:27:57 +0100 Subject: [PATCH 8/8] qeth: get rid of redundant 0-termination 0-termination is redundant, since sprintf has done that. Signed-off-by: Rasmus Villemoes Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index fe1845acf560..787153764120 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2684,8 +2684,6 @@ void qeth_print_status_message(struct qeth_card *card) sprintf(card->info.mcl_level, "%02x%02x", card->info.mcl_level[2], card->info.mcl_level[3]); - - card->info.mcl_level[QETH_MCL_LENGTH] = 0; break; } /* fallthrough */