From c3a32a3333739979dca4d46cddb651e514d239d8 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Mon, 12 May 2008 06:13:46 +0000 Subject: [PATCH] - check for nohide mounts (bz 442618). - ignore nsswitch sources that aren't supported (bz 445880). --- autofs-5.0.3-nfs4-nohide-check.patch | 196 +++++++++++++++++++++++++++ autofs-5.0.3-nss-source-any.patch | 151 +++++++++++++++++++++ autofs.spec | 10 +- 3 files changed, 356 insertions(+), 1 deletion(-) create mode 100644 autofs-5.0.3-nfs4-nohide-check.patch create mode 100644 autofs-5.0.3-nss-source-any.patch diff --git a/autofs-5.0.3-nfs4-nohide-check.patch b/autofs-5.0.3-nfs4-nohide-check.patch new file mode 100644 index 0000000..7ed8f41 --- /dev/null +++ b/autofs-5.0.3-nfs4-nohide-check.patch @@ -0,0 +1,196 @@ +autofs 5.0.3 - check for nohide mounts + +From: Ian Kent + +If a server exports file systems with the nohide option +autofs will mistakenly over mount them when it constructs +and mounts its multi-mount triggers. + +This patch makes autofs check for nohide mounts and ignores +them if the kernel mounts them while it mounts multi-mount +triggers. + +We don't want to fight with NFS over mounting these because +it confuses autofs and they magically go away when the owner +mount is umounted. This isn't ideal because autofs will mount +the nohide exports while constructing its multi-mount triggers +but it is unavoidable at the moment. +--- + + daemon/direct.c | 26 ++++++++++++++++++-------- + include/automount.h | 4 ++++ + lib/parse_subs.c | 26 ++++++++++++++++++-------- + 3 files changed, 40 insertions(+), 16 deletions(-) + + +diff --git a/daemon/direct.c b/daemon/direct.c +index a9dda87..c67f38a 100644 +--- a/daemon/direct.c ++++ b/daemon/direct.c +@@ -664,12 +664,12 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me) + if (ap->state != ST_READMAP) + warn(ap->logopt, + "trigger %s already mounted", me->key); +- return 0; ++ return MOUNT_OFFSET_OK; + } + + if (me->ioctlfd != -1) { + error(ap->logopt, "active offset mount %s", me->key); +- return -1; ++ return MOUNT_OFFSET_FAIL; + } + + status = pthread_once(&key_mnt_params_once, key_mnt_params_init); +@@ -683,7 +683,7 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me) + crit(ap->logopt, + "mnt_params value create failed for offset mount %s", + me->key); +- return 0; ++ return MOUNT_OFFSET_OK; + } + mp->options = NULL; + +@@ -697,12 +697,22 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me) + if (!mp->options) { + mp->options = make_options_string(ap->path, ap->kpipefd, "offset"); + if (!mp->options) +- return 0; ++ return MOUNT_OFFSET_OK; + } + + /* In case the directory doesn't exist, try to mkdir it */ + if (mkdir_path(me->key, 0555) < 0) { + if (errno == EEXIST) { ++ /* ++ * If the mount point directory is a real mount ++ * and it isn't the root offset then it must be ++ * a "nohide" mount, automounted by the kernel NFS ++ * client. ++ */ ++ if (me->multi != me && ++ is_mounted(_PROC_MOUNTS, me->key, MNTS_REAL)) ++ return MOUNT_OFFSET_IGNORE; ++ + /* + * If we recieve an error, and it's EEXIST + * we know the directory was not created. +@@ -721,13 +731,13 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me) + debug(ap->logopt, + "can't create mount directory: %s, %s", + me->key, estr); +- return -1; ++ return MOUNT_OFFSET_FAIL; + } else { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + crit(ap->logopt, + "failed to create mount directory: %s, %s", + me->key, estr); +- return -1; ++ return MOUNT_OFFSET_FAIL; + } + } else { + /* No errors so the directory was successfully created */ +@@ -787,7 +797,7 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me) + + debug(ap->logopt, "mounted trigger %s", me->key); + +- return 0; ++ return MOUNT_OFFSET_OK; + + out_close: + close(ioctlfd); +@@ -797,7 +807,7 @@ out_err: + if (stat(me->key, &st) == 0 && me->dir_created) + rmdir_path(ap, me->key, st.st_dev); + +- return -1; ++ return MOUNT_OFFSET_FAIL; + } + + static int expire_direct(int ioctlfd, const char *path, unsigned int when, unsigned int logopt) +diff --git a/include/automount.h b/include/automount.h +index cd8ce7b..d59be77 100644 +--- a/include/automount.h ++++ b/include/automount.h +@@ -468,6 +468,10 @@ struct autofs_point { + + /* Standard functions used by daemon or modules */ + ++#define MOUNT_OFFSET_OK 0 ++#define MOUNT_OFFSET_FAIL -1 ++#define MOUNT_OFFSET_IGNORE -2 ++ + void *handle_mounts(void *arg); + int umount_multi(struct autofs_point *ap, const char *path, int incl); + int send_ready(unsigned logopt, int ioctlfd, unsigned int wait_queue_token); +diff --git a/lib/parse_subs.c b/lib/parse_subs.c +index 5422fef..27cb0fc 100644 +--- a/lib/parse_subs.c ++++ b/lib/parse_subs.c +@@ -390,7 +390,7 @@ int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, + struct list_head *pos = NULL; + unsigned int fs_path_len; + unsigned int mounted; +- int start; ++ int ret, start; + + fs_path_len = strlen(root) + strlen(base); + if (fs_path_len > PATH_MAX) +@@ -411,15 +411,25 @@ int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, + } + + oe = cache_lookup_offset(base, offset, start, &me->multi_list); +- if (!oe) ++ if (!oe || !oe->mapent) + goto cont; + + debug(ap->logopt, "mount offset %s", oe->key); + +- if (mount_autofs_offset(ap, oe) < 0) +- warn(ap->logopt, "failed to mount offset"); +- else ++ ret = mount_autofs_offset(ap, oe); ++ if (ret >= MOUNT_OFFSET_OK) + mounted++; ++ else { ++ if (ret != MOUNT_OFFSET_IGNORE) ++ warn(ap->logopt, "failed to mount offset"); ++ else { ++ debug(ap->logopt, ++ "ignoring \"nohide\" trigger %s", ++ oe->key); ++ free(oe->mapent); ++ oe->mapent = NULL; ++ } ++ } + cont: + offset = cache_get_offset(base, + offset, start, &me->multi_list, &pos); +@@ -457,7 +467,7 @@ int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me + + oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list); + /* root offset is a special case */ +- if (!oe || (strlen(oe->key) - start) == 1) ++ if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1) + continue; + + /* +@@ -481,7 +491,7 @@ int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me + while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) { + oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list); + /* root offset is a special case */ +- if (!oe || (strlen(oe->key) - start) == 1) ++ if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1) + continue; + + debug(ap->logopt, "umount offset %s", oe->key); +@@ -505,7 +515,7 @@ int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me + if (is_mounted(_PATH_MOUNTED, root, MNTS_REAL)) { + info(ap->logopt, "unmounting dir = %s", root); + if (umount_ent(ap, root)) { +- if (!mount_multi_triggers(ap, root, me, "/")) ++ if (mount_multi_triggers(ap, root, me, "/") < 0) + warn(ap->logopt, + "failed to remount offset triggers"); + return left++; diff --git a/autofs-5.0.3-nss-source-any.patch b/autofs-5.0.3-nss-source-any.patch new file mode 100644 index 0000000..c5ffb52 --- /dev/null +++ b/autofs-5.0.3-nss-source-any.patch @@ -0,0 +1,151 @@ +autofs-5.0.3 - ignore nsswitch sources that aren't supported + +From: Ian Kent + +Allow any source name in nsswitch and ignore those we don't support. +This has the side affect of also ignoring any action associated with +a source that isn't supported by autofs. +--- + + lib/nss_parse.y | 31 ++++++++++++++++--------------- + lib/nss_tok.l | 22 ++++++++++++---------- + 2 files changed, 28 insertions(+), 25 deletions(-) + + +diff --git a/lib/nss_parse.y b/lib/nss_parse.y +index 90b7d25..fa6958a 100644 +--- a/lib/nss_parse.y ++++ b/lib/nss_parse.y +@@ -64,7 +64,6 @@ char strval[128]; + %token SOURCE + %token STATUS + %token ACTION +-%token OTHER + + %start file + +@@ -83,7 +82,9 @@ sources: nss_source + + nss_source: SOURCE + { +- if (strcmp($1, "winbind")) ++ if (!strcmp($1, "files") || !strcmp($1, "yp") || ++ !strcmp($1, "nis") || !strcmp($1, "ldap") || ++ !strcmp($1, "nisplus") || !strcmp($1, "hesiod")) + src = add_source(nss_list, $1); + else + nss_ignore($1); +@@ -91,7 +92,9 @@ nss_source: SOURCE + { + enum nsswitch_status a; + +- if (strcmp($1, "winbind")) { ++ if (!strcmp($1, "files") || !strcmp($1, "yp") || ++ !strcmp($1, "nis") || !strcmp($1, "ldap") || ++ !strcmp($1, "nisplus") || !strcmp($1, "hesiod")) { + src = add_source(nss_list, $1); + for (a = 0; a < NSS_STATUS_MAX; a++) { + if (act[a].action != NSS_ACTION_UNKNOWN) { +@@ -101,12 +104,10 @@ nss_source: SOURCE + } + } else + nss_ignore($1); +-} | SOURCE LBRACKET status_exp_list SOURCE { nss_error($4); YYABORT; } +- | SOURCE LBRACKET status_exp_list OTHER { nss_error($4); YYABORT; } +- | SOURCE LBRACKET status_exp_list NL { nss_error("no closing bracket"); YYABORT; } +- | SOURCE LBRACKET OTHER { nss_error($3); YYABORT; } +- | SOURCE OTHER { nss_error("no opening bracket"); YYABORT; } +- | error OTHER { nss_error($2); YYABORT; }; ++} | SOURCE LBRACKET status_exp_list SOURCE { nss_error("missing close bracket"); YYABORT; } ++ | SOURCE LBRACKET status_exp_list NL { nss_error("missing close bracket"); YYABORT; } ++ | SOURCE LBRACKET SOURCE { nss_error($3); YYABORT; } ++ | error SOURCE { nss_error($2); YYABORT; }; + + status_exp_list: status_exp + | status_exp status_exp_list +@@ -117,17 +118,17 @@ status_exp: STATUS EQUAL ACTION + } | BANG STATUS EQUAL ACTION + { + set_action(act, $2, $4, 1); +-} | STATUS EQUAL OTHER {nss_error($3); YYABORT; } +- | STATUS OTHER {nss_error($2); YYABORT; } +- | BANG STATUS EQUAL OTHER {nss_error($4); YYABORT; } +- | BANG STATUS OTHER {nss_error($3); YYABORT; } +- | BANG OTHER {nss_error($2); YYABORT; }; ++} | STATUS EQUAL SOURCE {nss_error($3); YYABORT; } ++ | STATUS SOURCE {nss_error($2); YYABORT; } ++ | BANG STATUS EQUAL SOURCE {nss_error($4); YYABORT; } ++ | BANG STATUS SOURCE {nss_error($3); YYABORT; } ++ | BANG SOURCE {nss_error($2); YYABORT; }; + + %% + + static int nss_ignore(const char *s) + { +- logmsg("ignored invalid nsswitch config near [ %s ]", s); ++ logmsg("ignored unsupported autofs nsswitch source \"%s\"", s); + return(0); + } + +diff --git a/lib/nss_tok.l b/lib/nss_tok.l +index c435b63..1aede97 100644 +--- a/lib/nss_tok.l ++++ b/lib/nss_tok.l +@@ -62,13 +62,13 @@ extern unsigned int nss_automount_found; + + %option nounput + +-%x AUTOMOUNT ++%x AUTOMOUNT ACTIONSTR + + WS [[:blank:]]+ + + automount ([Aa][Uu][Tt][Oo][Mm][Oo][Uu][Nn][Tt]) + +-source files|yp|nis|nisplus|ldap|hesiod|winbind ++source [[:alnum:]@$%^&*()-+_":;?,<>./'{}~`]+ + + success ([Ss][Uu][Cc][Cc][Ee][Ss][Ss]) + notfound ([Nn][Oo][Tt][Ff][Oo][Uu][Nn][Dd]) +@@ -82,8 +82,6 @@ return ([Rr][Ee][Tt][Uu][Rr][Nn]) + + action ({continue}|{return}) + +-other [[:alnum:]@$%^&*()-+_":;?,<>./'{}~`]+ +- + %% + + ^{automount}: { +@@ -101,6 +99,14 @@ other [[:alnum:]@$%^&*()-+_":;?,<>./'{}~`]+ + return SOURCE; + } + ++ "[" { BEGIN(ACTIONSTR); yyless(0); } ++ ++ \n { BEGIN(INITIAL); return NL; } ++} ++ ++{ ++ {WS} { } ++ + {status} { + strcpy(nss_lval.strval, nss_text); + return STATUS; +@@ -112,15 +118,11 @@ other [[:alnum:]@$%^&*()-+_":;?,<>./'{}~`]+ + } + + "[" { return LBRACKET; } +- "]" { return RBRACKET; } ++ "]" { BEGIN(AUTOMOUNT); return RBRACKET; } + "=" { return EQUAL; } + "!" { return BANG; } + +- {other} { +- strcpy(nss_lval.strval, nss_text); +- return OTHER; +- } +- ++ . { BEGIN(AUTOMOUNT); yyless(0); } + \n { BEGIN(INITIAL); return NL; } + } + diff --git a/autofs.spec b/autofs.spec index 6e03775..54f61bb 100644 --- a/autofs.spec +++ b/autofs.spec @@ -4,7 +4,7 @@ Summary: A tool for automatically mounting and unmounting filesystems Name: autofs Version: 5.0.3 -Release: 13 +Release: 14 Epoch: 1 License: GPL Group: System Environment/Daemons @@ -22,6 +22,8 @@ Patch9: autofs-5.0.3-handle-zero-length-nis-key.patch Patch10: autofs-5.0.2-init-cb-on-load.patch Patch11: autofs-5.0.3-map-type-in-map-name.patch Patch12: autofs-5.0.3-mount-thread-create-cond-handling.patch +Patch13: autofs-5.0.3-nfs4-nohide-check.patch +Patch14: autofs-5.0.3-nss-source-any.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: autoconf, hesiod-devel, openldap-devel, bison, flex, libxml2-devel, cyrus-sasl-devel, openssl-devel module-init-tools util-linux nfs-utils e2fsprogs Conflicts: kernel < 2.6.17 @@ -75,6 +77,8 @@ echo %{version}-%{release} > .version %patch10 -p1 %patch11 -p1 %patch12 -p1 +%patch13 -p1 +%patch14 -p1 %build #CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr --libdir=%{_libdir} @@ -127,6 +131,10 @@ fi %{_libdir}/autofs/ %changelog +* Mon May 12 2008 Ian Kent - 5.0.3-14 +- check for nohide mounts (bz 442618). +- ignore nsswitch sources that aren't supported (bz 445880). + * Thu Apr 17 2008 Ian Kent - 5.0.3-13 - fix typo in patch for incorrect pthreads condition handling patch.