Blame SOURCES/autofs-5.1.6-make-bind-mounts-propagation-slave-by-default.patch

9a499a
autofs-5.1.6 - make bind mounts propagation slave by default
9a499a
9a499a
From: Ian Kent <raven@themaw.net>
9a499a
9a499a
Make setting mount propagation on bind mounts mandatory with a default
9a499a
of propagation slave.
9a499a
9a499a
When using multi-mounts that have bind mounts the bind mount will have
9a499a
the same properties as its parent which is commonly propagation shared.
9a499a
And if the mount target is also propagation shared this can lead to a
9a499a
deadlock when attempting to access the offset mounts. When this happens
9a499a
an unwanted offset mount is propagated back to the target file system
9a499a
resulting in a deadlock since the automount target is itself an
9a499a
(unwanted) automount trigger.
9a499a
9a499a
This problem has been present much longer than I originally thought,
9a499a
perhaps since mount propagation was introduced into the kernel, so
9a499a
explicitly setting bind mount propagation is the sensible thing to do.
9a499a
9a499a
Signed-off-by: Ian Kent <raven@themaw.net>
9a499a
---
9a499a
 CHANGELOG            |    1 +
9a499a
 include/automount.h  |    9 +++++----
9a499a
 lib/master_parse.y   |   29 +++++++++++++++++------------
9a499a
 lib/master_tok.l     |    1 +
9a499a
 modules/mount_bind.c |   40 ++++++++++++++++++++++------------------
9a499a
 5 files changed, 46 insertions(+), 34 deletions(-)
9a499a
9a499a
--- autofs-5.1.4.orig/include/automount.h
9a499a
+++ autofs-5.1.4/include/automount.h
9a499a
@@ -551,14 +551,15 @@ struct kernel_mod_version {
9a499a
 #define MOUNT_FLAG_AMD_CACHE_ALL	0x0080
9a499a
 
9a499a
 /* Set mount propagation for bind mounts */
9a499a
-#define MOUNT_FLAG_SLAVE		0x0100
9a499a
-#define MOUNT_FLAG_PRIVATE		0x0200
9a499a
+#define MOUNT_FLAG_SHARED		0x0100
9a499a
+#define MOUNT_FLAG_SLAVE		0x0200
9a499a
+#define MOUNT_FLAG_PRIVATE		0x0400
9a499a
 
9a499a
 /* Use strict expire semantics if requested and kernel supports it */
9a499a
-#define MOUNT_FLAG_STRICTEXPIRE		0x0400
9a499a
+#define MOUNT_FLAG_STRICTEXPIRE		0x0800
9a499a
 
9a499a
 /* Indicator for applications to ignore the mount entry */
9a499a
-#define MOUNT_FLAG_IGNORE		0x0800
9a499a
+#define MOUNT_FLAG_IGNORE		0x1000
9a499a
 
9a499a
 struct autofs_point {
9a499a
 	pthread_t thid;
9a499a
--- autofs-5.1.4.orig/lib/master_parse.y
9a499a
+++ autofs-5.1.4/lib/master_parse.y
9a499a
@@ -59,8 +59,6 @@ static long timeout;
9a499a
 static long negative_timeout;
9a499a
 static unsigned symlnk;
9a499a
 static unsigned strictexpire;
9a499a
-static unsigned slave;
9a499a
-static unsigned private;
9a499a
 static unsigned nobind;
9a499a
 static unsigned ghost;
9a499a
 extern unsigned global_selection_options;
9a499a
@@ -72,6 +70,14 @@ static int tmp_argc;
9a499a
 static char **local_argv;
9a499a
 static int local_argc;
9a499a
 
9a499a
+#define PROPAGATION_SHARED	MOUNT_FLAG_SHARED
9a499a
+#define PROPAGATION_SLAVE	MOUNT_FLAG_SLAVE
9a499a
+#define PROPAGATION_PRIVATE	MOUNT_FLAG_PRIVATE
9a499a
+#define PROPAGATION_MASK	(MOUNT_FLAG_SHARED | \
9a499a
+				 MOUNT_FLAG_SLAVE  | \
9a499a
+				 MOUNT_FLAG_PRIVATE)
9a499a
+static unsigned int propagation;
9a499a
+
9a499a
 static char errstr[MAX_ERR_LEN];
9a499a
 
9a499a
 static unsigned int verbose;
9a499a
@@ -106,7 +112,7 @@ static int master_fprintf(FILE *, char *
9a499a
 %token MAP
9a499a
 %token OPT_TIMEOUT OPT_NTIMEOUT OPT_NOBIND OPT_NOGHOST OPT_GHOST OPT_VERBOSE
9a499a
 %token OPT_DEBUG OPT_RANDOM OPT_USE_WEIGHT OPT_SYMLINK OPT_MODE
9a499a
-%token OPT_STRICTEXPIRE OPT_SLAVE OPT_PRIVATE
9a499a
+%token OPT_STRICTEXPIRE OPT_SHARED OPT_SLAVE OPT_PRIVATE
9a499a
 %token COLON COMMA NL DDASH
9a499a
 %type <strtype> map
9a499a
 %type <strtype> options
9a499a
@@ -208,6 +214,7 @@ line:
9a499a
 	| PATH OPT_TIMEOUT { master_notify($1); YYABORT; }
9a499a
 	| PATH OPT_SYMLINK { master_notify($1); YYABORT; }
9a499a
 	| PATH OPT_STRICTEXPIRE { master_notify($1); YYABORT; }
9a499a
+	| PATH OPT_SHARED { master_notify($1); YYABORT; }
9a499a
 	| PATH OPT_SLAVE { master_notify($1); YYABORT; }
9a499a
 	| PATH OPT_PRIVATE { master_notify($1); YYABORT; }
9a499a
 	| PATH OPT_NOBIND { master_notify($1); YYABORT; }
9a499a
@@ -622,8 +629,9 @@ daemon_option: OPT_TIMEOUT NUMBER { time
9a499a
 	| OPT_NTIMEOUT NUMBER { negative_timeout = $2; }
9a499a
 	| OPT_SYMLINK	{ symlnk = 1; }
9a499a
 	| OPT_STRICTEXPIRE { strictexpire = 1; }
9a499a
-	| OPT_SLAVE	{ slave = 1; }
9a499a
-	| OPT_PRIVATE	{ private = 1; }
9a499a
+	| OPT_SHARED	{ propagation = PROPAGATION_SHARED; }
9a499a
+	| OPT_SLAVE	{ propagation = PROPAGATION_SLAVE; }
9a499a
+	| OPT_PRIVATE	{ propagation = PROPAGATION_PRIVATE; }
9a499a
 	| OPT_NOBIND	{ nobind = 1; }
9a499a
 	| OPT_NOGHOST	{ ghost = 0; }
9a499a
 	| OPT_GHOST	{ ghost = 1; }
9a499a
@@ -697,8 +705,7 @@ static void local_init_vars(void)
9a499a
 	negative_timeout = 0;
9a499a
 	symlnk = 0;
9a499a
 	strictexpire = 0;
9a499a
-	slave = 0;
9a499a
-	private = 0;
9a499a
+	propagation = PROPAGATION_SLAVE;
9a499a
 	nobind = 0;
9a499a
 	ghost = defaults_get_browse_mode();
9a499a
 	random_selection = global_selection_options & MOUNT_FLAG_RANDOM_SELECT;
9a499a
@@ -888,7 +895,6 @@ int master_parse_entry(const char *buffe
9a499a
 			ghost = 1;
9a499a
 	}
9a499a
 
9a499a
-
9a499a
 	if (!entry->ap) {
9a499a
 		ret = master_add_autofs_point(entry, logopt, nobind, ghost, 0);
9a499a
 		if (!ret) {
9a499a
@@ -899,6 +905,9 @@ int master_parse_entry(const char *buffe
9a499a
 			return 0;
9a499a
 		}
9a499a
 	}
9a499a
+	entry->ap->flags &= ~(PROPAGATION_MASK);
9a499a
+	entry->ap->flags |= propagation;
9a499a
+
9a499a
 	if (random_selection)
9a499a
 		entry->ap->flags |= MOUNT_FLAG_RANDOM_SELECT;
9a499a
 	if (use_weight)
9a499a
@@ -907,10 +916,6 @@ int master_parse_entry(const char *buffe
9a499a
 		entry->ap->flags |= MOUNT_FLAG_SYMLINK;
9a499a
 	if (strictexpire)
9a499a
 		entry->ap->flags |= MOUNT_FLAG_STRICTEXPIRE;
9a499a
-	if (slave)
9a499a
-		entry->ap->flags |= MOUNT_FLAG_SLAVE;
9a499a
-	if (private)
9a499a
-		entry->ap->flags |= MOUNT_FLAG_PRIVATE;
9a499a
 	if (negative_timeout)
9a499a
 		entry->ap->negative_timeout = negative_timeout;
9a499a
 	if (mode && mode < LONG_MAX)
9a499a
--- autofs-5.1.4.orig/lib/master_tok.l
9a499a
+++ autofs-5.1.4/lib/master_tok.l
9a499a
@@ -389,6 +389,7 @@ MODE		(--mode{OPTWS}|--mode{OPTWS}={OPTW
9a499a
 	-?symlink		{ return(OPT_SYMLINK); }
9a499a
 	-?nobind		{ return(OPT_NOBIND); }
9a499a
 	-?nobrowse		{ return(OPT_NOGHOST); }
9a499a
+	-?shared		{ return(OPT_SHARED); }
9a499a
 	-?slave			{ return(OPT_SLAVE); }
9a499a
 	-?private		{ return(OPT_PRIVATE); }
9a499a
 	-?strictexpire		{ return(OPT_STRICTEXPIRE); }
9a499a
--- autofs-5.1.4.orig/modules/mount_bind.c
9a499a
+++ autofs-5.1.4/modules/mount_bind.c
9a499a
@@ -153,6 +153,7 @@ int mount_mount(struct autofs_point *ap,
9a499a
 
9a499a
 	if (!symlnk && bind_works) {
9a499a
 		int status, existed = 1;
9a499a
+		int flags;
9a499a
 
9a499a
 		debug(ap->logopt, MODPREFIX "calling mkdir_path %s", fullpath);
9a499a
 
9a499a
@@ -190,24 +191,27 @@ int mount_mount(struct autofs_point *ap,
9a499a
 			      what, fstype, fullpath);
9a499a
 		}
9a499a
 
9a499a
-		if (ap->flags & (MOUNT_FLAG_SLAVE | MOUNT_FLAG_PRIVATE)) {
9a499a
-			int flags = MS_SLAVE;
9a499a
-
9a499a
-			if (ap->flags & MOUNT_FLAG_PRIVATE)
9a499a
-				flags = MS_PRIVATE;
9a499a
-
9a499a
-			/* The bind mount has succeeded but if the target
9a499a
-			 * mount is propagation shared propagation of child
9a499a
-			 * mounts (autofs offset mounts for example) back to
9a499a
-			 * the target of the bind mount must be avoided or
9a499a
-			 * autofs trigger mounts will deadlock.
9a499a
-			 */
9a499a
-			err = mount(NULL, fullpath, NULL, flags, NULL);
9a499a
-			if (err) {
9a499a
-				warn(ap->logopt,
9a499a
-				     "failed to set propagation for %s",
9a499a
-				     fullpath, root);
9a499a
-			}
9a499a
+		/* The bind mount has succeeded, now set the mount propagation.
9a499a
+		 *
9a499a
+		 * The default is propagation shared, change it if the master
9a499a
+		 * map entry has a different option specified.
9a499a
+		 */
9a499a
+		flags = MS_SLAVE;
9a499a
+		if (ap->flags & MOUNT_FLAG_PRIVATE)
9a499a
+			flags = MS_PRIVATE;
9a499a
+		else if (ap->flags & MOUNT_FLAG_SHARED)
9a499a
+			flags = MS_SHARED;
9a499a
+
9a499a
+		/* Note: If the parent mount is propagation shared propagation
9a499a
+		 *  of child mounts (autofs offset mounts for example) back to
9a499a
+		 *  the target of the bind mount can happen in some cases and
9a499a
+		 *  must be avoided or autofs trigger mounts will deadlock.
9a499a
+		 */
9a499a
+		err = mount(NULL, fullpath, NULL, flags, NULL);
9a499a
+		if (err) {
9a499a
+			warn(ap->logopt,
9a499a
+			     "failed to set propagation for %s",
9a499a
+			     fullpath, root);
9a499a
 		}
9a499a
 
9a499a
 		return 0;
9a499a
--- autofs-5.1.4.orig/CHANGELOG
9a499a
+++ autofs-5.1.4/CHANGELOG
9a499a
@@ -114,6 +114,7 @@ xx/xx/2018 autofs-5.1.5
9a499a
 - use defines for expire type.
9a499a
 - remove unused function dump_master().
9a499a
 - fix additional typing errors.
9a499a
+- make bind mounts propagation slave by default.
9a499a
 
9a499a
 19/12/2017 autofs-5.1.4
9a499a
 - fix spec file url.