.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * IDE ioctls handling. |
---|
3 | 4 | */ |
---|
4 | 5 | |
---|
| 6 | +#include <linux/compat.h> |
---|
5 | 7 | #include <linux/export.h> |
---|
6 | 8 | #include <linux/hdreg.h> |
---|
7 | 9 | #include <linux/ide.h> |
---|
8 | 10 | #include <linux/slab.h> |
---|
| 11 | + |
---|
| 12 | +static int put_user_long(long val, unsigned long arg) |
---|
| 13 | +{ |
---|
| 14 | + if (in_compat_syscall()) |
---|
| 15 | + return put_user(val, (compat_long_t __user *)compat_ptr(arg)); |
---|
| 16 | + |
---|
| 17 | + return put_user(val, (long __user *)arg); |
---|
| 18 | +} |
---|
9 | 19 | |
---|
10 | 20 | static const struct ide_ioctl_devset ide_ioctl_settings[] = { |
---|
11 | 21 | { HDIO_GET_32BIT, HDIO_SET_32BIT, &ide_devset_io_32bit }, |
---|
.. | .. |
---|
36 | 46 | mutex_lock(&ide_setting_mtx); |
---|
37 | 47 | err = ds->get(drive); |
---|
38 | 48 | mutex_unlock(&ide_setting_mtx); |
---|
39 | | - return err >= 0 ? put_user(err, (long __user *)arg) : err; |
---|
| 49 | + return err >= 0 ? put_user_long(err, arg) : err; |
---|
40 | 50 | |
---|
41 | 51 | set_val: |
---|
42 | | - if (bdev != bdev->bd_contains) |
---|
| 52 | + if (bdev_is_partition(bdev)) |
---|
43 | 53 | err = -EINVAL; |
---|
44 | 54 | else { |
---|
45 | 55 | if (!capable(CAP_SYS_ADMIN)) |
---|
.. | .. |
---|
55 | 65 | EXPORT_SYMBOL_GPL(ide_setting_ioctl); |
---|
56 | 66 | |
---|
57 | 67 | static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, |
---|
58 | | - unsigned long arg) |
---|
| 68 | + void __user *argp) |
---|
59 | 69 | { |
---|
60 | 70 | u16 *id = NULL; |
---|
61 | 71 | int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142; |
---|
.. | .. |
---|
76 | 86 | memcpy(id, drive->id, size); |
---|
77 | 87 | ata_id_to_hd_driveid(id); |
---|
78 | 88 | |
---|
79 | | - if (copy_to_user((void __user *)arg, id, size)) |
---|
| 89 | + if (copy_to_user(argp, id, size)) |
---|
80 | 90 | rc = -EFAULT; |
---|
81 | 91 | |
---|
82 | 92 | kfree(id); |
---|
.. | .. |
---|
86 | 96 | |
---|
87 | 97 | static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg) |
---|
88 | 98 | { |
---|
89 | | - return put_user((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) |
---|
| 99 | + return put_user_long((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) |
---|
90 | 100 | << IDE_NICE_DSC_OVERLAP) | |
---|
91 | 101 | (!!(drive->dev_flags & IDE_DFLAG_NICE1) |
---|
92 | | - << IDE_NICE_1), (long __user *)arg); |
---|
| 102 | + << IDE_NICE_1), arg); |
---|
93 | 103 | } |
---|
94 | 104 | |
---|
95 | 105 | static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) |
---|
.. | .. |
---|
114 | 124 | return 0; |
---|
115 | 125 | } |
---|
116 | 126 | |
---|
117 | | -static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg) |
---|
| 127 | +static int ide_cmd_ioctl(ide_drive_t *drive, void __user *argp) |
---|
118 | 128 | { |
---|
119 | 129 | u8 *buf = NULL; |
---|
120 | 130 | int bufsize = 0, err = 0; |
---|
.. | .. |
---|
122 | 132 | struct ide_cmd cmd; |
---|
123 | 133 | struct ide_taskfile *tf = &cmd.tf; |
---|
124 | 134 | |
---|
125 | | - if (NULL == (void *) arg) { |
---|
| 135 | + if (NULL == argp) { |
---|
126 | 136 | struct request *rq; |
---|
127 | 137 | |
---|
128 | 138 | rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, 0); |
---|
.. | .. |
---|
134 | 144 | return err; |
---|
135 | 145 | } |
---|
136 | 146 | |
---|
137 | | - if (copy_from_user(args, (void __user *)arg, 4)) |
---|
| 147 | + if (copy_from_user(args, argp, 4)) |
---|
138 | 148 | return -EFAULT; |
---|
139 | 149 | |
---|
140 | 150 | memset(&cmd, 0, sizeof(cmd)); |
---|
.. | .. |
---|
180 | 190 | args[1] = tf->error; |
---|
181 | 191 | args[2] = tf->nsect; |
---|
182 | 192 | abort: |
---|
183 | | - if (copy_to_user((void __user *)arg, &args, 4)) |
---|
| 193 | + if (copy_to_user(argp, &args, 4)) |
---|
184 | 194 | err = -EFAULT; |
---|
185 | 195 | if (buf) { |
---|
186 | | - if (copy_to_user((void __user *)(arg + 4), buf, bufsize)) |
---|
| 196 | + if (copy_to_user((argp + 4), buf, bufsize)) |
---|
187 | 197 | err = -EFAULT; |
---|
188 | 198 | kfree(buf); |
---|
189 | 199 | } |
---|
190 | 200 | return err; |
---|
191 | 201 | } |
---|
192 | 202 | |
---|
193 | | -static int ide_task_ioctl(ide_drive_t *drive, unsigned long arg) |
---|
| 203 | +static int ide_task_ioctl(ide_drive_t *drive, void __user *p) |
---|
194 | 204 | { |
---|
195 | | - void __user *p = (void __user *)arg; |
---|
196 | 205 | int err = 0; |
---|
197 | 206 | u8 args[7]; |
---|
198 | 207 | struct ide_cmd cmd; |
---|
.. | .. |
---|
236 | 245 | unsigned int cmd, unsigned long arg) |
---|
237 | 246 | { |
---|
238 | 247 | int err; |
---|
| 248 | + void __user *argp = (void __user *)arg; |
---|
| 249 | + |
---|
| 250 | + if (in_compat_syscall()) |
---|
| 251 | + argp = compat_ptr(arg); |
---|
239 | 252 | |
---|
240 | 253 | err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings); |
---|
241 | 254 | if (err != -EOPNOTSUPP) |
---|
.. | .. |
---|
244 | 257 | switch (cmd) { |
---|
245 | 258 | case HDIO_OBSOLETE_IDENTITY: |
---|
246 | 259 | case HDIO_GET_IDENTITY: |
---|
247 | | - if (bdev != bdev->bd_contains) |
---|
| 260 | + if (bdev_is_partition(bdev)) |
---|
248 | 261 | return -EINVAL; |
---|
249 | | - return ide_get_identity_ioctl(drive, cmd, arg); |
---|
| 262 | + return ide_get_identity_ioctl(drive, cmd, argp); |
---|
250 | 263 | case HDIO_GET_NICE: |
---|
251 | 264 | return ide_get_nice_ioctl(drive, arg); |
---|
252 | 265 | case HDIO_SET_NICE: |
---|
.. | .. |
---|
257 | 270 | case HDIO_DRIVE_TASKFILE: |
---|
258 | 271 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) |
---|
259 | 272 | return -EACCES; |
---|
| 273 | + /* missing compat handler for HDIO_DRIVE_TASKFILE */ |
---|
| 274 | + if (in_compat_syscall()) |
---|
| 275 | + return -ENOTTY; |
---|
260 | 276 | if (drive->media == ide_disk) |
---|
261 | 277 | return ide_taskfile_ioctl(drive, arg); |
---|
262 | 278 | return -ENOMSG; |
---|
.. | .. |
---|
264 | 280 | case HDIO_DRIVE_CMD: |
---|
265 | 281 | if (!capable(CAP_SYS_RAWIO)) |
---|
266 | 282 | return -EACCES; |
---|
267 | | - return ide_cmd_ioctl(drive, arg); |
---|
| 283 | + return ide_cmd_ioctl(drive, argp); |
---|
268 | 284 | case HDIO_DRIVE_TASK: |
---|
269 | 285 | if (!capable(CAP_SYS_RAWIO)) |
---|
270 | 286 | return -EACCES; |
---|
271 | | - return ide_task_ioctl(drive, arg); |
---|
| 287 | + return ide_task_ioctl(drive, argp); |
---|
272 | 288 | case HDIO_DRIVE_RESET: |
---|
273 | 289 | if (!capable(CAP_SYS_ADMIN)) |
---|
274 | 290 | return -EACCES; |
---|
.. | .. |
---|
276 | 292 | case HDIO_GET_BUSSTATE: |
---|
277 | 293 | if (!capable(CAP_SYS_ADMIN)) |
---|
278 | 294 | return -EACCES; |
---|
279 | | - if (put_user(BUSSTATE_ON, (long __user *)arg)) |
---|
| 295 | + if (put_user_long(BUSSTATE_ON, arg)) |
---|
280 | 296 | return -EFAULT; |
---|
281 | 297 | return 0; |
---|
282 | 298 | case HDIO_SET_BUSSTATE: |
---|