Commit 98dbec0a authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'rxrpc-fixes'



David Howells says:

====================
rxrpc: Fixes for I/O thread conversion/SACK table expansion

Here are some fixes for AF_RXRPC:

 (1) Fix missing unlock in rxrpc's sendmsg.

 (2) Fix (lack of) propagation of security settings to rxrpc_call.

 (3) Fix NULL ptr deref in rxrpc_unuse_local().

 (4) Fix problem with kthread_run() not invoking the I/O thread function if
     the kthread gets stopped first.  Possibly this should actually be
     fixed in the kthread code.

 (5) Fix locking problem as putting a peer (which may be done from RCU) may
     now invoke kthread_stop().

 (6) Fix switched parameters in a couple of trace calls.

 (7) Fix I/O thread's checking for kthread stop to make sure it completes
     all outstanding work before returning so that calls are cleaned up.

 (8) Fix an uninitialised var in the new rxperf test server.

 (9) Fix the return value of rxrpc_new_incoming_call() so that the checks
     on it work correctly.

The patches fix at least one syzbot bug[1] and probably some others that
don't have reproducers[2][3][4].  I think it also fixes another[5], but
that showed another failure during testing that was different to the
original.

There's also an outstanding bug in rxrpc_put_peer()[6] that is fixed by a
combination of several patches in my rxrpc-next branch, but I haven't
included that here.
====================

Tested-by: default avatarMarc Dionne <marc.dionne@auristor.com>
Tested-by: default avatar <kafs-testing+fedora36_64checkkafs-build-164@auristor.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9cd3fd20 31d35a02
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -471,7 +471,7 @@ TRACE_EVENT(rxrpc_peer,
	    TP_STRUCT__entry(
		    __field(unsigned int,	peer		)
		    __field(int,		ref		)
		    __field(int,		why		)
		    __field(enum rxrpc_peer_trace, why		)
			     ),

	    TP_fast_assign(
+4 −4
Original line number Diff line number Diff line
@@ -287,6 +287,7 @@ struct rxrpc_local {
	struct hlist_node	link;
	struct socket		*socket;	/* my UDP socket */
	struct task_struct	*io_thread;
	struct completion	io_thread_ready; /* Indication that the I/O thread started */
	struct rxrpc_sock __rcu	*service;	/* Service(s) listening on this endpoint */
	struct rw_semaphore	defrag_sem;	/* control re-enablement of IP DF bit */
	struct sk_buff_head	rx_queue;	/* Received packets */
@@ -811,7 +812,7 @@ extern struct workqueue_struct *rxrpc_workqueue;
 */
int rxrpc_service_prealloc(struct rxrpc_sock *, gfp_t);
void rxrpc_discard_prealloc(struct rxrpc_sock *);
bool rxrpc_new_incoming_call(struct rxrpc_local *, struct rxrpc_peer *,
int rxrpc_new_incoming_call(struct rxrpc_local *, struct rxrpc_peer *,
			    struct rxrpc_connection *, struct sockaddr_rxrpc *,
			    struct sk_buff *);
void rxrpc_accept_incoming_calls(struct rxrpc_local *);
@@ -1072,7 +1073,6 @@ void rxrpc_destroy_all_peers(struct rxrpc_net *);
struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *, enum rxrpc_peer_trace);
struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *, enum rxrpc_peer_trace);
void rxrpc_put_peer(struct rxrpc_peer *, enum rxrpc_peer_trace);
void rxrpc_put_peer_locked(struct rxrpc_peer *, enum rxrpc_peer_trace);

/*
 * proc.c
+9 −9
Original line number Diff line number Diff line
@@ -326,7 +326,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
 * If we want to report an error, we mark the skb with the packet type and
 * abort code and return false.
 */
bool rxrpc_new_incoming_call(struct rxrpc_local *local,
int rxrpc_new_incoming_call(struct rxrpc_local *local,
			    struct rxrpc_peer *peer,
			    struct rxrpc_connection *conn,
			    struct sockaddr_rxrpc *peer_srx,
@@ -342,7 +342,7 @@ bool rxrpc_new_incoming_call(struct rxrpc_local *local,
	/* Don't set up a call for anything other than the first DATA packet. */
	if (sp->hdr.seq != 1 ||
	    sp->hdr.type != RXRPC_PACKET_TYPE_DATA)
		return true; /* Just discard */
		return 0; /* Just discard */

	rcu_read_lock();

@@ -413,7 +413,7 @@ bool rxrpc_new_incoming_call(struct rxrpc_local *local,
	_leave(" = %p{%d}", call, call->debug_id);
	rxrpc_input_call_event(call, skb);
	rxrpc_put_call(call, rxrpc_call_put_input);
	return true;
	return 0;

unsupported_service:
	trace_rxrpc_abort(0, "INV", sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
@@ -425,10 +425,10 @@ bool rxrpc_new_incoming_call(struct rxrpc_local *local,
reject:
	rcu_read_unlock();
	_leave(" = f [%u]", skb->mark);
	return false;
	return -EPROTO;
discard:
	rcu_read_unlock();
	return true;
	return 0;
}

/*
+1 −0
Original line number Diff line number Diff line
@@ -217,6 +217,7 @@ static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx,
	call->tx_total_len	= p->tx_total_len;
	call->key		= key_get(cp->key);
	call->local		= rxrpc_get_local(cp->local, rxrpc_local_get_call);
	call->security_level	= cp->security_level;
	if (p->kernel)
		__set_bit(RXRPC_CALL_KERNEL, &call->flags);
	if (cp->upgrade)
+0 −2
Original line number Diff line number Diff line
@@ -551,8 +551,6 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
	call->conn	= rxrpc_get_connection(conn, rxrpc_conn_get_activate_call);
	call->cid	= conn->proto.cid | channel;
	call->call_id	= call_id;
	call->security	= conn->security;
	call->security_ix = conn->security_ix;
	call->dest_srx.srx_service = conn->service_id;

	trace_rxrpc_connect_call(call);
Loading