Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Multiple Bug Report When Running the System #9875

Open
Rrooach opened this issue Jan 6, 2025 · 2 comments
Open

[Bug] Multiple Bug Report When Running the System #9875

Rrooach opened this issue Jan 6, 2025 · 2 comments

Comments

@Rrooach
Copy link

Rrooach commented Jan 6, 2025

RT-Thread Version

2f55990

Hardware Type/Architectures

QEMU/arm32

Develop Toolchain

GCC

Describe the bug

Hi, when I test the RTthread with our fuzzing tool, we encounter several crashes in kernel.

Step to reproduce

To reproduce, modify the rtthread/rt-thread/bsp/qemu-vexpress-a9.
run scons . and run with qemu-nographic.sh for each crash at a time can observe the crash.

The following are the reproducer program

#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <rtthread.h>
long syz_event_recv(volatile int event, volatile int set, volatile int option, volatile int timeout, volatile int recved) {
    rt_uint32_t recv;
    rt_err_t result = rt_event_recv((rt_event_t)event, (rt_uint32_t)set, (rt_uint8_t)option, (rt_int32_t)timeout, &recv);
    if (result != RT_EOK) {
        //rt_kprintf("Failed to receive event: %d\n", result);
        return -1;
    }
    *(rt_uint32_t *)recved = recv;
    return 0;
}
void syz_traverse_object_list() {
    rt_object_t obj = RT_NULL;
    rt_list_t *node = RT_NULL;

    //rt_kprintf("Traversing object list:\n");
    rt_list_for_each(node, &(obj_info.object_list)) {
        obj = rt_list_entry(node, struct rt_object, list);
        //rt_kprintf("Object name: %s\n", obj->name);
    }
}
long syz_mp_complex_usage(volatile int mp_handle) {
    // Attempt to allocate multiple blocks
    void *blocks[10];
    for (int i = 0; i < 10; i++) {
        blocks[i] = rt_mp_alloc((rt_mp_t)mp_handle, RT_WAITING_NO);
        if (blocks[i] == RT_NULL) {
            //rt_kprintf("Failed to allocate block at index %d.\n", i);
            // Attempt to free all allocated blocks so far
            for (int j = 0; j < i; j++) {
                rt_mp_free(blocks[j]);
            }
            return -1; // Failure
        }
    }
  
    for (int i = 0; i < 10; i++) {
        rt_mp_free(blocks[i]);
    }
    return 0; // Success
}
void syz_object_init_update_info() {
    rt_object_init(&obj_example, RT_Object_Class_Thread, "et");
    obj_info.type = RT_Object_Class_Thread;
    rt_list_insert_after(&(obj_info.object_list), &(obj_example.list));
    obj_info.object_size = sizeof(obj_example);
}
void syz_system_heap_init() {
    void *begin_addr = malloc(1024 * 1024);
    void *end_addr = begin_addr + 1024 * 1024;
    rt_system_heap_init(begin_addr, end_addr);
}
long syz_event_send(volatile int event, volatile int set) {
    rt_err_t result = rt_event_send((rt_event_t)event, (rt_uint32_t)set);
    if (result != RT_EOK) {
        //rt_kprintf("Failed to send event: %d\n", result);
        return -1;
    }
    return 0;
}
int main(void)
{
    executor_check_ints();
    rt_kprintf("Hello RT-Thread!\n");
    rt_kprintf("Starting executor.\n");
//  crash 1
    syz_event_recv (0x4, 0x0, 0x2, 0x0, 0xa000);
//  crash 2
    syz_traverse_object_list();
//  crash 3
    syz_mp_complex_usage (0xc4);
//  crash 4
    syz_object_init_update_info();
//  crash 5
    syz_system_heap_init();
//  crash 6
    syz_event_send (0x7fff, 0x0);
    rt_kprintf("Finish executor.\n");
    return 0;
}

System Logs:

crash 1:

it end up in

rt_uint8_t rt_object_get_type(rt_object_t object)
{
    /* object check */
    RT_ASSERT(object != RT_NULL);
    return object->type & ~RT_Object_Class_Static;
}

where failed to check the validity of object->type & ~RT_Object_Class_Static; cause the crash.

crash 2:

It ends up in

rt_inline int rt_list_isempty(const rt_list_t *l)
{
    return l->next == l;
}

My guess is there might be a illegal memory access in return l->next == l;, but I failed to analyze the actual case here.

crash 3:

The program crashed at thread = rt_thread_self();, but I failed to debug deeper, as it directly crashed at rt_thread_self.

void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time)
{
    rt_uint8_t *block_ptr;
    rt_base_t level;
    struct rt_thread *thread;
    rt_uint32_t before_sleep = 0;

    /* parameter check */
    RT_ASSERT(mp != RT_NULL);

    /* get current thread */
    thread = rt_thread_self();

crash 4:

The program crashed at type = (enum rt_object_class_type)(type & ~RT_Object_Class_Static);, similar to crash 1, where it seems to fail to check the vadaility of a certain value and trigger this error.

struct rt_object_information *
rt_object_get_information(enum rt_object_class_type type)
{
    int index;

    type = (enum rt_object_class_type)(type & ~RT_Object_Class_Static);

    for (index = 0; index < RT_Object_Info_Unknown; index ++)
        if (_object_container[index].type == type) return &_object_container[index];

    return RT_NULL;
}

crash 5:

It ends up in _heap_lock, where seems rt_spin_lock_irqsave triggers an illegal memory access.

rt_inline rt_base_t _heap_lock(void)
{
#if defined(RT_USING_HEAP_ISR)
    return rt_spin_lock_irqsave(&_heap_spinlock);
#elif defined(RT_USING_MUTEX)
    if (rt_thread_self())
        return rt_mutex_take(&_lock, RT_WAITING_FOREVER);

crash 6:

It crashed at rt_event_send, where seems failed to check the validity of event.

long syz_event_send(volatile int event, volatile int set) {
    rt_err_t result = rt_event_send((rt_event_t)event, (rt_uint32_t)set);
    if (result != RT_EOK) {
        //rt_kprintf("Failed to send event: %d\n", result);
        return -1;
    }
    return 0;
}

It would be so nice of you to review this bug report. Thank you again for taking the time. Any suggestions or feedback you can provide would be very helpful.

Best regards,

Other additional context

No response

@BernardXiong
Copy link
Member

Thank you for your feedback. What's your configuration? Enable smart in qemu-vexpress-a9?

@Rrooach
Copy link
Author

Rrooach commented Jan 7, 2025

What's your configuration? Enable smart in qemu-vexpress-a9?

Hi, I'm using the default configuration when compile in qemu-vexpree-a9: https://pastebin.com/6VHe5mtD

And for kconfig:

mainmenu "RT-Thread Project Configuration"

config BSP_DIR
    string
    option env="BSP_ROOT"
    default "."

config RTT_DIR
    string
    option env="RTT_ROOT"
    default "../.."

config PKGS_DIR
    string
    option env="PKGS_ROOT"
    default "packages"

source "$RTT_DIR/Kconfig"
source "$PKGS_DIR/Kconfig"
source "$BSP_DIR/drivers/Kconfig"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants