bug#81016: Segmentation Fault using Address Sanitizer Compilation

Daniel Anderson <[email protected]> Sun, 10 May 2026 20:24:31 -0400
Newsgroups gmane.comp.gnu.parted.bugs
Message-ID <[email protected]>
--Apple-Mail=_F273FE5A-5D30-45A0-A455-80B40DC5663E
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=utf-8

There=E2=80=99s a null pointer dereference bug in libparted/libparted.c =
that can cause a seg fault.  I repreduced it by compiling under Adress =
Sanitizer.

Specificly on line 239+  This part here:

```C
ped_malloc (size_t size)
{
	void*		mem;

	mem =3D (void*) malloc (size);
	if (!mem) {
		ped_exception_throw (PED_EXCEPTION_FATAL, =
PED_EXCEPTION_CANCEL,
				     _("Out of memory."));
		return NULL;
	}

	return mem;
}

void* ped_calloc (size_t size)
{
        void* buf =3D ped_malloc (size);

        memset (buf, 0, size);

        return buf;
}
```


You can see above that ped_malloc can return NULL in line 248 of the =
code but ped_calloc does not check for NULL values.  It then calls =
memset on a NULL resulting in the seg fault.

I freshly compiled under Raspbian on Raspberry Pi 5 (aarch64) to show =
the bug works.  I=E2=80=99m attaching a file, poc.sh, to trigger the seg =
fault under a parted build with ASAN enabled.  I=E2=80=99m also =
attaching the patch.

You run the POC after making sure you have the ASAN build in your path, =
like:

```$ ASAN_PRELOAD=3D"$ASAN" =
LD_LIBRARY_PATH=3D/home/dan/local/parted-asan/lib =
PARTED_BIN=3D/home/dan/local/parted-asan/sbin/parted ./poc.sh```

I also ran the POC against the patched code and the patch works!

Full disclosure I found this but using the N184 bug and security =
vulnerability scanner.  I wrote the bug report and patch myself.  You =
can read more about N184 here: https://github.com/MillaFleurs/N184

Let me know if you have any questions.

Thanks,

Dan




--Apple-Mail=_F273FE5A-5D30-45A0-A455-80B40DC5663E
Content-Disposition: attachment;
	filename=patch.diff
Content-Type: application/octet-stream;
	x-unix-mode=0644;
	name="patch.diff"
Content-Transfer-Encoding: 7bit

--- a/libparted/libparted.c
+++ b/libparted/libparted.c
@@ -255,6 +255,8 @@ void* ped_calloc (size_t size)
 {
         void* buf = ped_malloc (size);
 
+        if (buf == NULL)
+                return NULL;
         memset (buf, 0, size);
 
         return buf;

--Apple-Mail=_F273FE5A-5D30-45A0-A455-80B40DC5663E
Content-Disposition: attachment;
	filename=poc.sh
Content-Type: application/octet-stream;
	x-unix-mode=0755;
	name="poc.sh"
Content-Transfer-Encoding: 7bit

#!/bin/sh
set -eu

case "$(uname -s)" in
	Linux) ;;
	*)
		echo "PoC requires Linux LD_PRELOAD. Run this on Debian/Linux."
		exit 0
		;;
esac

parted_bin=${PARTED_BIN:-}
if [ -z "$parted_bin" ]; then
	if which parted >/dev/null 2>&1; then
		parted_bin=$(which parted)
	fi
fi

if [ -z "$parted_bin" ]; then
	echo "PoC skipped: set PARTED_BIN to a GNU parted binary, e.g. /usr/sbin/parted."
	exit 0
fi

cc_bin=${CC:-cc}
if ! which "$cc_bin" >/dev/null 2>&1; then
	echo "PoC requires a C compiler. Set CC=/path/to/cc if needed."
	exit 1
fi

if ! which python3 >/dev/null 2>&1; then
	echo "PoC requires python3."
	exit 1
fi

tmp=$(mktemp -d "${TMPDIR:-/tmp}/parted-ped-calloc-poc.XXXXXX")
trap 'rm -rf "$tmp"' EXIT
lib="$tmp/fail-ped-malloc.so"
img=${IMAGE_PATH:-./ped-calloc-null-mbr.img}

cat >"$tmp/fail-ped-malloc.c" <<'C'
#define _GNU_SOURCE
#include <dlfcn.h>
#include <errno.h>
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static void *(*real_ped_malloc)(size_t);
static int failed;

static int
stack_has_ped_calloc(void)
{
	void *frames[48];
	int n = backtrace(frames, 48);

	for (int i = 0; i < n; i++) {
		Dl_info info;
		if (dladdr(frames[i], &info) == 0 || info.dli_sname == NULL)
			continue;
		if (strstr(info.dli_sname, "ped_calloc") != NULL)
			return 1;
	}

	return 0;
}

void *
ped_malloc(size_t size)
{
	if (real_ped_malloc == NULL) {
		real_ped_malloc = dlsym(RTLD_NEXT, "ped_malloc");
		if (real_ped_malloc == NULL) {
			fprintf(stderr, "fail-ped-malloc: could not find real ped_malloc\n");
			_exit(127);
		}
	}

	if (!failed && stack_has_ped_calloc()) {
		failed = 1;
		errno = ENOMEM;
		fprintf(stderr,
		        "fail-ped-malloc: returning NULL for ped_malloc(%zu) from ped_calloc stack\n",
		        size);
		return NULL;
	}

	return real_ped_malloc(size);
}
C

"$cc_bin" -shared -fPIC "$tmp/fail-ped-malloc.c" -o "$lib" -ldl

python3 - "$img" <<'PY'
import struct
import sys

img = sys.argv[1]
sector_size = 512
sectors = 20480

with open(img, "wb") as f:
    f.truncate(sectors * sector_size)
    mbr = bytearray(sector_size)
    # One normal Linux partition. Parsing it reaches msdos_partition_new(),
    # which allocates DosPartitionData with ped_calloc().
    mbr[446:462] = struct.pack(
        "<B3sB3sII",
        0x00,
        b"\x00\x02\x00",
        0x83,
        b"\xff\xff\xff",
        2048,
        4096,
    )
    mbr[510:512] = b"\x55\xaa"
    f.seek(0)
    f.write(mbr)

print(f"created {img}")
print("image layout: raw MBR disk image with one Linux partition")
PY

echo
echo "Running with ped_malloc failure injected only from a ped_calloc() call stack:"
echo "  $parted_bin -s $img unit s print"

preload=$lib
if [ -n "${ASAN_PRELOAD:-}" ]; then
	preload="$ASAN_PRELOAD:$preload"
elif [ -n "${LD_PRELOAD:-}" ]; then
	preload="$LD_PRELOAD:$preload"
fi

set +e
LD_PRELOAD="$preload" \
ASAN_OPTIONS="${ASAN_OPTIONS:-abort_on_error=1:symbolize=1}" \
	"$parted_bin" -s "$img" unit s print >"$tmp/stdout" 2>"$tmp/stderr"
status=$?
set -e

echo "parted exit status: $status"
if [ -s "$tmp/stdout" ]; then
	echo "stdout:"
	sed 's/^/  /' "$tmp/stdout"
fi
if [ -s "$tmp/stderr" ]; then
	echo "stderr:"
	sed 's/^/  /' "$tmp/stderr"
fi

if ! grep -q 'fail-ped-malloc: returning NULL' "$tmp/stderr"; then
	echo "Bug not triggered: ped_malloc failure did not occur from a visible ped_calloc() stack."
	echo "Use an unstripped/shared GNU Parted build, preferably the ASAN build from ./asan-build-and-run.sh."
	exit 1
fi

case "$status" in
	139|134)
		echo "BUG TRIGGERED: real GNU Parted crashed after ped_calloc() received NULL."
		exit 0
		;;
	*)
		if grep -qi 'AddressSanitizer\|SEGV\|segmentation fault\|null pointer' "$tmp/stderr" 2>/dev/null; then
			echo "BUG TRIGGERED: sanitizer/crash text was reported."
			exit 0
		fi
		echo "Malloc failure was injected, but this binary did not crash in the expected way."
		exit 1
		;;
esac

--Apple-Mail=_F273FE5A-5D30-45A0-A455-80B40DC5663E
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=us-ascii


created ./ped-calloc-null-mbr.img image layout: raw MBR disk image with =
one Linux partition Running with ped_malloc failure injected only from a =
ped_calloc() call stack: /home/dan/local/parted-asan/sbin/parted -s =
./ped-calloc-null-mbr.img unit s print parted exit status: 139 stderr: =
fail-ped-malloc: returning NULL for ped_malloc(16) from ped_calloc stack =
You found a bug in GNU Parted! Here's what you have to do: Don't panic! =
The bug has most likely not affected any of your data. Help us to fix =
this bug by doing the following: Check whether the bug has already been =
fixed by checking
the last version of GNU Parted that you can find at: =
http://ftp.gnu.org/gnu/parted/ Please check this version prior to bug =
reporting. If this has not been fixed yet or if you don't know how to =
check, please visit the GNU Parted website: =
http://www.gnu.org/software/parted for further information. Your report =
should contain the version of this release (3.7.5-4fdb) along with the =
error message below, the output of=20
parted DEVICE unit co print unit s print and the following history of =
commands you entered. Also include any additional information about your =
setup you
  consider important. Segmentation fault (core dumped) BUG TRIGGERED: =
real GNU Parted crashed after ped_calloc() received NULL.=

--Apple-Mail=_F273FE5A-5D30-45A0-A455-80B40DC5663E--