aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Young <hidave.darkstar@gmail.com>2007-06-19 03:14:26 -0400
committerJens Axboe <jens.axboe@oracle.com>2007-07-10 02:03:33 -0400
commit554988d6fe369719ae5b41255c577569ecf47c30 (patch)
treed7e14d962b6dfad90815a44ff3c9dcf97ad903e9
parent32eef964110985c5845472e07fa0a18838a970c4 (diff)
[PATCH] cdrom_sysctl_info fix
Fix the cdrom_sysctl_info possible buffer overwrite bug. Also fix the locking of accessing topCdromPtr pointer. Signed-off-by: Dave Young <hidave.darkstar@gmail.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r--drivers/cdrom/cdrom.c216
1 files changed, 125 insertions, 91 deletions
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 3625a05bc3d3..aa5468f487ba 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -302,7 +302,7 @@ module_param(lockdoor, bool, 0);
302module_param(check_media_type, bool, 0); 302module_param(check_media_type, bool, 0);
303module_param(mrw_format_restart, bool, 0); 303module_param(mrw_format_restart, bool, 0);
304 304
305static DEFINE_SPINLOCK(cdrom_lock); 305static DEFINE_MUTEX(cdrom_mutex);
306 306
307static const char *mrw_format_status[] = { 307static const char *mrw_format_status[] = {
308 "not mrw", 308 "not mrw",
@@ -438,10 +438,10 @@ int register_cdrom(struct cdrom_device_info *cdi)
438 cdo->generic_packet = cdrom_dummy_generic_packet; 438 cdo->generic_packet = cdrom_dummy_generic_packet;
439 439
440 cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name); 440 cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
441 spin_lock(&cdrom_lock); 441 mutex_lock(&cdrom_mutex);
442 cdi->next = topCdromPtr; 442 cdi->next = topCdromPtr;
443 topCdromPtr = cdi; 443 topCdromPtr = cdi;
444 spin_unlock(&cdrom_lock); 444 mutex_unlock(&cdrom_mutex);
445 return 0; 445 return 0;
446} 446}
447#undef ENSURE 447#undef ENSURE
@@ -452,7 +452,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
452 cdinfo(CD_OPEN, "entering unregister_cdrom\n"); 452 cdinfo(CD_OPEN, "entering unregister_cdrom\n");
453 453
454 prev = NULL; 454 prev = NULL;
455 spin_lock(&cdrom_lock); 455 mutex_lock(&cdrom_mutex);
456 cdi = topCdromPtr; 456 cdi = topCdromPtr;
457 while (cdi && cdi != unreg) { 457 while (cdi && cdi != unreg) {
458 prev = cdi; 458 prev = cdi;
@@ -460,7 +460,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
460 } 460 }
461 461
462 if (cdi == NULL) { 462 if (cdi == NULL) {
463 spin_unlock(&cdrom_lock); 463 mutex_unlock(&cdrom_mutex);
464 return -2; 464 return -2;
465 } 465 }
466 if (prev) 466 if (prev)
@@ -468,7 +468,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
468 else 468 else
469 topCdromPtr = cdi->next; 469 topCdromPtr = cdi->next;
470 470
471 spin_unlock(&cdrom_lock); 471 mutex_unlock(&cdrom_mutex);
472 472
473 if (cdi->exit) 473 if (cdi->exit)
474 cdi->exit(cdi); 474 cdi->exit(cdi);
@@ -3289,103 +3289,137 @@ static struct cdrom_sysctl_settings {
3289 int check; /* check media type */ 3289 int check; /* check media type */
3290} cdrom_sysctl_settings; 3290} cdrom_sysctl_settings;
3291 3291
3292enum cdrom_print_option {
3293 CTL_NAME,
3294 CTL_SPEED,
3295 CTL_SLOTS,
3296 CTL_CAPABILITY
3297};
3298
3299static int cdrom_print_info(const char *header, int val, char *info,
3300 int *pos, enum cdrom_print_option option)
3301{
3302 const int max_size = sizeof(cdrom_sysctl_settings.info);
3303 struct cdrom_device_info *cdi;
3304 int ret;
3305
3306 ret = scnprintf(info + *pos, max_size - *pos, header);
3307 if (!ret)
3308 return 1;
3309
3310 *pos += ret;
3311
3312 for (cdi = topCdromPtr; cdi; cdi = cdi->next) {
3313 switch (option) {
3314 case CTL_NAME:
3315 ret = scnprintf(info + *pos, max_size - *pos,
3316 "\t%s", cdi->name);
3317 break;
3318 case CTL_SPEED:
3319 ret = scnprintf(info + *pos, max_size - *pos,
3320 "\t%d", cdi->speed);
3321 break;
3322 case CTL_SLOTS:
3323 ret = scnprintf(info + *pos, max_size - *pos,
3324 "\t%d", cdi->capacity);
3325 break;
3326 case CTL_CAPABILITY:
3327 ret = scnprintf(info + *pos, max_size - *pos,
3328 "\t%d", CDROM_CAN(val) != 0);
3329 break;
3330 default:
3331 printk(KERN_INFO "cdrom: invalid option%d\n", option);
3332 return 1;
3333 }
3334 if (!ret)
3335 return 1;
3336 *pos += ret;
3337 }
3338
3339 return 0;
3340}
3341
3292static int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp, 3342static int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp,
3293 void __user *buffer, size_t *lenp, loff_t *ppos) 3343 void __user *buffer, size_t *lenp, loff_t *ppos)
3294{ 3344{
3295 int pos; 3345 int pos;
3296 struct cdrom_device_info *cdi;
3297 char *info = cdrom_sysctl_settings.info; 3346 char *info = cdrom_sysctl_settings.info;
3347 const int max_size = sizeof(cdrom_sysctl_settings.info);
3298 3348
3299 if (!*lenp || (*ppos && !write)) { 3349 if (!*lenp || (*ppos && !write)) {
3300 *lenp = 0; 3350 *lenp = 0;
3301 return 0; 3351 return 0;
3302 } 3352 }
3303 3353
3354 mutex_lock(&cdrom_mutex);
3355
3304 pos = sprintf(info, "CD-ROM information, " VERSION "\n"); 3356 pos = sprintf(info, "CD-ROM information, " VERSION "\n");
3305 3357
3306 pos += sprintf(info+pos, "\ndrive name:\t"); 3358 if (cdrom_print_info("\ndrive name:\t", 0, info, &pos, CTL_NAME))
3307 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3359 goto done;
3308 pos += sprintf(info+pos, "\t%s", cdi->name); 3360 if (cdrom_print_info("\ndrive speed:\t", 0, info, &pos, CTL_SPEED))
3309 3361 goto done;
3310 pos += sprintf(info+pos, "\ndrive speed:\t"); 3362 if (cdrom_print_info("\ndrive # of slots:", 0, info, &pos, CTL_SLOTS))
3311 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3363 goto done;
3312 pos += sprintf(info+pos, "\t%d", cdi->speed); 3364 if (cdrom_print_info("\nCan close tray:\t",
3313 3365 CDC_CLOSE_TRAY, info, &pos, CTL_CAPABILITY))
3314 pos += sprintf(info+pos, "\ndrive # of slots:"); 3366 goto done;
3315 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3367 if (cdrom_print_info("\nCan open tray:\t",
3316 pos += sprintf(info+pos, "\t%d", cdi->capacity); 3368 CDC_OPEN_TRAY, info, &pos, CTL_CAPABILITY))
3317 3369 goto done;
3318 pos += sprintf(info+pos, "\nCan close tray:\t"); 3370 if (cdrom_print_info("\nCan lock tray:\t",
3319 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3371 CDC_LOCK, info, &pos, CTL_CAPABILITY))
3320 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CLOSE_TRAY) != 0); 3372 goto done;
3321 3373 if (cdrom_print_info("\nCan change speed:",
3322 pos += sprintf(info+pos, "\nCan open tray:\t"); 3374 CDC_SELECT_SPEED, info, &pos, CTL_CAPABILITY))
3323 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3375 goto done;
3324 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_OPEN_TRAY) != 0); 3376 if (cdrom_print_info("\nCan select disk:",
3325 3377 CDC_SELECT_DISC, info, &pos, CTL_CAPABILITY))
3326 pos += sprintf(info+pos, "\nCan lock tray:\t"); 3378 goto done;
3327 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3379 if (cdrom_print_info("\nCan read multisession:",
3328 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_LOCK) != 0); 3380 CDC_MULTI_SESSION, info, &pos, CTL_CAPABILITY))
3329 3381 goto done;
3330 pos += sprintf(info+pos, "\nCan change speed:"); 3382 if (cdrom_print_info("\nCan read MCN:\t",
3331 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3383 CDC_MCN, info, &pos, CTL_CAPABILITY))
3332 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_SPEED) != 0); 3384 goto done;
3333 3385 if (cdrom_print_info("\nReports media changed:",
3334 pos += sprintf(info+pos, "\nCan select disk:"); 3386 CDC_MEDIA_CHANGED, info, &pos, CTL_CAPABILITY))
3335 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3387 goto done;
3336 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_DISC) != 0); 3388 if (cdrom_print_info("\nCan play audio:\t",
3337 3389 CDC_PLAY_AUDIO, info, &pos, CTL_CAPABILITY))
3338 pos += sprintf(info+pos, "\nCan read multisession:"); 3390 goto done;
3339 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3391 if (cdrom_print_info("\nCan write CD-R:\t",
3340 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MULTI_SESSION) != 0); 3392 CDC_CD_R, info, &pos, CTL_CAPABILITY))
3341 3393 goto done;
3342 pos += sprintf(info+pos, "\nCan read MCN:\t"); 3394 if (cdrom_print_info("\nCan write CD-RW:",
3343 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3395 CDC_CD_RW, info, &pos, CTL_CAPABILITY))
3344 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MCN) != 0); 3396 goto done;
3345 3397 if (cdrom_print_info("\nCan read DVD:\t",
3346 pos += sprintf(info+pos, "\nReports media changed:"); 3398 CDC_DVD, info, &pos, CTL_CAPABILITY))
3347 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3399 goto done;
3348 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MEDIA_CHANGED) != 0); 3400 if (cdrom_print_info("\nCan write DVD-R:",
3349 3401 CDC_DVD_R, info, &pos, CTL_CAPABILITY))
3350 pos += sprintf(info+pos, "\nCan play audio:\t"); 3402 goto done;
3351 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3403 if (cdrom_print_info("\nCan write DVD-RAM:",
3352 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_PLAY_AUDIO) != 0); 3404 CDC_DVD_RAM, info, &pos, CTL_CAPABILITY))
3353 3405 goto done;
3354 pos += sprintf(info+pos, "\nCan write CD-R:\t"); 3406 if (cdrom_print_info("\nCan read MRW:\t",
3355 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3407 CDC_MRW, info, &pos, CTL_CAPABILITY))
3356 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_R) != 0); 3408 goto done;
3357 3409 if (cdrom_print_info("\nCan write MRW:\t",
3358 pos += sprintf(info+pos, "\nCan write CD-RW:"); 3410 CDC_MRW_W, info, &pos, CTL_CAPABILITY))
3359 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3411 goto done;
3360 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_RW) != 0); 3412 if (cdrom_print_info("\nCan write RAM:\t",
3361 3413 CDC_RAM, info, &pos, CTL_CAPABILITY))
3362 pos += sprintf(info+pos, "\nCan read DVD:\t"); 3414 goto done;
3363 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3415 if (!scnprintf(info + pos, max_size - pos, "\n\n"))
3364 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD) != 0); 3416 goto done;
3365 3417doit:
3366 pos += sprintf(info+pos, "\nCan write DVD-R:"); 3418 mutex_unlock(&cdrom_mutex);
3367 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) 3419 return proc_dostring(ctl, write, filp, buffer, lenp, ppos);
3368 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_R) != 0); 3420done:
3369 3421 printk(KERN_INFO "cdrom: info buffer too small\n");
3370 pos += sprintf(info+pos, "\nCan write DVD-RAM:"); 3422 goto doit;
3371 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
3372 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0);
3373
3374 pos += sprintf(info+pos, "\nCan read MRW:\t");
3375 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
3376 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW) != 0);
3377
3378 pos += sprintf(info+pos, "\nCan write MRW:\t");
3379 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
3380 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW_W) != 0);
3381
3382 pos += sprintf(info+pos, "\nCan write RAM:\t");
3383 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
3384 pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_RAM) != 0);
3385
3386 strcpy(info+pos,"\n\n");
3387
3388 return proc_dostring(ctl, write, filp, buffer, lenp, ppos);
3389} 3423}
3390 3424
3391/* Unfortunately, per device settings are not implemented through 3425/* Unfortunately, per device settings are not implemented through