From 48683e52caf555cd6ef76384542d7b940d911d6e Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Mon, 28 May 2018 22:51:33 +0200 Subject: Copy surface ioctl params from user --- harddoomdev.c | 60 ++++++++++---------- harddoomdev.h | 10 ++-- surface.c | 179 ++++++++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 164 insertions(+), 85 deletions(-) diff --git a/harddoomdev.c b/harddoomdev.c index fc1f0e4..4a17001 100644 --- a/harddoomdev.c +++ b/harddoomdev.c @@ -194,68 +194,68 @@ void set_draw_params(struct doom_data *doom_data, uint8_t flags) } } -void fill_rect(struct surface_data *surface_data, struct doomdev_fill_rect rect) +void fill_rect(struct surface_data *surface_data, struct doomdev_fill_rect *rect) { set_surf_dst_pt(surface_data->doom_data, surface_data->page_table_dev); set_surf_dims(surface_data->doom_data, surface_data->width, surface_data->height); - set_xy_a(surface_data->doom_data, rect.pos_dst_x, rect.pos_dst_y); - set_fill_color(surface_data->doom_data, rect.color); + set_xy_a(surface_data->doom_data, rect->pos_dst_x, rect->pos_dst_y); + set_fill_color(surface_data->doom_data, rect->color); - send_command(surface_data->doom_data, HARDDOOM_CMD_FILL_RECT(rect.width, rect.height)); + send_command(surface_data->doom_data, HARDDOOM_CMD_FILL_RECT(rect->width, rect->height)); } -void draw_line(struct surface_data *surface_data, struct doomdev_line line) +void draw_line(struct surface_data *surface_data, struct doomdev_line *line) { set_surf_dst_pt(surface_data->doom_data, surface_data->page_table_dev); set_surf_dims(surface_data->doom_data, surface_data->width, surface_data->height); - set_xy_a(surface_data->doom_data, line.pos_a_x, line.pos_a_y); - set_xy_b(surface_data->doom_data, line.pos_b_x, line.pos_b_y); - set_fill_color(surface_data->doom_data, line.color); + set_xy_a(surface_data->doom_data, line->pos_a_x, line->pos_a_y); + set_xy_b(surface_data->doom_data, line->pos_b_x, line->pos_b_y); + set_fill_color(surface_data->doom_data, line->color); send_command(surface_data->doom_data, HARDDOOM_CMD_DRAW_LINE); } void copy_rect(struct surface_data *dst_data, struct surface_data *src_data, - struct doomdev_copy_rect rect) + struct doomdev_copy_rect *rect) { set_surf_dst_pt(dst_data->doom_data, dst_data->page_table_dev); set_surf_src_pt(dst_data->doom_data, src_data->page_table_dev); set_surf_dims(dst_data->doom_data, dst_data->width, dst_data->height); - set_xy_a(dst_data->doom_data, rect.pos_dst_x, rect.pos_dst_y); - set_xy_b(dst_data->doom_data, rect.pos_src_x, rect.pos_src_y); + set_xy_a(dst_data->doom_data, rect->pos_dst_x, rect->pos_dst_y); + set_xy_b(dst_data->doom_data, rect->pos_src_x, rect->pos_src_y); - send_command(dst_data->doom_data, HARDDOOM_CMD_COPY_RECT(rect.width, rect.height)); + send_command(dst_data->doom_data, HARDDOOM_CMD_COPY_RECT(rect->width, rect->height)); } void draw_column(struct surface_data *surface_data, - struct texture_data *texture_data, struct doomdev_column column, + struct texture_data *texture_data, struct doomdev_column *column, struct colors_data *colors_data, struct colors_data *trans_data, uint8_t flags, uint8_t trans_idx) { uint16_t y1, y2; - y1 = min(column.y1, column.y2); - y2 = max(column.y1, column.y2); + y1 = min(column->y1, column->y2); + y2 = max(column->y1, column->y2); set_surf_dst_pt(surface_data->doom_data, surface_data->page_table_dev); set_surf_dims(surface_data->doom_data, surface_data->width, surface_data->height); set_draw_params(surface_data->doom_data, flags); - set_xy_a(surface_data->doom_data, column.x, y1); - set_xy_b(surface_data->doom_data, column.x, y2); + set_xy_a(surface_data->doom_data, column->x, y1); + set_xy_b(surface_data->doom_data, column->x, y2); if (!(flags & HARDDOOM_DRAW_PARAMS_FUZZ)) { set_texture_pt(surface_data->doom_data, texture_data->page_table_dev); set_texture_dims(surface_data->doom_data, texture_data->size, texture_data->height); - set_ustart(surface_data->doom_data, column.ustart); - set_ustep(surface_data->doom_data, column.ustep); + set_ustart(surface_data->doom_data, column->ustart); + set_ustep(surface_data->doom_data, column->ustep); } if (flags & HARDDOOM_DRAW_PARAMS_FUZZ || flags & HARDDOOM_DRAW_PARAMS_COLORMAP) { set_colormap(surface_data->doom_data, colors_data->colors_dev + - HARDDOOM_COLORMAP_SIZE * column.colormap_idx); + HARDDOOM_COLORMAP_SIZE * column->colormap_idx); } if (flags & HARDDOOM_DRAW_PARAMS_TRANSLATE) { @@ -264,27 +264,27 @@ void draw_column(struct surface_data *surface_data, } send_command(surface_data->doom_data, - HARDDOOM_CMD_DRAW_COLUMN(column.texture_offset)); + HARDDOOM_CMD_DRAW_COLUMN(column->texture_offset)); } void draw_span(struct surface_data *surface_data, struct flat_data *flat_data, - struct doomdev_span span) + struct doomdev_span *span) { uint16_t x1, x2; - x1 = min(span.x1, span.x2); - x2 = max(span.x1, span.x2); + x1 = min(span->x1, span->x2); + x2 = max(span->x1, span->x2); set_surf_dst_pt(surface_data->doom_data, surface_data->page_table_dev); set_surf_dims(surface_data->doom_data, surface_data->width, surface_data->height); set_flat(surface_data->doom_data, flat_data->flat_dev); - set_xy_a(surface_data->doom_data, x1, span.y); - set_xy_b(surface_data->doom_data, x2, span.y); - set_ustart(surface_data->doom_data, span.ustart); - set_ustep(surface_data->doom_data, span.ustep); - set_vstart(surface_data->doom_data, span.vstart); - set_vstep(surface_data->doom_data, span.vstep); + set_xy_a(surface_data->doom_data, x1, span->y); + set_xy_b(surface_data->doom_data, x2, span->y); + set_ustart(surface_data->doom_data, span->ustart); + set_ustep(surface_data->doom_data, span->ustep); + set_vstart(surface_data->doom_data, span->vstart); + set_vstep(surface_data->doom_data, span->vstep); set_draw_params(surface_data->doom_data, 0); send_command(surface_data->doom_data, HARDDOOM_CMD_DRAW_SPAN); diff --git a/harddoomdev.h b/harddoomdev.h index 90d2b51..d37dd59 100644 --- a/harddoomdev.h +++ b/harddoomdev.h @@ -15,16 +15,16 @@ void deactivate_intr(void __iomem *iomem, uint32_t intr); void disable_intr(void __iomem *iomem, uint32_t intr); void ping_sync(struct doom_data *doom_data); -void draw_line(struct surface_data *surface_data, struct doomdev_line line); -void fill_rect(struct surface_data *surface_data, struct doomdev_fill_rect rect); +void draw_line(struct surface_data *surface_data, struct doomdev_line *line); +void fill_rect(struct surface_data *surface_data, struct doomdev_fill_rect *rect); void copy_rect(struct surface_data *dst_data, struct surface_data *src_data, - struct doomdev_copy_rect rect); + struct doomdev_copy_rect *rect); void draw_column(struct surface_data *surface_data, - struct texture_data *texture_data, struct doomdev_column column, + struct texture_data *texture_data, struct doomdev_column *column, struct colors_data *colors_data, struct colors_data *trans_data, uint8_t flags, uint8_t trans_idx); void draw_span(struct surface_data *surface_data, struct flat_data *flat_data, - struct doomdev_span span); + struct doomdev_span *span); void draw_background(struct surface_data *surface_data, struct flat_data *flat_data); diff --git a/surface.c b/surface.c index f4fa64f..82d9756 100644 --- a/surface.c +++ b/surface.c @@ -330,45 +330,80 @@ error_data: long draw_lines(struct file *filp, unsigned long arg) { struct surface_data *surface_data; - struct doomdev_surf_ioctl_draw_lines *param; + struct doomdev_surf_ioctl_draw_lines param; struct doomdev_line *lines; + struct doomdev_line line; int i; + int err; + int not_copied; surface_data = filp->private_data; - param = (struct doomdev_surf_ioctl_draw_lines *) arg; - lines = (struct doomdev_line *) param->lines_ptr; + not_copied = copy_from_user(¶m, (void __iomem *) arg, sizeof(param)); + if (not_copied) { + err = -EFAULT; + goto error_param; + } + + lines = (struct doomdev_line *) param.lines_ptr; mutex_lock(&surface_data->doom_data->cmd_mutex); - for (i = 0; i < param->lines_num; i++) { - draw_line(surface_data, lines[i]); + for (i = 0; i < param.lines_num; i++) { + not_copied = copy_from_user(&line, (void __iomem *) &lines[i], + sizeof(line)); + if (not_copied) { + goto error_copy; + } + + draw_line(surface_data, &lines[i]); } +error_copy: + err = i; mutex_unlock(&surface_data->doom_data->cmd_mutex); - return param->lines_num; +error_param: + return err; } long fill_rects(struct file *filp, unsigned long arg) { struct surface_data *surface_data; - struct doomdev_surf_ioctl_fill_rects *param; + struct doomdev_surf_ioctl_fill_rects param; struct doomdev_fill_rect *rects; + struct doomdev_fill_rect rect; int i; + int not_copied; + int err; surface_data = filp->private_data; - param = (struct doomdev_surf_ioctl_fill_rects *) arg; - rects = (struct doomdev_fill_rect *) param->rects_ptr; + not_copied = copy_from_user(¶m, (void __iomem *) arg, sizeof(param)); + if (not_copied) { + err = -EFAULT; + goto error_param; + } + + rects = (struct doomdev_fill_rect *) param.rects_ptr; mutex_lock(&surface_data->doom_data->cmd_mutex); - for (i = 0; i < param->rects_num; i++) { - fill_rect(surface_data, rects[i]); + for (i = 0; i < param.rects_num; i++) { + not_copied = copy_from_user(&rect, (void __iomem *) &rects[i], + sizeof(rect)); + if (not_copied) { + goto error_copy; + } + + fill_rect(surface_data, &rect); } +error_copy: + err = i; + mutex_unlock(&surface_data->doom_data->cmd_mutex); - return param->rects_num; +error_param: + return err; } struct file_operations surface_fops; @@ -377,17 +412,24 @@ long copy_rects(struct file *filp, unsigned long arg) { struct surface_data *dst_data; struct surface_data *src_data; - struct doomdev_surf_ioctl_copy_rects *param; + struct doomdev_surf_ioctl_copy_rects param; struct doomdev_copy_rect *rects; + struct doomdev_copy_rect rect; struct fd src_fds; int i; int err; + int not_copied; dst_data = filp->private_data; - param = (struct doomdev_surf_ioctl_copy_rects *) arg; - rects = (struct doomdev_copy_rect *) param->rects_ptr; + not_copied = copy_from_user(¶m, (void __iomem *) arg, sizeof(param)); + if (not_copied) { + err = -EFAULT; + goto error_param; + } - src_fds = fdget(param->surf_src_fd); + rects = (struct doomdev_copy_rect *) param.rects_ptr; + + src_fds = fdget(param.surf_src_fd); if (src_fds.file->f_op != &surface_fops) { err = -EINVAL; goto error_fdget; @@ -401,51 +443,62 @@ long copy_rects(struct file *filp, unsigned long arg) mutex_lock(&dst_data->doom_data->cmd_mutex); - for (i = 0; i < param->rects_num; i++) { - copy_rect(dst_data, src_data, rects[i]); + for (i = 0; i < param.rects_num; i++) { + not_copied = copy_from_user(&rect, (void __iomem *) &rects[i], + sizeof(rect)); + if (not_copied) { + goto error_copy; + } + + copy_rect(dst_data, src_data, &rect); } - err = param->rects_num; +error_copy: + err = i; mutex_unlock(&dst_data->doom_data->cmd_mutex); error_fdget: fdput(src_fds); +error_param: return err; } long draw_columns(struct file *filp, unsigned long arg) { - struct doomdev_surf_ioctl_draw_columns *param; + struct doomdev_surf_ioctl_draw_columns param; struct surface_data *surface_data; struct texture_data *texture_data; struct colors_data *colors_data; struct colors_data *trans_data; struct doomdev_column *columns; + struct doomdev_column column; struct fd texture_fds; struct fd colors_fds; struct fd trans_fds; - uint8_t flags; bool got_colors = false; bool got_trans = false; bool got_texture = false; + int not_copied; int i; int err; surface_data = filp->private_data; - param = (struct doomdev_surf_ioctl_draw_columns *) arg; - - flags = param->draw_flags; + not_copied = copy_from_user(¶m, (void __iomem *) arg, sizeof(param)); + if (not_copied) { + err = -EFAULT; + goto error_param; + } - if (flags & DOOMDEV_DRAW_FLAGS_FUZZ || - flags & DOOMDEV_DRAW_FLAGS_COLORMAP) { - if (flags & DOOMDEV_DRAW_FLAGS_FUZZ) { - flags = DOOMDEV_DRAW_FLAGS_FUZZ; + if (param.draw_flags & DOOMDEV_DRAW_FLAGS_FUZZ || + param.draw_flags & DOOMDEV_DRAW_FLAGS_COLORMAP) { + if (param.draw_flags & DOOMDEV_DRAW_FLAGS_FUZZ) { + param.draw_flags = DOOMDEV_DRAW_FLAGS_FUZZ; } - colors_fds = fdget(param->colormaps_fd); + colors_fds = fdget(param.colormaps_fd); got_colors = true; if (colors_fds.file->f_op != &colors_fops) { err = -EINVAL; @@ -459,8 +512,8 @@ long draw_columns(struct file *filp, unsigned long arg) } } - if (flags & DOOMDEV_DRAW_FLAGS_TRANSLATE) { - trans_fds = fdget(param->translations_fd); + if (param.draw_flags & DOOMDEV_DRAW_FLAGS_TRANSLATE) { + trans_fds = fdget(param.translations_fd); got_trans = true; if (trans_fds.file->f_op != &colors_fops) { err = -EINVAL; @@ -474,7 +527,7 @@ long draw_columns(struct file *filp, unsigned long arg) } } - texture_fds = fdget(param->texture_fd); + texture_fds = fdget(param.texture_fd); got_texture = true; if (texture_fds.file->f_op != &texture_fops) { err = -EINVAL; @@ -487,16 +540,23 @@ long draw_columns(struct file *filp, unsigned long arg) goto error_fdget; } - columns = (struct doomdev_column *) param->columns_ptr; + columns = (struct doomdev_column *) param.columns_ptr; mutex_lock(&surface_data->doom_data->cmd_mutex); - for (i = 0; i < param->columns_num; i++) { - draw_column(surface_data, texture_data, columns[i], colors_data, - trans_data, flags, param->translation_idx); + for (i = 0; i < param.columns_num; i++) { + not_copied = copy_from_user(&column, + (void __iomem *) &columns[i], sizeof(column)); + if (not_copied) { + goto error_copy; + } + + draw_column(surface_data, texture_data, &column, colors_data, + trans_data, param.draw_flags, param.translation_idx); } - err = param->columns_num; +error_copy: + err = i; mutex_unlock(&surface_data->doom_data->cmd_mutex); @@ -514,24 +574,31 @@ error_fdget: fdput(trans_fds); } - return param->columns_num; +error_param: + return err; } long draw_spans(struct file *filp, unsigned long arg) { - struct doomdev_surf_ioctl_draw_spans *param; + struct doomdev_surf_ioctl_draw_spans param; struct surface_data *surface_data; struct flat_data *flat_data; struct doomdev_span *spans; + struct doomdev_span span; struct fd flat_fds; int i; int err; + int not_copied; surface_data = filp->private_data; - param = (struct doomdev_surf_ioctl_draw_spans *) arg; + not_copied = copy_from_user(¶m, (void __iomem *) arg, sizeof(param)); + if (not_copied) { + err = -EFAULT; + goto error_param; + } - flat_fds = fdget(param->flat_fd); + flat_fds = fdget(param.flat_fd); if (flat_fds.file->f_op != &flat_fops) { err = -EINVAL; goto error_fdget; @@ -543,37 +610,49 @@ long draw_spans(struct file *filp, unsigned long arg) goto error_fdget; } - spans = (struct doomdev_span *) param->spans_ptr; + spans = (struct doomdev_span *) param.spans_ptr; mutex_lock(&surface_data->doom_data->cmd_mutex); - for (i = 0; i < param->spans_num; i++) { - draw_span(surface_data, flat_data, spans[i]); + for (i = 0; i < param.spans_num; i++) { + not_copied = copy_from_user(&span, (void __iomem *) &spans[i], + sizeof(span)); + if (not_copied) { + goto error_copy; + } + + draw_span(surface_data, flat_data, &span); } - err = param->spans_num; +error_copy: + err = i; mutex_unlock(&surface_data->doom_data->cmd_mutex); error_fdget: fdput(flat_fds); - +error_param: return err; } long do_draw_background(struct file *filp, unsigned long arg) { - struct doomdev_surf_ioctl_draw_background *param; + struct doomdev_surf_ioctl_draw_background param; struct surface_data *surface_data; struct flat_data *flat_data; struct fd flat_fds; int err = 0; + int not_written; surface_data = filp->private_data; - param = (struct doomdev_surf_ioctl_draw_background *) arg; + not_written = copy_from_user(¶m, (void __iomem *) arg, sizeof(param)); + if (not_written) { + err = -EFAULT; + goto error_param; + } - flat_fds = fdget(param->flat_fd); + flat_fds = fdget(param.flat_fd); if (flat_fds.file->f_op != &flat_fops) { err = -EINVAL; goto error_fdget; @@ -593,7 +672,7 @@ long do_draw_background(struct file *filp, unsigned long arg) error_fdget: fdput(flat_fds); - +error_param: return err; } -- cgit v1.2.3