a46dbe
diff --git a/modules/pam_namespace/namespace.conf.5.xml b/modules/pam_namespace/namespace.conf.5.xml
a46dbe
index c7698cb..a94b49e 100644
a46dbe
--- a/modules/pam_namespace/namespace.conf.5.xml
a46dbe
+++ b/modules/pam_namespace/namespace.conf.5.xml
a46dbe
@@ -122,9 +122,14 @@
a46dbe
     <para><emphasis>mntopts</emphasis>=<replaceable>value</replaceable>
a46dbe
       - value of this flag is passed to the mount call when the tmpfs mount is
a46dbe
       done. It allows for example the specification of the maximum size of the
a46dbe
-      tmpfs instance that is created by the mount call. See <citerefentry>
a46dbe
-      <refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum>
a46dbe
-      </citerefentry> for details.
a46dbe
+      tmpfs instance that is created by the mount call. In addition to
a46dbe
+      options specified in the <citerefentry>
a46dbe
+      <refentrytitle>tmpfs</refentrytitle><manvolnum>5</manvolnum>
a46dbe
+      </citerefentry> manual the <emphasis>nosuid</emphasis>,
a46dbe
+      <emphasis>noexec</emphasis>, and <emphasis>nodev</emphasis> flags
a46dbe
+      can be used to respectively disable setuid bit effect, disable running
a46dbe
+      executables, and disable devices to be interpreted on the mounted
a46dbe
+      tmpfs filesystem.
a46dbe
     </para>
a46dbe
 
a46dbe
     <para>
a46dbe
diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
a46dbe
index f541f89..660c7a1 100644
a46dbe
--- a/modules/pam_namespace/pam_namespace.c
a46dbe
+++ b/modules/pam_namespace/pam_namespace.c
a46dbe
@@ -230,6 +230,73 @@ static int parse_iscript_params(char *params, struct polydir_s *poly)
a46dbe
     return 0;
a46dbe
 }
a46dbe
 
a46dbe
+struct mntflag {
a46dbe
+    const char *name;
a46dbe
+    size_t len;
a46dbe
+    unsigned long flag;
a46dbe
+};
a46dbe
+
a46dbe
+#define LITERAL_AND_LEN(x) x, sizeof(x) - 1
a46dbe
+
a46dbe
+static const struct mntflag mntflags[] = {
a46dbe
+	{ LITERAL_AND_LEN("noexec"), MS_NOEXEC },
a46dbe
+	{ LITERAL_AND_LEN("nosuid"), MS_NOSUID },
a46dbe
+	{ LITERAL_AND_LEN("nodev"), MS_NODEV }
a46dbe
+    };
a46dbe
+
a46dbe
+static int filter_mntopts(const char *opts, char **filtered,
a46dbe
+		unsigned long *mountflags)
a46dbe
+{
a46dbe
+    size_t origlen = strlen(opts);
a46dbe
+    const char *end;
a46dbe
+    char *dest;
a46dbe
+
a46dbe
+    dest = *filtered = NULL;
a46dbe
+    *mountflags = 0;
a46dbe
+
a46dbe
+    if (origlen == 0)
a46dbe
+	return 0;
a46dbe
+
a46dbe
+    do {
a46dbe
+	size_t len;
a46dbe
+	int i;
a46dbe
+
a46dbe
+	end = strchr(opts, ',');
a46dbe
+	if (end == NULL) {
a46dbe
+	    len = strlen(opts);
a46dbe
+	} else {
a46dbe
+	    len = end - opts;
a46dbe
+	}
a46dbe
+
a46dbe
+	for (i = 0; i < (int)(sizeof(mntflags)/sizeof(mntflags[0])); i++) {
a46dbe
+	    if (mntflags[i].len != len)
a46dbe
+		continue;
a46dbe
+	    if (memcmp(mntflags[i].name, opts, len) == 0) {
a46dbe
+		*mountflags |= mntflags[i].flag;
a46dbe
+		opts = end;
a46dbe
+		break;
a46dbe
+	    }
a46dbe
+	}
a46dbe
+
a46dbe
+	if (opts != end) {
a46dbe
+	    if (dest != NULL) {
a46dbe
+		*dest = ',';
a46dbe
+		++dest;
a46dbe
+	    } else {
a46dbe
+		dest = *filtered = calloc(1, origlen + 1);
a46dbe
+		if (dest == NULL)
a46dbe
+		    return -1;
a46dbe
+	    }
a46dbe
+	    memcpy(dest, opts, len);
a46dbe
+	    dest += len;
a46dbe
+	}
a46dbe
+
a46dbe
+	opts = end + 1;
a46dbe
+    } while (end != NULL);
a46dbe
+
a46dbe
+    return 0;
a46dbe
+}
a46dbe
+
a46dbe
 static int parse_method(char *method, struct polydir_s *poly,
a46dbe
 		struct instance_data *idata)
a46dbe
 {
a46dbe
@@ -289,7 +356,8 @@ static int parse_method(char *method, struct polydir_s *poly,
a46dbe
 					break;
a46dbe
 				}
a46dbe
 				free(poly->mount_opts); /* if duplicate mntopts specified */
a46dbe
-				if ((poly->mount_opts = strdup(flag+namelen+1)) == NULL) {
a46dbe
+				poly->mount_opts = NULL;
a46dbe
+				if (filter_mntopts(flag+namelen+1, &poly->mount_opts, &poly->mount_flags) != 0) {
a46dbe
 					pam_syslog(idata->pamh, LOG_CRIT, "Memory allocation error");
a46dbe
 					return -1;
a46dbe
 				}
a46dbe
@@ -1484,7 +1552,7 @@ static int ns_setup(struct polydir_s *polyptr,
a46dbe
     }
a46dbe
 
a46dbe
     if (polyptr->method == TMPFS) {
a46dbe
-	if (mount("tmpfs", polyptr->dir, "tmpfs", 0, polyptr->mount_opts) < 0) {
a46dbe
+	if (mount("tmpfs", polyptr->dir, "tmpfs", polyptr->mount_flags, polyptr->mount_opts) < 0) {
a46dbe
 	    pam_syslog(idata->pamh, LOG_ERR, "Error mounting tmpfs on %s, %m",
a46dbe
 		polyptr->dir);
a46dbe
             return PAM_SESSION_ERR;
a46dbe
diff --git a/modules/pam_namespace/pam_namespace.h b/modules/pam_namespace/pam_namespace.h
a46dbe
index 47ebcc3..1522386 100644
a46dbe
--- a/modules/pam_namespace/pam_namespace.h
a46dbe
+++ b/modules/pam_namespace/pam_namespace.h
a46dbe
@@ -166,6 +166,7 @@ struct polydir_s {
a46dbe
     unsigned int flags;			/* polydir flags */
a46dbe
     char *init_script;			/* path to init script */
a46dbe
     char *mount_opts;			/* mount options for tmpfs mount */
a46dbe
+    unsigned long mount_flags;		/* mount flags for tmpfs mount */
a46dbe
     uid_t owner;			/* user which should own the polydir */
a46dbe
     gid_t group;			/* group which should own the polydir */
a46dbe
     mode_t mode;			/* mode of the polydir */