diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2011-04-27 05:27:47 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-08 10:49:08 -0500 |
commit | 0fd0ea064c30022577f62d9060889d964123be6f (patch) | |
tree | 937fb63d9a6072b51594d933814aab769d814f3b | |
parent | d9cc6e231897a9ab1a94e6cfe12d71bfec0b7a81 (diff) |
drbd: Consider all crypto options in connect and in net-options
So for this was simply not considered after the options have been
re-arranged.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 230 |
1 files changed, 121 insertions, 109 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index a16089ce0a56..f85cef448387 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -1727,6 +1727,88 @@ check_net_options(struct drbd_tconn *tconn, struct net_conf *new_conf) | |||
1727 | return rv; | 1727 | return rv; |
1728 | } | 1728 | } |
1729 | 1729 | ||
1730 | struct crypto { | ||
1731 | struct crypto_hash *verify_tfm; | ||
1732 | struct crypto_hash *csums_tfm; | ||
1733 | struct crypto_hash *cram_hmac_tfm; | ||
1734 | struct crypto_hash *integrity_w_tfm; | ||
1735 | struct crypto_hash *integrity_r_tfm; | ||
1736 | void *int_dig_in; | ||
1737 | void *int_dig_vv; | ||
1738 | }; | ||
1739 | |||
1740 | static int | ||
1741 | alloc_tfm(struct crypto_hash **tfm, char *tfm_name, int err_alg, int err_nd) | ||
1742 | { | ||
1743 | if (!tfm_name[0]) | ||
1744 | return NO_ERROR; | ||
1745 | |||
1746 | *tfm = crypto_alloc_hash(tfm_name, 0, CRYPTO_ALG_ASYNC); | ||
1747 | if (IS_ERR(*tfm)) { | ||
1748 | *tfm = NULL; | ||
1749 | return err_alg; | ||
1750 | } | ||
1751 | |||
1752 | if (!drbd_crypto_is_hash(crypto_hash_tfm(*tfm))) | ||
1753 | return err_nd; | ||
1754 | |||
1755 | return NO_ERROR; | ||
1756 | } | ||
1757 | |||
1758 | static enum drbd_ret_code | ||
1759 | alloc_crypto(struct crypto *crypto, struct net_conf *new_conf) | ||
1760 | { | ||
1761 | char hmac_name[CRYPTO_MAX_ALG_NAME]; | ||
1762 | enum drbd_ret_code rv; | ||
1763 | int hash_size; | ||
1764 | |||
1765 | rv = alloc_tfm(&crypto->csums_tfm, new_conf->csums_alg, | ||
1766 | ERR_CSUMS_ALG, ERR_CSUMS_ALG_ND); | ||
1767 | if (rv != NO_ERROR) | ||
1768 | return rv; | ||
1769 | rv = alloc_tfm(&crypto->verify_tfm, new_conf->verify_alg, | ||
1770 | ERR_VERIFY_ALG, ERR_VERIFY_ALG_ND); | ||
1771 | if (rv != NO_ERROR) | ||
1772 | return rv; | ||
1773 | rv = alloc_tfm(&crypto->integrity_w_tfm, new_conf->integrity_alg, | ||
1774 | ERR_INTEGRITY_ALG, ERR_INTEGRITY_ALG_ND); | ||
1775 | if (rv != NO_ERROR) | ||
1776 | return rv; | ||
1777 | rv = alloc_tfm(&crypto->integrity_r_tfm, new_conf->integrity_alg, | ||
1778 | ERR_INTEGRITY_ALG, ERR_INTEGRITY_ALG_ND); | ||
1779 | if (rv != NO_ERROR) | ||
1780 | return rv; | ||
1781 | if (new_conf->cram_hmac_alg[0] != 0) { | ||
1782 | snprintf(hmac_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)", | ||
1783 | new_conf->cram_hmac_alg); | ||
1784 | |||
1785 | rv = alloc_tfm(&crypto->cram_hmac_tfm, hmac_name, | ||
1786 | ERR_AUTH_ALG, ERR_AUTH_ALG_ND); | ||
1787 | } | ||
1788 | if (crypto->integrity_w_tfm) { | ||
1789 | hash_size = crypto_hash_digestsize(crypto->integrity_w_tfm); | ||
1790 | crypto->int_dig_in = kmalloc(hash_size, GFP_KERNEL); | ||
1791 | if (!crypto->int_dig_in) | ||
1792 | return ERR_NOMEM; | ||
1793 | crypto->int_dig_vv = kmalloc(hash_size, GFP_KERNEL); | ||
1794 | if (!crypto->int_dig_vv) | ||
1795 | return ERR_NOMEM; | ||
1796 | } | ||
1797 | |||
1798 | return rv; | ||
1799 | } | ||
1800 | |||
1801 | static void free_crypto(struct crypto *crypto) | ||
1802 | { | ||
1803 | kfree(crypto->int_dig_in); | ||
1804 | kfree(crypto->int_dig_vv); | ||
1805 | crypto_free_hash(crypto->cram_hmac_tfm); | ||
1806 | crypto_free_hash(crypto->integrity_w_tfm); | ||
1807 | crypto_free_hash(crypto->integrity_r_tfm); | ||
1808 | crypto_free_hash(crypto->csums_tfm); | ||
1809 | crypto_free_hash(crypto->verify_tfm); | ||
1810 | } | ||
1811 | |||
1730 | int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) | 1812 | int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) |
1731 | { | 1813 | { |
1732 | enum drbd_ret_code retcode; | 1814 | enum drbd_ret_code retcode; |
@@ -1735,9 +1817,7 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) | |||
1735 | int err; | 1817 | int err; |
1736 | int ovr; /* online verify running */ | 1818 | int ovr; /* online verify running */ |
1737 | int rsr; /* re-sync running */ | 1819 | int rsr; /* re-sync running */ |
1738 | struct crypto_hash *verify_tfm = NULL; | 1820 | struct crypto crypto = { }; |
1739 | struct crypto_hash *csums_tfm = NULL; | ||
1740 | |||
1741 | 1821 | ||
1742 | retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_CONN); | 1822 | retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_CONN); |
1743 | if (!adm_ctx.reply_skb) | 1823 | if (!adm_ctx.reply_skb) |
@@ -1779,61 +1859,49 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) | |||
1779 | 1859 | ||
1780 | /* re-sync running */ | 1860 | /* re-sync running */ |
1781 | rsr = conn_resync_running(tconn); | 1861 | rsr = conn_resync_running(tconn); |
1782 | if (rsr && old_conf && strcmp(new_conf->csums_alg, old_conf->csums_alg)) { | 1862 | if (rsr && strcmp(new_conf->csums_alg, old_conf->csums_alg)) { |
1783 | retcode = ERR_CSUMS_RESYNC_RUNNING; | 1863 | retcode = ERR_CSUMS_RESYNC_RUNNING; |
1784 | goto fail; | 1864 | goto fail; |
1785 | } | 1865 | } |
1786 | 1866 | ||
1787 | if (!rsr && new_conf->csums_alg[0]) { | ||
1788 | csums_tfm = crypto_alloc_hash(new_conf->csums_alg, 0, CRYPTO_ALG_ASYNC); | ||
1789 | if (IS_ERR(csums_tfm)) { | ||
1790 | csums_tfm = NULL; | ||
1791 | retcode = ERR_CSUMS_ALG; | ||
1792 | goto fail; | ||
1793 | } | ||
1794 | |||
1795 | if (!drbd_crypto_is_hash(crypto_hash_tfm(csums_tfm))) { | ||
1796 | retcode = ERR_CSUMS_ALG_ND; | ||
1797 | goto fail; | ||
1798 | } | ||
1799 | } | ||
1800 | |||
1801 | /* online verify running */ | 1867 | /* online verify running */ |
1802 | ovr = conn_ov_running(tconn); | 1868 | ovr = conn_ov_running(tconn); |
1803 | if (ovr) { | 1869 | if (ovr && strcmp(new_conf->verify_alg, old_conf->verify_alg)) { |
1804 | if (strcmp(new_conf->verify_alg, old_conf->verify_alg)) { | 1870 | retcode = ERR_VERIFY_RUNNING; |
1805 | retcode = ERR_VERIFY_RUNNING; | 1871 | goto fail; |
1806 | goto fail; | ||
1807 | } | ||
1808 | } | 1872 | } |
1809 | 1873 | ||
1810 | if (!ovr && new_conf->verify_alg[0]) { | 1874 | retcode = alloc_crypto(&crypto, new_conf); |
1811 | verify_tfm = crypto_alloc_hash(new_conf->verify_alg, 0, CRYPTO_ALG_ASYNC); | 1875 | if (retcode != NO_ERROR) |
1812 | if (IS_ERR(verify_tfm)) { | 1876 | goto fail; |
1813 | verify_tfm = NULL; | ||
1814 | retcode = ERR_VERIFY_ALG; | ||
1815 | goto fail; | ||
1816 | } | ||
1817 | |||
1818 | if (!drbd_crypto_is_hash(crypto_hash_tfm(verify_tfm))) { | ||
1819 | retcode = ERR_VERIFY_ALG_ND; | ||
1820 | goto fail; | ||
1821 | } | ||
1822 | } | ||
1823 | 1877 | ||
1824 | rcu_assign_pointer(tconn->net_conf, new_conf); | 1878 | rcu_assign_pointer(tconn->net_conf, new_conf); |
1825 | 1879 | ||
1826 | if (!rsr) { | 1880 | if (!rsr) { |
1827 | crypto_free_hash(tconn->csums_tfm); | 1881 | crypto_free_hash(tconn->csums_tfm); |
1828 | tconn->csums_tfm = csums_tfm; | 1882 | tconn->csums_tfm = crypto.csums_tfm; |
1829 | csums_tfm = NULL; | 1883 | crypto.csums_tfm = NULL; |
1830 | } | 1884 | } |
1831 | if (!ovr) { | 1885 | if (!ovr) { |
1832 | crypto_free_hash(tconn->verify_tfm); | 1886 | crypto_free_hash(tconn->verify_tfm); |
1833 | tconn->verify_tfm = verify_tfm; | 1887 | tconn->verify_tfm = crypto.verify_tfm; |
1834 | verify_tfm = NULL; | 1888 | crypto.verify_tfm = NULL; |
1835 | } | 1889 | } |
1836 | 1890 | ||
1891 | /* FIXME can not assign these so bluntly while we have ongoing IO */ | ||
1892 | kfree(tconn->int_dig_in); | ||
1893 | tconn->int_dig_in = crypto.int_dig_in; | ||
1894 | kfree(tconn->int_dig_vv); | ||
1895 | tconn->int_dig_vv = crypto.int_dig_vv; | ||
1896 | crypto_free_hash(tconn->integrity_w_tfm); | ||
1897 | tconn->integrity_w_tfm = crypto.integrity_w_tfm; | ||
1898 | crypto_free_hash(tconn->integrity_r_tfm); | ||
1899 | tconn->integrity_r_tfm = crypto.integrity_r_tfm; | ||
1900 | |||
1901 | /* FIXME Changing cram_hmac while the connection is established is useless */ | ||
1902 | crypto_free_hash(tconn->cram_hmac_tfm); | ||
1903 | tconn->cram_hmac_tfm = crypto.cram_hmac_tfm; | ||
1904 | |||
1837 | mutex_unlock(&tconn->net_conf_update); | 1905 | mutex_unlock(&tconn->net_conf_update); |
1838 | synchronize_rcu(); | 1906 | synchronize_rcu(); |
1839 | kfree(old_conf); | 1907 | kfree(old_conf); |
@@ -1845,8 +1913,7 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) | |||
1845 | 1913 | ||
1846 | fail: | 1914 | fail: |
1847 | mutex_unlock(&tconn->net_conf_update); | 1915 | mutex_unlock(&tconn->net_conf_update); |
1848 | crypto_free_hash(csums_tfm); | 1916 | free_crypto(&crypto); |
1849 | crypto_free_hash(verify_tfm); | ||
1850 | kfree(new_conf); | 1917 | kfree(new_conf); |
1851 | done: | 1918 | done: |
1852 | conn_reconfig_done(tconn); | 1919 | conn_reconfig_done(tconn); |
@@ -1857,14 +1924,9 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) | |||
1857 | 1924 | ||
1858 | int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info) | 1925 | int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info) |
1859 | { | 1926 | { |
1860 | char hmac_name[CRYPTO_MAX_ALG_NAME]; | ||
1861 | struct drbd_conf *mdev; | 1927 | struct drbd_conf *mdev; |
1862 | struct net_conf *old_conf, *new_conf = NULL; | 1928 | struct net_conf *old_conf, *new_conf = NULL; |
1863 | struct crypto_hash *tfm = NULL; | 1929 | struct crypto crypto = { }; |
1864 | struct crypto_hash *integrity_w_tfm = NULL; | ||
1865 | struct crypto_hash *integrity_r_tfm = NULL; | ||
1866 | void *int_dig_in = NULL; | ||
1867 | void *int_dig_vv = NULL; | ||
1868 | struct drbd_tconn *oconn; | 1930 | struct drbd_tconn *oconn; |
1869 | struct drbd_tconn *tconn; | 1931 | struct drbd_tconn *tconn; |
1870 | struct sockaddr *new_my_addr, *new_peer_addr, *taken_addr; | 1932 | struct sockaddr *new_my_addr, *new_peer_addr, *taken_addr; |
@@ -1969,60 +2031,12 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info) | |||
1969 | goto fail; | 2031 | goto fail; |
1970 | } | 2032 | } |
1971 | 2033 | ||
1972 | if (new_conf->cram_hmac_alg[0] != 0) { | 2034 | retcode = alloc_crypto(&crypto, new_conf); |
1973 | snprintf(hmac_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)", | 2035 | if (retcode != NO_ERROR) |
1974 | new_conf->cram_hmac_alg); | 2036 | goto fail; |
1975 | tfm = crypto_alloc_hash(hmac_name, 0, CRYPTO_ALG_ASYNC); | ||
1976 | if (IS_ERR(tfm)) { | ||
1977 | tfm = NULL; | ||
1978 | retcode = ERR_AUTH_ALG; | ||
1979 | goto fail; | ||
1980 | } | ||
1981 | |||
1982 | if (!drbd_crypto_is_hash(crypto_hash_tfm(tfm))) { | ||
1983 | retcode = ERR_AUTH_ALG_ND; | ||
1984 | goto fail; | ||
1985 | } | ||
1986 | } | ||
1987 | |||
1988 | if (new_conf->integrity_alg[0]) { | ||
1989 | integrity_w_tfm = crypto_alloc_hash(new_conf->integrity_alg, 0, CRYPTO_ALG_ASYNC); | ||
1990 | if (IS_ERR(integrity_w_tfm)) { | ||
1991 | integrity_w_tfm = NULL; | ||
1992 | retcode=ERR_INTEGRITY_ALG; | ||
1993 | goto fail; | ||
1994 | } | ||
1995 | |||
1996 | if (!drbd_crypto_is_hash(crypto_hash_tfm(integrity_w_tfm))) { | ||
1997 | retcode=ERR_INTEGRITY_ALG_ND; | ||
1998 | goto fail; | ||
1999 | } | ||
2000 | |||
2001 | integrity_r_tfm = crypto_alloc_hash(new_conf->integrity_alg, 0, CRYPTO_ALG_ASYNC); | ||
2002 | if (IS_ERR(integrity_r_tfm)) { | ||
2003 | integrity_r_tfm = NULL; | ||
2004 | retcode=ERR_INTEGRITY_ALG; | ||
2005 | goto fail; | ||
2006 | } | ||
2007 | } | ||
2008 | 2037 | ||
2009 | ((char *)new_conf->shared_secret)[SHARED_SECRET_MAX-1] = 0; | 2038 | ((char *)new_conf->shared_secret)[SHARED_SECRET_MAX-1] = 0; |
2010 | 2039 | ||
2011 | /* allocation not in the IO path, cqueue thread context */ | ||
2012 | if (integrity_w_tfm) { | ||
2013 | i = crypto_hash_digestsize(integrity_w_tfm); | ||
2014 | int_dig_in = kmalloc(i, GFP_KERNEL); | ||
2015 | if (!int_dig_in) { | ||
2016 | retcode = ERR_NOMEM; | ||
2017 | goto fail; | ||
2018 | } | ||
2019 | int_dig_vv = kmalloc(i, GFP_KERNEL); | ||
2020 | if (!int_dig_vv) { | ||
2021 | retcode = ERR_NOMEM; | ||
2022 | goto fail; | ||
2023 | } | ||
2024 | } | ||
2025 | |||
2026 | conn_flush_workqueue(tconn); | 2040 | conn_flush_workqueue(tconn); |
2027 | 2041 | ||
2028 | mutex_lock(&tconn->net_conf_update); | 2042 | mutex_lock(&tconn->net_conf_update); |
@@ -2035,11 +2049,13 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info) | |||
2035 | rcu_assign_pointer(tconn->net_conf, new_conf); | 2049 | rcu_assign_pointer(tconn->net_conf, new_conf); |
2036 | 2050 | ||
2037 | conn_free_crypto(tconn); | 2051 | conn_free_crypto(tconn); |
2038 | tconn->cram_hmac_tfm = tfm; | 2052 | tconn->int_dig_in = crypto.int_dig_in; |
2039 | tconn->integrity_w_tfm = integrity_w_tfm; | 2053 | tconn->int_dig_vv = crypto.int_dig_vv; |
2040 | tconn->integrity_r_tfm = integrity_r_tfm; | 2054 | tconn->cram_hmac_tfm = crypto.cram_hmac_tfm; |
2041 | tconn->int_dig_in = int_dig_in; | 2055 | tconn->integrity_w_tfm = crypto.integrity_w_tfm; |
2042 | tconn->int_dig_vv = int_dig_vv; | 2056 | tconn->integrity_r_tfm = crypto.integrity_r_tfm; |
2057 | tconn->csums_tfm = crypto.csums_tfm; | ||
2058 | tconn->verify_tfm = crypto.verify_tfm; | ||
2043 | 2059 | ||
2044 | mutex_unlock(&tconn->net_conf_update); | 2060 | mutex_unlock(&tconn->net_conf_update); |
2045 | 2061 | ||
@@ -2057,11 +2073,7 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info) | |||
2057 | return 0; | 2073 | return 0; |
2058 | 2074 | ||
2059 | fail: | 2075 | fail: |
2060 | kfree(int_dig_in); | 2076 | free_crypto(&crypto); |
2061 | kfree(int_dig_vv); | ||
2062 | crypto_free_hash(tfm); | ||
2063 | crypto_free_hash(integrity_w_tfm); | ||
2064 | crypto_free_hash(integrity_r_tfm); | ||
2065 | kfree(new_conf); | 2077 | kfree(new_conf); |
2066 | 2078 | ||
2067 | conn_reconfig_done(tconn); | 2079 | conn_reconfig_done(tconn); |