Commit 7d4c782c authored by Andreas Gruenbacher's avatar Andreas Gruenbacher Committed by Philipp Reisner

drbd: Fix the data-integrity-alg setting

The last data-integrity-alg fix made data integrity checking work when the
algorithm was changed for an established connection, but the common case of
configuring the algorithm before connecting was still broken.  Fix that.
Signed-off-by: default avatarAndreas Gruenbacher <agruen@linbit.com>
Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent 71fc7eed
...@@ -1775,8 +1775,7 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req) ...@@ -1775,8 +1775,7 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req)
sock = &mdev->tconn->data; sock = &mdev->tconn->data;
p = drbd_prepare_command(mdev, sock); p = drbd_prepare_command(mdev, sock);
dgs = (mdev->tconn->agreed_pro_version >= 87 && mdev->tconn->integrity_tfm) ? dgs = mdev->tconn->integrity_tfm ? crypto_hash_digestsize(mdev->tconn->integrity_tfm) : 0;
crypto_hash_digestsize(mdev->tconn->integrity_tfm) : 0;
if (!p) if (!p)
return -EIO; return -EIO;
...@@ -1849,8 +1848,7 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packet cmd, ...@@ -1849,8 +1848,7 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packet cmd,
sock = &mdev->tconn->data; sock = &mdev->tconn->data;
p = drbd_prepare_command(mdev, sock); p = drbd_prepare_command(mdev, sock);
dgs = (mdev->tconn->agreed_pro_version >= 87 && mdev->tconn->integrity_tfm) ? dgs = mdev->tconn->integrity_tfm ? crypto_hash_digestsize(mdev->tconn->integrity_tfm) : 0;
crypto_hash_digestsize(mdev->tconn->integrity_tfm) : 0;
if (!p) if (!p)
return -EIO; return -EIO;
......
...@@ -1824,8 +1824,6 @@ struct crypto { ...@@ -1824,8 +1824,6 @@ struct crypto {
struct crypto_hash *csums_tfm; struct crypto_hash *csums_tfm;
struct crypto_hash *cram_hmac_tfm; struct crypto_hash *cram_hmac_tfm;
struct crypto_hash *integrity_tfm; struct crypto_hash *integrity_tfm;
void *int_dig_in;
void *int_dig_vv;
}; };
static int static int
...@@ -1848,7 +1846,6 @@ alloc_crypto(struct crypto *crypto, struct net_conf *new_conf) ...@@ -1848,7 +1846,6 @@ alloc_crypto(struct crypto *crypto, struct net_conf *new_conf)
{ {
char hmac_name[CRYPTO_MAX_ALG_NAME]; char hmac_name[CRYPTO_MAX_ALG_NAME];
enum drbd_ret_code rv; enum drbd_ret_code rv;
int hash_size;
rv = alloc_hash(&crypto->csums_tfm, new_conf->csums_alg, rv = alloc_hash(&crypto->csums_tfm, new_conf->csums_alg,
ERR_CSUMS_ALG); ERR_CSUMS_ALG);
...@@ -1869,23 +1866,12 @@ alloc_crypto(struct crypto *crypto, struct net_conf *new_conf) ...@@ -1869,23 +1866,12 @@ alloc_crypto(struct crypto *crypto, struct net_conf *new_conf)
rv = alloc_hash(&crypto->cram_hmac_tfm, hmac_name, rv = alloc_hash(&crypto->cram_hmac_tfm, hmac_name,
ERR_AUTH_ALG); ERR_AUTH_ALG);
} }
if (crypto->integrity_tfm) {
hash_size = crypto_hash_digestsize(crypto->integrity_tfm);
crypto->int_dig_in = kmalloc(hash_size, GFP_KERNEL);
if (!crypto->int_dig_in)
return ERR_NOMEM;
crypto->int_dig_vv = kmalloc(hash_size, GFP_KERNEL);
if (!crypto->int_dig_vv)
return ERR_NOMEM;
}
return rv; return rv;
} }
static void free_crypto(struct crypto *crypto) static void free_crypto(struct crypto *crypto)
{ {
kfree(crypto->int_dig_in);
kfree(crypto->int_dig_vv);
crypto_free_hash(crypto->cram_hmac_tfm); crypto_free_hash(crypto->cram_hmac_tfm);
crypto_free_hash(crypto->integrity_tfm); crypto_free_hash(crypto->integrity_tfm);
crypto_free_hash(crypto->csums_tfm); crypto_free_hash(crypto->csums_tfm);
...@@ -1974,10 +1960,6 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) ...@@ -1974,10 +1960,6 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info)
crypto.verify_tfm = NULL; crypto.verify_tfm = NULL;
} }
kfree(tconn->int_dig_in);
tconn->int_dig_in = crypto.int_dig_in;
kfree(tconn->int_dig_vv);
tconn->int_dig_vv = crypto.int_dig_vv;
crypto_free_hash(tconn->integrity_tfm); crypto_free_hash(tconn->integrity_tfm);
tconn->integrity_tfm = crypto.integrity_tfm; tconn->integrity_tfm = crypto.integrity_tfm;
if (tconn->cstate >= C_WF_REPORT_PARAMS && tconn->agreed_pro_version >= 100) if (tconn->cstate >= C_WF_REPORT_PARAMS && tconn->agreed_pro_version >= 100)
...@@ -2094,8 +2076,6 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info) ...@@ -2094,8 +2076,6 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info)
rcu_assign_pointer(tconn->net_conf, new_conf); rcu_assign_pointer(tconn->net_conf, new_conf);
conn_free_crypto(tconn); conn_free_crypto(tconn);
tconn->int_dig_in = crypto.int_dig_in;
tconn->int_dig_vv = crypto.int_dig_vv;
tconn->cram_hmac_tfm = crypto.cram_hmac_tfm; tconn->cram_hmac_tfm = crypto.cram_hmac_tfm;
tconn->integrity_tfm = crypto.integrity_tfm; tconn->integrity_tfm = crypto.integrity_tfm;
tconn->csums_tfm = crypto.csums_tfm; tconn->csums_tfm = crypto.csums_tfm;
......
...@@ -3024,7 +3024,53 @@ static int receive_protocol(struct drbd_tconn *tconn, struct packet_info *pi) ...@@ -3024,7 +3024,53 @@ static int receive_protocol(struct drbd_tconn *tconn, struct packet_info *pi)
integrity_alg[SHARED_SECRET_MAX - 1] = 0; integrity_alg[SHARED_SECRET_MAX - 1] = 0;
} }
if (pi->cmd == P_PROTOCOL_UPDATE) { if (pi->cmd != P_PROTOCOL_UPDATE) {
clear_bit(CONN_DRY_RUN, &tconn->flags);
if (cf & CF_DRY_RUN)
set_bit(CONN_DRY_RUN, &tconn->flags);
rcu_read_lock();
nc = rcu_dereference(tconn->net_conf);
if (p_proto != nc->wire_protocol) {
conn_err(tconn, "incompatible %s settings\n", "protocol");
goto disconnect_rcu_unlock;
}
if (convert_after_sb(p_after_sb_0p) != nc->after_sb_0p) {
conn_err(tconn, "incompatible %s settings\n", "after-sb-0pri");
goto disconnect_rcu_unlock;
}
if (convert_after_sb(p_after_sb_1p) != nc->after_sb_1p) {
conn_err(tconn, "incompatible %s settings\n", "after-sb-1pri");
goto disconnect_rcu_unlock;
}
if (convert_after_sb(p_after_sb_2p) != nc->after_sb_2p) {
conn_err(tconn, "incompatible %s settings\n", "after-sb-2pri");
goto disconnect_rcu_unlock;
}
if (p_discard_my_data && nc->discard_my_data) {
conn_err(tconn, "incompatible %s settings\n", "discard-my-data");
goto disconnect_rcu_unlock;
}
if (p_two_primaries != nc->two_primaries) {
conn_err(tconn, "incompatible %s settings\n", "allow-two-primaries");
goto disconnect_rcu_unlock;
}
if (strcmp(integrity_alg, nc->integrity_alg)) {
conn_err(tconn, "incompatible %s settings\n", "data-integrity-alg");
goto disconnect_rcu_unlock;
}
rcu_read_unlock();
}
if (integrity_alg[0]) { if (integrity_alg[0]) {
int hash_size; int hash_size;
...@@ -3069,8 +3115,6 @@ static int receive_protocol(struct drbd_tconn *tconn, struct packet_info *pi) ...@@ -3069,8 +3115,6 @@ static int receive_protocol(struct drbd_tconn *tconn, struct packet_info *pi)
new_net_conf->after_sb_1p = convert_after_sb(p_after_sb_1p); new_net_conf->after_sb_1p = convert_after_sb(p_after_sb_1p);
new_net_conf->after_sb_2p = convert_after_sb(p_after_sb_2p); new_net_conf->after_sb_2p = convert_after_sb(p_after_sb_2p);
new_net_conf->two_primaries = p_two_primaries; new_net_conf->two_primaries = p_two_primaries;
strcpy(new_net_conf->integrity_alg, integrity_alg);
new_net_conf->integrity_alg_len = strlen(integrity_alg) + 1;
rcu_assign_pointer(tconn->net_conf, new_net_conf); rcu_assign_pointer(tconn->net_conf, new_net_conf);
mutex_unlock(&tconn->conf_update); mutex_unlock(&tconn->conf_update);
...@@ -3089,52 +3133,6 @@ static int receive_protocol(struct drbd_tconn *tconn, struct packet_info *pi) ...@@ -3089,52 +3133,6 @@ static int receive_protocol(struct drbd_tconn *tconn, struct packet_info *pi)
synchronize_rcu(); synchronize_rcu();
kfree(old_net_conf); kfree(old_net_conf);
} else {
clear_bit(CONN_DRY_RUN, &tconn->flags);
if (cf & CF_DRY_RUN)
set_bit(CONN_DRY_RUN, &tconn->flags);
rcu_read_lock();
nc = rcu_dereference(tconn->net_conf);
if (p_proto != nc->wire_protocol) {
conn_err(tconn, "incompatible %s settings\n", "protocol");
goto disconnect_rcu_unlock;
}
if (convert_after_sb(p_after_sb_0p) != nc->after_sb_0p) {
conn_err(tconn, "incompatible %s settings\n", "after-sb-0pri");
goto disconnect_rcu_unlock;
}
if (convert_after_sb(p_after_sb_1p) != nc->after_sb_1p) {
conn_err(tconn, "incompatible %s settings\n", "after-sb-1pri");
goto disconnect_rcu_unlock;
}
if (convert_after_sb(p_after_sb_2p) != nc->after_sb_2p) {
conn_err(tconn, "incompatible %s settings\n", "after-sb-2pri");
goto disconnect_rcu_unlock;
}
if (p_discard_my_data && nc->discard_my_data) {
conn_err(tconn, "incompatible %s settings\n", "discard-my-data");
goto disconnect_rcu_unlock;
}
if (p_two_primaries != nc->two_primaries) {
conn_err(tconn, "incompatible %s settings\n", "allow-two-primaries");
goto disconnect_rcu_unlock;
}
if (strcmp(integrity_alg, nc->integrity_alg)) {
conn_err(tconn, "incompatible %s settings\n", "data-integrity-alg");
goto disconnect_rcu_unlock;
}
rcu_read_unlock();
}
return 0; return 0;
disconnect_rcu_unlock: disconnect_rcu_unlock:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment