Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52a4c640 authored by Nikolay Aleksandrov's avatar Nikolay Aleksandrov Committed by Steffen Klassert
Browse files

selinux: add gfp argument to security_xfrm_policy_alloc and fix callers



security_xfrm_policy_alloc can be called in atomic context so the
allocation should be done with GFP_ATOMIC. Add an argument to let the
callers choose the appropriate way. In order to do so a gfp argument
needs to be added to the method xfrm_policy_alloc_security in struct
security_operations and to the internal function
selinux_xfrm_alloc_user. After that switch to GFP_ATOMIC in the atomic
callers and leave GFP_KERNEL as before for the rest.
The path that needed the gfp argument addition is:
security_xfrm_policy_alloc -> security_ops.xfrm_policy_alloc_security ->
all users of xfrm_policy_alloc_security (e.g. selinux_xfrm_policy_alloc) ->
selinux_xfrm_alloc_user (here the allocation used to be GFP_KERNEL only)

Now adding a gfp argument to selinux_xfrm_alloc_user requires us to also
add it to security_context_to_sid which is used inside and prior to this
patch did only GFP_KERNEL allocation. So add gfp argument to
security_context_to_sid and adjust all of its callers as well.

CC: Paul Moore <paul@paul-moore.com>
CC: Dave Jones <davej@redhat.com>
CC: Steffen Klassert <steffen.klassert@secunet.com>
CC: Fan Du <fan.du@windriver.com>
CC: David S. Miller <davem@davemloft.net>
CC: LSM list <linux-security-module@vger.kernel.org>
CC: SELinux list <selinux@tycho.nsa.gov>

Signed-off-by: default avatarNikolay Aleksandrov <nikolay@redhat.com>
Acked-by: default avatarPaul Moore <paul@paul-moore.com>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent 87536a81
Loading
Loading
Loading
Loading
+7 −3
Original line number Original line Diff line number Diff line
@@ -1040,6 +1040,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
 *	Allocate a security structure to the xp->security field; the security
 *	Allocate a security structure to the xp->security field; the security
 *	field is initialized to NULL when the xfrm_policy is allocated.
 *	field is initialized to NULL when the xfrm_policy is allocated.
 *	Return 0 if operation was successful (memory to allocate, legal context)
 *	Return 0 if operation was successful (memory to allocate, legal context)
 *	@gfp is to specify the context for the allocation
 * @xfrm_policy_clone_security:
 * @xfrm_policy_clone_security:
 *	@old_ctx contains an existing xfrm_sec_ctx.
 *	@old_ctx contains an existing xfrm_sec_ctx.
 *	@new_ctxp contains a new xfrm_sec_ctx being cloned from old.
 *	@new_ctxp contains a new xfrm_sec_ctx being cloned from old.
@@ -1683,7 +1684,7 @@ struct security_operations {


#ifdef CONFIG_SECURITY_NETWORK_XFRM
#ifdef CONFIG_SECURITY_NETWORK_XFRM
	int (*xfrm_policy_alloc_security) (struct xfrm_sec_ctx **ctxp,
	int (*xfrm_policy_alloc_security) (struct xfrm_sec_ctx **ctxp,
			struct xfrm_user_sec_ctx *sec_ctx);
			struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp);
	int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx);
	int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx);
	void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx);
	void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx);
	int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx);
	int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx);
@@ -2859,7 +2860,8 @@ static inline void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)


#ifdef CONFIG_SECURITY_NETWORK_XFRM
#ifdef CONFIG_SECURITY_NETWORK_XFRM


int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx);
int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
			       struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp);
int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctxp);
int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctxp);
void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx);
int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx);
@@ -2877,7 +2879,9 @@ void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl);


#else	/* CONFIG_SECURITY_NETWORK_XFRM */
#else	/* CONFIG_SECURITY_NETWORK_XFRM */


static inline int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx)
static inline int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
					     struct xfrm_user_sec_ctx *sec_ctx,
					     gfp_t gfp)
{
{
	return 0;
	return 0;
}
}
+3 −3
Original line number Original line Diff line number Diff line
@@ -2239,7 +2239,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_
			goto out;
			goto out;
		}
		}


		err = security_xfrm_policy_alloc(&xp->security, uctx);
		err = security_xfrm_policy_alloc(&xp->security, uctx, GFP_KERNEL);
		kfree(uctx);
		kfree(uctx);


		if (err)
		if (err)
@@ -2341,7 +2341,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa
		if (!uctx)
		if (!uctx)
			return -ENOMEM;
			return -ENOMEM;


		err = security_xfrm_policy_alloc(&pol_ctx, uctx);
		err = security_xfrm_policy_alloc(&pol_ctx, uctx, GFP_KERNEL);
		kfree(uctx);
		kfree(uctx);
		if (err)
		if (err)
			return err;
			return err;
@@ -3241,7 +3241,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
		if ((*dir = verify_sec_ctx_len(p)))
		if ((*dir = verify_sec_ctx_len(p)))
			goto out;
			goto out;
		uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_ATOMIC);
		uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_ATOMIC);
		*dir = security_xfrm_policy_alloc(&xp->security, uctx);
		*dir = security_xfrm_policy_alloc(&xp->security, uctx, GFP_ATOMIC);
		kfree(uctx);
		kfree(uctx);


		if (*dir)
		if (*dir)
+3 −3
Original line number Original line Diff line number Diff line
@@ -1221,7 +1221,7 @@ static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs
		return 0;
		return 0;


	uctx = nla_data(rt);
	uctx = nla_data(rt);
	return security_xfrm_policy_alloc(&pol->security, uctx);
	return security_xfrm_policy_alloc(&pol->security, uctx, GFP_KERNEL);
}
}


static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
@@ -1626,7 +1626,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
		if (rt) {
		if (rt) {
			struct xfrm_user_sec_ctx *uctx = nla_data(rt);
			struct xfrm_user_sec_ctx *uctx = nla_data(rt);


			err = security_xfrm_policy_alloc(&ctx, uctx);
			err = security_xfrm_policy_alloc(&ctx, uctx, GFP_KERNEL);
			if (err)
			if (err)
				return err;
				return err;
		}
		}
@@ -1928,7 +1928,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
		if (rt) {
		if (rt) {
			struct xfrm_user_sec_ctx *uctx = nla_data(rt);
			struct xfrm_user_sec_ctx *uctx = nla_data(rt);


			err = security_xfrm_policy_alloc(&ctx, uctx);
			err = security_xfrm_policy_alloc(&ctx, uctx, GFP_KERNEL);
			if (err)
			if (err)
				return err;
				return err;
		}
		}
+2 −1
Original line number Original line Diff line number Diff line
@@ -757,7 +757,8 @@ static void cap_skb_owned_by(struct sk_buff *skb, struct sock *sk)


#ifdef CONFIG_SECURITY_NETWORK_XFRM
#ifdef CONFIG_SECURITY_NETWORK_XFRM
static int cap_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp,
static int cap_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp,
					  struct xfrm_user_sec_ctx *sec_ctx)
					  struct xfrm_user_sec_ctx *sec_ctx,
					  gfp_t gfp)
{
{
	return 0;
	return 0;
}
}
+4 −2
Original line number Original line Diff line number Diff line
@@ -1317,9 +1317,11 @@ void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)


#ifdef CONFIG_SECURITY_NETWORK_XFRM
#ifdef CONFIG_SECURITY_NETWORK_XFRM


int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx)
int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
			       struct xfrm_user_sec_ctx *sec_ctx,
			       gfp_t gfp)
{
{
	return security_ops->xfrm_policy_alloc_security(ctxp, sec_ctx);
	return security_ops->xfrm_policy_alloc_security(ctxp, sec_ctx, gfp);
}
}
EXPORT_SYMBOL(security_xfrm_policy_alloc);
EXPORT_SYMBOL(security_xfrm_policy_alloc);


Loading