diff options
Diffstat (limited to 'net/rxrpc/security.c')
-rw-r--r-- | net/rxrpc/security.c | 71 |
1 files changed, 44 insertions, 27 deletions
diff --git a/net/rxrpc/security.c b/net/rxrpc/security.c index 50cb5f1ee0c0..cb8dd1d3b1d4 100644 --- a/net/rxrpc/security.c +++ b/net/rxrpc/security.c @@ -63,19 +63,17 @@ const struct rxrpc_security *rxrpc_security_lookup(u8 security_index) } /* - * initialise the security on a client connection + * Initialise the security on a client call. */ -int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) +int rxrpc_init_client_call_security(struct rxrpc_call *call) { - const struct rxrpc_security *sec; + const struct rxrpc_security *sec = &rxrpc_no_security; struct rxrpc_key_token *token; - struct key *key = conn->params.key; + struct key *key = call->key; int ret; - _enter("{%d},{%x}", conn->debug_id, key_serial(key)); - if (!key) - return 0; + goto found; ret = key_validate(key); if (ret < 0) @@ -89,16 +87,41 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) return -EKEYREJECTED; found: - conn->security = sec; + call->security = sec; + call->security_ix = sec->security_index; + return 0; +} - ret = conn->security->init_connection_security(conn, token); - if (ret < 0) { - conn->security = &rxrpc_no_security; - return ret; +/* + * initialise the security on a client connection + */ +int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) +{ + struct rxrpc_key_token *token; + struct key *key = conn->key; + int ret = 0; + + _enter("{%d},{%x}", conn->debug_id, key_serial(key)); + + for (token = key->payload.data[0]; token; token = token->next) { + if (token->security_index == conn->security->security_index) + goto found; } + return -EKEYREJECTED; - _leave(" = 0"); - return 0; +found: + mutex_lock(&conn->security_lock); + if (conn->state == RXRPC_CONN_CLIENT_UNSECURED) { + ret = conn->security->init_connection_security(conn, token); + if (ret == 0) { + spin_lock(&conn->state_lock); + if (conn->state == RXRPC_CONN_CLIENT_UNSECURED) + conn->state = RXRPC_CONN_CLIENT; + spin_unlock(&conn->state_lock); + } + } + mutex_unlock(&conn->security_lock); + return ret; } /* @@ -114,21 +137,15 @@ const struct rxrpc_security *rxrpc_get_incoming_security(struct rxrpc_sock *rx, sec = rxrpc_security_lookup(sp->hdr.securityIndex); if (!sec) { - trace_rxrpc_abort(0, "SVS", - sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq, - RX_INVALID_OPERATION, EKEYREJECTED); - skb->mark = RXRPC_SKB_MARK_REJECT_ABORT; - skb->priority = RX_INVALID_OPERATION; + rxrpc_direct_abort(skb, rxrpc_abort_unsupported_security, + RX_INVALID_OPERATION, -EKEYREJECTED); return NULL; } if (sp->hdr.securityIndex != RXRPC_SECURITY_NONE && !rx->securities) { - trace_rxrpc_abort(0, "SVR", - sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq, - RX_INVALID_OPERATION, EKEYREJECTED); - skb->mark = RXRPC_SKB_MARK_REJECT_ABORT; - skb->priority = sec->no_key_abort; + rxrpc_direct_abort(skb, rxrpc_abort_no_service_key, + sec->no_key_abort, -EKEYREJECTED); return NULL; } @@ -161,9 +178,9 @@ struct key *rxrpc_look_up_server_security(struct rxrpc_connection *conn, sprintf(kdesc, "%u:%u", sp->hdr.serviceId, sp->hdr.securityIndex); - rcu_read_lock(); + read_lock(&conn->local->services_lock); - rx = rcu_dereference(conn->params.local->service); + rx = conn->local->service; if (!rx) goto out; @@ -185,6 +202,6 @@ struct key *rxrpc_look_up_server_security(struct rxrpc_connection *conn, } out: - rcu_read_unlock(); + read_unlock(&conn->local->services_lock); return key; } |