Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 130701790bf2d95e902edf16031ff596 > files > 181

autofs-5.0.1-0.rc2.164.el5_8.src.rpm

diff --git a/CHANGELOG b/CHANGELOG
index 6f6e71f..ac0fe8d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -33,6 +33,7 @@
 - fix misc memory leaks.
 - mitigate manual umount of automounts where possible.
 - fix multiply recursive bind mounts.
+- check kernel module version and require 5.00 or above.
 
 1/9/2006 autofs-5.0.1 rc2
 -------------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index 4e776ca..ae87556 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -1512,6 +1512,20 @@ int main(int argc, char *argv[])
 			program);
 		exit(1);
 	}
+#if 0
+	if (!load_autofs4_module()) {
+		fprintf(stderr, "%s: can't load %s filesystem module.\n",
+			program, FS_MODULE_NAME);
+		exit(1);
+	}
+#endif
+
+	if (!query_kproto_ver() || get_kver_major() < 5) {
+		fprintf(stderr,
+			"%s: kernel protocol version 5.00 or above required.\n",
+			program);
+		exit(1);
+	}
 
 	rlim.rlim_cur = MAX_OPEN_FILES;
 	rlim.rlim_max = MAX_OPEN_FILES;
@@ -1573,6 +1587,8 @@ #endif
 
 	msg("Starting automounter version %s, master map %s",
 		version, master_list->name);
+	msg("using kernel protocol version %d.%02d",
+		get_kver_major(), get_kver_minor());
 
 	status = pthread_key_create(&key_thread_stdenv_vars,
 				key_thread_stdenv_vars_destroy);
@@ -1597,17 +1613,6 @@ #endif
 		close(start_pipefd[1]);
 		exit(1);
 	}
-#if 0
-	if (!load_autofs4_module()) {
-		crit(LOGOPT_ANY, "%s: can't load %s filesystem module",
-			program, FS_MODULE_NAME);
-		master_kill(master_list);
-		*pst_stat = 2;
-		res = write(start_pipefd[1], pst_stat, sizeof(pst_stat));
-		close(start_pipefd[1]);
-		exit(2);
-	}
-#endif
 	if (!master_read_master(master_list, age, 0)) {
 		master_kill(master_list);
 		*pst_stat = 3;
diff --git a/daemon/direct.c b/daemon/direct.c
index ef96cc4..1aefa9f 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -435,8 +435,6 @@ int do_mount_autofs_direct(struct autofs
 		goto out_err;
 	}
 
-	msg("mounted autofs direct mount on %s", me->key);
-
 	/* Root directory for ioctl()'s */
 	ioctlfd = open(me->key, O_RDONLY);
 	if (ioctlfd < 0) {
@@ -449,42 +447,20 @@ int do_mount_autofs_direct(struct autofs
 		fcntl(ioctlfd, F_SETFD, cl_flags);
 	}
 
-	/* Only calculate this first time round */
-	if (ap->kver.major)
-		goto got_version;
-
-	ap->kver.major = 0;
-	ap->kver.minor = 0;
-
-	/* If this ioctl() doesn't work, it is kernel version 2 */
-	if (!ioctl(ioctlfd, AUTOFS_IOC_PROTOVER, &ap->kver.major)) {
-		 /* If this ioctl() fails the kernel doesn't support direct mounts */
-		 if (ioctl(me->ioctlfd, AUTOFS_IOC_PROTOSUBVER, &ap->kver.minor)) {
-			ap->kver.minor = 0;
-			ap->ghost = 0;
-		 }
-	}
-
-	msg("using kernel protocol version %d.%02d", ap->kver.major, ap->kver.minor);
-
-	if (ap->kver.major < 5) {
-		crit(ap->logopt, "kernel does not support direct mounts");
-		goto out_close;
-	}
-
 	/* Calculate the timeouts */
 	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
 
-	if (timeout) {
-		msg("using timeout %d seconds; freq %d secs",
-			(int) ap->exp_timeout, (int) ap->exp_runfreq);
-	} else {
-		msg("timeouts disabled");
-	}
-
-got_version:
 	ioctl(ioctlfd, AUTOFS_IOC_SETTIMEOUT, &timeout);
 
+	if (ap->exp_timeout)
+		msg("mounted direct mount on %s "
+		    "with timeout %u, freq %u seconds", me->key,
+		    (unsigned int) ap->exp_timeout,
+		    (unsigned int) ap->exp_runfreq);
+	else
+		msg("mounted direct mount on %s with timeouts disabled",
+		    me->key);
+
 	ret = fstat(ioctlfd, &st);
 	if (ret == -1) {
 		error(ap->logopt,
diff --git a/daemon/indirect.c b/daemon/indirect.c
index 5b073e4..6363522 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -193,8 +193,6 @@ static int do_mount_autofs_indirect(stru
 
 	options = NULL;
 
-	msg("mounted autofs indirect mount on %s", ap->path);
-
 	/* Root directory for ioctl()'s */
 	ap->ioctlfd = open(ap->path, O_RDONLY);
 	if (ap->ioctlfd < 0) {
@@ -208,44 +206,19 @@ static int do_mount_autofs_indirect(stru
 		fcntl(ap->ioctlfd, F_SETFD, cl_flags);
 	}
 
-	ap->kver.major = 0;
-	ap->kver.minor = 0;
-
-	/* If this ioctl() doesn't work, it is kernel version 2 */
-	if (!ioctl(ap->ioctlfd, AUTOFS_IOC_PROTOVER, &ap->kver.major)) {
-		 /* If this ioctl() doesn't work, kernel does not support ghosting */
-		 if (ioctl(ap->ioctlfd, AUTOFS_IOC_PROTOSUBVER, &ap->kver.minor)) {
-			ap->kver.minor = 0;
-			if (ap->ghost) {
-				msg("kernel does not support ghosting, disabled");
-				ap->ghost = 0;
-			}
-		 }
-	} else {
-		ap->kver.major = 2;
-		ap->kver.minor = 0;
-	}
-
-	msg("using kernel protocol version %d.%02d", ap->kver.major, ap->kver.minor);
-
-	/* Calculate the timeouts */
-	if (ap->kver.major < 3 || !timeout) {
-		ap->exp_timeout = ap->exp_runfreq = 0;
-		ap->ghost = 0;
-		if (ap->kver.major >= 3) {
-			msg("timeouts disabled");
-		} else {
-			msg("kernel does not support timeouts");
-		}
-	} else {
-		ap->exp_runfreq = (ap->exp_timeout + CHECK_RATIO - 1) / CHECK_RATIO;
-
-		msg("using timeout %d seconds; freq %d secs",
-		       (int) ap->exp_timeout, (int) ap->exp_runfreq);
-	}
+	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
 
 	ioctl(ap->ioctlfd, AUTOFS_IOC_SETTIMEOUT, &timeout);
 
+	if (ap->exp_timeout)
+		msg("mounted indirect mount on %s "
+		    "with timeout %u, freq %u seconds", ap->path,
+	 	   (unsigned int) ap->exp_timeout,
+		   (unsigned int) ap->exp_runfreq);
+	else
+		msg("mounted indirect mount on %s with timeouts disabled",
+		    ap->path);
+
 	fstat(ap->ioctlfd, &st);
 	ap->dev = st.st_dev;	/* Device number for mount point checks */
 
diff --git a/include/automount.h b/include/automount.h
index 89610ee..92da8f9 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -347,6 +347,9 @@ struct mnt_list {
 	struct list_head ordered;
 };
 
+unsigned int query_kproto_ver(void);
+unsigned int get_kver_major(void);
+unsigned int get_kver_minor(void);
 char *make_options_string(char *path, int kernel_pipefd, char *extra);
 char *make_mnt_name_string(char *path);
 struct mnt_list *get_mnt_list(const char *table, const char *path, int include);
@@ -433,7 +436,6 @@ struct autofs_point {
 	time_t exp_runfreq;		/* Frequency for polling for timeouts */
 	unsigned ghost;			/* Enable/disable gohsted directories */
 	unsigned logopt;		/* Per map logging */
-	struct kernel_mod_version kver;	/* autofs kernel module version */
 	pthread_t exp_thread;		/* Thread that is expiring */
 	pthread_t readmap_thread;	/* Thread that is reading maps */
 	pthread_mutex_t state_mutex;	/* Protect state changes */
diff --git a/lib/master.c b/lib/master.c
index f0fdb62..1c499d6 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -53,8 +53,6 @@ int master_add_autofs_point(struct maste
 		return 0;
 
 	ap->state = ST_INIT;
-	ap->kver.major = 0;
-	ap->kver.minor = 0;
 
 	ap->state_pipe[0] = -1;
 	ap->state_pipe[1] = -1;
diff --git a/lib/mounts.c b/lib/mounts.c
index a4f68c5..c2a8f04 100644
--- a/lib/mounts.c
+++ b/lib/mounts.c
@@ -19,6 +19,9 @@ #include <mntent.h>
 #include <limits.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/mount.h>
 #include <stdio.h>
 
 #include "automount.h"
@@ -30,6 +33,88 @@ static const char options_template[]    
 static const char options_template_extra[] = "fd=%d,pgrp=%u,minproto=5,maxproto=%d,%s";
 static const char mnt_name_template[]      = "automount(pid%u)";
 
+static struct kernel_mod_version kver = {0, 0};
+static const char kver_options_template[]  = "fd=%d,pgrp=%u,minproto=3,maxproto=5";
+
+unsigned int query_kproto_ver(void)
+{
+	char options[MAX_OPTIONS_LEN + 1], *tmp;
+	pid_t pgrp = getpgrp();
+	int pipefd[2], ioctlfd, len;
+
+	tmp = tempnam(NULL, "auto");
+	if (mkdir(tmp, 0700) == -1)
+		return 0;
+
+	if (pipe(pipefd) == -1) {
+		rmdir(tmp);
+		return 0;
+	}
+
+	len = snprintf(options, MAX_OPTIONS_LEN,
+		       kver_options_template, pipefd[1], (unsigned) pgrp);
+	if (len < 0) {
+		close(pipefd[0]);
+		close(pipefd[1]);
+		rmdir(tmp);
+		return 0;
+	}
+
+	if (mount("automount", tmp, "autofs", MS_MGC_VAL, options)) {
+		close(pipefd[0]);
+		close(pipefd[1]);
+		rmdir(tmp);
+		return 0;
+	}
+
+	close(pipefd[1]);
+
+	ioctlfd = open(tmp, O_RDONLY);
+	if (ioctlfd == -1) {
+		umount(tmp);
+		close(pipefd[0]);
+		rmdir(tmp);
+		return 0;
+	}
+
+	ioctl(ioctlfd, AUTOFS_IOC_CATATONIC, 0);
+
+	/* If this ioctl() doesn't work, it is kernel version 2 */
+	if (ioctl(ioctlfd, AUTOFS_IOC_PROTOVER, &kver.major) == -1) {
+		close(ioctlfd);
+		umount(tmp);
+		close(pipefd[0]);
+		rmdir(tmp);
+		return 0;
+	}
+
+	/* If this ioctl() doesn't work, version is 4 or less */
+	if (ioctl(ioctlfd, AUTOFS_IOC_PROTOSUBVER, &kver.minor) == -1) {
+		close(ioctlfd);
+		umount(tmp);
+		close(pipefd[0]);
+		rmdir(tmp);
+		return 0;
+	}
+
+	close(ioctlfd);
+	umount(tmp);
+	close(pipefd[0]);
+	rmdir(tmp);
+
+	return 1;
+}
+
+unsigned int get_kver_major(void)
+{
+	return kver.major;
+}
+
+unsigned int get_kver_minor(void)
+{
+	return kver.minor;
+}
+
 /*
  * Make common autofs mount options string
  */