92f3acf
diff -up Linux-PAM-1.1.5/modules/pam_namespace/pam_namespace.8.xml.rslave Linux-PAM-1.1.5/modules/pam_namespace/pam_namespace.8.xml
92f3acf
--- Linux-PAM-1.1.5/modules/pam_namespace/pam_namespace.8.xml.rslave	2011-06-21 11:04:56.000000000 +0200
92f3acf
+++ Linux-PAM-1.1.5/modules/pam_namespace/pam_namespace.8.xml	2012-01-31 16:40:36.495716240 +0100
92f3acf
@@ -246,12 +246,18 @@
92f3acf
 	    This option can be used on systems where the / mount point or
92f3acf
 	    its submounts are made shared (for example with a
92f3acf
 	    <command>mount --make-rshared /</command> command).
92f3acf
-	    The module will make the polyinstantiated directory mount points
92f3acf
-	    private. Normally the pam_namespace will try to detect the
92f3acf
+	    The module will mark the whole directory tree so any mount and
92f3acf
+	    unmount operations in the polyinstantiation namespace are private.
92f3acf
+	    Normally the pam_namespace will try to detect the
92f3acf
 	    shared / mount point and make the polyinstantiated directories
92f3acf
 	    private automatically. This option has to be used just when
92f3acf
 	    only a subtree is shared and / is not.
92f3acf
           </para>
92f3acf
+          <para>
92f3acf
+	    Note that mounts and unmounts done in the private namespace will not
92f3acf
+	    affect the parent namespace if this option is used or when the
92f3acf
+	    shared / mount point is autodetected.
92f3acf
+          </para>
92f3acf
         </listitem>
92f3acf
       </varlistentry>
92f3acf
 
92f3acf
diff -up Linux-PAM-1.1.5/modules/pam_namespace/pam_namespace.c.rslave Linux-PAM-1.1.5/modules/pam_namespace/pam_namespace.c
92f3acf
--- Linux-PAM-1.1.5/modules/pam_namespace/pam_namespace.c.rslave	2011-06-21 11:04:56.000000000 +0200
92f3acf
+++ Linux-PAM-1.1.5/modules/pam_namespace/pam_namespace.c	2012-01-31 16:42:07.762506791 +0100
92f3acf
@@ -1003,7 +1003,7 @@ static int protect_mount(int dfd, const
92f3acf
 	return 0;
92f3acf
 }
92f3acf
 
92f3acf
-static int protect_dir(const char *path, mode_t mode, int do_mkdir, int always,
92f3acf
+static int protect_dir(const char *path, mode_t mode, int do_mkdir,
92f3acf
 	struct instance_data *idata)
92f3acf
 {
92f3acf
 	char *p = strdup(path);
92f3acf
@@ -1082,7 +1082,7 @@ static int protect_dir(const char *path,
92f3acf
 		}
92f3acf
 	}
92f3acf
 
92f3acf
-	if ((flags & O_NOFOLLOW) || always) { 
92f3acf
+	if (flags & O_NOFOLLOW) {
92f3acf
 		/* we are inside user-owned dir - protect */
92f3acf
 		if (protect_mount(rv, p, idata) == -1) {
92f3acf
 			save_errno = errno;
92f3acf
@@ -1124,7 +1124,7 @@ static int check_inst_parent(char *ipath
92f3acf
 	if (trailing_slash)
92f3acf
 		*trailing_slash = '\0';
92f3acf
 
92f3acf
-	dfd = protect_dir(inst_parent, 0, 1, 0, idata);
92f3acf
+	dfd = protect_dir(inst_parent, 0, 1, idata);
92f3acf
 
92f3acf
 	if (dfd == -1 || fstat(dfd, &instpbuf) < 0) {
92f3acf
 		pam_syslog(idata->pamh, LOG_ERR,
92f3acf
@@ -1259,7 +1259,7 @@ static int create_polydir(struct polydir
92f3acf
     }
92f3acf
 #endif
92f3acf
 
92f3acf
-    rc = protect_dir(dir, mode, 1, idata->flags & PAMNS_MOUNT_PRIVATE, idata);
92f3acf
+    rc = protect_dir(dir, mode, 1, idata);
92f3acf
     if (rc == -1) {
92f3acf
             pam_syslog(idata->pamh, LOG_ERR,
92f3acf
                        "Error creating directory %s: %m", dir);
92f3acf
@@ -1447,7 +1447,7 @@ static int ns_setup(struct polydir_s *po
92f3acf
         pam_syslog(idata->pamh, LOG_DEBUG,
92f3acf
                "Set namespace for directory %s", polyptr->dir);
92f3acf
 
92f3acf
-    retval = protect_dir(polyptr->dir, 0, 0, idata->flags & PAMNS_MOUNT_PRIVATE, idata);
92f3acf
+    retval = protect_dir(polyptr->dir, 0, 0, idata);
92f3acf
 
92f3acf
     if (retval < 0 && errno != ENOENT) {
92f3acf
 	pam_syslog(idata->pamh, LOG_ERR, "Polydir %s access error: %m",
92f3acf
@@ -1534,22 +1534,6 @@ static int ns_setup(struct polydir_s *po
92f3acf
         goto error_out;
92f3acf
     }
92f3acf
 
92f3acf
-    if (idata->flags & PAMNS_MOUNT_PRIVATE) {
92f3acf
-        /*
92f3acf
-         * Make the polyinstantiated dir private mount. This depends
92f3acf
-         * on making the dir a mount point in the protect_dir call.
92f3acf
-         */
92f3acf
-        if (mount(polyptr->dir, polyptr->dir, NULL, MS_PRIVATE|MS_REC, NULL) < 0) {
92f3acf
-            pam_syslog(idata->pamh, LOG_ERR, "Error making %s a private mount, %m",
92f3acf
-                       polyptr->dir);
92f3acf
-            goto error_out;
92f3acf
-        }
92f3acf
-        if (idata->flags & PAMNS_DEBUG)
92f3acf
-            pam_syslog(idata->pamh, LOG_DEBUG,
92f3acf
-                      "Polyinstantiated directory %s made as private mount", polyptr->dir);
92f3acf
-
92f3acf
-    }
92f3acf
-
92f3acf
     /*
92f3acf
      * Bind mount instance directory on top of the polyinstantiated
92f3acf
      * directory to provide an instance of polyinstantiated directory
92f3acf
@@ -1720,6 +1704,18 @@ static int setup_namespace(struct instan
92f3acf
 		"Unable to unshare from parent namespace, %m");
92f3acf
             return PAM_SESSION_ERR;
92f3acf
         }
92f3acf
+	if (idata->flags & PAMNS_MOUNT_PRIVATE) {
92f3acf
+	    /* Remount / as SLAVE so that nothing mounted in the namespace 
92f3acf
+	       shows up in the parent */
92f3acf
+	    if (mount("/", "/", NULL, MS_SLAVE | MS_REC , NULL) < 0) {
92f3acf
+		pam_syslog(idata->pamh, LOG_ERR,
92f3acf
+			"Failed to mark / as a slave mount point, %m");
92f3acf
+		return PAM_SESSION_ERR;
92f3acf
+	    }
92f3acf
+	    if (idata->flags & PAMNS_DEBUG)
92f3acf
+		pam_syslog(idata->pamh, LOG_DEBUG,
92f3acf
+			"The / mount point was marked as slave");
92f3acf
+	}
92f3acf
     } else {
92f3acf
     	del_polydir_list(idata->polydirs_ptr);
92f3acf
         return PAM_SUCCESS;