mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 13:49:24 -04:00
net: qrtr: Prevent stale ports from sending
The current implementation of the control port bind releases and reacquires the port lock between allocating the port idr and resetting the existing sockets. This creates a race condition where sockets can send to the control port during the control port bind. Hold the lock for the duration of the control port bind to prevent this. In order to prevent messages from stale sockets being sent, check if ENETRESET has been set on the socket and drop the packet. Change-Id: Ie9abc6c51139e82d3c9ebd4d546d1acd7269875e Signed-off-by: Chris Lew <clew@codeaurora.org>
This commit is contained in:
parent
0d116bcb6a
commit
d2a5084230
1 changed files with 18 additions and 10 deletions
|
|
@ -757,7 +757,6 @@ static int qrtr_port_assign(struct qrtr_sock *ipc, int *port)
|
|||
{
|
||||
int rc;
|
||||
|
||||
mutex_lock(&qrtr_port_lock);
|
||||
if (!*port) {
|
||||
rc = idr_alloc_cyclic(&qrtr_ports, ipc, QRTR_MIN_EPH_SOCKET,
|
||||
QRTR_MAX_EPH_SOCKET + 1, GFP_ATOMIC);
|
||||
|
|
@ -773,7 +772,6 @@ static int qrtr_port_assign(struct qrtr_sock *ipc, int *port)
|
|||
if (rc >= 0)
|
||||
*port = rc;
|
||||
}
|
||||
mutex_unlock(&qrtr_port_lock);
|
||||
|
||||
if (rc == -ENOSPC)
|
||||
return -EADDRINUSE;
|
||||
|
|
@ -791,7 +789,6 @@ static void qrtr_reset_ports(void)
|
|||
struct qrtr_sock *ipc;
|
||||
int id;
|
||||
|
||||
mutex_lock(&qrtr_port_lock);
|
||||
idr_for_each_entry(&qrtr_ports, ipc, id) {
|
||||
/* Don't reset control port */
|
||||
if (id == 0)
|
||||
|
|
@ -802,7 +799,6 @@ static void qrtr_reset_ports(void)
|
|||
ipc->sk.sk_error_report(&ipc->sk);
|
||||
sock_put(&ipc->sk);
|
||||
}
|
||||
mutex_unlock(&qrtr_port_lock);
|
||||
}
|
||||
|
||||
/* Bind socket to address.
|
||||
|
|
@ -821,22 +817,24 @@ static int __qrtr_bind(struct socket *sock,
|
|||
if (!zapped && addr->sq_port == ipc->us.sq_port)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&qrtr_port_lock);
|
||||
port = addr->sq_port;
|
||||
rc = qrtr_port_assign(ipc, &port);
|
||||
if (rc)
|
||||
if (rc) {
|
||||
mutex_unlock(&qrtr_port_lock);
|
||||
return rc;
|
||||
}
|
||||
/* Notify all open ports about the new controller */
|
||||
if (port == QRTR_PORT_CTRL)
|
||||
qrtr_reset_ports();
|
||||
mutex_unlock(&qrtr_port_lock);
|
||||
|
||||
/* unbind previous, if any */
|
||||
if (!zapped)
|
||||
qrtr_port_remove(ipc);
|
||||
ipc->us.sq_port = port;
|
||||
|
||||
sock_reset_flag(sk, SOCK_ZAPPED);
|
||||
|
||||
/* Notify all open ports about the new controller */
|
||||
if (port == QRTR_PORT_CTRL)
|
||||
qrtr_reset_ports();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -884,12 +882,22 @@ static int qrtr_local_enqueue(struct qrtr_node *node, struct sk_buff *skb,
|
|||
{
|
||||
struct qrtr_sock *ipc;
|
||||
struct qrtr_cb *cb;
|
||||
struct sock *sk = skb->sk;
|
||||
|
||||
ipc = qrtr_port_lookup(to->sq_port);
|
||||
if (!ipc || &ipc->sk == skb->sk) { /* do not send to self */
|
||||
kfree_skb(skb);
|
||||
return -ENODEV;
|
||||
}
|
||||
/* Keep resetting NETRESET until socket is closed */
|
||||
if (sk && sk->sk_err == ENETRESET) {
|
||||
sock_hold(sk);
|
||||
sk->sk_err = ENETRESET;
|
||||
sk->sk_error_report(sk);
|
||||
sock_put(sk);
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cb = (struct qrtr_cb *)skb->cb;
|
||||
cb->src_node = from->sq_node;
|
||||
|
|
|
|||
Loading…
Reference in a new issue