Commit 5a42976d authored by David Howells's avatar David Howells

rxrpc: Add tracepoint for working out where aborts happen

Add a tracepoint for working out where local aborts happen.  Each
tracepoint call is labelled with a 3-letter code so that they can be
distinguished - and the DATA sequence number is added too where available.

rxrpc_kernel_abort_call() also takes a 3-letter code so that AFS can
indicate the circumstances when it aborts a call.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent e8d6bbb0
...@@ -377,7 +377,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp, ...@@ -377,7 +377,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
return wait_mode->wait(call); return wait_mode->wait(call);
error_do_abort: error_do_abort:
rxrpc_kernel_abort_call(afs_socket, rxcall, RX_USER_ABORT); rxrpc_kernel_abort_call(afs_socket, rxcall, RX_USER_ABORT, -ret, "KSD");
error_kill_call: error_kill_call:
afs_end_call(call); afs_end_call(call);
_leave(" = %d", ret); _leave(" = %d", ret);
...@@ -425,12 +425,12 @@ static void afs_deliver_to_call(struct afs_call *call) ...@@ -425,12 +425,12 @@ static void afs_deliver_to_call(struct afs_call *call)
case -ENOTCONN: case -ENOTCONN:
abort_code = RX_CALL_DEAD; abort_code = RX_CALL_DEAD;
rxrpc_kernel_abort_call(afs_socket, call->rxcall, rxrpc_kernel_abort_call(afs_socket, call->rxcall,
abort_code); abort_code, -ret, "KNC");
goto do_abort; goto do_abort;
case -ENOTSUPP: case -ENOTSUPP:
abort_code = RX_INVALID_OPERATION; abort_code = RX_INVALID_OPERATION;
rxrpc_kernel_abort_call(afs_socket, call->rxcall, rxrpc_kernel_abort_call(afs_socket, call->rxcall,
abort_code); abort_code, -ret, "KIV");
goto do_abort; goto do_abort;
case -ENODATA: case -ENODATA:
case -EBADMSG: case -EBADMSG:
...@@ -440,7 +440,7 @@ static void afs_deliver_to_call(struct afs_call *call) ...@@ -440,7 +440,7 @@ static void afs_deliver_to_call(struct afs_call *call)
if (call->state != AFS_CALL_AWAIT_REPLY) if (call->state != AFS_CALL_AWAIT_REPLY)
abort_code = RXGEN_SS_UNMARSHAL; abort_code = RXGEN_SS_UNMARSHAL;
rxrpc_kernel_abort_call(afs_socket, call->rxcall, rxrpc_kernel_abort_call(afs_socket, call->rxcall,
abort_code); abort_code, EBADMSG, "KUM");
goto do_abort; goto do_abort;
} }
} }
...@@ -463,6 +463,7 @@ static void afs_deliver_to_call(struct afs_call *call) ...@@ -463,6 +463,7 @@ static void afs_deliver_to_call(struct afs_call *call)
*/ */
static int afs_wait_for_call_to_complete(struct afs_call *call) static int afs_wait_for_call_to_complete(struct afs_call *call)
{ {
const char *abort_why;
int ret; int ret;
DECLARE_WAITQUEUE(myself, current); DECLARE_WAITQUEUE(myself, current);
...@@ -481,9 +482,11 @@ static int afs_wait_for_call_to_complete(struct afs_call *call) ...@@ -481,9 +482,11 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
continue; continue;
} }
abort_why = "KWC";
ret = call->error; ret = call->error;
if (call->state == AFS_CALL_COMPLETE) if (call->state == AFS_CALL_COMPLETE)
break; break;
abort_why = "KWI";
ret = -EINTR; ret = -EINTR;
if (signal_pending(current)) if (signal_pending(current))
break; break;
...@@ -497,7 +500,7 @@ static int afs_wait_for_call_to_complete(struct afs_call *call) ...@@ -497,7 +500,7 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
if (call->state < AFS_CALL_COMPLETE) { if (call->state < AFS_CALL_COMPLETE) {
_debug("call incomplete"); _debug("call incomplete");
rxrpc_kernel_abort_call(afs_socket, call->rxcall, rxrpc_kernel_abort_call(afs_socket, call->rxcall,
RX_CALL_DEAD); RX_CALL_DEAD, -ret, abort_why);
} }
_debug("call complete"); _debug("call complete");
...@@ -695,7 +698,7 @@ void afs_send_empty_reply(struct afs_call *call) ...@@ -695,7 +698,7 @@ void afs_send_empty_reply(struct afs_call *call)
case -ENOMEM: case -ENOMEM:
_debug("oom"); _debug("oom");
rxrpc_kernel_abort_call(afs_socket, call->rxcall, rxrpc_kernel_abort_call(afs_socket, call->rxcall,
RX_USER_ABORT); RX_USER_ABORT, ENOMEM, "KOO");
default: default:
afs_end_call(call); afs_end_call(call);
_leave(" [error]"); _leave(" [error]");
...@@ -734,7 +737,7 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len) ...@@ -734,7 +737,7 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
if (n == -ENOMEM) { if (n == -ENOMEM) {
_debug("oom"); _debug("oom");
rxrpc_kernel_abort_call(afs_socket, call->rxcall, rxrpc_kernel_abort_call(afs_socket, call->rxcall,
RX_USER_ABORT); RX_USER_ABORT, ENOMEM, "KOO");
} }
afs_end_call(call); afs_end_call(call);
_leave(" [error]"); _leave(" [error]");
......
...@@ -35,7 +35,8 @@ int rxrpc_kernel_send_data(struct socket *, struct rxrpc_call *, ...@@ -35,7 +35,8 @@ int rxrpc_kernel_send_data(struct socket *, struct rxrpc_call *,
struct msghdr *, size_t); struct msghdr *, size_t);
int rxrpc_kernel_recv_data(struct socket *, struct rxrpc_call *, int rxrpc_kernel_recv_data(struct socket *, struct rxrpc_call *,
void *, size_t, size_t *, bool, u32 *); void *, size_t, size_t *, bool, u32 *);
void rxrpc_kernel_abort_call(struct socket *, struct rxrpc_call *, u32); void rxrpc_kernel_abort_call(struct socket *, struct rxrpc_call *,
u32, int, const char *);
void rxrpc_kernel_end_call(struct socket *, struct rxrpc_call *); void rxrpc_kernel_end_call(struct socket *, struct rxrpc_call *);
struct rxrpc_call *rxrpc_kernel_accept_call(struct socket *, unsigned long, struct rxrpc_call *rxrpc_kernel_accept_call(struct socket *, unsigned long,
rxrpc_notify_rx_t); rxrpc_notify_rx_t);
......
...@@ -84,6 +84,35 @@ TRACE_EVENT(rxrpc_skb, ...@@ -84,6 +84,35 @@ TRACE_EVENT(rxrpc_skb,
__entry->where) __entry->where)
); );
TRACE_EVENT(rxrpc_abort,
TP_PROTO(const char *why, u32 cid, u32 call_id, rxrpc_seq_t seq,
int abort_code, int error),
TP_ARGS(why, cid, call_id, seq, abort_code, error),
TP_STRUCT__entry(
__array(char, why, 4 )
__field(u32, cid )
__field(u32, call_id )
__field(rxrpc_seq_t, seq )
__field(int, abort_code )
__field(int, error )
),
TP_fast_assign(
memcpy(__entry->why, why, 4);
__entry->cid = cid;
__entry->call_id = call_id;
__entry->abort_code = abort_code;
__entry->error = error;
__entry->seq = seq;
),
TP_printk("%08x:%08x s=%u a=%d e=%d %s",
__entry->cid, __entry->call_id, __entry->seq,
__entry->abort_code, __entry->error, __entry->why)
);
#endif /* _TRACE_RXRPC_H */ #endif /* _TRACE_RXRPC_H */
/* This part must be outside protection */ /* This part must be outside protection */
......
...@@ -155,7 +155,8 @@ struct rxrpc_security { ...@@ -155,7 +155,8 @@ struct rxrpc_security {
void *); void *);
/* verify the security on a received packet */ /* verify the security on a received packet */
int (*verify_packet)(struct rxrpc_call *, struct sk_buff *, u32 *); int (*verify_packet)(struct rxrpc_call *, struct sk_buff *,
rxrpc_seq_t, u16);
/* issue a challenge */ /* issue a challenge */
int (*issue_challenge)(struct rxrpc_connection *); int (*issue_challenge)(struct rxrpc_connection *);
...@@ -637,9 +638,12 @@ static inline bool rxrpc_call_completed(struct rxrpc_call *call) ...@@ -637,9 +638,12 @@ static inline bool rxrpc_call_completed(struct rxrpc_call *call)
/* /*
* Record that a call is locally aborted. * Record that a call is locally aborted.
*/ */
static inline bool __rxrpc_abort_call(struct rxrpc_call *call, static inline bool __rxrpc_abort_call(const char *why, struct rxrpc_call *call,
rxrpc_seq_t seq,
u32 abort_code, int error) u32 abort_code, int error)
{ {
trace_rxrpc_abort(why, call->cid, call->call_id, seq,
abort_code, error);
if (__rxrpc_set_call_completion(call, if (__rxrpc_set_call_completion(call,
RXRPC_CALL_LOCALLY_ABORTED, RXRPC_CALL_LOCALLY_ABORTED,
abort_code, error)) { abort_code, error)) {
...@@ -649,13 +653,13 @@ static inline bool __rxrpc_abort_call(struct rxrpc_call *call, ...@@ -649,13 +653,13 @@ static inline bool __rxrpc_abort_call(struct rxrpc_call *call,
return false; return false;
} }
static inline bool rxrpc_abort_call(struct rxrpc_call *call, static inline bool rxrpc_abort_call(const char *why, struct rxrpc_call *call,
u32 abort_code, int error) rxrpc_seq_t seq, u32 abort_code, int error)
{ {
bool ret; bool ret;
write_lock_bh(&call->state_lock); write_lock_bh(&call->state_lock);
ret = __rxrpc_abort_call(call, abort_code, error); ret = __rxrpc_abort_call(why, call, seq, abort_code, error);
write_unlock_bh(&call->state_lock); write_unlock_bh(&call->state_lock);
return ret; return ret;
} }
......
...@@ -598,7 +598,8 @@ static int rxrpc_process_rx_queue(struct rxrpc_call *call, ...@@ -598,7 +598,8 @@ static int rxrpc_process_rx_queue(struct rxrpc_call *call,
/* secured packets must be verified and possibly decrypted */ /* secured packets must be verified and possibly decrypted */
if (call->conn->security->verify_packet(call, skb, if (call->conn->security->verify_packet(call, skb,
_abort_code) < 0) sp->hdr.seq,
sp->hdr.cksum) < 0)
goto protocol_error; goto protocol_error;
rxrpc_insert_oos_packet(call, skb); rxrpc_insert_oos_packet(call, skb);
...@@ -982,7 +983,7 @@ void rxrpc_process_call(struct work_struct *work) ...@@ -982,7 +983,7 @@ void rxrpc_process_call(struct work_struct *work)
} }
if (test_bit(RXRPC_CALL_EV_LIFE_TIMER, &call->events)) { if (test_bit(RXRPC_CALL_EV_LIFE_TIMER, &call->events)) {
rxrpc_abort_call(call, RX_CALL_TIMEOUT, ETIME); rxrpc_abort_call("EXP", call, 0, RX_CALL_TIMEOUT, ETIME);
_debug("post timeout"); _debug("post timeout");
if (rxrpc_post_message(call, RXRPC_SKB_MARK_LOCAL_ERROR, if (rxrpc_post_message(call, RXRPC_SKB_MARK_LOCAL_ERROR,
...@@ -1005,7 +1006,7 @@ void rxrpc_process_call(struct work_struct *work) ...@@ -1005,7 +1006,7 @@ void rxrpc_process_call(struct work_struct *work)
case -EKEYEXPIRED: case -EKEYEXPIRED:
case -EKEYREJECTED: case -EKEYREJECTED:
case -EPROTO: case -EPROTO:
rxrpc_abort_call(call, abort_code, -ret); rxrpc_abort_call("PRO", call, 0, abort_code, -ret);
goto kill_ACKs; goto kill_ACKs;
} }
} }
......
...@@ -563,7 +563,7 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) ...@@ -563,7 +563,7 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
if (call->state < RXRPC_CALL_COMPLETE) { if (call->state < RXRPC_CALL_COMPLETE) {
_debug("+++ ABORTING STATE %d +++\n", call->state); _debug("+++ ABORTING STATE %d +++\n", call->state);
__rxrpc_abort_call(call, RX_CALL_DEAD, ECONNRESET); __rxrpc_abort_call("SKT", call, 0, RX_CALL_DEAD, ECONNRESET);
clear_bit(RXRPC_CALL_EV_ACK_FINAL, &call->events); clear_bit(RXRPC_CALL_EV_ACK_FINAL, &call->events);
rxrpc_send_call_packet(call, RXRPC_PACKET_TYPE_ABORT); rxrpc_send_call_packet(call, RXRPC_PACKET_TYPE_ABORT);
} }
......
...@@ -158,6 +158,11 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn, ...@@ -158,6 +158,11 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn,
lockdep_is_held(&conn->channel_lock)); lockdep_is_held(&conn->channel_lock));
if (call) { if (call) {
rxrpc_see_call(call); rxrpc_see_call(call);
if (compl == RXRPC_CALL_LOCALLY_ABORTED)
trace_rxrpc_abort("CON", call->cid,
call->call_id, 0,
abort_code, error);
write_lock_bh(&call->state_lock); write_lock_bh(&call->state_lock);
if (rxrpc_set_call_completion(call, compl, abort_code, if (rxrpc_set_call_completion(call, compl, abort_code,
error)) { error)) {
...@@ -167,6 +172,7 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn, ...@@ -167,6 +172,7 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn,
write_unlock_bh(&call->state_lock); write_unlock_bh(&call->state_lock);
if (queue) if (queue)
rxrpc_queue_call(call); rxrpc_queue_call(call);
} }
} }
......
...@@ -429,7 +429,7 @@ void rxrpc_fast_process_packet(struct rxrpc_call *call, struct sk_buff *skb) ...@@ -429,7 +429,7 @@ void rxrpc_fast_process_packet(struct rxrpc_call *call, struct sk_buff *skb)
_debug("protocol error"); _debug("protocol error");
write_lock_bh(&call->state_lock); write_lock_bh(&call->state_lock);
protocol_error_locked: protocol_error_locked:
if (__rxrpc_abort_call(call, RX_PROTOCOL_ERROR, EPROTO)) if (__rxrpc_abort_call("FPR", call, 0, RX_PROTOCOL_ERROR, EPROTO))
rxrpc_queue_call(call); rxrpc_queue_call(call);
free_packet_unlock: free_packet_unlock:
write_unlock_bh(&call->state_lock); write_unlock_bh(&call->state_lock);
...@@ -495,9 +495,10 @@ static void rxrpc_process_jumbo_packet(struct rxrpc_call *call, ...@@ -495,9 +495,10 @@ static void rxrpc_process_jumbo_packet(struct rxrpc_call *call,
protocol_error: protocol_error:
_debug("protocol error"); _debug("protocol error");
rxrpc_free_skb(part); rxrpc_free_skb(part);
rxrpc_free_skb(jumbo); if (rxrpc_abort_call("PJP", call, sp->hdr.seq,
if (rxrpc_abort_call(call, RX_PROTOCOL_ERROR, EPROTO)) RX_PROTOCOL_ERROR, EPROTO))
rxrpc_queue_call(call); rxrpc_queue_call(call);
rxrpc_free_skb(jumbo);
_leave(""); _leave("");
} }
......
...@@ -23,31 +23,32 @@ static int none_prime_packet_security(struct rxrpc_connection *conn) ...@@ -23,31 +23,32 @@ static int none_prime_packet_security(struct rxrpc_connection *conn)
} }
static int none_secure_packet(struct rxrpc_call *call, static int none_secure_packet(struct rxrpc_call *call,
struct sk_buff *skb, struct sk_buff *skb,
size_t data_size, size_t data_size,
void *sechdr) void *sechdr)
{ {
return 0; return 0;
} }
static int none_verify_packet(struct rxrpc_call *call, static int none_verify_packet(struct rxrpc_call *call,
struct sk_buff *skb, struct sk_buff *skb,
u32 *_abort_code) rxrpc_seq_t seq,
u16 expected_cksum)
{ {
return 0; return 0;
} }
static int none_respond_to_challenge(struct rxrpc_connection *conn, 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; *_abort_code = RX_PROTOCOL_ERROR;
return -EPROTO; return -EPROTO;
} }
static int none_verify_response(struct rxrpc_connection *conn, 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; *_abort_code = RX_PROTOCOL_ERROR;
return -EPROTO; return -EPROTO;
......
...@@ -316,12 +316,10 @@ static int rxkad_secure_packet(struct rxrpc_call *call, ...@@ -316,12 +316,10 @@ static int rxkad_secure_packet(struct rxrpc_call *call,
/* /*
* decrypt partial encryption on a packet (level 1 security) * decrypt partial encryption on a packet (level 1 security)
*/ */
static int rxkad_verify_packet_auth(const struct rxrpc_call *call, static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
struct sk_buff *skb, rxrpc_seq_t seq)
u32 *_abort_code)
{ {
struct rxkad_level1_hdr sechdr; struct rxkad_level1_hdr sechdr;
struct rxrpc_skb_priv *sp;
SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher);
struct rxrpc_crypt iv; struct rxrpc_crypt iv;
struct scatterlist sg[16]; struct scatterlist sg[16];
...@@ -332,7 +330,10 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call, ...@@ -332,7 +330,10 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call,
_enter(""); _enter("");
sp = rxrpc_skb(skb); if (skb->len < 8) {
rxrpc_abort_call("V1H", call, seq, RXKADSEALEDINCON, EPROTO);
goto protocol_error;
}
/* we want to decrypt the skbuff in-place */ /* we want to decrypt the skbuff in-place */
nsg = skb_cow_data(skb, 0, &trailer); nsg = skb_cow_data(skb, 0, &trailer);
...@@ -351,9 +352,11 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call, ...@@ -351,9 +352,11 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call,
crypto_skcipher_decrypt(req); crypto_skcipher_decrypt(req);
skcipher_request_zero(req); skcipher_request_zero(req);
/* remove the decrypted packet length */ /* Extract the decrypted packet length */
if (skb_copy_bits(skb, 0, &sechdr, sizeof(sechdr)) < 0) if (skb_copy_bits(skb, 0, &sechdr, sizeof(sechdr)) < 0) {
goto datalen_error; rxrpc_abort_call("XV1", call, seq, RXKADDATALEN, EPROTO);
goto protocol_error;
}
if (!skb_pull(skb, sizeof(sechdr))) if (!skb_pull(skb, sizeof(sechdr)))
BUG(); BUG();
...@@ -361,24 +364,24 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call, ...@@ -361,24 +364,24 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call,
data_size = buf & 0xffff; data_size = buf & 0xffff;
check = buf >> 16; check = buf >> 16;
check ^= sp->hdr.seq ^ sp->hdr.callNumber; check ^= seq ^ call->call_id;
check &= 0xffff; check &= 0xffff;
if (check != 0) { if (check != 0) {
*_abort_code = RXKADSEALEDINCON; rxrpc_abort_call("V1C", call, seq, RXKADSEALEDINCON, EPROTO);
goto protocol_error; goto protocol_error;
} }
/* shorten the packet to remove the padding */ /* shorten the packet to remove the padding */
if (data_size > skb->len) if (data_size > skb->len) {
goto datalen_error; rxrpc_abort_call("V1L", call, seq, RXKADDATALEN, EPROTO);
else if (data_size < skb->len) goto protocol_error;
}
if (data_size < skb->len)
skb->len = data_size; skb->len = data_size;
_leave(" = 0 [dlen=%x]", data_size); _leave(" = 0 [dlen=%x]", data_size);
return 0; return 0;
datalen_error:
*_abort_code = RXKADDATALEN;
protocol_error: protocol_error:
_leave(" = -EPROTO"); _leave(" = -EPROTO");
return -EPROTO; return -EPROTO;
...@@ -391,13 +394,11 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call, ...@@ -391,13 +394,11 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call,
/* /*
* wholly decrypt a packet (level 2 security) * wholly decrypt a packet (level 2 security)
*/ */
static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
struct sk_buff *skb, rxrpc_seq_t seq)
u32 *_abort_code)
{ {
const struct rxrpc_key_token *token; const struct rxrpc_key_token *token;
struct rxkad_level2_hdr sechdr; struct rxkad_level2_hdr sechdr;
struct rxrpc_skb_priv *sp;
SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher);
struct rxrpc_crypt iv; struct rxrpc_crypt iv;
struct scatterlist _sg[4], *sg; struct scatterlist _sg[4], *sg;
...@@ -408,7 +409,10 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, ...@@ -408,7 +409,10 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call,
_enter(",{%d}", skb->len); _enter(",{%d}", skb->len);
sp = rxrpc_skb(skb); if (skb->len < 8) {
rxrpc_abort_call("V2H", call, seq, RXKADSEALEDINCON, EPROTO);
goto protocol_error;
}
/* we want to decrypt the skbuff in-place */ /* we want to decrypt the skbuff in-place */
nsg = skb_cow_data(skb, 0, &trailer); nsg = skb_cow_data(skb, 0, &trailer);
...@@ -437,9 +441,11 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, ...@@ -437,9 +441,11 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call,
if (sg != _sg) if (sg != _sg)
kfree(sg); kfree(sg);
/* remove the decrypted packet length */ /* Extract the decrypted packet length */
if (skb_copy_bits(skb, 0, &sechdr, sizeof(sechdr)) < 0) if (skb_copy_bits(skb, 0, &sechdr, sizeof(sechdr)) < 0) {
goto datalen_error; rxrpc_abort_call("XV2", call, seq, RXKADDATALEN, EPROTO);
goto protocol_error;
}
if (!skb_pull(skb, sizeof(sechdr))) if (!skb_pull(skb, sizeof(sechdr)))
BUG(); BUG();
...@@ -447,24 +453,23 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, ...@@ -447,24 +453,23 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call,
data_size = buf & 0xffff; data_size = buf & 0xffff;
check = buf >> 16; check = buf >> 16;
check ^= sp->hdr.seq ^ sp->hdr.callNumber; check ^= seq ^ call->call_id;
check &= 0xffff; check &= 0xffff;
if (check != 0) { if (check != 0) {
*_abort_code = RXKADSEALEDINCON; rxrpc_abort_call("V2C", call, seq, RXKADSEALEDINCON, EPROTO);
goto protocol_error; goto protocol_error;
} }
/* shorten the packet to remove the padding */ if (data_size > skb->len) {
if (data_size > skb->len) rxrpc_abort_call("V2L", call, seq, RXKADDATALEN, EPROTO);
goto datalen_error; goto protocol_error;
else if (data_size < skb->len) }
if (data_size < skb->len)
skb->len = data_size; skb->len = data_size;
_leave(" = 0 [dlen=%x]", data_size); _leave(" = 0 [dlen=%x]", data_size);
return 0; return 0;
datalen_error:
*_abort_code = RXKADDATALEN;
protocol_error: protocol_error:
_leave(" = -EPROTO"); _leave(" = -EPROTO");
return -EPROTO; return -EPROTO;
...@@ -475,40 +480,30 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, ...@@ -475,40 +480,30 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call,
} }
/* /*
* verify the security on a received packet * Verify the security on a received packet or subpacket (if part of a
* jumbo packet).
*/ */
static int rxkad_verify_packet(struct rxrpc_call *call, static int rxkad_verify_packet(struct rxrpc_call *call, struct sk_buff *skb,
struct sk_buff *skb, rxrpc_seq_t seq, u16 expected_cksum)
u32 *_abort_code)
{ {
SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher);
struct rxrpc_skb_priv *sp;
struct rxrpc_crypt iv; struct rxrpc_crypt iv;
struct scatterlist sg; struct scatterlist sg;
u16 cksum; u16 cksum;
u32 x, y; u32 x, y;
int ret;
sp = rxrpc_skb(skb);
_enter("{%d{%x}},{#%u}", _enter("{%d{%x}},{#%u}",
call->debug_id, key_serial(call->conn->params.key), sp->hdr.seq); call->debug_id, key_serial(call->conn->params.key), seq);
if (!call->conn->cipher) if (!call->conn->cipher)
return 0; return 0;
if (sp->hdr.securityIndex != RXRPC_SECURITY_RXKAD) {
*_abort_code = RXKADINCONSISTENCY;
_leave(" = -EPROTO [not rxkad]");
return -EPROTO;
}
/* continue encrypting from where we left off */ /* continue encrypting from where we left off */
memcpy(&iv, call->conn->csum_iv.x, sizeof(iv)); memcpy(&iv, call->conn->csum_iv.x, sizeof(iv));
/* validate the security checksum */ /* validate the security checksum */
x = (call->cid & RXRPC_CHANNELMASK) << (32 - RXRPC_CIDSHIFT); x = (call->cid & RXRPC_CHANNELMASK) << (32 - RXRPC_CIDSHIFT);
x |= sp->hdr.seq & 0x3fffffff; x |= seq & 0x3fffffff;
call->crypto_buf[0] = htonl(call->call_id); call->crypto_buf[0] = htonl(call->call_id);
call->crypto_buf[1] = htonl(x); call->crypto_buf[1] = htonl(x);
...@@ -524,29 +519,22 @@ static int rxkad_verify_packet(struct rxrpc_call *call, ...@@ -524,29 +519,22 @@ static int rxkad_verify_packet(struct rxrpc_call *call,
if (cksum == 0) if (cksum == 0)
cksum = 1; /* zero checksums are not permitted */ cksum = 1; /* zero checksums are not permitted */
if (sp->hdr.cksum != cksum) { if (cksum != expected_cksum) {
*_abort_code = RXKADSEALEDINCON; rxrpc_abort_call("VCK", call, seq, RXKADSEALEDINCON, EPROTO);
_leave(" = -EPROTO [csum failed]"); _leave(" = -EPROTO [csum failed]");
return -EPROTO; return -EPROTO;
} }
switch (call->conn->params.security_level) { switch (call->conn->params.security_level) {
case RXRPC_SECURITY_PLAIN: case RXRPC_SECURITY_PLAIN:
ret = 0; return 0;
break;
case RXRPC_SECURITY_AUTH: case RXRPC_SECURITY_AUTH:
ret = rxkad_verify_packet_auth(call, skb, _abort_code); return rxkad_verify_packet_1(call, skb, seq);
break;
case RXRPC_SECURITY_ENCRYPT: case RXRPC_SECURITY_ENCRYPT:
ret = rxkad_verify_packet_encrypt(call, skb, _abort_code); return rxkad_verify_packet_2(call, skb, seq);
break;
default: default:
ret = -ENOANO; return -ENOANO;
break;
} }
_leave(" = %d", ret);
return ret;
} }
/* /*
......
...@@ -454,14 +454,15 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg, ...@@ -454,14 +454,15 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg,
/* /*
* abort a call, sending an ABORT packet to the peer * abort a call, sending an ABORT packet to the peer
*/ */
static void rxrpc_send_abort(struct rxrpc_call *call, u32 abort_code) static void rxrpc_send_abort(struct rxrpc_call *call, const char *why,
u32 abort_code, int error)
{ {
if (call->state >= RXRPC_CALL_COMPLETE) if (call->state >= RXRPC_CALL_COMPLETE)
return; return;
write_lock_bh(&call->state_lock); write_lock_bh(&call->state_lock);
if (__rxrpc_abort_call(call, abort_code, ECONNABORTED)) { if (__rxrpc_abort_call(why, call, 0, abort_code, error)) {
del_timer_sync(&call->resend_timer); del_timer_sync(&call->resend_timer);
del_timer_sync(&call->ack_timer); del_timer_sync(&call->ack_timer);
clear_bit(RXRPC_CALL_EV_RESEND_TIMER, &call->events); clear_bit(RXRPC_CALL_EV_RESEND_TIMER, &call->events);
...@@ -556,7 +557,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) ...@@ -556,7 +557,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
/* it's too late for this call */ /* it's too late for this call */
ret = -ESHUTDOWN; ret = -ESHUTDOWN;
} else if (cmd == RXRPC_CMD_SEND_ABORT) { } else if (cmd == RXRPC_CMD_SEND_ABORT) {
rxrpc_send_abort(call, abort_code); rxrpc_send_abort(call, "CMD", abort_code, ECONNABORTED);
ret = 0; ret = 0;
} else if (cmd != RXRPC_CMD_SEND_DATA) { } else if (cmd != RXRPC_CMD_SEND_DATA) {
ret = -EINVAL; ret = -EINVAL;
...@@ -626,20 +627,19 @@ EXPORT_SYMBOL(rxrpc_kernel_send_data); ...@@ -626,20 +627,19 @@ EXPORT_SYMBOL(rxrpc_kernel_send_data);
* @sock: The socket the call is on * @sock: The socket the call is on
* @call: The call to be aborted * @call: The call to be aborted
* @abort_code: The abort code to stick into the ABORT packet * @abort_code: The abort code to stick into the ABORT packet
* @error: Local error value
* @why: 3-char string indicating why.
* *
* Allow a kernel service to abort a call, if it's still in an abortable state. * Allow a kernel service to abort a call, if it's still in an abortable state.
*/ */
void rxrpc_kernel_abort_call(struct socket *sock, struct rxrpc_call *call, void rxrpc_kernel_abort_call(struct socket *sock, struct rxrpc_call *call,
u32 abort_code) u32 abort_code, int error, const char *why)
{ {
_enter("{%d},%d", call->debug_id, abort_code); _enter("{%d},%d,%d,%s", call->debug_id, abort_code, error, why);
lock_sock(sock->sk); lock_sock(sock->sk);
_debug("CALL %d USR %lx ST %d on CONN %p", rxrpc_send_abort(call, why, abort_code, error);
call->debug_id, call->user_call_ID, call->state, call->conn);
rxrpc_send_abort(call, abort_code);
release_sock(sock->sk); release_sock(sock->sk);
_leave(""); _leave("");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment