Blame SOURCES/autofs-5.1.6-fix-autofs-mount-options-construction.patch

b2d21a
autofs-5.1.6 - fix autofs mount options construction
b2d21a
b2d21a
From: Ian Kent <raven@themaw.net>
b2d21a
b2d21a
There's an off by one length error in the autofs mount options
b2d21a
construction.
b2d21a
b2d21a
Consolidate the options construction into make_options_string() and
b2d21a
use snprintf() to verify the options length calculation is correct.
b2d21a
b2d21a
Signed-off-by: Ian Kent <raven@themaw.net>
b2d21a
---
b2d21a
 CHANGELOG         |    1 
b2d21a
 daemon/direct.c   |   46 ++-----------------------
b2d21a
 daemon/indirect.c |   23 +-----------
b2d21a
 include/mounts.h  |    3 +
b2d21a
 lib/mounts.c      |   98 +++++++++++++++++++++++++++++++++++++++++++++---------
b2d21a
 5 files changed, 92 insertions(+), 79 deletions(-)
b2d21a
b2d21a
--- autofs-5.1.4.orig/CHANGELOG
b2d21a
+++ autofs-5.1.4/CHANGELOG
b2d21a
@@ -80,6 +80,7 @@ xx/xx/2018 autofs-5.1.5
b2d21a
 - fix trailing dollar sun entry expansion.
b2d21a
 - initialize struct addrinfo for getaddrinfo() calls.
b2d21a
 - fix quoted string length calc in expandsunent().
b2d21a
+- fix autofs mount options construction.
b2d21a
 
b2d21a
 19/12/2017 autofs-5.1.4
b2d21a
 - fix spec file url.
b2d21a
--- autofs-5.1.4.orig/daemon/direct.c
b2d21a
+++ autofs-5.1.4/daemon/direct.c
b2d21a
@@ -348,29 +348,10 @@ int do_mount_autofs_direct(struct autofs
b2d21a
 	}
b2d21a
 
b2d21a
 	if (!mp->options) {
b2d21a
-		mp->options = make_options_string(ap->path, ap->kpipefd, str_direct);
b2d21a
+		mp->options = make_options_string(ap->path,
b2d21a
+				ap->kpipefd, str_direct, ap->flags);
b2d21a
 		if (!mp->options)
b2d21a
 			return 0;
b2d21a
-
b2d21a
-		if ((ap->flags & MOUNT_FLAG_STRICTEXPIRE) &&
b2d21a
-		    ((get_kver_major() == 5 && get_kver_minor() > 3) ||
b2d21a
-		     (get_kver_major() > 5))) {
b2d21a
-			char *tmp = realloc(mp->options, strlen(mp->options) + 12);
b2d21a
-			if (tmp) {
b2d21a
-				strcat(tmp, ",strictexpire");
b2d21a
-				mp->options = tmp;
b2d21a
-			}
b2d21a
-		}
b2d21a
-
b2d21a
-		if ((ap->flags & MOUNT_FLAG_IGNORE) &&
b2d21a
-		    ((get_kver_major() == 5 && get_kver_minor() > 4) ||
b2d21a
-		     (get_kver_major() > 5))) {
b2d21a
-			char *tmp = realloc(mp->options, strlen(mp->options) + 7);
b2d21a
-			if (tmp) {
b2d21a
-				strcat(tmp, ",ignore");
b2d21a
-				mp->options = tmp;
b2d21a
-			}
b2d21a
-		}
b2d21a
 	}
b2d21a
 
b2d21a
 	/* In case the directory doesn't exist, try to mkdir it */
b2d21a
@@ -676,29 +657,10 @@ int mount_autofs_offset(struct autofs_po
b2d21a
 	}
b2d21a
 
b2d21a
 	if (!mp->options) {
b2d21a
-		mp->options = make_options_string(ap->path, ap->kpipefd, str_offset);
b2d21a
+		mp->options = make_options_string(ap->path,
b2d21a
+				ap->kpipefd, str_offset, ap->flags);
b2d21a
 		if (!mp->options)
b2d21a
 			return MOUNT_OFFSET_OK;
b2d21a
-
b2d21a
-		if ((ap->flags & MOUNT_FLAG_STRICTEXPIRE) &&
b2d21a
-		    ((get_kver_major() == 5 && get_kver_minor() > 3) ||
b2d21a
-		     (get_kver_major() > 5))) {
b2d21a
-			char *tmp = realloc(mp->options, strlen(mp->options) + 12);
b2d21a
-			if (tmp) {
b2d21a
-				strcat(tmp, ",strictexpire");
b2d21a
-				mp->options = tmp;
b2d21a
-			}
b2d21a
-		}
b2d21a
-
b2d21a
-		if ((ap->flags & MOUNT_FLAG_IGNORE) &&
b2d21a
-		    ((get_kver_major() == 5 && get_kver_minor() > 4) ||
b2d21a
-		     (get_kver_major() > 5))) {
b2d21a
-			char *tmp = realloc(mp->options, strlen(mp->options) + 7);
b2d21a
-			if (tmp) {
b2d21a
-				strcat(tmp, ",ignore");
b2d21a
-				mp->options = tmp;
b2d21a
-			}
b2d21a
-		}
b2d21a
 	}
b2d21a
 
b2d21a
 	strcpy(mountpoint, root);
b2d21a
--- autofs-5.1.4.orig/daemon/indirect.c
b2d21a
+++ autofs-5.1.4/daemon/indirect.c
b2d21a
@@ -78,32 +78,13 @@ static int do_mount_autofs_indirect(stru
b2d21a
 		}
b2d21a
 	}
b2d21a
 
b2d21a
-	options = make_options_string(ap->path, ap->kpipefd, str_indirect);
b2d21a
+	options = make_options_string(ap->path,
b2d21a
+				ap->kpipefd, str_indirect, ap->flags);
b2d21a
 	if (!options) {
b2d21a
 		error(ap->logopt, "options string error");
b2d21a
 		goto out_err;
b2d21a
 	}
b2d21a
 
b2d21a
-	if ((ap->flags & MOUNT_FLAG_STRICTEXPIRE) &&
b2d21a
-	    ((get_kver_major() == 5 && get_kver_minor() > 3) ||
b2d21a
-	     (get_kver_major() > 5))) {
b2d21a
-		char *tmp = realloc(options, strlen(options) + 12);
b2d21a
-		if (tmp) {
b2d21a
-			strcat(tmp, ",strictexpire");
b2d21a
-			options = tmp;
b2d21a
-		}
b2d21a
-	}
b2d21a
-
b2d21a
-	if ((ap->flags & MOUNT_FLAG_IGNORE) &&
b2d21a
-	    ((get_kver_major() == 5 && get_kver_minor() > 4) ||
b2d21a
-	     (get_kver_major() > 5))) {
b2d21a
-		char *tmp = realloc(options, strlen(options) + 7);
b2d21a
-		if (tmp) {
b2d21a
-			strcat(tmp, ",ignore");
b2d21a
-			options = tmp;
b2d21a
-		}
b2d21a
-	}
b2d21a
-
b2d21a
 	/* In case the directory doesn't exist, try to mkdir it */
b2d21a
 	if (mkdir_path(root, mp_mode) < 0) {
b2d21a
 		if (errno != EEXIST && errno != EROFS) {
b2d21a
--- autofs-5.1.4.orig/include/mounts.h
b2d21a
+++ autofs-5.1.4/include/mounts.h
b2d21a
@@ -94,7 +94,8 @@ void free_amd_entry_list(struct list_hea
b2d21a
 unsigned int query_kproto_ver(void);
b2d21a
 unsigned int get_kver_major(void);
b2d21a
 unsigned int get_kver_minor(void);
b2d21a
-char *make_options_string(char *path, int kernel_pipefd, const char *extra);
b2d21a
+char *make_options_string(char *path, int pipefd,
b2d21a
+			  const char *type, unsigned int flags);
b2d21a
 char *make_mnt_name_string(char *path);
b2d21a
 int ext_mount_add(struct list_head *, const char *, unsigned int);
b2d21a
 int ext_mount_remove(struct list_head *, const char *);
b2d21a
--- autofs-5.1.4.orig/lib/mounts.c
b2d21a
+++ autofs-5.1.4/lib/mounts.c
b2d21a
@@ -599,43 +599,111 @@ void free_amd_entry_list(struct list_hea
b2d21a
 	}
b2d21a
 }
b2d21a
 
b2d21a
+static int cacl_max_options_len(unsigned int flags)
b2d21a
+{
b2d21a
+	unsigned int kver_major = get_kver_major();
b2d21a
+	unsigned int kver_minor = get_kver_minor();
b2d21a
+	int max_len;
b2d21a
+
b2d21a
+	/* %d and %u are maximum lenght of 10 and mount type is maximum
b2d21a
+	 * length of 9 (e. ",indirect").
b2d21a
+	 * The base temaplate is "fd=%d,pgrp=%u,minproto=5,maxproto=%d"
b2d21a
+	 * plus the length of mount type plus 1 for the NULL.
b2d21a
+	 */
b2d21a
+	max_len = 79 + 1;
b2d21a
+
b2d21a
+	if (kver_major < 5 || (kver_major == 5 && kver_minor < 4))
b2d21a
+		goto out;
b2d21a
+
b2d21a
+	/* maybe add ",strictexpire" */
b2d21a
+	if (flags & MOUNT_FLAG_STRICTEXPIRE)
b2d21a
+		max_len += 13;
b2d21a
+
b2d21a
+	if (kver_major == 5 && kver_minor < 5)
b2d21a
+		goto out;
b2d21a
+
b2d21a
+	/* maybe add ",ignore" */
b2d21a
+	if (flags & MOUNT_FLAG_IGNORE)
b2d21a
+		max_len += 7;
b2d21a
+out:
b2d21a
+	return max_len;
b2d21a
+}
b2d21a
+
b2d21a
 /*
b2d21a
  * Make common autofs mount options string
b2d21a
  */
b2d21a
-char *make_options_string(char *path, int pipefd, const char *extra)
b2d21a
+char *make_options_string(char *path, int pipefd,
b2d21a
+			  const char *type, unsigned int flags)
b2d21a
 {
b2d21a
+	unsigned int kver_major = get_kver_major();
b2d21a
+	unsigned int kver_minor = get_kver_minor();
b2d21a
 	char *options;
b2d21a
-	int len;
b2d21a
+	int max_len, len, new;
b2d21a
 
b2d21a
-	options = malloc(MAX_OPTIONS_LEN + 1);
b2d21a
+	max_len = cacl_max_options_len(flags);
b2d21a
+
b2d21a
+	options = malloc(max_len);
b2d21a
 	if (!options) {
b2d21a
 		logerr("can't malloc options string");
b2d21a
 		return NULL;
b2d21a
 	}
b2d21a
 
b2d21a
-	if (extra) 
b2d21a
-		len = snprintf(options, MAX_OPTIONS_LEN,
b2d21a
+	if (type)
b2d21a
+		len = snprintf(options, max_len,
b2d21a
 				options_template_extra,
b2d21a
 				pipefd, (unsigned) getpgrp(),
b2d21a
-				AUTOFS_MAX_PROTO_VERSION, extra);
b2d21a
+				AUTOFS_MAX_PROTO_VERSION, type);
b2d21a
 	else
b2d21a
-		len = snprintf(options, MAX_OPTIONS_LEN, options_template,
b2d21a
+		len = snprintf(options, max_len, options_template,
b2d21a
 			pipefd, (unsigned) getpgrp(),
b2d21a
 			AUTOFS_MAX_PROTO_VERSION);
b2d21a
 
b2d21a
-	if (len >= MAX_OPTIONS_LEN) {
b2d21a
-		logerr("buffer to small for options - truncated");
b2d21a
-		len = MAX_OPTIONS_LEN - 1;
b2d21a
+	if (len < 0)
b2d21a
+		goto error_out;
b2d21a
+
b2d21a
+	if (len >= max_len)
b2d21a
+		goto truncated;
b2d21a
+
b2d21a
+	if (kver_major < 5 || (kver_major == 5 && kver_minor < 4))
b2d21a
+		goto out;
b2d21a
+
b2d21a
+	/* maybe add ",strictexpire" */
b2d21a
+	if (flags & MOUNT_FLAG_STRICTEXPIRE) {
b2d21a
+		new = snprintf(options + len,
b2d21a
+			       max_len, "%s", ",strictexpire");
b2d21a
+		if (new < 0)
b2d21a
+		       goto error_out;
b2d21a
+		len += new;
b2d21a
+		if (len >= max_len)
b2d21a
+			goto truncated;
b2d21a
 	}
b2d21a
 
b2d21a
-	if (len < 0) {
b2d21a
-		logerr("failed to malloc autofs mount options for %s", path);
b2d21a
-		free(options);
b2d21a
-		return NULL;
b2d21a
+	if (kver_major == 5 && kver_minor < 5)
b2d21a
+		goto out;
b2d21a
+
b2d21a
+	/* maybe add ",ignore" */
b2d21a
+	if (flags & MOUNT_FLAG_IGNORE) {
b2d21a
+		new = snprintf(options + len,
b2d21a
+			       max_len, "%s", ",ignore");
b2d21a
+		if (new < 0)
b2d21a
+		       goto error_out;
b2d21a
+		len += new;
b2d21a
+		if (len >= max_len)
b2d21a
+			goto truncated;
b2d21a
 	}
b2d21a
+out:
b2d21a
 	options[len] = '\0';
b2d21a
-
b2d21a
 	return options;
b2d21a
+
b2d21a
+truncated:
b2d21a
+	logerr("buffer to small for options - truncated");
b2d21a
+	len = max_len -1;
b2d21a
+	goto out;
b2d21a
+
b2d21a
+error_out:
b2d21a
+	logerr("error constructing mount options string for %s", path);
b2d21a
+	free(options);
b2d21a
+	return NULL;
b2d21a
 }
b2d21a
 
b2d21a
 char *make_mnt_name_string(char *path)