[OpenWrt-Devel] [PATCH fstools 2/2] libblkid-tiny: use separated buffer for each block device read

Rafał Miłecki zajec5 at gmail.com
Sat Dec 14 16:55:01 EST 2019


From: Rafał Miłecki <rafal at milecki.pl>

This allows reading multiple chunks of block device data and operating
on them simultaneously. Previous implementation was using a single
buffer (except for reading more data than allocated size) and subsequent
reads were corrupting memory of previously returned buffers.

This fixes e.g. problem with reading NTFS UUID and validating VFAT
signature.

Implementation is based on original libblkid code which handles it
similarly. Buffers are put on probe internal list and freed when
releasing a probe struct.

Signed-off-by: Rafał Miłecki <rafal at milecki.pl>
---
 libblkid-tiny/libblkid-tiny.c | 36 ++++++++++++++---------------------
 libblkid-tiny/libblkid-tiny.h |  2 ++
 libblkid-tiny/probe.c         | 23 ++++++++++++++++++++++
 3 files changed, 39 insertions(+), 22 deletions(-)

diff --git a/libblkid-tiny/libblkid-tiny.c b/libblkid-tiny/libblkid-tiny.c
index a30f619..05b4b99 100644
--- a/libblkid-tiny/libblkid-tiny.c
+++ b/libblkid-tiny/libblkid-tiny.c
@@ -13,9 +13,6 @@
 
 int blkid_debug_mask = 0;
 
-static unsigned char *probe_buffer;
-static unsigned int probe_buffer_size = 0;
-
 int get_linux_version (void)
 {
 	static int kver = -1;
@@ -81,32 +78,27 @@ int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...)
 unsigned char *blkid_probe_get_buffer(blkid_probe pr,
 				blkid_loff_t off, blkid_loff_t len)
 {
+	struct blkid_bufinfo *bf;
 	int ret;
-	unsigned char *buf;
-
-	if (len > probe_buffer_size) {
-		buf = realloc(probe_buffer, len);
 
-		if (!buf) {
-			fprintf(stderr, "failed to allocate %d byte buffer\n",
-			        (int)len);
-
-			return NULL;
-		}
-
-		probe_buffer = buf;
-		probe_buffer_size = len;
-	}
-
-	memset(probe_buffer, 0, probe_buffer_size);
+	bf = malloc(sizeof(*bf) + len);
+	if (!bf)
+		return NULL;
+	memset(bf, 0, sizeof(*bf));
+	bf->data = ((unsigned char *)bf) + sizeof(*bf);
 
 	lseek(pr->fd, off, SEEK_SET);
-	ret = read(pr->fd, probe_buffer, len);
+	ret = read(pr->fd, bf->data, len);
 
-	if (ret != len)
+	if (ret != len) {
 		fprintf(stderr, "faile to read blkid\n");
+		free(bf);
+		return NULL;
+	}
+
+	list_add_tail(&bf->bufs, &pr->buffers);
 
-	return probe_buffer;
+	return bf->data;
 }
 
 int blkid_probe_set_label(blkid_probe pr, unsigned char *label, size_t len)
diff --git a/libblkid-tiny/libblkid-tiny.h b/libblkid-tiny/libblkid-tiny.h
index 06ff94b..aa87fd9 100644
--- a/libblkid-tiny/libblkid-tiny.h
+++ b/libblkid-tiny/libblkid-tiny.h
@@ -58,6 +58,8 @@ struct blkid_struct_probe
 	char	uuid[64];
 	char	label[256];
 	char	version[64];
+
+	struct list_head	buffers;	/* list of buffers */
 };
 
 struct blkid_struct_probe *blkid_new_probe(void);
diff --git a/libblkid-tiny/probe.c b/libblkid-tiny/probe.c
index 54e22dc..ae7e708 100644
--- a/libblkid-tiny/probe.c
+++ b/libblkid-tiny/probe.c
@@ -9,8 +9,11 @@
 
 #include <stdlib.h>
 
+#include "blkidP.h"
 #include "libblkid-tiny.h"
 
+static int blkid_probe_reset_buffers(struct blkid_struct_probe *pr);
+
 struct blkid_struct_probe *blkid_new_probe(void)
 {
 	struct blkid_struct_probe *pr;
@@ -19,6 +22,8 @@ struct blkid_struct_probe *blkid_new_probe(void)
 	if (!pr)
 		return NULL;
 
+	INIT_LIST_HEAD(&pr->buffers);
+
 	return pr;
 }
 
@@ -27,5 +32,23 @@ void blkid_free_probe(struct blkid_struct_probe *pr)
 	if (!pr)
 		return;
 
+	blkid_probe_reset_buffers(pr);
+
 	free(pr);
 }
+
+static int blkid_probe_reset_buffers(struct blkid_struct_probe *pr)
+{
+	if (list_empty(&pr->buffers))
+		return 0;
+
+	while (!list_empty(&pr->buffers)) {
+		struct blkid_bufinfo *bf = list_first_entry(&pr->buffers, struct blkid_bufinfo, bufs);
+
+		list_del(&bf->bufs);
+
+		free(bf);
+	}
+
+	return 0;
+}
-- 
2.21.0


_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel


More information about the openwrt-devel mailing list