aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/security.h19
-rw-r--r--include/net/xfrm.h2
-rw-r--r--net/key/af_key.c15
-rw-r--r--net/xfrm/xfrm_state.c2
-rw-r--r--net/xfrm/xfrm_user.c13
-rw-r--r--security/dummy.c3
-rw-r--r--security/selinux/include/xfrm.h3
-rw-r--r--security/selinux/xfrm.c33
8 files changed, 66 insertions, 24 deletions
diff --git a/include/linux/security.h b/include/linux/security.h
index f3909d189fe..8e3dc6c51a6 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -827,8 +827,10 @@ struct swap_info_struct;
827 * used by the XFRM system. 827 * used by the XFRM system.
828 * @sec_ctx contains the security context information being provided by 828 * @sec_ctx contains the security context information being provided by
829 * the user-level policy update program (e.g., setkey). 829 * the user-level policy update program (e.g., setkey).
830 * @sk refers to the sock from which to derive the security context.
830 * Allocate a security structure to the xp->security field; the security 831 * Allocate a security structure to the xp->security field; the security
831 * field is initialized to NULL when the xfrm_policy is allocated. 832 * field is initialized to NULL when the xfrm_policy is allocated. Only
833 * one of sec_ctx or sock can be specified.
832 * Return 0 if operation was successful (memory to allocate, legal context) 834 * Return 0 if operation was successful (memory to allocate, legal context)
833 * @xfrm_policy_clone_security: 835 * @xfrm_policy_clone_security:
834 * @old contains an existing xfrm_policy in the SPD. 836 * @old contains an existing xfrm_policy in the SPD.
@@ -1359,7 +1361,8 @@ struct security_operations {
1359#endif /* CONFIG_SECURITY_NETWORK */ 1361#endif /* CONFIG_SECURITY_NETWORK */
1360 1362
1361#ifdef CONFIG_SECURITY_NETWORK_XFRM 1363#ifdef CONFIG_SECURITY_NETWORK_XFRM
1362 int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx); 1364 int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp,
1365 struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk);
1363 int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new); 1366 int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new);
1364 void (*xfrm_policy_free_security) (struct xfrm_policy *xp); 1367 void (*xfrm_policy_free_security) (struct xfrm_policy *xp);
1365 int (*xfrm_policy_delete_security) (struct xfrm_policy *xp); 1368 int (*xfrm_policy_delete_security) (struct xfrm_policy *xp);
@@ -3057,7 +3060,12 @@ static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
3057#ifdef CONFIG_SECURITY_NETWORK_XFRM 3060#ifdef CONFIG_SECURITY_NETWORK_XFRM
3058static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx) 3061static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
3059{ 3062{
3060 return security_ops->xfrm_policy_alloc_security(xp, sec_ctx); 3063 return security_ops->xfrm_policy_alloc_security(xp, sec_ctx, NULL);
3064}
3065
3066static inline int security_xfrm_sock_policy_alloc(struct xfrm_policy *xp, struct sock *sk)
3067{
3068 return security_ops->xfrm_policy_alloc_security(xp, NULL, sk);
3061} 3069}
3062 3070
3063static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) 3071static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
@@ -3132,6 +3140,11 @@ static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm
3132 return 0; 3140 return 0;
3133} 3141}
3134 3142
3143static inline int security_xfrm_sock_policy_alloc(struct xfrm_policy *xp, struct sock *sk)
3144{
3145 return 0;
3146}
3147
3135static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) 3148static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
3136{ 3149{
3137 return 0; 3150 return 0;
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 3ecd9fa1ed4..00bf86e6e82 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -362,7 +362,7 @@ struct xfrm_mgr
362 char *id; 362 char *id;
363 int (*notify)(struct xfrm_state *x, struct km_event *c); 363 int (*notify)(struct xfrm_state *x, struct km_event *c);
364 int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir); 364 int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
365 struct xfrm_policy *(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir); 365 struct xfrm_policy *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir);
366 int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); 366 int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
367 int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c); 367 int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);
368}; 368};
diff --git a/net/key/af_key.c b/net/key/af_key.c
index a065e1a6777..797c744a843 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2843,14 +2843,14 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
2843 return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL); 2843 return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL);
2844} 2844}
2845 2845
2846static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt, 2846static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
2847 u8 *data, int len, int *dir) 2847 u8 *data, int len, int *dir)
2848{ 2848{
2849 struct xfrm_policy *xp; 2849 struct xfrm_policy *xp;
2850 struct sadb_x_policy *pol = (struct sadb_x_policy*)data; 2850 struct sadb_x_policy *pol = (struct sadb_x_policy*)data;
2851 struct sadb_x_sec_ctx *sec_ctx; 2851 struct sadb_x_sec_ctx *sec_ctx;
2852 2852
2853 switch (family) { 2853 switch (sk->sk_family) {
2854 case AF_INET: 2854 case AF_INET:
2855 if (opt != IP_IPSEC_POLICY) { 2855 if (opt != IP_IPSEC_POLICY) {
2856 *dir = -EOPNOTSUPP; 2856 *dir = -EOPNOTSUPP;
@@ -2891,7 +2891,7 @@ static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt,
2891 xp->lft.hard_byte_limit = XFRM_INF; 2891 xp->lft.hard_byte_limit = XFRM_INF;
2892 xp->lft.soft_packet_limit = XFRM_INF; 2892 xp->lft.soft_packet_limit = XFRM_INF;
2893 xp->lft.hard_packet_limit = XFRM_INF; 2893 xp->lft.hard_packet_limit = XFRM_INF;
2894 xp->family = family; 2894 xp->family = sk->sk_family;
2895 2895
2896 xp->xfrm_nr = 0; 2896 xp->xfrm_nr = 0;
2897 if (pol->sadb_x_policy_type == IPSEC_POLICY_IPSEC && 2897 if (pol->sadb_x_policy_type == IPSEC_POLICY_IPSEC &&
@@ -2907,8 +2907,10 @@ static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt,
2907 p += pol->sadb_x_policy_len*8; 2907 p += pol->sadb_x_policy_len*8;
2908 sec_ctx = (struct sadb_x_sec_ctx *)p; 2908 sec_ctx = (struct sadb_x_sec_ctx *)p;
2909 if (len < pol->sadb_x_policy_len*8 + 2909 if (len < pol->sadb_x_policy_len*8 +
2910 sec_ctx->sadb_x_sec_len) 2910 sec_ctx->sadb_x_sec_len) {
2911 *dir = -EINVAL;
2911 goto out; 2912 goto out;
2913 }
2912 if ((*dir = verify_sec_ctx_len(p))) 2914 if ((*dir = verify_sec_ctx_len(p)))
2913 goto out; 2915 goto out;
2914 uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); 2916 uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
@@ -2918,6 +2920,11 @@ static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt,
2918 if (*dir) 2920 if (*dir)
2919 goto out; 2921 goto out;
2920 } 2922 }
2923 else {
2924 *dir = security_xfrm_sock_policy_alloc(xp, sk);
2925 if (*dir)
2926 goto out;
2927 }
2921 2928
2922 *dir = pol->sadb_x_policy_dir-1; 2929 *dir = pol->sadb_x_policy_dir-1;
2923 return xp; 2930 return xp;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index be02bd981d1..1c796087ee7 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1026,7 +1026,7 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
1026 err = -EINVAL; 1026 err = -EINVAL;
1027 read_lock(&xfrm_km_lock); 1027 read_lock(&xfrm_km_lock);
1028 list_for_each_entry(km, &xfrm_km_list, list) { 1028 list_for_each_entry(km, &xfrm_km_list, list) {
1029 pol = km->compile_policy(sk->sk_family, optname, data, 1029 pol = km->compile_policy(sk, optname, data,
1030 optlen, &err); 1030 optlen, &err);
1031 if (err >= 0) 1031 if (err >= 0)
1032 break; 1032 break;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index dac8db1088b..f70e158874d 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1757,7 +1757,7 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
1757/* User gives us xfrm_user_policy_info followed by an array of 0 1757/* User gives us xfrm_user_policy_info followed by an array of 0
1758 * or more templates. 1758 * or more templates.
1759 */ 1759 */
1760static struct xfrm_policy *xfrm_compile_policy(u16 family, int opt, 1760static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt,
1761 u8 *data, int len, int *dir) 1761 u8 *data, int len, int *dir)
1762{ 1762{
1763 struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data; 1763 struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data;
@@ -1765,7 +1765,7 @@ static struct xfrm_policy *xfrm_compile_policy(u16 family, int opt,
1765 struct xfrm_policy *xp; 1765 struct xfrm_policy *xp;
1766 int nr; 1766 int nr;
1767 1767
1768 switch (family) { 1768 switch (sk->sk_family) {
1769 case AF_INET: 1769 case AF_INET:
1770 if (opt != IP_XFRM_POLICY) { 1770 if (opt != IP_XFRM_POLICY) {
1771 *dir = -EOPNOTSUPP; 1771 *dir = -EOPNOTSUPP;
@@ -1807,6 +1807,15 @@ static struct xfrm_policy *xfrm_compile_policy(u16 family, int opt,
1807 copy_from_user_policy(xp, p); 1807 copy_from_user_policy(xp, p);
1808 copy_templates(xp, ut, nr); 1808 copy_templates(xp, ut, nr);
1809 1809
1810 if (!xp->security) {
1811 int err = security_xfrm_sock_policy_alloc(xp, sk);
1812 if (err) {
1813 kfree(xp);
1814 *dir = err;
1815 return NULL;
1816 }
1817 }
1818
1810 *dir = p->dir; 1819 *dir = p->dir;
1811 1820
1812 return xp; 1821 return xp;
diff --git a/security/dummy.c b/security/dummy.c
index c0ff6b9bfd7..66cc0640493 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -815,7 +815,8 @@ static inline void dummy_sk_getsecid(struct sock *sk, u32 *secid)
815#endif /* CONFIG_SECURITY_NETWORK */ 815#endif /* CONFIG_SECURITY_NETWORK */
816 816
817#ifdef CONFIG_SECURITY_NETWORK_XFRM 817#ifdef CONFIG_SECURITY_NETWORK_XFRM
818static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx) 818static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp,
819 struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk)
819{ 820{
820 return 0; 821 return 0;
821} 822}
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 8e45c1d588a..1822c73e508 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -7,7 +7,8 @@
7#ifndef _SELINUX_XFRM_H_ 7#ifndef _SELINUX_XFRM_H_
8#define _SELINUX_XFRM_H_ 8#define _SELINUX_XFRM_H_
9 9
10int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx); 10int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
11 struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk);
11int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new); 12int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
12void selinux_xfrm_policy_free(struct xfrm_policy *xp); 13void selinux_xfrm_policy_free(struct xfrm_policy *xp);
13int selinux_xfrm_policy_delete(struct xfrm_policy *xp); 14int selinux_xfrm_policy_delete(struct xfrm_policy *xp);
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index c750ef7af66..d3690f98513 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -208,10 +208,8 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
208 208
209 BUG_ON(uctx && pol); 209 BUG_ON(uctx && pol);
210 210
211 if (pol) 211 if (!uctx)
212 goto from_policy; 212 goto not_from_user;
213
214 BUG_ON(!uctx);
215 213
216 if (uctx->ctx_doi != XFRM_SC_ALG_SELINUX) 214 if (uctx->ctx_doi != XFRM_SC_ALG_SELINUX)
217 return -EINVAL; 215 return -EINVAL;
@@ -251,11 +249,14 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
251 249
252 return rc; 250 return rc;
253 251
254from_policy: 252not_from_user:
255 BUG_ON(!pol); 253 if (pol) {
256 rc = security_sid_mls_copy(pol->ctx_sid, sid, &ctx_sid); 254 rc = security_sid_mls_copy(pol->ctx_sid, sid, &ctx_sid);
257 if (rc) 255 if (rc)
258 goto out; 256 goto out;
257 }
258 else
259 ctx_sid = sid;
259 260
260 rc = security_sid_to_context(ctx_sid, &ctx_str, &str_len); 261 rc = security_sid_to_context(ctx_sid, &ctx_str, &str_len);
261 if (rc) 262 if (rc)
@@ -293,13 +294,23 @@ out2:
293 * LSM hook implementation that allocs and transfers uctx spec to 294 * LSM hook implementation that allocs and transfers uctx spec to
294 * xfrm_policy. 295 * xfrm_policy.
295 */ 296 */
296int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *uctx) 297int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
298 struct xfrm_user_sec_ctx *uctx, struct sock *sk)
297{ 299{
298 int err; 300 int err;
301 u32 sid;
299 302
300 BUG_ON(!xp); 303 BUG_ON(!xp);
304 BUG_ON(uctx && sk);
305
306 if (sk) {
307 struct sk_security_struct *ssec = sk->sk_security;
308 sid = ssec->sid;
309 }
310 else
311 sid = SECSID_NULL;
301 312
302 err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, NULL, 0); 313 err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, NULL, sid);
303 return err; 314 return err;
304} 315}
305 316