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] Insufficient parameter validation in the syscall implementation in RT-Thread Smart #9877

Open
x-codingman opened this issue Jan 7, 2025 · 2 comments

Comments

@x-codingman
Copy link

RT-Thread Version

v5.1.0

Hardware Type/Architectures

None

Develop Toolchain

GCC

Describe the bug

Basic Information

I am reporting a potential vulnerability that has been identified in the latest version of RT-Thread (i.e., v5.1.0). I am opening this issue for your review, as I could not find a reporting email in the security policy of this repository. Kindly let me know if you intend to request a CVE ID upon confirmation of the vulnerability. I am more than happy to provide additional details or clarification if needed.

Summary

A critical information leak vulnerability (CWE-200) has been identified in the RT-Thread system call implementations. This vulnerability allows an attacker to read sensitive memory data through an unvalidated char pointer.

Details

Vulnerable Code Location

The vulnerability resides in the rt-thread/components/lwp/lwp_syscall.c file.

rt_thread_t sys_thread_create(void *arg[])
{
    void *user_stack = 0;
    struct rt_lwp *lwp = 0;
    rt_thread_t thread = RT_NULL;
    int tid = 0;

    lwp = rt_thread_self()->lwp;
    lwp_ref_inc(lwp);
#ifdef ARCH_MM_MMU
    user_stack = lwp_map_user(lwp, 0, (size_t)arg[3], 0);
    if (!user_stack)
    {
        goto fail;
    }
    if ((tid = lwp_tid_get()) == 0)
    {
        goto fail;
    }
    thread = rt_thread_create((const char *)arg[0], // VUL: arg[0] (i.e., char * name) is not validated.
            _crt_thread_entry,
            (void *)arg[2],
            ALLOC_KERNEL_STACK_SIZE,
            (rt_uint8_t)(size_t)arg[4],
            (rt_uint32_t)(rt_size_t)arg[5]);
    if (!thread)
    {
        goto fail;
    }
    
    //omitted code
}

Vulnerability Description

When RT-Thread Smart is enabled, user and kernel spaces are isolated. However, insufficient parameter validation for arg[0], which represents the char * pointer, can lead to a potential information leak. Specifically, a malicious user thread could pass crafted parameters that cause this pointer to reference kernel memory, potentially exposing sensitive data.

Impact

This vulnerability results in an information leak, which could allow unauthorized access to sensitive kernel data.

Other additional context

No response

@x-codingman
Copy link
Author

In addition to the syscall I reported earlier (i.e., sys_thread_create), I have identified that many other syscalls (specifically 36) also have privilege escalation vulnerabilities related to parameter checking in the latest version (v5.1.0). If a user thread is compromised, this issue could lead to severe security consequences, as it breaks the user-kernel isolation.

Vulnerable Code Location

The vulnerability is present in the rt-thread/components/lwp/lwp_syscall.c file. The affected syscalls are listed below:

/* sem interfaces */
sysret_t sys_sem_delete(rt_sem_t sem)
sysret_t sys_sem_take(rt_sem_t sem, rt_int32_t time)
sysret_t sys_sem_release(rt_sem_t sem)

/* mutex interfaces */
sysret_t sys_mutex_delete(rt_mutex_t mutex)
sysret_t sys_mutex_take(rt_mutex_t mutex, rt_int32_t time)
sysret_t sys_mutex_release(rt_mutex_t mutex)

/* event interfaces */
sysret_t sys_event_delete(rt_event_t event)
sysret_t sys_event_send(rt_event_t event, rt_uint32_t set)
sysret_t sys_event_recv(rt_event_t   event,
                       rt_uint32_t  set,
                       rt_uint8_t   opt,
                       rt_int32_t   timeout,
                       rt_uint32_t *recved)

/* mb interfaces */
sysret_t sys_mb_delete(rt_mailbox_t mb)
sysret_t sys_mb_send(rt_mailbox_t mb, rt_ubase_t value)
sysret_t sys_mb_send_wait(rt_mailbox_t mb,
                         rt_ubase_t  value,
                         rt_int32_t   timeout)
sysret_t sys_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout);

/* mq interfaces */
sysret_t sys_mq_send(rt_mq_t mq, void *buffer, rt_size_t size);
sysret_t sys_mq_urgent(rt_mq_t mq, void *buffer, rt_size_t size);
sysret_t sys_mq_recv(rt_mq_t mq, void *buffer, rt_size_t size, rt_int32_t timeout);

/* rt_timer interfaces */
sysret_t sys_rt_timer_delete(rt_timer_t timer)
sysret_t sys_rt_timer_start(rt_timer_t timer)
sysret_t sys_rt_timer_stop(rt_timer_t timer)
sysret_t sys_rt_timer_control(rt_timer_t timer, int cmd, void *arg)
sysret_t sys_timer_gettime(timer_t timerid, struct itimerspec *curr_value)
sysret_t sys_timer_delete(timer_t timerid)
sysret_t sys_timer_settime(timer_t timerid, int flags,
                           const struct itimerspec *restrict new_value,
                           struct itimerspec *restrict old_value)
                           
/* thread interfaces */
sysret_t sys_thread_delete(rt_thread_t thread)
sysret_t sys_thread_startup(rt_thread_t thread)

/* shared memory interfaces */
void* sys_shmat(int id, void* shm_vaddr)
sysret_t sys_shmdt(void* shm_vaddr)

/* device interfaces */
sysret_t sys_device_init(rt_device_t dev)
sysret_t sys_device_register(rt_device_t dev, const char *name, rt_uint16_t flags)
sysret_t sys_device_control(rt_device_t dev, int cmd, void *arg)
rt_device_t sys_device_find(const char* name)
sysret_t sys_device_open(rt_device_t dev, rt_uint16_t oflag)
sysret_t sys_device_close(rt_device_t dev)
rt_ssize_t sys_device_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
rt_ssize_t sys_device_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)

Vulnerability Description

These syscalls fail to validate pointer parameters, particularly kernel object and buffer pointers. For example, in the sys_device_write syscall, it accepts a struct pointer dev and a buffer pointer buf. Both of these pointers can be crafted by a malicious user. As a result, the assertion dev->parent can be easily bypassed, and the dev structure can be manipulated to invoke a memory operation function (e.g., memset). Meanwhile, the buf pointer can be directed to kernel memory. This vulnerability allows an attacker to perform arbitrary memory read/write operations.

#define device_write    (dev->write)

rt_ssize_t rt_device_write(rt_device_t dev,
                          rt_off_t    pos,
                          const void *buffer,
                          rt_size_t   size)
{
    /* parameter check */
    RT_ASSERT(dev != RT_NULL);
    RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);

    if (dev->ref_count == 0)
    {
        rt_set_errno(-RT_ERROR);
        return 0;
    }

    /* call device_write interface */
    if (device_write != RT_NULL)
    {
        return device_write(dev, pos, buffer, size);
    }

    /* set error code */
    rt_set_errno(-RT_ENOSYS);

    return 0;
}

Impact

These vulnerabilities result in serious privilege escalation, potentially allowing unauthorized memory access and control flow hijacking.

Recommendation

I strongly recommend implementing proper validation checks for the parameters in these syscalls, particularly for kernel object pointers and buffer pointers. I am more than happy to provide additional details or clarification if needed.

@x-codingman
Copy link
Author

Please feel free to contact me at [email protected] for further information or assistance.

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

1 participant