Commit 648af7fc authored by David Howells's avatar David Howells Committed by David S. Miller

rxrpc: Absorb the rxkad security module

Absorb the rxkad security module into the af_rxrpc module so that there's
only one module file.  This avoids a circular dependency whereby rxkad pins
af_rxrpc and cached connections pin rxkad but can't be manually evicted
(they will expire eventually and cease pinning).

With this change, af_rxrpc can just be unloaded, despite having cached
connections.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6dd050f8
...@@ -30,7 +30,7 @@ config AF_RXRPC_DEBUG ...@@ -30,7 +30,7 @@ config AF_RXRPC_DEBUG
config RXKAD config RXKAD
tristate "RxRPC Kerberos security" bool "RxRPC Kerberos security"
depends on AF_RXRPC depends on AF_RXRPC
select CRYPTO select CRYPTO
select CRYPTO_MANAGER select CRYPTO_MANAGER
......
...@@ -22,8 +22,7 @@ af-rxrpc-y := \ ...@@ -22,8 +22,7 @@ af-rxrpc-y := \
misc.o misc.o
af-rxrpc-$(CONFIG_PROC_FS) += ar-proc.o af-rxrpc-$(CONFIG_PROC_FS) += ar-proc.o
af-rxrpc-$(CONFIG_RXKAD) += rxkad.o
af-rxrpc-$(CONFIG_SYSCTL) += sysctl.o af-rxrpc-$(CONFIG_SYSCTL) += sysctl.o
obj-$(CONFIG_AF_RXRPC) += af-rxrpc.o obj-$(CONFIG_AF_RXRPC) += af-rxrpc.o
obj-$(CONFIG_RXKAD) += rxkad.o
...@@ -806,6 +806,12 @@ static int __init af_rxrpc_init(void) ...@@ -806,6 +806,12 @@ static int __init af_rxrpc_init(void)
goto error_work_queue; goto error_work_queue;
} }
ret = rxrpc_init_security();
if (ret < 0) {
printk(KERN_CRIT "RxRPC: Cannot initialise security\n");
goto error_security;
}
ret = proto_register(&rxrpc_proto, 1); ret = proto_register(&rxrpc_proto, 1);
if (ret < 0) { if (ret < 0) {
printk(KERN_CRIT "RxRPC: Cannot register protocol\n"); printk(KERN_CRIT "RxRPC: Cannot register protocol\n");
...@@ -853,6 +859,8 @@ static int __init af_rxrpc_init(void) ...@@ -853,6 +859,8 @@ static int __init af_rxrpc_init(void)
proto_unregister(&rxrpc_proto); proto_unregister(&rxrpc_proto);
error_proto: error_proto:
destroy_workqueue(rxrpc_workqueue); destroy_workqueue(rxrpc_workqueue);
error_security:
rxrpc_exit_security();
error_work_queue: error_work_queue:
kmem_cache_destroy(rxrpc_call_jar); kmem_cache_destroy(rxrpc_call_jar);
error_call_jar: error_call_jar:
...@@ -883,6 +891,7 @@ static void __exit af_rxrpc_exit(void) ...@@ -883,6 +891,7 @@ static void __exit af_rxrpc_exit(void)
remove_proc_entry("rxrpc_conns", init_net.proc_net); remove_proc_entry("rxrpc_conns", init_net.proc_net);
remove_proc_entry("rxrpc_calls", init_net.proc_net); remove_proc_entry("rxrpc_calls", init_net.proc_net);
destroy_workqueue(rxrpc_workqueue); destroy_workqueue(rxrpc_workqueue);
rxrpc_exit_security();
kmem_cache_destroy(rxrpc_call_jar); kmem_cache_destroy(rxrpc_call_jar);
_leave(""); _leave("");
} }
......
...@@ -124,11 +124,15 @@ enum rxrpc_command { ...@@ -124,11 +124,15 @@ enum rxrpc_command {
* RxRPC security module interface * RxRPC security module interface
*/ */
struct rxrpc_security { struct rxrpc_security {
struct module *owner; /* providing module */
struct list_head link; /* link in master list */
const char *name; /* name of this service */ const char *name; /* name of this service */
u8 security_index; /* security type provided */ u8 security_index; /* security type provided */
/* Initialise a security service */
int (*init)(void);
/* Clean up a security service */
void (*exit)(void);
/* initialise a connection's security */ /* initialise a connection's security */
int (*init_connection_security)(struct rxrpc_connection *); int (*init_connection_security)(struct rxrpc_connection *);
...@@ -268,7 +272,7 @@ struct rxrpc_connection { ...@@ -268,7 +272,7 @@ struct rxrpc_connection {
struct rb_root calls; /* calls on this connection */ struct rb_root calls; /* calls on this connection */
struct sk_buff_head rx_queue; /* received conn-level packets */ struct sk_buff_head rx_queue; /* received conn-level packets */
struct rxrpc_call *channels[RXRPC_MAXCALLS]; /* channels (active calls) */ struct rxrpc_call *channels[RXRPC_MAXCALLS]; /* channels (active calls) */
struct rxrpc_security *security; /* applied security module */ const struct rxrpc_security *security; /* applied security module */
struct key *key; /* security for this connection (client) */ struct key *key; /* security for this connection (client) */
struct key *server_key; /* security for this service */ struct key *server_key; /* security for this service */
struct crypto_skcipher *cipher; /* encryption handle */ struct crypto_skcipher *cipher; /* encryption handle */
...@@ -604,8 +608,8 @@ int rxrpc_recvmsg(struct socket *, struct msghdr *, size_t, int); ...@@ -604,8 +608,8 @@ int rxrpc_recvmsg(struct socket *, struct msghdr *, size_t, int);
/* /*
* ar-security.c * ar-security.c
*/ */
int rxrpc_register_security(struct rxrpc_security *); int __init rxrpc_init_security(void);
void rxrpc_unregister_security(struct rxrpc_security *); void rxrpc_exit_security(void);
int rxrpc_init_client_conn_security(struct rxrpc_connection *); int rxrpc_init_client_conn_security(struct rxrpc_connection *);
int rxrpc_init_server_conn_security(struct rxrpc_connection *); int rxrpc_init_server_conn_security(struct rxrpc_connection *);
int rxrpc_secure_packet(const struct rxrpc_call *, struct sk_buff *, size_t, int rxrpc_secure_packet(const struct rxrpc_call *, struct sk_buff *, size_t,
...@@ -645,6 +649,13 @@ extern const s8 rxrpc_ack_priority[]; ...@@ -645,6 +649,13 @@ extern const s8 rxrpc_ack_priority[];
extern const char *rxrpc_acks(u8 reason); extern const char *rxrpc_acks(u8 reason);
/*
* rxkad.c
*/
#ifdef CONFIG_RXKAD
extern const struct rxrpc_security rxkad;
#endif
/* /*
* sysctl.c * sysctl.c
*/ */
......
...@@ -22,109 +22,59 @@ ...@@ -22,109 +22,59 @@
static LIST_HEAD(rxrpc_security_methods); static LIST_HEAD(rxrpc_security_methods);
static DECLARE_RWSEM(rxrpc_security_sem); static DECLARE_RWSEM(rxrpc_security_sem);
/* static const struct rxrpc_security *rxrpc_security_types[] = {
* get an RxRPC security module #ifdef CONFIG_RXKAD
*/ [RXRPC_SECURITY_RXKAD] = &rxkad,
static struct rxrpc_security *rxrpc_security_get(struct rxrpc_security *sec) #endif
{ };
return try_module_get(sec->owner) ? sec : NULL;
}
/*
* release an RxRPC security module
*/
static void rxrpc_security_put(struct rxrpc_security *sec)
{
module_put(sec->owner);
}
/* int __init rxrpc_init_security(void)
* look up an rxrpc security module
*/
static struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
{ {
struct rxrpc_security *sec = NULL; int i, ret;
_enter("");
down_read(&rxrpc_security_sem);
list_for_each_entry(sec, &rxrpc_security_methods, link) { for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++) {
if (sec->security_index == security_index) { if (rxrpc_security_types[i]) {
if (unlikely(!rxrpc_security_get(sec))) ret = rxrpc_security_types[i]->init();
break; if (ret < 0)
goto out; goto failed;
} }
} }
sec = NULL; return 0;
out:
up_read(&rxrpc_security_sem); failed:
_leave(" = %p [%s]", sec, sec ? sec->name : ""); for (i--; i >= 0; i--)
return sec; if (rxrpc_security_types[i])
rxrpc_security_types[i]->exit();
return ret;
} }
/** void rxrpc_exit_security(void)
* rxrpc_register_security - register an RxRPC security handler
* @sec: security module
*
* register an RxRPC security handler for use by RxRPC
*/
int rxrpc_register_security(struct rxrpc_security *sec)
{ {
struct rxrpc_security *psec; int i;
int ret;
_enter("");
down_write(&rxrpc_security_sem);
ret = -EEXIST;
list_for_each_entry(psec, &rxrpc_security_methods, link) {
if (psec->security_index == sec->security_index)
goto out;
}
list_add(&sec->link, &rxrpc_security_methods);
printk(KERN_NOTICE "RxRPC: Registered security type %d '%s'\n",
sec->security_index, sec->name);
ret = 0;
out: for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++)
up_write(&rxrpc_security_sem); if (rxrpc_security_types[i])
_leave(" = %d", ret); rxrpc_security_types[i]->exit();
return ret;
} }
EXPORT_SYMBOL_GPL(rxrpc_register_security); /*
* look up an rxrpc security module
/**
* rxrpc_unregister_security - unregister an RxRPC security handler
* @sec: security module
*
* unregister an RxRPC security handler
*/ */
void rxrpc_unregister_security(struct rxrpc_security *sec) static const struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
{ {
if (security_index >= ARRAY_SIZE(rxrpc_security_types))
_enter(""); return NULL;
down_write(&rxrpc_security_sem); return rxrpc_security_types[security_index];
list_del_init(&sec->link);
up_write(&rxrpc_security_sem);
printk(KERN_NOTICE "RxRPC: Unregistered security type %d '%s'\n",
sec->security_index, sec->name);
} }
EXPORT_SYMBOL_GPL(rxrpc_unregister_security);
/* /*
* initialise the security on a client connection * initialise the security on a client connection
*/ */
int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
{ {
const struct rxrpc_security *sec;
struct rxrpc_key_token *token; struct rxrpc_key_token *token;
struct rxrpc_security *sec;
struct key *key = conn->key; struct key *key = conn->key;
int ret; int ret;
...@@ -148,7 +98,6 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) ...@@ -148,7 +98,6 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
ret = conn->security->init_connection_security(conn); ret = conn->security->init_connection_security(conn);
if (ret < 0) { if (ret < 0) {
rxrpc_security_put(conn->security);
conn->security = NULL; conn->security = NULL;
return ret; return ret;
} }
...@@ -162,7 +111,7 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) ...@@ -162,7 +111,7 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
*/ */
int rxrpc_init_server_conn_security(struct rxrpc_connection *conn) int rxrpc_init_server_conn_security(struct rxrpc_connection *conn)
{ {
struct rxrpc_security *sec; const struct rxrpc_security *sec;
struct rxrpc_local *local = conn->trans->local; struct rxrpc_local *local = conn->trans->local;
struct rxrpc_sock *rx; struct rxrpc_sock *rx;
struct key *key; struct key *key;
...@@ -188,14 +137,12 @@ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn) ...@@ -188,14 +137,12 @@ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn)
/* the service appears to have died */ /* the service appears to have died */
read_unlock_bh(&local->services_lock); read_unlock_bh(&local->services_lock);
rxrpc_security_put(sec);
_leave(" = -ENOENT"); _leave(" = -ENOENT");
return -ENOENT; return -ENOENT;
found_service: found_service:
if (!rx->securities) { if (!rx->securities) {
read_unlock_bh(&local->services_lock); read_unlock_bh(&local->services_lock);
rxrpc_security_put(sec);
_leave(" = -ENOKEY"); _leave(" = -ENOKEY");
return -ENOKEY; return -ENOKEY;
} }
...@@ -205,7 +152,6 @@ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn) ...@@ -205,7 +152,6 @@ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn)
&key_type_rxrpc_s, kdesc); &key_type_rxrpc_s, kdesc);
if (IS_ERR(kref)) { if (IS_ERR(kref)) {
read_unlock_bh(&local->services_lock); read_unlock_bh(&local->services_lock);
rxrpc_security_put(sec);
_leave(" = %ld [search]", PTR_ERR(kref)); _leave(" = %ld [search]", PTR_ERR(kref));
return PTR_ERR(kref); return PTR_ERR(kref);
} }
...@@ -253,11 +199,8 @@ void rxrpc_clear_conn_security(struct rxrpc_connection *conn) ...@@ -253,11 +199,8 @@ void rxrpc_clear_conn_security(struct rxrpc_connection *conn)
{ {
_enter("{%d}", conn->debug_id); _enter("{%d}", conn->debug_id);
if (conn->security) { if (conn->security)
conn->security->clear(conn); conn->security->clear(conn);
rxrpc_security_put(conn->security);
conn->security = NULL;
}
key_put(conn->key); key_put(conn->key);
key_put(conn->server_key); key_put(conn->server_key);
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include <net/sock.h> #include <net/sock.h>
#include <net/af_rxrpc.h> #include <net/af_rxrpc.h>
#include <keys/rxrpc-type.h> #include <keys/rxrpc-type.h>
#define rxrpc_debug rxkad_debug
#include "ar-internal.h" #include "ar-internal.h"
#define RXKAD_VERSION 2 #define RXKAD_VERSION 2
...@@ -31,10 +30,6 @@ ...@@ -31,10 +30,6 @@
#define REALM_SZ 40 /* size of principal's auth domain */ #define REALM_SZ 40 /* size of principal's auth domain */
#define SNAME_SZ 40 /* size of service name */ #define SNAME_SZ 40 /* size of service name */
unsigned int rxrpc_debug;
module_param_named(debug, rxrpc_debug, uint, S_IWUSR | S_IRUGO);
MODULE_PARM_DESC(debug, "rxkad debugging mask");
struct rxkad_level1_hdr { struct rxkad_level1_hdr {
__be32 data_size; /* true data size (excluding padding) */ __be32 data_size; /* true data size (excluding padding) */
}; };
...@@ -44,10 +39,6 @@ struct rxkad_level2_hdr { ...@@ -44,10 +39,6 @@ struct rxkad_level2_hdr {
__be32 checksum; /* decrypted data checksum */ __be32 checksum; /* decrypted data checksum */
}; };
MODULE_DESCRIPTION("RxRPC network protocol type-2 security (Kerberos 4)");
MODULE_AUTHOR("Red Hat, Inc.");
MODULE_LICENSE("GPL");
/* /*
* this holds a pinned cipher so that keventd doesn't get called by the cipher * this holds a pinned cipher so that keventd doesn't get called by the cipher
* alloc routine, but since we have it to hand, we use it to decrypt RESPONSE * alloc routine, but since we have it to hand, we use it to decrypt RESPONSE
...@@ -1164,43 +1155,41 @@ static void rxkad_clear(struct rxrpc_connection *conn) ...@@ -1164,43 +1155,41 @@ static void rxkad_clear(struct rxrpc_connection *conn)
} }
/* /*
* RxRPC Kerberos-based security * Initialise the rxkad security service.
*/ */
static struct rxrpc_security rxkad = { static int rxkad_init(void)
.owner = THIS_MODULE,
.name = "rxkad",
.security_index = RXRPC_SECURITY_RXKAD,
.init_connection_security = rxkad_init_connection_security,
.prime_packet_security = rxkad_prime_packet_security,
.secure_packet = rxkad_secure_packet,
.verify_packet = rxkad_verify_packet,
.issue_challenge = rxkad_issue_challenge,
.respond_to_challenge = rxkad_respond_to_challenge,
.verify_response = rxkad_verify_response,
.clear = rxkad_clear,
};
static __init int rxkad_init(void)
{ {
_enter("");
/* pin the cipher we need so that the crypto layer doesn't invoke /* pin the cipher we need so that the crypto layer doesn't invoke
* keventd to go get it */ * keventd to go get it */
rxkad_ci = crypto_alloc_skcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC); rxkad_ci = crypto_alloc_skcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(rxkad_ci)) if (IS_ERR(rxkad_ci))
return PTR_ERR(rxkad_ci); return PTR_ERR(rxkad_ci);
return 0;
return rxrpc_register_security(&rxkad);
} }
module_init(rxkad_init); /*
* Clean up the rxkad security service.
static __exit void rxkad_exit(void) */
static void rxkad_exit(void)
{ {
_enter(""); if (rxkad_ci)
rxrpc_unregister_security(&rxkad);
crypto_free_skcipher(rxkad_ci); crypto_free_skcipher(rxkad_ci);
} }
module_exit(rxkad_exit); /*
* RxRPC Kerberos-based security
*/
const struct rxrpc_security rxkad = {
.name = "rxkad",
.security_index = RXRPC_SECURITY_RXKAD,
.init = rxkad_init,
.exit = rxkad_exit,
.init_connection_security = rxkad_init_connection_security,
.prime_packet_security = rxkad_prime_packet_security,
.secure_packet = rxkad_secure_packet,
.verify_packet = rxkad_verify_packet,
.issue_challenge = rxkad_issue_challenge,
.respond_to_challenge = rxkad_respond_to_challenge,
.verify_response = rxkad_verify_response,
.clear = rxkad_clear,
};
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