1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * compat ioctls for control API 4 * 5 * Copyright (c) by Takashi Iwai <tiwai@suse.de> 6 */ 7 8 /* this file included from control.c */ 9 10 #include <linux/compat.h> 11 #include <linux/slab.h> 12 13 struct snd_ctl_elem_list32 { 14 u32 offset; 15 u32 space; 16 u32 used; 17 u32 count; 18 u32 pids; 19 unsigned char reserved[50]; 20 } /* don't set packed attribute here */; 21 22 static int snd_ctl_elem_list_compat(struct snd_card *card, 23 struct snd_ctl_elem_list32 __user *data32) 24 { 25 struct snd_ctl_elem_list __user *data; 26 compat_caddr_t ptr; 27 int err; 28 29 data = compat_alloc_user_space(sizeof(*data)); 30 31 /* offset, space, used, count */ 32 if (copy_in_user(data, data32, 4 * sizeof(u32))) 33 return -EFAULT; 34 /* pids */ 35 if (get_user(ptr, &data32->pids) || 36 put_user(compat_ptr(ptr), &data->pids)) 37 return -EFAULT; 38 err = snd_ctl_elem_list(card, data); 39 if (err < 0) 40 return err; 41 /* copy the result */ 42 if (copy_in_user(data32, data, 4 * sizeof(u32))) 43 return -EFAULT; 44 return 0; 45 } 46 47 /* 48 * control element info 49 * it uses union, so the things are not easy.. 50 */ 51 52 struct snd_ctl_elem_info32 { 53 struct snd_ctl_elem_id id; // the size of struct is same 54 s32 type; 55 u32 access; 56 u32 count; 57 s32 owner; 58 union { 59 struct { 60 s32 min; 61 s32 max; 62 s32 step; 63 } integer; 64 struct { 65 u64 min; 66 u64 max; 67 u64 step; 68 } integer64; 69 struct { 70 u32 items; 71 u32 item; 72 char name[64]; 73 u64 names_ptr; 74 u32 names_length; 75 } enumerated; 76 unsigned char reserved[128]; 77 } value; 78 unsigned char reserved[64]; 79 } __attribute__((packed)); 80 81 static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl, 82 struct snd_ctl_elem_info32 __user *data32) 83 { 84 struct snd_ctl_elem_info *data; 85 int err; 86 87 data = kzalloc(sizeof(*data), GFP_KERNEL); 88 if (! data) 89 return -ENOMEM; 90 91 err = -EFAULT; 92 /* copy id */ 93 if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) 94 goto error; 95 /* we need to copy the item index. 96 * hope this doesn't break anything.. 97 */ 98 if (get_user(data->value.enumerated.item, &data32->value.enumerated.item)) 99 goto error; 100 101 err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0); 102 if (err < 0) 103 goto error; 104 err = snd_ctl_elem_info(ctl, data); 105 if (err < 0) 106 goto error; 107 /* restore info to 32bit */ 108 err = -EFAULT; 109 /* id, type, access, count */ 110 if (copy_to_user(&data32->id, &data->id, sizeof(data->id)) || 111 copy_to_user(&data32->type, &data->type, 3 * sizeof(u32))) 112 goto error; 113 if (put_user(data->owner, &data32->owner)) 114 goto error; 115 switch (data->type) { 116 case SNDRV_CTL_ELEM_TYPE_BOOLEAN: 117 case SNDRV_CTL_ELEM_TYPE_INTEGER: 118 if (put_user(data->value.integer.min, &data32->value.integer.min) || 119 put_user(data->value.integer.max, &data32->value.integer.max) || 120 put_user(data->value.integer.step, &data32->value.integer.step)) 121 goto error; 122 break; 123 case SNDRV_CTL_ELEM_TYPE_INTEGER64: 124 if (copy_to_user(&data32->value.integer64, 125 &data->value.integer64, 126 sizeof(data->value.integer64))) 127 goto error; 128 break; 129 case SNDRV_CTL_ELEM_TYPE_ENUMERATED: 130 if (copy_to_user(&data32->value.enumerated, 131 &data->value.enumerated, 132 sizeof(data->value.enumerated))) 133 goto error; 134 break; 135 default: 136 break; 137 } 138 err = 0; 139 error: 140 kfree(data); 141 return err; 142 } 143 144 /* read / write */ 145 struct snd_ctl_elem_value32 { 146 struct snd_ctl_elem_id id; 147 unsigned int indirect; /* bit-field causes misalignment */ 148 union { 149 s32 integer[128]; 150 unsigned char data[512]; 151 #ifndef CONFIG_X86_64 152 s64 integer64[64]; 153 #endif 154 } value; 155 unsigned char reserved[128]; 156 }; 157 158 #ifdef CONFIG_X86_X32 159 /* x32 has a different alignment for 64bit values from ia32 */ 160 struct snd_ctl_elem_value_x32 { 161 struct snd_ctl_elem_id id; 162 unsigned int indirect; /* bit-field causes misalignment */ 163 union { 164 s32 integer[128]; 165 unsigned char data[512]; 166 s64 integer64[64]; 167 } value; 168 unsigned char reserved[128]; 169 }; 170 #endif /* CONFIG_X86_X32 */ 171 172 /* get the value type and count of the control */ 173 static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, 174 int *countp) 175 { 176 struct snd_kcontrol *kctl; 177 struct snd_ctl_elem_info *info; 178 int err; 179 180 down_read(&card->controls_rwsem); 181 kctl = snd_ctl_find_id(card, id); 182 if (! kctl) { 183 up_read(&card->controls_rwsem); 184 return -ENOENT; 185 } 186 info = kzalloc(sizeof(*info), GFP_KERNEL); 187 if (info == NULL) { 188 up_read(&card->controls_rwsem); 189 return -ENOMEM; 190 } 191 info->id = *id; 192 err = kctl->info(kctl, info); 193 up_read(&card->controls_rwsem); 194 if (err >= 0) { 195 err = info->type; 196 *countp = info->count; 197 } 198 kfree(info); 199 return err; 200 } 201 202 static int get_elem_size(int type, int count) 203 { 204 switch (type) { 205 case SNDRV_CTL_ELEM_TYPE_INTEGER64: 206 return sizeof(s64) * count; 207 case SNDRV_CTL_ELEM_TYPE_ENUMERATED: 208 return sizeof(int) * count; 209 case SNDRV_CTL_ELEM_TYPE_BYTES: 210 return 512; 211 case SNDRV_CTL_ELEM_TYPE_IEC958: 212 return sizeof(struct snd_aes_iec958); 213 default: 214 return -1; 215 } 216 } 217 218 static int copy_ctl_value_from_user(struct snd_card *card, 219 struct snd_ctl_elem_value *data, 220 void __user *userdata, 221 void __user *valuep, 222 int *typep, int *countp) 223 { 224 struct snd_ctl_elem_value32 __user *data32 = userdata; 225 int i, type, size; 226 int count; 227 unsigned int indirect; 228 229 if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) 230 return -EFAULT; 231 if (get_user(indirect, &data32->indirect)) 232 return -EFAULT; 233 if (indirect) 234 return -EINVAL; 235 type = get_ctl_type(card, &data->id, &count); 236 if (type < 0) 237 return type; 238 239 if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || 240 type == SNDRV_CTL_ELEM_TYPE_INTEGER) { 241 for (i = 0; i < count; i++) { 242 s32 __user *intp = valuep; 243 int val; 244 if (get_user(val, &intp[i])) 245 return -EFAULT; 246 data->value.integer.value[i] = val; 247 } 248 } else { 249 size = get_elem_size(type, count); 250 if (size < 0) { 251 dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); 252 return -EINVAL; 253 } 254 if (copy_from_user(data->value.bytes.data, valuep, size)) 255 return -EFAULT; 256 } 257 258 *typep = type; 259 *countp = count; 260 return 0; 261 } 262 263 /* restore the value to 32bit */ 264 static int copy_ctl_value_to_user(void __user *userdata, 265 void __user *valuep, 266 struct snd_ctl_elem_value *data, 267 int type, int count) 268 { 269 int i, size; 270 271 if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || 272 type == SNDRV_CTL_ELEM_TYPE_INTEGER) { 273 for (i = 0; i < count; i++) { 274 s32 __user *intp = valuep; 275 int val; 276 val = data->value.integer.value[i]; 277 if (put_user(val, &intp[i])) 278 return -EFAULT; 279 } 280 } else { 281 size = get_elem_size(type, count); 282 if (copy_to_user(valuep, data->value.bytes.data, size)) 283 return -EFAULT; 284 } 285 return 0; 286 } 287 288 static int ctl_elem_read_user(struct snd_card *card, 289 void __user *userdata, void __user *valuep) 290 { 291 struct snd_ctl_elem_value *data; 292 int err, type, count; 293 294 data = kzalloc(sizeof(*data), GFP_KERNEL); 295 if (data == NULL) 296 return -ENOMEM; 297 298 err = copy_ctl_value_from_user(card, data, userdata, valuep, 299 &type, &count); 300 if (err < 0) 301 goto error; 302 303 err = snd_power_wait(card, SNDRV_CTL_POWER_D0); 304 if (err < 0) 305 goto error; 306 err = snd_ctl_elem_read(card, data); 307 if (err < 0) 308 goto error; 309 err = copy_ctl_value_to_user(userdata, valuep, data, type, count); 310 error: 311 kfree(data); 312 return err; 313 } 314 315 static int ctl_elem_write_user(struct snd_ctl_file *file, 316 void __user *userdata, void __user *valuep) 317 { 318 struct snd_ctl_elem_value *data; 319 struct snd_card *card = file->card; 320 int err, type, count; 321 322 data = kzalloc(sizeof(*data), GFP_KERNEL); 323 if (data == NULL) 324 return -ENOMEM; 325 326 err = copy_ctl_value_from_user(card, data, userdata, valuep, 327 &type, &count); 328 if (err < 0) 329 goto error; 330 331 err = snd_power_wait(card, SNDRV_CTL_POWER_D0); 332 if (err < 0) 333 goto error; 334 err = snd_ctl_elem_write(card, file, data); 335 if (err < 0) 336 goto error; 337 err = copy_ctl_value_to_user(userdata, valuep, data, type, count); 338 error: 339 kfree(data); 340 return err; 341 } 342 343 static int snd_ctl_elem_read_user_compat(struct snd_card *card, 344 struct snd_ctl_elem_value32 __user *data32) 345 { 346 return ctl_elem_read_user(card, data32, &data32->value); 347 } 348 349 static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, 350 struct snd_ctl_elem_value32 __user *data32) 351 { 352 return ctl_elem_write_user(file, data32, &data32->value); 353 } 354 355 #ifdef CONFIG_X86_X32 356 static int snd_ctl_elem_read_user_x32(struct snd_card *card, 357 struct snd_ctl_elem_value_x32 __user *data32) 358 { 359 return ctl_elem_read_user(card, data32, &data32->value); 360 } 361 362 static int snd_ctl_elem_write_user_x32(struct snd_ctl_file *file, 363 struct snd_ctl_elem_value_x32 __user *data32) 364 { 365 return ctl_elem_write_user(file, data32, &data32->value); 366 } 367 #endif /* CONFIG_X86_X32 */ 368 369 /* add or replace a user control */ 370 static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, 371 struct snd_ctl_elem_info32 __user *data32, 372 int replace) 373 { 374 struct snd_ctl_elem_info *data; 375 int err; 376 377 data = kzalloc(sizeof(*data), GFP_KERNEL); 378 if (! data) 379 return -ENOMEM; 380 381 err = -EFAULT; 382 /* id, type, access, count */ \ 383 if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) || 384 copy_from_user(&data->type, &data32->type, 3 * sizeof(u32))) 385 goto error; 386 if (get_user(data->owner, &data32->owner)) 387 goto error; 388 switch (data->type) { 389 case SNDRV_CTL_ELEM_TYPE_BOOLEAN: 390 case SNDRV_CTL_ELEM_TYPE_INTEGER: 391 if (get_user(data->value.integer.min, &data32->value.integer.min) || 392 get_user(data->value.integer.max, &data32->value.integer.max) || 393 get_user(data->value.integer.step, &data32->value.integer.step)) 394 goto error; 395 break; 396 case SNDRV_CTL_ELEM_TYPE_INTEGER64: 397 if (copy_from_user(&data->value.integer64, 398 &data32->value.integer64, 399 sizeof(data->value.integer64))) 400 goto error; 401 break; 402 case SNDRV_CTL_ELEM_TYPE_ENUMERATED: 403 if (copy_from_user(&data->value.enumerated, 404 &data32->value.enumerated, 405 sizeof(data->value.enumerated))) 406 goto error; 407 data->value.enumerated.names_ptr = 408 (uintptr_t)compat_ptr(data->value.enumerated.names_ptr); 409 break; 410 default: 411 break; 412 } 413 err = snd_ctl_elem_add(file, data, replace); 414 error: 415 kfree(data); 416 return err; 417 } 418 419 enum { 420 SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct snd_ctl_elem_list32), 421 SNDRV_CTL_IOCTL_ELEM_INFO32 = _IOWR('U', 0x11, struct snd_ctl_elem_info32), 422 SNDRV_CTL_IOCTL_ELEM_READ32 = _IOWR('U', 0x12, struct snd_ctl_elem_value32), 423 SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32), 424 SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32), 425 SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32), 426 #ifdef CONFIG_X86_X32 427 SNDRV_CTL_IOCTL_ELEM_READ_X32 = _IOWR('U', 0x12, struct snd_ctl_elem_value_x32), 428 SNDRV_CTL_IOCTL_ELEM_WRITE_X32 = _IOWR('U', 0x13, struct snd_ctl_elem_value_x32), 429 #endif /* CONFIG_X86_X32 */ 430 }; 431 432 static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) 433 { 434 struct snd_ctl_file *ctl; 435 struct snd_kctl_ioctl *p; 436 void __user *argp = compat_ptr(arg); 437 int err; 438 439 ctl = file->private_data; 440 if (snd_BUG_ON(!ctl || !ctl->card)) 441 return -ENXIO; 442 443 switch (cmd) { 444 case SNDRV_CTL_IOCTL_PVERSION: 445 case SNDRV_CTL_IOCTL_CARD_INFO: 446 case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: 447 case SNDRV_CTL_IOCTL_POWER: 448 case SNDRV_CTL_IOCTL_POWER_STATE: 449 case SNDRV_CTL_IOCTL_ELEM_LOCK: 450 case SNDRV_CTL_IOCTL_ELEM_UNLOCK: 451 case SNDRV_CTL_IOCTL_ELEM_REMOVE: 452 case SNDRV_CTL_IOCTL_TLV_READ: 453 case SNDRV_CTL_IOCTL_TLV_WRITE: 454 case SNDRV_CTL_IOCTL_TLV_COMMAND: 455 return snd_ctl_ioctl(file, cmd, (unsigned long)argp); 456 case SNDRV_CTL_IOCTL_ELEM_LIST32: 457 return snd_ctl_elem_list_compat(ctl->card, argp); 458 case SNDRV_CTL_IOCTL_ELEM_INFO32: 459 return snd_ctl_elem_info_compat(ctl, argp); 460 case SNDRV_CTL_IOCTL_ELEM_READ32: 461 return snd_ctl_elem_read_user_compat(ctl->card, argp); 462 case SNDRV_CTL_IOCTL_ELEM_WRITE32: 463 return snd_ctl_elem_write_user_compat(ctl, argp); 464 case SNDRV_CTL_IOCTL_ELEM_ADD32: 465 return snd_ctl_elem_add_compat(ctl, argp, 0); 466 case SNDRV_CTL_IOCTL_ELEM_REPLACE32: 467 return snd_ctl_elem_add_compat(ctl, argp, 1); 468 #ifdef CONFIG_X86_X32 469 case SNDRV_CTL_IOCTL_ELEM_READ_X32: 470 return snd_ctl_elem_read_user_x32(ctl->card, argp); 471 case SNDRV_CTL_IOCTL_ELEM_WRITE_X32: 472 return snd_ctl_elem_write_user_x32(ctl, argp); 473 #endif /* CONFIG_X86_X32 */ 474 } 475 476 down_read(&snd_ioctl_rwsem); 477 list_for_each_entry(p, &snd_control_compat_ioctls, list) { 478 if (p->fioctl) { 479 err = p->fioctl(ctl->card, ctl, cmd, arg); 480 if (err != -ENOIOCTLCMD) { 481 up_read(&snd_ioctl_rwsem); 482 return err; 483 } 484 } 485 } 486 up_read(&snd_ioctl_rwsem); 487 return -ENOIOCTLCMD; 488 } 489