Subject: UVM permissions check for ARM_SYNC_ICACHE syscall
To: None <port-arm@NetBSD.org>
From: Todd Poynor <tpoynor@danger.com>
List: port-arm
Date: 11/06/2007 16:09:42
The ARM_SYNC_ICACHE syscall will invalidate any I cache (and clean and
invalidate any D cache) ranges requested by userspace, including
kernel virtual addresses.  It may be possible for a rogue program to
cause some mischief by invalidating modifications made by the kernel.

The suggested patch below fails the arm_sync_icache() with EINVAL if
the address range is not fully mapped writeable to the process.  Any
suggestions appreciated. -- Todd


Index: netbsd/src/sys/arch/arm/arm32/sys_machdep.c
===================================================================
--- netbsd.orig/src/sys/arch/arm/arm32/sys_machdep.c
+++ netbsd/src/sys/arch/arm/arm32/sys_machdep.c
@@ -66,11 +66,26 @@ arm32_sync_icache(p, args, retval)
  	register_t *retval;
  {
  	struct arm_sync_icache_args ua;
+	struct vmspace *vm;
  	int error;
+	int rv;

  	if ((error = copyin(args, &ua, sizeof(ua))) != 0)
  		return (error);

+	if ((error = proc_vmspace_getref(p, &vm)) != 0)
+		return (error);
+
+	vm_map_lock(&vm->vm_map);
+	rv = uvm_map_checkprot(&vm->vm_map, ua.addr, ua.addr + ua.len,
+			       VM_PROT_WRITE);
+	vm_map_unlock(&vm->vm_map);
+	uvmspace_free(vm);
+
+	if (rv == 0) {
+		return EINVAL;
+	}
+
  	cpu_icache_sync_range(ua.addr, ua.len);

  	*retval = 0;