Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fb46f6ee authored by David Howells's avatar David Howells
Browse files

rxrpc: Trace protocol errors in received packets



Add a tracepoint (rxrpc_rx_proto) to record protocol errors in received
packets.  The following changes are made:

 (1) Add a function, __rxrpc_abort_eproto(), to note a protocol error on a
     call and mark the call aborted.  This is wrapped by
     rxrpc_abort_eproto() that makes the why string usable in trace.

 (2) Add trace_rxrpc_rx_proto() or rxrpc_abort_eproto() to protocol error
     generation points, replacing rxrpc_abort_call() with the latter.

 (3) Only send an abort packet in rxkad_verify_packet*() if we actually
     managed to abort the call.

Note that a trace event is also emitted if a kernel user (e.g. afs) tries
to send data through a call when it's not in the transmission phase, though
it's not technically a receive event.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent ef68622d
Loading
Loading
Loading
Loading
+24 −0
Original line number Original line Diff line number Diff line
@@ -1087,6 +1087,30 @@ TRACE_EVENT(rxrpc_improper_term,
		      __entry->abort_code)
		      __entry->abort_code)
	    );
	    );


TRACE_EVENT(rxrpc_rx_eproto,
	    TP_PROTO(struct rxrpc_call *call, rxrpc_serial_t serial,
		     const char *why),

	    TP_ARGS(call, serial, why),

	    TP_STRUCT__entry(
		    __field(struct rxrpc_call *,	call		)
		    __field(rxrpc_serial_t,		serial		)
		    __field(const char *,		why		)
			     ),

	    TP_fast_assign(
		    __entry->call = call;
		    __entry->serial = serial;
		    __entry->why = why;
			   ),

	    TP_printk("c=%p EPROTO %08x %s",
		      __entry->call,
		      __entry->serial,
		      __entry->why)
	    );

#endif /* _TRACE_RXRPC_H */
#endif /* _TRACE_RXRPC_H */


/* This part must be outside protection */
/* This part must be outside protection */
+19 −0
Original line number Original line Diff line number Diff line
@@ -739,6 +739,25 @@ static inline bool rxrpc_abort_call(const char *why, struct rxrpc_call *call,
	return ret;
	return ret;
}
}


/*
 * Abort a call due to a protocol error.
 */
static inline bool __rxrpc_abort_eproto(struct rxrpc_call *call,
					struct sk_buff *skb,
					const char *eproto_why,
					const char *why,
					u32 abort_code)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);

	trace_rxrpc_rx_eproto(call, sp->hdr.serial, eproto_why);
	return rxrpc_abort_call(why, call, sp->hdr.seq, abort_code, -EPROTO);
}

#define rxrpc_abort_eproto(call, skb, eproto_why, abort_why, abort_code) \
	__rxrpc_abort_eproto((call), (skb), tracepoint_string(eproto_why), \
			     (abort_why), (abort_code))

/*
/*
 * conn_client.c
 * conn_client.c
 */
 */
+6 −3
Original line number Original line Diff line number Diff line
@@ -281,8 +281,11 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,


	case RXRPC_PACKET_TYPE_ABORT:
	case RXRPC_PACKET_TYPE_ABORT:
		if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
		if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
				  &wtmp, sizeof(wtmp)) < 0)
				  &wtmp, sizeof(wtmp)) < 0) {
			trace_rxrpc_rx_eproto(NULL, sp->hdr.serial,
					      tracepoint_string("bad_abort"));
			return -EPROTO;
			return -EPROTO;
		}
		abort_code = ntohl(wtmp);
		abort_code = ntohl(wtmp);
		_proto("Rx ABORT %%%u { ac=%d }", sp->hdr.serial, abort_code);
		_proto("Rx ABORT %%%u { ac=%d }", sp->hdr.serial, abort_code);


@@ -327,7 +330,8 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
		return 0;
		return 0;


	default:
	default:
		_leave(" = -EPROTO [%u]", sp->hdr.type);
		trace_rxrpc_rx_eproto(NULL, sp->hdr.serial,
				      tracepoint_string("bad_conn_pkt"));
		return -EPROTO;
		return -EPROTO;
	}
	}
}
}
@@ -422,6 +426,5 @@ void rxrpc_process_connection(struct work_struct *work)
	if (rxrpc_abort_connection(conn, ret, abort_code) < 0)
	if (rxrpc_abort_connection(conn, ret, abort_code) < 0)
		goto requeue_and_leave;
		goto requeue_and_leave;
	rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
	rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
	_leave(" [EPROTO]");
	goto out;
	goto out;
}
}
+4 −1
Original line number Original line Diff line number Diff line
@@ -1017,8 +1017,11 @@ int rxrpc_extract_header(struct rxrpc_skb_priv *sp, struct sk_buff *skb)
	struct rxrpc_wire_header whdr;
	struct rxrpc_wire_header whdr;


	/* dig out the RxRPC connection details */
	/* dig out the RxRPC connection details */
	if (skb_copy_bits(skb, 0, &whdr, sizeof(whdr)) < 0)
	if (skb_copy_bits(skb, 0, &whdr, sizeof(whdr)) < 0) {
		trace_rxrpc_rx_eproto(NULL, sp->hdr.serial,
				      tracepoint_string("bad_hdr"));
		return -EBADMSG;
		return -EBADMSG;
	}


	memset(sp, 0, sizeof(*sp));
	memset(sp, 0, sizeof(*sp));
	sp->hdr.epoch		= ntohl(whdr.epoch);
	sp->hdr.epoch		= ntohl(whdr.epoch);
+8 −2
Original line number Original line Diff line number Diff line
@@ -46,7 +46,10 @@ static int none_respond_to_challenge(struct rxrpc_connection *conn,
				     struct sk_buff *skb,
				     struct sk_buff *skb,
				     u32 *_abort_code)
				     u32 *_abort_code)
{
{
	*_abort_code = RX_PROTOCOL_ERROR;
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);

	trace_rxrpc_rx_eproto(NULL, sp->hdr.serial,
			      tracepoint_string("chall_none"));
	return -EPROTO;
	return -EPROTO;
}
}


@@ -54,7 +57,10 @@ static int none_verify_response(struct rxrpc_connection *conn,
				struct sk_buff *skb,
				struct sk_buff *skb,
				u32 *_abort_code)
				u32 *_abort_code)
{
{
	*_abort_code = RX_PROTOCOL_ERROR;
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);

	trace_rxrpc_rx_eproto(NULL, sp->hdr.serial,
			      tracepoint_string("resp_none"));
	return -EPROTO;
	return -EPROTO;
}
}


Loading