Page MenuHomeFreeBSD

stand: userboot: improve userdisk error handling
Needs ReviewPublic

Authored by novel on Aug 29 2026, 6:49 AM.
Tags
None
Referenced Files
F174093842: D59262.diff
Wed, Sep 30, 2:11 PM
Unknown Object (File)
Tue, Sep 29, 5:45 PM
Unknown Object (File)
Sat, Sep 26, 8:40 PM
Unknown Object (File)
Thu, Sep 24, 4:43 AM
Unknown Object (File)
Wed, Sep 23, 12:56 PM
Unknown Object (File)
Tue, Sep 22, 8:31 PM
Unknown Object (File)
Mon, Sep 21, 7:57 AM
Unknown Object (File)
Sun, Sep 20, 11:12 AM
Subscribers

Details

Reviewers
manu
Group Reviewers
bhyve
Summary

Currently, userdisk_init() iterates through disks and
checks whether DIOCGSECTORSIZE and DIOCGMEDIASIZE ioctls
are available for the device. If either ioctl fails, userdisk_init()
returns ENXIO with ud_info only partially initialized.
devinit() records the failure, but loader_main() ignores
devinit()'s return value, so later code may access an
uninitialized entry.

In certain cases this code can still boot from a disk even if
userdisk_init() returns ENXIO, for example, when the first of
two disks is valid and the second errors out.

To address this issue while not breaking the current behavior, do
the following:

  • Extend the 'userdisk_info' struct with the boolean 'ud_usable' field, and mark disks that do not support the ioctls mentioned above with ud_usable = false.
  • Update userdisk_print() not to print unusable disks.
  • Update userdisk_open() to return EIO for unusable disks.
  • Update extract_currdev() to pick the first usable disk instead of the first disk. Introduce userboot_disk_firstunit() for that.

Additionally, reset counters on ud_info allocation failure to prevent
accessing unallocated data.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 76291
Build 73174: arc lint + arc unit

Event Timeline

novel requested review of this revision.Aug 29 2026, 6:49 AM

My only other thought in addition to the memset() suggestion is maybe treating mediasize == 0 as ud_usable == false vs adding a new field.

stand/userboot/userboot/userboot_disk.c
90

Can we use calloc() here, or if not, memset the array to zero after the allocation? That will simplify initialization a bit I think (and ensure the values are always deterministic).

97

With the memset suggestion above you can trim some of the assignments, and possibly refactor as:

if (CALLBACK(...) == 0) {
    ud_info[i].mediasize = mediasize;
    ud_info[i[.sectorsize = sectorsize;
    ud_info[i].ud_usable = true;
    userdisk_usable++;
}