diff options
-rw-r--r-- | drivers/block/floppy.c | 73 |
1 files changed, 38 insertions, 35 deletions
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 4807203827cc..b7190fd582f4 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
@@ -3126,6 +3126,7 @@ static inline int raw_cmd_copyout(int cmd, void __user *param, | |||
3126 | } | 3126 | } |
3127 | ptr = ptr->next; | 3127 | ptr = ptr->next; |
3128 | } | 3128 | } |
3129 | |||
3129 | return 0; | 3130 | return 0; |
3130 | } | 3131 | } |
3131 | 3132 | ||
@@ -3156,18 +3157,19 @@ static inline int raw_cmd_copyin(int cmd, void __user *param, | |||
3156 | int i; | 3157 | int i; |
3157 | 3158 | ||
3158 | *rcmd = NULL; | 3159 | *rcmd = NULL; |
3159 | while (1) { | 3160 | |
3160 | ptr = kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER); | 3161 | loop: |
3161 | if (!ptr) | 3162 | ptr = kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER); |
3162 | return -ENOMEM; | 3163 | if (!ptr) |
3163 | *rcmd = ptr; | 3164 | return -ENOMEM; |
3164 | ret = copy_from_user(ptr, param, sizeof(*ptr)); | 3165 | *rcmd = ptr; |
3165 | if (ret) | 3166 | ret = copy_from_user(ptr, param, sizeof(*ptr)); |
3166 | return -EFAULT; | 3167 | if (ret) |
3167 | ptr->next = NULL; | 3168 | return -EFAULT; |
3168 | ptr->buffer_length = 0; | 3169 | ptr->next = NULL; |
3169 | param += sizeof(struct floppy_raw_cmd); | 3170 | ptr->buffer_length = 0; |
3170 | if (ptr->cmd_count > 33) | 3171 | param += sizeof(struct floppy_raw_cmd); |
3172 | if (ptr->cmd_count > 33) | ||
3171 | /* the command may now also take up the space | 3173 | /* the command may now also take up the space |
3172 | * initially intended for the reply & the | 3174 | * initially intended for the reply & the |
3173 | * reply count. Needed for long 82078 commands | 3175 | * reply count. Needed for long 82078 commands |
@@ -3176,34 +3178,35 @@ static inline int raw_cmd_copyin(int cmd, void __user *param, | |||
3176 | * 16 bytes for a structure, you'll one day | 3178 | * 16 bytes for a structure, you'll one day |
3177 | * discover that you really need 17... | 3179 | * discover that you really need 17... |
3178 | */ | 3180 | */ |
3181 | return -EINVAL; | ||
3182 | |||
3183 | for (i = 0; i < 16; i++) | ||
3184 | ptr->reply[i] = 0; | ||
3185 | ptr->resultcode = 0; | ||
3186 | ptr->kernel_data = NULL; | ||
3187 | |||
3188 | if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { | ||
3189 | if (ptr->length <= 0) | ||
3179 | return -EINVAL; | 3190 | return -EINVAL; |
3191 | ptr->kernel_data = (char *)fd_dma_mem_alloc(ptr->length); | ||
3192 | fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length); | ||
3193 | if (!ptr->kernel_data) | ||
3194 | return -ENOMEM; | ||
3195 | ptr->buffer_length = ptr->length; | ||
3196 | } | ||
3197 | if (ptr->flags & FD_RAW_WRITE) { | ||
3198 | ret = fd_copyin(ptr->data, ptr->kernel_data, ptr->length); | ||
3199 | if (ret) | ||
3200 | return ret; | ||
3201 | } | ||
3180 | 3202 | ||
3181 | for (i = 0; i < 16; i++) | 3203 | if (ptr->flags & FD_RAW_MORE) { |
3182 | ptr->reply[i] = 0; | ||
3183 | ptr->resultcode = 0; | ||
3184 | ptr->kernel_data = NULL; | ||
3185 | |||
3186 | if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { | ||
3187 | if (ptr->length <= 0) | ||
3188 | return -EINVAL; | ||
3189 | ptr->kernel_data = | ||
3190 | (char *)fd_dma_mem_alloc(ptr->length); | ||
3191 | fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length); | ||
3192 | if (!ptr->kernel_data) | ||
3193 | return -ENOMEM; | ||
3194 | ptr->buffer_length = ptr->length; | ||
3195 | } | ||
3196 | if (ptr->flags & FD_RAW_WRITE) { | ||
3197 | ret = fd_copyin(ptr->data, ptr->kernel_data, | ||
3198 | ptr->length); | ||
3199 | if (ret) | ||
3200 | return ret; | ||
3201 | } | ||
3202 | rcmd = &(ptr->next); | 3204 | rcmd = &(ptr->next); |
3203 | if (!(ptr->flags & FD_RAW_MORE)) | ||
3204 | return 0; | ||
3205 | ptr->rate &= 0x43; | 3205 | ptr->rate &= 0x43; |
3206 | goto loop; | ||
3206 | } | 3207 | } |
3208 | |||
3209 | return 0; | ||
3207 | } | 3210 | } |
3208 | 3211 | ||
3209 | static int raw_cmd_ioctl(int cmd, void __user *param) | 3212 | static int raw_cmd_ioctl(int cmd, void __user *param) |