Skip to content

Commit

Permalink
iscsi: ensure RNG is seeded before use
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jason A. Donenfeld authored and Theodore Ts'o committed Jun 20, 2017
1 parent 51b0817 commit 6787ab8
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 11 deletions.
14 changes: 11 additions & 3 deletions drivers/target/iscsi/iscsi_target_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,21 @@ static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len)
}
}

static void chap_gen_challenge(
static int chap_gen_challenge(
struct iscsi_conn *conn,
int caller,
char *c_str,
unsigned int *c_len)
{
int ret;
unsigned char challenge_asciihex[CHAP_CHALLENGE_LENGTH * 2 + 1];
struct iscsi_chap *chap = conn->auth_protocol;

memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1);

get_random_bytes(chap->challenge, CHAP_CHALLENGE_LENGTH);
ret = get_random_bytes_wait(chap->challenge, CHAP_CHALLENGE_LENGTH);
if (unlikely(ret))
return ret;
chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge,
CHAP_CHALLENGE_LENGTH);
/*
Expand All @@ -69,6 +72,7 @@ static void chap_gen_challenge(

pr_debug("[%s] Sending CHAP_C=0x%s\n\n", (caller) ? "server" : "client",
challenge_asciihex);
return 0;
}

static int chap_check_algorithm(const char *a_str)
Expand Down Expand Up @@ -143,6 +147,7 @@ static struct iscsi_chap *chap_server_open(
case CHAP_DIGEST_UNKNOWN:
default:
pr_err("Unsupported CHAP_A value\n");
kfree(conn->auth_protocol);
return NULL;
}

Expand All @@ -156,7 +161,10 @@ static struct iscsi_chap *chap_server_open(
/*
* Generate Challenge.
*/
chap_gen_challenge(conn, 1, aic_str, aic_len);
if (chap_gen_challenge(conn, 1, aic_str, aic_len) < 0) {
kfree(conn->auth_protocol);
return NULL;
}

return chap;
}
Expand Down
22 changes: 14 additions & 8 deletions drivers/target/iscsi/iscsi_target_login.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,22 +245,26 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
return 0;
}

static void iscsi_login_set_conn_values(
static int iscsi_login_set_conn_values(
struct iscsi_session *sess,
struct iscsi_conn *conn,
__be16 cid)
{
int ret;
conn->sess = sess;
conn->cid = be16_to_cpu(cid);
/*
* Generate a random Status sequence number (statsn) for the new
* iSCSI connection.
*/
get_random_bytes(&conn->stat_sn, sizeof(u32));
ret = get_random_bytes_wait(&conn->stat_sn, sizeof(u32));
if (unlikely(ret))
return ret;

mutex_lock(&auth_id_lock);
conn->auth_id = iscsit_global->auth_id++;
mutex_unlock(&auth_id_lock);
return 0;
}

__printf(2, 3) int iscsi_change_param_sprintf(
Expand Down Expand Up @@ -306,7 +310,11 @@ static int iscsi_login_zero_tsih_s1(
return -ENOMEM;
}

iscsi_login_set_conn_values(sess, conn, pdu->cid);
ret = iscsi_login_set_conn_values(sess, conn, pdu->cid);
if (unlikely(ret)) {
kfree(sess);
return ret;
}
sess->init_task_tag = pdu->itt;
memcpy(&sess->isid, pdu->isid, 6);
sess->exp_cmd_sn = be32_to_cpu(pdu->cmdsn);
Expand Down Expand Up @@ -497,8 +505,7 @@ static int iscsi_login_non_zero_tsih_s1(
{
struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf;

iscsi_login_set_conn_values(NULL, conn, pdu->cid);
return 0;
return iscsi_login_set_conn_values(NULL, conn, pdu->cid);
}

/*
Expand Down Expand Up @@ -554,9 +561,8 @@ static int iscsi_login_non_zero_tsih_s2(
atomic_set(&sess->session_continuation, 1);
spin_unlock_bh(&sess->conn_lock);

iscsi_login_set_conn_values(sess, conn, pdu->cid);

if (iscsi_copy_param_list(&conn->param_list,
if (iscsi_login_set_conn_values(sess, conn, pdu->cid) < 0 ||
iscsi_copy_param_list(&conn->param_list,
conn->tpg->param_list, 0) < 0) {
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
Expand Down

0 comments on commit 6787ab8

Please sign in to comment.