diff --git a/iscsi-scst/kernel/config.c b/iscsi-scst/kernel/config.c index 6a3de7039..f48d8eac6 100644 --- a/iscsi-scst/kernel/config.c +++ b/iscsi-scst/kernel/config.c @@ -302,16 +302,19 @@ const struct attribute *iscsi_attrs[] = { /* target_mgmt_mutex supposed to be locked */ static int add_conn(void __user *ptr) { - int err; + int err, rc; struct iscsi_session *session; struct iscsi_kern_conn_info info; struct iscsi_target *target; TRACE_ENTRY(); - err = copy_from_user(&info, ptr, sizeof(info)); - if (err < 0) + rc = copy_from_user(&info, ptr, sizeof(info)); + if (rc != 0) { + PRINT_ERROR("Failed to copy %d user's bytes", rc); + err = -EFAULT; goto out; + } target = target_lookup_by_id(info.tid); if (target == NULL) { @@ -343,16 +346,19 @@ out: /* target_mgmt_mutex supposed to be locked */ static int del_conn(void __user *ptr) { - int err; + int err, rc; struct iscsi_session *session; struct iscsi_kern_conn_info info; struct iscsi_target *target; TRACE_ENTRY(); - err = copy_from_user(&info, ptr, sizeof(info)); - if (err < 0) + rc = copy_from_user(&info, ptr, sizeof(info)); + if (rc != 0) { + PRINT_ERROR("Failed to copy %d user's bytes", rc); + err = -EFAULT; goto out; + } target = target_lookup_by_id(info.tid); if (target == NULL) { @@ -384,7 +390,7 @@ out: /* target_mgmt_mutex supposed to be locked */ static int add_session(void __user *ptr) { - int err; + int err, rc; struct iscsi_kern_session_info *info; struct iscsi_target *target; @@ -397,9 +403,9 @@ static int add_session(void __user *ptr) goto out; } - err = copy_from_user(info, ptr, sizeof(*info)); - if (err != 0) { - PRINT_ERROR("copy_from_user() didn't copy %d bytes", err); + rc = copy_from_user(info, ptr, sizeof(*info)); + if (rc != 0) { + PRINT_ERROR("Failed to copy %d user's bytes", rc); err = -EFAULT; goto out_free; } @@ -429,7 +435,7 @@ out: /* target_mgmt_mutex supposed to be locked */ static int del_session(void __user *ptr) { - int err; + int err, rc; struct iscsi_kern_session_info *info; struct iscsi_target *target; @@ -442,9 +448,9 @@ static int del_session(void __user *ptr) goto out; } - err = copy_from_user(info, ptr, sizeof(*info)); - if (err != 0) { - PRINT_ERROR("copy_from_user() didn't copy %d bytes", err); + rc = copy_from_user(info, ptr, sizeof(*info)); + if (rc != 0) { + PRINT_ERROR("Failed to copy %d user's bytes", rc); err = -EFAULT; goto out_free; } @@ -476,15 +482,18 @@ out: /* target_mgmt_mutex supposed to be locked */ static int iscsi_params_config(void __user *ptr, int set) { - int err; + int err, rc; struct iscsi_kern_params_info info; struct iscsi_target *target; TRACE_ENTRY(); - err = copy_from_user(&info, ptr, sizeof(info)); - if (err < 0) + rc = copy_from_user(&info, ptr, sizeof(info)); + if (rc != 0) { + PRINT_ERROR("Failed to copy %d user's bytes", rc); + err = -EFAULT; goto out; + } target = target_lookup_by_id(info.tid); if (target == NULL) { @@ -500,8 +509,14 @@ static int iscsi_params_config(void __user *ptr, int set) if (err < 0) goto out; - if (!set) - err = copy_to_user(ptr, &info, sizeof(info)); + if (!set) { + rc = copy_to_user(ptr, &info, sizeof(info)); + if (rc != 0) { + PRINT_ERROR("Failed to copy to user %d bytes", rc); + err = -EFAULT; + goto out; + } + } out: TRACE_EXIT_RES(err); @@ -521,6 +536,7 @@ static int mgmt_cmd_callback(void __user *ptr) rc = copy_from_user(&cinfo, ptr, sizeof(cinfo)); if (rc != 0) { + PRINT_ERROR("Failed to copy %d user's bytes", rc); err = -EFAULT; goto out; } @@ -800,6 +816,7 @@ static int iscsi_attr_cmd(void __user *ptr, unsigned int cmd) rc = copy_from_user(&info, ptr, sizeof(info)); if (rc != 0) { + PRINT_ERROR("Failed to copy %d user's bytes", rc); err = -EFAULT; goto out; } @@ -849,7 +866,7 @@ out: /* target_mgmt_mutex supposed to be locked */ static int add_target(void __user *ptr) { - int err; + int err, rc; struct iscsi_kern_target_info *info; #ifndef CONFIG_SCST_PROC struct scst_sysfs_user_info *uinfo; @@ -864,9 +881,9 @@ static int add_target(void __user *ptr) goto out; } - err = copy_from_user(info, ptr, sizeof(*info)); - if (err != 0) { - PRINT_ERROR("copy_from_user() didn't copy %d bytes", err); + rc = copy_from_user(info, ptr, sizeof(*info)); + if (rc != 0) { + PRINT_ERROR("Failed to copy %d user's bytes", rc); err = -EFAULT; goto out_free; } @@ -911,7 +928,7 @@ out: /* target_mgmt_mutex supposed to be locked */ static int del_target(void __user *ptr) { - int err; + int err, rc; struct iscsi_kern_target_info info; #ifndef CONFIG_SCST_PROC struct scst_sysfs_user_info *uinfo; @@ -919,9 +936,12 @@ static int del_target(void __user *ptr) TRACE_ENTRY(); - err = copy_from_user(&info, ptr, sizeof(info)); - if (err < 0) + rc = copy_from_user(&info, ptr, sizeof(info)); + if (rc != 0) { + PRINT_ERROR("Failed to copy %d user's bytes", rc); + err = -EFAULT; goto out; + } info.name[sizeof(info.name)-1] = '\0'; @@ -968,7 +988,7 @@ static int iscsi_register(void __user *arg) rc = copy_from_user(ver, (void __user *)(unsigned long)reg.version, sizeof(ver)); - if (rc < 0) { + if (rc != 0) { PRINT_ERROR("%s", "Unable to get version string"); res = -EFAULT; goto out; @@ -989,7 +1009,7 @@ static int iscsi_register(void __user *arg) rc = copy_to_user(arg, ®, sizeof(reg)); if (rc != 0) { - PRINT_ERROR("copy_to_user() failed to copy %d bytes", res); + PRINT_ERROR("Failed to copy to user %d bytes", rc); res = -EFAULT; goto out; } diff --git a/iscsi-scst/kernel/target.c b/iscsi-scst/kernel/target.c index 0f03da08c..b72fbd9bd 100644 --- a/iscsi-scst/kernel/target.c +++ b/iscsi-scst/kernel/target.c @@ -184,7 +184,7 @@ int __add_target(struct iscsi_kern_target_info *info) rc = copy_from_user(attr_info, attrs_ptr, sizeof(*attr_info)); if (rc != 0) { - PRINT_ERROR("copy_from_user() of users of target %s " + PRINT_ERROR("Failed to copy users of target %s " "failed", info->name); err = -EFAULT; goto out_del_unlock; diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index 995778be6..fd8f59727 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -1245,7 +1245,7 @@ out_hwerr: static int dev_user_process_reply_parse(struct scst_user_cmd *ucmd, struct scst_user_reply_cmd *reply) { - int res = 0; + int res = 0, rc; struct scst_user_scsi_cmd_reply_parse *preply = &reply->parse_reply; struct scst_cmd *cmd = ucmd->cmd; @@ -1323,11 +1323,12 @@ out_status: sense_len = min_t(int, cmd->sense_buflen, preply->sense_len); - res = copy_from_user(cmd->sense, + rc = copy_from_user(cmd->sense, (void __user *)(unsigned long)preply->psense_buffer, sense_len); - if (res < 0) { - PRINT_ERROR("%s", "Unable to get sense data"); + if (rc != 0) { + PRINT_ERROR("Failed to copy %d sense's bytes", rc); + res = -EFAULT; goto out_hwerr_res_set; } cmd->sense_valid_len = sense_len; @@ -1443,7 +1444,7 @@ static int dev_user_process_reply_exec(struct scst_user_cmd *ucmd, cmd->status = ereply->status; if (ereply->sense_len != 0) { - int sense_len; + int sense_len, rc; res = scst_alloc_sense(cmd, 0); if (res != 0) @@ -1451,11 +1452,12 @@ static int dev_user_process_reply_exec(struct scst_user_cmd *ucmd, sense_len = min((int)cmd->sense_buflen, (int)ereply->sense_len); - res = copy_from_user(cmd->sense, + rc = copy_from_user(cmd->sense, (void __user *)(unsigned long)ereply->psense_buffer, sense_len); - if (res < 0) { - PRINT_ERROR("%s", "Unable to get sense data"); + if (rc != 0) { + PRINT_ERROR("Failed to copy %d sense's bytes", rc); + res = -EFAULT; goto out_hwerr_res_set; } cmd->sense_valid_len = sense_len; @@ -1610,7 +1612,7 @@ out_unlock: static int dev_user_reply_cmd(struct file *file, void __user *arg) { - int res = 0; + int res = 0, rc; struct scst_user_dev *dev; struct scst_user_reply_cmd reply; @@ -1626,9 +1628,12 @@ static int dev_user_reply_cmd(struct file *file, void __user *arg) down_read(&dev->dev_rwsem); mutex_unlock(&dev_priv_mutex); - res = copy_from_user(&reply, arg, sizeof(reply)); - if (unlikely(res < 0)) + rc = copy_from_user(&reply, arg, sizeof(reply)); + if (unlikely(rc != 0)) { + PRINT_ERROR("Failed to copy %d user's bytes", rc); + res = -EFAULT; goto out_up; + } TRACE_DBG("Reply for dev %s", dev->name); @@ -1648,7 +1653,7 @@ out: static int dev_user_get_ext_cdb(struct file *file, void __user *arg) { - int res = 0; + int res = 0, rc; struct scst_user_dev *dev; struct scst_user_cmd *ucmd; struct scst_cmd *cmd = NULL; @@ -1666,9 +1671,12 @@ static int dev_user_get_ext_cdb(struct file *file, void __user *arg) down_read(&dev->dev_rwsem); mutex_unlock(&dev_priv_mutex); - res = copy_from_user(&get, arg, sizeof(get)); - if (unlikely(res < 0)) + rc = copy_from_user(&get, arg, sizeof(get)); + if (unlikely(rc != 0)) { + PRINT_ERROR("Failed to copy %d user's bytes", rc); + res = -EFAULT; goto out_up; + } TRACE_MGMT_DBG("Get ext cdb for dev %s", dev->name); @@ -1709,8 +1717,13 @@ static int dev_user_get_ext_cdb(struct file *file, void __user *arg) goto out_cmd_put; TRACE_BUFFER("EXT CDB", cmd->ext_cdb, cmd->ext_cdb_len); - res = copy_to_user((void __user *)(unsigned long)get.ext_cdb_buffer, + rc = copy_to_user((void __user *)(unsigned long)get.ext_cdb_buffer, cmd->ext_cdb, cmd->ext_cdb_len); + if (unlikely(rc != 0)) { + PRINT_ERROR("Failed to copy to user %d bytes", rc); + res = -EFAULT; + goto out_cmd_put; + } out_cmd_put: scst_cmd_put(cmd); @@ -1878,7 +1891,7 @@ static int dev_user_get_next_cmd(struct scst_user_dev *dev, static int dev_user_reply_get_cmd(struct file *file, void __user *arg) { - int res = 0; + int res = 0, rc; struct scst_user_dev *dev; struct scst_user_get_cmd *cmd; struct scst_user_reply_cmd *reply; @@ -1898,11 +1911,14 @@ static int dev_user_reply_get_cmd(struct file *file, void __user *arg) mutex_unlock(&dev_priv_mutex); /* get_user() can't be used with 64-bit values on x86_32 */ - res = copy_from_user(&ureply, (uint64_t __user *) + rc = copy_from_user(&ureply, (uint64_t __user *) &((struct scst_user_get_cmd __user *)arg)->preply, sizeof(ureply)); - if (unlikely(res < 0)) + if (unlikely(rc != 0)) { + PRINT_ERROR("Failed to copy %d user's bytes", rc); + res = -EFAULT; goto out_up; + } TRACE_DBG("ureply %lld (dev %s)", (long long unsigned int)ureply, dev->name); @@ -1916,9 +1932,12 @@ static int dev_user_reply_get_cmd(struct file *file, void __user *arg) if (ureply != 0) { unsigned long u = (unsigned long)ureply; reply = (struct scst_user_reply_cmd *)cmd; - res = copy_from_user(reply, (void __user *)u, sizeof(*reply)); - if (unlikely(res < 0)) + rc = copy_from_user(reply, (void __user *)u, sizeof(*reply)); + if (unlikely(rc != 0)) { + PRINT_ERROR("Failed to copy %d user's bytes", rc); + res = -EFAULT; goto out_free; + } TRACE_BUFFER("Reply", reply, sizeof(*reply)); @@ -1952,11 +1971,12 @@ again: TRACE_DBG("ucmd %p (user_cmd %p), payload_len %d (len %d)", ucmd, &ucmd->user_cmd, ucmd->user_cmd_payload_len, len); TRACE_BUFFER("UCMD", &ucmd->user_cmd, len); - res = copy_to_user(arg, &ucmd->user_cmd, len); - if (unlikely(res != 0)) { + rc = copy_to_user(arg, &ucmd->user_cmd, len); + if (unlikely(rc != 0)) { + PRINT_ERROR("Copy to user failed (%d), requeuing ucmd " + "%p back to head of ready cmd list", rc, ucmd); + res = -EFAULT; /* Requeue ucmd back */ - TRACE_DBG("Copy to user failed (%d), requeuing ucmd %p " - "back to head of ready cmd list", res, ucmd); spin_lock_irq(&dev->cmd_lists.cmd_list_lock); list_add(&ucmd->ready_cmd_list_entry, &dev->ready_cmd_list); @@ -1985,7 +2005,7 @@ out_free: static long dev_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - long res; + long res, rc; TRACE_ENTRY(); @@ -2014,9 +2034,11 @@ static long dev_user_ioctl(struct file *file, unsigned int cmd, res = -ENOMEM; goto out; } - res = copy_from_user(dev_desc, (void __user *)arg, + rc = copy_from_user(dev_desc, (void __user *)arg, sizeof(*dev_desc)); - if (res < 0) { + if (rc != 0) { + PRINT_ERROR("Failed to copy %ld user's bytes", rc); + res = -EFAULT; kfree(dev_desc); goto out; } @@ -2042,9 +2064,12 @@ static long dev_user_ioctl(struct file *file, unsigned int cmd, { struct scst_user_opt opt; TRACE_DBG("%s", "SET_OPTIONS"); - res = copy_from_user(&opt, (void __user *)arg, sizeof(opt)); - if (res < 0) + rc = copy_from_user(&opt, (void __user *)arg, sizeof(opt)); + if (rc != 0) { + PRINT_ERROR("Failed to copy %ld user's bytes", rc); + res = -EFAULT; goto out; + } TRACE_BUFFER("opt", &opt, sizeof(opt)); res = dev_user_set_opt(file, &opt); break; @@ -2705,13 +2730,14 @@ static void dev_user_setup_functions(struct scst_user_dev *dev) static int dev_user_check_version(const struct scst_user_dev_desc *dev_desc) { char ver[sizeof(DEV_USER_VERSION)+1]; - int res; + int res = 0, rc; - res = copy_from_user(ver, + rc = copy_from_user(ver, (void __user *)(unsigned long)dev_desc->version_str, sizeof(ver)); - if (res < 0) { + if (rc != 0) { PRINT_ERROR("%s", "Unable to get version string"); + res = -EFAULT; goto out; } ver[sizeof(ver)-1] = '\0'; @@ -3040,7 +3066,7 @@ out: static int dev_user_prealloc_buffer(struct file *file, void __user *arg) { - int res = 0; + int res = 0, rc; struct scst_user_dev *dev; union scst_user_prealloc_buffer pre; aligned_u64 pbuf; @@ -3062,9 +3088,12 @@ static int dev_user_prealloc_buffer(struct file *file, void __user *arg) down_read(&dev->dev_rwsem); mutex_unlock(&dev_priv_mutex); - res = copy_from_user(&pre.in, arg, sizeof(pre.in)); - if (unlikely(res < 0)) + rc = copy_from_user(&pre.in, arg, sizeof(pre.in)); + if (unlikely(rc != 0)) { + PRINT_ERROR("Failed to copy %d user's bytes", rc); + res = -EFAULT; goto out_up; + } TRACE_MEM("Prealloc buffer with size %dKB for dev %s", pre.in.bufflen / 1024, dev->name); @@ -3120,7 +3149,12 @@ static int dev_user_prealloc_buffer(struct file *file, void __user *arg) dev_user_free_sgv(ucmd); pre.out.cmd_h = ucmd->h; - res = copy_to_user(arg, &pre.out, sizeof(pre.out)); + rc = copy_to_user(arg, &pre.out, sizeof(pre.out)); + if (unlikely(rc != 0)) { + PRINT_ERROR("Failed to copy to user %d bytes", rc); + res = -EFAULT; + goto out_put; + } out_put: ucmd_put(ucmd); @@ -3233,7 +3267,7 @@ out: static int dev_user_get_opt(struct file *file, void __user *arg) { - int res; + int res, rc; struct scst_user_dev *dev; struct scst_user_opt opt; @@ -3267,9 +3301,16 @@ static int dev_user_get_opt(struct file *file, void __user *arg) opt.on_free_cmd_type, opt.memory_reuse_type, opt.partial_transfers_type, opt.partial_len); - res = copy_to_user(arg, &opt, sizeof(opt)); + rc = copy_to_user(arg, &opt, sizeof(opt)); + if (unlikely(rc != 0)) { + PRINT_ERROR("Failed to copy to user %d bytes", rc); + res = -EFAULT; + goto out_up; + } +out_up: up_read(&dev->dev_rwsem); + out: TRACE_EXIT_RES(res); return res;