aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <mchristi@redhat.com>2018-08-27 15:45:16 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2018-08-30 07:07:12 -0400
commit05a86e78ea9823ec25b3515db078dd8a76fc263c (patch)
tree47b7cd2caed9db4f3de6f98d6cc96cfac2229b98
parent7915919bb94e12460c58e27c708472e6f85f6699 (diff)
scsi: iscsi: target: Fix conn_ops double free
If iscsi_login_init_conn fails it can free conn_ops. __iscsi_target_login_thread will then call iscsi_target_login_sess_out which will also free it. This fixes the problem by organizing conn allocation/setup into parts that are needed through the life of the conn and parts that are only needed for the login. The free functions then release what was allocated in the alloc functions. With this patch we have: iscsit_alloc_conn/iscsit_free_conn - allocs/frees the conn we need for the entire life of the conn. iscsi_login_init_conn/iscsi_target_nego_release - allocs/frees the parts of the conn that are only needed during login. Signed-off-by: Mike Christie <mchristi@redhat.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/target/iscsi/iscsi_target.c9
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c141
-rw-r--r--drivers/target/iscsi/iscsi_target_login.h2
3 files changed, 77 insertions, 75 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 94bad43c41ff..9cdfccbdd06f 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -4208,22 +4208,15 @@ int iscsit_close_connection(
4208 crypto_free_ahash(tfm); 4208 crypto_free_ahash(tfm);
4209 } 4209 }
4210 4210
4211 free_cpumask_var(conn->conn_cpumask);
4212
4213 kfree(conn->conn_ops);
4214 conn->conn_ops = NULL;
4215
4216 if (conn->sock) 4211 if (conn->sock)
4217 sock_release(conn->sock); 4212 sock_release(conn->sock);
4218 4213
4219 if (conn->conn_transport->iscsit_free_conn) 4214 if (conn->conn_transport->iscsit_free_conn)
4220 conn->conn_transport->iscsit_free_conn(conn); 4215 conn->conn_transport->iscsit_free_conn(conn);
4221 4216
4222 iscsit_put_transport(conn->conn_transport);
4223
4224 pr_debug("Moving to TARG_CONN_STATE_FREE.\n"); 4217 pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
4225 conn->conn_state = TARG_CONN_STATE_FREE; 4218 conn->conn_state = TARG_CONN_STATE_FREE;
4226 kfree(conn); 4219 iscsit_free_conn(conn);
4227 4220
4228 spin_lock_bh(&sess->conn_lock); 4221 spin_lock_bh(&sess->conn_lock);
4229 atomic_dec(&sess->nconn); 4222 atomic_dec(&sess->nconn);
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index f58b9c1d6fd4..bb90c80ff388 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -67,45 +67,10 @@ static struct iscsi_login *iscsi_login_init_conn(struct iscsi_conn *conn)
67 goto out_req_buf; 67 goto out_req_buf;
68 } 68 }
69 69
70 conn->conn_ops = kzalloc(sizeof(struct iscsi_conn_ops), GFP_KERNEL);
71 if (!conn->conn_ops) {
72 pr_err("Unable to allocate memory for"
73 " struct iscsi_conn_ops.\n");
74 goto out_rsp_buf;
75 }
76
77 init_waitqueue_head(&conn->queues_wq);
78 INIT_LIST_HEAD(&conn->conn_list);
79 INIT_LIST_HEAD(&conn->conn_cmd_list);
80 INIT_LIST_HEAD(&conn->immed_queue_list);
81 INIT_LIST_HEAD(&conn->response_queue_list);
82 init_completion(&conn->conn_post_wait_comp);
83 init_completion(&conn->conn_wait_comp);
84 init_completion(&conn->conn_wait_rcfr_comp);
85 init_completion(&conn->conn_waiting_on_uc_comp);
86 init_completion(&conn->conn_logout_comp);
87 init_completion(&conn->rx_half_close_comp);
88 init_completion(&conn->tx_half_close_comp);
89 init_completion(&conn->rx_login_comp);
90 spin_lock_init(&conn->cmd_lock);
91 spin_lock_init(&conn->conn_usage_lock);
92 spin_lock_init(&conn->immed_queue_lock);
93 spin_lock_init(&conn->nopin_timer_lock);
94 spin_lock_init(&conn->response_queue_lock);
95 spin_lock_init(&conn->state_lock);
96
97 if (!zalloc_cpumask_var(&conn->conn_cpumask, GFP_KERNEL)) {
98 pr_err("Unable to allocate conn->conn_cpumask\n");
99 goto out_conn_ops;
100 }
101 conn->conn_login = login; 70 conn->conn_login = login;
102 71
103 return login; 72 return login;
104 73
105out_conn_ops:
106 kfree(conn->conn_ops);
107out_rsp_buf:
108 kfree(login->rsp_buf);
109out_req_buf: 74out_req_buf:
110 kfree(login->req_buf); 75 kfree(login->req_buf);
111out_login: 76out_login:
@@ -1147,6 +1112,75 @@ iscsit_conn_set_transport(struct iscsi_conn *conn, struct iscsit_transport *t)
1147 return 0; 1112 return 0;
1148} 1113}
1149 1114
1115static struct iscsi_conn *iscsit_alloc_conn(struct iscsi_np *np)
1116{
1117 struct iscsi_conn *conn;
1118
1119 conn = kzalloc(sizeof(struct iscsi_conn), GFP_KERNEL);
1120 if (!conn) {
1121 pr_err("Could not allocate memory for new connection\n");
1122 return NULL;
1123 }
1124 pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
1125 conn->conn_state = TARG_CONN_STATE_FREE;
1126
1127 init_waitqueue_head(&conn->queues_wq);
1128 INIT_LIST_HEAD(&conn->conn_list);
1129 INIT_LIST_HEAD(&conn->conn_cmd_list);
1130 INIT_LIST_HEAD(&conn->immed_queue_list);
1131 INIT_LIST_HEAD(&conn->response_queue_list);
1132 init_completion(&conn->conn_post_wait_comp);
1133 init_completion(&conn->conn_wait_comp);
1134 init_completion(&conn->conn_wait_rcfr_comp);
1135 init_completion(&conn->conn_waiting_on_uc_comp);
1136 init_completion(&conn->conn_logout_comp);
1137 init_completion(&conn->rx_half_close_comp);
1138 init_completion(&conn->tx_half_close_comp);
1139 init_completion(&conn->rx_login_comp);
1140 spin_lock_init(&conn->cmd_lock);
1141 spin_lock_init(&conn->conn_usage_lock);
1142 spin_lock_init(&conn->immed_queue_lock);
1143 spin_lock_init(&conn->nopin_timer_lock);
1144 spin_lock_init(&conn->response_queue_lock);
1145 spin_lock_init(&conn->state_lock);
1146
1147 timer_setup(&conn->nopin_response_timer,
1148 iscsit_handle_nopin_response_timeout, 0);
1149 timer_setup(&conn->nopin_timer, iscsit_handle_nopin_timeout, 0);
1150
1151 if (iscsit_conn_set_transport(conn, np->np_transport) < 0)
1152 goto free_conn;
1153
1154 conn->conn_ops = kzalloc(sizeof(struct iscsi_conn_ops), GFP_KERNEL);
1155 if (!conn->conn_ops) {
1156 pr_err("Unable to allocate memory for struct iscsi_conn_ops.\n");
1157 goto put_transport;
1158 }
1159
1160 if (!zalloc_cpumask_var(&conn->conn_cpumask, GFP_KERNEL)) {
1161 pr_err("Unable to allocate conn->conn_cpumask\n");
1162 goto free_mask;
1163 }
1164
1165 return conn;
1166
1167free_mask:
1168 free_cpumask_var(conn->conn_cpumask);
1169put_transport:
1170 iscsit_put_transport(conn->conn_transport);
1171free_conn:
1172 kfree(conn);
1173 return NULL;
1174}
1175
1176void iscsit_free_conn(struct iscsi_conn *conn)
1177{
1178 free_cpumask_var(conn->conn_cpumask);
1179 kfree(conn->conn_ops);
1180 iscsit_put_transport(conn->conn_transport);
1181 kfree(conn);
1182}
1183
1150void iscsi_target_login_sess_out(struct iscsi_conn *conn, 1184void iscsi_target_login_sess_out(struct iscsi_conn *conn,
1151 struct iscsi_np *np, bool zero_tsih, bool new_sess) 1185 struct iscsi_np *np, bool zero_tsih, bool new_sess)
1152{ 1186{
@@ -1196,10 +1230,6 @@ old_sess_out:
1196 crypto_free_ahash(tfm); 1230 crypto_free_ahash(tfm);
1197 } 1231 }
1198 1232
1199 free_cpumask_var(conn->conn_cpumask);
1200
1201 kfree(conn->conn_ops);
1202
1203 if (conn->param_list) { 1233 if (conn->param_list) {
1204 iscsi_release_param_list(conn->param_list); 1234 iscsi_release_param_list(conn->param_list);
1205 conn->param_list = NULL; 1235 conn->param_list = NULL;
@@ -1217,8 +1247,7 @@ old_sess_out:
1217 if (conn->conn_transport->iscsit_free_conn) 1247 if (conn->conn_transport->iscsit_free_conn)
1218 conn->conn_transport->iscsit_free_conn(conn); 1248 conn->conn_transport->iscsit_free_conn(conn);
1219 1249
1220 iscsit_put_transport(conn->conn_transport); 1250 iscsit_free_conn(conn);
1221 kfree(conn);
1222} 1251}
1223 1252
1224static int __iscsi_target_login_thread(struct iscsi_np *np) 1253static int __iscsi_target_login_thread(struct iscsi_np *np)
@@ -1248,31 +1277,16 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
1248 } 1277 }
1249 spin_unlock_bh(&np->np_thread_lock); 1278 spin_unlock_bh(&np->np_thread_lock);
1250 1279
1251 conn = kzalloc(sizeof(struct iscsi_conn), GFP_KERNEL); 1280 conn = iscsit_alloc_conn(np);
1252 if (!conn) { 1281 if (!conn) {
1253 pr_err("Could not allocate memory for"
1254 " new connection\n");
1255 /* Get another socket */ 1282 /* Get another socket */
1256 return 1; 1283 return 1;
1257 } 1284 }
1258 pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
1259 conn->conn_state = TARG_CONN_STATE_FREE;
1260
1261 timer_setup(&conn->nopin_response_timer,
1262 iscsit_handle_nopin_response_timeout, 0);
1263 timer_setup(&conn->nopin_timer, iscsit_handle_nopin_timeout, 0);
1264
1265 if (iscsit_conn_set_transport(conn, np->np_transport) < 0) {
1266 kfree(conn);
1267 return 1;
1268 }
1269 1285
1270 rc = np->np_transport->iscsit_accept_np(np, conn); 1286 rc = np->np_transport->iscsit_accept_np(np, conn);
1271 if (rc == -ENOSYS) { 1287 if (rc == -ENOSYS) {
1272 complete(&np->np_restart_comp); 1288 complete(&np->np_restart_comp);
1273 iscsit_put_transport(conn->conn_transport); 1289 iscsit_free_conn(conn);
1274 kfree(conn);
1275 conn = NULL;
1276 goto exit; 1290 goto exit;
1277 } else if (rc < 0) { 1291 } else if (rc < 0) {
1278 spin_lock_bh(&np->np_thread_lock); 1292 spin_lock_bh(&np->np_thread_lock);
@@ -1280,17 +1294,13 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
1280 np->np_thread_state = ISCSI_NP_THREAD_ACTIVE; 1294 np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
1281 spin_unlock_bh(&np->np_thread_lock); 1295 spin_unlock_bh(&np->np_thread_lock);
1282 complete(&np->np_restart_comp); 1296 complete(&np->np_restart_comp);
1283 iscsit_put_transport(conn->conn_transport); 1297 iscsit_free_conn(conn);
1284 kfree(conn);
1285 conn = NULL;
1286 /* Get another socket */ 1298 /* Get another socket */
1287 return 1; 1299 return 1;
1288 } 1300 }
1289 spin_unlock_bh(&np->np_thread_lock); 1301 spin_unlock_bh(&np->np_thread_lock);
1290 iscsit_put_transport(conn->conn_transport); 1302 iscsit_free_conn(conn);
1291 kfree(conn); 1303 return 1;
1292 conn = NULL;
1293 goto out;
1294 } 1304 }
1295 /* 1305 /*
1296 * Perform the remaining iSCSI connection initialization items.. 1306 * Perform the remaining iSCSI connection initialization items..
@@ -1440,7 +1450,6 @@ old_sess_out:
1440 tpg_np = NULL; 1450 tpg_np = NULL;
1441 } 1451 }
1442 1452
1443out:
1444 return 1; 1453 return 1;
1445 1454
1446exit: 1455exit:
diff --git a/drivers/target/iscsi/iscsi_target_login.h b/drivers/target/iscsi/iscsi_target_login.h
index 74ac3abc44a0..3b8e3639ff5d 100644
--- a/drivers/target/iscsi/iscsi_target_login.h
+++ b/drivers/target/iscsi/iscsi_target_login.h
@@ -19,7 +19,7 @@ extern int iscsi_target_setup_login_socket(struct iscsi_np *,
19extern int iscsit_accept_np(struct iscsi_np *, struct iscsi_conn *); 19extern int iscsit_accept_np(struct iscsi_np *, struct iscsi_conn *);
20extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *); 20extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *);
21extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32); 21extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32);
22extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *); 22extern void iscsit_free_conn(struct iscsi_conn *);
23extern int iscsit_start_kthreads(struct iscsi_conn *); 23extern int iscsit_start_kthreads(struct iscsi_conn *);
24extern void iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8); 24extern void iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8);
25extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *, 25extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *,