summaryrefslogtreecommitdiffstats
path: root/meta-oe
diff options
context:
space:
mode:
authorPeter Marko <peter.marko@siemens.com>2025-03-06 22:28:47 +0100
committerArmin Kuster <akuster808@gmail.com>2025-03-20 09:56:59 -0400
commitd5fb81cbfb9c4f0893daf8fca5d5a471768a5172 (patch)
tree1572bd5978c65a93a86e8e6cfb37c9ff92829613 /meta-oe
parent7e18b3fc774b7efabf9a20ae3cd6abd0e0715b59 (diff)
downloadmeta-openembedded-d5fb81cbfb9c4f0893daf8fca5d5a471768a5172.tar.gz
libmodbus: patch CVE-2024-10918
Pick commit mentioning the bug and two follow-up commits mentioning the first commit. Tested by running the test-suite (test starter scripts were copied from scarthgap version which has them working). Signed-off-by: Peter Marko <peter.marko@siemens.com> Signed-off-by: Armin Kuster <akuster808@gmail.com>
Diffstat (limited to 'meta-oe')
-rw-r--r--meta-oe/recipes-extended/libmodbus/libmodbus.inc7
-rw-r--r--meta-oe/recipes-extended/libmodbus/libmodbus/CVE-2024-10918-01.patch159
-rw-r--r--meta-oe/recipes-extended/libmodbus/libmodbus/CVE-2024-10918-02.patch113
-rw-r--r--meta-oe/recipes-extended/libmodbus/libmodbus/CVE-2024-10918-03.patch240
4 files changed, 518 insertions, 1 deletions
diff --git a/meta-oe/recipes-extended/libmodbus/libmodbus.inc b/meta-oe/recipes-extended/libmodbus/libmodbus.inc
index 0857cc455b..62252a39d2 100644
--- a/meta-oe/recipes-extended/libmodbus/libmodbus.inc
+++ b/meta-oe/recipes-extended/libmodbus/libmodbus.inc
@@ -8,7 +8,12 @@ SECTION = "libs"
8LICENSE = "LGPL-2.1-or-later" 8LICENSE = "LGPL-2.1-or-later"
9LIC_FILES_CHKSUM = "file://COPYING.LESSER;md5=4fbd65380cdd255951079008b364516c" 9LIC_FILES_CHKSUM = "file://COPYING.LESSER;md5=4fbd65380cdd255951079008b364516c"
10 10
11SRC_URI = "http://libmodbus.org/releases/${BP}.tar.gz" 11SRC_URI = " \
12 http://libmodbus.org/releases/${BP}.tar.gz \
13 file://CVE-2024-10918-01.patch \
14 file://CVE-2024-10918-02.patch \
15 file://CVE-2024-10918-03.patch \
16"
12 17
13PACKAGECONFIG ??= "" 18PACKAGECONFIG ??= ""
14PACKAGECONFIG[documentation] = "--with-documentation,--without-documentation,asciidoc-native xmlto-native" 19PACKAGECONFIG[documentation] = "--with-documentation,--without-documentation,asciidoc-native xmlto-native"
diff --git a/meta-oe/recipes-extended/libmodbus/libmodbus/CVE-2024-10918-01.patch b/meta-oe/recipes-extended/libmodbus/libmodbus/CVE-2024-10918-01.patch
new file mode 100644
index 0000000000..ae7c920525
--- /dev/null
+++ b/meta-oe/recipes-extended/libmodbus/libmodbus/CVE-2024-10918-01.patch
@@ -0,0 +1,159 @@
1From df79a02feb253c0a9a009bcdbb21e47581315111 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?St=C3=A9phane=20Raimbault?= <stephane.raimbault@gmail.com>
3Date: Fri, 18 Oct 2024 10:47:14 +0200
4Subject: [PATCH] Check length passed to modbus_reply (write_bit)
5
6The modbus_reply function is designed to receive arguments
7from modbus_receive. This patch avoid a wrong use of memcpy if
8the user chooses to inject a bad length argument.
9
10Thank you Nozomi Networks Labs Advisory for the report.
11
12CVE: CVE-2024-10918
13Upstream-Status: Backport [https://github.com/stephane/libmodbus/commit/df79a02feb253c0a9a009bcdbb21e47581315111]
14Signed-off-by: Peter Marko <peter.marko@siemens.com>
15---
16 src/modbus.c | 42 ++++++++++++++++++++++++++--------------
17 tests/unit-test-client.c | 9 +++++++--
18 tests/unit-test-server.c | 16 ++++++++++++---
19 tests/unit-test.h.in | 1 +
20 4 files changed, 49 insertions(+), 19 deletions(-)
21
22diff --git a/src/modbus.c b/src/modbus.c
23index 5a9b867..33086ec 100644
24--- a/src/modbus.c
25+++ b/src/modbus.c
26@@ -802,20 +802,33 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req,
27 ctx, &sft, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,
28 "Illegal data address 0x%0X in write_bit\n",
29 address);
30+ break;
31+ }
32+
33+ /* This check is only done here to ensure using memcpy is safe. */
34+ rsp_length = compute_response_length_from_request(ctx, (uint8_t *) req);
35+ if (rsp_length != req_length) {
36+ /* Bad use of modbus_reply */
37+ rsp_length = response_exception(ctx,
38+ &sft,
39+ MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
40+ rsp,
41+ FALSE,
42+ "Invalid request length (%d)\n",
43+ req_length);
44+ break;
45+ }
46+
47+ int data = (req[offset + 3] << 8) + req[offset + 4];
48+ if (data == 0xFF00 || data == 0x0) {
49+ mb_mapping->tab_bits[mapping_address] = data ? ON : OFF;
50+ memcpy(rsp, req, rsp_length);
51 } else {
52- int data = (req[offset + 3] << 8) + req[offset + 4];
53-
54- if (data == 0xFF00 || data == 0x0) {
55- mb_mapping->tab_bits[mapping_address] = data ? ON : OFF;
56- memcpy(rsp, req, req_length);
57- rsp_length = req_length;
58- } else {
59- rsp_length = response_exception(
60- ctx, &sft,
61- MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, FALSE,
62- "Illegal data value 0x%0X in write_bit request at address %0X\n",
63- data, address);
64- }
65+ rsp_length = response_exception(
66+ ctx, &sft,
67+ MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, FALSE,
68+ "Illegal data value 0x%0X in write_bit request at address %0X\n",
69+ data, address);
70 }
71 }
72 break;
73@@ -1687,7 +1700,8 @@ int modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec)
74 return 0;
75 }
76
77-/* Get the timeout interval used by the server to wait for an indication from a client */
78+/* Get the timeout interval used by the server to wait for an indication from a client
79+ */
80 int modbus_get_indication_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec)
81 {
82 if (ctx == NULL) {
83diff --git a/tests/unit-test-client.c b/tests/unit-test-client.c
84index a441766..50859f8 100644
85--- a/tests/unit-test-client.c
86+++ b/tests/unit-test-client.c
87@@ -362,12 +362,12 @@ int main(int argc, char *argv[])
88 ASSERT_TRUE(rc == -1 && errno == EMBXILADD, "");
89
90 rc = modbus_write_bits(ctx, 0, 1, tab_rp_bits);
91- printf("* modbus_write_coils (0): ");
92+ printf("* modbus_write_bits (0): ");
93 ASSERT_TRUE(rc == -1 && errno == EMBXILADD, "");
94
95 rc = modbus_write_bits(ctx, UT_BITS_ADDRESS + UT_BITS_NB,
96 UT_BITS_NB, tab_rp_bits);
97- printf("* modbus_write_coils (max): ");
98+ printf("* modbus_write_bits (max): ");
99 ASSERT_TRUE(rc == -1 && errno == EMBXILADD, "");
100
101 rc = modbus_write_register(ctx, 0, tab_rp_registers[0]);
102@@ -445,6 +445,11 @@ int main(int argc, char *argv[])
103 printf("* modbus_write_registers: ");
104 ASSERT_TRUE(rc == -1 && errno == EMBMDATA, "");
105
106+
107+ /** BAD USE OF REPLY FUNCTION **/
108+ rc = modbus_write_bit(ctx, UT_BITS_ADDRESS_INVALID_REQUEST_LENGTH, ON);
109+ printf("* modbus_write_bit (triggers invalid reply): ");
110+ ASSERT_TRUE(rc == -1 && errno == EMBXILVAL, "");
111 /** SLAVE REPLY **/
112 old_slave = modbus_get_slave(ctx);
113
114diff --git a/tests/unit-test-server.c b/tests/unit-test-server.c
115index 561d64d..8e28124 100644
116--- a/tests/unit-test-server.c
117+++ b/tests/unit-test-server.c
118@@ -123,9 +123,8 @@ int main(int argc, char*argv[])
119 break;
120 }
121
122- /* Special server behavior to test client */
123- if (query[header_length] == 0x03) {
124- /* Read holding registers */
125+ /** Special server behavior to test client **/
126+ if (query[header_length] == MODBUS_FC_READ_HOLDING_REGISTERS) {
127
128 if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 3)
129 == UT_REGISTERS_NB_SPECIAL) {
130@@ -178,6 +177,17 @@ int main(int argc, char*argv[])
131 }
132 continue;
133 }
134+
135+ } else if (query[header_length] == MODBUS_FC_WRITE_SINGLE_COIL) {
136+ if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 1) ==
137+ UT_BITS_ADDRESS_INVALID_REQUEST_LENGTH) {
138+ // The valid length is lengths of header + checkum + FC + address + value
139+ // (max 12)
140+ rc = 34;
141+ printf("Special modbus_write_bit detected. Inject a wrong rc value (%d) "
142+ "in modbus_reply\n",
143+ rc);
144+ }
145 }
146
147 rc = modbus_reply(ctx, query, rc, mb_mapping);
148diff --git a/tests/unit-test.h.in b/tests/unit-test.h.in
149index 5e379bb..21d09e3 100644
150--- a/tests/unit-test.h.in
151+++ b/tests/unit-test.h.in
152@@ -28,6 +28,7 @@
153 const uint16_t UT_BITS_ADDRESS = 0x130;
154 const uint16_t UT_BITS_NB = 0x25;
155 const uint8_t UT_BITS_TAB[] = { 0xCD, 0x6B, 0xB2, 0x0E, 0x1B };
156+const uint16_t UT_BITS_ADDRESS_INVALID_REQUEST_LENGTH = UT_BITS_ADDRESS + 2;
157
158 const uint16_t UT_INPUT_BITS_ADDRESS = 0x1C4;
159 const uint16_t UT_INPUT_BITS_NB = 0x16;
diff --git a/meta-oe/recipes-extended/libmodbus/libmodbus/CVE-2024-10918-02.patch b/meta-oe/recipes-extended/libmodbus/libmodbus/CVE-2024-10918-02.patch
new file mode 100644
index 0000000000..6f304a337a
--- /dev/null
+++ b/meta-oe/recipes-extended/libmodbus/libmodbus/CVE-2024-10918-02.patch
@@ -0,0 +1,113 @@
1From d8a971e04d52be16bf405b51d934a30b8aa3f2c3 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?St=C3=A9phane=20Raimbault?= <stephane.raimbault@gmail.com>
3Date: Sun, 20 Oct 2024 18:02:22 +0200
4Subject: [PATCH] Check length passed to modbus_reply (write_register)
5
6Related to df79a02feb253c.
7
8CVE: CVE-2024-10918
9Upstream-Status: Backport [https://github.com/stephane/libmodbus/commit/d8a971e04d52be16bf405b51d934a30b8aa3f2c3]
10Signed-off-by: Peter Marko <peter.marko@siemens.com>
11---
12 src/modbus.c | 38 ++++++++++++++++++++++++++------------
13 tests/unit-test-client.c | 4 ++++
14 tests/unit-test-server.c | 13 +++++++++++--
15 3 files changed, 41 insertions(+), 14 deletions(-)
16
17diff --git a/src/modbus.c b/src/modbus.c
18index 33086ec..fe192a7 100644
19--- a/src/modbus.c
20+++ b/src/modbus.c
21@@ -809,13 +809,14 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req,
22 rsp_length = compute_response_length_from_request(ctx, (uint8_t *) req);
23 if (rsp_length != req_length) {
24 /* Bad use of modbus_reply */
25- rsp_length = response_exception(ctx,
26- &sft,
27- MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
28- rsp,
29- FALSE,
30- "Invalid request length (%d)\n",
31- req_length);
32+ rsp_length =
33+ response_exception(ctx,
34+ &sft,
35+ MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
36+ rsp,
37+ FALSE,
38+ "Invalid request length used in modbus_reply (%d)\n",
39+ req_length);
40 break;
41 }
42
43@@ -841,13 +842,26 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req,
44 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,
45 "Illegal data address 0x%0X in write_register\n",
46 address);
47- } else {
48- int data = (req[offset + 3] << 8) + req[offset + 4];
49+ break;
50+ }
51
52- mb_mapping->tab_registers[mapping_address] = data;
53- memcpy(rsp, req, req_length);
54- rsp_length = req_length;
55+ rsp_length = compute_response_length_from_request(ctx, (uint8_t *) req);
56+ if (rsp_length != req_length) {
57+ /* Bad use of modbus_reply */
58+ rsp_length =
59+ response_exception(ctx,
60+ &sft,
61+ MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
62+ rsp,
63+ FALSE,
64+ "Invalid request length used in modbus_reply (%d)\n",
65+ req_length);
66+ break;
67 }
68+ int data = (req[offset + 3] << 8) + req[offset + 4];
69+
70+ mb_mapping->tab_registers[mapping_address] = data;
71+ memcpy(rsp, req, rsp_length);
72 }
73 break;
74 case MODBUS_FC_WRITE_MULTIPLE_COILS: {
75diff --git a/tests/unit-test-client.c b/tests/unit-test-client.c
76index 50859f8..84d5840 100644
77--- a/tests/unit-test-client.c
78+++ b/tests/unit-test-client.c
79@@ -450,6 +450,10 @@ int main(int argc, char *argv[])
80 rc = modbus_write_bit(ctx, UT_BITS_ADDRESS_INVALID_REQUEST_LENGTH, ON);
81 printf("* modbus_write_bit (triggers invalid reply): ");
82 ASSERT_TRUE(rc == -1 && errno == EMBXILVAL, "");
83+
84+ rc = modbus_write_register(ctx, UT_REGISTERS_ADDRESS_SPECIAL, 0x42);
85+ printf("* modbus_write_register (triggers invalid reply): ");
86+ ASSERT_TRUE(rc == -1 && errno == EMBXILVAL, "");
87 /** SLAVE REPLY **/
88 old_slave = modbus_get_slave(ctx);
89
90diff --git a/tests/unit-test-server.c b/tests/unit-test-server.c
91index 8e28124..fc7ceb3 100644
92--- a/tests/unit-test-server.c
93+++ b/tests/unit-test-server.c
94@@ -184,8 +184,17 @@ int main(int argc, char*argv[])
95 // The valid length is lengths of header + checkum + FC + address + value
96 // (max 12)
97 rc = 34;
98- printf("Special modbus_write_bit detected. Inject a wrong rc value (%d) "
99- "in modbus_reply\n",
100+ printf(
101+ "Special modbus_write_bit detected. Inject a wrong length value (%d) "
102+ "in modbus_reply\n",
103+ rc);
104+ }
105+ } else if (query[header_length] == MODBUS_FC_WRITE_SINGLE_REGISTER) {
106+ if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 1) ==
107+ UT_REGISTERS_ADDRESS_SPECIAL) {
108+ rc = 45;
109+ printf("Special modbus_write_register detected. Inject a wrong length "
110+ "value (%d) in modbus_reply\n",
111 rc);
112 }
113 }
diff --git a/meta-oe/recipes-extended/libmodbus/libmodbus/CVE-2024-10918-03.patch b/meta-oe/recipes-extended/libmodbus/libmodbus/CVE-2024-10918-03.patch
new file mode 100644
index 0000000000..ccc9cfa379
--- /dev/null
+++ b/meta-oe/recipes-extended/libmodbus/libmodbus/CVE-2024-10918-03.patch
@@ -0,0 +1,240 @@
1From 81bf713cf029bfa5b5da87b945c1e8817b4398f9 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?St=C3=A9phane=20Raimbault?= <stephane.raimbault@gmail.com>
3Date: Mon, 21 Oct 2024 17:32:39 +0200
4Subject: [PATCH] Fix request length check in modbus_reply in RTU
5
6- rename internal *_prepare_response_tid to *_get_response_tid
7- change signature, don't need req length anymore
8- remove misleading modification of req_length
9- check of req length before use in memcpy for mask write register
10
11Related to df79a02feb253c0a9a009bcdbb21e47581315111
12
13CVE: CVE-2024-10918
14Upstream-Status: Backport [https://github.com/stephane/libmodbus/commit/81bf713cf029bfa5b5da87b945c1e8817b4398f9]
15Signed-off-by: Peter Marko <peter.marko@siemens.com>
16---
17 src/modbus-private.h | 2 +-
18 src/modbus-rtu.c | 5 ++--
19 src/modbus-tcp.c | 7 ++---
20 src/modbus.c | 71 ++++++++++++++++++++++++++++----------------
21 4 files changed, 52 insertions(+), 33 deletions(-)
22
23diff --git a/src/modbus-private.h b/src/modbus-private.h
24index 6cd3424..ea83187 100644
25--- a/src/modbus-private.h
26+++ b/src/modbus-private.h
27@@ -73,7 +73,7 @@ typedef struct _modbus_backend {
28 int (*build_request_basis) (modbus_t *ctx, int function, int addr,
29 int nb, uint8_t *req);
30 int (*build_response_basis) (sft_t *sft, uint8_t *rsp);
31- int (*prepare_response_tid) (const uint8_t *req, int *req_length);
32+ int (*get_response_tid)(const uint8_t *req);
33 int (*send_msg_pre) (uint8_t *req, int req_length);
34 ssize_t (*send) (modbus_t *ctx, const uint8_t *req, int req_length);
35 int (*receive) (modbus_t *ctx, uint8_t *req);
36diff --git a/src/modbus-rtu.c b/src/modbus-rtu.c
37index b774923..8b5ee08 100644
38--- a/src/modbus-rtu.c
39+++ b/src/modbus-rtu.c
40@@ -145,9 +145,8 @@ static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)
41 return (crc_hi << 8 | crc_lo);
42 }
43
44-static int _modbus_rtu_prepare_response_tid(const uint8_t *req, int *req_length)
45+static int _modbus_rtu_get_response_tid(const uint8_t *req)
46 {
47- (*req_length) -= _MODBUS_RTU_CHECKSUM_LENGTH;
48 /* No TID */
49 return 0;
50 }
51@@ -1204,7 +1203,7 @@ const modbus_backend_t _modbus_rtu_backend = {
52 _modbus_set_slave,
53 _modbus_rtu_build_request_basis,
54 _modbus_rtu_build_response_basis,
55- _modbus_rtu_prepare_response_tid,
56+ _modbus_rtu_get_response_tid,
57 _modbus_rtu_send_msg_pre,
58 _modbus_rtu_send,
59 _modbus_rtu_receive,
60diff --git a/src/modbus-tcp.c b/src/modbus-tcp.c
61index f8ef4e8..4ee82a7 100644
62--- a/src/modbus-tcp.c
63+++ b/src/modbus-tcp.c
64@@ -146,8 +146,7 @@ static int _modbus_tcp_build_response_basis(sft_t *sft, uint8_t *rsp)
65 return _MODBUS_TCP_PRESET_RSP_LENGTH;
66 }
67
68-
69-static int _modbus_tcp_prepare_response_tid(const uint8_t *req, int *req_length)
70+static int _modbus_tcp_get_response_tid(const uint8_t *req)
71 {
72 return (req[0] << 8) + req[1];
73 }
74@@ -752,7 +751,7 @@ const modbus_backend_t _modbus_tcp_backend = {
75 _modbus_set_slave,
76 _modbus_tcp_build_request_basis,
77 _modbus_tcp_build_response_basis,
78- _modbus_tcp_prepare_response_tid,
79+ _modbus_tcp_get_response_tid,
80 _modbus_tcp_send_msg_pre,
81 _modbus_tcp_send,
82 _modbus_tcp_receive,
83@@ -775,7 +774,7 @@ const modbus_backend_t _modbus_tcp_pi_backend = {
84 _modbus_set_slave,
85 _modbus_tcp_build_request_basis,
86 _modbus_tcp_build_response_basis,
87- _modbus_tcp_prepare_response_tid,
88+ _modbus_tcp_get_response_tid,
89 _modbus_tcp_send_msg_pre,
90 _modbus_tcp_send,
91 _modbus_tcp_receive,
92diff --git a/src/modbus.c b/src/modbus.c
93index fe192a7..e3737bb 100644
94--- a/src/modbus.c
95+++ b/src/modbus.c
96@@ -125,7 +125,7 @@ int modbus_flush(modbus_t *ctx)
97 return rc;
98 }
99
100-/* Computes the length of the expected response */
101+/* Computes the length of the expected response including checksum */
102 static unsigned int compute_response_length_from_request(modbus_t *ctx, uint8_t *req)
103 {
104 int length;
105@@ -366,8 +366,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
106 length_to_read = ctx->backend->header_length + 1;
107
108 if (msg_type == MSG_INDICATION) {
109- /* Wait for a message, we don't know when the message will be
110- * received */
111+ /* Wait for a message, we don't know when the message will be received */
112 if (ctx->indication_timeout.tv_sec == 0 && ctx->indication_timeout.tv_usec == 0) {
113 /* By default, the indication timeout isn't set */
114 p_tv = NULL;
115@@ -725,7 +724,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req,
116
117 sft.slave = slave;
118 sft.function = function;
119- sft.t_id = ctx->backend->prepare_response_tid(req, &req_length);
120+ sft.t_id = ctx->backend->get_response_tid(req);
121
122 /* Data are flushed on illegal number of values errors. */
123 switch (function) {
124@@ -800,7 +799,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req,
125 if (mapping_address < 0 || mapping_address >= mb_mapping->nb_bits) {
126 rsp_length = response_exception(
127 ctx, &sft, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,
128- "Illegal data address 0x%0X in write_bit\n",
129+ "Illegal data address 0x%0X in write bit\n",
130 address);
131 break;
132 }
133@@ -809,20 +808,26 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req,
134 rsp_length = compute_response_length_from_request(ctx, (uint8_t *) req);
135 if (rsp_length != req_length) {
136 /* Bad use of modbus_reply */
137- rsp_length =
138- response_exception(ctx,
139- &sft,
140- MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
141- rsp,
142- FALSE,
143- "Invalid request length used in modbus_reply (%d)\n",
144- req_length);
145+ rsp_length = response_exception(
146+ ctx,
147+ &sft,
148+ MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
149+ rsp,
150+ FALSE,
151+ "Invalid request length in modbus_reply to write bit (%d)\n",
152+ req_length);
153 break;
154 }
155
156+ /* Don't copy the CRC, if any, it will be computed later (even if identical to the
157+ * request) */
158+ rsp_length -= ctx->backend->checksum_length;
159+
160 int data = (req[offset + 3] << 8) + req[offset + 4];
161 if (data == 0xFF00 || data == 0x0) {
162+ /* Apply the change to mapping */
163 mb_mapping->tab_bits[mapping_address] = data ? ON : OFF;
164+ /* Prepare response */
165 memcpy(rsp, req, rsp_length);
166 } else {
167 rsp_length = response_exception(
168@@ -848,19 +853,21 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req,
169 rsp_length = compute_response_length_from_request(ctx, (uint8_t *) req);
170 if (rsp_length != req_length) {
171 /* Bad use of modbus_reply */
172- rsp_length =
173- response_exception(ctx,
174- &sft,
175- MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
176- rsp,
177- FALSE,
178- "Invalid request length used in modbus_reply (%d)\n",
179- req_length);
180+ rsp_length = response_exception(
181+ ctx,
182+ &sft,
183+ MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
184+ rsp,
185+ FALSE,
186+ "Invalid request length in modbus_reply to write register (%d)\n",
187+ req_length);
188 break;
189 }
190 int data = (req[offset + 3] << 8) + req[offset + 4];
191
192 mb_mapping->tab_registers[mapping_address] = data;
193+
194+ rsp_length -= ctx->backend->checksum_length;
195 memcpy(rsp, req, rsp_length);
196 }
197 break;
198@@ -966,8 +973,23 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req,
199
200 data = (data & and) | (or & (~and));
201 mb_mapping->tab_registers[mapping_address] = data;
202- memcpy(rsp, req, req_length);
203- rsp_length = req_length;
204+
205+ rsp_length = compute_response_length_from_request(ctx, (uint8_t *) req);
206+ if (rsp_length != req_length) {
207+ /* Bad use of modbus_reply */
208+ rsp_length = response_exception(ctx,
209+ &sft,
210+ MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
211+ rsp,
212+ FALSE,
213+ "Invalid request length in modbus_reply "
214+ "to mask write register (%d)\n",
215+ req_length);
216+ break;
217+ }
218+
219+ rsp_length -= ctx->backend->checksum_length;
220+ memcpy(rsp, req, rsp_length);
221 }
222 }
223 break;
224@@ -1037,7 +1059,6 @@ int modbus_reply_exception(modbus_t *ctx, const uint8_t *req,
225 int function;
226 uint8_t rsp[MAX_MESSAGE_LENGTH];
227 int rsp_length;
228- int dummy_length = 99;
229 sft_t sft;
230
231 if (ctx == NULL) {
232@@ -1051,7 +1072,7 @@ int modbus_reply_exception(modbus_t *ctx, const uint8_t *req,
233
234 sft.slave = slave;
235 sft.function = function + 0x80;
236- sft.t_id = ctx->backend->prepare_response_tid(req, &dummy_length);
237+ sft.t_id = ctx->backend->get_response_tid(req);
238 rsp_length = ctx->backend->build_response_basis(&sft, rsp);
239
240 /* Positive exception code */