- check for nohide mounts (bz 442618).

- ignore nsswitch sources that aren't supported (bz 445880).
This commit is contained in:
Ian Kent 2008-05-12 06:13:46 +00:00
parent cc758546cf
commit c3a32a3333
3 changed files with 356 additions and 1 deletions

View File

@ -0,0 +1,196 @@
autofs 5.0.3 - check for nohide mounts
From: Ian Kent <raven@themaw.net>
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++;

View File

@ -0,0 +1,151 @@
autofs-5.0.3 - ignore nsswitch sources that aren't supported
From: Ian Kent <raven@themaw.net>
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 <strval> SOURCE
%token <strval> STATUS
%token <strval> ACTION
-%token <strval> 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; }
+}
+
+<ACTIONSTR>{
+ {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; }
}

View File

@ -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 <ikent@redhat.com> - 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 <ikent@redhat.com> - 5.0.3-13
- fix typo in patch for incorrect pthreads condition handling patch.