Index | Thread | Search

From:
Luis Henriques <henrix@camandro.org>
Subject:
Re: Don't detach volumes that have mounted partitions
To:
"Theo de Raadt" <deraadt@openbsd.org>
Cc:
tech@openbsd.org
Date:
Wed, 06 Mar 2024 22:54:06 +0000

Download raw body.

Thread
"Theo de Raadt" <deraadt@openbsd.org> writes:

> That's not good enough.
>
> One issue is swap.
>
> But I suspect there are other in-use circumstances this won't catch.
>
> Sometimes doing nothing is better, because it encourages people to be
> paranoid and careful of bear the consequences.

Hmm... yeah, makes sense.  Adding a check for a swap device should be
easy.  Below is an _untested_ (and probably buggy) patch that adds the
check for swap, stolen from swapctl(8).  If that's something worth
pursuing I can give it some more thought and testing tomorrow.
Otherwise... I'll just drop it.

Cheers,
-- 
Luís

diff --git sbin/bioctl/bioctl.8 sbin/bioctl/bioctl.8
index a187daf36edd..6dc06b8503d4 100644
--- sbin/bioctl/bioctl.8
+++ sbin/bioctl/bioctl.8
@@ -245,6 +245,9 @@ they become part of the array again.
 .It Fl d
 Detach volume specified by
 .Ar device .
+It will fail if
+.Ar device
+has a mounted partition.
 .It Fl k Ar keydisk
 Use special device
 .Ar keydisk
diff --git sbin/bioctl/bioctl.c sbin/bioctl/bioctl.c
index 2e25d5801d9e..2d0a82ec35af 100644
--- sbin/bioctl/bioctl.c
+++ sbin/bioctl/bioctl.c
@@ -31,6 +31,9 @@
 #include <sys/ioctl.h>
 #include <sys/dkio.h>
 #include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <sys/swap.h>
 #include <dev/softraidvar.h>
 #include <dev/biovar.h>
 
@@ -39,6 +42,7 @@
 #include <fcntl.h>
 #include <util.h>
 #include <ctype.h>
+#include <paths.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -1080,6 +1084,48 @@ void
 bio_deleteraid(char *dev)
 {
 	struct bioc_deleteraid	bd;
+	struct statfs *fs;
+	struct  swapent *sep, *fsep;
+	int len, n, nswap;
+	char *s;
+
+	n = getmntinfo(&fs, MNT_NOWAIT);
+	if (n == 0)
+		errx(1, "getmntinfo");
+	len = sizeof(_PATH_DEV) - 1;
+	while (--n >= 0) {
+		s = fs[n].f_mntfromname;
+		if (strncmp(_PATH_DEV, s, len) == 0)
+			s += len;
+		if (strncmp(dev, s, strlen(dev)) == 0)
+			errx(1, "%s is still mounted on %s",
+			     fs[n].f_mntfromname, fs[n].f_mntonname);
+	}
+
+	n = swapctl(SWAP_NSWAP, 0, 0);
+	if (len < 0)
+		errx(1, "swapctl");
+
+	fsep = sep = calloc(n, sizeof(*sep));
+	if (sep == NULL)
+		errx(1, "calloc");
+
+	nswap = swapctl(SWAP_STATS, (void *)sep, n);
+	if (n == -1)
+		errx(1, "swapctl");
+	if (nswap != n)
+		warnx("SWAP_STATS different to SWAP_NSWAP (%d != %d)",
+		      nswap, n);
+	for (; nswap-- > 0; sep++) {
+		s = sep->se_path;
+		if (strncmp(_PATH_DEV, s, len) == 0)
+			s += len;
+		if (strncmp(dev, s, strlen(dev)) == 0)
+			errx(1, "%s is being used as swap",
+			     sep->se_path);
+	}
+	free(fsep);
+
 	memset(&bd, 0, sizeof(bd));
 
 	bd.bd_bio.bio_cookie = bio_cookie;