Commit 2aff9d20 authored by Casey Schaufler's avatar Casey Schaufler Committed by Paul Moore
Browse files

lsm: infrastructure management of the sock security



Move management of the sock->sk_security blob out
of the individual security modules and into the security
infrastructure. Instead of allocating the blobs from within
the modules the modules tell the infrastructure how much
space is required, and the space is allocated there.

Acked-by: default avatarPaul Moore <paul@paul-moore.com>
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Reviewed-by: default avatarJohn Johansen <john.johansen@canonical.com>
Acked-by: default avatarStephen Smalley <stephen.smalley.work@gmail.com>
Signed-off-by: default avatarCasey Schaufler <casey@schaufler-ca.com>
[PM: subject tweak]
Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
parent 8400291e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ struct lsm_blob_sizes {
	int	lbs_cred;
	int	lbs_file;
	int	lbs_inode;
	int	lbs_sock;
	int	lbs_superblock;
	int	lbs_ipc;
	int	lbs_msg_msg;
+1 −2
Original line number Diff line number Diff line
@@ -51,10 +51,9 @@ struct aa_sk_ctx {
	struct aa_label *peer;
};

#define SK_CTX(X) ((X)->sk_security)
static inline struct aa_sk_ctx *aa_sock(const struct sock *sk)
{
	return sk->sk_security;
	return sk->sk_security + apparmor_blob_sizes.lbs_sock;
}

#define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P)				  \
+1 −16
Original line number Diff line number Diff line
@@ -1058,27 +1058,12 @@ static int apparmor_userns_create(const struct cred *cred)
	return error;
}

static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags)
{
	struct aa_sk_ctx *ctx;

	ctx = kzalloc(sizeof(*ctx), flags);
	if (!ctx)
		return -ENOMEM;

	sk->sk_security = ctx;

	return 0;
}

static void apparmor_sk_free_security(struct sock *sk)
{
	struct aa_sk_ctx *ctx = aa_sock(sk);

	sk->sk_security = NULL;
	aa_put_label(ctx->label);
	aa_put_label(ctx->peer);
	kfree(ctx);
}

/**
@@ -1433,6 +1418,7 @@ struct lsm_blob_sizes apparmor_blob_sizes __ro_after_init = {
	.lbs_cred = sizeof(struct aa_label *),
	.lbs_file = sizeof(struct aa_file_ctx),
	.lbs_task = sizeof(struct aa_task_ctx),
	.lbs_sock = sizeof(struct aa_sk_ctx),
};

static const struct lsm_id apparmor_lsmid = {
@@ -1478,7 +1464,6 @@ static struct security_hook_list apparmor_hooks[] __ro_after_init = {
	LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
	LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),

	LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security),
	LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security),
	LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security),

+1 −1
Original line number Diff line number Diff line
@@ -151,7 +151,7 @@ static int aa_label_sk_perm(const struct cred *subj_cred,
			    const char *op, u32 request,
			    struct sock *sk)
{
	struct aa_sk_ctx *ctx = SK_CTX(sk);
	struct aa_sk_ctx *ctx = aa_sock(sk);
	int error = 0;

	AA_BUG(!label);
+35 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <linux/msg.h>
#include <linux/overflow.h>
#include <net/flow.h>
#include <net/sock.h>

/* How many LSMs were built into the kernel? */
#define LSM_COUNT (__end_lsm_info - __start_lsm_info)
@@ -227,6 +228,7 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
	lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
	lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc);
	lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
	lsm_set_blob_size(&needed->lbs_sock, &blob_sizes.lbs_sock);
	lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
	lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
	lsm_set_blob_size(&needed->lbs_xattr_count,
@@ -401,6 +403,7 @@ static void __init ordered_lsm_init(void)
	init_debug("inode blob size      = %d\n", blob_sizes.lbs_inode);
	init_debug("ipc blob size        = %d\n", blob_sizes.lbs_ipc);
	init_debug("msg_msg blob size    = %d\n", blob_sizes.lbs_msg_msg);
	init_debug("sock blob size       = %d\n", blob_sizes.lbs_sock);
	init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
	init_debug("task blob size       = %d\n", blob_sizes.lbs_task);
	init_debug("xattr slots          = %d\n", blob_sizes.lbs_xattr_count);
@@ -4673,6 +4676,28 @@ int security_socket_getpeersec_dgram(struct socket *sock,
}
EXPORT_SYMBOL(security_socket_getpeersec_dgram);

/**
 * lsm_sock_alloc - allocate a composite sock blob
 * @sock: the sock that needs a blob
 * @priority: allocation mode
 *
 * Allocate the sock blob for all the modules
 *
 * Returns 0, or -ENOMEM if memory can't be allocated.
 */
static int lsm_sock_alloc(struct sock *sock, gfp_t priority)
{
	if (blob_sizes.lbs_sock == 0) {
		sock->sk_security = NULL;
		return 0;
	}

	sock->sk_security = kzalloc(blob_sizes.lbs_sock, priority);
	if (sock->sk_security == NULL)
		return -ENOMEM;
	return 0;
}

/**
 * security_sk_alloc() - Allocate and initialize a sock's LSM blob
 * @sk: sock
@@ -4686,7 +4711,14 @@ EXPORT_SYMBOL(security_socket_getpeersec_dgram);
 */
int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
{
	return call_int_hook(sk_alloc_security, sk, family, priority);
	int rc = lsm_sock_alloc(sk, priority);

	if (unlikely(rc))
		return rc;
	rc = call_int_hook(sk_alloc_security, sk, family, priority);
	if (unlikely(rc))
		security_sk_free(sk);
	return rc;
}

/**
@@ -4698,6 +4730,8 @@ int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
void security_sk_free(struct sock *sk)
{
	call_void_hook(sk_free_security, sk);
	kfree(sk->sk_security);
	sk->sk_security = NULL;
}

/**
Loading