diff --git a/iscsi-scst/kernel/conn.c b/iscsi-scst/kernel/conn.c index 03596afd8..55e45d3b2 100644 --- a/iscsi-scst/kernel/conn.c +++ b/iscsi-scst/kernel/conn.c @@ -275,6 +275,12 @@ static void conn_rsp_timer_fn(unsigned long arg) return; } +/* + * Note: the code belows passes a kernel space pointer (&opt) to setsockopt() + * while the declaration of setsockopt specifies that it expects a user space + * pointer. This seems to work fine, and this approach is also used in some + * other parts of the Linux kernel (see e.g. fs/ocfs2/cluster/tcp.c). + */ static int iscsi_socket_bind(struct iscsi_conn *conn) { int res = 0; @@ -314,7 +320,7 @@ static int iscsi_socket_bind(struct iscsi_conn *conn) oldfs = get_fs(); set_fs(get_ds()); conn->sock->ops->setsockopt(conn->sock, SOL_TCP, TCP_NODELAY, - (void *)&opt, sizeof(opt)); + (void __force __user *)&opt, sizeof(opt)); set_fs(oldfs); out: diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index c8d55540c..44bab35ca 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -961,7 +961,7 @@ static void cmnd_prepare_get_rejected_cmd_data(struct iscsi_cmnd *cmnd) cmnd->own_sg = 1; } - addr = page_address(sg_page(&sg[0])); + addr = (char __force __user *)(page_address(sg_page(&sg[0]))); sBUG_ON(addr == NULL); size = (size + 3) & -4; conn->read_size = size; @@ -1030,7 +1030,7 @@ static int cmnd_prepare_recv_pdu(struct iscsi_conn *conn, struct scatterlist *sg = cmd->sg; int bufflen = cmd->bufflen; int idx, i; - char *addr; + char __user *addr; int res = 0; TRACE_DBG("%p %u,%u", cmd->sg, offset, size); @@ -1054,7 +1054,7 @@ static int cmnd_prepare_recv_pdu(struct iscsi_conn *conn, i = 0; while (1) { - addr = page_address(sg_page(&sg[idx])); + addr = (char __force __user *)(page_address(sg_page(&sg[idx]))); sBUG_ON(addr == NULL); conn->read_iov[i].iov_base = addr + offset; if (offset + size <= PAGE_SIZE) { @@ -1254,7 +1254,7 @@ static int noop_out_start(struct iscsi_cmnd *cmnd) for (i = 0; i < cmnd->sg_cnt; i++) { conn->read_iov[i].iov_base = - page_address(sg_page(&sg[i])); + (void __force __user *)(page_address(sg_page(&sg[i]))); tmp = min_t(u32, size, PAGE_SIZE); conn->read_iov[i].iov_len = tmp; conn->read_size += tmp; @@ -1269,7 +1269,7 @@ static int noop_out_start(struct iscsi_cmnd *cmnd) */ for (i = 0; i < ISCSI_CONN_IOV_MAX; i++) { conn->read_iov[i].iov_base = - page_address(dummy_page); + (void __force __user *)(page_address(dummy_page)); tmp = min_t(u32, size, PAGE_SIZE); conn->read_iov[i].iov_len = tmp; conn->read_size += tmp; @@ -2107,6 +2107,12 @@ static void cmnd_send_pdu(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) __cmnd_send_pdu(conn, cmnd, 0, size); } +/* + * Note: the code belows passes a kernel space pointer (&opt) to setsockopt() + * while the declaration of setsockopt specifies that it expects a user space + * pointer. This seems to work fine, and this approach is also used in some + * other parts of the Linux kernel (see e.g. fs/ocfs2/cluster/tcp.c). + */ static void set_cork(struct socket *sock, int on) { int opt = on; @@ -2115,7 +2121,7 @@ static void set_cork(struct socket *sock, int on) oldfs = get_fs(); set_fs(get_ds()); sock->ops->setsockopt(sock, SOL_TCP, TCP_CORK, - (void *)&opt, sizeof(opt)); + (void __force __user *)&opt, sizeof(opt)); set_fs(oldfs); } @@ -2130,8 +2136,8 @@ void cmnd_tx_start(struct iscsi_cmnd *cmnd) set_cork(conn->sock, 1); - conn->write_iop = conn->write_iov; - conn->write_iop->iov_base = &cmnd->pdu.bhs; + conn->write_iop = (void __force __user *)(conn->write_iov); + conn->write_iop->iov_base = (void __force __user *)(&cmnd->pdu.bhs); conn->write_iop->iov_len = sizeof(cmnd->pdu.bhs); conn->write_iop_used = 1; conn->write_size = sizeof(cmnd->pdu.bhs); diff --git a/iscsi-scst/kernel/iscsi.h b/iscsi-scst/kernel/iscsi.h index ea004435b..6f7b956cb 100644 --- a/iscsi-scst/kernel/iscsi.h +++ b/iscsi-scst/kernel/iscsi.h @@ -164,12 +164,12 @@ struct iscsi_conn { struct task_struct *wr_task; #endif - /* + /* * All are unprotected, since accessed only from a single write * thread. */ struct iscsi_cmnd *write_cmnd; - struct iovec *write_iop; + struct iovec __user *write_iop; int write_iop_used; struct iovec write_iov[2]; u32 write_size; diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index 8bbdef748..22f5bae9f 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -535,7 +535,8 @@ static void start_close_conn(struct iscsi_conn *conn) return; } -static inline void iscsi_conn_init_read(struct iscsi_conn *conn, void *data, +static inline void iscsi_conn_init_read(struct iscsi_conn *conn, + void __user *data, size_t len) { len = (len + 3) & -4; /* XXX ??? */ @@ -552,7 +553,8 @@ static void iscsi_conn_read_ahs(struct iscsi_conn *conn, /* ToDo: __GFP_NOFAIL ?? */ cmnd->pdu.ahs = kmalloc(cmnd->pdu.ahssize, __GFP_NOFAIL|GFP_KERNEL); sBUG_ON(cmnd->pdu.ahs == NULL); - iscsi_conn_init_read(conn, cmnd->pdu.ahs, cmnd->pdu.ahssize); + iscsi_conn_init_read(conn, (void __force __user *)cmnd->pdu.ahs, + cmnd->pdu.ahssize); } static struct iscsi_cmnd *iscsi_get_send_cmnd(struct iscsi_conn *conn) @@ -651,7 +653,8 @@ static struct iscsi_cmnd *create_cmnd(struct iscsi_conn *conn) struct iscsi_cmnd *cmnd; cmnd = cmnd_alloc(conn, NULL); - iscsi_conn_init_read(cmnd->conn, &cmnd->pdu.bhs, sizeof(cmnd->pdu.bhs)); + iscsi_conn_init_read(cmnd->conn, (void __force __user *)&cmnd->pdu.bhs, + sizeof(cmnd->pdu.bhs)); conn->read_state = RX_BHS; return cmnd; @@ -692,7 +695,8 @@ static int recv(struct iscsi_conn *conn) if (res <= 0 || conn->read_state != RX_INIT_HDIGEST) break; case RX_INIT_HDIGEST: - iscsi_conn_init_read(conn, &cmnd->hdigest, sizeof(u32)); + iscsi_conn_init_read(conn, + (void __force __user *)&cmnd->hdigest, sizeof(u32)); conn->read_state = RX_HDIGEST; case RX_HDIGEST: res = do_recv(conn, RX_CHECK_HDIGEST); @@ -723,7 +727,8 @@ static int recv(struct iscsi_conn *conn) if (res <= 0 || conn->read_state != RX_INIT_DDIGEST) break; case RX_INIT_DDIGEST: - iscsi_conn_init_read(conn, &cmnd->ddigest, sizeof(u32)); + iscsi_conn_init_read(conn, + (void __force __user *)&cmnd->ddigest, sizeof(u32)); conn->read_state = RX_DDIGEST; case RX_DDIGEST: res = do_recv(conn, RX_CHECK_DDIGEST); @@ -983,7 +988,7 @@ static int write_data(struct iscsi_conn *conn) struct iscsi_cmnd *write_cmnd = conn->write_cmnd; struct iscsi_cmnd *ref_cmd; struct scatterlist *sg; - struct iovec *iop; + struct iovec __user *iop; int saved_size, size, sendsize; int offset, idx, sg_offset; int flags, res, count; @@ -1035,8 +1040,7 @@ static int write_data(struct iscsi_conn *conn) retry: oldfs = get_fs(); set_fs(KERNEL_DS); - res = vfs_writev(file, (struct iovec __user *)iop, - count, &off); + res = vfs_writev(file, iop, count, &off); set_fs(oldfs); TRACE_WRITE("%#Lx:%u: %d(%ld)", (long long unsigned int)conn->session->sid, @@ -1268,7 +1272,8 @@ static int tx_ddigest(struct iscsi_cmnd *cmnd, int state) TRACE_DBG("Sending data digest %x (cmd %p)", cmnd->ddigest, cmnd); - iov.iov_base = (char *) (&cmnd->ddigest) + (sizeof(u32) - rest); + iov.iov_base = + (char __force __user *) (&cmnd->ddigest) + (sizeof(u32) - rest); iov.iov_len = rest; res = kernel_sendmsg(cmnd->conn->sock, &msg, &iov, 1, rest); @@ -1296,7 +1301,7 @@ static void init_tx_hdigest(struct iscsi_cmnd *cmnd) iop = &conn->write_iop[conn->write_iop_used]; conn->write_iop_used++; - iop->iov_base = &(cmnd->hdigest); + iop->iov_base = (void __force __user *)&(cmnd->hdigest); iop->iov_len = sizeof(u32); conn->write_size += sizeof(u32); diff --git a/scst/include/scst.h b/scst/include/scst.h index 51e728947..aa06e9356 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -550,8 +550,8 @@ struct scst_tgt_template { * * Shall return 0 in case of success or < 0 (preferrably -ENOMEM) * in case of error, or > 0 if the regular SCST allocation should be - * done. In case of returning successfully, scst_cmd->tgt_data_buf_alloced - * will be set by SCST. + * done. In case of returning successfully, + * scst_cmd->tgt_data_buf_alloced will be set by SCST. * * It is possible that both target driver and dev handler request own * memory allocation. In this case, data will be memcpy() between diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index edd490c37..e86913d90 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -809,7 +809,7 @@ static void dev_user_flush_dcache(struct scst_user_cmd *ucmd) * faster, since it should be cache hot, while ucmd->buf_ucmd and * buf_ucmd->data_pages are cache cold. But, from other side, * sizeof(buf_ucmd->data_pages[0]) is considerably smaller, than - * sizeof(ucmd->cmd->sg[0]), so on big buffers going over + * sizeof(ucmd->cmd->sg[0]), so on big buffers going over * data_pages array can lead to less cache misses. So, real numbers are * needed. ToDo. */ @@ -1510,6 +1510,8 @@ out: } static int dev_user_process_scst_commands(struct scst_user_dev *dev) + __releases(&dev->cmd_lists.cmd_list_lock) + __acquires(&dev->cmd_lists.cmd_list_lock) { int res = 0; @@ -1533,6 +1535,8 @@ static int dev_user_process_scst_commands(struct scst_user_dev *dev) /* Called under cmd_lists.cmd_list_lock and IRQ off */ static struct scst_user_cmd *__dev_user_get_next_cmd(struct list_head *cmd_list) + __releases(&dev->cmd_lists.cmd_list_lock) + __acquires(&dev->cmd_lists.cmd_list_lock) { struct scst_user_cmd *u; @@ -1841,6 +1845,8 @@ out: */ static void dev_user_unjam_cmd(struct scst_user_cmd *ucmd, int busy, unsigned long *flags) + __releases(&dev->cmd_lists.cmd_list_lock) + __acquires(&dev->cmd_lists.cmd_list_lock) { int state = ucmd->state; struct scst_user_dev *dev = ucmd->dev; @@ -1959,6 +1965,8 @@ out: } static void dev_user_unjam_dev(struct scst_user_dev *dev) + __releases(&dev->cmd_lists.cmd_list_lock) + __acquires(&dev->cmd_lists.cmd_list_lock) { int i; struct scst_user_cmd *ucmd; diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index a95930a41..b5f9facba 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -2082,7 +2082,7 @@ static void vdisk_exec_read(struct scst_cmd *cmd, mm_segment_t old_fs; loff_t err; ssize_t length, full_len; - uint8_t *address; + uint8_t __user *address; struct scst_vdisk_dev *virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv; struct file *fd = thr->fd; @@ -2101,14 +2101,14 @@ static void vdisk_exec_read(struct scst_cmd *cmd, iv_count = 0; full_len = 0; i = -1; - length = scst_get_buf_first(cmd, &address); + length = scst_get_buf_first(cmd, (uint8_t __force **)&address); while (length > 0) { full_len += length; i++; iv_count++; iv[i].iov_base = address; iv[i].iov_len = length; - length = scst_get_buf_next(cmd, &address); + length = scst_get_buf_next(cmd, (uint8_t __force **)&address); } if (unlikely(length < 0)) { PRINT_ERROR("scst_get_buf_() failed: %zd", length); @@ -2161,7 +2161,7 @@ out_set_fs: out_put: for (; i >= 0; i--) - scst_put_buf(cmd, iv[i].iov_base); + scst_put_buf(cmd, (void __force *)(iv[i].iov_base)); out: TRACE_EXIT(); @@ -2174,7 +2174,7 @@ static void vdisk_exec_write(struct scst_cmd *cmd, mm_segment_t old_fs; loff_t err; ssize_t length, full_len; - uint8_t *address; + uint8_t __user *address; struct scst_vdisk_dev *virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv; struct file *fd = thr->fd; @@ -2192,13 +2192,13 @@ static void vdisk_exec_write(struct scst_cmd *cmd, iv_count = 0; full_len = 0; - length = scst_get_buf_first(cmd, &address); + length = scst_get_buf_first(cmd, (uint8_t __force **)&address); while (length > 0) { full_len += length; iv[iv_count].iov_base = address; iv[iv_count].iov_len = length; iv_count++; - length = scst_get_buf_next(cmd, &address); + length = scst_get_buf_next(cmd, (uint8_t __force **)&address); } if (unlikely(length < 0)) { PRINT_ERROR("scst_get_buf_() failed: %zd", length); @@ -2269,7 +2269,8 @@ restart: eiv_count--; } else { eiv->iov_base = - (uint8_t *)eiv->iov_base + err; + (uint8_t __force __user *)eiv->iov_base + + err; eiv->iov_len -= err; break; } @@ -2282,7 +2283,7 @@ out_set_fs: out_put: while (iv_count > 0) { - scst_put_buf(cmd, iv[iv_count-1].iov_base); + scst_put_buf(cmd, (void __force *)(iv[iv_count-1].iov_base)); iv_count--; } @@ -2546,8 +2547,9 @@ static void vdisk_exec_verify(struct scst_cmd *cmd, TRACE_DBG("Verify: length %zd - len_mem %zd", length, len_mem); if (!virt_dev->nullio) - err = fd->f_op->read(fd, (char *)mem_verify, len_mem, - &fd->f_pos); + err = fd->f_op->read(fd, + (char __force __user *)mem_verify, len_mem, + &fd->f_pos); else err = len_mem; if ((err < 0) || (err < len_mem)) { diff --git a/scst/src/scst_mem.c b/scst/src/scst_mem.c index 114553786..9ee173057 100644 --- a/scst/src/scst_mem.c +++ b/scst/src/scst_mem.c @@ -436,8 +436,8 @@ static int sgv_pool_cached_purge(struct sgv_pool_obj *e, int t, /* Called under pool_mgr_lock held, but drops/reaquires it inside */ static int sgv_pool_oom_free_objs(int pgs) - __releases(sgv_pools_mgr.mgr.pool_mgr_lock) - __acquires(sgv_pools_mgr.mgr.pool_mgr_lock) + __releases(&sgv_pools_mgr.mgr.pool_mgr_lock) + __acquires(&sgv_pools_mgr.mgr.pool_mgr_lock) { TRACE_MEM("Shrinking pools about %d pages", pgs); while ((sgv_pools_mgr.mgr.throttle.inactive_pages_total > @@ -940,7 +940,7 @@ int sgv_pool_init(struct sgv_pool *pool, const char *name, int clustered) (sizeof(obj->sg_entries[0]) + (clustered ? sizeof(obj->trans_tbl[0]) : 0)); } else if (i <= sgv_pools_mgr.sgv_max_trans_order) { - /* + /* * sgv ie sg_entries is allocated outside object, but * ttbl is still embedded. */ diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 46d1ebd35..e940e6159 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -793,7 +793,7 @@ out_error: goto out; } -void scst_restart_cmd(struct scst_cmd *cmd, int status, +void scst_restart_cmd(struct scst_cmd *cmd, int status, enum scst_exec_context pref_context) { TRACE_ENTRY(); @@ -1215,7 +1215,7 @@ static void scst_do_cmd_done(struct scst_cmd *cmd, int result, TRACE(TRACE_SCSI, "cmd %p, result=%x, cmd->status=%x, resid=%d, " "cmd->msg_status=%x, cmd->host_status=%x, " - "cmd->driver_status=%x (cmd %p)",cmd, result, cmd->status, resid, + "cmd->driver_status=%x (cmd %p)", cmd, result, cmd->status, resid, cmd->msg_status, cmd->host_status, cmd->driver_status, cmd); cmd->completed = 1; @@ -3157,6 +3157,8 @@ out_busy: /* Called under scst_init_lock and IRQs disabled */ static void scst_do_job_init(void) + __releases(&scst_init_lock) + __acquires(&scst_init_lock) { struct scst_cmd *cmd; int susp; @@ -3444,6 +3446,8 @@ EXPORT_SYMBOL(scst_process_active_cmd); /* Called under cmd_list_lock and IRQs disabled */ static void scst_do_job_active(struct list_head *cmd_list, spinlock_t *cmd_list_lock, bool atomic) + __releases(cmd_list_lock) + __acquires(cmd_list_lock) { TRACE_ENTRY(); @@ -4329,7 +4333,7 @@ static int scst_target_reset(struct scst_mgmt_cmd *mcmd) #if 0 if ((rc != SUCCESS) && (mcmd->status == SCST_MGMT_STATUS_SUCCESS)) { - /* + /* * SCSI_TRY_RESET_BUS is also done by * scsi_reset_provider() */ @@ -4877,7 +4881,7 @@ int scst_mgmt_cmd_thread(void *arg) if (rc > 0) { if (test_bit(SCST_FLAG_SUSPENDED, &scst_flags) && !test_bit(SCST_FLAG_SUSPENDING, - &scst_flags)) { + &scst_flags)) { TRACE_MGMT_DBG("Adding mgmt cmd %p to " "head of delayed mgmt cmd list", mcmd);