aboutsummaryrefslogtreecommitdiffstats
path: root/net/key/af_key.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/key/af_key.c')
-rw-r--r--net/key/af_key.c143
1 files changed, 110 insertions, 33 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c
index e9ef9af4a53b..1fb0fe42a72e 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -48,6 +48,17 @@ struct pfkey_sock {
48 struct sock sk; 48 struct sock sk;
49 int registered; 49 int registered;
50 int promisc; 50 int promisc;
51
52 struct {
53 uint8_t msg_version;
54 uint32_t msg_pid;
55 int (*dump)(struct pfkey_sock *sk);
56 void (*done)(struct pfkey_sock *sk);
57 union {
58 struct xfrm_policy_walk policy;
59 struct xfrm_state_walk state;
60 } u;
61 } dump;
51}; 62};
52 63
53static inline struct pfkey_sock *pfkey_sk(struct sock *sk) 64static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
@@ -55,6 +66,27 @@ static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
55 return (struct pfkey_sock *)sk; 66 return (struct pfkey_sock *)sk;
56} 67}
57 68
69static int pfkey_can_dump(struct sock *sk)
70{
71 if (3 * atomic_read(&sk->sk_rmem_alloc) <= 2 * sk->sk_rcvbuf)
72 return 1;
73 return 0;
74}
75
76static int pfkey_do_dump(struct pfkey_sock *pfk)
77{
78 int rc;
79
80 rc = pfk->dump.dump(pfk);
81 if (rc == -ENOBUFS)
82 return 0;
83
84 pfk->dump.done(pfk);
85 pfk->dump.dump = NULL;
86 pfk->dump.done = NULL;
87 return rc;
88}
89
58static void pfkey_sock_destruct(struct sock *sk) 90static void pfkey_sock_destruct(struct sock *sk)
59{ 91{
60 skb_queue_purge(&sk->sk_receive_queue); 92 skb_queue_purge(&sk->sk_receive_queue);
@@ -1709,45 +1741,60 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
1709 return 0; 1741 return 0;
1710} 1742}
1711 1743
1712struct pfkey_dump_data
1713{
1714 struct sk_buff *skb;
1715 struct sadb_msg *hdr;
1716 struct sock *sk;
1717};
1718
1719static int dump_sa(struct xfrm_state *x, int count, void *ptr) 1744static int dump_sa(struct xfrm_state *x, int count, void *ptr)
1720{ 1745{
1721 struct pfkey_dump_data *data = ptr; 1746 struct pfkey_sock *pfk = ptr;
1722 struct sk_buff *out_skb; 1747 struct sk_buff *out_skb;
1723 struct sadb_msg *out_hdr; 1748 struct sadb_msg *out_hdr;
1724 1749
1750 if (!pfkey_can_dump(&pfk->sk))
1751 return -ENOBUFS;
1752
1725 out_skb = pfkey_xfrm_state2msg(x); 1753 out_skb = pfkey_xfrm_state2msg(x);
1726 if (IS_ERR(out_skb)) 1754 if (IS_ERR(out_skb))
1727 return PTR_ERR(out_skb); 1755 return PTR_ERR(out_skb);
1728 1756
1729 out_hdr = (struct sadb_msg *) out_skb->data; 1757 out_hdr = (struct sadb_msg *) out_skb->data;
1730 out_hdr->sadb_msg_version = data->hdr->sadb_msg_version; 1758 out_hdr->sadb_msg_version = pfk->dump.msg_version;
1731 out_hdr->sadb_msg_type = SADB_DUMP; 1759 out_hdr->sadb_msg_type = SADB_DUMP;
1732 out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto); 1760 out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
1733 out_hdr->sadb_msg_errno = 0; 1761 out_hdr->sadb_msg_errno = 0;
1734 out_hdr->sadb_msg_reserved = 0; 1762 out_hdr->sadb_msg_reserved = 0;
1735 out_hdr->sadb_msg_seq = count; 1763 out_hdr->sadb_msg_seq = count;
1736 out_hdr->sadb_msg_pid = data->hdr->sadb_msg_pid; 1764 out_hdr->sadb_msg_pid = pfk->dump.msg_pid;
1737 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, data->sk); 1765 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk);
1738 return 0; 1766 return 0;
1739} 1767}
1740 1768
1769static int pfkey_dump_sa(struct pfkey_sock *pfk)
1770{
1771 return xfrm_state_walk(&pfk->dump.u.state, dump_sa, (void *) pfk);
1772}
1773
1774static void pfkey_dump_sa_done(struct pfkey_sock *pfk)
1775{
1776 xfrm_state_walk_done(&pfk->dump.u.state);
1777}
1778
1741static int pfkey_dump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) 1779static int pfkey_dump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
1742{ 1780{
1743 u8 proto; 1781 u8 proto;
1744 struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk }; 1782 struct pfkey_sock *pfk = pfkey_sk(sk);
1783
1784 if (pfk->dump.dump != NULL)
1785 return -EBUSY;
1745 1786
1746 proto = pfkey_satype2proto(hdr->sadb_msg_satype); 1787 proto = pfkey_satype2proto(hdr->sadb_msg_satype);
1747 if (proto == 0) 1788 if (proto == 0)
1748 return -EINVAL; 1789 return -EINVAL;
1749 1790
1750 return xfrm_state_walk(proto, dump_sa, &data); 1791 pfk->dump.msg_version = hdr->sadb_msg_version;
1792 pfk->dump.msg_pid = hdr->sadb_msg_pid;
1793 pfk->dump.dump = pfkey_dump_sa;
1794 pfk->dump.done = pfkey_dump_sa_done;
1795 xfrm_state_walk_init(&pfk->dump.u.state, proto);
1796
1797 return pfkey_do_dump(pfk);
1751} 1798}
1752 1799
1753static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) 1800static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
@@ -1780,7 +1827,9 @@ static int check_reqid(struct xfrm_policy *xp, int dir, int count, void *ptr)
1780 1827
1781static u32 gen_reqid(void) 1828static u32 gen_reqid(void)
1782{ 1829{
1830 struct xfrm_policy_walk walk;
1783 u32 start; 1831 u32 start;
1832 int rc;
1784 static u32 reqid = IPSEC_MANUAL_REQID_MAX; 1833 static u32 reqid = IPSEC_MANUAL_REQID_MAX;
1785 1834
1786 start = reqid; 1835 start = reqid;
@@ -1788,8 +1837,10 @@ static u32 gen_reqid(void)
1788 ++reqid; 1837 ++reqid;
1789 if (reqid == 0) 1838 if (reqid == 0)
1790 reqid = IPSEC_MANUAL_REQID_MAX+1; 1839 reqid = IPSEC_MANUAL_REQID_MAX+1;
1791 if (xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, check_reqid, 1840 xfrm_policy_walk_init(&walk, XFRM_POLICY_TYPE_MAIN);
1792 (void*)&reqid) != -EEXIST) 1841 rc = xfrm_policy_walk(&walk, check_reqid, (void*)&reqid);
1842 xfrm_policy_walk_done(&walk);
1843 if (rc != -EEXIST)
1793 return reqid; 1844 return reqid;
1794 } while (reqid != start); 1845 } while (reqid != start);
1795 return 0; 1846 return 0;
@@ -2241,7 +2292,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
2241 goto out; 2292 goto out;
2242 } 2293 }
2243 2294
2244 err = security_xfrm_policy_alloc(xp, uctx); 2295 err = security_xfrm_policy_alloc(&xp->security, uctx);
2245 kfree(uctx); 2296 kfree(uctx);
2246 2297
2247 if (err) 2298 if (err)
@@ -2301,10 +2352,11 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
2301 int err; 2352 int err;
2302 struct sadb_address *sa; 2353 struct sadb_address *sa;
2303 struct sadb_x_policy *pol; 2354 struct sadb_x_policy *pol;
2304 struct xfrm_policy *xp, tmp; 2355 struct xfrm_policy *xp;
2305 struct xfrm_selector sel; 2356 struct xfrm_selector sel;
2306 struct km_event c; 2357 struct km_event c;
2307 struct sadb_x_sec_ctx *sec_ctx; 2358 struct sadb_x_sec_ctx *sec_ctx;
2359 struct xfrm_sec_ctx *pol_ctx;
2308 2360
2309 if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], 2361 if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
2310 ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || 2362 ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -2334,25 +2386,23 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
2334 sel.dport_mask = htons(0xffff); 2386 sel.dport_mask = htons(0xffff);
2335 2387
2336 sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1]; 2388 sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
2337 memset(&tmp, 0, sizeof(struct xfrm_policy));
2338
2339 if (sec_ctx != NULL) { 2389 if (sec_ctx != NULL) {
2340 struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); 2390 struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
2341 2391
2342 if (!uctx) 2392 if (!uctx)
2343 return -ENOMEM; 2393 return -ENOMEM;
2344 2394
2345 err = security_xfrm_policy_alloc(&tmp, uctx); 2395 err = security_xfrm_policy_alloc(&pol_ctx, uctx);
2346 kfree(uctx); 2396 kfree(uctx);
2347
2348 if (err) 2397 if (err)
2349 return err; 2398 return err;
2350 } 2399 } else
2351 2400 pol_ctx = NULL;
2352 xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1,
2353 &sel, tmp.security, 1, &err);
2354 security_xfrm_policy_free(&tmp);
2355 2401
2402 xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN,
2403 pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
2404 1, &err);
2405 security_xfrm_policy_free(pol_ctx);
2356 if (xp == NULL) 2406 if (xp == NULL)
2357 return -ENOENT; 2407 return -ENOENT;
2358 2408
@@ -2638,11 +2688,14 @@ out:
2638 2688
2639static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr) 2689static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
2640{ 2690{
2641 struct pfkey_dump_data *data = ptr; 2691 struct pfkey_sock *pfk = ptr;
2642 struct sk_buff *out_skb; 2692 struct sk_buff *out_skb;
2643 struct sadb_msg *out_hdr; 2693 struct sadb_msg *out_hdr;
2644 int err; 2694 int err;
2645 2695
2696 if (!pfkey_can_dump(&pfk->sk))
2697 return -ENOBUFS;
2698
2646 out_skb = pfkey_xfrm_policy2msg_prep(xp); 2699 out_skb = pfkey_xfrm_policy2msg_prep(xp);
2647 if (IS_ERR(out_skb)) 2700 if (IS_ERR(out_skb))
2648 return PTR_ERR(out_skb); 2701 return PTR_ERR(out_skb);
@@ -2652,21 +2705,40 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
2652 return err; 2705 return err;
2653 2706
2654 out_hdr = (struct sadb_msg *) out_skb->data; 2707 out_hdr = (struct sadb_msg *) out_skb->data;
2655 out_hdr->sadb_msg_version = data->hdr->sadb_msg_version; 2708 out_hdr->sadb_msg_version = pfk->dump.msg_version;
2656 out_hdr->sadb_msg_type = SADB_X_SPDDUMP; 2709 out_hdr->sadb_msg_type = SADB_X_SPDDUMP;
2657 out_hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; 2710 out_hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
2658 out_hdr->sadb_msg_errno = 0; 2711 out_hdr->sadb_msg_errno = 0;
2659 out_hdr->sadb_msg_seq = count; 2712 out_hdr->sadb_msg_seq = count;
2660 out_hdr->sadb_msg_pid = data->hdr->sadb_msg_pid; 2713 out_hdr->sadb_msg_pid = pfk->dump.msg_pid;
2661 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, data->sk); 2714 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk);
2662 return 0; 2715 return 0;
2663} 2716}
2664 2717
2718static int pfkey_dump_sp(struct pfkey_sock *pfk)
2719{
2720 return xfrm_policy_walk(&pfk->dump.u.policy, dump_sp, (void *) pfk);
2721}
2722
2723static void pfkey_dump_sp_done(struct pfkey_sock *pfk)
2724{
2725 xfrm_policy_walk_done(&pfk->dump.u.policy);
2726}
2727
2665static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) 2728static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
2666{ 2729{
2667 struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk }; 2730 struct pfkey_sock *pfk = pfkey_sk(sk);
2731
2732 if (pfk->dump.dump != NULL)
2733 return -EBUSY;
2734
2735 pfk->dump.msg_version = hdr->sadb_msg_version;
2736 pfk->dump.msg_pid = hdr->sadb_msg_pid;
2737 pfk->dump.dump = pfkey_dump_sp;
2738 pfk->dump.done = pfkey_dump_sp_done;
2739 xfrm_policy_walk_init(&pfk->dump.u.policy, XFRM_POLICY_TYPE_MAIN);
2668 2740
2669 return xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, dump_sp, &data); 2741 return pfkey_do_dump(pfk);
2670} 2742}
2671 2743
2672static int key_notify_policy_flush(struct km_event *c) 2744static int key_notify_policy_flush(struct km_event *c)
@@ -3225,7 +3297,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
3225 if ((*dir = verify_sec_ctx_len(p))) 3297 if ((*dir = verify_sec_ctx_len(p)))
3226 goto out; 3298 goto out;
3227 uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); 3299 uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
3228 *dir = security_xfrm_policy_alloc(xp, uctx); 3300 *dir = security_xfrm_policy_alloc(&xp->security, uctx);
3229 kfree(uctx); 3301 kfree(uctx);
3230 3302
3231 if (*dir) 3303 if (*dir)
@@ -3671,6 +3743,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
3671 int flags) 3743 int flags)
3672{ 3744{
3673 struct sock *sk = sock->sk; 3745 struct sock *sk = sock->sk;
3746 struct pfkey_sock *pfk = pfkey_sk(sk);
3674 struct sk_buff *skb; 3747 struct sk_buff *skb;
3675 int copied, err; 3748 int copied, err;
3676 3749
@@ -3698,6 +3771,10 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
3698 3771
3699 err = (flags & MSG_TRUNC) ? skb->len : copied; 3772 err = (flags & MSG_TRUNC) ? skb->len : copied;
3700 3773
3774 if (pfk->dump.dump != NULL &&
3775 3 * atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf)
3776 pfkey_do_dump(pfk);
3777
3701out_free: 3778out_free:
3702 skb_free_datagram(sk, skb); 3779 skb_free_datagram(sk, skb);
3703out: 3780out: