aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_input.c41
-rw-r--r--net/xfrm/xfrm_output.c6
-rw-r--r--net/xfrm/xfrm_policy.c63
3 files changed, 87 insertions, 23 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 8624cbdb2a1e..493243fc5fe5 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -119,8 +119,10 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
119 struct sec_path *sp; 119 struct sec_path *sp;
120 120
121 sp = secpath_dup(skb->sp); 121 sp = secpath_dup(skb->sp);
122 if (!sp) 122 if (!sp) {
123 XFRM_INC_STATS(LINUX_MIB_XFRMINERROR);
123 goto drop; 124 goto drop;
125 }
124 if (skb->sp) 126 if (skb->sp)
125 secpath_put(skb->sp); 127 secpath_put(skb->sp);
126 skb->sp = sp; 128 skb->sp = sp;
@@ -131,31 +133,45 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
131 family = XFRM_SPI_SKB_CB(skb)->family; 133 family = XFRM_SPI_SKB_CB(skb)->family;
132 134
133 seq = 0; 135 seq = 0;
134 if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) 136 if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) {
137 XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR);
135 goto drop; 138 goto drop;
139 }
136 140
137 do { 141 do {
138 if (skb->sp->len == XFRM_MAX_DEPTH) 142 if (skb->sp->len == XFRM_MAX_DEPTH) {
143 XFRM_INC_STATS(LINUX_MIB_XFRMINBUFFERERROR);
139 goto drop; 144 goto drop;
145 }
140 146
141 x = xfrm_state_lookup(daddr, spi, nexthdr, family); 147 x = xfrm_state_lookup(daddr, spi, nexthdr, family);
142 if (x == NULL) 148 if (x == NULL) {
149 XFRM_INC_STATS(LINUX_MIB_XFRMINNOSTATES);
143 goto drop; 150 goto drop;
151 }
144 152
145 skb->sp->xvec[skb->sp->len++] = x; 153 skb->sp->xvec[skb->sp->len++] = x;
146 154
147 spin_lock(&x->lock); 155 spin_lock(&x->lock);
148 if (unlikely(x->km.state != XFRM_STATE_VALID)) 156 if (unlikely(x->km.state != XFRM_STATE_VALID)) {
157 XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEINVALID);
149 goto drop_unlock; 158 goto drop_unlock;
159 }
150 160
151 if ((x->encap ? x->encap->encap_type : 0) != encap_type) 161 if ((x->encap ? x->encap->encap_type : 0) != encap_type) {
162 XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEINVALID);
152 goto drop_unlock; 163 goto drop_unlock;
164 }
153 165
154 if (x->props.replay_window && xfrm_replay_check(x, seq)) 166 if (x->props.replay_window && xfrm_replay_check(x, seq)) {
167 XFRM_INC_STATS(LINUX_MIB_XFRMINSEQOUTOFWINDOW);
155 goto drop_unlock; 168 goto drop_unlock;
169 }
156 170
157 if (xfrm_state_check_expire(x)) 171 if (xfrm_state_check_expire(x)) {
172 XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEEXPIRED);
158 goto drop_unlock; 173 goto drop_unlock;
174 }
159 175
160 spin_unlock(&x->lock); 176 spin_unlock(&x->lock);
161 177
@@ -171,6 +187,7 @@ resume:
171 if (nexthdr <= 0) { 187 if (nexthdr <= 0) {
172 if (nexthdr == -EBADMSG) 188 if (nexthdr == -EBADMSG)
173 x->stats.integrity_failed++; 189 x->stats.integrity_failed++;
190 XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEPROTOERROR);
174 goto drop_unlock; 191 goto drop_unlock;
175 } 192 }
176 193
@@ -187,8 +204,10 @@ resume:
187 204
188 XFRM_MODE_SKB_CB(skb)->protocol = nexthdr; 205 XFRM_MODE_SKB_CB(skb)->protocol = nexthdr;
189 206
190 if (x->inner_mode->input(x, skb)) 207 if (x->inner_mode->input(x, skb)) {
208 XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMODEERROR);
191 goto drop; 209 goto drop;
210 }
192 211
193 if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) { 212 if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
194 decaps = 1; 213 decaps = 1;
@@ -203,8 +222,10 @@ resume:
203 family = x->outer_mode->afinfo->family; 222 family = x->outer_mode->afinfo->family;
204 223
205 err = xfrm_parse_spi(skb, nexthdr, &spi, &seq); 224 err = xfrm_parse_spi(skb, nexthdr, &spi, &seq);
206 if (err < 0) 225 if (err < 0) {
226 XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR);
207 goto drop; 227 goto drop;
228 }
208 } while (!err); 229 } while (!err);
209 230
210 nf_reset(skb); 231 nf_reset(skb);
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 26fa0cb78c94..867484a046af 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -69,10 +69,13 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
69 err = x->type->output(x, skb); 69 err = x->type->output(x, skb);
70 70
71resume: 71resume:
72 if (err) 72 if (err) {
73 XFRM_INC_STATS(LINUX_MIB_XFRMOUTSTATEPROTOERROR);
73 goto error_nolock; 74 goto error_nolock;
75 }
74 76
75 if (!(skb->dst = dst_pop(dst))) { 77 if (!(skb->dst = dst_pop(dst))) {
78 XFRM_INC_STATS(LINUX_MIB_XFRMOUTERROR);
76 err = -EHOSTUNREACH; 79 err = -EHOSTUNREACH;
77 goto error_nolock; 80 goto error_nolock;
78 } 81 }
@@ -167,6 +170,7 @@ int xfrm_output(struct sk_buff *skb)
167 if (skb->ip_summed == CHECKSUM_PARTIAL) { 170 if (skb->ip_summed == CHECKSUM_PARTIAL) {
168 err = skb_checksum_help(skb); 171 err = skb_checksum_help(skb);
169 if (err) { 172 if (err) {
173 XFRM_INC_STATS(LINUX_MIB_XFRMOUTERROR);
170 kfree_skb(skb); 174 kfree_skb(skb);
171 return err; 175 return err;
172 } 176 }
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 32ddb7b12e7f..74807a7d3d69 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1494,8 +1494,10 @@ restart:
1494 if (sk && sk->sk_policy[XFRM_POLICY_OUT]) { 1494 if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
1495 policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); 1495 policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
1496 err = PTR_ERR(policy); 1496 err = PTR_ERR(policy);
1497 if (IS_ERR(policy)) 1497 if (IS_ERR(policy)) {
1498 XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR);
1498 goto dropdst; 1499 goto dropdst;
1500 }
1499 } 1501 }
1500 1502
1501 if (!policy) { 1503 if (!policy) {
@@ -1529,6 +1531,7 @@ restart:
1529 default: 1531 default:
1530 case XFRM_POLICY_BLOCK: 1532 case XFRM_POLICY_BLOCK:
1531 /* Prohibit the flow */ 1533 /* Prohibit the flow */
1534 XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLBLOCK);
1532 err = -EPERM; 1535 err = -EPERM;
1533 goto error; 1536 goto error;
1534 1537
@@ -1548,6 +1551,7 @@ restart:
1548 */ 1551 */
1549 dst = xfrm_find_bundle(fl, policy, family); 1552 dst = xfrm_find_bundle(fl, policy, family);
1550 if (IS_ERR(dst)) { 1553 if (IS_ERR(dst)) {
1554 XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
1551 err = PTR_ERR(dst); 1555 err = PTR_ERR(dst);
1552 goto error; 1556 goto error;
1553 } 1557 }
@@ -1562,10 +1566,12 @@ restart:
1562 XFRM_POLICY_OUT); 1566 XFRM_POLICY_OUT);
1563 if (pols[1]) { 1567 if (pols[1]) {
1564 if (IS_ERR(pols[1])) { 1568 if (IS_ERR(pols[1])) {
1569 XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR);
1565 err = PTR_ERR(pols[1]); 1570 err = PTR_ERR(pols[1]);
1566 goto error; 1571 goto error;
1567 } 1572 }
1568 if (pols[1]->action == XFRM_POLICY_BLOCK) { 1573 if (pols[1]->action == XFRM_POLICY_BLOCK) {
1574 XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLBLOCK);
1569 err = -EPERM; 1575 err = -EPERM;
1570 goto error; 1576 goto error;
1571 } 1577 }
@@ -1611,6 +1617,7 @@ restart:
1611 nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family); 1617 nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family);
1612 1618
1613 if (nx == -EAGAIN && signal_pending(current)) { 1619 if (nx == -EAGAIN && signal_pending(current)) {
1620 XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES);
1614 err = -ERESTART; 1621 err = -ERESTART;
1615 goto error; 1622 goto error;
1616 } 1623 }
@@ -1621,8 +1628,10 @@ restart:
1621 } 1628 }
1622 err = nx; 1629 err = nx;
1623 } 1630 }
1624 if (err < 0) 1631 if (err < 0) {
1632 XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES);
1625 goto error; 1633 goto error;
1634 }
1626 } 1635 }
1627 if (nx == 0) { 1636 if (nx == 0) {
1628 /* Flow passes not transformed. */ 1637 /* Flow passes not transformed. */
@@ -1632,8 +1641,10 @@ restart:
1632 1641
1633 dst = xfrm_bundle_create(policy, xfrm, nx, fl, dst_orig); 1642 dst = xfrm_bundle_create(policy, xfrm, nx, fl, dst_orig);
1634 err = PTR_ERR(dst); 1643 err = PTR_ERR(dst);
1635 if (IS_ERR(dst)) 1644 if (IS_ERR(dst)) {
1645 XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLEGENERROR);
1636 goto error; 1646 goto error;
1647 }
1637 1648
1638 for (pi = 0; pi < npols; pi++) { 1649 for (pi = 0; pi < npols; pi++) {
1639 read_lock_bh(&pols[pi]->lock); 1650 read_lock_bh(&pols[pi]->lock);
@@ -1652,6 +1663,10 @@ restart:
1652 if (dst) 1663 if (dst)
1653 dst_free(dst); 1664 dst_free(dst);
1654 1665
1666 if (pol_dead)
1667 XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLDEAD);
1668 else
1669 XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
1655 err = -EHOSTUNREACH; 1670 err = -EHOSTUNREACH;
1656 goto error; 1671 goto error;
1657 } 1672 }
@@ -1664,6 +1679,7 @@ restart:
1664 write_unlock_bh(&policy->lock); 1679 write_unlock_bh(&policy->lock);
1665 if (dst) 1680 if (dst)
1666 dst_free(dst); 1681 dst_free(dst);
1682 XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
1667 goto error; 1683 goto error;
1668 } 1684 }
1669 1685
@@ -1817,8 +1833,11 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1817 dir &= XFRM_POLICY_MASK; 1833 dir &= XFRM_POLICY_MASK;
1818 fl_dir = policy_to_flow_dir(dir); 1834 fl_dir = policy_to_flow_dir(dir);
1819 1835
1820 if (__xfrm_decode_session(skb, &fl, family, reverse) < 0) 1836 if (__xfrm_decode_session(skb, &fl, family, reverse) < 0) {
1837 XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR);
1821 return 0; 1838 return 0;
1839 }
1840
1822 nf_nat_decode_session(skb, &fl, family); 1841 nf_nat_decode_session(skb, &fl, family);
1823 1842
1824 /* First, check used SA against their selectors. */ 1843 /* First, check used SA against their selectors. */
@@ -1827,28 +1846,35 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1827 1846
1828 for (i=skb->sp->len-1; i>=0; i--) { 1847 for (i=skb->sp->len-1; i>=0; i--) {
1829 struct xfrm_state *x = skb->sp->xvec[i]; 1848 struct xfrm_state *x = skb->sp->xvec[i];
1830 if (!xfrm_selector_match(&x->sel, &fl, family)) 1849 if (!xfrm_selector_match(&x->sel, &fl, family)) {
1850 XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMISMATCH);
1831 return 0; 1851 return 0;
1852 }
1832 } 1853 }
1833 } 1854 }
1834 1855
1835 pol = NULL; 1856 pol = NULL;
1836 if (sk && sk->sk_policy[dir]) { 1857 if (sk && sk->sk_policy[dir]) {
1837 pol = xfrm_sk_policy_lookup(sk, dir, &fl); 1858 pol = xfrm_sk_policy_lookup(sk, dir, &fl);
1838 if (IS_ERR(pol)) 1859 if (IS_ERR(pol)) {
1860 XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR);
1839 return 0; 1861 return 0;
1862 }
1840 } 1863 }
1841 1864
1842 if (!pol) 1865 if (!pol)
1843 pol = flow_cache_lookup(&fl, family, fl_dir, 1866 pol = flow_cache_lookup(&fl, family, fl_dir,
1844 xfrm_policy_lookup); 1867 xfrm_policy_lookup);
1845 1868
1846 if (IS_ERR(pol)) 1869 if (IS_ERR(pol)) {
1870 XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR);
1847 return 0; 1871 return 0;
1872 }
1848 1873
1849 if (!pol) { 1874 if (!pol) {
1850 if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) { 1875 if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) {
1851 xfrm_secpath_reject(xerr_idx, skb, &fl); 1876 xfrm_secpath_reject(xerr_idx, skb, &fl);
1877 XFRM_INC_STATS(LINUX_MIB_XFRMINNOPOLS);
1852 return 0; 1878 return 0;
1853 } 1879 }
1854 return 1; 1880 return 1;
@@ -1864,8 +1890,10 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1864 &fl, family, 1890 &fl, family,
1865 XFRM_POLICY_IN); 1891 XFRM_POLICY_IN);
1866 if (pols[1]) { 1892 if (pols[1]) {
1867 if (IS_ERR(pols[1])) 1893 if (IS_ERR(pols[1])) {
1894 XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR);
1868 return 0; 1895 return 0;
1896 }
1869 pols[1]->curlft.use_time = get_seconds(); 1897 pols[1]->curlft.use_time = get_seconds();
1870 npols ++; 1898 npols ++;
1871 } 1899 }
@@ -1886,10 +1914,14 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1886 1914
1887 for (pi = 0; pi < npols; pi++) { 1915 for (pi = 0; pi < npols; pi++) {
1888 if (pols[pi] != pol && 1916 if (pols[pi] != pol &&
1889 pols[pi]->action != XFRM_POLICY_ALLOW) 1917 pols[pi]->action != XFRM_POLICY_ALLOW) {
1918 XFRM_INC_STATS(LINUX_MIB_XFRMINPOLBLOCK);
1890 goto reject; 1919 goto reject;
1891 if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH) 1920 }
1921 if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH) {
1922 XFRM_INC_STATS(LINUX_MIB_XFRMINBUFFERERROR);
1892 goto reject_error; 1923 goto reject_error;
1924 }
1893 for (i = 0; i < pols[pi]->xfrm_nr; i++) 1925 for (i = 0; i < pols[pi]->xfrm_nr; i++)
1894 tpp[ti++] = &pols[pi]->xfrm_vec[i]; 1926 tpp[ti++] = &pols[pi]->xfrm_vec[i];
1895 } 1927 }
@@ -1911,16 +1943,20 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1911 if (k < -1) 1943 if (k < -1)
1912 /* "-2 - errored_index" returned */ 1944 /* "-2 - errored_index" returned */
1913 xerr_idx = -(2+k); 1945 xerr_idx = -(2+k);
1946 XFRM_INC_STATS(LINUX_MIB_XFRMINTMPLMISMATCH);
1914 goto reject; 1947 goto reject;
1915 } 1948 }
1916 } 1949 }
1917 1950
1918 if (secpath_has_nontransport(sp, k, &xerr_idx)) 1951 if (secpath_has_nontransport(sp, k, &xerr_idx)) {
1952 XFRM_INC_STATS(LINUX_MIB_XFRMINTMPLMISMATCH);
1919 goto reject; 1953 goto reject;
1954 }
1920 1955
1921 xfrm_pols_put(pols, npols); 1956 xfrm_pols_put(pols, npols);
1922 return 1; 1957 return 1;
1923 } 1958 }
1959 XFRM_INC_STATS(LINUX_MIB_XFRMINPOLBLOCK);
1924 1960
1925reject: 1961reject:
1926 xfrm_secpath_reject(xerr_idx, skb, &fl); 1962 xfrm_secpath_reject(xerr_idx, skb, &fl);
@@ -1934,8 +1970,11 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
1934{ 1970{
1935 struct flowi fl; 1971 struct flowi fl;
1936 1972
1937 if (xfrm_decode_session(skb, &fl, family) < 0) 1973 if (xfrm_decode_session(skb, &fl, family) < 0) {
1974 /* XXX: we should have something like FWDHDRERROR here. */
1975 XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR);
1938 return 0; 1976 return 0;
1977 }
1939 1978
1940 return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0; 1979 return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0;
1941} 1980}