Commit 22a9189f authored by Thomas Bogendoerfer's avatar Thomas Bogendoerfer Committed by Jens Axboe

cdrom: use kmalloced buffers instead of buffers on stack

If cdrom commands are issued to a scsi drive in most cases the buffer will be
filled via dma.  This leads to bad stack corruption on non coherent platforms,
because the buffers are neither cache line aligned nor is the size a multiple
of the cache line size.  Using kmalloced buffers avoids this.
Signed-off-by: default avatarThomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 0a0c4114
...@@ -461,27 +461,37 @@ int cdrom_get_media_event(struct cdrom_device_info *cdi, ...@@ -461,27 +461,37 @@ int cdrom_get_media_event(struct cdrom_device_info *cdi,
struct media_event_desc *med) struct media_event_desc *med)
{ {
struct packet_command cgc; struct packet_command cgc;
unsigned char buffer[8]; unsigned char *buffer;
struct event_header *eh = (struct event_header *) buffer; struct event_header *eh;
int ret = 1;
buffer = kmalloc(8, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); eh = (struct event_header *)buffer;
init_cdrom_command(&cgc, buffer, 8, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION; cgc.cmd[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION;
cgc.cmd[1] = 1; /* IMMED */ cgc.cmd[1] = 1; /* IMMED */
cgc.cmd[4] = 1 << 4; /* media event */ cgc.cmd[4] = 1 << 4; /* media event */
cgc.cmd[8] = sizeof(buffer); cgc.cmd[8] = 8;
cgc.quiet = 1; cgc.quiet = 1;
if (cdi->ops->generic_packet(cdi, &cgc)) if (cdi->ops->generic_packet(cdi, &cgc))
return 1; goto err;
if (be16_to_cpu(eh->data_len) < sizeof(*med)) if (be16_to_cpu(eh->data_len) < sizeof(*med))
return 1; goto err;
if (eh->nea || eh->notification_class != 0x4) if (eh->nea || eh->notification_class != 0x4)
return 1; goto err;
memcpy(med, &buffer[sizeof(*eh)], sizeof(*med)); memcpy(med, buffer + sizeof(*eh), sizeof(*med));
return 0; ret = 0;
err:
kfree(buffer);
return ret;
} }
/* /*
...@@ -491,68 +501,82 @@ int cdrom_get_media_event(struct cdrom_device_info *cdi, ...@@ -491,68 +501,82 @@ int cdrom_get_media_event(struct cdrom_device_info *cdi,
static int cdrom_mrw_probe_pc(struct cdrom_device_info *cdi) static int cdrom_mrw_probe_pc(struct cdrom_device_info *cdi)
{ {
struct packet_command cgc; struct packet_command cgc;
char buffer[16]; char *buffer;
int ret = 1;
buffer = kmalloc(16, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
cgc.timeout = HZ; cgc.timeout = HZ;
cgc.quiet = 1; cgc.quiet = 1;
if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC, 0)) { if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC, 0)) {
cdi->mrw_mode_page = MRW_MODE_PC; cdi->mrw_mode_page = MRW_MODE_PC;
return 0; ret = 0;
} else if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC_PRE1, 0)) { } else if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC_PRE1, 0)) {
cdi->mrw_mode_page = MRW_MODE_PC_PRE1; cdi->mrw_mode_page = MRW_MODE_PC_PRE1;
return 0; ret = 0;
} }
kfree(buffer);
return 1; return ret;
} }
static int cdrom_is_mrw(struct cdrom_device_info *cdi, int *write) static int cdrom_is_mrw(struct cdrom_device_info *cdi, int *write)
{ {
struct packet_command cgc; struct packet_command cgc;
struct mrw_feature_desc *mfd; struct mrw_feature_desc *mfd;
unsigned char buffer[16]; unsigned char *buffer;
int ret; int ret;
*write = 0; *write = 0;
buffer = kmalloc(16, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_GET_CONFIGURATION; cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
cgc.cmd[3] = CDF_MRW; cgc.cmd[3] = CDF_MRW;
cgc.cmd[8] = sizeof(buffer); cgc.cmd[8] = 16;
cgc.quiet = 1; cgc.quiet = 1;
if ((ret = cdi->ops->generic_packet(cdi, &cgc))) if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
return ret; goto err;
mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)]; mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)];
if (be16_to_cpu(mfd->feature_code) != CDF_MRW) if (be16_to_cpu(mfd->feature_code) != CDF_MRW) {
return 1; ret = 1;
goto err;
}
*write = mfd->write; *write = mfd->write;
if ((ret = cdrom_mrw_probe_pc(cdi))) { if ((ret = cdrom_mrw_probe_pc(cdi))) {
*write = 0; *write = 0;
return ret;
} }
err:
return 0; kfree(buffer);
return ret;
} }
static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont) static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont)
{ {
struct packet_command cgc; struct packet_command cgc;
unsigned char buffer[12]; unsigned char *buffer;
int ret; int ret;
printk(KERN_INFO "cdrom: %sstarting format\n", cont ? "Re" : ""); printk(KERN_INFO "cdrom: %sstarting format\n", cont ? "Re" : "");
buffer = kmalloc(12, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
/* /*
* FmtData bit set (bit 4), format type is 1 * FmtData bit set (bit 4), format type is 1
*/ */
init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_WRITE); init_cdrom_command(&cgc, buffer, 12, CGC_DATA_WRITE);
cgc.cmd[0] = GPCMD_FORMAT_UNIT; cgc.cmd[0] = GPCMD_FORMAT_UNIT;
cgc.cmd[1] = (1 << 4) | 1; cgc.cmd[1] = (1 << 4) | 1;
...@@ -579,6 +603,7 @@ static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont) ...@@ -579,6 +603,7 @@ static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont)
if (ret) if (ret)
printk(KERN_INFO "cdrom: bgformat failed\n"); printk(KERN_INFO "cdrom: bgformat failed\n");
kfree(buffer);
return ret; return ret;
} }
...@@ -638,16 +663,17 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space) ...@@ -638,16 +663,17 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
{ {
struct packet_command cgc; struct packet_command cgc;
struct mode_page_header *mph; struct mode_page_header *mph;
char buffer[16]; char *buffer;
int ret, offset, size; int ret, offset, size;
init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); buffer = kmalloc(16, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
cgc.buffer = buffer; init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
cgc.buflen = sizeof(buffer);
if ((ret = cdrom_mode_sense(cdi, &cgc, cdi->mrw_mode_page, 0))) if ((ret = cdrom_mode_sense(cdi, &cgc, cdi->mrw_mode_page, 0)))
return ret; goto err;
mph = (struct mode_page_header *) buffer; mph = (struct mode_page_header *) buffer;
offset = be16_to_cpu(mph->desc_length); offset = be16_to_cpu(mph->desc_length);
...@@ -657,55 +683,70 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space) ...@@ -657,55 +683,70 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
cgc.buflen = size; cgc.buflen = size;
if ((ret = cdrom_mode_select(cdi, &cgc))) if ((ret = cdrom_mode_select(cdi, &cgc)))
return ret; goto err;
printk(KERN_INFO "cdrom: %s: mrw address space %s selected\n", cdi->name, mrw_address_space[space]); printk(KERN_INFO "cdrom: %s: mrw address space %s selected\n", cdi->name, mrw_address_space[space]);
return 0; ret = 0;
err:
kfree(buffer);
return ret;
} }
static int cdrom_get_random_writable(struct cdrom_device_info *cdi, static int cdrom_get_random_writable(struct cdrom_device_info *cdi,
struct rwrt_feature_desc *rfd) struct rwrt_feature_desc *rfd)
{ {
struct packet_command cgc; struct packet_command cgc;
char buffer[24]; char *buffer;
int ret; int ret;
init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); buffer = kmalloc(24, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
init_cdrom_command(&cgc, buffer, 24, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_GET_CONFIGURATION; /* often 0x46 */ cgc.cmd[0] = GPCMD_GET_CONFIGURATION; /* often 0x46 */
cgc.cmd[3] = CDF_RWRT; /* often 0x0020 */ cgc.cmd[3] = CDF_RWRT; /* often 0x0020 */
cgc.cmd[8] = sizeof(buffer); /* often 0x18 */ cgc.cmd[8] = 24; /* often 0x18 */
cgc.quiet = 1; cgc.quiet = 1;
if ((ret = cdi->ops->generic_packet(cdi, &cgc))) if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
return ret; goto err;
memcpy(rfd, &buffer[sizeof(struct feature_header)], sizeof (*rfd)); memcpy(rfd, &buffer[sizeof(struct feature_header)], sizeof (*rfd));
return 0; ret = 0;
err:
kfree(buffer);
return ret;
} }
static int cdrom_has_defect_mgt(struct cdrom_device_info *cdi) static int cdrom_has_defect_mgt(struct cdrom_device_info *cdi)
{ {
struct packet_command cgc; struct packet_command cgc;
char buffer[16]; char *buffer;
__be16 *feature_code; __be16 *feature_code;
int ret; int ret;
init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); buffer = kmalloc(16, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_GET_CONFIGURATION; cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
cgc.cmd[3] = CDF_HWDM; cgc.cmd[3] = CDF_HWDM;
cgc.cmd[8] = sizeof(buffer); cgc.cmd[8] = 16;
cgc.quiet = 1; cgc.quiet = 1;
if ((ret = cdi->ops->generic_packet(cdi, &cgc))) if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
return ret; goto err;
feature_code = (__be16 *) &buffer[sizeof(struct feature_header)]; feature_code = (__be16 *) &buffer[sizeof(struct feature_header)];
if (be16_to_cpu(*feature_code) == CDF_HWDM) if (be16_to_cpu(*feature_code) == CDF_HWDM)
return 0; ret = 0;
err:
return 1; kfree(buffer);
return ret;
} }
...@@ -796,10 +837,14 @@ static int cdrom_mrw_open_write(struct cdrom_device_info *cdi) ...@@ -796,10 +837,14 @@ static int cdrom_mrw_open_write(struct cdrom_device_info *cdi)
static int mo_open_write(struct cdrom_device_info *cdi) static int mo_open_write(struct cdrom_device_info *cdi)
{ {
struct packet_command cgc; struct packet_command cgc;
char buffer[255]; char *buffer;
int ret; int ret;
init_cdrom_command(&cgc, &buffer, 4, CGC_DATA_READ); buffer = kmalloc(255, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
init_cdrom_command(&cgc, buffer, 4, CGC_DATA_READ);
cgc.quiet = 1; cgc.quiet = 1;
/* /*
...@@ -816,10 +861,15 @@ static int mo_open_write(struct cdrom_device_info *cdi) ...@@ -816,10 +861,15 @@ static int mo_open_write(struct cdrom_device_info *cdi)
} }
/* drive gave us no info, let the user go ahead */ /* drive gave us no info, let the user go ahead */
if (ret) if (ret) {
return 0; ret = 0;
goto err;
}
return buffer[3] & 0x80; ret = buffer[3] & 0x80;
err:
kfree(buffer);
return ret;
} }
static int cdrom_ram_open_write(struct cdrom_device_info *cdi) static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
...@@ -842,15 +892,19 @@ static int cdrom_ram_open_write(struct cdrom_device_info *cdi) ...@@ -842,15 +892,19 @@ static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
static void cdrom_mmc3_profile(struct cdrom_device_info *cdi) static void cdrom_mmc3_profile(struct cdrom_device_info *cdi)
{ {
struct packet_command cgc; struct packet_command cgc;
char buffer[32]; char *buffer;
int ret, mmc3_profile; int ret, mmc3_profile;
init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); buffer = kmalloc(32, GFP_KERNEL);
if (!buffer)
return;
init_cdrom_command(&cgc, buffer, 32, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_GET_CONFIGURATION; cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
cgc.cmd[1] = 0; cgc.cmd[1] = 0;
cgc.cmd[2] = cgc.cmd[3] = 0; /* Starting Feature Number */ cgc.cmd[2] = cgc.cmd[3] = 0; /* Starting Feature Number */
cgc.cmd[8] = sizeof(buffer); /* Allocation Length */ cgc.cmd[8] = 32; /* Allocation Length */
cgc.quiet = 1; cgc.quiet = 1;
if ((ret = cdi->ops->generic_packet(cdi, &cgc))) if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
...@@ -859,6 +913,7 @@ static void cdrom_mmc3_profile(struct cdrom_device_info *cdi) ...@@ -859,6 +913,7 @@ static void cdrom_mmc3_profile(struct cdrom_device_info *cdi)
mmc3_profile = (buffer[6] << 8) | buffer[7]; mmc3_profile = (buffer[6] << 8) | buffer[7];
cdi->mmc3_profile = mmc3_profile; cdi->mmc3_profile = mmc3_profile;
kfree(buffer);
} }
static int cdrom_is_dvd_rw(struct cdrom_device_info *cdi) static int cdrom_is_dvd_rw(struct cdrom_device_info *cdi)
...@@ -1573,12 +1628,15 @@ static void setup_send_key(struct packet_command *cgc, unsigned agid, unsigned t ...@@ -1573,12 +1628,15 @@ static void setup_send_key(struct packet_command *cgc, unsigned agid, unsigned t
static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
{ {
int ret; int ret;
u_char buf[20]; u_char *buf;
struct packet_command cgc; struct packet_command cgc;
struct cdrom_device_ops *cdo = cdi->ops; struct cdrom_device_ops *cdo = cdi->ops;
rpc_state_t rpc_state; rpc_state_t *rpc_state;
buf = kzalloc(20, GFP_KERNEL);
if (!buf)
return -ENOMEM;
memset(buf, 0, sizeof(buf));
init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ); init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ);
switch (ai->type) { switch (ai->type) {
...@@ -1589,7 +1647,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) ...@@ -1589,7 +1647,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
setup_report_key(&cgc, ai->lsa.agid, 0); setup_report_key(&cgc, ai->lsa.agid, 0);
if ((ret = cdo->generic_packet(cdi, &cgc))) if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret; goto err;
ai->lsa.agid = buf[7] >> 6; ai->lsa.agid = buf[7] >> 6;
/* Returning data, let host change state */ /* Returning data, let host change state */
...@@ -1600,7 +1658,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) ...@@ -1600,7 +1658,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
setup_report_key(&cgc, ai->lsk.agid, 2); setup_report_key(&cgc, ai->lsk.agid, 2);
if ((ret = cdo->generic_packet(cdi, &cgc))) if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret; goto err;
copy_key(ai->lsk.key, &buf[4]); copy_key(ai->lsk.key, &buf[4]);
/* Returning data, let host change state */ /* Returning data, let host change state */
...@@ -1611,7 +1669,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) ...@@ -1611,7 +1669,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
setup_report_key(&cgc, ai->lsc.agid, 1); setup_report_key(&cgc, ai->lsc.agid, 1);
if ((ret = cdo->generic_packet(cdi, &cgc))) if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret; goto err;
copy_chal(ai->lsc.chal, &buf[4]); copy_chal(ai->lsc.chal, &buf[4]);
/* Returning data, let host change state */ /* Returning data, let host change state */
...@@ -1628,7 +1686,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) ...@@ -1628,7 +1686,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
cgc.cmd[2] = ai->lstk.lba >> 24; cgc.cmd[2] = ai->lstk.lba >> 24;
if ((ret = cdo->generic_packet(cdi, &cgc))) if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret; goto err;
ai->lstk.cpm = (buf[4] >> 7) & 1; ai->lstk.cpm = (buf[4] >> 7) & 1;
ai->lstk.cp_sec = (buf[4] >> 6) & 1; ai->lstk.cp_sec = (buf[4] >> 6) & 1;
...@@ -1642,7 +1700,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) ...@@ -1642,7 +1700,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
setup_report_key(&cgc, ai->lsasf.agid, 5); setup_report_key(&cgc, ai->lsasf.agid, 5);
if ((ret = cdo->generic_packet(cdi, &cgc))) if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret; goto err;
ai->lsasf.asf = buf[7] & 1; ai->lsasf.asf = buf[7] & 1;
break; break;
...@@ -1655,7 +1713,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) ...@@ -1655,7 +1713,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
copy_chal(&buf[4], ai->hsc.chal); copy_chal(&buf[4], ai->hsc.chal);
if ((ret = cdo->generic_packet(cdi, &cgc))) if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret; goto err;
ai->type = DVD_LU_SEND_KEY1; ai->type = DVD_LU_SEND_KEY1;
break; break;
...@@ -1668,7 +1726,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) ...@@ -1668,7 +1726,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
if ((ret = cdo->generic_packet(cdi, &cgc))) { if ((ret = cdo->generic_packet(cdi, &cgc))) {
ai->type = DVD_AUTH_FAILURE; ai->type = DVD_AUTH_FAILURE;
return ret; goto err;
} }
ai->type = DVD_AUTH_ESTABLISHED; ai->type = DVD_AUTH_ESTABLISHED;
break; break;
...@@ -1679,24 +1737,23 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) ...@@ -1679,24 +1737,23 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGID\n"); cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGID\n");
setup_report_key(&cgc, ai->lsa.agid, 0x3f); setup_report_key(&cgc, ai->lsa.agid, 0x3f);
if ((ret = cdo->generic_packet(cdi, &cgc))) if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret; goto err;
break; break;
/* Get region settings */ /* Get region settings */
case DVD_LU_SEND_RPC_STATE: case DVD_LU_SEND_RPC_STATE:
cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n"); cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n");
setup_report_key(&cgc, 0, 8); setup_report_key(&cgc, 0, 8);
memset(&rpc_state, 0, sizeof(rpc_state_t));
cgc.buffer = (char *) &rpc_state;
if ((ret = cdo->generic_packet(cdi, &cgc))) if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret; goto err;
ai->lrpcs.type = rpc_state.type_code; rpc_state = (rpc_state_t *)buf;
ai->lrpcs.vra = rpc_state.vra; ai->lrpcs.type = rpc_state->type_code;
ai->lrpcs.ucca = rpc_state.ucca; ai->lrpcs.vra = rpc_state->vra;
ai->lrpcs.region_mask = rpc_state.region_mask; ai->lrpcs.ucca = rpc_state->ucca;
ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme; ai->lrpcs.region_mask = rpc_state->region_mask;
ai->lrpcs.rpc_scheme = rpc_state->rpc_scheme;
break; break;
/* Set region settings */ /* Set region settings */
...@@ -1707,20 +1764,23 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) ...@@ -1707,20 +1764,23 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
buf[4] = ai->hrpcs.pdrc; buf[4] = ai->hrpcs.pdrc;
if ((ret = cdo->generic_packet(cdi, &cgc))) if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret; goto err;
break; break;
default: default:
cdinfo(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type); cdinfo(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type);
return -ENOTTY; ret = -ENOTTY;
goto err;
} }
ret = 0;
return 0; err:
kfree(buf);
return ret;
} }
static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s) static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
{ {
unsigned char buf[21], *base; unsigned char *buf, *base;
struct dvd_layer *layer; struct dvd_layer *layer;
struct packet_command cgc; struct packet_command cgc;
struct cdrom_device_ops *cdo = cdi->ops; struct cdrom_device_ops *cdo = cdi->ops;
...@@ -1729,7 +1789,11 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s) ...@@ -1729,7 +1789,11 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
if (layer_num >= DVD_LAYERS) if (layer_num >= DVD_LAYERS)
return -EINVAL; return -EINVAL;
init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); buf = kmalloc(21, GFP_KERNEL);
if (!buf)
return -ENOMEM;
init_cdrom_command(&cgc, buf, 21, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[6] = layer_num; cgc.cmd[6] = layer_num;
cgc.cmd[7] = s->type; cgc.cmd[7] = s->type;
...@@ -1741,7 +1805,7 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s) ...@@ -1741,7 +1805,7 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
cgc.quiet = 1; cgc.quiet = 1;
if ((ret = cdo->generic_packet(cdi, &cgc))) if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret; goto err;
base = &buf[4]; base = &buf[4];
layer = &s->physical.layer[layer_num]; layer = &s->physical.layer[layer_num];
...@@ -1765,17 +1829,24 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s) ...@@ -1765,17 +1829,24 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15]; layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15];
layer->bca = base[16] >> 7; layer->bca = base[16] >> 7;
return 0; ret = 0;
err:
kfree(buf);
return ret;
} }
static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s) static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
{ {
int ret; int ret;
u_char buf[8]; u_char *buf;
struct packet_command cgc; struct packet_command cgc;
struct cdrom_device_ops *cdo = cdi->ops; struct cdrom_device_ops *cdo = cdi->ops;
init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); buf = kmalloc(8, GFP_KERNEL);
if (!buf)
return -ENOMEM;
init_cdrom_command(&cgc, buf, 8, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[6] = s->copyright.layer_num; cgc.cmd[6] = s->copyright.layer_num;
cgc.cmd[7] = s->type; cgc.cmd[7] = s->type;
...@@ -1783,12 +1854,15 @@ static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s) ...@@ -1783,12 +1854,15 @@ static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
cgc.cmd[9] = cgc.buflen & 0xff; cgc.cmd[9] = cgc.buflen & 0xff;
if ((ret = cdo->generic_packet(cdi, &cgc))) if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret; goto err;
s->copyright.cpst = buf[4]; s->copyright.cpst = buf[4];
s->copyright.rmi = buf[5]; s->copyright.rmi = buf[5];
return 0; ret = 0;
err:
kfree(buf);
return ret;
} }
static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s) static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
...@@ -1820,26 +1894,33 @@ static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s) ...@@ -1820,26 +1894,33 @@ static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s) static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s)
{ {
int ret; int ret;
u_char buf[4 + 188]; u_char *buf;
struct packet_command cgc; struct packet_command cgc;
struct cdrom_device_ops *cdo = cdi->ops; struct cdrom_device_ops *cdo = cdi->ops;
init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); buf = kmalloc(4 + 188, GFP_KERNEL);
if (!buf)
return -ENOMEM;
init_cdrom_command(&cgc, buf, 4 + 188, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[7] = s->type; cgc.cmd[7] = s->type;
cgc.cmd[9] = cgc.buflen & 0xff; cgc.cmd[9] = cgc.buflen & 0xff;
if ((ret = cdo->generic_packet(cdi, &cgc))) if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret; goto err;
s->bca.len = buf[0] << 8 | buf[1]; s->bca.len = buf[0] << 8 | buf[1];
if (s->bca.len < 12 || s->bca.len > 188) { if (s->bca.len < 12 || s->bca.len > 188) {
cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len); cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len);
return -EIO; ret = -EIO;
goto err;
} }
memcpy(s->bca.value, &buf[4], s->bca.len); memcpy(s->bca.value, &buf[4], s->bca.len);
ret = 0;
return 0; err:
kfree(buf);
return ret;
} }
static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s) static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s)
...@@ -1939,9 +2020,13 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi, ...@@ -1939,9 +2020,13 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
{ {
struct cdrom_device_ops *cdo = cdi->ops; struct cdrom_device_ops *cdo = cdi->ops;
struct packet_command cgc; struct packet_command cgc;
char buffer[32]; char *buffer;
int ret; int ret;
buffer = kmalloc(32, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ); init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_SUBCHANNEL; cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
cgc.cmd[1] = 2; /* MSF addressing */ cgc.cmd[1] = 2; /* MSF addressing */
...@@ -1950,7 +2035,7 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi, ...@@ -1950,7 +2035,7 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
cgc.cmd[8] = 16; cgc.cmd[8] = 16;
if ((ret = cdo->generic_packet(cdi, &cgc))) if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret; goto err;
subchnl->cdsc_audiostatus = cgc.buffer[1]; subchnl->cdsc_audiostatus = cgc.buffer[1];
subchnl->cdsc_format = CDROM_MSF; subchnl->cdsc_format = CDROM_MSF;
...@@ -1965,7 +2050,10 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi, ...@@ -1965,7 +2050,10 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
subchnl->cdsc_absaddr.msf.second = cgc.buffer[10]; subchnl->cdsc_absaddr.msf.second = cgc.buffer[10];
subchnl->cdsc_absaddr.msf.frame = cgc.buffer[11]; subchnl->cdsc_absaddr.msf.frame = cgc.buffer[11];
return 0; ret = 0;
err:
kfree(buffer);
return ret;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment