Przeglądaj źródła

dsp-kernel: Fix to use copy from user for compat invoke user pointers

When allocating context to copy the compat invoke call arguments data,
it incorrectly treats compat invoke call arguments as kernel memory,
leading to exceptions. The fix is to recognize them as userspace pointers.

Change-Id: I336b33156498103d3c3591768be98e0c105dda89
Signed-off-by: rnallago <[email protected]>
Ramesh Nallagopu 8 miesięcy temu
rodzic
commit
1145bbef01
2 zmienionych plików z 22 dodań i 32 usunięć
  1. 4 4
      dsp/adsprpc.c
  2. 18 28
      dsp/adsprpc_compat.c

+ 4 - 4
dsp/adsprpc.c

@@ -1894,7 +1894,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
 	}
 
 	if (invokefd->fds) {
-		K_COPY_FROM_USER(err, kernel, ctx->fds, invokefd->fds,
+		K_COPY_FROM_USER(err, kernel_msg, ctx->fds, invokefd->fds,
 						bufs * sizeof(*ctx->fds));
 		if (err) {
 			ADSPRPC_ERR(
@@ -1907,7 +1907,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
 		ctx->fds = NULL;
 	}
 	if (invokefd->attrs) {
-		K_COPY_FROM_USER(err, kernel, ctx->attrs, invokefd->attrs,
+		K_COPY_FROM_USER(err, kernel_msg, ctx->attrs, invokefd->attrs,
 						bufs * sizeof(*ctx->attrs));
 		if (err) {
 			ADSPRPC_ERR(
@@ -1952,7 +1952,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
 		ctx->perf->tid = fl->tgid;
 	}
 	if (invokefd->job) {
-		K_COPY_FROM_USER(err, kernel, &ctx->asyncjob, invokefd->job,
+		K_COPY_FROM_USER(err, kernel_msg, &ctx->asyncjob, invokefd->job,
 						sizeof(ctx->asyncjob));
 		if (err)
 			goto bail;
@@ -3924,7 +3924,7 @@ int fastrpc_internal_invoke2(struct fastrpc_file *fl,
 			err = -EBADE;
 			goto bail;
 		}
-		K_COPY_FROM_USER(err, is_compat, &p.user_concurrency,
+		K_COPY_FROM_USER(err, 0, &p.user_concurrency,
 				(void *)inv2->invparam, size);
 		if (err)
 			goto bail;

+ 18 - 28
dsp/adsprpc_compat.c

@@ -280,7 +280,6 @@ static int compat_get_fastrpc_ioctl_invoke(
 	if (err)
 		return err;
 	pra32 = compat_ptr(p);
-	pra = (union remote_arg *)(inv + 1);
 	for (j = 0; j < len; j++) {
 		err |= get_user(p, &pra32[j].buf.pv);
 		memcpy((uintptr_t *)&pra[j].buf.pv, &p, sizeof(p));
@@ -288,12 +287,11 @@ static int compat_get_fastrpc_ioctl_invoke(
 		memcpy(&pra[j].buf.len, &s, sizeof(s));
 	}
 
-	inv->fds = NULL;
 	if (cmd != COMPAT_FASTRPC_IOCTL_INVOKE) {
 		err |= get_user(p, &inv32->fds);
 		memcpy(&inv->fds, &p, sizeof(p));
 	}
-	inv->attrs = NULL;
+
 	if ((cmd == COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS) ||
 		(cmd == COMPAT_FASTRPC_IOCTL_INVOKE_CRC) ||
 		(cmd == COMPAT_FASTRPC_IOCTL_INVOKE_PERF) ||
@@ -301,19 +299,17 @@ static int compat_get_fastrpc_ioctl_invoke(
 		err |= get_user(p, &inv32->attrs);
 		memcpy(&inv->attrs, &p, sizeof(p));
 	}
-	inv->crc = NULL;
+
 	if ((cmd == COMPAT_FASTRPC_IOCTL_INVOKE_CRC) ||
 		(cmd == COMPAT_FASTRPC_IOCTL_INVOKE_PERF)) {
 		err |= get_user(p, &inv32->crc);
 		memcpy(&inv->crc, &p, sizeof(p));
 	}
-	inv->job = NULL;
+
 	if (cmd == FASTRPC_INVOKE2_ASYNC) {
 		err |= get_user(p, &inv32->job);
 		memcpy(&inv->job, &p, sizeof(p));
 	}
-	inv->perf_kernel = NULL;
-	inv->perf_dsp = NULL;
 
 	if ((cmd == COMPAT_FASTRPC_IOCTL_INVOKE_PERF) || (cmd == FASTRPC_INVOKE2_ASYNC)) {
 		err |= get_user(k, &inv32->perf_kernel);
@@ -338,7 +334,7 @@ static int compat_fastrpc_ioctl_invoke(struct file *filp,
 	if (err)
 		return err;
 	len = REMOTE_SCALARS_LENGTH(sc);
-	VERIFY(err, NULL != (inv = kmalloc(
+	VERIFY(err, NULL != (inv = kzalloc(
 		sizeof(*inv) + len * sizeof(union remote_arg), GFP_KERNEL)));
 	if (err)
 		return -EFAULT;
@@ -390,7 +386,7 @@ static int compat_get_fastrpc_ioctl_invoke2(
 		if (err)
 			goto bail;
 		len = REMOTE_SCALARS_LENGTH(sc);
-		VERIFY(err, NULL != (inv2_user = kmalloc(
+		VERIFY(err, NULL != (inv2_user = kzalloc(
 				sizeof(*inv2_user) + sizeof(*asyncinv_user) +
 					len * sizeof(union remote_arg), GFP_KERNEL)));
 		if (err) {
@@ -406,11 +402,8 @@ static int compat_get_fastrpc_ioctl_invoke2(
 			if (err)
 				goto bail;
 
-			asyncinv_user->job = NULL;
 			err |= get_user(p, &lasync32_old->job);
 			memcpy(&asyncinv_user->job, &p, sizeof(p));
-			asyncinv_user->perf_kernel = NULL;
-			asyncinv_user->perf_dsp = NULL;
 		} else {
 			VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(lasync32,
 							asyncinv_user, req, sc));
@@ -420,8 +413,6 @@ static int compat_get_fastrpc_ioctl_invoke2(
 		memcpy(&inv2_user->req, &req, sizeof(req));
 		inv2_user->invparam = (uintptr_t)asyncinv_user;
 		inv2_user->size = sizeof(*asyncinv_user);
-		if (err)
-			goto bail;
 		break;
 	}
 	case FASTRPC_INVOKE2_ASYNC_RESPONSE:
@@ -452,7 +443,7 @@ static int compat_get_fastrpc_ioctl_invoke2(
 				goto bail;
 			}
 		}
-		VERIFY(err, NULL != (inv2_user = kmalloc(
+		VERIFY(err, NULL != (inv2_user = kzalloc(
 							sizeof(*inv2_user), GFP_KERNEL)));
 		if (err) {
 			err = -EFAULT;
@@ -461,16 +452,15 @@ static int compat_get_fastrpc_ioctl_invoke2(
 		memcpy(&inv2_user->req, &req, sizeof(req));
 		memcpy(&inv2_user->invparam, &pparam, sizeof(pparam));
 		memcpy(&inv2_user->size, &size, sizeof(size));
-		if (err)
-			goto bail;
 		break;
 	}
 	default:
 		err = -ENOTTY;
 		break;
 	}
-	*inva = inv2_user;
+
 bail:
+	*inva = inv2_user;
 	return err;
 }
 
@@ -751,7 +741,7 @@ static int compat_fastrpc_control(struct fastrpc_file *fl,
 	compat_uptr_t p;
 
 	ctrl32 = compat_ptr(arg);
-	VERIFY(err, NULL != (ctrl = kmalloc(
+	VERIFY(err, NULL != (ctrl = kzalloc(
 						sizeof(*ctrl), GFP_KERNEL)));
 	if (err)
 		return -EFAULT;
@@ -784,7 +774,7 @@ static int compat_fastrpc_get_dsp_info(struct fastrpc_file *fl,
 	size_t info_size = 0;
 
 	info32 = compat_ptr(arg);
-	VERIFY(err, NULL != (info = kmalloc(
+	VERIFY(err, NULL != (info = kzalloc(
 				sizeof(*info), GFP_KERNEL)));
 	info_size = sizeof(*info);
 	if (err) {
@@ -823,7 +813,7 @@ static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
 		struct fastrpc_ioctl_mem_map *map = NULL;
 
 		map32 = compat_ptr(arg);
-		VERIFY(err, NULL != (map = kmalloc(
+		VERIFY(err, NULL != (map = kzalloc(
 			sizeof(*map), GFP_KERNEL)));
 		if (err)
 			return -EFAULT;
@@ -850,7 +840,7 @@ static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
 		struct fastrpc_ioctl_mem_unmap *unmap = NULL;
 
 		unmap32 = compat_ptr(arg);
-		unmap = kmalloc(sizeof(*unmap), GFP_KERNEL);
+		unmap = kzalloc(sizeof(*unmap), GFP_KERNEL);
 		if (unmap == NULL)
 			return -EFAULT;
 
@@ -871,7 +861,7 @@ static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
 		struct fastrpc_ioctl_mmap *map = NULL;
 
 		map32 = compat_ptr(arg);
-		VERIFY(err, NULL != (map = kmalloc(
+		VERIFY(err, NULL != (map = kzalloc(
 							sizeof(*map), GFP_KERNEL)));
 		if (err)
 			return -EFAULT;
@@ -893,7 +883,7 @@ static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
 		struct fastrpc_ioctl_mmap *map = NULL;
 
 		map32 = compat_ptr(arg);
-		VERIFY(err, NULL != (map = kmalloc(
+		VERIFY(err, NULL != (map = kzalloc(
 							sizeof(*map), GFP_KERNEL)));
 		if (err)
 			return -EFAULT;
@@ -913,7 +903,7 @@ static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
 		struct fastrpc_ioctl_munmap *unmap = NULL;
 
 		unmap32 = compat_ptr(arg);
-		VERIFY(err, NULL != (unmap = kmalloc(
+		VERIFY(err, NULL != (unmap = kzalloc(
 							sizeof(*unmap), GFP_KERNEL)));
 		if (err)
 			return -EFAULT;
@@ -1021,7 +1011,7 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
 		struct fastrpc_ioctl_munmap *unmap = NULL;
 
 		unmap32 = compat_ptr(arg);
-		VERIFY(err, NULL != (unmap = kmalloc(
+		VERIFY(err, NULL != (unmap = kzalloc(
 							sizeof(*unmap), GFP_KERNEL)));
 
 		if (err)
@@ -1047,7 +1037,7 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
 		struct fastrpc_ioctl_init_attrs *init = NULL;
 
 		init32 = compat_ptr(arg);
-		VERIFY(err, NULL != (init = kmalloc(
+		VERIFY(err, NULL != (init = kzalloc(
 							sizeof(*init), GFP_KERNEL)));
 		if (err)
 			return -EFAULT;
@@ -1070,7 +1060,7 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
 		compat_uint_t u;
 
 		info32 = compat_ptr(arg);
-		VERIFY(err, NULL != (info = kmalloc(
+		VERIFY(err, NULL != (info = kzalloc(
 							sizeof(*info), GFP_KERNEL)));
 		if (err)
 			return -EFAULT;