Skip to content

sudo upscmd -u XXX -p XXX test.battery.start.XXX all type causing segmentation false #3436

@siravijbb

Description

@siravijbb

nutdrv_qx: SIGSEGV in main_instcmd() when INSTCMD sent without extra parameter

Environment

  • NUT version: 2.8.1
  • OS: Debian Trixie (Raspberry Pi, aarch64)
  • Driver: nutdrv_qx (Megatec 0.07 protocol)
  • UPS: MEC MEC0003 2000VA (VendorID: 0001, ProductID: 0000)

Description

When upscmd sends an INSTCMD with no extra parameter (e.g. test.battery.start.quick),
the driver crashes with SIGSEGV inside __vsnprintf_chk.

Steps to Reproduce

upscmd -u admin -p password nutdev1 test.battery.start.quick

Expected Behavior

Battery test executes. Driver continues running.

Actual Behavior

Driver crashes with segmentation fault.

Root Cause

In drivers/dstate.c, sock_arg() correctly sets cmdparam to NULL when no extra
parameter is present (i.e. numarg == 2), but then passes arg[2] — a garbage/uninitialized
pointer — directly to main_instcmd() instead of using cmdparam:

// dstate.c ~line 783
ret = main_instcmd(arg[1], arg[2], conn);  // BUG: arg[2] is garbage when numarg == 2

main_instcmd() in drivers/main.c then passes this garbage pointer to upsdebugx():

// main.c ~line 700
upsdebugx(2, "entering main_instcmd(%s, %s) for [%s] on %s",
        cmdname, extra, NUT_STRARG(upsname), buf);  // extra = 0x26 → SIGSEGV

vsnprintf attempts to dereference 0x26 as a string pointer → SIGSEGV.

GDB Stack Trace

Thread 1 "nutdrv_qx" received signal SIGSEGV, Segmentation fault.
#3 __vsnprintf_chk () from /lib/aarch64-linux-gnu/libc.so.6
#4 vupslog (fmt="[D2] entering main_instcmd(%s, %s) for [%s] on %s") at common.c:1283
#5 main_instcmd (cmdname="test.battery.start.quick",
extra=0x26 <error: Cannot access memory at address 0x26>,
conn=0x555569fcc0) at main.c:700
#6 sock_arg (conn=0x555569fcc0) at dstate.c:783
#7 sock_read (conn=0x555569fcc0) at dstate.c:920
#8 dstate_poll_fds () at dstate.c:1094
#9 main () at main.c:2448

Fix

drivers/dstate.c line 783 — use cmdparam (which is already correctly set to NULL
when no parameter is present) instead of raw arg[2]:

- ret = main_instcmd(arg[1], arg[2], conn);
+ ret = main_instcmd(arg[1], cmdparam, conn);

Optionally, also harden the debug log in drivers/main.c line 700:

- upsdebugx(2, "entering main_instcmd(%s, %s) for [%s] on %s",
-         cmdname, extra, NUT_STRARG(upsname), buf);
+ upsdebugx(2, "entering main_instcmd(%s, %s) for [%s] on %s",
+         cmdname, NUT_STRARG(extra), NUT_STRARG(upsname), buf);

Additional Notes

This UPS also has a related issue: the I command returns all-spaces for the firmware
field, causing nutdrv_qx Megatec protocol probe to fail with Device not supported!
even though Q1 responses are valid. Workaround: add novendor to ups.conf.
A proper fix would be adding QX_FLAG_ABSENT to the ups.firmware entry in
drivers/nutdrv_qx_megatec.c line 78.

This bug was fixed by Sonnet 4.6 ,Atleast it not crashed

Metadata

Metadata

Assignees

No one assigned

    Labels

    AIFor good or bad, machine tools are upon us. Humans are still the responsible ones.Qx protocol driverDriver based on Megatec Q<number> such as new nutdrv_qx, or obsoleted blazer and some othersUPSilon2000Devices bundled with UPSilon2000 monitoring softwareUSB VID=0001 PID=0000 (Fry's Electronics/MEC0003)Seems to be a generic USB chip interfacing many devices and protocols (Qx, USB HID, ATCL...)bugimpacts-release-2.8.1Issues reported against NUT release 2.8.1 (maybe vanilla or with minor packaging tweaks)

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions