summaryrefslogtreecommitdiff
path: root/net/rxrpc/security.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/rxrpc/security.c')
-rw-r--r--net/rxrpc/security.c71
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;
}