Solaris是一款由Sun开发和维护的商业性质UNIX操作系统。 Solaris内核中用于在32位模式系统上处理SYS_kaio系统调用请求的代码存在整数溢出漏洞,本地攻击者可以利用这个漏洞导致由于内核忙碌而触发的系统崩溃。由于所有的Solaris区共享相同的内核,因此即使由普通的非全局区触发也可以导致整个系统崩溃。 /uts/common/os/aio.c中的源码: [..] 221 static int64_t 222 kaioc( 223 long a0, 224 long a1, 225 long a2, 226 long a3, 227 long a4, 228 long a5) 229 { 230 int error; 231 long rval = 0; 232 233 switch ((int)a0 & ~AIO_POLL_BIT) { ... 266 case AIOSUSPEND: 267 [1] error = aiosuspend((void *)a1, (int)a2, (timespec_t *)a3, 268 (int)a4, &rval, AIO_64); 269 break; [..] [1] aiosuspend()函数的a1、a2、a3和a4参数是受控的。 /uts/common/os/aio.c中的源码: [..] 897 static int 898 aiosuspend( 899 void *aiocb, 900 int nent, 901 struct timespec *timout, 902 int flag, 903 long *rval, 904 int run_mode) 905 { ... 925 aiop = curproc->p_aio; 926 [2] if (aiop == NULL || nent <= 0) 927 return (EINVAL); ... 951 if (model == DATAMODEL_NATIVE) 952 [3] ssize = (sizeof (aiocb_t *) * nent); 953 #ifdef _SYSCALL32_IMPL 954 else 955 [3] ssize = (sizeof (caddr32_t) * nent); 956...
Solaris是一款由Sun开发和维护的商业性质UNIX操作系统。 Solaris内核中用于在32位模式系统上处理SYS_kaio系统调用请求的代码存在整数溢出漏洞,本地攻击者可以利用这个漏洞导致由于内核忙碌而触发的系统崩溃。由于所有的Solaris区共享相同的内核,因此即使由普通的非全局区触发也可以导致整个系统崩溃。 /uts/common/os/aio.c中的源码: [..] 221 static int64_t 222 kaioc( 223 long a0, 224 long a1, 225 long a2, 226 long a3, 227 long a4, 228 long a5) 229 { 230 int error; 231 long rval = 0; 232 233 switch ((int)a0 & ~AIO_POLL_BIT) { ... 266 case AIOSUSPEND: 267 [1] error = aiosuspend((void *)a1, (int)a2, (timespec_t *)a3, 268 (int)a4, &rval, AIO_64); 269 break; [..] [1] aiosuspend()函数的a1、a2、a3和a4参数是受控的。 /uts/common/os/aio.c中的源码: [..] 897 static int 898 aiosuspend( 899 void *aiocb, 900 int nent, 901 struct timespec *timout, 902 int flag, 903 long *rval, 904 int run_mode) 905 { ... 925 aiop = curproc->p_aio; 926 [2] if (aiop == NULL || nent <= 0) 927 return (EINVAL); ... 951 if (model == DATAMODEL_NATIVE) 952 [3] ssize = (sizeof (aiocb_t *) * nent); 953 #ifdef _SYSCALL32_IMPL 954 else 955 [3] ssize = (sizeof (caddr32_t) * nent); 956 #endif /* _SYSCALL32_IMPL */ 957 958 [4] cbplist = kmem_alloc(ssize, KM_NOSLEEP); [..] [2] 由于nent是受控的,如果nent > 0就可以绕过这个检查 [3] 使用用户控制的nent值计算ssize值,对nent提供0x3fffffff值就可以触发整数溢出,导致ssize = 0x00000000。在[4]处用0x00000000长度值调用kmem_alloc()函数,kmem_alloc()函数本身用0x00000000值调用vmem_alloc(),该函数用相同的size值调用vmem_xalloc()。 /lib/libumem/common/vmem.c中的源码: [..] 815 void * 816 vmem_xalloc(vmem_t *vmp, size_t size, size_t align, size_t phase, 817 size_t nocross, void *minaddr, void *maxaddr, int vmflag) 818 { ... 934 [6] if (size == 0) 935 umem_panic(\"vmem_xalloc(): size == 0\"); [..] [6] 如果向vmem_xalloc()函数提供了0x00000000的size值就会导致内核忙碌。