Bug 2460997 (CVE-2026-85234) - CVE-2026-85234 tftp: tftp-hpa: Denial of Service due to out-of-bounds read/write in remap engine
Summary: CVE-2026-85234 tftp: tftp-hpa: Denial of Service due to out-of-bounds read/wr...
Keywords:
Status: NEW
Alias: CVE-2026-85234
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Product Security DevOps Team
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-04-23 01:24 UTC by OSIDB Bzimport
Modified: 2026-09-15 16:15 UTC (History)
3 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed:
Embargoed:


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-04-23 01:24:09 UTC
AI_ONLY_REPORT
package: tftp-5.2-50.el10
------
Summary: Out-of-bounds read/write in genmatchstring() when RULE_INVERSE  
clears pmatch to -1 and RULE_ABORT formats custom error: when an inverse  
remap rule also aborts with a non-empty custom error message, the remap  
engine passes match offsets of `-1` into `genmatchstring()`, causing  
out-of-bounds pointer arithmetic and `memcpy` operations that can crash the  
daemon in affected deployments.
Requirements to exploit: The attacker needs network reachability to an  
`in.tftpd` deployment that was built with remap support, started with  
`m/-map-file`, and configured with an inverse (`~`) + abort (`a`) rule  
that has a non-empty custom error pattern. The attacker then only needs to  
send an unauthenticated RRQ/WRQ for a filename that does not match the rule  
regex.
Component affected: tftp-hpa (`in.tftpd` remap engine in `tftpd/remap.c`,  
`genmatchstring()` / `rewrite_string()`)
Version affected: `tftp-5.2-50.el10` (confirmed in the provided source  
snapshot); introduction commit provenance could not be determined in this  
checkout, and other versions with the same remap logic are likely affected.  
The same vulnerable logic is also present in `tftpd/remap.c.zero`.
Patch available: Proposed fix included in this report (see "Proposed Fix");  
upstream release status unknown.
Version fixed (if any already): unknown
Upstream coordination: Not yet notified.
CVSS: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H` - 7.5 (HIGH)
AV:N - Triggerable over the network via unauthenticated RRQ/WRQ requests.
AC:L - Once an affected remap deployment exists, exploitation only  
requires a non-matching filename request; no race or advanced conditions  
are needed.
PR:N - No authentication is required.
UI:N - No user interaction is required.
S:U  - The vulnerable and impacted component is the TFTP service itself.
C:N  - No direct confidentiality impact is demonstrated.
I:N  - No reliable integrity impact is demonstrated.
A:H  - The demonstrated outcome is a daemon crash / remote denial of  
service.
Impact: Moderate. This is a real remote, unauthenticated memory-safety  
flaw, but the demonstrated impact is denial of service rather than proven  
code execution or data exposure. The issue only affects deployments with  
remap support enabled, `m/-map-file` in use, and a specific inverse+abort  
rule with a non-empty custom message, which makes it less broadly  
exploitable than a default-path network service flaw.
Embargo: no
Reason: The issue is configuration-dependent and mitigation is  
straightforward: disable filename remapping, remove inverse+abort  
custom-message rules, or build without remap support until a fix is  
available. Based on the current evidence, this does not appear to require  
embargoed handling.
Acknowledgement: Aisle Research
Steps to reproduce:
1. Build `in.tftpd` with remap support enabled, or verify at runtime that  
`in.tftpd -V` reports `with remap`.
2. Create a remap file containing:
```text
a~ ^allowed/ Access denied for \0
```
3. Start the server with filename remapping enabled, for example:
```bash
in.tftpd -L -m <remap-file> -s <tftp-root>
```
4. Send an RRQ or WRQ for a filename that does not match `^allowed/`, such  
as `badfile`.
5. In the inverse path, `rewrite_string()` clears `pmatch[*]` to `-1`; the  
abort path then calls `genmatchstring()` twice to format the custom error.
6. Observe a crash or sanitizer error in `genmatchstring()` at the `memcpy`  
/ pointer arithmetic operations.
Mitigation:
Do not enable filename remapping with `m/-map-file` unless it is  
required.

If remapping is required, avoid inverse (`~`) + abort (`a`) rules that  
use a non-empty custom error message.

Where feasible, build without remap support (`--without-remap`) until a  
fix is available.




Vulnerability Details






When `rewrite_string()` takes an inverse match, it deliberately clears all  
`pmatch[]` entries to `-1`:
```c
if (ruleptr->rule_flags & RULE_INVERSE) {
int i;
for (i = 0; i < 10; i++)
pmatch[i].rm_so = pmatch[i].rm_eo = -1;
}
```
If that same rule also has `RULE_ABORT` and a non-empty `pattern`,  
`genmatchstring()` is still called twice with this invalid state:
```c
if (ruleptr->rule_flags & RULE_ABORT) {
if (ruleptr->pattern[0]) {
len = genmatchstring(NULL, ruleptr->pattern, current, pmatch,  
macrosub);
newstr = tfmalloc(len + 1);
genmatchstring(newstr, ruleptr->pattern, current, pmatch, macrosub);
*errmsg = newstr;
}
return NULL;
}
```
`genmatchstring()` assumes `pmatch[0]` contains valid offsets and uses it  
in length calculations, pointer arithmetic, and `memcpy`:
```c
endbytes = strlen(input) - pmatch[0].rm_eo;
len = pmatch[0].rm_so + endbytes;
memcpy(string, input, pmatch[0].rm_so);
memcpy(string, input + pmatch[0].rm_eo, endbytes);
```
With `pmatch[0].rm_so = pmatch[0].rm_eo = -1`, the second  
`genmatchstring()` call converts `-1` to a huge `size_t` and also forms  
`input - 1`, producing a reachable out-of-bounds read/write. The parser  
permits `` + `a` and only rejects `` + `r`, and remote filename requests  
are passed through this remap path when `m/-map-file` is in use.


Proposed Fix






```diff
diff --git a/tftpd/remap.c b/tftpd/remap.c
@@
static int genmatchstring(char *string, const char *pattern,
const char *input, const regmatch_t * pmatch,
match_pattern_callback macrosub)
{
int (*xform) (int) = xform_null;
int len = 0;
int n, mlen, sublen;
   int endbytes;
+    size_t inlen, endbytes;
+    regoff_t so, eo;
@@

   endbytes = strlen(input) - pmatch[0].rm_eo;

   len = pmatch[0].rm_so + endbytes;
+    inlen = strlen(input);
+    so = pmatch[0].rm_so;
+    eo = pmatch[0].rm_eo;
+    if (so < 0 || eo < 0 || eo < so || (size_t)so > inlen || (size_t)eo >  
inlen) {
+        so = 0;
+        eo = 0;
+    }
+    endbytes = inlen - (size_t)eo;
+    len = (int)so + (int)endbytes;
      if (string) {

       memcpy(string, input, pmatch[0].rm_so);

       string += pmatch[0].rm_so;
+        memcpy(string, input, (size_t)so);
+        string += so;
@@
      if (string) {

       memcpy(string, input + pmatch[0].rm_eo, endbytes);
+        memcpy(string, input + eo, endbytes);
          string[endbytes] = '\0';
      }
```


The same fix should also be applied to `tftpd/remap.c.zero` if that file is  
maintained in sync.
------
This report was generated using AI technology. Always review AI-generated  
content prior to use


Note You need to log in before you can comment on or make changes to this bug.