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 #include #include #include +#include +#include +#include #include #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 */