Skip to content

The array memory allocation failure in the responsive_io_status() function in modbus.c #804

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
balckgu1 opened this issue Mar 26, 2025 · 1 comment

Comments

@balckgu1
Copy link

libmodbus version

libmodbus v3.1.6

OS and/or distribution

Ubuntu 18

Environment

..

Description

The array memory allocation failure in the responsive_io_status() function in modbus.c resulted in segment errors

Actual behavior if applicable

SIGSEGV, Segmentation fault.

Expected behavior or suggestion

no crash

Steps to reproduce the behavior (commands or source code)

  1. Requires installation of the prenny library
git clone https://github.com/zardus/preeny.git
cd preeny/
make

Then find the desock.so path in the prenny installation directory

2. Add the -fsanitize=address and -g parameter at compile time
  ./autogen.sh
  ./configure --enable-static CC="gcc -fsanitize=address  -O0 -g" CXX="g++ -fsanitize=address  -O0 -g"
   make -j8
   cd tests
   gcc -g -fsanitize=address -O0  unit-test-server.c -o unit-test-server -I ../src/ ../src/.libs/libmodbus.a
3. run in GDB
    LD_PRELOAD="/home/user/preeny/src/desock.so gdb ./unit-test-server"
    run < ./poc

POC:

poc.zip

GDB output

(gdb) run < crashes/section4exp_crashes/crashes/id:000007,sig:11,src:000289,op:havoc,rep:16,hot:0:1:0
Starting program: /home/zyl/libmodbuspoc/tests/unit-test-server < crashes/section4exp_crashes/crashes/id:000007,sig:11,src:000289,op:havoc,rep:16,hot:0:1:0
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff7a00640 (LWP 14866)]
[New Thread 0x7ffff7000640 (LWP 14867)]
[Thread 0x7ffff7a00640 (LWP 14866) exited]
The client connection from 0.0.0.0 is accepted
Waiting for an indication...
<00><01><1F><03><7F><40><00><17><01><6C><00><08><01><02><00><20><40><06><EE><0F><11><00><00><08><01><FA><00><00><D7><01><01><01><01><01><01><40><00><11><00><FC><10><00><40><06><EE><01><01><40><00><09><E9><FC><00><00><4C><00><12><00><FC><FF><7F><00><00><00><08><01><00><00><08><01><FA><00><00><D7><01><01><01><01><00><E8><52>
[00][01][00][00][00][13][00][17][10][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]
Waiting for an indication...
<00><12><00><FC><00><00><D7><01><01><01><01><00>

Thread 1 "unit-test-serve" received signal SIGSEGV, Segmentation fault.
0x0000555555558245 in response_io_status (tab_io_status=0x5555e8520100 <error: Cannot access memory at address 0x5555e8520100>, address=67106584, nb=256, rsp=0x7fffffffda70 "", offset=9) at modbus.c:652
652	        one_byte |= tab_io_status[i] << shift;
(gdb) bt
#0  0x0000555555558245 in response_io_status (
    tab_io_status=0x5555e8520100 <error: Cannot access memory at address 0x5555e8520100>, address=67106584, nb=256, rsp=0x7fffffffda70 "", offset=9)
    at modbus.c:652
#1  0x0000555555558836 in modbus_reply (ctx=0x5555555642a0, 
    req=0x555555564320 "", req_length=12, mb_mapping=0x555555564430)
    at modbus.c:758
#2  0x0000555555556e47 in main (argc=1, argv=0x7fffffffdd08)
    at unit-test-server.c:183
(gdb) l
647	    /* Instead of byte (not allowed in Win32) */
648	    int one_byte = 0;
649	    int i;
650	
651	    for (i = address; i < address + nb; i++) {
652	        one_byte |= tab_io_status[i] << shift;
653	        if (shift == 7) {
654	            /* Byte is full */
655	            rsp[offset++] = one_byte;
656	            one_byte = shift = 0;
(gdb) print i
$1 = 67106584
(gdb) print address
$2 = 67106584
(gdb) print nb
$3 = 256
(gdb) print tab_io_status
$4 = (uint8_t *) 0x5555e8520100 <error: Cannot access memory at address 0x5555e8520100>
(gdb) print tab_tibs
No symbol "tab_tibs" in current context.
(gdb) bt
#0  0x0000555555558245 in response_io_status (
    tab_io_status=0x5555e8520100 <error: Cannot access memory at address 0x5555e8520100>, 
    address=67106584, nb=256, rsp=0x7fffffffda70 "", offset=9) at modbus.c:652
#1  0x0000555555558836 in modbus_reply (ctx=0x5555555642a0, req=0x555555564320 "", 
    req_length=12, mb_mapping=0x555555564430) at modbus.c:758
#2  0x0000555555556e47 in main (argc=1, argv=0x7fffffffdd08) at unit-test-server.c:183
(gdb) frame 1
#1  0x0000555555558836 in modbus_reply (ctx=0x5555555642a0, req=0x555555564320 "", 
    req_length=12, mb_mapping=0x555555564430) at modbus.c:758
758	            rsp_length = response_io_status(tab_bits, mapping_address, nb,
(gdb) list
753	                "Illegal data address 0x%0X in %s\n",
754	                mapping_address < 0 ? address : address + nb, name);
755	        } else {
756	            rsp_length = ctx->backend->build_response_basis(&sft, rsp);
757	            rsp[rsp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0);
758	            rsp_length = response_io_status(tab_bits, mapping_address, nb,
759	                                            rsp, rsp_length);
760	        }
761	    }
762	        break;
(gdb) print ctx
$5 = (modbus_t *) 0x5555555642a0
(gdb) print req
$6 = (const uint8_t *) 0x555555564320 ""
(gdb) print mb_mapping
$7 = (modbus_mapping_t *) 0x555555564430
(gdb) print tab_bits
$8 = (uint8_t *) 0x5555e8520100 <error: Cannot access memory at address 0x5555e8520100>
(gdb) print *mb_mapping
$9 = {nb_bits = 1073742081, start_bits = -67106327, nb_input_bits = 1179724, 
  start_input_bits = -8453892, nb_input_registers = 524288, 
  start_input_registers = 524544, nb_registers = 506, start_registers = 16897793, 
  tab_bits = 0x5555e8520100 <error: Cannot access memory at address 0x5555e8520100>, 
  tab_input_bits = 0x5555555644b0 "", tab_input_registers = 0x555555564520, 
  tab_registers = 0x5555555644d0}
(gdb) print nb
$10 = 256
(gdb) print mapping_address
$11 = 67106584
(gdb) print is_input
$12 = 0

ASAN output

The client connection from 127.0.0.1 is accepted
Waiting for an indication...
<00><01><1F><03><7F><40><00><17><01><6C><00><08><01><02><00><20><40><06><EE><0F><11><00><00><08><01><FA><00><00><D7><01><01><01><01><01><01><40><00><11><00><FC><10><00><40><06><EE><01><01><40><00><09><E9><FC><00><00><4C><00><12><00><FC><FF><7F><00><00><00><08><01><00><00><08><01><FA><00><00><D7><01><01><01><01><00><E8><52>

AddressSanitizer:DEADLYSIGNAL

==9284==ERROR: AddressSanitizer: SEGV on unknown address 0x605fffffffc4 (pc 0x579d8304cc88 bp 0x7ffca00734b0 sp 0x7ffca0073290 T0)
==9284==The signal is caused by a WRITE memory access.
    #0 0x579d8304cc88  (/home/zyl/libmodbus/tests/unit-test-server+0xec88)
    #1 0x579d83044e30  (/home/zyl/libmodbus/tests/unit-test-server+0x6e30)
    #2 0x78707fe29d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)
    #3 0x78707fe29e3f  (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f)
    #4 0x579d83043cc4  (/home/zyl/libmodbus/tests/unit-test-server+0x5cc4)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/home/zyl/libmodbus/tests/unit-test-server+0xec88) 
==9284==ABORTING
Aborted (core dumped)

Analysis

When is_input=1, everything is normal. When is_input=0, the first parameter passed when calling the responsive_io_status() function is the tab_fits pointer, which points to an invalid memory address and has an abnormally high value. Invalid tab_fits pointer and excessively large address parameter value caused a segment error when accessing tab_fits[i].

@psychon
Copy link

psychon commented Mar 31, 2025

libmodbus v3.1.6

Uhm... why do you keep reporting issues in this old version of the library? See e.g. #750 and #749 and #748

Until proven otherwise, I will assume that you are just reporting more ways to hit the same bugs. I will not even verify that this is fixed in commit b4ef4c1 and assume so until you prove otherwise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants