Skip to contentSkip to conversation

block: partition: aix: bound LV name formatting

PATCH Superseded Ren Wei 3 participants 4 messages Jun 26 – Jun 28 1 message not in the archive Block layer

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Ren Wei

author
#1 lore raw

PATCH 1/1 block: partition: aix: bound LV name formatting

In reply to a message not in the archive

From: Zhiling Zou <[email protected]>

AIX logical volume names are stored on disk as fixed-size fields. The partition parser reads them into struct lvname, but later formats the fields with %s. If an on-disk name is not NUL-terminated, the string formatting code can keep reading past the end of the 64-byte name field.

Limit the formatted string length to the size of the on-disk name field when printing AIX logical volume names.

Fixes 6ceea22bbbc8 ("partitions: add aix lvm partition support files")
Assisted-by Codex:gpt-5.4
---
 block/partitions/aix.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
block/partitions/aix.c +4 -2
index f3c4174e003e..de19c19c85b2 100644
@@ -261,7 +261,8 @@ int aix_partition(struct parsed_partitions *state)
 				put_partition(state, lv_ix + 1,
 				  (i + 1 - lp_ix) * pp_blocks_size + psn_part1,
 				  lvip[lv_ix].pps_per_lv * pp_blocks_size);
-				seq_buf_printf(&state->pp_buf, " <%s>\n",
+				seq_buf_printf(&state->pp_buf, " <%.*s>\n",
+					       (int)sizeof(n[lv_ix].name),
 					       n[lv_ix].name);
 				lvip[lv_ix].lv_is_contiguous = 1;
 				ret = 1;
@@ -273,7 +274,8 @@ int aix_partition(struct parsed_partitions *state)
 			if (lvip[i].pps_found && !lvip[i].lv_is_contiguous) {
 				char tmp[sizeof(n[i].name) + 1]; // null char
 
-				snprintf(tmp, sizeof(tmp), "%s", n[i].name);
+				snprintf(tmp, sizeof(tmp), "%.*s",
+					 (int)sizeof(n[i].name), n[i].name);
 				pr_warn("partition %s (%u pp's found) is "
 					"not contiguous\n",
 					tmp, lvip[i].pps_found);
Signature · 1 line
2.43.0
#2 lore raw

Hello Ren Wei,

Quoted 36 lines · Ren Wei

From: Zhiling Zou <[email protected]>

AIX logical volume names are stored on disk as fixed-size fields. The partition parser reads them into struct lvname, but later formats the fields with %s. If an on-disk name is not NUL-terminated, the string formatting code can keep reading past the end of the 64-byte name field.

Limit the formatted string length to the size of the on-disk name field when printing AIX logical volume names.

Fixes 6ceea22bbbc8 ("partitions: add aix lvm partition support files")
Assisted-by Codex:gpt-5.4
---
 block/partitions/aix.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
block/partitions/aix.c +2 -1
index f3c4174e003e..de19c19c85b2 100644
@@ -261,7 +261,8 @@ int aix_partition(struct parsed_partitions *state)
 				put_partition(state, lv_ix + 1,
 				  (i + 1 - lp_ix) * pp_blocks_size + psn_part1,
 				  lvip[lv_ix].pps_per_lv * pp_blocks_size);
-				seq_buf_printf(&state->pp_buf, " <%s>\n",
+				seq_buf_printf(&state->pp_buf, " <%.*s>\n",
+					       (int)sizeof(n[lv_ix].name),
 					       n[lv_ix].name);
 				lvip[lv_ix].lv_is_contiguous = 1;
 				ret = 1;

block/partitions/aix.c int aix_partition(struct parsed_partitions *state) · line 278

Quoted 6 lines
block/partitions/aix.c +2 -1
@@ -273,7 +274,8 @@ int aix_partition(struct parsed_partitions *state)
 			if (lvip[i].pps_found && !lvip[i].lv_is_contiguous) {
 				char tmp[sizeof(n[i].name) + 1]; // null char
 
-				snprintf(tmp, sizeof(tmp), "%s", n[i].name);
+				snprintf(tmp, sizeof(tmp), "%.*s",
+					 (int)sizeof(n[i].name), n[i].name);

Is this change necessary ? snprintf always adds a NULL terminator and truncates the input if needed, isn't it ?

Quoted 5 lines
block/partitions/aix.c +0 -0
 				pr_warn("partition %s (%u pp's found) is "
 					"not contiguous\n",
 					tmp, lvip[i].pps_found);
Signature · 1 line
2.43.0

Best Regards

Philippe De Muyter

#3 lore raw
Quoted 43 lines · Philippe De Muyter

Hello Ren Wei,

Quoted 39 lines · Ren Wei

From: Zhiling Zou <[email protected]>

AIX logical volume names are stored on disk as fixed-size fields. The partition parser reads them into struct lvname, but later formats the fields with %s. If an on-disk name is not NUL-terminated, the string formatting code can keep reading past the end of the 64-byte name field.

Limit the formatted string length to the size of the on-disk name field when printing AIX logical volume names.

Fixes 6ceea22bbbc8 ("partitions: add aix lvm partition support files")
Assisted-by Codex:gpt-5.4
---
 block/partitions/aix.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
block/partitions/aix.c +2 -1
index f3c4174e003e..de19c19c85b2 100644
@@ -261,7 +261,8 @@ int aix_partition(struct parsed_partitions *state)
                              put_partition(state, lv_ix + 1,
                                (i + 1 - lp_ix) * pp_blocks_size + psn_part1,
                                lvip[lv_ix].pps_per_lv * pp_blocks_size);
-                             seq_buf_printf(&state->pp_buf, " <%s>\n",
+                             seq_buf_printf(&state->pp_buf, " <%.*s>\n",
+                                            (int)sizeof(n[lv_ix].name),
                                             n[lv_ix].name);
                              lvip[lv_ix].lv_is_contiguous = 1;
                              ret = 1;
@@ -273,7 +274,8 @@ int aix_partition(struct parsed_partitions *state)
                      if (lvip[i].pps_found && !lvip[i].lv_is_contiguous) {
                              char tmp[sizeof(n[i].name) + 1]; // null char
 
Quoted 7 lines

block/partitions/aix.c int aix_partition(struct parsed_partitions *state) · line 278

Quoted 3 lines
block/partitions/aix.c +2 -1
-                             snprintf(tmp, sizeof(tmp), "%s", n[i].name);
+                             snprintf(tmp, sizeof(tmp), "%.*s",
+                                      (int)sizeof(n[i].name), n[i].name);

Is this change necessary ? snprintf always adds a NULL terminator and truncates the input if needed, isn't it ?

Yes, snprintf() guarantees that the destination buffer is NUL-terminated and truncates the output.

However, with %s and no precision, snprintf() still treats n[i].name as a NUL-terminated source string. If the on-disk fixed-size name field is not NUL-terminated, snprintf() can keep reading past the end of n[i].name while looking for the terminator, before truncating the output into tmp.

So the issue is not an overflow of tmp, but an out-of-bounds read from the fixed-width source field. The precision is needed to bound that source read to sizeof(n[i].name).

Quoted 9 lines
Quoted 5 lines
block/partitions/aix.c +0 -1
                              pr_warn("partition %s (%u pp's found) is "
                                      "not contiguous\n",
                                      tmp, lvip[i].pps_found);
--

2.43.0

Best Regards

Philippe De Muyter

#4 lore raw

Hello tt roxy,

Quoted 27 lines · tt roxy
Quoted 9 lines · Philippe De Muyter

Hello Ren Wei,

Quoted 5 lines · Ren Wei

From: Zhiling Zou <[email protected]>

block/partitions/aix.c +0 -0
@@ -273,7 +274,8 @@ int aix_partition(struct parsed_partitions *state)
                      if (lvip[i].pps_found && !lvip[i].lv_is_contiguous) {
                              char tmp[sizeof(n[i].name) + 1]; // null char
 
Quoted 7 lines

block/partitions/aix.c int aix_partition(struct parsed_partitions *state) · line 278

Quoted 3 lines
block/partitions/aix.c +2 -1
-                             snprintf(tmp, sizeof(tmp), "%s", n[i].name);
+                             snprintf(tmp, sizeof(tmp), "%.*s",
+                                      (int)sizeof(n[i].name), n[i].name);

Is this change necessary ? snprintf always adds a NULL terminator and truncates the input if needed, isn't it ?

Yes, snprintf() guarantees that the destination buffer is NUL-terminated and truncates the output.

However, with %s and no precision, snprintf() still treats n[i].name as a NUL-terminated source string. If the on-disk fixed-size name field is not NUL-terminated, snprintf() can keep reading past the end of n[i].name while looking for the terminator, before truncating the output into tmp.

Quoted 8 lines

So the issue is not an overflow of tmp, but an out-of-bounds read from the fixed-width source field. The precision is needed to bound that source read to sizeof(n[i].name).

Quoted 4 lines
Quoted 4 lines
block/partitions/aix.c +0 -1
                              pr_warn("partition %s (%u pp's found) is "
                                      "not contiguous\n",
                                      tmp, lvip[i].pps_found);
--

Actually the 'tmp' buffer is not needed. Printing directky n[i].name with '%.*s' in pr_warn would be enough to fix the problem IMHO.

Philippe