diff options
Diffstat (limited to 'net/qrtr/qrtr.c')
-rw-r--r-- | net/qrtr/qrtr.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 8d9a244f4534..f712f521db26 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -235,7 +235,7 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) if (dst != QRTR_PORT_CTRL && type != QRTR_TYPE_DATA) return -EINVAL; - skb = netdev_alloc_skb(NULL, len); + skb = __netdev_alloc_skb(NULL, len, GFP_ATOMIC | __GFP_NOWARN); if (!skb) return -ENOMEM; @@ -660,7 +660,7 @@ static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb) } mutex_unlock(&qrtr_node_lock); - qrtr_local_enqueue(node, skb); + qrtr_local_enqueue(NULL, skb); return 0; } @@ -710,20 +710,21 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) node = NULL; if (addr->sq_node == QRTR_NODE_BCAST) { - enqueue_fn = qrtr_bcast_enqueue; - if (addr->sq_port != QRTR_PORT_CTRL) { + if (addr->sq_port != QRTR_PORT_CTRL && + qrtr_local_nid != QRTR_NODE_BCAST) { release_sock(sk); return -ENOTCONN; } + enqueue_fn = qrtr_bcast_enqueue; } else if (addr->sq_node == ipc->us.sq_node) { enqueue_fn = qrtr_local_enqueue; } else { - enqueue_fn = qrtr_node_enqueue; node = qrtr_node_lookup(addr->sq_node); if (!node) { release_sock(sk); return -ECONNRESET; } + enqueue_fn = qrtr_node_enqueue; } plen = (len + 3) & ~3; @@ -818,6 +819,11 @@ static int qrtr_recvmsg(struct socket *sock, struct msghdr *msg, rc = copied; if (addr) { + /* There is an anonymous 2-byte hole after sq_family, + * make sure to clear it. + */ + memset(addr, 0, sizeof(*addr)); + addr->sq_family = AF_QIPCRTR; addr->sq_node = le32_to_cpu(phdr->src_node_id); addr->sq_port = le32_to_cpu(phdr->src_port_id); |