Commit fce471e3 authored by David S. Miller's avatar David S. Miller

Merge branch 'iucv-fixes'

Julian Wiedmann says:

====================
net/iucv: fixes 2018-09-05

please apply three straight-forward fixes for iucv. One that prevents
leaking the skb on malformed inbound packets, one to fix the error
handling on transmit error, and one to get rid of a compile warning.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ee28bb56 b7f41565
...@@ -351,20 +351,28 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock, ...@@ -351,20 +351,28 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock,
memcpy(&phs_hdr->iucv_hdr, imsg, sizeof(struct iucv_message)); memcpy(&phs_hdr->iucv_hdr, imsg, sizeof(struct iucv_message));
skb->dev = iucv->hs_dev; skb->dev = iucv->hs_dev;
if (!skb->dev) if (!skb->dev) {
return -ENODEV; err = -ENODEV;
if (!(skb->dev->flags & IFF_UP) || !netif_carrier_ok(skb->dev)) goto err_free;
return -ENETDOWN; }
if (!(skb->dev->flags & IFF_UP) || !netif_carrier_ok(skb->dev)) {
err = -ENETDOWN;
goto err_free;
}
if (skb->len > skb->dev->mtu) { if (skb->len > skb->dev->mtu) {
if (sock->sk_type == SOCK_SEQPACKET) if (sock->sk_type == SOCK_SEQPACKET) {
return -EMSGSIZE; err = -EMSGSIZE;
else goto err_free;
skb_trim(skb, skb->dev->mtu); }
skb_trim(skb, skb->dev->mtu);
} }
skb->protocol = cpu_to_be16(ETH_P_AF_IUCV); skb->protocol = cpu_to_be16(ETH_P_AF_IUCV);
nskb = skb_clone(skb, GFP_ATOMIC); nskb = skb_clone(skb, GFP_ATOMIC);
if (!nskb) if (!nskb) {
return -ENOMEM; err = -ENOMEM;
goto err_free;
}
skb_queue_tail(&iucv->send_skb_q, nskb); skb_queue_tail(&iucv->send_skb_q, nskb);
err = dev_queue_xmit(skb); err = dev_queue_xmit(skb);
if (net_xmit_eval(err)) { if (net_xmit_eval(err)) {
...@@ -375,6 +383,10 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock, ...@@ -375,6 +383,10 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock,
WARN_ON(atomic_read(&iucv->msg_recv) < 0); WARN_ON(atomic_read(&iucv->msg_recv) < 0);
} }
return net_xmit_eval(err); return net_xmit_eval(err);
err_free:
kfree_skb(skb);
return err;
} }
static struct sock *__iucv_get_sock_by_name(char *nm) static struct sock *__iucv_get_sock_by_name(char *nm)
...@@ -1167,7 +1179,7 @@ static int iucv_sock_sendmsg(struct socket *sock, struct msghdr *msg, ...@@ -1167,7 +1179,7 @@ static int iucv_sock_sendmsg(struct socket *sock, struct msghdr *msg,
err = afiucv_hs_send(&txmsg, sk, skb, 0); err = afiucv_hs_send(&txmsg, sk, skb, 0);
if (err) { if (err) {
atomic_dec(&iucv->msg_sent); atomic_dec(&iucv->msg_sent);
goto fail; goto out;
} }
} else { /* Classic VM IUCV transport */ } else { /* Classic VM IUCV transport */
skb_queue_tail(&iucv->send_skb_q, skb); skb_queue_tail(&iucv->send_skb_q, skb);
...@@ -2155,8 +2167,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -2155,8 +2167,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
struct sock *sk; struct sock *sk;
struct iucv_sock *iucv; struct iucv_sock *iucv;
struct af_iucv_trans_hdr *trans_hdr; struct af_iucv_trans_hdr *trans_hdr;
int err = NET_RX_SUCCESS;
char nullstring[8]; char nullstring[8];
int err = 0;
if (skb->len < (ETH_HLEN + sizeof(struct af_iucv_trans_hdr))) { if (skb->len < (ETH_HLEN + sizeof(struct af_iucv_trans_hdr))) {
WARN_ONCE(1, "AF_IUCV too short skb, len=%d, min=%d", WARN_ONCE(1, "AF_IUCV too short skb, len=%d, min=%d",
...@@ -2254,7 +2266,7 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -2254,7 +2266,7 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
err = afiucv_hs_callback_rx(sk, skb); err = afiucv_hs_callback_rx(sk, skb);
break; break;
default: default:
; kfree_skb(skb);
} }
return err; return err;
......
...@@ -1874,7 +1874,7 @@ static void iucv_pm_complete(struct device *dev) ...@@ -1874,7 +1874,7 @@ static void iucv_pm_complete(struct device *dev)
* Returns 0 if there are still iucv pathes defined * Returns 0 if there are still iucv pathes defined
* 1 if there are no iucv pathes defined * 1 if there are no iucv pathes defined
*/ */
int iucv_path_table_empty(void) static int iucv_path_table_empty(void)
{ {
int i; int i;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment