Skip to content

fs/inode: bound fdlist_extend() against the requested row - #20000

Open
AlmAck wants to merge 1 commit into
apache:masterfrom
AlmAck:fix/fs-fdlist-extend-bound
Open

fs/inode: bound fdlist_extend() against the requested row#20000
AlmAck wants to merge 1 commit into
apache:masterfrom
AlmAck:fix/fs-fdlist-extend-bound

Conversation

@AlmAck

@AlmAck AlmAck commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Summary

fdlist_extend() grows a task group's descriptor table to row rows of
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK entries each, and guards the growth
against OPEN_MAX:

if (CONFIG_NFILE_DESCRIPTORS_PER_BLOCK * (orig_rows + 1) > OPEN_MAX)
  {
    fdlist_dump(list);
    return -EMFILE;
  }

The check sizes the table at orig_rows + 1, which assumes the caller
only ever grows by a single block. The function then allocates row
rows, so the two agree only for growth by one.

Callers do skip ahead:

  • fdlist_dup3() asks for fd2 / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + 1
  • fdlist_dupfile() asks for the row holding minfd
  • fdlist_copy() asks for the row holding a parent descriptor it is
    duplicating

Any of those can request a row well past orig_rows + 1. Such a request
passes the check, and the function then allocates and installs a table
with more than OPEN_MAX descriptors.

Check the row actually being requested instead. For single-block growth
row == orig_rows + 1 and the comparison is unchanged.

Impact

Affects the paths that grow the descriptor table by more than one block:
dup2()/dup3() with a large target descriptor, fcntl(F_DUPFD) with a
large minfd, and posix_spawn-style descriptor copying from a parent
holding a high descriptor.

With the defaults (8 per block, OPEN_MAX 256) a process holding one row
that calls dup2(fd, 400) ends up with 51 rows — 408 descriptor slots
against a 256 limit — instead of receiving -EMFILE.

This is a limit-enforcement bug rather than memory corruption: the table
stays internally consistent, it is simply larger than the process is
entitled to, along with the memory for those rows.

fdlist_extend() grows a task group's descriptor table to 'row' rows of
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK entries each, and guards the growth
against OPEN_MAX:

  if (CONFIG_NFILE_DESCRIPTORS_PER_BLOCK * (orig_rows + 1) > OPEN_MAX)

The check sizes the table at orig_rows + 1, which assumes the caller
only ever grows by a single block.  The function then allocates 'row'
rows, so the two agree only for growth by one.

Callers do skip ahead.  fdlist_dup3() asks for
fd2 / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + 1, fdlist_dupfile() for the
row holding minfd, and fdlist_copy() for the row holding a parent
descriptor it is duplicating.  Any of those can request a row well past
orig_rows + 1.

Such a request passes the check and the function then allocates and
installs a table with more than OPEN_MAX descriptors.  With the defaults
(8 per block, OPEN_MAX 256) a process holding one row that calls
dup2(fd, 400) ends up with 51 rows, or 408 descriptor slots, against a
256 limit.

Check the row actually being requested.  For single-block growth
row == orig_rows + 1 and the comparison is unchanged.

Signed-off-by: AlmAck <gluca86@gmail.com>
@github-actions github-actions Bot added Area: File System File System issues Size: XS The size of the change in this PR is very small labels Aug 29, 2026
@github-actions

Copy link
Copy Markdown

MemBrowse Memory Report

arduino-mega2560

  • flash: .text -4 B (-0.0%, 65,088 B / 262,144 B, total: 25% used)

esp32-devkitc

  • ROM: .flash.text -8 B (-0.0%, 124,892 B / 4,194,272 B, total: 3% used)
  • irom0_0_seg: .flash.text -8 B (-0.0%, 89,096 B / 3,342,304 B, total: 3% used)

hifive1-revb

  • flash: .text -4 B (-0.0%, 83,712 B / 4,194,304 B, total: 2% used)

mirtoo

  • kseg0_progmem: .text -8 B (-0.0%, 67,744 B / 131,072 B, total: 52% used)

qemu-armv8a

  • Code: .text.fdlist_extend -4 B (-0.0%, 319,808 B)

qemu-intel64

  • Code: .text -6 B (-0.0%, 8,659,708 B)

s698pm-dkit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: File System File System issues Size: XS The size of the change in this PR is very small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants