diff options
| author | David S. Miller <davem@davemloft.net> | 2014-03-18 12:42:33 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-03-18 12:42:33 -0400 |
| commit | 72c2dfdefa42c747c8e61f3d3ebfafc8e8d5762f (patch) | |
| tree | 36ffd7b181a7b72fe02015014086001e440a043d | |
| parent | b085f311e85b1d6f75d610097c2f20583b776fda (diff) | |
| parent | 52a4c6404f91f2d2c5592ee6365a8418c4565f53 (diff) | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says:
====================
1) 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.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/linux/security.h | 10 | ||||
| -rw-r--r-- | net/key/af_key.c | 19 | ||||
| -rw-r--r-- | net/xfrm/xfrm_user.c | 6 | ||||
| -rw-r--r-- | security/capability.c | 3 | ||||
| -rw-r--r-- | security/security.c | 6 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 13 | ||||
| -rw-r--r-- | security/selinux/include/security.h | 2 | ||||
| -rw-r--r-- | security/selinux/include/xfrm.h | 3 | ||||
| -rw-r--r-- | security/selinux/selinuxfs.c | 28 | ||||
| -rw-r--r-- | security/selinux/ss/services.c | 6 | ||||
| -rw-r--r-- | security/selinux/xfrm.c | 14 |
11 files changed, 66 insertions, 44 deletions
diff --git a/include/linux/security.h b/include/linux/security.h index 5623a7f965b7..2fc42d191f79 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
| @@ -1040,6 +1040,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 1040 | * Allocate a security structure to the xp->security field; the security | 1040 | * Allocate a security structure to the xp->security field; the security |
| 1041 | * field is initialized to NULL when the xfrm_policy is allocated. | 1041 | * field is initialized to NULL when the xfrm_policy is allocated. |
| 1042 | * Return 0 if operation was successful (memory to allocate, legal context) | 1042 | * Return 0 if operation was successful (memory to allocate, legal context) |
| 1043 | * @gfp is to specify the context for the allocation | ||
| 1043 | * @xfrm_policy_clone_security: | 1044 | * @xfrm_policy_clone_security: |
| 1044 | * @old_ctx contains an existing xfrm_sec_ctx. | 1045 | * @old_ctx contains an existing xfrm_sec_ctx. |
| 1045 | * @new_ctxp contains a new xfrm_sec_ctx being cloned from old. | 1046 | * @new_ctxp contains a new xfrm_sec_ctx being cloned from old. |
| @@ -1683,7 +1684,7 @@ struct security_operations { | |||
| 1683 | 1684 | ||
| 1684 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 1685 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
| 1685 | int (*xfrm_policy_alloc_security) (struct xfrm_sec_ctx **ctxp, | 1686 | int (*xfrm_policy_alloc_security) (struct xfrm_sec_ctx **ctxp, |
| 1686 | struct xfrm_user_sec_ctx *sec_ctx); | 1687 | struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp); |
| 1687 | int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx); | 1688 | int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx); |
| 1688 | void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx); | 1689 | void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx); |
| 1689 | int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx); | 1690 | 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) | |||
| 2859 | 2860 | ||
| 2860 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 2861 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
| 2861 | 2862 | ||
| 2862 | int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx); | 2863 | int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, |
| 2864 | struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp); | ||
| 2863 | int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctxp); | 2865 | int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctxp); |
| 2864 | void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx); | 2866 | void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx); |
| 2865 | int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx); | 2867 | 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); | |||
| 2877 | 2879 | ||
| 2878 | #else /* CONFIG_SECURITY_NETWORK_XFRM */ | 2880 | #else /* CONFIG_SECURITY_NETWORK_XFRM */ |
| 2879 | 2881 | ||
| 2880 | static inline int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx) | 2882 | static inline int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, |
| 2883 | struct xfrm_user_sec_ctx *sec_ctx, | ||
| 2884 | gfp_t gfp) | ||
| 2881 | { | 2885 | { |
| 2882 | return 0; | 2886 | return 0; |
| 2883 | } | 2887 | } |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 1a04c1329362..79326978517a 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
| @@ -433,12 +433,13 @@ static inline int verify_sec_ctx_len(const void *p) | |||
| 433 | return 0; | 433 | return 0; |
| 434 | } | 434 | } |
| 435 | 435 | ||
| 436 | static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx(const struct sadb_x_sec_ctx *sec_ctx) | 436 | static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx(const struct sadb_x_sec_ctx *sec_ctx, |
| 437 | gfp_t gfp) | ||
| 437 | { | 438 | { |
| 438 | struct xfrm_user_sec_ctx *uctx = NULL; | 439 | struct xfrm_user_sec_ctx *uctx = NULL; |
| 439 | int ctx_size = sec_ctx->sadb_x_ctx_len; | 440 | int ctx_size = sec_ctx->sadb_x_ctx_len; |
| 440 | 441 | ||
| 441 | uctx = kmalloc((sizeof(*uctx)+ctx_size), GFP_KERNEL); | 442 | uctx = kmalloc((sizeof(*uctx)+ctx_size), gfp); |
| 442 | 443 | ||
| 443 | if (!uctx) | 444 | if (!uctx) |
| 444 | return NULL; | 445 | return NULL; |
| @@ -1124,7 +1125,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, | |||
| 1124 | 1125 | ||
| 1125 | sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1]; | 1126 | sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1]; |
| 1126 | if (sec_ctx != NULL) { | 1127 | if (sec_ctx != NULL) { |
| 1127 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); | 1128 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_KERNEL); |
| 1128 | 1129 | ||
| 1129 | if (!uctx) | 1130 | if (!uctx) |
| 1130 | goto out; | 1131 | goto out; |
| @@ -2231,14 +2232,14 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_ | |||
| 2231 | 2232 | ||
| 2232 | sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1]; | 2233 | sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1]; |
| 2233 | if (sec_ctx != NULL) { | 2234 | if (sec_ctx != NULL) { |
| 2234 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); | 2235 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_KERNEL); |
| 2235 | 2236 | ||
| 2236 | if (!uctx) { | 2237 | if (!uctx) { |
| 2237 | err = -ENOBUFS; | 2238 | err = -ENOBUFS; |
| 2238 | goto out; | 2239 | goto out; |
| 2239 | } | 2240 | } |
| 2240 | 2241 | ||
| 2241 | err = security_xfrm_policy_alloc(&xp->security, uctx); | 2242 | err = security_xfrm_policy_alloc(&xp->security, uctx, GFP_KERNEL); |
| 2242 | kfree(uctx); | 2243 | kfree(uctx); |
| 2243 | 2244 | ||
| 2244 | if (err) | 2245 | if (err) |
| @@ -2335,12 +2336,12 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa | |||
| 2335 | 2336 | ||
| 2336 | sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1]; | 2337 | sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1]; |
| 2337 | if (sec_ctx != NULL) { | 2338 | if (sec_ctx != NULL) { |
| 2338 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); | 2339 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_KERNEL); |
| 2339 | 2340 | ||
| 2340 | if (!uctx) | 2341 | if (!uctx) |
| 2341 | return -ENOMEM; | 2342 | return -ENOMEM; |
| 2342 | 2343 | ||
| 2343 | err = security_xfrm_policy_alloc(&pol_ctx, uctx); | 2344 | err = security_xfrm_policy_alloc(&pol_ctx, uctx, GFP_KERNEL); |
| 2344 | kfree(uctx); | 2345 | kfree(uctx); |
| 2345 | if (err) | 2346 | if (err) |
| 2346 | return err; | 2347 | return err; |
| @@ -3239,8 +3240,8 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, | |||
| 3239 | } | 3240 | } |
| 3240 | if ((*dir = verify_sec_ctx_len(p))) | 3241 | if ((*dir = verify_sec_ctx_len(p))) |
| 3241 | goto out; | 3242 | goto out; |
| 3242 | uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); | 3243 | uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_ATOMIC); |
| 3243 | *dir = security_xfrm_policy_alloc(&xp->security, uctx); | 3244 | *dir = security_xfrm_policy_alloc(&xp->security, uctx, GFP_ATOMIC); |
| 3244 | kfree(uctx); | 3245 | kfree(uctx); |
| 3245 | 3246 | ||
| 3246 | if (*dir) | 3247 | if (*dir) |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index c274179d60a2..2f7ddc3a59b4 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
| @@ -1221,7 +1221,7 @@ static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs | |||
| 1221 | return 0; | 1221 | return 0; |
| 1222 | 1222 | ||
| 1223 | uctx = nla_data(rt); | 1223 | uctx = nla_data(rt); |
| 1224 | return security_xfrm_policy_alloc(&pol->security, uctx); | 1224 | return security_xfrm_policy_alloc(&pol->security, uctx, GFP_KERNEL); |
| 1225 | } | 1225 | } |
| 1226 | 1226 | ||
| 1227 | static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, | 1227 | 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, | |||
| 1626 | if (rt) { | 1626 | if (rt) { |
| 1627 | struct xfrm_user_sec_ctx *uctx = nla_data(rt); | 1627 | struct xfrm_user_sec_ctx *uctx = nla_data(rt); |
| 1628 | 1628 | ||
| 1629 | err = security_xfrm_policy_alloc(&ctx, uctx); | 1629 | err = security_xfrm_policy_alloc(&ctx, uctx, GFP_KERNEL); |
| 1630 | if (err) | 1630 | if (err) |
| 1631 | return err; | 1631 | return err; |
| 1632 | } | 1632 | } |
| @@ -1928,7 +1928,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 1928 | if (rt) { | 1928 | if (rt) { |
| 1929 | struct xfrm_user_sec_ctx *uctx = nla_data(rt); | 1929 | struct xfrm_user_sec_ctx *uctx = nla_data(rt); |
| 1930 | 1930 | ||
| 1931 | err = security_xfrm_policy_alloc(&ctx, uctx); | 1931 | err = security_xfrm_policy_alloc(&ctx, uctx, GFP_KERNEL); |
| 1932 | if (err) | 1932 | if (err) |
| 1933 | return err; | 1933 | return err; |
| 1934 | } | 1934 | } |
diff --git a/security/capability.c b/security/capability.c index 8b4f24ae4338..21e2b9cae685 100644 --- a/security/capability.c +++ b/security/capability.c | |||
| @@ -757,7 +757,8 @@ static void cap_skb_owned_by(struct sk_buff *skb, struct sock *sk) | |||
| 757 | < | ||
