diff options
| author | Matthias Andree <mandree@FreeBSD.org> | 2025-09-30 00:30:47 +0200 |
|---|---|---|
| committer | Matthias Andree <mandree@FreeBSD.org> | 2025-09-30 01:09:52 +0200 |
| commit | fd46b8c7f0d78952a1a60e56aacccbdccdc76dc1 (patch) | |
| tree | 5d6ec03a43dcfe95376c76a87ced188e99d9a334 /filesystems | |
| parent | 4aea75ddb74a4dee0c57f43687151ff8a6892cb4 (diff) | |
filesystems/libblkid: fix odd reads and fdisk
TL;DR: This fixes "invalid argument" in util-linux's fdisk.
libblkid assumes buffered block devices, skipping most character
devices (unless their name starts with "ubi") and failing because
it tries reads that aren't a multiple of the underlying I/O size.
Detail: util-linux assumes a Linux-like behavior and naming of devices,
and assumes it's looking at buffered block devices, which FreeBSD has
not been provided for many major releases. It also requires specific
layouts of procfs, sysfs, devfs, which FreeBSD or its Linuxulator does
not provide.
So we specifically need to patch the read_buffer function to make sure
it rounds up its read size to the io_size (often 512) and not attempt to
read 36, 256, 548 or other strange sizes and emulate a buffered disk
character device; we also need to patch many of the S_ISCHR checks so
they accept our character devices.
This patching is apparently enough to fix the "invalid argument"
(EINVAL, errno==22) errors from the util-linux fdisk tools.
This patch set is not complete, but is sufficient to get the util-linux
fdisk/cfdisk/sfdisk back up to their feet so we can nuke the dangerous
linuxfdisk port now and for good.
Note that many uses will require sysctl to allow foot-shooting
by setting kern.geom.debugflags=16.
blkid can not yet enumerate disk character devices if run without
argument.
Approved by: portmgr@ (blanket just-fix it)
Could the port maintainer please check with the upstream what their
stance on supporting non-GNU userspaces and non-Linux kernels is?
Can we work with them to get such fixes upstreamed or will they turn
us down because the tools are specifically called "util-linux"?
Diffstat (limited to 'filesystems')
| -rw-r--r-- | filesystems/libblkid/Makefile | 2 | ||||
| -rw-r--r-- | filesystems/libblkid/files/patch-libblkid_src_devname.c | 30 | ||||
| -rw-r--r-- | filesystems/libblkid/files/patch-libblkid_src_probe.c | 49 | ||||
| -rw-r--r-- | filesystems/libblkid/files/patch-misc-utils_blkid.c | 18 |
4 files changed, 98 insertions, 1 deletions
diff --git a/filesystems/libblkid/Makefile b/filesystems/libblkid/Makefile index 077bc2158912..3367ae62ac6b 100644 --- a/filesystems/libblkid/Makefile +++ b/filesystems/libblkid/Makefile @@ -1,7 +1,7 @@ PORTNAME= libblkid DISTVERSIONPREFIX= v DISTVERSION= 2.41.1 -PORTREVISION= 1 +PORTREVISION= 2 CATEGORIES= filesystems MAINTAINER= arrowd@FreeBSD.org diff --git a/filesystems/libblkid/files/patch-libblkid_src_devname.c b/filesystems/libblkid/files/patch-libblkid_src_devname.c new file mode 100644 index 000000000000..cf1040ef3f52 --- /dev/null +++ b/filesystems/libblkid/files/patch-libblkid_src_devname.c @@ -0,0 +1,30 @@ +--- libblkid/src/devname.c.orig 2025-06-24 07:55:28 UTC ++++ libblkid/src/devname.c +@@ -224,7 +224,11 @@ static void probe_one(blkid_cache cache, const char *p + + if (stat(device, &st) == 0 && + (S_ISBLK(st.st_mode) || +- (S_ISCHR(st.st_mode) && !strncmp(ptname, "ubi", 3))) && ++ (S_ISCHR(st.st_mode) ++#ifdef __linux__ ++ && !strncmp(ptname, "ubi", 3) ++#endif ++ )) && + st.st_rdev == devno) { + devname = strdup(device); + goto get_dev; +@@ -251,8 +255,12 @@ set_pri: + dev->bid_pri = BLKID_PRI_DM; + if (is_dm_leaf(ptname)) + dev->bid_pri += 5; +- } else if (!strncmp(ptname, "md", 2)) +- dev->bid_pri = BLKID_PRI_MD; ++ } else { ++#ifdef __linux__ ++ if (!strncmp(ptname, "md", 2)) ++ dev->bid_pri = BLKID_PRI_MD; ++#endif ++ } + if (removable) + dev->bid_flags |= BLKID_BID_FL_REMOVABLE; + } diff --git a/filesystems/libblkid/files/patch-libblkid_src_probe.c b/filesystems/libblkid/files/patch-libblkid_src_probe.c new file mode 100644 index 000000000000..aecc99b2b03b --- /dev/null +++ b/filesystems/libblkid/files/patch-libblkid_src_probe.c @@ -0,0 +1,49 @@ +--- libblkid/src/probe.c.orig 2025-06-24 07:55:28 UTC ++++ libblkid/src/probe.c +@@ -594,7 +594,18 @@ static struct blkid_bufinfo *read_buffer(blkid_probe p + DBG(LOWPROBE, ul_debug("\tread: off=%"PRIu64" len=%"PRIu64"", + real_off, len)); + +- ret = read(pr->fd, bf->data, len); ++ /* on FreeBSD, devices are unbuffered so we need to align to full I/O blocks by ourselves */ ++ if (len % pr->io_size) { ++ unsigned rawlen = len + (pr->io_size - len % pr->io_size); ++ char buf[rawlen]; ++ ret = read(pr->fd, buf, rawlen); ++ if (ret < 0 || ret < len) ++ return NULL; ++ memcpy(bf->data, buf, len); ++ ret = len; ++ } else { ++ ret = read(pr->fd, bf->data, len); ++ } + if (ret != (ssize_t) len) { + DBG(LOWPROBE, ul_debug("\tread failed: %m")); + remove_buffer(bf); +@@ -718,7 +729,7 @@ const unsigned char *blkid_probe_get_buffer(blkid_prob + struct blkid_bufinfo *bf = NULL; + uint64_t real_off, bias, len_align; + +- bias = off % pr->io_size; ++ bias = off % /* pr->io_size */ 4096; + off -= bias; + len += bias; + +@@ -1106,6 +1117,7 @@ int blkid_probe_set_device(blkid_probe pr, int fd, + goto err; + } + } else if (S_ISCHR(sb.st_mode)) { ++#ifdef __linux__ + char buf[PATH_MAX]; + + if (!sysfs_chrdev_devno_to_devname(sb.st_rdev, buf, sizeof(buf)) +@@ -1114,6 +1126,9 @@ int blkid_probe_set_device(blkid_probe pr, int fd, + errno = EINVAL; + goto err; + } ++#else ++ /* no-op, FreeBSD maps block devices as character */ ++#endif + devsiz = 1; /* UBI devices are char... */ + } else if (S_ISREG(sb.st_mode)) + devsiz = sb.st_size; /* regular file */ diff --git a/filesystems/libblkid/files/patch-misc-utils_blkid.c b/filesystems/libblkid/files/patch-misc-utils_blkid.c new file mode 100644 index 000000000000..6fe581bc1c13 --- /dev/null +++ b/filesystems/libblkid/files/patch-misc-utils_blkid.c @@ -0,0 +1,18 @@ +--- misc-utils/blkid.c.orig 2025-06-24 07:55:28 UTC ++++ misc-utils/blkid.c +@@ -876,6 +876,7 @@ int main(int argc, char **argv) + else if (S_ISREG(sb.st_mode)) + ; + else if (S_ISCHR(sb.st_mode)) { ++#ifdef __linux__ + char buf[PATH_MAX]; + + if (!sysfs_chrdev_devno_to_devname( +@@ -883,6 +884,7 @@ int main(int argc, char **argv) + continue; + if (strncmp(buf, "ubi", 3) != 0) + continue; ++#endif + } else + continue; + |
