cdrom: Make device operations read-only
Since function tables are a common target for attackers, it's best to keep them in read-only memory. As such, this makes the CDROM device ops tables const. This drops additionally n_minors, since it isn't used meaningfully, and sets the only user of cdrom_dummy_generic_packet explicitly so the variables can all be const. Inspired by similar changes in grsecurity/PaX. Signed-off-by: Kees Cook <keescook@chromium.org> Acked-by: David S. Miller <davem@davemloft.net> Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
@@ -342,8 +342,8 @@ static void cdrom_sysctl_register(void);
|
||||
|
||||
static LIST_HEAD(cdrom_list);
|
||||
|
||||
static int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi,
|
||||
struct packet_command *cgc)
|
||||
int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi,
|
||||
struct packet_command *cgc)
|
||||
{
|
||||
if (cgc->sense) {
|
||||
cgc->sense->sense_key = 0x05;
|
||||
@@ -354,6 +354,7 @@ static int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi,
|
||||
cgc->stat = -EIO;
|
||||
return -EIO;
|
||||
}
|
||||
EXPORT_SYMBOL(cdrom_dummy_generic_packet);
|
||||
|
||||
static int cdrom_flush_cache(struct cdrom_device_info *cdi)
|
||||
{
|
||||
@@ -371,7 +372,7 @@ static int cdrom_flush_cache(struct cdrom_device_info *cdi)
|
||||
static int cdrom_get_disc_info(struct cdrom_device_info *cdi,
|
||||
disc_information *di)
|
||||
{
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
struct packet_command cgc;
|
||||
int ret, buflen;
|
||||
|
||||
@@ -586,7 +587,7 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
|
||||
int register_cdrom(struct cdrom_device_info *cdi)
|
||||
{
|
||||
static char banner_printed;
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
int *change_capability = (int *)&cdo->capability; /* hack */
|
||||
|
||||
cd_dbg(CD_OPEN, "entering register_cdrom\n");
|
||||
@@ -610,7 +611,6 @@ int register_cdrom(struct cdrom_device_info *cdi)
|
||||
ENSURE(reset, CDC_RESET);
|
||||
ENSURE(generic_packet, CDC_GENERIC_PACKET);
|
||||
cdi->mc_flags = 0;
|
||||
cdo->n_minors = 0;
|
||||
cdi->options = CDO_USE_FFLAGS;
|
||||
|
||||
if (autoclose == 1 && CDROM_CAN(CDC_CLOSE_TRAY))
|
||||
@@ -630,8 +630,7 @@ int register_cdrom(struct cdrom_device_info *cdi)
|
||||
else
|
||||
cdi->cdda_method = CDDA_OLD;
|
||||
|
||||
if (!cdo->generic_packet)
|
||||
cdo->generic_packet = cdrom_dummy_generic_packet;
|
||||
WARN_ON(!cdo->generic_packet);
|
||||
|
||||
cd_dbg(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
|
||||
mutex_lock(&cdrom_mutex);
|
||||
@@ -652,7 +651,6 @@ void unregister_cdrom(struct cdrom_device_info *cdi)
|
||||
if (cdi->exit)
|
||||
cdi->exit(cdi);
|
||||
|
||||
cdi->ops->n_minors--;
|
||||
cd_dbg(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
|
||||
}
|
||||
|
||||
@@ -1036,7 +1034,7 @@ static
|
||||
int open_for_data(struct cdrom_device_info *cdi)
|
||||
{
|
||||
int ret;
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
tracktype tracks;
|
||||
cd_dbg(CD_OPEN, "entering open_for_data\n");
|
||||
/* Check if the driver can report drive status. If it can, we
|
||||
@@ -1198,8 +1196,8 @@ err:
|
||||
/* This code is similar to that in open_for_data. The routine is called
|
||||
whenever an audio play operation is requested.
|
||||
*/
|
||||
static int check_for_audio_disc(struct cdrom_device_info * cdi,
|
||||
struct cdrom_device_ops * cdo)
|
||||
static int check_for_audio_disc(struct cdrom_device_info *cdi,
|
||||
const struct cdrom_device_ops *cdo)
|
||||
{
|
||||
int ret;
|
||||
tracktype tracks;
|
||||
@@ -1254,7 +1252,7 @@ static int check_for_audio_disc(struct cdrom_device_info * cdi,
|
||||
|
||||
void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode)
|
||||
{
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
int opened_for_data;
|
||||
|
||||
cd_dbg(CD_CLOSE, "entering cdrom_release\n");
|
||||
@@ -1294,7 +1292,7 @@ static int cdrom_read_mech_status(struct cdrom_device_info *cdi,
|
||||
struct cdrom_changer_info *buf)
|
||||
{
|
||||
struct packet_command cgc;
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
int length;
|
||||
|
||||
/*
|
||||
@@ -1643,7 +1641,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
|
||||
int ret;
|
||||
u_char buf[20];
|
||||
struct packet_command cgc;
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
rpc_state_t rpc_state;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
@@ -1791,7 +1789,7 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s,
|
||||
{
|
||||
unsigned char buf[21], *base;
|
||||
struct dvd_layer *layer;
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
int ret, layer_num = s->physical.layer_num;
|
||||
|
||||
if (layer_num >= DVD_LAYERS)
|
||||
@@ -1842,7 +1840,7 @@ static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s,
|
||||
{
|
||||
int ret;
|
||||
u_char buf[8];
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
|
||||
init_cdrom_command(cgc, buf, sizeof(buf), CGC_DATA_READ);
|
||||
cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE;
|
||||
@@ -1866,7 +1864,7 @@ static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s,
|
||||
{
|
||||
int ret, size;
|
||||
u_char *buf;
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
|
||||
size = sizeof(s->disckey.value) + 4;
|
||||
|
||||
@@ -1894,7 +1892,7 @@ static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s,
|
||||
{
|
||||
int ret, size = 4 + 188;
|
||||
u_char *buf;
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
|
||||
buf = kmalloc(size, GFP_KERNEL);
|
||||
if (!buf)
|
||||
@@ -1928,7 +1926,7 @@ static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s,
|
||||
{
|
||||
int ret = 0, size;
|
||||
u_char *buf;
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
|
||||
size = sizeof(s->manufact.value) + 4;
|
||||
|
||||
@@ -1995,7 +1993,7 @@ int cdrom_mode_sense(struct cdrom_device_info *cdi,
|
||||
struct packet_command *cgc,
|
||||
int page_code, int page_control)
|
||||
{
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
|
||||
memset(cgc->cmd, 0, sizeof(cgc->cmd));
|
||||
|
||||
@@ -2010,7 +2008,7 @@ int cdrom_mode_sense(struct cdrom_device_info *cdi,
|
||||
int cdrom_mode_select(struct cdrom_device_info *cdi,
|
||||
struct packet_command *cgc)
|
||||
{
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
|
||||
memset(cgc->cmd, 0, sizeof(cgc->cmd));
|
||||
memset(cgc->buffer, 0, 2);
|
||||
@@ -2025,7 +2023,7 @@ int cdrom_mode_select(struct cdrom_device_info *cdi,
|
||||
static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
|
||||
struct cdrom_subchnl *subchnl, int mcn)
|
||||
{
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
struct packet_command cgc;
|
||||
char buffer[32];
|
||||
int ret;
|
||||
@@ -2073,7 +2071,7 @@ static int cdrom_read_cd(struct cdrom_device_info *cdi,
|
||||
struct packet_command *cgc, int lba,
|
||||
int blocksize, int nblocks)
|
||||
{
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
|
||||
memset(&cgc->cmd, 0, sizeof(cgc->cmd));
|
||||
cgc->cmd[0] = GPCMD_READ_10;
|
||||
@@ -2093,7 +2091,7 @@ static int cdrom_read_block(struct cdrom_device_info *cdi,
|
||||
struct packet_command *cgc,
|
||||
int lba, int nblocks, int format, int blksize)
|
||||
{
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
|
||||
memset(&cgc->cmd, 0, sizeof(cgc->cmd));
|
||||
cgc->cmd[0] = GPCMD_READ_CD;
|
||||
@@ -2764,7 +2762,7 @@ static int cdrom_ioctl_audioctl(struct cdrom_device_info *cdi,
|
||||
*/
|
||||
static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size)
|
||||
{
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
struct packet_command cgc;
|
||||
struct modesel_head mh;
|
||||
|
||||
@@ -2790,7 +2788,7 @@ static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size)
|
||||
static int cdrom_get_track_info(struct cdrom_device_info *cdi,
|
||||
__u16 track, __u8 type, track_information *ti)
|
||||
{
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
struct packet_command cgc;
|
||||
int ret, buflen;
|
||||
|
||||
@@ -3049,7 +3047,7 @@ static noinline int mmc_ioctl_cdrom_play_msf(struct cdrom_device_info *cdi,
|
||||
void __user *arg,
|
||||
struct packet_command *cgc)
|
||||
{
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
struct cdrom_msf msf;
|
||||
cd_dbg(CD_DO_IOCTL, "entering CDROMPLAYMSF\n");
|
||||
if (copy_from_user(&msf, (struct cdrom_msf __user *)arg, sizeof(msf)))
|
||||
@@ -3069,7 +3067,7 @@ static noinline int mmc_ioctl_cdrom_play_blk(struct cdrom_device_info *cdi,
|
||||
void __user *arg,
|
||||
struct packet_command *cgc)
|
||||
{
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
struct cdrom_blk blk;
|
||||
cd_dbg(CD_DO_IOCTL, "entering CDROMPLAYBLK\n");
|
||||
if (copy_from_user(&blk, (struct cdrom_blk __user *)arg, sizeof(blk)))
|
||||
@@ -3164,7 +3162,7 @@ static noinline int mmc_ioctl_cdrom_start_stop(struct cdrom_device_info *cdi,
|
||||
struct packet_command *cgc,
|
||||
int cmd)
|
||||
{
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
cd_dbg(CD_DO_IOCTL, "entering CDROMSTART/CDROMSTOP\n");
|
||||
cgc->cmd[0] = GPCMD_START_STOP_UNIT;
|
||||
cgc->cmd[1] = 1;
|
||||
@@ -3177,7 +3175,7 @@ static noinline int mmc_ioctl_cdrom_pause_resume(struct cdrom_device_info *cdi,
|
||||
struct packet_command *cgc,
|
||||
int cmd)
|
||||
{
|
||||
struct cdrom_device_ops *cdo = cdi->ops;
|
||||
const struct cdrom_device_ops *cdo = cdi->ops;
|
||||
cd_dbg(CD_DO_IOCTL, "entering CDROMPAUSE/CDROMRESUME\n");
|
||||
cgc->cmd[0] = GPCMD_PAUSE_RESUME;
|
||||
cgc->cmd[8] = (cmd == CDROMRESUME) ? 1 : 0;
|
||||
|
Reference in New Issue
Block a user