#1117956 Bug: at: segmentation fault on malformed environment entry (possible minimal security issue) - Package: at 3.2.5

Package:
at
Source:
at
Description:
Delayed job execution and batch processing
Submitter:
Tarith Jayasooriya
Date:
2025-10-12 19:55:03 UTC
Severity:
normal
#1117956#5
Date:
2025-10-12 19:52:57 UTC
From:
To:
`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 <contact@tarith.dev>


Regards,
Tarith