Messages in this thread Patch in this message |  | | From | Andreas Schwab <> | Date | Fri, 22 Nov 96 11:33:45 +0100 | Subject | Big security hole in 2.1.10+ |
| |
Since 2.1.10 the kernel contains a security hole as big as the universe, making it possible for everyone to overwrite arbitrary kernel memory! This patch reverts most of the change done to sr_ioctl.c in 2.1.10.
--- drivers/scsi/sr_ioctl.c.~1~ Tue Nov 19 19:56:27 1996 +++ drivers/scsi/sr_ioctl.c Mon Nov 18 23:29:32 1996 @@ -246,17 +246,22 @@ case CDROMPLAYMSF: { - struct cdrom_msf* msf = (struct cdrom_msf*)arg; + struct cdrom_msf msf; + + if (copy_from_user(&msf, (void *) arg, sizeof(msf))) { + result = -EFAULT; + break; + } sr_cmd[0] = SCMD_PLAYAUDIO_MSF; sr_cmd[1] = scsi_CDs[target].device->lun << 5; sr_cmd[2] = 0; - sr_cmd[3] = msf->cdmsf_min0; - sr_cmd[4] = msf->cdmsf_sec0; - sr_cmd[5] = msf->cdmsf_frame0; - sr_cmd[6] = msf->cdmsf_min1; - sr_cmd[7] = msf->cdmsf_sec1; - sr_cmd[8] = msf->cdmsf_frame1; + sr_cmd[3] = msf.cdmsf_min0; + sr_cmd[4] = msf.cdmsf_sec0; + sr_cmd[5] = msf.cdmsf_frame0; + sr_cmd[6] = msf.cdmsf_min1; + sr_cmd[7] = msf.cdmsf_sec1; + sr_cmd[8] = msf.cdmsf_frame1; sr_cmd[9] = 0; result = sr_do_ioctl(target, sr_cmd, NULL, 255); @@ -265,17 +270,22 @@ case CDROMPLAYBLK: { - struct cdrom_blk* blk = (struct cdrom_blk*)arg; + struct cdrom_blk blk; + + if (copy_from_user(&blk, (void *) arg, sizeof(blk))) { + result = -EFAULT; + break; + } sr_cmd[0] = SCMD_PLAYAUDIO10; sr_cmd[1] = scsi_CDs[target].device->lun << 5; - sr_cmd[2] = blk->from >> 24; - sr_cmd[3] = blk->from >> 16; - sr_cmd[4] = blk->from >> 8; - sr_cmd[5] = blk->from; + sr_cmd[2] = blk.from >> 24; + sr_cmd[3] = blk.from >> 16; + sr_cmd[4] = blk.from >> 8; + sr_cmd[5] = blk.from; sr_cmd[6] = 0; - sr_cmd[7] = blk->len >> 8; - sr_cmd[8] = blk->len; + sr_cmd[7] = blk.len >> 8; + sr_cmd[8] = blk.len; sr_cmd[9] = 0; result = sr_do_ioctl(target, sr_cmd, NULL, 255); @@ -284,17 +294,22 @@ case CDROMPLAYTRKIND: { - struct cdrom_ti* ti = (struct cdrom_ti*)arg; + struct cdrom_ti ti; + + if (copy_from_user(&ti, (void *) arg, sizeof(ti))) { + result = -EFAULT; + break; + } sr_cmd[0] = SCMD_PLAYAUDIO_TI; sr_cmd[1] = scsi_CDs[target].device->lun << 5; sr_cmd[2] = 0; sr_cmd[3] = 0; - sr_cmd[4] = ti->cdti_trk0; - sr_cmd[5] = ti->cdti_ind0; + sr_cmd[4] = ti.cdti_trk0; + sr_cmd[5] = ti.cdti_ind0; sr_cmd[6] = 0; - sr_cmd[7] = ti->cdti_trk1; - sr_cmd[8] = ti->cdti_ind1; + sr_cmd[7] = ti.cdti_trk1; + sr_cmd[8] = ti.cdti_ind1; sr_cmd[9] = 0; result = sr_do_ioctl(target, sr_cmd, NULL, 255); @@ -303,7 +318,7 @@ case CDROMREADTOCHDR: { - struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg; + struct cdrom_tochdr tochdr; char * buffer; sr_cmd[0] = SCMD_READ_TOC; @@ -319,23 +334,31 @@ result = sr_do_ioctl(target, sr_cmd, buffer, 12); - tochdr->cdth_trk0 = buffer[2]; - tochdr->cdth_trk1 = buffer[3]; + tochdr.cdth_trk0 = buffer[2]; + tochdr.cdth_trk1 = buffer[3]; scsi_free(buffer, 512); + + if (copy_to_user ((void *) arg, &tochdr, sizeof (struct cdrom_tochdr))) + result = -EFAULT; break; } case CDROMREADTOCENTRY: { - struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg; + struct cdrom_tocentry tocentry; unsigned char * buffer; + if (copy_from_user (&tocentry, (void *) arg, sizeof (struct cdrom_tocentry))) { + result = -EFAULT; + break; + } + sr_cmd[0] = SCMD_READ_TOC; sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | - (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0); + (tocentry.cdte_format == CDROM_MSF ? 0x02 : 0); sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; - sr_cmd[6] = tocentry->cdte_track; + sr_cmd[6] = tocentry.cdte_track; sr_cmd[7] = 0; /* MSB of length (12) */ sr_cmd[8] = 12; /* LSB of length */ sr_cmd[9] = 0; @@ -345,18 +368,21 @@ result = sr_do_ioctl (target, sr_cmd, buffer, 12); - tocentry->cdte_ctrl = buffer[5] & 0xf; - tocentry->cdte_adr = buffer[5] >> 4; - tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0; - if (tocentry->cdte_format == CDROM_MSF) { - tocentry->cdte_addr.msf.minute = buffer[9]; - tocentry->cdte_addr.msf.second = buffer[10]; - tocentry->cdte_addr.msf.frame = buffer[11]; + tocentry.cdte_ctrl = buffer[5] & 0xf; + tocentry.cdte_adr = buffer[5] >> 4; + tocentry.cdte_datamode = (tocentry.cdte_ctrl & 0x04) ? 1 : 0; + if (tocentry.cdte_format == CDROM_MSF) { + tocentry.cdte_addr.msf.minute = buffer[9]; + tocentry.cdte_addr.msf.second = buffer[10]; + tocentry.cdte_addr.msf.frame = buffer[11]; } else - tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8) + tocentry.cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8) + buffer[10]) << 8) + buffer[11]; scsi_free(buffer, 512); + + if (copy_to_user ((void *) arg, &tocentry, sizeof (struct cdrom_tocentry))) + result = -EFAULT; break; } @@ -381,8 +407,13 @@ case CDROMVOLCTRL: { char * buffer, * mask; - struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg; + struct cdrom_volctrl volctrl; + if (copy_from_user (&volctrl, (void *) arg, sizeof (struct cdrom_volctrl))) { + result = -EFAULT; + break; + } + /* First we get the current params so we can just twiddle the volume */ sr_cmd[0] = MODE_SENSE; @@ -425,10 +456,10 @@ /* Now mask and substitute our own volume and reuse the rest */ buffer[0] = 0; /* Clear reserved field */ - buffer[21] = volctrl->channel0 & mask[21]; - buffer[23] = volctrl->channel1 & mask[23]; - buffer[25] = volctrl->channel2 & mask[25]; - buffer[27] = volctrl->channel3 & mask[27]; + buffer[21] = volctrl.channel0 & mask[21]; + buffer[23] = volctrl.channel1 & mask[23]; + buffer[25] = volctrl.channel2 & mask[25]; + buffer[27] = volctrl.channel3 & mask[27]; sr_cmd[0] = MODE_SELECT; sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 0x10; /* Params are SCSI-2 */ @@ -445,7 +476,7 @@ case CDROMVOLREAD: { char * buffer; - struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg; + struct cdrom_volctrl volctrl; /* Get the current params */ @@ -465,18 +496,21 @@ break; } - volctrl->channel0 = buffer[21]; - volctrl->channel1 = buffer[23]; - volctrl->channel2 = buffer[25]; - volctrl->channel3 = buffer[27]; + volctrl.channel0 = buffer[21]; + volctrl.channel1 = buffer[23]; + volctrl.channel2 = buffer[25]; + volctrl.channel3 = buffer[27]; scsi_free(buffer, 512); + + if (copy_to_user ((void *) arg, &volctrl, sizeof (struct cdrom_volctrl))) + result = -EFAULT; break; } case CDROMSUBCHNL: { - struct cdrom_subchnl* subchnl = (struct cdrom_subchnl*)arg; + struct cdrom_subchnl subchnl; char * buffer; sr_cmd[0] = SCMD_READ_SUBCHANNEL; @@ -494,20 +528,23 @@ result = sr_do_ioctl(target, sr_cmd, buffer, 16); - subchnl->cdsc_audiostatus = buffer[1]; - subchnl->cdsc_format = CDROM_MSF; - subchnl->cdsc_ctrl = buffer[5] & 0xf; - subchnl->cdsc_trk = buffer[6]; - subchnl->cdsc_ind = buffer[7]; - - subchnl->cdsc_reladdr.msf.minute = buffer[13]; - subchnl->cdsc_reladdr.msf.second = buffer[14]; - subchnl->cdsc_reladdr.msf.frame = buffer[15]; - subchnl->cdsc_absaddr.msf.minute = buffer[9]; - subchnl->cdsc_absaddr.msf.second = buffer[10]; - subchnl->cdsc_absaddr.msf.frame = buffer[11]; + subchnl.cdsc_audiostatus = buffer[1]; + subchnl.cdsc_format = CDROM_MSF; + subchnl.cdsc_ctrl = buffer[5] & 0xf; + subchnl.cdsc_trk = buffer[6]; + subchnl.cdsc_ind = buffer[7]; + + subchnl.cdsc_reladdr.msf.minute = buffer[13]; + subchnl.cdsc_reladdr.msf.second = buffer[14]; + subchnl.cdsc_reladdr.msf.frame = buffer[15]; + subchnl.cdsc_absaddr.msf.minute = buffer[9]; + subchnl.cdsc_absaddr.msf.second = buffer[10]; + subchnl.cdsc_absaddr.msf.frame = buffer[11]; scsi_free(buffer, 512); + + if (copy_to_user ((void *) arg, &subchnl, sizeof (struct cdrom_subchnl))) + result = -EFAULT; break; } default: -- Andreas Schwab "And now for something schwab@issan.informatik.uni-dortmund.de completely different"
|  |