aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/security.h24
-rw-r--r--include/net/xfrm.h3
-rw-r--r--net/ipv4/xfrm4_policy.c2
-rw-r--r--net/ipv6/xfrm6_policy.c2
-rw-r--r--net/key/af_key.c5
-rw-r--r--net/xfrm/xfrm_policy.c7
-rw-r--r--net/xfrm/xfrm_user.c9
-rw-r--r--security/dummy.c3
-rw-r--r--security/selinux/include/xfrm.h3
-rw-r--r--security/selinux/xfrm.c53
10 files changed, 62 insertions, 49 deletions
diff --git a/include/linux/security.h b/include/linux/security.h
index 9b5fea81f55e..b200b9856f32 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -882,7 +882,8 @@ struct request_sock;
882 * Check permission when a flow selects a xfrm_policy for processing 882 * Check permission when a flow selects a xfrm_policy for processing
883 * XFRMs on a packet. The hook is called when selecting either a 883 * XFRMs on a packet. The hook is called when selecting either a
884 * per-socket policy or a generic xfrm policy. 884 * per-socket policy or a generic xfrm policy.
885 * Return 0 if permission is granted. 885 * Return 0 if permission is granted, -ESRCH otherwise, or -errno
886 * on other errors.
886 * @xfrm_state_pol_flow_match: 887 * @xfrm_state_pol_flow_match:
887 * @x contains the state to match. 888 * @x contains the state to match.
888 * @xp contains the policy to check for a match. 889 * @xp contains the policy to check for a match.
@@ -891,6 +892,7 @@ struct request_sock;
891 * @xfrm_flow_state_match: 892 * @xfrm_flow_state_match:
892 * @fl contains the flow key to match. 893 * @fl contains the flow key to match.
893 * @xfrm points to the xfrm_state to match. 894 * @xfrm points to the xfrm_state to match.
895 * @xp points to the xfrm_policy to match.
894 * Return 1 if there is a match. 896 * Return 1 if there is a match.
895 * @xfrm_decode_session: 897 * @xfrm_decode_session:
896 * @skb points to skb to decode. 898 * @skb points to skb to decode.
@@ -1388,7 +1390,8 @@ struct security_operations {
1388 int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir); 1390 int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
1389 int (*xfrm_state_pol_flow_match)(struct xfrm_state *x, 1391 int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
1390 struct xfrm_policy *xp, struct flowi *fl); 1392 struct xfrm_policy *xp, struct flowi *fl);
1391 int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm); 1393 int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm,
1394 struct xfrm_policy *xp);
1392 int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall); 1395 int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall);
1393#endif /* CONFIG_SECURITY_NETWORK_XFRM */ 1396#endif /* CONFIG_SECURITY_NETWORK_XFRM */
1394 1397
@@ -3120,11 +3123,6 @@ static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm
3120 return security_ops->xfrm_policy_alloc_security(xp, sec_ctx, NULL); 3123 return security_ops->xfrm_policy_alloc_security(xp, sec_ctx, NULL);
3121} 3124}
3122 3125
3123static inline int security_xfrm_sock_policy_alloc(struct xfrm_policy *xp, struct sock *sk)
3124{
3125 return security_ops->xfrm_policy_alloc_security(xp, NULL, sk);
3126}
3127
3128static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) 3126static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
3129{ 3127{
3130 return security_ops->xfrm_policy_clone_security(old, new); 3128 return security_ops->xfrm_policy_clone_security(old, new);
@@ -3175,9 +3173,10 @@ static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
3175 return security_ops->xfrm_state_pol_flow_match(x, xp, fl); 3173 return security_ops->xfrm_state_pol_flow_match(x, xp, fl);
3176} 3174}
3177 3175
3178static inline int security_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm) 3176static inline int security_xfrm_flow_state_match(struct flowi *fl,
3177 struct xfrm_state *xfrm, struct xfrm_policy *xp)
3179{ 3178{
3180 return security_ops->xfrm_flow_state_match(fl, xfrm); 3179 return security_ops->xfrm_flow_state_match(fl, xfrm, xp);
3181} 3180}
3182 3181
3183static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) 3182static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
@@ -3197,11 +3196,6 @@ static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm
3197 return 0; 3196 return 0;
3198} 3197}
3199 3198
3200static inline int security_xfrm_sock_policy_alloc(struct xfrm_policy *xp, struct sock *sk)
3201{
3202 return 0;
3203}
3204
3205static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) 3199static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
3206{ 3200{
3207 return 0; 3201 return 0;
@@ -3249,7 +3243,7 @@ static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
3249} 3243}
3250 3244
3251static inline int security_xfrm_flow_state_match(struct flowi *fl, 3245static inline int security_xfrm_flow_state_match(struct flowi *fl,
3252 struct xfrm_state *xfrm) 3246 struct xfrm_state *xfrm, struct xfrm_policy *xp)
3253{ 3247{
3254 return 1; 3248 return 1;
3255} 3249}
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 1e2a4ddec96e..737fdb2ee8a4 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -995,7 +995,8 @@ struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
995 int create, unsigned short family); 995 int create, unsigned short family);
996extern void xfrm_policy_flush(u8 type); 996extern void xfrm_policy_flush(u8 type);
997extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); 997extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
998extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family, int strict); 998extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
999 struct flowi *fl, int family, int strict);
999extern void xfrm_init_pmtu(struct dst_entry *dst); 1000extern void xfrm_init_pmtu(struct dst_entry *dst);
1000 1001
1001extern wait_queue_head_t km_waitq; 1002extern wait_queue_head_t km_waitq;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 7a7a00147e55..1bed0cdf53e3 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -52,7 +52,7 @@ __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
52 xdst->u.rt.fl.fl4_dst == fl->fl4_dst && 52 xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
53 xdst->u.rt.fl.fl4_src == fl->fl4_src && 53 xdst->u.rt.fl.fl4_src == fl->fl4_src &&
54 xdst->u.rt.fl.fl4_tos == fl->fl4_tos && 54 xdst->u.rt.fl.fl4_tos == fl->fl4_tos &&
55 xfrm_bundle_ok(xdst, fl, AF_INET, 0)) { 55 xfrm_bundle_ok(policy, xdst, fl, AF_INET, 0)) {
56 dst_clone(dst); 56 dst_clone(dst);
57 break; 57 break;
58 } 58 }
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 6a252e2134d1..73cee2ec07e8 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -73,7 +73,7 @@ __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
73 xdst->u.rt6.rt6i_src.plen); 73 xdst->u.rt6.rt6i_src.plen);
74 if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) && 74 if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) &&
75 ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) && 75 ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) &&
76 xfrm_bundle_ok(xdst, fl, AF_INET6, 76 xfrm_bundle_ok(policy, xdst, fl, AF_INET6,
77 (xdst->u.rt6.rt6i_dst.plen != 128 || 77 (xdst->u.rt6.rt6i_dst.plen != 128 ||
78 xdst->u.rt6.rt6i_src.plen != 128))) { 78 xdst->u.rt6.rt6i_src.plen != 128))) {
79 dst_clone(dst); 79 dst_clone(dst);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ff98e70b0931..20ff7cca1d07 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2928,11 +2928,6 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
2928 if (*dir) 2928 if (*dir)
2929 goto out; 2929 goto out;
2930 } 2930 }
2931 else {
2932 *dir = security_xfrm_sock_policy_alloc(xp, sk);
2933 if (*dir)
2934 goto out;
2935 }
2936 2931
2937 *dir = pol->sadb_x_policy_dir-1; 2932 *dir = pol->sadb_x_policy_dir-1;
2938 return xp; 2933 return xp;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index fffdd34f3baf..695761ff1321 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1744,7 +1744,7 @@ static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
1744 1744
1745static int stale_bundle(struct dst_entry *dst) 1745static int stale_bundle(struct dst_entry *dst)
1746{ 1746{
1747 return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0); 1747 return !xfrm_bundle_ok(NULL, (struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0);
1748} 1748}
1749 1749
1750void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev) 1750void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
@@ -1866,7 +1866,8 @@ EXPORT_SYMBOL(xfrm_init_pmtu);
1866 * still valid. 1866 * still valid.
1867 */ 1867 */
1868 1868
1869int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int strict) 1869int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
1870 struct flowi *fl, int family, int strict)
1870{ 1871{
1871 struct dst_entry *dst = &first->u.dst; 1872 struct dst_entry *dst = &first->u.dst;
1872 struct xfrm_dst *last; 1873 struct xfrm_dst *last;
@@ -1883,7 +1884,7 @@ int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int str
1883 1884
1884 if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family)) 1885 if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
1885 return 0; 1886 return 0;
1886 if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm)) 1887 if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm, pol))
1887 return 0; 1888 return 0;
1888 if (dst->xfrm->km.state != XFRM_STATE_VALID) 1889 if (dst->xfrm->km.state != XFRM_STATE_VALID)
1889 return 0; 1890 return 0;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index d54b3a70d5df..2b2e59d8ffbc 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1992,15 +1992,6 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt,
1992 xp->type = XFRM_POLICY_TYPE_MAIN; 1992 xp->type = XFRM_POLICY_TYPE_MAIN;
1993 copy_templates(xp, ut, nr); 1993 copy_templates(xp, ut, nr);
1994 1994
1995 if (!xp->security) {
1996 int err = security_xfrm_sock_policy_alloc(xp, sk);
1997 if (err) {
1998 kfree(xp);
1999 *dir = err;
2000 return NULL;
2001 }
2002 }
2003
2004 *dir = p->dir; 1995 *dir = p->dir;
2005 1996
2006 return xp; 1997 return xp;
diff --git a/security/dummy.c b/security/dummy.c
index aeee70565509..43874c1e6e23 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -881,7 +881,8 @@ static int dummy_xfrm_state_pol_flow_match(struct xfrm_state *x,
881 return 1; 881 return 1;
882} 882}
883 883
884static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm) 884static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
885 struct xfrm_policy *xp)
885{ 886{
886 return 1; 887 return 1;
887} 888}
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 81eb59890162..526b28019aca 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -19,7 +19,8 @@ int selinux_xfrm_state_delete(struct xfrm_state *x);
19int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir); 19int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
20int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, 20int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
21 struct xfrm_policy *xp, struct flowi *fl); 21 struct xfrm_policy *xp, struct flowi *fl);
22int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm); 22int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
23 struct xfrm_policy *xp);
23 24
24 25
25/* 26/*
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 3e742b850af6..675b995a67c3 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -77,8 +77,8 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
77 */ 77 */
78int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir) 78int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
79{ 79{
80 int rc = 0; 80 int rc;
81 u32 sel_sid = SECINITSID_UNLABELED; 81 u32 sel_sid;
82 struct xfrm_sec_ctx *ctx; 82 struct xfrm_sec_ctx *ctx;
83 83
84 /* Context sid is either set to label or ANY_ASSOC */ 84 /* Context sid is either set to label or ANY_ASSOC */
@@ -88,11 +88,21 @@ int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
88 88
89 sel_sid = ctx->ctx_sid; 89 sel_sid = ctx->ctx_sid;
90 } 90 }
91 else
92 /*
93 * All flows should be treated as polmatch'ing an
94 * otherwise applicable "non-labeled" policy. This
95 * would prevent inadvertent "leaks".
96 */
97 return 0;
91 98
92 rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION, 99 rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION,
93 ASSOCIATION__POLMATCH, 100 ASSOCIATION__POLMATCH,
94 NULL); 101 NULL);
95 102
103 if (rc == -EACCES)
104 rc = -ESRCH;
105
96 return rc; 106 return rc;
97} 107}
98 108
@@ -108,15 +118,20 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
108 u32 pol_sid; 118 u32 pol_sid;
109 int err; 119 int err;
110 120
111 if (x->security) 121 if (xp->security) {
112 state_sid = x->security->ctx_sid; 122 if (!x->security)
113 else 123 /* unlabeled SA and labeled policy can't match */
114 state_sid = SECINITSID_UNLABELED; 124 return 0;
115 125 else
116 if (xp->security) 126 state_sid = x->security->ctx_sid;
117 pol_sid = xp->security->ctx_sid; 127 pol_sid = xp->security->ctx_sid;
118 else 128 } else
119 pol_sid = SECINITSID_UNLABELED; 129 if (x->security)
130 /* unlabeled policy and labeled SA can't match */
131 return 0;
132 else
133 /* unlabeled policy and unlabeled SA match all flows */
134 return 1;
120 135
121 err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION, 136 err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION,
122 ASSOCIATION__POLMATCH, 137 ASSOCIATION__POLMATCH,
@@ -125,7 +140,11 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
125 if (err) 140 if (err)
126 return 0; 141 return 0;
127 142
128 return selinux_xfrm_flow_state_match(fl, x); 143 err = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION,
144 ASSOCIATION__SENDTO,
145 NULL)? 0:1;
146
147 return err;
129} 148}
130 149
131/* 150/*
@@ -133,12 +152,22 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
133 * can use a given security association. 152 * can use a given security association.
134 */ 153 */
135 154
136int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm) 155int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
156 struct xfrm_policy *xp)
137{ 157{
138 int rc = 0; 158 int rc = 0;
139 u32 sel_sid = SECINITSID_UNLABELED; 159 u32 sel_sid = SECINITSID_UNLABELED;
140 struct xfrm_sec_ctx *ctx; 160 struct xfrm_sec_ctx *ctx;
141 161
162 if (!xp->security)
163 if (!xfrm->security)
164 return 1;
165 else
166 return 0;
167 else
168 if (!xfrm->security)
169 return 0;
170
142 /* Context sid is either set to label or ANY_ASSOC */ 171 /* Context sid is either set to label or ANY_ASSOC */
143 if ((ctx = xfrm->security)) { 172 if ((ctx = xfrm->security)) {
144 if (!selinux_authorizable_ctx(ctx)) 173 if (!selinux_authorizable_ctx(ctx))