Package: at
Version: 3.2.5

`at` crashes with a segmentation fault when invoked with a malformed environment entry (missing '='), potentially leaving partially written job files under /var/spool/at.

Proof of concept in python:

```
import ctypes, os
libc = ctypes.CDLL(None)
argv = (ctypes.c_char_p * 6)(b"/usr/bin/at", b"now", b"+", b"1", b"minute", None) env = (ctypes.c_char_p * 8)(b"PATH=/usr/bin'", b"HOME=/tmp", b"USER=testuser", b"MALFORMED", b"NORMAL=value", b"SHELL=/bin/sh", None) # A entry with no = is present libc.execve(b"/usr/bin/at", argv, env) # should segfault (this is the issue)
```

```
import ctypes, os
libc = ctypes.CDLL(None)
argv = (ctypes.c_char_p * 6)(b"/usr/bin/at", b"now", b"+", b"1", b"minute", None) env = (ctypes.c_char_p * 8)(b"PATH=/usr/bin'", b"HOME=/tmp", b"USER=testuser", b"NOTMALFORMED=1", b"NORMAL=value", b"SHELL=/bin/sh", None) # All entries are proper key pair values
libc.execve(b"/usr/bin/at", argv, env) # should not segfault
```

Stack trace extracted from `coredumpctl debug`

Stack trace of thread 152251:
                #0  0x00007f26db3e1d49 __memcpy_evex_unaligned_erms (libc.so.6 + 0x157d49)                 #1  0x00007f26db2f3071 _IO_file_xsputn@@GLIBC_2.2.5 (libc.so.6 + 0x69071)
                #2  0x00007f26db2e6893 _IO_fwrite (libc.so.6 + 0x5c893)
                #3  0x0000557032b63c67 writefile (at + 0x3c67)
                #4  0x0000557032b62a06 main (at + 0x2a06)
                #5  0x00007f26db28d248 __libc_start_call_main (libc.so.6 + 0x3248)                 #6  0x00007f26db28d30b __libc_start_main@@GLIBC_2.34 (libc.so.6 + 0x330b)
                #7  0x0000557032b62d25 _start (at + 0x2d25)


I believe this is happening due to at.c line 434 in master branch of salsa.debian.org/debian/at

```

    eqp = strchr(*atenv, '=');
    if (ap == NULL)
        eqp = *atenv;
    else {
        unsigned int i;
        for (i = 0; i < sizeof(no_export) / sizeof(no_export[0]); i++) {
        export = export
            && (strncmp(*atenv, no_export[i],
                (size_t) (eqp - *atenv)) != 0);
        }
        eqp++;
    }

    if (export) {
        fwrite(*atenv, sizeof(char), eqp - *atenv, fp);

```


When strchr() returns NULL for an entry without a '=', eqp becomes NULL and `eqp - *atenv` underflows to a large size_t, causing `fwrite()` to attempt to write an excessive number of bytes and eventually crash (SIGSEGV).

Tested on,

* Fedora Linux 41, Linux 6.12.11-200.fc41.x86_64 and libc 2.40

* Debian GNU/Linux 12 (bookworm), Linux 6.12.11-200.fc41.x86_64 and libc 2.36


Please assign a CVE if appropriate

I would like to be credited as: Tarith Jayasooriya <[email protected]>


Regards,
Tarith

Reply via email to