diff options
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 63 |
1 files changed, 51 insertions, 12 deletions
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 | ||
1925 | reject: | 1961 | reject: |
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 | } |