diff options
-rw-r--r-- | include/linux/xfrm.h | 7 | ||||
-rw-r--r-- | include/net/xfrm.h | 1 | ||||
-rw-r--r-- | net/key/af_key.c | 18 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 134 |
4 files changed, 142 insertions, 18 deletions
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 492fb9818747..14ecd19f4cdc 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h | |||
@@ -230,6 +230,12 @@ enum xfrm_ae_ftype_t { | |||
230 | #define XFRM_AE_MAX (__XFRM_AE_MAX - 1) | 230 | #define XFRM_AE_MAX (__XFRM_AE_MAX - 1) |
231 | }; | 231 | }; |
232 | 232 | ||
233 | struct xfrm_userpolicy_type { | ||
234 | __u8 type; | ||
235 | __u16 reserved1; | ||
236 | __u8 reserved2; | ||
237 | }; | ||
238 | |||
233 | /* Netlink message attributes. */ | 239 | /* Netlink message attributes. */ |
234 | enum xfrm_attr_type_t { | 240 | enum xfrm_attr_type_t { |
235 | XFRMA_UNSPEC, | 241 | XFRMA_UNSPEC, |
@@ -248,6 +254,7 @@ enum xfrm_attr_type_t { | |||
248 | XFRMA_SRCADDR, /* xfrm_address_t */ | 254 | XFRMA_SRCADDR, /* xfrm_address_t */ |
249 | XFRMA_COADDR, /* xfrm_address_t */ | 255 | XFRMA_COADDR, /* xfrm_address_t */ |
250 | XFRMA_LASTUSED, | 256 | XFRMA_LASTUSED, |
257 | XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */ | ||
251 | __XFRMA_MAX | 258 | __XFRMA_MAX |
252 | 259 | ||
253 | #define XFRMA_MAX (__XFRMA_MAX - 1) | 260 | #define XFRMA_MAX (__XFRMA_MAX - 1) |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index d341603e4ba8..c75b3287d8f8 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -203,6 +203,7 @@ struct km_event | |||
203 | u32 proto; | 203 | u32 proto; |
204 | u32 byid; | 204 | u32 byid; |
205 | u32 aevent; | 205 | u32 aevent; |
206 | u32 type; | ||
206 | } data; | 207 | } data; |
207 | 208 | ||
208 | u32 seq; | 209 | u32 seq; |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 19e047b0e678..83b443ddc72f 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -1731,7 +1731,8 @@ static u32 gen_reqid(void) | |||
1731 | ++reqid; | 1731 | ++reqid; |
1732 | if (reqid == 0) | 1732 | if (reqid == 0) |
1733 | reqid = IPSEC_MANUAL_REQID_MAX+1; | 1733 | reqid = IPSEC_MANUAL_REQID_MAX+1; |
1734 | if (xfrm_policy_walk(check_reqid, (void*)&reqid) != -EEXIST) | 1734 | if (xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, check_reqid, |
1735 | (void*)&reqid) != -EEXIST) | ||
1735 | return reqid; | 1736 | return reqid; |
1736 | } while (reqid != start); | 1737 | } while (reqid != start); |
1737 | return 0; | 1738 | return 0; |
@@ -2268,7 +2269,8 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
2268 | return err; | 2269 | return err; |
2269 | } | 2270 | } |
2270 | 2271 | ||
2271 | xp = xfrm_policy_bysel_ctx(pol->sadb_x_policy_dir-1, &sel, tmp.security, 1); | 2272 | xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1, |
2273 | &sel, tmp.security, 1); | ||
2272 | security_xfrm_policy_free(&tmp); | 2274 | security_xfrm_policy_free(&tmp); |
2273 | if (xp == NULL) | 2275 | if (xp == NULL) |
2274 | return -ENOENT; | 2276 | return -ENOENT; |
@@ -2330,7 +2332,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
2330 | if (dir >= XFRM_POLICY_MAX) | 2332 | if (dir >= XFRM_POLICY_MAX) |
2331 | return -EINVAL; | 2333 | return -EINVAL; |
2332 | 2334 | ||
2333 | xp = xfrm_policy_byid(dir, pol->sadb_x_policy_id, | 2335 | xp = xfrm_policy_byid(XFRM_POLICY_TYPE_MAIN, dir, pol->sadb_x_policy_id, |
2334 | hdr->sadb_msg_type == SADB_X_SPDDELETE2); | 2336 | hdr->sadb_msg_type == SADB_X_SPDDELETE2); |
2335 | if (xp == NULL) | 2337 | if (xp == NULL) |
2336 | return -ENOENT; | 2338 | return -ENOENT; |
@@ -2378,7 +2380,7 @@ static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg * | |||
2378 | { | 2380 | { |
2379 | struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk }; | 2381 | struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk }; |
2380 | 2382 | ||
2381 | return xfrm_policy_walk(dump_sp, &data); | 2383 | return xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, dump_sp, &data); |
2382 | } | 2384 | } |
2383 | 2385 | ||
2384 | static int key_notify_policy_flush(struct km_event *c) | 2386 | static int key_notify_policy_flush(struct km_event *c) |
@@ -2405,7 +2407,8 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
2405 | { | 2407 | { |
2406 | struct km_event c; | 2408 | struct km_event c; |
2407 | 2409 | ||
2408 | xfrm_policy_flush(); | 2410 | xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN); |
2411 | c.data.type = XFRM_POLICY_TYPE_MAIN; | ||
2409 | c.event = XFRM_MSG_FLUSHPOLICY; | 2412 | c.event = XFRM_MSG_FLUSHPOLICY; |
2410 | c.pid = hdr->sadb_msg_pid; | 2413 | c.pid = hdr->sadb_msg_pid; |
2411 | c.seq = hdr->sadb_msg_seq; | 2414 | c.seq = hdr->sadb_msg_seq; |
@@ -2667,6 +2670,9 @@ static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c) | |||
2667 | 2670 | ||
2668 | static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c) | 2671 | static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c) |
2669 | { | 2672 | { |
2673 | if (xp && xp->type != XFRM_POLICY_TYPE_MAIN) | ||
2674 | return 0; | ||
2675 | |||
2670 | switch (c->event) { | 2676 | switch (c->event) { |
2671 | case XFRM_MSG_POLEXPIRE: | 2677 | case XFRM_MSG_POLEXPIRE: |
2672 | return key_notify_policy_expire(xp, c); | 2678 | return key_notify_policy_expire(xp, c); |
@@ -2675,6 +2681,8 @@ static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_e | |||
2675 | case XFRM_MSG_UPDPOLICY: | 2681 | case XFRM_MSG_UPDPOLICY: |
2676 | return key_notify_policy(xp, dir, c); | 2682 | return key_notify_policy(xp, dir, c); |
2677 | case XFRM_MSG_FLUSHPOLICY: | 2683 | case XFRM_MSG_FLUSHPOLICY: |
2684 | if (c->data.type != XFRM_POLICY_TYPE_MAIN) | ||
2685 | break; | ||
2678 | return key_notify_policy_flush(c); | 2686 | return key_notify_policy_flush(c); |
2679 | default: | 2687 | default: |
2680 | printk("pfkey: Unknown policy event %d\n", c->event); | 2688 | printk("pfkey: Unknown policy event %d\n", c->event); |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 7303b820bea4..c59a78d2923a 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -786,6 +786,22 @@ static int verify_policy_dir(__u8 dir) | |||
786 | return 0; | 786 | return 0; |
787 | } | 787 | } |
788 | 788 | ||
789 | static int verify_policy_type(__u8 type) | ||
790 | { | ||
791 | switch (type) { | ||
792 | case XFRM_POLICY_TYPE_MAIN: | ||
793 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
794 | case XFRM_POLICY_TYPE_SUB: | ||
795 | #endif | ||
796 | break; | ||
797 | |||
798 | default: | ||
799 | return -EINVAL; | ||
800 | }; | ||
801 | |||
802 | return 0; | ||
803 | } | ||
804 | |||
789 | static int verify_newpolicy_info(struct xfrm_userpolicy_info *p) | 805 | static int verify_newpolicy_info(struct xfrm_userpolicy_info *p) |
790 | { | 806 | { |
791 | switch (p->share) { | 807 | switch (p->share) { |
@@ -879,6 +895,29 @@ static int copy_from_user_tmpl(struct xfrm_policy *pol, struct rtattr **xfrma) | |||
879 | return 0; | 895 | return 0; |
880 | } | 896 | } |
881 | 897 | ||
898 | static int copy_from_user_policy_type(u8 *tp, struct rtattr **xfrma) | ||
899 | { | ||
900 | struct rtattr *rt = xfrma[XFRMA_POLICY_TYPE-1]; | ||
901 | struct xfrm_userpolicy_type *upt; | ||
902 | __u8 type = XFRM_POLICY_TYPE_MAIN; | ||
903 | int err; | ||
904 | |||
905 | if (rt) { | ||
906 | if (rt->rta_len < sizeof(*upt)) | ||
907 | return -EINVAL; | ||
908 | |||
909 | upt = RTA_DATA(rt); | ||
910 | type = upt->type; | ||
911 | } | ||
912 | |||
913 | err = verify_policy_type(type); | ||
914 | if (err) | ||
915 | return err; | ||
916 | |||
917 | *tp = type; | ||
918 | return 0; | ||
919 | } | ||
920 | |||
882 | static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p) | 921 | static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p) |
883 | { | 922 | { |
884 | xp->priority = p->priority; | 923 | xp->priority = p->priority; |
@@ -917,16 +956,20 @@ static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p, | |||
917 | 956 | ||
918 | copy_from_user_policy(xp, p); | 957 | copy_from_user_policy(xp, p); |
919 | 958 | ||
959 | err = copy_from_user_policy_type(&xp->type, xfrma); | ||
960 | if (err) | ||
961 | goto error; | ||
962 | |||
920 | if (!(err = copy_from_user_tmpl(xp, xfrma))) | 963 | if (!(err = copy_from_user_tmpl(xp, xfrma))) |
921 | err = copy_from_user_sec_ctx(xp, xfrma); | 964 | err = copy_from_user_sec_ctx(xp, xfrma); |
922 | 965 | if (err) | |
923 | if (err) { | 966 | goto error; |
924 | *errp = err; | ||
925 | kfree(xp); | ||
926 | xp = NULL; | ||
927 | } | ||
928 | 967 | ||
929 | return xp; | 968 | return xp; |
969 | error: | ||
970 | *errp = err; | ||
971 | kfree(xp); | ||
972 | return NULL; | ||
930 | } | 973 | } |
931 | 974 | ||
932 | static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | 975 | static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) |
@@ -1037,6 +1080,29 @@ static inline int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *s | |||
1037 | return 0; | 1080 | return 0; |
1038 | } | 1081 | } |
1039 | 1082 | ||
1083 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
1084 | static int copy_to_user_policy_type(struct xfrm_policy *xp, struct sk_buff *skb) | ||
1085 | { | ||
1086 | struct xfrm_userpolicy_type upt; | ||
1087 | |||
1088 | memset(&upt, 0, sizeof(upt)); | ||
1089 | upt.type = xp->type; | ||
1090 | |||
1091 | RTA_PUT(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt); | ||
1092 | |||
1093 | return 0; | ||
1094 | |||
1095 | rtattr_failure: | ||
1096 | return -1; | ||
1097 | } | ||
1098 | |||
1099 | #else | ||
1100 | static inline int copy_to_user_policy_type(struct xfrm_policy *xp, struct sk_buff *skb) | ||
1101 | { | ||
1102 | return 0; | ||
1103 | } | ||
1104 | #endif | ||
1105 | |||
1040 | static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr) | 1106 | static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr) |
1041 | { | 1107 | { |
1042 | struct xfrm_dump_info *sp = ptr; | 1108 | struct xfrm_dump_info *sp = ptr; |
@@ -1060,6 +1126,8 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr | |||
1060 | goto nlmsg_failure; | 1126 | goto nlmsg_failure; |
1061 | if (copy_to_user_sec_ctx(xp, skb)) | 1127 | if (copy_to_user_sec_ctx(xp, skb)) |
1062 | goto nlmsg_failure; | 1128 | goto nlmsg_failure; |
1129 | if (copy_to_user_policy_type(xp, skb) < 0) | ||
1130 | goto nlmsg_failure; | ||
1063 | 1131 | ||
1064 | nlh->nlmsg_len = skb->tail - b; | 1132 | nlh->nlmsg_len = skb->tail - b; |
1065 | out: | 1133 | out: |
@@ -1081,7 +1149,10 @@ static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) | |||
1081 | info.nlmsg_flags = NLM_F_MULTI; | 1149 | info.nlmsg_flags = NLM_F_MULTI; |
1082 | info.this_idx = 0; | 1150 | info.this_idx = 0; |
1083 | info.start_idx = cb->args[0]; | 1151 | info.start_idx = cb->args[0]; |
1084 | (void) xfrm_policy_walk(dump_one_policy, &info); | 1152 | (void) xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, dump_one_policy, &info); |
1153 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
1154 | (void) xfrm_policy_walk(XFRM_POLICY_TYPE_SUB, dump_one_policy, &info); | ||
1155 | #endif | ||
1085 | cb->args[0] = info.this_idx; | 1156 | cb->args[0] = info.this_idx; |
1086 | 1157 | ||
1087 | return skb->len; | 1158 | return skb->len; |
@@ -1117,6 +1188,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr | |||
1117 | { | 1188 | { |
1118 | struct xfrm_policy *xp; | 1189 | struct xfrm_policy *xp; |
1119 | struct xfrm_userpolicy_id *p; | 1190 | struct xfrm_userpolicy_id *p; |
1191 | __u8 type = XFRM_POLICY_TYPE_MAIN; | ||
1120 | int err; | 1192 | int err; |
1121 | struct km_event c; | 1193 | struct km_event c; |
1122 | int delete; | 1194 | int delete; |
@@ -1124,12 +1196,16 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr | |||
1124 | p = NLMSG_DATA(nlh); | 1196 | p = NLMSG_DATA(nlh); |
1125 | delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY; | 1197 | delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY; |
1126 | 1198 | ||
1199 | err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma); | ||
1200 | if (err) | ||
1201 | return err; | ||
1202 | |||
1127 | err = verify_policy_dir(p->dir); | 1203 | err = verify_policy_dir(p->dir); |
1128 | if (err) | 1204 | if (err) |
1129 | return err; | 1205 | return err; |
1130 | 1206 | ||
1131 | if (p->index) | 1207 | if (p->index) |
1132 | xp = xfrm_policy_byid(p->dir, p->index, delete); | 1208 | xp = xfrm_policy_byid(type, p->dir, p->index, delete); |
1133 | else { | 1209 | else { |
1134 | struct rtattr **rtattrs = (struct rtattr **)xfrma; | 1210 | struct rtattr **rtattrs = (struct rtattr **)xfrma; |
1135 | struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1]; | 1211 | struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1]; |
@@ -1146,7 +1222,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr | |||
1146 | if ((err = security_xfrm_policy_alloc(&tmp, uctx))) | 1222 | if ((err = security_xfrm_policy_alloc(&tmp, uctx))) |
1147 | return err; | 1223 | return err; |
1148 | } | 1224 | } |
1149 | xp = xfrm_policy_bysel_ctx(p->dir, &p->sel, tmp.security, delete); | 1225 | xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, delete); |
1150 | security_xfrm_policy_free(&tmp); | 1226 | security_xfrm_policy_free(&tmp); |
1151 | } | 1227 | } |
1152 | if (xp == NULL) | 1228 | if (xp == NULL) |
@@ -1329,9 +1405,16 @@ out: | |||
1329 | 1405 | ||
1330 | static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | 1406 | static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) |
1331 | { | 1407 | { |
1332 | struct km_event c; | 1408 | struct km_event c; |
1409 | __u8 type = XFRM_POLICY_TYPE_MAIN; | ||
1410 | int err; | ||
1411 | |||
1412 | err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma); | ||
1413 | if (err) | ||
1414 | return err; | ||
1333 | 1415 | ||
1334 | xfrm_policy_flush(); | 1416 | xfrm_policy_flush(type); |
1417 | c.data.type = type; | ||
1335 | c.event = nlh->nlmsg_type; | 1418 | c.event = nlh->nlmsg_type; |
1336 | c.seq = nlh->nlmsg_seq; | 1419 | c.seq = nlh->nlmsg_seq; |
1337 | c.pid = nlh->nlmsg_pid; | 1420 | c.pid = nlh->nlmsg_pid; |
@@ -1344,10 +1427,15 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void * | |||
1344 | struct xfrm_policy *xp; | 1427 | struct xfrm_policy *xp; |
1345 | struct xfrm_user_polexpire *up = NLMSG_DATA(nlh); | 1428 | struct xfrm_user_polexpire *up = NLMSG_DATA(nlh); |
1346 | struct xfrm_userpolicy_info *p = &up->pol; | 1429 | struct xfrm_userpolicy_info *p = &up->pol; |
1430 | __u8 type = XFRM_POLICY_TYPE_MAIN; | ||
1347 | int err = -ENOENT; | 1431 | int err = -ENOENT; |
1348 | 1432 | ||
1433 | err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma); | ||
1434 | if (err) | ||
1435 | return err; | ||
1436 | |||
1349 | if (p->index) | 1437 | if (p->index) |
1350 | xp = xfrm_policy_byid(p->dir, p->index, 0); | 1438 | xp = xfrm_policy_byid(type, p->dir, p->index, 0); |
1351 | else { | 1439 | else { |
1352 | struct rtattr **rtattrs = (struct rtattr **)xfrma; | 1440 | struct rtattr **rtattrs = (struct rtattr **)xfrma; |
1353 | struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1]; | 1441 | struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1]; |
@@ -1364,7 +1452,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void * | |||
1364 | if ((err = security_xfrm_policy_alloc(&tmp, uctx))) | 1452 | if ((err = security_xfrm_policy_alloc(&tmp, uctx))) |
1365 | return err; | 1453 | return err; |
1366 | } | 1454 | } |
1367 | xp = xfrm_policy_bysel_ctx(p->dir, &p->sel, tmp.security, 0); | 1455 | xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, 0); |
1368 | security_xfrm_policy_free(&tmp); | 1456 | security_xfrm_policy_free(&tmp); |
1369 | } | 1457 | } |
1370 | 1458 | ||
@@ -1818,6 +1906,8 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, | |||
1818 | goto nlmsg_failure; | 1906 | goto nlmsg_failure; |
1819 | if (copy_to_user_state_sec_ctx(x, skb)) | 1907 | if (copy_to_user_state_sec_ctx(x, skb)) |
1820 | goto nlmsg_failure; | 1908 | goto nlmsg_failure; |
1909 | if (copy_to_user_policy_type(xp, skb) < 0) | ||
1910 | goto nlmsg_failure; | ||
1821 | 1911 | ||
1822 | nlh->nlmsg_len = skb->tail - b; | 1912 | nlh->nlmsg_len = skb->tail - b; |
1823 | return skb->len; | 1913 | return skb->len; |
@@ -1898,6 +1988,7 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, | |||
1898 | } | 1988 | } |
1899 | 1989 | ||
1900 | copy_from_user_policy(xp, p); | 1990 | copy_from_user_policy(xp, p); |
1991 | xp->type = XFRM_POLICY_TYPE_MAIN; | ||
1901 | copy_templates(xp, ut, nr); | 1992 | copy_templates(xp, ut, nr); |
1902 | 1993 | ||
1903 | if (!xp->security) { | 1994 | if (!xp->security) { |
@@ -1931,6 +2022,8 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, | |||
1931 | goto nlmsg_failure; | 2022 | goto nlmsg_failure; |
1932 | if (copy_to_user_sec_ctx(xp, skb)) | 2023 | if (copy_to_user_sec_ctx(xp, skb)) |
1933 | goto nlmsg_failure; | 2024 | goto nlmsg_failure; |
2025 | if (copy_to_user_policy_type(xp, skb) < 0) | ||
2026 | goto nlmsg_failure; | ||
1934 | upe->hard = !!hard; | 2027 | upe->hard = !!hard; |
1935 | 2028 | ||
1936 | nlh->nlmsg_len = skb->tail - b; | 2029 | nlh->nlmsg_len = skb->tail - b; |
@@ -2002,6 +2095,8 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event * | |||
2002 | copy_to_user_policy(xp, p, dir); | 2095 | copy_to_user_policy(xp, p, dir); |
2003 | if (copy_to_user_tmpl(xp, skb) < 0) | 2096 | if (copy_to_user_tmpl(xp, skb) < 0) |
2004 | goto nlmsg_failure; | 2097 | goto nlmsg_failure; |
2098 | if (copy_to_user_policy_type(xp, skb) < 0) | ||
2099 | goto nlmsg_failure; | ||
2005 | 2100 | ||
2006 | nlh->nlmsg_len = skb->tail - b; | 2101 | nlh->nlmsg_len = skb->tail - b; |
2007 | 2102 | ||
@@ -2019,6 +2114,9 @@ static int xfrm_notify_policy_flush(struct km_event *c) | |||
2019 | struct nlmsghdr *nlh; | 2114 | struct nlmsghdr *nlh; |
2020 | struct sk_buff *skb; | 2115 | struct sk_buff *skb; |
2021 | unsigned char *b; | 2116 | unsigned char *b; |
2117 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
2118 | struct xfrm_userpolicy_type upt; | ||
2119 | #endif | ||
2022 | int len = NLMSG_LENGTH(0); | 2120 | int len = NLMSG_LENGTH(0); |
2023 | 2121 | ||
2024 | skb = alloc_skb(len, GFP_ATOMIC); | 2122 | skb = alloc_skb(len, GFP_ATOMIC); |
@@ -2028,6 +2126,13 @@ static int xfrm_notify_policy_flush(struct km_event *c) | |||
2028 | 2126 | ||
2029 | 2127 | ||
2030 | nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0); | 2128 | nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0); |
2129 | nlh->nlmsg_flags = 0; | ||
2130 | |||
2131 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
2132 | memset(&upt, 0, sizeof(upt)); | ||
2133 | upt.type = c->data.type; | ||
2134 | RTA_PUT(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt); | ||
2135 | #endif | ||
2031 | 2136 | ||
2032 | nlh->nlmsg_len = skb->tail - b; | 2137 | nlh->nlmsg_len = skb->tail - b; |
2033 | 2138 | ||
@@ -2035,6 +2140,9 @@ static int xfrm_notify_policy_flush(struct km_event *c) | |||
2035 | return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); | 2140 | return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); |
2036 | 2141 | ||
2037 | nlmsg_failure: | 2142 | nlmsg_failure: |
2143 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
2144 | rtattr_failure: | ||
2145 | #endif | ||
2038 | kfree_skb(skb); | 2146 | kfree_skb(skb); |
2039 | return -1; | 2147 | return -1; |
2040 | } | 2148 | } |