diff mbox series

[v2] fstools: blockd Check /tmp/run/blockd for existing mounts

Message ID mailman.5323.1623574873.434944.openwrt-devel@lists.openwrt.org
State New
Headers show
Series [v2] fstools: blockd Check /tmp/run/blockd for existing mounts | expand

Commit Message

David Adair June 13, 2021, 9:01 a.m. UTC
The sender domain has a DMARC Reject/Quarantine policy which disallows
sending mailing list messages using the original "From" header.

To mitigate this problem, the original message has been wrapped
automatically by the mailing list software.
Currently volume names can not match rootfs files/directories
so LV names like "home" "usr" or "www" are not allowed.

This changes the check for existing mount points to
examine /tmp/run/blockd/<newdev> instead of /<newdev>.

It also checks that a link is present at
/mnt/<newdev> and skips the request if it is missing
e.g. the "map" does not support the requested "key".

This aligns the mount logic to match the automount
daemon indirect.c logic from kernel.org.
 - If mountpoint exist and is not a zombie return success.
 - If mountpoint is a zombie delete it.
 - If map is missing or mount fails return failure.

This greatly simplifies hotplug-remove since we leave
devices alone once link is removed.  It also fixes most
instances of poision directories remaining in automount
dir and causing "too many symlinks" errors.

Signed-off-by: David Adair <djabhead@aol.com>
---
 blockd.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/blockd.c b/blockd.c
index d6dfeb8..6024c60 100644
--- a/blockd.c
+++ b/blockd.c
@@ -41,6 +41,7 @@  struct device {
 
 static struct uloop_fd fd_autofs_read;
 static int fd_autofs_write = 0;
+static struct stat autofs_mp_stat;
 static struct ubus_auto_conn conn;
 struct blob_buf bb = { 0 };
 
@@ -501,8 +502,10 @@  static void autofs_read_handler(struct uloop_fd *u, unsigned int events)
 {
 	union autofs_v5_packet_union pktu;
 	const struct autofs_v5_packet *pkt;
-	int cmd = AUTOFS_IOC_READY;
 	struct stat st;
+	struct device *device;
+	char *mnt;
+	int cmd = AUTOFS_IOC_READY;
 
 	while (read(u->fd, &pktu, sizeof(pktu)) == -1) {
 		if (errno != EINTR)
@@ -517,9 +520,24 @@  static void autofs_read_handler(struct uloop_fd *u, unsigned int events)
 
 	pkt = &pktu.missing_indirect;
         ULOG_ERR("kernel is requesting a mount -> %s\n", pkt->name);
-	if (lstat(pkt->name, &st) == -1)
-		if (block("autofs", "add", (char *)pkt->name))
+	/*
+	 * if MP exists send "ready"
+	 *   second part of check detects zombie mounts --
+	 *   valid target should have target dev not autofs.
+	 */
+	if (asprintf(&mnt, "%s%s", AUTOFS_MOUNT_PATH, pkt->name) == -1)
+		exit(ENOMEM);
+	if ((lstat(mnt, &st) == -1) ||
+	    (S_ISDIR(st.st_mode) && st.st_dev == autofs_mp_stat.st_dev)) {
+		rmdir(mnt);
+		device = vlist_find(&devices, pkt->name, device, node);
+		/* Map doesn't exist or mount fails send "fail" */
+		if (!device || !device->target ||
+		    lstat(device->target, &st) || ! S_ISLNK(st.st_mode) ||
+		    block("autofs", "add", (char *)pkt->name))
 			cmd = AUTOFS_IOC_FAIL;
+	}
+	free(mnt);
 
 	if (ioctl(fd_autofs_write, cmd, pkt->wait_queue_token) < 0)
 		ULOG_ERR("failed to report back to kernel\n");
@@ -562,6 +580,7 @@  static int autofs_mount(void)
 		return -1;
 	}
 	close(pipefd[1]);
+	stat(AUTOFS_MOUNT_PATH, &autofs_mp_stat);
 	fd_autofs_read.fd = pipefd[0];
 	fd_autofs_read.cb = autofs_read_handler;
 	uloop_fd_add(&fd_autofs_read, ULOOP_READ);