aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2017-06-07 22:34:26 -0400
committerTheodore Ts'o <tytso@mit.edu>2017-06-19 22:06:28 -0400
commit6787ab81b29115b6d2e7d17fe8a8017da66197d6 (patch)
treec926aac68602cbf76c6aa121fcacf5902cfc749f
parent51b0817b0d23d51223575eff14629b3602a93cd4 (diff)
iscsi: ensure RNG is seeded before use
It's not safe to use weak random data here, especially for the challenge response randomness. Since we're always in process context, it's safe to simply wait until we have enough randomness to carry out the authentication correctly. While we're at it, we clean up a small memleak during an error condition. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> Cc: "Nicholas A. Bellinger" <nab@linux-iscsi.org> Cc: Lee Duncan <lduncan@suse.com> Cc: Chris Leech <cleech@redhat.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--drivers/target/iscsi/iscsi_target_auth.c14
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c22
2 files changed, 25 insertions, 11 deletions
diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c
index 903b667f8e01..f9bc8ec6fb6b 100644
--- a/drivers/target/iscsi/iscsi_target_auth.c
+++ b/drivers/target/iscsi/iscsi_target_auth.c
@@ -47,18 +47,21 @@ static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len)
47 } 47 }
48} 48}
49 49
50static void chap_gen_challenge( 50static int chap_gen_challenge(
51 struct iscsi_conn *conn, 51 struct iscsi_conn *conn,
52 int caller, 52 int caller,
53 char *c_str, 53 char *c_str,
54 unsigned int *c_len) 54 unsigned int *c_len)
55{ 55{
56 int ret;
56 unsigned char challenge_asciihex[CHAP_CHALLENGE_LENGTH * 2 + 1]; 57 unsigned char challenge_asciihex[CHAP_CHALLENGE_LENGTH * 2 + 1];
57 struct iscsi_chap *chap = conn->auth_protocol; 58 struct iscsi_chap *chap = conn->auth_protocol;
58 59
59 memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1); 60 memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1);
60 61
61 get_random_bytes(chap->challenge, CHAP_CHALLENGE_LENGTH); 62 ret = get_random_bytes_wait(chap->challenge, CHAP_CHALLENGE_LENGTH);
63 if (unlikely(ret))
64 return ret;
62 chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge, 65 chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge,
63 CHAP_CHALLENGE_LENGTH); 66 CHAP_CHALLENGE_LENGTH);
64 /* 67 /*
@@ -69,6 +72,7 @@ static void chap_gen_challenge(
69 72
70 pr_debug("[%s] Sending CHAP_C=0x%s\n\n", (caller) ? "server" : "client", 73 pr_debug("[%s] Sending CHAP_C=0x%s\n\n", (caller) ? "server" : "client",
71 challenge_asciihex); 74 challenge_asciihex);
75 return 0;
72} 76}
73 77
74static int chap_check_algorithm(const char *a_str) 78static int chap_check_algorithm(const char *a_str)
@@ -143,6 +147,7 @@ static struct iscsi_chap *chap_server_open(
143 case CHAP_DIGEST_UNKNOWN: 147 case CHAP_DIGEST_UNKNOWN:
144 default: 148 default:
145 pr_err("Unsupported CHAP_A value\n"); 149 pr_err("Unsupported CHAP_A value\n");
150 kfree(conn->auth_protocol);
146 return NULL; 151 return NULL;
147 } 152 }
148 153
@@ -156,7 +161,10 @@ static struct iscsi_chap *chap_server_open(
156 /* 161 /*
157 * Generate Challenge. 162 * Generate Challenge.
158 */ 163 */
159 chap_gen_challenge(conn, 1, aic_str, aic_len); 164 if (chap_gen_challenge(conn, 1, aic_str, aic_len) < 0) {
165 kfree(conn->auth_protocol);
166 return NULL;
167 }
160 168
161 return chap; 169 return chap;
162} 170}
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 66238477137b..5ef028c11738 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -245,22 +245,26 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
245 return 0; 245 return 0;
246} 246}
247 247
248static void iscsi_login_set_conn_values( 248static int iscsi_login_set_conn_values(
249 struct iscsi_session *sess, 249 struct iscsi_session *sess,
250 struct iscsi_conn *conn, 250 struct iscsi_conn *conn,
251 __be16 cid) 251 __be16 cid)
252{ 252{
253 int ret;
253 conn->sess = sess; 254 conn->sess = sess;
254 conn->cid = be16_to_cpu(cid); 255 conn->cid = be16_to_cpu(cid);
255 /* 256 /*
256 * Generate a random Status sequence number (statsn) for the new 257 * Generate a random Status sequence number (statsn) for the new
257 * iSCSI connection. 258 * iSCSI connection.
258 */ 259 */
259 get_random_bytes(&conn->stat_sn, sizeof(u32)); 260 ret = get_random_bytes_wait(&conn->stat_sn, sizeof(u32));
261 if (unlikely(ret))
262 return ret;
260 263
261 mutex_lock(&auth_id_lock); 264 mutex_lock(&auth_id_lock);
262 conn->auth_id = iscsit_global->auth_id++; 265 conn->auth_id = iscsit_global->auth_id++;
263 mutex_unlock(&auth_id_lock); 266 mutex_unlock(&auth_id_lock);
267 return 0;
264} 268}
265 269
266__printf(2, 3) int iscsi_change_param_sprintf( 270__printf(2, 3) int iscsi_change_param_sprintf(
@@ -306,7 +310,11 @@ static int iscsi_login_zero_tsih_s1(
306 return -ENOMEM; 310 return -ENOMEM;
307 } 311 }
308 312
309 iscsi_login_set_conn_values(sess, conn, pdu->cid); 313 ret = iscsi_login_set_conn_values(sess, conn, pdu->cid);
314 if (unlikely(ret)) {
315 kfree(sess);
316 return ret;
317 }
310 sess->init_task_tag = pdu->itt; 318 sess->init_task_tag = pdu->itt;
311 memcpy(&sess->isid, pdu->isid, 6); 319 memcpy(&sess->isid, pdu->isid, 6);
312 sess->exp_cmd_sn = be32_to_cpu(pdu->cmdsn); 320 sess->exp_cmd_sn = be32_to_cpu(pdu->cmdsn);
@@ -497,8 +505,7 @@ static int iscsi_login_non_zero_tsih_s1(
497{ 505{
498 struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf; 506 struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf;
499 507
500 iscsi_login_set_conn_values(NULL, conn, pdu->cid); 508 return iscsi_login_set_conn_values(NULL, conn, pdu->cid);
501 return 0;
502} 509}
503 510
504/* 511/*
@@ -554,9 +561,8 @@ static int iscsi_login_non_zero_tsih_s2(
554 atomic_set(&sess->session_continuation, 1); 561 atomic_set(&sess->session_continuation, 1);
555 spin_unlock_bh(&sess->conn_lock); 562 spin_unlock_bh(&sess->conn_lock);
556 563
557 iscsi_login_set_conn_values(sess, conn, pdu->cid); 564 if (iscsi_login_set_conn_values(sess, conn, pdu->cid) < 0 ||
558 565 iscsi_copy_param_list(&conn->param_list,
559 if (iscsi_copy_param_list(&conn->param_list,
560 conn->tpg->param_list, 0) < 0) { 566 conn->tpg->param_list, 0) < 0) {
561 iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, 567 iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
562 ISCSI_LOGIN_STATUS_NO_RESOURCES); 568 ISCSI_LOGIN_STATUS_NO_RESOURCES);