Skip to content

Commit

Permalink
Revert "staging: vchiq: avoid mixing kernel and user pointers"
Browse files Browse the repository at this point in the history
See: #4016

This reverts commit 1c95454.
  • Loading branch information
pelwell committed Dec 21, 2020
1 parent 967d45b commit 2854316
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 30 deletions.
22 changes: 9 additions & 13 deletions drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ static irqreturn_t
vchiq_doorbell_irq(int irq, void *dev_id);

static struct vchiq_pagelist_info *
create_pagelist(char *buf, char __user *ubuf, size_t count, unsigned short type);
create_pagelist(char __user *buf, size_t count, unsigned short type);

static void
free_pagelist(struct vchiq_pagelist_info *pagelistinfo,
Expand Down Expand Up @@ -251,12 +251,12 @@ remote_event_signal(struct remote_event *event)
}

enum vchiq_status
vchiq_prepare_bulk_data(struct vchiq_bulk *bulk, void *offset,
void __user *uoffset, int size, int dir)
vchiq_prepare_bulk_data(struct vchiq_bulk *bulk, void *offset, int size,
int dir)
{
struct vchiq_pagelist_info *pagelistinfo;

pagelistinfo = create_pagelist(offset, uoffset, size,
pagelistinfo = create_pagelist((char __user *)offset, size,
(dir == VCHIQ_BULK_RECEIVE)
? PAGELIST_READ
: PAGELIST_WRITE);
Expand Down Expand Up @@ -345,8 +345,7 @@ cleanup_pagelistinfo(struct vchiq_pagelist_info *pagelistinfo)
*/

static struct vchiq_pagelist_info *
create_pagelist(char *buf, char __user *ubuf,
size_t count, unsigned short type)
create_pagelist(char __user *buf, size_t count, unsigned short type)
{
struct pagelist *pagelist;
struct vchiq_pagelist_info *pagelistinfo;
Expand All @@ -363,10 +362,7 @@ create_pagelist(char *buf, char __user *ubuf,
if (count >= INT_MAX - PAGE_SIZE)
return NULL;

if (buf)
offset = (uintptr_t)buf & (PAGE_SIZE - 1);
else
offset = (uintptr_t)ubuf & (PAGE_SIZE - 1);
offset = ((unsigned int)(unsigned long)buf & (PAGE_SIZE - 1));
num_pages = DIV_ROUND_UP(count + offset, PAGE_SIZE);

if (num_pages > (SIZE_MAX - sizeof(struct pagelist) -
Expand Down Expand Up @@ -423,14 +419,14 @@ create_pagelist(char *buf, char __user *ubuf,
pagelistinfo->scatterlist = scatterlist;
pagelistinfo->scatterlist_mapped = 0;

if (buf) {
if (is_vmalloc_addr((void __force *)buf)) {
unsigned long length = count;
unsigned int off = offset;

for (actual_pages = 0; actual_pages < num_pages;
actual_pages++) {
struct page *pg =
vmalloc_to_page((buf +
vmalloc_to_page((void __force *)(buf +
(actual_pages * PAGE_SIZE)));
size_t bytes = PAGE_SIZE - off;

Expand All @@ -448,7 +444,7 @@ create_pagelist(char *buf, char __user *ubuf,
/* do not try and release vmalloc pages */
} else {
actual_pages = pin_user_pages_fast(
(unsigned long)ubuf & PAGE_MASK,
(unsigned long)buf & PAGE_MASK,
num_pages,
type == PAGELIST_READ,
pages);
Expand Down
14 changes: 6 additions & 8 deletions drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,8 @@ vchiq_bulk_transmit(unsigned int handle, const void *data,
case VCHIQ_BULK_MODE_NOCALLBACK:
case VCHIQ_BULK_MODE_CALLBACK:
status = vchiq_bulk_transfer(handle,
(void *)data, NULL,
size, userdata, mode,
(void *)data, size,
userdata, mode,
VCHIQ_BULK_TRANSMIT);
break;
case VCHIQ_BULK_MODE_BLOCKING:
Expand Down Expand Up @@ -405,8 +405,7 @@ enum vchiq_status vchiq_bulk_receive(unsigned int handle, void *data,
switch (mode) {
case VCHIQ_BULK_MODE_NOCALLBACK:
case VCHIQ_BULK_MODE_CALLBACK:
status = vchiq_bulk_transfer(handle, data, NULL,
size, userdata,
status = vchiq_bulk_transfer(handle, data, size, userdata,
mode, VCHIQ_BULK_RECEIVE);
break;
case VCHIQ_BULK_MODE_BLOCKING:
Expand Down Expand Up @@ -486,8 +485,7 @@ vchiq_blocking_bulk_transfer(unsigned int handle, void *data,
}
}

status = vchiq_bulk_transfer(handle, data, NULL, size,
&waiter->bulk_waiter,
status = vchiq_bulk_transfer(handle, data, size, &waiter->bulk_waiter,
VCHIQ_BULK_MODE_BLOCKING, dir);
if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) ||
!waiter->bulk_waiter.bulk) {
Expand Down Expand Up @@ -934,7 +932,7 @@ static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance,
ret = -ENOTCONN;
} else if (header->size <= args->bufsize) {
/* Copy to user space if msgbuf is not NULL */
if (!args->buf || (copy_to_user(args->buf,
if (!args->buf || (copy_to_user((void __user *)args->buf,
header->data, header->size) == 0)) {
ret = header->size;
vchiq_release_message(service->handle, header);
Expand Down Expand Up @@ -1009,7 +1007,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
* accessing kernel data instead of user space, based on the
* address.
*/
status = vchiq_bulk_transfer(args->handle, NULL, args->data, args->size,
status = vchiq_bulk_transfer(args->handle, args->data, args->size,
userdata, args->mode, dir);

if (!waiter) {
Expand Down
10 changes: 4 additions & 6 deletions drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -3015,8 +3015,8 @@ vchiq_remove_service(unsigned int handle)
* structure.
*/
enum vchiq_status vchiq_bulk_transfer(unsigned int handle,
void *offset, void __user *uoffset,
int size, void *userdata,
void *offset, int size,
void *userdata,
enum vchiq_bulk_mode mode,
enum vchiq_bulk_dir dir)
{
Expand All @@ -3032,8 +3032,7 @@ enum vchiq_status vchiq_bulk_transfer(unsigned int handle,
int payload[2];

if (!service || service->srvstate != VCHIQ_SRVSTATE_OPEN ||
(!offset && !uoffset) ||
vchiq_check_service(service) != VCHIQ_SUCCESS)
!offset || vchiq_check_service(service) != VCHIQ_SUCCESS)
goto error_exit;

switch (mode) {
Expand Down Expand Up @@ -3089,8 +3088,7 @@ enum vchiq_status vchiq_bulk_transfer(unsigned int handle,
bulk->size = size;
bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED;

if (vchiq_prepare_bulk_data(bulk, offset, uoffset, size, dir)
!= VCHIQ_SUCCESS)
if (vchiq_prepare_bulk_data(bulk, offset, size, dir) != VCHIQ_SUCCESS)
goto unlock_error_exit;

wmb();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -559,8 +559,8 @@ extern void
remote_event_pollall(struct vchiq_state *state);

extern enum vchiq_status
vchiq_bulk_transfer(unsigned int handle, void *offset, void __user *uoffset,
int size, void *userdata, enum vchiq_bulk_mode mode,
vchiq_bulk_transfer(unsigned int handle, void *offset, int size,
void *userdata, enum vchiq_bulk_mode mode,
enum vchiq_bulk_dir dir);

extern int
Expand Down Expand Up @@ -633,7 +633,7 @@ vchiq_queue_message(unsigned int handle,

extern enum vchiq_status
vchiq_prepare_bulk_data(struct vchiq_bulk *bulk, void *offset,
void __user *uoffset, int size, int dir);
int size, int dir);

extern void
vchiq_complete_bulk(struct vchiq_bulk *bulk);
Expand Down

0 comments on commit 2854316

Please sign in to comment.