pull request (net): ipsec 2014-03-18
Subsystems (5)
Steffen Klassert
maintainer1) Fix a sleep in atomic when pfkey_sadb2xfrm_user_sec_ctx() is called from pfkey_compile_policy().
Fix from Nikolay Aleksandrov.
2) security_xfrm_policy_alloc() can be called in process and atomic context. Add an argument to let the callers choose the appropriate way. Fix from Nikolay Aleksandrov.
Please pull or let me know if there are problems.
Thanks!
The following changes since commit a8d9bc2e9f5d1c5a25e33cec096d2a1652d3fd52:
bnx2: Fix shutdown sequence (2014-03-09 19:02:27 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git master
for you to fetch changes up to 52a4c6404f91f2d2c5592ee6365a8418c4565f53:
selinux: add gfp argument to security_xfrm_policy_alloc and fix callers (2014-03-10 08:30:02 +0100)
----------------------------------------------------------------
Nikolay Aleksandrov (2):
net: af_key: fix sleeping under rcu
selinux: add gfp argument to security_xfrm_policy_alloc and fix callers
include/linux/security.h | 10 +++++++--- net/key/af_key.c | 19 ++++++++++--------- net/xfrm/xfrm_user.c | 6 +++--- security/capability.c | 3 ++- security/security.c | 6 ++++-- security/selinux/hooks.c | 13 +++++++------ security/selinux/include/security.h | 2 +- security/selinux/include/xfrm.h | 3 ++- security/selinux/selinuxfs.c | 28 ++++++++++++++++++---------- security/selinux/ss/services.c | 6 ++++-- security/selinux/xfrm.c | 14 ++++++++------ 11 files changed, 66 insertions(+), 44 deletions(-)
Steffen Klassert
maintainerPATCH 1/2 net: af_key: fix sleeping under rcu
From: Nikolay Aleksandrov <[email protected]>
There's a kmalloc with GFP_KERNEL in a helper (pfkey_sadb2xfrm_user_sec_ctx) used in pfkey_compile_policy which is called under rcu_read_lock. Adjust pfkey_sadb2xfrm_user_sec_ctx to have a gfp argument and adjust the users.
--- net/key/af_key.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
net/key/af_key.c +7 -6
@@ -433,12 +433,13 @@ static inline int verify_sec_ctx_len(const void *p)return 0 ; } -static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx (const struct sadb_x_sec_ctx *sec_ctx) +static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx (const struct sadb_x_sec_ctx *sec_ctx, +gfp_t gfp) {struct xfrm_user_sec_ctx *uctx =NULL ;int ctx_size = sec_ctx->sadb_x_ctx_len; - uctx =kmalloc ((sizeof (*uctx)+ctx_size),GFP_KERNEL ); + uctx =kmalloc ((sizeof (*uctx)+ctx_size), gfp);if (!uctx)return NULL ;
@@ -1124,7 +1125,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX -1 ];if (sec_ctx !=NULL ) { -struct xfrm_user_sec_ctx *uctx =pfkey_sadb2xfrm_user_sec_ctx (sec_ctx); +struct xfrm_user_sec_ctx *uctx =pfkey_sadb2xfrm_user_sec_ctx (sec_ctx,GFP_KERNEL );if (!uctx) goto out;
@@ -2231,7 +2232,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_ sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX -1 ];if (sec_ctx !=NULL ) { -struct xfrm_user_sec_ctx *uctx =pfkey_sadb2xfrm_user_sec_ctx (sec_ctx); +struct xfrm_user_sec_ctx *uctx =pfkey_sadb2xfrm_user_sec_ctx (sec_ctx,GFP_KERNEL );if (!uctx) { err = -ENOBUFS ;
@@ -2335,7 +2336,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX -1 ];if (sec_ctx !=NULL ) { -struct xfrm_user_sec_ctx *uctx =pfkey_sadb2xfrm_user_sec_ctx (sec_ctx); +struct xfrm_user_sec_ctx *uctx =pfkey_sadb2xfrm_user_sec_ctx (sec_ctx,GFP_KERNEL );if (!uctx)return -ENOMEM ;
@@ -3239,7 +3240,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, }if ((*dir =verify_sec_ctx_len (p))) goto out; - uctx =pfkey_sadb2xfrm_user_sec_ctx (sec_ctx); + uctx =pfkey_sadb2xfrm_user_sec_ctx (sec_ctx,GFP_ATOMIC ); *dir =security_xfrm_policy_alloc (&xp->security, uctx);kfree (uctx);
Signature · 1 line
1.7.9.5
Steffen Klassert
maintainerPATCH 2/2 selinux: add gfp argument to security_xfrm_policy_alloc and fix callers
In reply to Steffen KlassertFrom: Nikolay Aleksandrov <[email protected]>
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.
--- include/linux/security.h | 10 +++++++--- net/key/af_key.c | 6 +++--- net/xfrm/xfrm_user.c | 6 +++--- security/capability.c | 3 ++- security/security.c | 6 ++++-- security/selinux/hooks.c | 13 +++++++------ security/selinux/include/security.h | 2 +- security/selinux/include/xfrm.h | 3 ++- security/selinux/selinuxfs.c | 28 ++++++++++++++++++---------- security/selinux/ss/services.c | 6 ++++-- security/selinux/xfrm.c | 14 ++++++++------ 11 files changed, 59 insertions(+), 38 deletions(-)
include/linux/security.h +7 -3
@@ -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 * field is initialized to NULL when the xfrm_policy is allocated. * Return 0 if operation was successful (memory to allocate, legal context) +* @gfp is to specify the context for the allocation * @xfrm_policy_clone_security: * @old_ctx contains an existing xfrm_sec_ctx. * @new_ctxp contains a new xfrm_sec_ctx being cloned from old.
@@ -1683,7 +1684,7 @@ struct security_operations {#ifdef CONFIG_SECURITY_NETWORK_XFRM 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);void (*xfrm_policy_free_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 -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);void security_xfrm_policy_free (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 */ -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 ; }
net/key/af_key.c +3 -3
@@ -2239,7 +2239,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_ goto out; } - err =security_xfrm_policy_alloc (&xp->security, uctx); + err =security_xfrm_policy_alloc (&xp->security, uctx,GFP_KERNEL );kfree (uctx);if (err)
@@ -2341,7 +2341,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct saif (!uctx)return -ENOMEM ; - err =security_xfrm_policy_alloc (&pol_ctx, uctx); + err =security_xfrm_policy_alloc (&pol_ctx, uctx,GFP_KERNEL );kfree (uctx);if (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))) goto out; 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);if (*dir)
net/xfrm/xfrm_user.c +3 -3
@@ -1221,7 +1221,7 @@ static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrsreturn 0 ; 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,
@@ -1626,7 +1626,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,if (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)return err; }
@@ -1928,7 +1928,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,if (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)return err; }
security/capability.c +2 -1
@@ -757,7 +757,8 @@ static void cap_skb_owned_by(struct sk_buff *skb, struct sock *sk)#ifdef CONFIG_SECURITY_NETWORK_XFRM 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 ; }
security/security.c +4 -2
@@ -1317,9 +1317,11 @@ void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)#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);
security/selinux/hooks.c +7 -6
@@ -668,7 +668,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,if (flags[i] ==SBLABEL_MNT )continue ; rc =security_context_to_sid (mount_options[i], -strlen (mount_options[i]), &sid); +strlen (mount_options[i]), &sid,GFP_KERNEL );if (rc) { printk(KERN_WARNING "SELinux: security_context_to_sid" "(%s) failed for (dev %s, type %s) errno=%d\n",
@@ -2489,7 +2489,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)if (flags[i] ==SBLABEL_MNT )continue ; len =strlen (mount_options[i]); - rc =security_context_to_sid (mount_options[i], len, &sid); + rc =security_context_to_sid (mount_options[i], len, &sid, +GFP_KERNEL );if (rc) { printk(KERN_WARNING "SELinux: security_context_to_sid" "(%s) failed for (dev %s, type %s) errno=%d\n",
@@ -2893,7 +2894,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,if (rc)return rc; - rc =security_context_to_sid (value, size, &newsid); + rc =security_context_to_sid (value, size, &newsid,GFP_KERNEL );if (rc == -EINVAL ) {if (!capable (CAP_MAC_ADMIN )) {struct audit_buffer *ab;
@@ -3050,7 +3051,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,if (!value || !size)return -EACCES ; - rc =security_context_to_sid ((void *)value, size, &newsid); + rc =security_context_to_sid ((void *)value, size, &newsid,GFP_KERNEL );if (rc)return rc;
@@ -5529,7 +5530,7 @@ static int selinux_setprocattr(struct task_struct *p, str[size-1 ] =0 ; size--; } - error =security_context_to_sid (value, size, &sid); + error =security_context_to_sid (value, size, &sid,GFP_KERNEL );if (error == -EINVAL && !strcmp (name,"fscreate" )) {if (!capable (CAP_MAC_ADMIN )) {struct audit_buffer *ab;
@@ -5638,7 +5639,7 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)static int selinux_secctx_to_secid (const char *secdata,u32 seclen,u32 *secid) { -return security_context_to_sid (secdata, seclen, secid); +return security_context_to_sid (secdata, seclen, secid,GFP_KERNEL ); }static void selinux_release_secctx (char *secdata,u32 seclen)
security/selinux/include/security.h +1 -1
@@ -134,7 +134,7 @@ int security_sid_to_context(u32 sid, char **scontext,int security_sid_to_context_force (u32 sid,char **scontext,u32 *scontext_len);int security_context_to_sid (const char *scontext,u32 scontext_len, -u32 *out_sid); +u32 *out_sid,gfp_t gfp);int security_context_to_sid_default (const char *scontext,u32 scontext_len,u32 *out_sid,u32 def_sid,gfp_t gfp_flags);
security/selinux/include/xfrm.h +2 -1
@@ -10,7 +10,8 @@#include <net/flow.h> int selinux_xfrm_policy_alloc (struct xfrm_sec_ctx **ctxp, -struct xfrm_user_sec_ctx *uctx); +struct xfrm_user_sec_ctx *uctx, +gfp_t gfp);int selinux_xfrm_policy_clone (struct xfrm_sec_ctx *old_ctx,struct xfrm_sec_ctx **new_ctxp);void selinux_xfrm_policy_free (struct xfrm_sec_ctx *ctx);
security/selinux/selinuxfs.c +18 -10
@@ -576,7 +576,7 @@ static ssize_t sel_write_context(struct file *file, char *buf, size_t size)if (length) goto out; - length =security_context_to_sid (buf, size, &sid); + length =security_context_to_sid (buf, size, &sid,GFP_KERNEL );if (length) goto out;
@@ -731,11 +731,13 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size)if (sscanf (buf,"%s %s %hu" , scon, tcon, &tclass) !=3 ) goto out; - length =security_context_to_sid (scon,strlen (scon) +1 , &ssid); + length =security_context_to_sid (scon,strlen (scon) +1 , &ssid, +GFP_KERNEL );if (length) goto out; - length =security_context_to_sid (tcon,strlen (tcon) +1 , &tsid); + length =security_context_to_sid (tcon,strlen (tcon) +1 , &tsid, +GFP_KERNEL );if (length) goto out;
@@ -817,11 +819,13 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) objname = namebuf; } - length =security_context_to_sid (scon,strlen (scon) +1 , &ssid); + length =security_context_to_sid (scon,strlen (scon) +1 , &ssid, +GFP_KERNEL );if (length) goto out; - length =security_context_to_sid (tcon,strlen (tcon) +1 , &tsid); + length =security_context_to_sid (tcon,strlen (tcon) +1 , &tsid, +GFP_KERNEL );if (length) goto out;
@@ -878,11 +882,13 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size)if (sscanf (buf,"%s %s %hu" , scon, tcon, &tclass) !=3 ) goto out; - length =security_context_to_sid (scon,strlen (scon) +1 , &ssid); + length =security_context_to_sid (scon,strlen (scon) +1 , &ssid, +GFP_KERNEL );if (length) goto out; - length =security_context_to_sid (tcon,strlen (tcon) +1 , &tsid); + length =security_context_to_sid (tcon,strlen (tcon) +1 , &tsid, +GFP_KERNEL );if (length) goto out;
@@ -934,7 +940,7 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size)if (sscanf (buf,"%s %s" , con, user) !=2 ) goto out; - length =security_context_to_sid (con,strlen (con) +1 , &sid); + length =security_context_to_sid (con,strlen (con) +1 , &sid,GFP_KERNEL );if (length) goto out;
@@ -994,11 +1000,13 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size)if (sscanf (buf,"%s %s %hu" , scon, tcon, &tclass) !=3 ) goto out; - length =security_context_to_sid (scon,strlen (scon) +1 , &ssid); + length =security_context_to_sid (scon,strlen (scon) +1 , &ssid, +GFP_KERNEL );if (length) goto out; - length =security_context_to_sid (tcon,strlen (tcon) +1 , &tsid); + length =security_context_to_sid (tcon,strlen (tcon) +1 , &tsid, +GFP_KERNEL );if (length) goto out;
security/selinux/ss/services.c +4 -2
@@ -1289,16 +1289,18 @@ out:* @scontext: security context * @scontext_len: length in bytes * @sid: security identifier, SID +* @gfp: context for the allocation * * Obtains a SID associated with the security context that * has the string representation specified by @scontext. * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient * memory is available, or 0 on success. */ -int security_context_to_sid (const char *scontext,u32 scontext_len,u32 *sid) +int security_context_to_sid (const char *scontext,u32 scontext_len,u32 *sid, +gfp_t gfp) {return security_context_to_sid_core (scontext, scontext_len, - sid,SECSID_NULL ,GFP_KERNEL ,0 ); + sid,SECSID_NULL , gfp,0 ); }/**
security/selinux/xfrm.c +8 -6
@@ -78,7 +78,8 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)* xfrm_user_sec_ctx context. */ static int selinux_xfrm_alloc_user (struct xfrm_sec_ctx **ctxp, -struct xfrm_user_sec_ctx *uctx) +struct xfrm_user_sec_ctx *uctx, +gfp_t gfp) {int rc;const struct task_security_struct *tsec =current_security ();
@@ -94,7 +95,7 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,if (str_len >=PAGE_SIZE )return -ENOMEM ; - ctx =kmalloc (sizeof (*ctx) + str_len +1 ,GFP_KERNEL ); + ctx =kmalloc (sizeof (*ctx) + str_len +1 , gfp);if (!ctx)return -ENOMEM ;
@@ -103,7 +104,7 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp, ctx->ctx_len = str_len;memcpy (ctx->ctx_str, &uctx[1 ], str_len); ctx->ctx_str[str_len] ='\0' ; - rc =security_context_to_sid (ctx->ctx_str, str_len, &ctx->ctx_sid); + rc =security_context_to_sid (ctx->ctx_str, str_len, &ctx->ctx_sid, gfp);if (rc) goto err;
@@ -282,9 +283,10 @@ int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)* LSM hook implementation that allocs and transfers uctx spec to xfrm_policy. */ int selinux_xfrm_policy_alloc (struct xfrm_sec_ctx **ctxp, -struct xfrm_user_sec_ctx *uctx) +struct xfrm_user_sec_ctx *uctx, +gfp_t gfp) { -return selinux_xfrm_alloc_user (ctxp, uctx); +return selinux_xfrm_alloc_user (ctxp, uctx, gfp); }/*
@@ -332,7 +334,7 @@ int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)int selinux_xfrm_state_alloc (struct xfrm_state *x,struct xfrm_user_sec_ctx *uctx) { -return selinux_xfrm_alloc_user (&x->security, uctx); +return selinux_xfrm_alloc_user (&x->security, uctx,GFP_KERNEL ); }/*
Signature · 1 line
1.7.9.5
David Miller
maintainerFrom: Steffen Klassert <[email protected]>
Date: Tue, 18 Mar 2014 08:43:01 +0100
Quoted 9 lines
1) Fix a sleep in atomic when
pfkey_sadb2xfrm_user_sec_ctx()is called frompfkey_compile_policy().
Fix from Nikolay Aleksandrov.2)
security_xfrm_policy_alloc()can be called in process and atomic context. Add an argument to let the callers choose the appropriate way. Fix from Nikolay Aleksandrov.Please pull or let me know if there are problems.
Pulled, thanks Steffen.