RxRPC fixes
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIVAwUAV6oCE/Sw1s6N8H32AQK1bxAAj2FoASombJwHomUjnvKb4RWdFkwA2Km3 A2R6qdPYCZLbdiH7gw8TqSYGBp//8EL6qlcMKKVvSciAFlS0oQb2G99Tni4cVB4W /xmRatAeU2/k1YBndPsOFHkhdDto6BlsUJbWaW3WIH2vqIfFsW1nh4oIR0N9yvt0 awF34s2yXfp77hr2t7Ca/PMibEcyCmg2kF83Kxilx5z/Ubpl/TtyqswLiPDO7EJq lfyoplgxoG0kvpN1wh2z8i4dKAh8+e3PMIMBdodG/2aA/srWVlECRDx0IqQ4hzQg iSaJDBp+E9ZhKExkPIDpEx49iH1kawerFub+udBDCR6n9JPSlPOWdHiYxXaVE7yA WGW2JGyv2Wo7vkEM76/3dzHBzn0w203T6C+Sa25I82oOxvVbAZfQRxHTJVmCdcOc lHyeGcEuk4h2lYc7U/ty3uGEwm7dL+tyoEw0MGcHQEDpnainKjFPdXiKSOOMb/Vd kiqXrsK9nPZ9JjDtRA1oK7uLNYbllFH13aDR5kU1VAH4s2zwD1498/tegcZ+Hds5 UKhyWfqHBr3uBrxEwRVLFnJ5yi6LQy+O4jNHg1gTakaY6B2j34sLzd5fuc1idhGe yUuCU+XC7mcdQQWoXAc96/orsqmtEiY6yABuTTijeZTSbpKBT3uJpelzAnuxCePZ 2u0lddGIl7M= =c47N -----END PGP SIGNATURE----- Merge tag 'rxrpc-fixes-20160809' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs David Howells says: ==================== rxrpc: Miscellaneous fixes Here are a bunch of miscellaneous fixes to AF_RXRPC: (*) Fix an uninitialised pointer. (*) Fix error handling when we fail to connect a call. (*) Fix a NULL pointer dereference. (*) Fix two occasions where a packet is accessed again after being queued for someone else to deal with. (*) Fix a missing skb free. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
aee4eda1ab
@ -837,6 +837,9 @@ void rxrpc_process_call(struct work_struct *work)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!call->conn)
|
||||
goto skip_msg_init;
|
||||
|
||||
/* there's a good chance we're going to have to send a message, so set
|
||||
* one up in advance */
|
||||
msg.msg_name = &call->conn->params.peer->srx.transport;
|
||||
@ -859,6 +862,7 @@ void rxrpc_process_call(struct work_struct *work)
|
||||
memset(iov, 0, sizeof(iov));
|
||||
iov[0].iov_base = &whdr;
|
||||
iov[0].iov_len = sizeof(whdr);
|
||||
skip_msg_init:
|
||||
|
||||
/* deal with events of a final nature */
|
||||
if (test_bit(RXRPC_CALL_EV_RCVD_ERROR, &call->events)) {
|
||||
|
@ -275,6 +275,7 @@ error:
|
||||
list_del_init(&call->link);
|
||||
write_unlock_bh(&rxrpc_call_lock);
|
||||
|
||||
set_bit(RXRPC_CALL_RELEASED, &call->flags);
|
||||
call->state = RXRPC_CALL_DEAD;
|
||||
rxrpc_put_call(call);
|
||||
_leave(" = %d", ret);
|
||||
@ -287,6 +288,7 @@ error:
|
||||
*/
|
||||
found_user_ID_now_present:
|
||||
write_unlock(&rx->call_lock);
|
||||
set_bit(RXRPC_CALL_RELEASED, &call->flags);
|
||||
call->state = RXRPC_CALL_DEAD;
|
||||
rxrpc_put_call(call);
|
||||
_leave(" = -EEXIST [%p]", call);
|
||||
@ -493,6 +495,7 @@ void rxrpc_release_call(struct rxrpc_call *call)
|
||||
(skb = skb_dequeue(&call->rx_oos_queue))) {
|
||||
spin_unlock_bh(&call->lock);
|
||||
|
||||
sp = rxrpc_skb(skb);
|
||||
_debug("- zap %s %%%u #%u",
|
||||
rxrpc_pkts[sp->hdr.type],
|
||||
sp->hdr.serial, sp->hdr.seq);
|
||||
|
@ -124,11 +124,15 @@ static int rxrpc_fast_process_data(struct rxrpc_call *call,
|
||||
struct rxrpc_skb_priv *sp;
|
||||
bool terminal;
|
||||
int ret, ackbit, ack;
|
||||
u32 serial;
|
||||
u8 flags;
|
||||
|
||||
_enter("{%u,%u},,{%u}", call->rx_data_post, call->rx_first_oos, seq);
|
||||
|
||||
sp = rxrpc_skb(skb);
|
||||
ASSERTCMP(sp->call, ==, NULL);
|
||||
flags = sp->hdr.flags;
|
||||
serial = sp->hdr.serial;
|
||||
|
||||
spin_lock(&call->lock);
|
||||
|
||||
@ -192,8 +196,8 @@ static int rxrpc_fast_process_data(struct rxrpc_call *call,
|
||||
sp->call = call;
|
||||
rxrpc_get_call(call);
|
||||
atomic_inc(&call->skb_count);
|
||||
terminal = ((sp->hdr.flags & RXRPC_LAST_PACKET) &&
|
||||
!(sp->hdr.flags & RXRPC_CLIENT_INITIATED));
|
||||
terminal = ((flags & RXRPC_LAST_PACKET) &&
|
||||
!(flags & RXRPC_CLIENT_INITIATED));
|
||||
ret = rxrpc_queue_rcv_skb(call, skb, false, terminal);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOMEM || ret == -ENOBUFS) {
|
||||
@ -205,12 +209,13 @@ static int rxrpc_fast_process_data(struct rxrpc_call *call,
|
||||
}
|
||||
|
||||
skb = NULL;
|
||||
sp = NULL;
|
||||
|
||||
_debug("post #%u", seq);
|
||||
ASSERTCMP(call->rx_data_post, ==, seq);
|
||||
call->rx_data_post++;
|
||||
|
||||
if (sp->hdr.flags & RXRPC_LAST_PACKET)
|
||||
if (flags & RXRPC_LAST_PACKET)
|
||||
set_bit(RXRPC_CALL_RCVD_LAST, &call->flags);
|
||||
|
||||
/* if we've reached an out of sequence packet then we need to drain
|
||||
@ -226,7 +231,7 @@ static int rxrpc_fast_process_data(struct rxrpc_call *call,
|
||||
|
||||
spin_unlock(&call->lock);
|
||||
atomic_inc(&call->ackr_not_idle);
|
||||
rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, sp->hdr.serial, false);
|
||||
rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial, false);
|
||||
_leave(" = 0 [posted]");
|
||||
return 0;
|
||||
|
||||
@ -239,7 +244,7 @@ out:
|
||||
|
||||
discard_and_ack:
|
||||
_debug("discard and ACK packet %p", skb);
|
||||
__rxrpc_propose_ACK(call, ack, sp->hdr.serial, true);
|
||||
__rxrpc_propose_ACK(call, ack, serial, true);
|
||||
discard:
|
||||
spin_unlock(&call->lock);
|
||||
rxrpc_free_skb(skb);
|
||||
@ -247,7 +252,7 @@ discard:
|
||||
return 0;
|
||||
|
||||
enqueue_and_ack:
|
||||
__rxrpc_propose_ACK(call, ack, sp->hdr.serial, true);
|
||||
__rxrpc_propose_ACK(call, ack, serial, true);
|
||||
enqueue_packet:
|
||||
_net("defer skb %p", skb);
|
||||
spin_unlock(&call->lock);
|
||||
@ -567,13 +572,13 @@ done:
|
||||
* post connection-level events to the connection
|
||||
* - this includes challenges, responses and some aborts
|
||||
*/
|
||||
static bool rxrpc_post_packet_to_conn(struct rxrpc_connection *conn,
|
||||
static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
_enter("%p,%p", conn, skb);
|
||||
|
||||
skb_queue_tail(&conn->rx_queue, skb);
|
||||
return rxrpc_queue_conn(conn);
|
||||
rxrpc_queue_conn(conn);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -694,7 +699,6 @@ void rxrpc_data_ready(struct sock *sk)
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
retry_find_conn:
|
||||
conn = rxrpc_find_connection_rcu(local, skb);
|
||||
if (!conn)
|
||||
goto cant_route_call;
|
||||
@ -702,8 +706,7 @@ retry_find_conn:
|
||||
if (sp->hdr.callNumber == 0) {
|
||||
/* Connection-level packet */
|
||||
_debug("CONN %p {%d}", conn, conn->debug_id);
|
||||
if (!rxrpc_post_packet_to_conn(conn, skb))
|
||||
goto retry_find_conn;
|
||||
rxrpc_post_packet_to_conn(conn, skb);
|
||||
} else {
|
||||
/* Call-bound packets are routed by connection channel. */
|
||||
unsigned int channel = sp->hdr.cid & RXRPC_CHANNELMASK;
|
||||
@ -741,6 +744,8 @@ cant_route_call:
|
||||
if (sp->hdr.type != RXRPC_PACKET_TYPE_ABORT) {
|
||||
_debug("reject type %d",sp->hdr.type);
|
||||
rxrpc_reject_packet(local, skb);
|
||||
} else {
|
||||
rxrpc_free_skb(skb);
|
||||
}
|
||||
_leave(" [no call]");
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user