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


David Howells says:

====================
rxrpc: Miscellaneous fixes

Here are some miscellaneous rxrpc fixes:

 (1) Fix the xdr encoding of the contents read from an rxrpc key.

 (2) Fix a BUG() for a unsupported encoding type.

 (3) Fix missing _bh lock annotations.

 (4) Fix acceptance handling for an incoming call where the incoming call
     is encrypted.

 (5) The server token keyring isn't network namespaced - it belongs to the
     server, so there's no need.  Namespacing it means that request_key()
     fails to find it.

 (6) Fix a leak of the server keyring.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 86bccd03 38b1dc47
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -51,11 +51,11 @@ enum rxrpc_cmsg_type {
	RXRPC_BUSY		= 6,	/* -r: server busy received [terminal] */
	RXRPC_LOCAL_ERROR	= 7,	/* -r: local error generated [terminal] */
	RXRPC_NEW_CALL		= 8,	/* -r: [Service] new incoming call notification */
	RXRPC_ACCEPT		= 9,	/* s-: [Service] accept request */
	RXRPC_EXCLUSIVE_CALL	= 10,	/* s-: Call should be on exclusive connection */
	RXRPC_UPGRADE_SERVICE	= 11,	/* s-: Request service upgrade for client call */
	RXRPC_TX_LENGTH		= 12,	/* s-: Total length of Tx data */
	RXRPC_SET_CALL_TIMEOUT	= 13,	/* s-: Set one or more call timeouts */
	RXRPC_CHARGE_ACCEPT	= 14,	/* s-: Charge the accept pool with a user call ID */
	RXRPC__SUPPORTED
};

+2 −5
Original line number Diff line number Diff line
@@ -518,7 +518,6 @@ enum rxrpc_call_state {
	RXRPC_CALL_CLIENT_RECV_REPLY,	/* - client receiving reply phase */
	RXRPC_CALL_SERVER_PREALLOC,	/* - service preallocation */
	RXRPC_CALL_SERVER_SECURING,	/* - server securing request connection */
	RXRPC_CALL_SERVER_ACCEPTING,	/* - server accepting request */
	RXRPC_CALL_SERVER_RECV_REQUEST,	/* - server receiving request */
	RXRPC_CALL_SERVER_ACK_REQUEST,	/* - server pending ACK of request */
	RXRPC_CALL_SERVER_SEND_REPLY,	/* - server sending reply */
@@ -714,8 +713,8 @@ struct rxrpc_ack_summary {
enum rxrpc_command {
	RXRPC_CMD_SEND_DATA,		/* send data message */
	RXRPC_CMD_SEND_ABORT,		/* request abort generation */
	RXRPC_CMD_ACCEPT,		/* [server] accept incoming call */
	RXRPC_CMD_REJECT_BUSY,		/* [server] reject a call as busy */
	RXRPC_CMD_CHARGE_ACCEPT,	/* [server] charge accept preallocation */
};

struct rxrpc_call_params {
@@ -755,9 +754,7 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *,
					   struct rxrpc_sock *,
					   struct sk_buff *);
void rxrpc_accept_incoming_calls(struct rxrpc_local *);
struct rxrpc_call *rxrpc_accept_call(struct rxrpc_sock *, unsigned long,
				     rxrpc_notify_rx_t);
int rxrpc_reject_call(struct rxrpc_sock *);
int rxrpc_user_charge_accept(struct rxrpc_sock *, unsigned long);

/*
 * call_event.c
+38 −225
Original line number Diff line number Diff line
@@ -39,8 +39,9 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
				      unsigned int debug_id)
{
	const void *here = __builtin_return_address(0);
	struct rxrpc_call *call;
	struct rxrpc_call *call, *xcall;
	struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk));
	struct rb_node *parent, **pp;
	int max, tmp;
	unsigned int size = RXRPC_BACKLOG_MAX;
	unsigned int head, tail, call_head, call_tail;
@@ -94,7 +95,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
	}

	/* Now it gets complicated, because calls get registered with the
	 * socket here, particularly if a user ID is preassigned by the user.
	 * socket here, with a user ID preassigned by the user.
	 */
	call = rxrpc_alloc_call(rx, gfp, debug_id);
	if (!call)
@@ -107,9 +108,6 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
			 here, (const void *)user_call_ID);

	write_lock(&rx->call_lock);
	if (user_attach_call) {
		struct rxrpc_call *xcall;
		struct rb_node *parent, **pp;

	/* Check the user ID isn't already in use */
	pp = &rx->calls.rb_node;
@@ -127,13 +125,15 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,

	call->user_call_ID = user_call_ID;
	call->notify_rx = notify_rx;
	if (user_attach_call) {
		rxrpc_get_call(call, rxrpc_call_got_kernel);
		user_attach_call(call, user_call_ID);
	}

	rxrpc_get_call(call, rxrpc_call_got_userid);
	rb_link_node(&call->sock_node, parent, pp);
	rb_insert_color(&call->sock_node, &rx->calls);
	set_bit(RXRPC_CALL_HAS_USERID, &call->flags);
	}

	list_add(&call->sock_link, &rx->sock_calls);

@@ -157,11 +157,8 @@ id_in_use:
}

/*
 * Preallocate sufficient service connections, calls and peers to cover the
 * entire backlog of a socket.  When a new call comes in, if we don't have
 * sufficient of each available, the call gets rejected as busy or ignored.
 *
 * The backlog is replenished when a connection is accepted or rejected.
 * Allocate the preallocation buffers for incoming service calls.  These must
 * be charged manually.
 */
int rxrpc_service_prealloc(struct rxrpc_sock *rx, gfp_t gfp)
{
@@ -174,13 +171,6 @@ int rxrpc_service_prealloc(struct rxrpc_sock *rx, gfp_t gfp)
		rx->backlog = b;
	}

	if (rx->discard_new_call)
		return 0;

	while (rxrpc_service_prealloc_one(rx, b, NULL, NULL, 0, gfp,
					  atomic_inc_return(&rxrpc_debug_id)) == 0)
		;

	return 0;
}

@@ -333,6 +323,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
	rxrpc_see_call(call);
	call->conn = conn;
	call->security = conn->security;
	call->security_ix = conn->security_ix;
	call->peer = rxrpc_get_peer(conn->params.peer);
	call->cong_cwnd = call->peer->cong_cwnd;
	return call;
@@ -402,8 +393,6 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,

	if (rx->notify_new_call)
		rx->notify_new_call(&rx->sk, call, call->user_call_ID);
	else
		sk_acceptq_added(&rx->sk);

	spin_lock(&conn->state_lock);
	switch (conn->state) {
@@ -415,12 +404,8 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,

	case RXRPC_CONN_SERVICE:
		write_lock(&call->state_lock);
		if (call->state < RXRPC_CALL_COMPLETE) {
			if (rx->discard_new_call)
		if (call->state < RXRPC_CALL_COMPLETE)
			call->state = RXRPC_CALL_SERVER_RECV_REQUEST;
			else
				call->state = RXRPC_CALL_SERVER_ACCEPTING;
		}
		write_unlock(&call->state_lock);
		break;

@@ -440,9 +425,6 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,

	rxrpc_send_ping(call, skb);

	if (call->state == RXRPC_CALL_SERVER_ACCEPTING)
		rxrpc_notify_socket(call);

	/* We have to discard the prealloc queue's ref here and rely on a
	 * combination of the RCU read lock and refs held either by the socket
	 * (recvmsg queue, to-be-accepted queue or user ID tree) or the kernel
@@ -460,187 +442,18 @@ no_call:
}

/*
 * handle acceptance of a call by userspace
 * - assign the user call ID to the call at the front of the queue
 * - called with the socket locked.
 */
struct rxrpc_call *rxrpc_accept_call(struct rxrpc_sock *rx,
				     unsigned long user_call_ID,
				     rxrpc_notify_rx_t notify_rx)
	__releases(&rx->sk.sk_lock.slock)
	__acquires(call->user_mutex)
{
	struct rxrpc_call *call;
	struct rb_node *parent, **pp;
	int ret;

	_enter(",%lx", user_call_ID);

	ASSERT(!irqs_disabled());

	write_lock(&rx->call_lock);

	if (list_empty(&rx->to_be_accepted)) {
		write_unlock(&rx->call_lock);
		release_sock(&rx->sk);
		kleave(" = -ENODATA [empty]");
		return ERR_PTR(-ENODATA);
	}

	/* check the user ID isn't already in use */
	pp = &rx->calls.rb_node;
	parent = NULL;
	while (*pp) {
		parent = *pp;
		call = rb_entry(parent, struct rxrpc_call, sock_node);

		if (user_call_ID < call->user_call_ID)
			pp = &(*pp)->rb_left;
		else if (user_call_ID > call->user_call_ID)
			pp = &(*pp)->rb_right;
		else
			goto id_in_use;
	}

	/* Dequeue the first call and check it's still valid.  We gain
	 * responsibility for the queue's reference.
	 */
	call = list_entry(rx->to_be_accepted.next,
			  struct rxrpc_call, accept_link);
	write_unlock(&rx->call_lock);

	/* We need to gain the mutex from the interrupt handler without
	 * upsetting lockdep, so we have to release it there and take it here.
	 * We are, however, still holding the socket lock, so other accepts
	 * must wait for us and no one can add the user ID behind our backs.
	 */
	if (mutex_lock_interruptible(&call->user_mutex) < 0) {
		release_sock(&rx->sk);
		kleave(" = -ERESTARTSYS");
		return ERR_PTR(-ERESTARTSYS);
	}

	write_lock(&rx->call_lock);
	list_del_init(&call->accept_link);
	sk_acceptq_removed(&rx->sk);
	rxrpc_see_call(call);

	/* Find the user ID insertion point. */
	pp = &rx->calls.rb_node;
	parent = NULL;
	while (*pp) {
		parent = *pp;
		call = rb_entry(parent, struct rxrpc_call, sock_node);

		if (user_call_ID < call->user_call_ID)
			pp = &(*pp)->rb_left;
		else if (user_call_ID > call->user_call_ID)
			pp = &(*pp)->rb_right;
		else
			BUG();
	}

	write_lock_bh(&call->state_lock);
	switch (call->state) {
	case RXRPC_CALL_SERVER_ACCEPTING:
		call->state = RXRPC_CALL_SERVER_RECV_REQUEST;
		break;
	case RXRPC_CALL_COMPLETE:
		ret = call->error;
		goto out_release;
	default:
		BUG();
	}

	/* formalise the acceptance */
	call->notify_rx = notify_rx;
	call->user_call_ID = user_call_ID;
	rxrpc_get_call(call, rxrpc_call_got_userid);
	rb_link_node(&call->sock_node, parent, pp);
	rb_insert_color(&call->sock_node, &rx->calls);
	if (test_and_set_bit(RXRPC_CALL_HAS_USERID, &call->flags))
		BUG();

	write_unlock_bh(&call->state_lock);
	write_unlock(&rx->call_lock);
	rxrpc_notify_socket(call);
	rxrpc_service_prealloc(rx, GFP_KERNEL);
	release_sock(&rx->sk);
	_leave(" = %p{%d}", call, call->debug_id);
	return call;

out_release:
	_debug("release %p", call);
	write_unlock_bh(&call->state_lock);
	write_unlock(&rx->call_lock);
	rxrpc_release_call(rx, call);
	rxrpc_put_call(call, rxrpc_call_put);
	goto out;

id_in_use:
	ret = -EBADSLT;
	write_unlock(&rx->call_lock);
out:
	rxrpc_service_prealloc(rx, GFP_KERNEL);
	release_sock(&rx->sk);
	_leave(" = %d", ret);
	return ERR_PTR(ret);
}

/*
 * Handle rejection of a call by userspace
 * - reject the call at the front of the queue
 * Charge up socket with preallocated calls, attaching user call IDs.
 */
int rxrpc_reject_call(struct rxrpc_sock *rx)
int rxrpc_user_charge_accept(struct rxrpc_sock *rx, unsigned long user_call_ID)
{
	struct rxrpc_call *call;
	bool abort = false;
	int ret;

	_enter("");

	ASSERT(!irqs_disabled());

	write_lock(&rx->call_lock);

	if (list_empty(&rx->to_be_accepted)) {
		write_unlock(&rx->call_lock);
		return -ENODATA;
	}

	/* Dequeue the first call and check it's still valid.  We gain
	 * responsibility for the queue's reference.
	 */
	call = list_entry(rx->to_be_accepted.next,
			  struct rxrpc_call, accept_link);
	list_del_init(&call->accept_link);
	sk_acceptq_removed(&rx->sk);
	rxrpc_see_call(call);
	struct rxrpc_backlog *b = rx->backlog;

	write_lock_bh(&call->state_lock);
	switch (call->state) {
	case RXRPC_CALL_SERVER_ACCEPTING:
		__rxrpc_abort_call("REJ", call, 1, RX_USER_ABORT, -ECONNABORTED);
		abort = true;
		fallthrough;
	case RXRPC_CALL_COMPLETE:
		ret = call->error;
		goto out_discard;
	default:
		BUG();
	}
	if (rx->sk.sk_state == RXRPC_CLOSE)
		return -ESHUTDOWN;

out_discard:
	write_unlock_bh(&call->state_lock);
	write_unlock(&rx->call_lock);
	if (abort) {
		rxrpc_send_abort_packet(call);
		rxrpc_release_call(rx, call);
		rxrpc_put_call(call, rxrpc_call_put);
	}
	rxrpc_service_prealloc(rx, GFP_KERNEL);
	_leave(" = %d", ret);
	return ret;
	return rxrpc_service_prealloc_one(rx, b, NULL, NULL, user_call_ID,
					  GFP_KERNEL,
					  atomic_inc_return(&rxrpc_debug_id));
}

/*
+1 −4
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ const char *const rxrpc_call_states[NR__RXRPC_CALL_STATES] = {
	[RXRPC_CALL_CLIENT_RECV_REPLY]		= "ClRcvRpl",
	[RXRPC_CALL_SERVER_PREALLOC]		= "SvPrealc",
	[RXRPC_CALL_SERVER_SECURING]		= "SvSecure",
	[RXRPC_CALL_SERVER_ACCEPTING]		= "SvAccept",
	[RXRPC_CALL_SERVER_RECV_REQUEST]	= "SvRcvReq",
	[RXRPC_CALL_SERVER_ACK_REQUEST]		= "SvAckReq",
	[RXRPC_CALL_SERVER_SEND_REPLY]		= "SvSndRpl",
@@ -352,8 +351,6 @@ void rxrpc_incoming_call(struct rxrpc_sock *rx,
	call->call_id		= sp->hdr.callNumber;
	call->service_id	= sp->hdr.serviceId;
	call->cid		= sp->hdr.cid;
	call->state		= RXRPC_CALL_SERVER_ACCEPTING;
	if (sp->hdr.securityIndex > 0)
	call->state		= RXRPC_CALL_SERVER_SECURING;
	call->cong_tstamp	= skb->tstamp;

+4 −4
Original line number Diff line number Diff line
@@ -269,7 +269,7 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
	if (call) {
		write_lock_bh(&call->state_lock);
		if (call->state == RXRPC_CALL_SERVER_SECURING) {
			call->state = RXRPC_CALL_SERVER_ACCEPTING;
			call->state = RXRPC_CALL_SERVER_RECV_REQUEST;
			rxrpc_notify_socket(call);
		}
		write_unlock_bh(&call->state_lock);
@@ -340,18 +340,18 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
			return ret;

		spin_lock(&conn->channel_lock);
		spin_lock(&conn->state_lock);
		spin_lock_bh(&conn->state_lock);

		if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) {
			conn->state = RXRPC_CONN_SERVICE;
			spin_unlock(&conn->state_lock);
			spin_unlock_bh(&conn->state_lock);
			for (loop = 0; loop < RXRPC_MAXCALLS; loop++)
				rxrpc_call_is_secure(
					rcu_dereference_protected(
						conn->channels[loop].call,
						lockdep_is_held(&conn->channel_lock)));
		} else {
			spin_unlock(&conn->state_lock);
			spin_unlock_bh(&conn->state_lock);
		}

		spin_unlock(&conn->channel_lock);
Loading