Blob Blame Raw
diff --git a/configure.ac b/configure.ac
index b4c76cd..5785734 100644
--- a/configure.ac
+++ b/configure.ac
@@ -404,7 +404,6 @@ AC_CONFIG_FILES([
    src/lib/runtime/files/group/Makefile
    src/lib/runtime/files/passwd/Makefile
    src/lib/runtime/files/resolvconf/Makefile
-   src/lib/runtime/files/libs/Makefile
    src/lib/runtime/mounts/Makefile
    src/lib/runtime/mounts/cwd/Makefile
    src/lib/runtime/mounts/dev/Makefile
@@ -412,9 +411,11 @@ AC_CONFIG_FILES([
    src/lib/runtime/mounts/home/Makefile
    src/lib/runtime/mounts/hostfs/Makefile
    src/lib/runtime/mounts/kernelfs/Makefile
+   src/lib/runtime/mounts/libs/Makefile
    src/lib/runtime/mounts/tmp/Makefile
    src/lib/runtime/mounts/userbinds/Makefile
    src/lib/runtime/mounts/scratch/Makefile
+   src/lib/runtime/mounts/domounts/Makefile
    src/lib/runtime/enter/Makefile
    src/lib/runtime/enter/chroot/Makefile
    src/lib/runtime/environment/Makefile
diff --git a/etc/singularity.conf.in b/etc/singularity.conf.in
index ecfff37..61a9cbd 100644
--- a/etc/singularity.conf.in
+++ b/etc/singularity.conf.in
@@ -137,6 +137,14 @@ bind path = /etc/hosts
 @ENABLE_OVERLAY@ = @ENABLE_OVERLAY_DEFAULT@
 
 
+# ENABLE UNDERLAY: [yes/no]
+# DEFAULT: @ENABLE_UNDERLAY_DEFAULT@
+# Enabling this option will make it possible to specify bind paths to locations
+# that do not currently exist within the container, similar to the overlay
+# option.  This will only be used if overlay is not enabled.
+@ENABLE_UNDERLAY@ = @ENABLE_UNDERLAY_DEFAULT@
+
+
 # MOUNT SLAVE: [BOOL]
 # DEFAULT: @MOUNT_SLAVE_DEFAULT@
 # Should we automatically propagate file-system changes from the host?
diff --git a/src/Makefile.am b/src/Makefile.am
index 9cb40b6..e1eff01 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -15,7 +15,7 @@ EXTRA_PROGRAMS = action-suid mount-suid start-suid
 cleanupd_SOURCES = cleanupd.c util/util.c util/file.c util/message.c util/privilege.c util/config_parser.c util/registry.c
 cleanupd_CPPFLAGS = $(AM_CPPFLAGS)
 
-action_SOURCES = action.c util/util.c util/file.c util/registry.c util/privilege.c util/sessiondir.c util/suid.c util/cleanupd.c util/daemon.c util/mount.c
+action_SOURCES = action.c util/util.c util/file.c util/registry.c util/privilege.c util/sessiondir.c util/suid.c util/cleanupd.c util/daemon.c util/mount.c util/mountlist.c
 action_LDADD = lib/image/libsingularity-image.la lib/runtime/libsingularity-runtime.la action-lib/libinternal.la
 action_CPPFLAGS = $(AM_CPPFLAGS)
 
@@ -24,7 +24,7 @@ builddef_LDADD = lib/image/libsingularity-image.la lib/runtime/libsingularity-ru
 builddef_CPPFLAGS = $(AM_CPPFLAGS)
 builddef_LDFLAGS = -static
 
-start_SOURCES = start.c util/util.c util/file.c util/registry.c util/privilege.c util/sessiondir.c util/suid.c util/cleanupd.c util/fork.c util/daemon.c util/signal.c util/mount.c
+start_SOURCES = start.c util/util.c util/file.c util/registry.c util/privilege.c util/sessiondir.c util/suid.c util/cleanupd.c util/fork.c util/daemon.c util/signal.c util/mount.c util/mountlist.c
 start_LDADD = lib/image/libsingularity-image.la lib/runtime/libsingularity-runtime.la action-lib/libinternal.la
 start_CPPFLAGS = $(AM_CPPFLAGS)
 
@@ -33,7 +33,7 @@ docker_extract_LDADD = -larchive
 docker_extract_CPPFLAGS = $(AM_CPPFLAGS)
 docker_extract_LDFLAGS = -static
 
-mount_SOURCES = mount.c util/util.c util/file.c util/registry.c util/suid.c util/privilege.c util/mount.c
+mount_SOURCES = mount.c util/util.c util/file.c util/registry.c util/suid.c util/privilege.c util/mount.c util/mountlist.c
 mount_LDADD = lib/image/libsingularity-image.la lib/runtime/libsingularity-runtime.la
 mount_CPPFLAGS = $(AM_CPPFLAGS)
 
diff --git a/src/lib/image/Makefile.am b/src/lib/image/Makefile.am
index 81e7161..44cfb42 100644
--- a/src/lib/image/Makefile.am
+++ b/src/lib/image/Makefile.am
@@ -13,7 +13,7 @@ distincludedir = $(includedir)/singularity
 noinst_LTLIBRARIES = libimage.la
 #libimage_la_LIBADD = bind/libinternal.la create/libinternal.la check/libinternal.la expand/libinternal.la mount/libinternal.la offset/libinternal.la open/libinternal.la ext3/libinternal.la dir/libinternal.la squashfs/libinternal.la
 libimage_la_LIBADD = ext3/libinternal.la dir/libinternal.la squashfs/libinternal.la
-libimage_la_SOURCES = image.c bind.c ../../util/registry.c ../../util/message.c ../../util/config_parser.c ../../util/privilege.c ../../util/util.c ../../util/file.c ../../util/suid.c ../../util/mount.c
+libimage_la_SOURCES = image.c bind.c ../../util/registry.c ../../util/message.c ../../util/config_parser.c ../../util/privilege.c ../../util/util.c ../../util/file.c ../../util/suid.c ../../util/mount.c ../../util/mountlist.c
 libimage_la_CFLAGS = $(AM_CFLAGS) # This fixes duplicate sources in library and progs
 
 distinclude_HEADERS = image.h bind.h
diff --git a/src/lib/runtime/Makefile.am b/src/lib/runtime/Makefile.am
index ed83005..d292cca 100644
--- a/src/lib/runtime/Makefile.am
+++ b/src/lib/runtime/Makefile.am
@@ -11,7 +11,7 @@ distincludedir = $(includedir)/singularity
 
 noinst_LTLIBRARIES = libinternal.la
 libinternal_la_LIBADD = ns/libinternal.la mounts/libinternal.la files/libinternal.la enter/libinternal.la overlayfs/libinternal.la environment/libinternal.la autofs/libinternal.la
-libinternal_la_SOURCES = runtime.c ../../util/fork.c ../../util/registry.c ../../util/message.c ../../util/config_parser.c ../../util/privilege.c ../../util/util.c ../../util/file.c ../../util/setns.c ../../util/mount.c ../../util/cleanupd.c ../../util/sessiondir.c ../../action-lib/ready.c
+libinternal_la_SOURCES = runtime.c ../../util/fork.c ../../util/registry.c ../../util/message.c ../../util/config_parser.c ../../util/privilege.c ../../util/util.c ../../util/file.c ../../util/setns.c ../../util/mount.c ../../util/cleanupd.c ../../util/sessiondir.c ../../action-lib/ready.c ../../util/mountlist.c
 libinternal_la_CFLAGS = $(AM_CFLAGS) # This fixes duplicate sources in library and progs
 
 distinclude_HEADERS = runtime.h
diff --git a/src/lib/runtime/files/Makefile.am b/src/lib/runtime/files/Makefile.am
index 017c0ee..c2551ce 100644
--- a/src/lib/runtime/files/Makefile.am
+++ b/src/lib/runtime/files/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = passwd group resolvconf libs
+SUBDIRS = passwd group resolvconf
 
 MAINTAINERCLEANFILES = Makefile.in
 DISTCLEANFILES = Makefile
@@ -11,7 +11,7 @@ AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\
 
 noinst_LTLIBRARIES = libinternal.la
 
-libinternal_la_LIBADD = passwd/libinternal.la group/libinternal.la resolvconf/libinternal.la libs/libinternal.la
+libinternal_la_LIBADD = passwd/libinternal.la group/libinternal.la resolvconf/libinternal.la
 libinternal_la_SOURCES = files.c file-bind.c
 
 EXTRA_DIST = file-bind.h files.h
diff --git a/src/lib/runtime/files/files.c b/src/lib/runtime/files/files.c
index 434d53c..915f81a 100644
--- a/src/lib/runtime/files/files.c
+++ b/src/lib/runtime/files/files.c
@@ -36,7 +36,6 @@
 #include "./passwd/passwd.h"
 #include "./group/group.h"
 #include "./resolvconf/resolvconf.h"
-#include "./libs/libs.h"
 
 
 int _singularity_runtime_files(void) {
@@ -46,7 +45,6 @@ int _singularity_runtime_files(void) {
     retval += _singularity_runtime_files_passwd();
     retval += _singularity_runtime_files_group();
     retval += _singularity_runtime_files_resolvconf();
-    retval += _singularity_runtime_files_libs();
 
     return(retval);
 }
diff --git a/src/lib/runtime/files/libs/Makefile.am b/src/lib/runtime/files/libs/Makefile.am
deleted file mode 100644
index f54f504..0000000
--- a/src/lib/runtime/files/libs/Makefile.am
+++ /dev/null
@@ -1,12 +0,0 @@
-MAINTAINERCLEANFILES = Makefile.in 
-DISTCLEANFILES = Makefile
-CLEANFILES = core.* *~ *.la
-
-AM_CFLAGS = -Wall -fpie
-AM_LDFLAGS = -pie
-AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DLIBEXECDIR=\"$(libexecdir)\" $(SINGULARITY_DEFINES)
-
-noinst_LTLIBRARIES = libinternal.la
-libinternal_la_SOURCES = libs.c
-
-EXTRA_DIST = libs.h
diff --git a/src/lib/runtime/files/libs/libs.c b/src/lib/runtime/files/libs/libs.c
deleted file mode 100644
index 4ba6f78..0000000
--- a/src/lib/runtime/files/libs/libs.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/* 
- * Copyright (c) 2017-2018, SyLabs, Inc. All rights reserved.
- * Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
- *
- * Copyright (c) 2015-2017, Gregory M. Kurtzer. All rights reserved.
- * 
- * Copyright (c) 2016-2017, The Regents of the University of California,
- * through Lawrence Berkeley National Laboratory (subject to receipt of any
- * required approvals from the U.S. Dept. of Energy).  All rights reserved.
- * 
- * This software is licensed under a customized 3-clause BSD license.  Please
- * consult LICENSE file distributed with the sources of this project regarding
- * your rights to use or distribute this software.
- * 
- * NOTICE.  This Software was developed under funding from the U.S. Department of
- * Energy and the U.S. Government consequently retains certain rights. As such,
- * the U.S. Government has been granted for itself and others acting on its
- * behalf a paid-up, nonexclusive, irrevocable, worldwide license in the Software
- * to reproduce, distribute copies to the public, prepare derivative works, and
- * perform publicly and display publicly, and to permit other to do so. 
- * 
-*/
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <libgen.h>
-#include <linux/limits.h>
-
-#include "config.h"
-#include "util/file.h"
-#include "util/util.h"
-#include "util/message.h"
-#include "util/privilege.h"
-#include "util/config_parser.h"
-#include "util/registry.h"
-#include "util/mount.h"
-
-#include "../file-bind.h"
-#include "../../runtime.h"
-
-
-int _singularity_runtime_files_libs(void) {
-    char *container_dir = CONTAINER_FINALDIR;
-    char *tmpdir = singularity_registry_get("SESSIONDIR");
-    char *includelibs_string;
-    char *libdir = joinpath(tmpdir, "/libs");
-    char *libdir_contained = joinpath(container_dir, "/.singularity.d/libs");
-
-    if ( ( includelibs_string = singularity_registry_get("CONTAINLIBS") ) != NULL ) {
-        char *tok = NULL;
-        char *current = strtok_r(strdup(includelibs_string), ",", &tok);
-
-        singularity_message(DEBUG, "Parsing SINGULARITY_CONTAINLIBS for user-specified libraries to include.\n");
-
-        free(includelibs_string);
-
-        singularity_message(DEBUG, "Checking if libdir in container exists: %s\n", libdir_contained);
-        if ( is_dir(libdir_contained) != 0 ) {
-            singularity_message(WARNING, "Library bind directory not present in container, update container\n");
-        }
-
-        singularity_message(DEBUG, "Creating session libdir at: %s\n", libdir);
-        if ( container_mkpath_nopriv(libdir, 0755) != 0 ) {
-            singularity_message(ERROR, "Failed creating temp lib directory at: %s\n", libdir);
-            ABORT(255);
-        }
-
-        while (current != NULL ) {
-            char *dest = NULL;
-            char *source = NULL;
-
-            singularity_message(DEBUG, "Evaluating requested library path: %s\n", current);
-
-            dest = joinpath(libdir, basename(current));
-
-            if ( is_file(dest) == 0 ) {
-                singularity_message(VERBOSE3, "Staged library exists, skipping: %s\n", current);
-                current = strtok_r(NULL, ",", &tok);
-                continue;
-            }
-
-            if ( is_link(current) == 0 ) {
-                char *link_name;
-                ssize_t len;
-
-                link_name = (char *) malloc(PATH_MAX);
-
-                len = readlink(current, link_name, PATH_MAX-1); // Flawfinder: ignore
-                if ( ( len > 0 ) && ( len <= PATH_MAX) ) {
-                    link_name[len] = '\0';
-                    singularity_message(VERBOSE3, "Found library link source: %s -> %s\n", current, link_name);
-                    if ( link_name[0] == '/' ) {
-                        source = strdup(link_name);
-                    } else {
-                        if ( link_name[0] == '/' ) {
-                            source = strdup(link_name);
-                        } else {
-                            source = joinpath(dirname(strdup(current)), link_name);
-                        }
-                    }
-                } else {
-                    singularity_message(WARNING, "Failed reading library link for %s: %s\n", current, strerror(errno));
-                    ABORT(255);
-                }
-                free(link_name);
-
-            } else if (is_file(current) == 0 ) {
-                source = strdup(current);
-                singularity_message(VERBOSE3, "Found library source: %s\n", source);
-            } else {
-                singularity_message(WARNING, "Could not find library: %s\n", current);
-                current = strtok_r(NULL, ",", &tok);
-                continue;
-            }
-
-            singularity_message(DEBUG, "Binding library source here: %s -> %s\n", source, dest);
-
-            if ( fileput_nopriv(dest, "") != 0 ) {
-                singularity_message(ERROR, "Failed creating file at %s: %s\n", dest, strerror(errno));
-                ABORT(255);
-            }
-
-            singularity_message(VERBOSE, "Binding file '%s' to '%s'\n", source, dest);
-            if ( singularity_mount(source, dest, NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0 ) {
-                    singularity_message(ERROR, "There was an error binding %s to %s: %s\n", source, dest, strerror(errno));
-                    ABORT(255);
-            }
-
-            free(source);
-            free(dest);
-            current = strtok_r(NULL, ",", &tok);
-        }
-
-        if ( is_dir(libdir_contained) != 0 ) {
-            char *ld_path;
-            singularity_message(DEBUG, "Attempting to create contained libdir\n");
-            if ( container_mkpath_priv(libdir_contained, 0755) != 0 ) {
-                singularity_message(ERROR, "Failed creating directory %s :%s\n", libdir_contained, strerror(errno));
-                ABORT(255);
-            }
-            ld_path = envar_path("LD_LIBRARY_PATH");
-            if ( ld_path == NULL ) {
-                singularity_message(DEBUG, "Setting LD_LIBRARY_PATH to '/.singularity.d/libs'\n");
-                envar_set("LD_LIBRARY_PATH", "/.singularity.d/libs", 1);
-            } else {
-                singularity_message(DEBUG, "Prepending '/.singularity.d/libs' to LD_LIBRARY_PATH\n");
-                envar_set("LD_LIBRARY_PATH", strjoin("/.singularity.d/libs:", ld_path), 1);
-            }
-        }
-
-        singularity_message(VERBOSE, "Binding libdir '%s' to '%s'\n", libdir, libdir_contained);
-        if ( singularity_mount(libdir, libdir_contained, NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0 ) {
-                singularity_message(ERROR, "There was an error binding %s to %s: %s\n", libdir, libdir_contained, strerror(errno));
-                ABORT(255);
-        }
-    }
-
-    return(0);
-}
diff --git a/src/lib/runtime/files/libs/libs.h b/src/lib/runtime/files/libs/libs.h
deleted file mode 100644
index e5f843d..0000000
--- a/src/lib/runtime/files/libs/libs.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* 
- * Copyright (c) 2017-2018, SyLabs, Inc. All rights reserved.
- * Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
- *
- * Copyright (c) 2015-2017, Gregory M. Kurtzer. All rights reserved.
- * 
- * Copyright (c) 2016-2017, The Regents of the University of California,
- * through Lawrence Berkeley National Laboratory (subject to receipt of any
- * required approvals from the U.S. Dept. of Energy).  All rights reserved.
- * 
- * This software is licensed under a customized 3-clause BSD license.  Please
- * consult LICENSE file distributed with the sources of this project regarding
- * your rights to use or distribute this software.
- * 
- * NOTICE.  This Software was developed under funding from the U.S. Department of
- * Energy and the U.S. Government consequently retains certain rights. As such,
- * the U.S. Government has been granted for itself and others acting on its
- * behalf a paid-up, nonexclusive, irrevocable, worldwide license in the Software
- * to reproduce, distribute copies to the public, prepare derivative works, and
- * perform publicly and display publicly, and to permit other to do so. 
- * 
-*/
-
-#ifndef __SINGULARITY_RUNTIME_FILES_LIBS_H_
-#define __SINGULARITY_RUNTIME_FILES_LIBS_H_
-
-extern int _singularity_runtime_files_libs(void);
-
-#endif /* __SINGULARITY_RUNTIME_FILES_LIBS_H */
-
diff --git a/src/lib/runtime/mounts/Makefile.am b/src/lib/runtime/mounts/Makefile.am
index f945dc2..8ec7c7f 100644
--- a/src/lib/runtime/mounts/Makefile.am
+++ b/src/lib/runtime/mounts/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = binds cwd dev home hostfs kernelfs scratch tmp userbinds
+SUBDIRS = binds cwd dev domounts home hostfs kernelfs libs scratch tmp userbinds
 
 MAINTAINERCLEANFILES = Makefile.in
 DISTCLEANFILES = Makefile
@@ -11,7 +11,7 @@ AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\
 
 noinst_LTLIBRARIES = libinternal.la
 
-libinternal_la_LIBADD = binds/libinternal.la cwd/libinternal.la dev/libinternal.la home/libinternal.la hostfs/libinternal.la kernelfs/libinternal.la scratch/libinternal.la tmp/libinternal.la userbinds/libinternal.la
+libinternal_la_LIBADD = binds/libinternal.la cwd/libinternal.la dev/libinternal.la domounts/libinternal.la home/libinternal.la hostfs/libinternal.la kernelfs/libinternal.la libs/libinternal.la scratch/libinternal.la tmp/libinternal.la userbinds/libinternal.la
 libinternal_la_SOURCES = mounts.c
 
 EXTRA_DIST = mounts.h
diff --git a/src/lib/runtime/mounts/binds/binds.c b/src/lib/runtime/mounts/binds/binds.c
index f27323b..4865aea 100644
--- a/src/lib/runtime/mounts/binds/binds.c
+++ b/src/lib/runtime/mounts/binds/binds.c
@@ -35,17 +35,17 @@
 #include "util/file.h"
 #include "util/util.h"
 #include "util/message.h"
-#include "util/privilege.h"
 #include "util/config_parser.h"
 #include "util/registry.h"
-#include "util/mount.h"
+#include "util/mountlist.h"
 
 #include "../../runtime.h"
 
 
-int _singularity_runtime_mount_binds(void) {
+int _singularity_runtime_mount_binds(struct mountlist *mountlist) {
     char *tmp_config_string;
-    char *container_dir = CONTAINER_FINALDIR;
+    char *source = NULL;
+    char *dest = NULL;
 
     if ( singularity_registry_get("CONTAIN") != NULL ) {
         singularity_message(DEBUG, "Skipping bind mounts as contain was requested\n");
@@ -60,14 +60,21 @@ int _singularity_runtime_mount_binds(void) {
     while ( *tmp_config_string_list != NULL ) {
         tmp_config_string = strdup(*tmp_config_string_list);
         tmp_config_string_list++;
-        char *source = strtok(tmp_config_string, ":");
-        char *dest = strtok(NULL, ":");
+        if (source != NULL)
+            free(source);
+        if (dest != NULL)
+            free(dest);
+        source = strtok(tmp_config_string, ":");
+        dest = strtok(NULL, ":");
+        source = strdup(source);
         chomp(source);
         if ( dest == NULL ) {
             dest = strdup(source);
         } else {
+            dest = strdup(dest);
             chomp(dest);
         }
+        free(tmp_config_string);
 
         singularity_message(VERBOSE2, "Found 'bind path' = %s, %s\n", source, dest);
 
@@ -76,62 +83,17 @@ int _singularity_runtime_mount_binds(void) {
             continue;
         }
 
-        singularity_message(DEBUG, "Checking if bind point is already mounted: %s\n", dest);
-        if ( check_mounted(dest) >= 0 ) {
-            singularity_message(VERBOSE, "Not mounting bind point (already mounted): %s\n", dest);
-            continue;
-        }
-
-        if ( ( is_file(source) == 0 ) && ( is_file(joinpath(container_dir, dest)) < 0 ) ) {
-            if ( singularity_registry_get("OVERLAYFS_ENABLED") != NULL ) {
-                char *basedir = dirname(joinpath(container_dir, dest));
-
-                singularity_message(DEBUG, "Checking base directory for file %s ('%s')\n", dest, basedir);
-                if ( is_dir(basedir) != 0 ) {
-                    singularity_message(DEBUG, "Creating base directory for file bind\n");
-                    if ( container_mkpath_priv(basedir, 0755) != 0 ) {
-                        singularity_message(ERROR, "Failed creating base directory to bind file: %s\n", dest);
-                        ABORT(255);
-                    }
-                }
-
-                free(basedir);
-
-                singularity_message(VERBOSE3, "Creating bind file on overlay file system: %s\n", dest);
-                if ( fileput_priv(joinpath(container_dir, dest), "") != 0 ) {
-                    continue;
-                }
-                singularity_message(DEBUG, "Created bind file: %s\n", dest);
-            } else {
-                singularity_message(WARNING, "Non existent bind point (file) in container: '%s'\n", dest);
-                continue;
-            }
-        } else if ( ( is_dir(source) == 0 ) && ( is_dir(joinpath(container_dir, dest)) < 0 ) ) {
-            if ( singularity_registry_get("OVERLAYFS_ENABLED") != NULL ) {
-                singularity_message(VERBOSE3, "Creating bind directory on overlay file system: %s\n", dest);
-                if ( container_mkpath_priv(joinpath(container_dir, dest), 0755) < 0 ) {
-                    singularity_message(WARNING, "Could not create bind point directory in container %s: %s\n", dest, strerror(errno));
-                    continue;
-                }
-            } else {
-                singularity_message(WARNING, "Non existent bind point (directory) in container: '%s'\n", dest);
-                continue;
-            }
-        }
-
-        singularity_message(VERBOSE, "Binding '%s' to '%s/%s'\n", source, container_dir, dest);
-        if ( singularity_mount(source, joinpath(container_dir, dest), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0 ) {
-            singularity_message(ERROR, "There was an error binding the path %s: %s\n", source, strerror(errno));
-            ABORT(255);
-        }
-        if ( singularity_priv_userns_enabled() != 1 ) {
-            if ( singularity_mount(NULL, joinpath(container_dir, dest), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC|MS_REMOUNT, NULL) < 0 ) {
-                singularity_message(ERROR, "There was an error remounting the path %s: %s\n", source, strerror(errno));
-                ABORT(255);
-            }
-        }
+        singularity_message(VERBOSE, "Queuing bind mount of '%s' to '%s'\n", source, dest);
+        mountlist_add(mountlist, source, dest, NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, 0);
+        source = NULL;
+        dest = NULL;
     }
 
+    if (source != NULL)
+        free(source);
+    if (dest != NULL)
+        free(dest);
+
     return(0);
 }
 
diff --git a/src/lib/runtime/mounts/binds/binds.h b/src/lib/runtime/mounts/binds/binds.h
index f555370..200ab76 100644
--- a/src/lib/runtime/mounts/binds/binds.h
+++ b/src/lib/runtime/mounts/binds/binds.h
@@ -24,7 +24,9 @@
 #ifndef __SINGULARITY_RUNTIME_MOUNT_BINDS_H_
 #define __SINGULARITY_RUNTIME_MOUNT_BINDS_H_
 
-extern int _singularity_runtime_mount_binds(void);
+struct mountlist;
+
+extern int _singularity_runtime_mount_binds(struct mountlist *mountlist);
 
 #endif /* __SINGULARITY_RUNTIME_MOUNT_BINDS_H */
 
diff --git a/src/lib/runtime/mounts/cwd/cwd.c b/src/lib/runtime/mounts/cwd/cwd.c
index c251edc..c90ffa4 100644
--- a/src/lib/runtime/mounts/cwd/cwd.c
+++ b/src/lib/runtime/mounts/cwd/cwd.c
@@ -40,18 +40,15 @@
 #include "util/file.h"
 #include "util/util.h"
 #include "util/message.h"
-#include "util/privilege.h"
 #include "util/config_parser.h"
 #include "util/registry.h"
-#include "util/mount.h"
+#include "util/mountlist.h"
 
 #include "../../runtime.h"
 
 
-int _singularity_runtime_mount_cwd(void) {
-    char *container_dir = CONTAINER_FINALDIR;
+int _singularity_runtime_mount_cwd(struct mountlist *mountlist) {
     char *cwd_path = (char *)malloc(PATH_MAX);
-    int r;
 
     singularity_message(DEBUG, "Checking to see if we should mount current working directory\n");
     if ( cwd_path == NULL ) {
@@ -73,34 +70,6 @@ int _singularity_runtime_mount_cwd(void) {
         return(0);
     }
 
-    singularity_message(DEBUG, "Checking if current directory already available within container: %s\n", cwd_path);
-    if ( is_dir(joinpath(container_dir, cwd_path)) == 0 ) {
-        char *cwd_fileid = file_devino(cwd_path);
-        char *container_cwd_fileid = file_devino(joinpath(container_dir, cwd_path));
-
-        singularity_message(DEBUG, "Checking if container's cwd == host's cwd\n");
-        if ( strcmp(cwd_fileid, container_cwd_fileid) == 0 ) {
-            singularity_message(VERBOSE, "Not mounting current directory: location already available within container\n");
-            free(cwd_path);
-            free(cwd_fileid);
-            free(container_cwd_fileid);
-            return(0);
-        } else {
-            singularity_message(DEBUG, "Container's cwd is not the same as the host, continuing on...\n");
-        }
-    } else {
-        singularity_message(VERBOSE, "Not mounting CWD, directory does not exist within container: %s\n", cwd_path);
-        free(cwd_path);
-        return(0);
-    }
-
-    singularity_message(DEBUG, "Checking if CWD is already mounted: %s\n", cwd_path);
-    if ( check_mounted(cwd_path) >= 0 ) {
-        singularity_message(VERBOSE, "Not mounting CWD (already mounted in container): %s\n", cwd_path);
-        free(cwd_path);
-        return(0);
-    }
-
     singularity_message(DEBUG, "Checking if cwd is in an operating system directory\n");
     if ( ( strcmp(cwd_path, "/") == 0 ) ||
          ( strcmp(cwd_path, "/bin") == 0 ) ||
@@ -131,16 +100,9 @@ int _singularity_runtime_mount_cwd(void) {
         return(0);
     }
 
-    singularity_message(VERBOSE, "Binding '%s' to '%s/%s'\n", cwd_path, container_dir, cwd_path);
-    r = singularity_mount(cwd_path, joinpath(container_dir, cwd_path), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, NULL);
-    if ( singularity_priv_userns_enabled() != 1 ) {
-        r = singularity_mount(NULL, joinpath(container_dir, cwd_path), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC|MS_REMOUNT, NULL);
-    }
-    if ( r < 0 ) {
-        singularity_message(WARNING, "Could not bind CWD to container %s: %s\n", cwd_path, strerror(errno));
-    }
+    singularity_message(VERBOSE, "Queuing bind mount of '%s' to '%s' if mountpoint exists\n", cwd_path, cwd_path);
+    mountlist_add(mountlist, NULL, cwd_path, NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, ML_ONLY_IF_POINT_PRESENT);
 
-    free(cwd_path);
     return(0);
 }
 
diff --git a/src/lib/runtime/mounts/cwd/cwd.h b/src/lib/runtime/mounts/cwd/cwd.h
index c2c9fd0..3404e12 100644
--- a/src/lib/runtime/mounts/cwd/cwd.h
+++ b/src/lib/runtime/mounts/cwd/cwd.h
@@ -24,7 +24,9 @@
 #ifndef __SINGULARITY_RUNTIME_MOUNT_CWD_H_
 #define __SINGULARITY_RUNTIME_MOUNT_CWD_H_
 
-extern int _singularity_runtime_mount_cwd(void);
+struct mountlist;
+
+extern int _singularity_runtime_mount_cwd(struct mountlist *mountlist);
 
 #endif /* __SINGULARITY_RUNTIME_MOUNT_CWD_H */
 
diff --git a/src/lib/runtime/mounts/dev/dev.c b/src/lib/runtime/mounts/dev/dev.c
index 7dc7a76..cbd6f19 100644
--- a/src/lib/runtime/mounts/dev/dev.c
+++ b/src/lib/runtime/mounts/dev/dev.c
@@ -43,14 +43,14 @@
 #include "util/registry.h"
 #include "util/mount.h"
 #include "util/suid.h"
+#include "util/mountlist.h"
 
 #include "../../runtime.h"
 
 static int bind_dev(char *tmpdir, char *dev);
 
 
-int _singularity_runtime_mount_dev(void) {
-    char *container_dir = CONTAINER_FINALDIR;
+int _singularity_runtime_mount_dev(struct mountlist *mountlist) {
 
     if ( ( singularity_registry_get("CONTAIN") != NULL ) || ( strcmp("minimal", singularity_config_get_value(MOUNT_DEV)) == 0 ) ) {
         char *sessiondir = singularity_registry_get("SESSIONDIR");
@@ -58,22 +58,6 @@ int _singularity_runtime_mount_dev(void) {
         char *nvopt = singularity_registry_get("NV"); 
         char memfs_type[] = "tmpfs";
 
-        if ( is_dir(joinpath(container_dir, "/dev")) < 0 ) {
-            int ret;
-
-            if ( singularity_registry_get("OVERLAYFS_ENABLED") == NULL ) {
-                singularity_message(WARNING, "Not mounting devices as /dev directory does not exist within container\n");
-                return(-1);
-            }
-
-            ret = container_mkpath_priv(joinpath(container_dir, "/dev"), 0755);
-
-            if ( ret < 0 ) {
-                singularity_message(ERROR, "Could not create /dev inside container\n");
-                ABORT(255);
-            }
-        }
-
         singularity_message(DEBUG, "Creating temporary staged /dev\n");
         if ( container_mkpath_nopriv(devdir, 0755) != 0 ) {
             singularity_message(ERROR, "Failed creating the session device directory %s: %s\n", devdir, strerror(errno));
@@ -220,31 +204,18 @@ int _singularity_runtime_mount_dev(void) {
                 free(devpts_opts);
         }
 
-        singularity_message(DEBUG, "Mounting minimal staged /dev into container\n");
-        if ( singularity_mount(devdir, joinpath(container_dir, "/dev"), NULL, MS_BIND|MS_REC, NULL) < 0 ) {
-            singularity_message(WARNING, "Could not stage dev tree: '%s' -> '%s': %s\n", devdir, joinpath(container_dir, "/dev"), strerror(errno));
-            free(sessiondir);
-            free(devdir);
-            return(-1);
-        }
+        singularity_message(DEBUG, "Queuing bind mount of minimal staged /dev to mount into container\n");
+        mountlist_add(mountlist, devdir, strdup("/dev"), NULL, MS_BIND|MS_REC, 0);
 
         free(sessiondir);
-        free(devdir);
 
         return(0);
     }
 
     singularity_message(DEBUG, "Checking configuration file for 'mount dev'\n");
     if ( singularity_config_get_bool_char(MOUNT_DEV) > 0 ) {
-        if ( is_dir(joinpath(container_dir, "/dev")) == 0 ) {
-                singularity_message(VERBOSE, "Bind mounting /dev\n");
-                if ( singularity_mount("/dev", joinpath(container_dir, "/dev"), NULL, MS_BIND|MS_NOSUID|MS_REC, NULL) < 0 ) {
-                    singularity_message(ERROR, "Could not bind mount container's /dev: %s\n", strerror(errno));
-                    ABORT(255);
-                }
-        } else {
-            singularity_message(WARNING, "Not mounting /dev, container has no bind directory\n");
-        }
+        singularity_message(VERBOSE, "Queuing bind mount of /dev\n");
+        mountlist_add(mountlist, NULL, strdup("/dev"), NULL, MS_BIND|MS_NOSUID|MS_REC, 0);
         return(0);
     }
 
diff --git a/src/lib/runtime/mounts/dev/dev.h b/src/lib/runtime/mounts/dev/dev.h
index 2e15d20..f929017 100644
--- a/src/lib/runtime/mounts/dev/dev.h
+++ b/src/lib/runtime/mounts/dev/dev.h
@@ -24,7 +24,9 @@
 #ifndef __SINGULARITY_RUNTIME_MOUNT_DEV_H_
 #define __SINGULARITY_RUNTIME_MOUNT_DEV_H_
 
-extern int _singularity_runtime_mount_dev(void);
+struct mountlist;
+
+extern int _singularity_runtime_mount_dev(struct mountlist *mountlist);
 
 #endif /* __SINGULARITY_RUNTIME_MOUNT_DEV_H */
 
diff --git a/src/lib/runtime/mounts/domounts/Makefile.am b/src/lib/runtime/mounts/domounts/Makefile.am
new file mode 100644
index 0000000..0774cef
--- /dev/null
+++ b/src/lib/runtime/mounts/domounts/Makefile.am
@@ -0,0 +1,12 @@
+MAINTAINERCLEANFILES = Makefile.in 
+DISTCLEANFILES = Makefile
+CLEANFILES = core.* *~ *.la
+
+AM_CFLAGS = -Wall -fpie
+AM_LDFLAGS = -pie
+AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DLIBEXECDIR=\"$(libexecdir)\" $(SINGULARITY_DEFINES)
+
+noinst_LTLIBRARIES = libinternal.la
+libinternal_la_SOURCES = domounts.c
+
+EXTRA_DIST = domounts.h
diff --git a/src/lib/runtime/mounts/domounts/domounts.c b/src/lib/runtime/mounts/domounts/domounts.c
new file mode 100644
index 0000000..485a87d
--- /dev/null
+++ b/src/lib/runtime/mounts/domounts/domounts.c
@@ -0,0 +1,415 @@
+/* 
+ * Copyright (c) 2017-2018, SyLabs, Inc. All rights reserved.
+ * Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
+ *
+ * Copyright (c) 2015-2017, Gregory M. Kurtzer. All rights reserved.
+ * 
+ * Copyright (c) 2016-2017, The Regents of the University of California,
+ * through Lawrence Berkeley National Laboratory (subject to receipt of any
+ * required approvals from the U.S. Dept. of Energy).  All rights reserved.
+ * 
+ * This software is licensed under a customized 3-clause BSD license.  Please
+ * consult LICENSE file distributed with the sources of this project regarding
+ * your rights to use or distribute this software.
+ * 
+ * NOTICE.  This Software was developed under funding from the U.S. Department of
+ * Energy and the U.S. Government consequently retains certain rights. As such,
+ * the U.S. Government has been granted for itself and others acting on its
+ * behalf a paid-up, nonexclusive, irrevocable, worldwide license in the Software
+ * to reproduce, distribute copies to the public, prepare derivative works, and
+ * perform publicly and display publicly, and to permit other to do so. 
+ * 
+*/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <libgen.h>
+
+#include "config.h"
+#include "util/config_parser.h"
+#include "util/file.h"
+#include "util/util.h"
+#include "util/message.h"
+#include "util/privilege.h"
+#include "util/registry.h"
+#include "util/mount.h"
+#include "util/mountlist.h"
+
+void singularity_runtime_domounts_init(struct mountlist *mountlist) {
+    memset(mountlist, 0, sizeof(*mountlist));
+
+    singularity_registry_set("UNDERLAY_ENABLED", NULL);
+    if ( ( singularity_config_get_bool_char(ENABLE_UNDERLAY) > 0 ) ) {
+        if ( singularity_registry_get("DISABLE_UNDERLAY") != NULL ) {
+            singularity_message(VERBOSE3, "Not enabling underlay via environment\n");
+        } else {
+            singularity_message(VERBOSE3, "Enabling underlay\n");
+            singularity_registry_set("UNDERLAY_ENABLED", "1");
+        }
+    }
+}
+
+static void bind_image_final(char *source, char *sub_path) {
+    char *target = joinpath(CONTAINER_FINALDIR, sub_path);
+    singularity_message(VERBOSE3, "Binding %s to %s\n", source, target);
+    if ( singularity_mount(source, target, NULL, MS_BIND|MS_NOSUID|MS_REC, NULL) < 0 ) {
+
+        singularity_message(ERROR, "Failed binding %s to %s\n", source, target);
+        ABORT(255);
+    }
+    free(target);
+}
+
+static void mount_missing(char *image_path, char *underlay_path, char *sub_path) {
+    DIR *dir;
+    struct dirent *dp; 
+    char *source = NULL;
+    char *target = NULL;
+    char *existing_path = NULL;
+    int binds = 0;
+
+    singularity_message(VERBOSE3, "Mounting missing files/directories from %s\n", image_path);
+
+    // First find an existing mountpoint inside the underlay directory, if any
+    if ( ( dir = opendir(underlay_path) ) == NULL ) {
+        singularity_message(ERROR, "Could not open underlay dir %s", underlay_path);
+        ABORT(255);
+    }
+    while ( (dp = readdir(dir) ) != NULL ) {
+        if ( ( strcmp(dp->d_name, ".") != 0 ) &&
+             ( strcmp(dp->d_name, "..") != 0 ) ) {
+            break;
+        }
+    }
+    if ( dp == NULL ) {
+        singularity_message(VERBOSE3, "Skipping empty underlay directory: %s\n", underlay_path);
+        closedir(dir);
+        return;
+    }
+    singularity_message(DEBUG, "There is at least one mountpoint in %s: %s\n", underlay_path, dp->d_name);
+    existing_path = joinpath(sub_path, dp->d_name);
+    closedir(dir);
+
+    // Now search through the image for missing mountpoints in the underlay
+    if ( ( dir = opendir(image_path) ) == NULL ) {
+        singularity_message(ERROR, "Could not open dir %s", image_path);
+        ABORT(255);
+    }
+
+    while ( ( dp = readdir(dir) ) != NULL ) {
+        if ( (strcmp(dp->d_name, ".") == 0 ) || (strcmp(dp->d_name, "..") == 0 ) )
+            continue;
+        if ( source != NULL )
+            free(source);
+        if ( target != NULL )
+            free(target);
+        source = joinpath(image_path, dp->d_name);
+        target = joinpath(underlay_path, dp->d_name);
+        char *new_sub_path;
+        if ( strcmp(sub_path, "/") == 0 )
+            new_sub_path = strdup(dp->d_name);
+        else
+            new_sub_path = joinpath(sub_path, dp->d_name);
+        struct stat statbuf;
+        int statret = lstat(target, &statbuf);
+
+        if ( is_link(source) == 0 ) {
+            if ( statret < 0 ) {
+                char link[PATH_MAX+1];
+                ssize_t linksize = readlink(source, link, PATH_MAX); // Flawfinder: ignore not controllable by user
+                if ( linksize <= 0 ) {
+                    singularity_message(WARNING, "Failure reading link info from %s, skipping: %s\n", source, strerror(errno));
+                } else { 
+                    link[linksize] = '\0';
+                    singularity_message(VERBOSE3, "Creating symlink on underlay file system: %s->%s\n", target, link);
+                    singularity_priv_escalate();
+                    if ( symlink(link, target) < 0 )
+                        singularity_message(WARNING, "Failure making link to %s at %s, skipping: %s\n", target, source, strerror(errno));
+                    singularity_priv_drop();
+                }
+            } else if ( S_ISDIR(statbuf.st_mode) ) {
+                // It has been replaced by a directory, recurse into it
+                mount_missing(source, target, new_sub_path);
+            } else {
+                singularity_message(VERBOSE3, "Link point on underlay file system already exists, skipping: %s\n", target);
+            }
+        } else if ( is_file(source) == 0 ) {
+            if ( statret < 0 ) {
+                singularity_message(VERBOSE3, "Creating file mountpoint on underlay file system: %s\n", target);
+                if ( fileput_priv(target, "") != 0 ) {
+                    singularity_message(ERROR, "Failed creating underlay file mountpoint: %s\n", target);
+                    ABORT(255);
+                }
+                bind_image_final(source, new_sub_path);
+                binds++;
+            } else {
+                singularity_message(VERBOSE3, "File mountpoint on underlay file system already exists, skipping: %s\n", target);
+            }
+        } else if ( is_dir(source) == 0 ) {
+            if ( statret < 0 ) {
+                singularity_message(VERBOSE3, "Creating directory mountpoint on underlay file system: %s\n", target);
+                if ( container_mkpath_priv(target, 0755) < 0 ) {
+                    singularity_message(ERROR, "Failed creating underlay directory mountpoint: %s\n", target);
+                    ABORT(255);
+                }
+                bind_image_final(source, new_sub_path);
+                binds++;
+            } else if ( S_ISDIR(statbuf.st_mode) ) {
+                mount_missing(source, target, new_sub_path);
+            } else {
+                singularity_message(VERBOSE3, "Skipping non-directory target with directory source: %s\n", target);
+            }
+        } else {
+            singularity_message(VERBOSE3, "Skipping source that is neither file nor directory nor symlink: %s\n", source);
+        }
+        free(new_sub_path);
+    }
+
+    if ( source != NULL )
+        free(source);
+    if ( target != NULL )
+        free(target);
+    closedir(dir);
+
+    if ( binds > 50 ) {
+        singularity_message(WARNING, "Underlay of /%s required more than 50 (%d) bind mounts\n",
+                existing_path, binds);
+    } else {
+        singularity_message(DEBUG, "Did %d bind mounts around /%s\n",
+                binds, existing_path);
+    }
+    free(existing_path);
+}
+
+static int do_mounts(struct mountlist *mountlist, int overlay) {
+    char *container_dir = CONTAINER_FINALDIR;
+    char *source = NULL;
+    char *target = NULL;
+    struct mountlist_point *point;
+
+    for (point = mountlist->first; point != NULL; point = point->next) {
+        source = (char *) point->source;
+        if ( source == NULL )
+            source = (char *) point->target;
+        if ( target != NULL )
+            free(target);
+        target = joinpath(container_dir, point->target);
+
+        if ( check_mounted(point->target) >= 0 ) {
+            // make the message only information if ML_ONLY_IF_POINT_PRESENT
+            int msglevel = ( point->mountlistflags & ML_ONLY_IF_POINT_PRESENT ) ? VERBOSE : WARNING;
+            singularity_message(msglevel, "Not mounting %s (already mounted in container)\n", point->target);
+            continue;
+        }
+
+        if ( ( is_file(source) == 0 ) && ( is_file(target) < 0 ) ) {
+            if ( point->mountlistflags & ML_ONLY_IF_POINT_PRESENT ) {
+                singularity_message(VERBOSE, "Not mounting '%s', file does not exist within container\n", source);
+                continue;
+            }
+            if ( overlay ) {
+                char *basedir = strdup(target);
+                basedir = dirname(basedir);
+
+                singularity_message(DEBUG, "Checking base directory for file %s ('%s')\n", target, basedir);
+                if ( is_dir(basedir) != 0 ) {
+                    singularity_message(DEBUG, "Creating base directory for file mount\n");
+                    if ( container_mkpath_priv(basedir, 0755) != 0 ) {
+                        singularity_message(ERROR, "Failed creating base directory for mounted file: %s\n", target);
+                        ABORT(255);
+                    }
+                }
+
+                free(basedir);
+
+                singularity_message(VERBOSE3, "Creating file mountpoint on overlay file system: %s\n", target);
+                if ( fileput_priv(target, "") != 0 ) {
+                    continue;
+                }
+                singularity_message(DEBUG, "Created bind file: %s\n", target);
+            } else {
+                singularity_message(WARNING, "Non existent mount point (file) in container: '%s'\n", target);
+                continue;
+            }
+        } else if ( ( is_dir(source) == 0 ) && ( is_dir(target) < 0 ) ) {
+            if ( point->mountlistflags & ML_ONLY_IF_POINT_PRESENT ) {
+                singularity_message(VERBOSE, "Not mounting '%s', directory does not exist within container\n", source);
+                continue;
+            }
+            if ( overlay ) {
+                singularity_message(VERBOSE3, "Creating mount directory on overlay file system: %s\n", target);
+                if ( container_mkpath_priv(target, 0755) < 0 ) {
+                    singularity_message(WARNING, "Could not create mount point directory in container %s: %s\n", target, strerror(errno));
+                    continue;
+                }
+            } else {
+                singularity_message(WARNING, "Non existent mountpoint (directory) in container: '%s'\n", target);
+                continue;
+            }
+        }
+
+        singularity_message(VERBOSE, "Mounting '%s' at '%s'\n", source, target);
+        int read_only = ( (point->mountflags & MS_RDONLY) != 0 );
+        point->mountflags &= ~MS_RDONLY;
+        if ( singularity_mount_point(point) < 0 ) {
+            singularity_message(ERROR, "There was an error mounting %s: %s\n", source, strerror(errno));
+            ABORT(255);
+        }
+
+        if ( read_only ) {
+            if ( singularity_priv_userns_enabled() == 1 ) {
+                singularity_message(WARNING, "Can not make mount read only within the user namespace: %s\n", target);
+            } else {
+                singularity_message(VERBOSE, "Remounting %s read-only\n", target);
+                point->mountflags |= MS_REMOUNT|MS_RDONLY;
+                if ( singularity_mount_point(point) < 0 ) {
+                    singularity_message(ERROR, "There was an error write-protecting the path %s: %s\n", source, strerror(errno));
+                    ABORT(255);
+                }
+                if ( access(target, W_OK) == 0 || (errno != EROFS && errno != EACCES) ) { // Flawfinder: ignore (precautionary confirmation, not necessary)
+                    singularity_message(ERROR, "Failed to write-protect the path %s: %s\n", source, strerror(errno));
+                    ABORT(255);
+                }
+            }
+        } else if ( singularity_priv_userns_enabled() != 1 ) {
+            point->mountflags |= MS_REMOUNT;
+            singularity_message(VERBOSE, "Remounting %s\n", target);
+            if ( singularity_mount_point(point) < 0 ) {
+                singularity_message(ERROR, "There was an error remounting the path %s: %s\n", source, strerror(errno));
+                ABORT(255);
+            }
+        }
+    }
+
+    if ( target != NULL )
+        free(target);
+    
+    return(0);
+}
+
+static int underlay_mounts(struct mountlist *mountlist) {
+    char *underlay_dir = joinpath(singularity_registry_get("SESSIONDIR"), "underlay");
+    char *image_dir = CONTAINER_MOUNTDIR;
+    char *final_dir = CONTAINER_FINALDIR;
+    char *source = NULL;
+    char *underlay_target = NULL;
+    char *image_target = NULL;
+    struct mountlist_point *point;
+
+    singularity_message(DEBUG, "Creating directory for underlay: %s\n", underlay_dir);
+    if ( container_mkpath_priv(underlay_dir, 0755) < 0 ) {
+        singularity_message(ERROR, "Failed creating underlay directory %s: %s\n", underlay_dir, strerror(errno));
+        ABORT(255);
+    }
+
+    singularity_message(DEBUG, "Unmounting final dir %s\n", final_dir);
+    singularity_priv_escalate();
+    if ( umount(final_dir) != 0 ) {
+        singularity_message(ERROR, "Could not umount final directory %s: %s\n", final_dir, strerror(errno));
+        ABORT(255);
+    }
+    singularity_priv_drop();
+
+    singularity_message(DEBUG, "Binding underlay directory to final directory %s->%s\n", underlay_dir, final_dir);
+    if ( singularity_mount(underlay_dir, final_dir, NULL, MS_BIND|MS_NOSUID|MS_REC, NULL) < 0 ) {
+        singularity_message(ERROR, "Could not bind mount underlay directory to final directory %s->%s: %s\n", underlay_dir, final_dir, strerror(errno));
+        ABORT(255);
+    }
+
+    // It's important for the underlay directory to be mounted read-only
+    //   because otherwise when running unprivileged the code inside the
+    //   container would be able to modify it's own root filesystem.
+    //   It's not necessary when running setuid because then the
+    //   root filesystem directory is owned by root, but do the same
+    //   thing anyway for consistency.
+    singularity_message(DEBUG, "Remounting underlay directory to final directory read-only %s->%s\n", underlay_dir, final_dir);
+    if ( singularity_mount(underlay_dir, final_dir, NULL, MS_REMOUNT|MS_BIND|MS_NOSUID|MS_REC|MS_RDONLY, NULL) < 0 ) {
+        singularity_message(ERROR, "Could not re-mount underlay directory to final directory read-only %s->%s: %s\n", underlay_dir, final_dir, strerror(errno));
+        ABORT(255);
+    }
+    errno = 0;
+    if ( access(final_dir, W_OK) == 0 || (errno != EROFS && errno != EACCES) ) { // Flawfinder: ignore (precautionary confirmation, not necessary)
+        singularity_message(ERROR, "Failed to write-protect the final directory %s: %s\n", final_dir, strerror(errno));
+        ABORT(255);
+    }
+
+    // make missing mount points in the underlay area
+    for (point = mountlist->first; point != NULL; point = point->next) {
+        if ( point->mountlistflags & ML_ONLY_IF_POINT_PRESENT )
+            continue;
+
+        source = (char *) point->source;
+        if ( source == NULL )
+            source = (char *) point->target;
+        if ( underlay_target != NULL )
+            free(underlay_target);
+        if ( image_target != NULL )
+            free(image_target);
+        underlay_target = joinpath(underlay_dir, point->target);
+        image_target = joinpath(image_dir, point->target);
+        char *basedir = strdup(underlay_target);
+        basedir = dirname(basedir);
+
+        if ( ( is_file(source) == 0 ) && ( is_file(underlay_target) < 0 ) &&
+               ( ( is_file(image_target) < 0 ) || ( is_dir(basedir) == 0 ) ) ) {
+
+            singularity_message(DEBUG, "Checking base directory for file %s ('%s')\n", underlay_target, basedir);
+            if ( is_dir(basedir) != 0 ) {
+                singularity_message(DEBUG, "Creating base directory for file mount\n");
+                if ( container_mkpath_priv(basedir, 0755) != 0 ) {
+                    singularity_message(ERROR, "Failed creating base directory for mounted file: %s\n", underlay_target);
+                    ABORT(255);
+                }
+            }
+
+
+            singularity_message(VERBOSE3, "Creating file mountpoint on underlay file system: %s\n", underlay_target);
+            if ( fileput_priv(underlay_target, "") != 0 ) {
+                singularity_message(ERROR, "Could not create mount point file in underlay %s: %s\n", underlay_target, strerror(errno));
+                ABORT(255);
+            }
+            singularity_message(DEBUG, "Created bind file: %s\n", underlay_target);
+        } else if ( ( ( point->filesystemtype != NULL ) ||
+                      ( is_dir(source) == 0 ) ) &&
+                  ( is_dir(underlay_target) < 0 ) &&
+                  ( ( is_dir(image_target) < 0 ) ||
+                    ( is_dir(basedir) == 0 ) ) ) {
+            singularity_message(VERBOSE3, "Creating mount directory on underlay file system: %s\n", underlay_target);
+            if ( container_mkpath_priv(underlay_target, 0755) < 0 ) {
+                singularity_message(ERROR, "Could not create mount point directory in underlay %s: %s\n", underlay_target, strerror(errno));
+                ABORT(255);
+            }
+        }
+        free(basedir);
+    }
+
+    if ( image_target != NULL )
+        free(image_target);
+    if ( underlay_target != NULL )
+        free(underlay_target);
+    
+    // mount everything else from the image into the underlay area
+    mount_missing(image_dir, underlay_dir, "/");
+
+    free(underlay_dir);
+
+    // finally, do the requested mounts
+    return(do_mounts(mountlist, 0));
+}
+
+int _singularity_runtime_domounts(struct mountlist *mountlist) {
+    if ( singularity_registry_get("OVERLAYFS_ENABLED") != NULL )
+        return(do_mounts(mountlist, 1));
+
+    if ( singularity_registry_get("UNDERLAY_ENABLED") != NULL )
+        return(underlay_mounts(mountlist));
+
+    return(do_mounts(mountlist, 0));
+}
diff --git a/src/lib/runtime/mounts/domounts/domounts.h b/src/lib/runtime/mounts/domounts/domounts.h
new file mode 100644
index 0000000..d7464b2
--- /dev/null
+++ b/src/lib/runtime/mounts/domounts/domounts.h
@@ -0,0 +1,33 @@
+/* 
+ * Copyright (c) 2017-2018, SyLabs, Inc. All rights reserved.
+ * Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
+ *
+ * Copyright (c) 2015-2017, Gregory M. Kurtzer. All rights reserved.
+ * 
+ * Copyright (c) 2016-2017, The Regents of the University of California,
+ * through Lawrence Berkeley National Laboratory (subject to receipt of any
+ * required approvals from the U.S. Dept. of Energy).  All rights reserved.
+ * 
+ * This software is licensed under a customized 3-clause BSD license.  Please
+ * consult LICENSE file distributed with the sources of this project regarding
+ * your rights to use or distribute this software.
+ * 
+ * NOTICE.  This Software was developed under funding from the U.S. Department of
+ * Energy and the U.S. Government consequently retains certain rights. As such,
+ * the U.S. Government has been granted for itself and others acting on its
+ * behalf a paid-up, nonexclusive, irrevocable, worldwide license in the Software
+ * to reproduce, distribute copies to the public, prepare derivative works, and
+ * perform publicly and display publicly, and to permit other to do so. 
+ * 
+*/
+
+#ifndef __SINGULARITY_RUNTIME_MOUNT_DOMOUNTS_H_
+#define __SINGULARITY_RUNTIME_MOUNT_DOMOUNTS_H_
+
+struct mountlist;
+
+extern int _singularity_runtime_domounts_init(struct mountlist *mountlist);
+extern int _singularity_runtime_domounts(struct mountlist *mountlist);
+
+#endif /* __SINGULARITY_RUNTIME_MOUNT_DOMOUNTS_H */
+
diff --git a/src/lib/runtime/mounts/home/home.c b/src/lib/runtime/mounts/home/home.c
index 665d256..c05c216 100644
--- a/src/lib/runtime/mounts/home/home.c
+++ b/src/lib/runtime/mounts/home/home.c
@@ -39,15 +39,15 @@
 #include "util/config_parser.h"
 #include "util/registry.h"
 #include "util/mount.h"
+#include "util/mountlist.h"
 
 #include "../../runtime.h"
 
 
-int _singularity_runtime_mount_home(void) {
+int _singularity_runtime_mount_home(struct mountlist *mountlist) {
     char *home_source = singularity_priv_homedir();
     char *home_dest = singularity_priv_home();
     char *session_dir = singularity_registry_get("SESSIONDIR");
-    char *container_dir = CONTAINER_FINALDIR;
 
     singularity_message(DEBUG, "Checking that home directry is configured: %s\n", home_dest);
     if ( home_dest == NULL ) {
@@ -83,12 +83,6 @@ int _singularity_runtime_mount_home(void) {
         ABORT(255);
     }
 
-    singularity_message(DEBUG, "Checking if home directory is already mounted: %s\n", home_dest);
-    if ( check_mounted(home_dest) >= 0 ) {
-        singularity_message(VERBOSE, "Not mounting home directory (already mounted in container): %s\n", home_dest);
-        return(0);
-    }
-
     singularity_message(DEBUG, "Creating temporary directory to stage home: %s\n", joinpath(session_dir, home_dest));
     if ( container_mkpath_nopriv(joinpath(session_dir, home_dest), 0755) < 0 ) {
         singularity_message(ERROR, "Failed creating home directory stage %s: %s\n", joinpath(session_dir, home_dest), strerror(errno));
@@ -112,8 +106,9 @@ int _singularity_runtime_mount_home(void) {
         singularity_message(VERBOSE, "Using sessiondir for home directory\n");
     }
 
-    singularity_message(DEBUG, "Checking if overlay is enabled\n");
-    if ( singularity_registry_get("OVERLAYFS_ENABLED") == NULL ) {
+    singularity_message(DEBUG, "Checking if overlay or underlay is enabled\n");
+    if ( ( singularity_registry_get("OVERLAYFS_ENABLED") == NULL ) &&
+            ( singularity_registry_get("UNDERLAY_ENABLED") == NULL ) ) {
         char *homedir_base;
 
         singularity_message(DEBUG, "Staging home directory base\n");
@@ -124,33 +119,12 @@ int _singularity_runtime_mount_home(void) {
             ABORT(255);
         }
 
-        singularity_message(DEBUG, "Checking home directory base exists in container: %s\n", homedir_base);
-        if ( is_dir(joinpath(container_dir, homedir_base)) != 0 ) {
-            singularity_message(ERROR, "Base home directory does not exist within the container: %s\n", homedir_base);
-            ABORT(255);
-        }
-
-        singularity_message(VERBOSE, "Mounting staged home directory base to container's base dir: %s -> %s\n", joinpath(session_dir, homedir_base), joinpath(container_dir, homedir_base));
-        if ( singularity_mount(joinpath(session_dir, homedir_base), joinpath(container_dir, homedir_base), NULL, MS_BIND | MS_NOSUID | MS_NODEV | MS_REC, NULL) < 0 ) {
-            singularity_message(ERROR, "Failed to mount staged home base: %s -> %s: %s\n", joinpath(session_dir, homedir_base), joinpath(container_dir, homedir_base), strerror(errno));
-            ABORT(255);
-        }
+        singularity_message(VERBOSE, "Queuing bind mount of staged home directory base to container's base dir: %s/%s -> %s\n", session_dir, homedir_base, homedir_base);
+        mountlist_add(mountlist, joinpath(session_dir, homedir_base), strdup(homedir_base), NULL, MS_BIND | MS_NOSUID | MS_NODEV | MS_REC, 0);
 
-        free(homedir_base);
     } else {
-        singularity_message(DEBUG, "Staging home directory\n");
-
-        singularity_message(DEBUG, "Creating home directory within container: %s\n", joinpath(container_dir, home_dest));
-        if ( container_mkpath_priv(joinpath(container_dir, home_dest), 0755) < 0 ) {
-            singularity_message(ERROR, "Failed creating home directory in container %s: %s\n", joinpath(container_dir, home_dest), strerror(errno));
-            ABORT(255);
-        }
-
-        singularity_message(VERBOSE, "Mounting staged home directory to container: %s -> %s\n", joinpath(session_dir, home_dest), joinpath(container_dir, home_dest));
-        if ( singularity_mount(joinpath(session_dir, home_dest), joinpath(container_dir, home_dest), NULL, MS_BIND | MS_NOSUID | MS_NODEV | MS_REC, NULL) < 0 ) {
-            singularity_message(ERROR, "Failed to mount staged home base: %s -> %s: %s\n", joinpath(session_dir, home_dest), joinpath(container_dir, home_dest), strerror(errno));
-            ABORT(255);
-        }
+        singularity_message(VERBOSE, "Queuing bind mount of staged home directory to container: %s/%s -> %s\n", session_dir, home_dest, home_dest);
+        mountlist_add(mountlist, joinpath(session_dir, home_dest), strdup(home_dest), NULL, MS_BIND | MS_NOSUID | MS_NODEV | MS_REC, 0);
     }
 
     envar_set("HOME", home_dest, 1);
diff --git a/src/lib/runtime/mounts/home/home.h b/src/lib/runtime/mounts/home/home.h
index a150177..2553d75 100644
--- a/src/lib/runtime/mounts/home/home.h
+++ b/src/lib/runtime/mounts/home/home.h
@@ -24,7 +24,9 @@
 #ifndef __SINGULARITY_RUNTIME_MOUNT_HOME_H_
 #define __SINGULARITY_RUNTIME_MOUNT_HOME_H_
 
-extern int _singularity_runtime_mount_home(void);
+struct mountlist;
+
+extern int _singularity_runtime_mount_home(struct mountlist *mountlist);
 
 #endif /* __SINGULARITY_RUNTIME_MOUNT_HOME_H */
 
diff --git a/src/lib/runtime/mounts/hostfs/hostfs.c b/src/lib/runtime/mounts/hostfs/hostfs.c
index 2040d53..a56c5cc 100644
--- a/src/lib/runtime/mounts/hostfs/hostfs.c
+++ b/src/lib/runtime/mounts/hostfs/hostfs.c
@@ -37,20 +37,18 @@
 #include "util/file.h"
 #include "util/util.h"
 #include "util/message.h"
-#include "util/privilege.h"
 #include "util/config_parser.h"
 #include "util/registry.h"
-#include "util/mount.h"
+#include "util/mountlist.h"
 
 #include "../../runtime.h"
 
 #define MAX_LINE_LEN 4096
 
 
-int _singularity_runtime_mount_hostfs(void) {
+int _singularity_runtime_mount_hostfs(struct mountlist *mountlist) {
     FILE *mounts;
     char *line = NULL;
-    char *container_dir = CONTAINER_FINALDIR;
 
     if ( singularity_config_get_bool(MOUNT_HOSTFS) <= 0 ) {
         singularity_message(DEBUG, "Not mounting host file systems per configuration\n");
@@ -88,7 +86,7 @@ int _singularity_runtime_mount_hostfs(void) {
             singularity_message(VERBOSE3, "Skipping blank or comment line in /proc/mounts\n");
             continue;
         }
-        if ( ( source = strtok(strdup(line), " ") ) == NULL ) {
+        if ( ( source = strtok(line, " ") ) == NULL ) {
             singularity_message(VERBOSE3, "Could not obtain mount source from /proc/mounts: %s\n", line);
             continue;
         }
@@ -129,8 +127,8 @@ int _singularity_runtime_mount_hostfs(void) {
             singularity_message(DEBUG, "Skipping /var based file system: %s,%s,%s\n", source, mountpoint, filesystem);
             continue;
         }
-        if ( strncmp(mountpoint, container_dir, strlength(container_dir, PATH_MAX)) == 0 ) {
-            singularity_message(DEBUG, "Skipping final_dir (%s) based file system: %s,%s,%s\n", container_dir, source, mountpoint, filesystem);
+        if ( strncmp(mountpoint, CONTAINER_FINALDIR, strlength(CONTAINER_FINALDIR, PATH_MAX)) == 0 ) {
+            singularity_message(DEBUG, "Skipping final_dir (%s) based file system: %s,%s,%s\n", CONTAINER_FINALDIR, source, mountpoint, filesystem);
             continue;
         }
         if ( strcmp(mountpoint, CONTAINER_MOUNTDIR) == 0 ) {
@@ -149,37 +147,9 @@ int _singularity_runtime_mount_hostfs(void) {
             singularity_message(DEBUG, "Skipping ramfs file system: %s,%s,%s\n", source, mountpoint, filesystem);
             continue;
         }
-        singularity_message(DEBUG, "Checking if host file system is already mounted: %s\n", mountpoint);
-        if ( check_mounted(mountpoint) >= 0 ) {
-            singularity_message(VERBOSE, "Not mounting host FS (already mounted in container): %s\n", mountpoint);
-            continue;
-        }
-
-        if ( ( is_dir(mountpoint) == 0 ) && ( is_dir(joinpath(container_dir, mountpoint)) < 0 ) ) {
-            if ( singularity_registry_get("OVERLAYFS_ENABLED") != NULL ) {
-                if ( container_mkpath_priv(joinpath(container_dir, mountpoint), 0755) < 0 ) {
-                    singularity_message(WARNING, "Could not create bind point directory in container %s: %s\n", mountpoint, strerror(errno));
-                    continue;
-                }
-            } else {
-                singularity_message(WARNING, "Non existent 'bind point' directory in container: '%s'\n", mountpoint);
-                continue;
-            }
-        }
-
-
-        singularity_message(VERBOSE, "Binding '%s'(%s) to '%s/%s'\n", mountpoint, filesystem, container_dir, mountpoint);
-        if ( singularity_mount(mountpoint, joinpath(container_dir, mountpoint), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0 ) {
-            singularity_message(ERROR, "There was an error binding the path %s: %s\n", mountpoint, strerror(errno));
-            ABORT(255);
-        }
-        if ( singularity_priv_userns_enabled() != 1 ) {
-            if ( singularity_mount(NULL, joinpath(container_dir, mountpoint), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC|MS_REMOUNT, NULL) < 0 ) {
-                singularity_message(ERROR, "There was an error remounting the path %s: %s\n", mountpoint, strerror(errno));
-                ABORT(255);
-            }
-        }
 
+        singularity_message(VERBOSE, "Queuing bind mount of '%s'(%s) to '%s'\n", mountpoint, filesystem, mountpoint);
+        mountlist_add(mountlist, NULL, strdup(mountpoint), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, 0);
     }
 
     free(line);
diff --git a/src/lib/runtime/mounts/hostfs/hostfs.h b/src/lib/runtime/mounts/hostfs/hostfs.h
index 9d9f6ab..62617a1 100644
--- a/src/lib/runtime/mounts/hostfs/hostfs.h
+++ b/src/lib/runtime/mounts/hostfs/hostfs.h
@@ -24,7 +24,9 @@
 #ifndef __SINGULARITY_RUNTIME_MOUNT_HOSTFS_H_
 #define __SINGULARITY_RUNTIME_MOUNT_HOSTFS_H_
 
-extern int _singularity_runtime_mount_hostfs(void);
+struct mountlist;
+
+extern int _singularity_runtime_mount_hostfs(struct mountlist *mountlist);
 
 #endif /* __SINGULARITY_RUNTIME_MOUNT_HOSTFS_H */
 
diff --git a/src/lib/runtime/mounts/kernelfs/kernelfs.c b/src/lib/runtime/mounts/kernelfs/kernelfs.c
index cc0de35..bfe9741 100644
--- a/src/lib/runtime/mounts/kernelfs/kernelfs.c
+++ b/src/lib/runtime/mounts/kernelfs/kernelfs.c
@@ -37,34 +37,23 @@
 #include "util/privilege.h"
 #include "util/config_parser.h"
 #include "util/registry.h"
-#include "util/mount.h"
+#include "util/mountlist.h"
 
 #include "../../runtime.h"
 #include "../../ns/ns.h"
 
 
-int _singularity_runtime_mount_kernelfs(void) {
-    char *container_dir = CONTAINER_FINALDIR;
+int _singularity_runtime_mount_kernelfs(struct mountlist *mountlist) {
 
     // Mount /proc if we are configured
     singularity_message(DEBUG, "Checking configuration file for 'mount proc'\n");
     if ( singularity_config_get_bool(MOUNT_PROC) > 0 ) {
-        if ( is_dir(joinpath(container_dir, "/proc")) == 0 ) {
-            if ( singularity_registry_get("PIDNS_ENABLED") == NULL ) {
-                singularity_message(VERBOSE, "Bind-mounting host /proc\n");
-                if ( singularity_mount("/proc", joinpath(container_dir, "/proc"), NULL, MS_BIND | MS_NOSUID | MS_REC, NULL) < 0 ) {
-                    singularity_message(ERROR, "Could not bind-mount host /proc into container: %s\n", strerror(errno));
-                    ABORT(255);
-                }
-            } else {
-                singularity_message(VERBOSE, "Mounting new procfs\n");
-                if ( singularity_mount("proc", joinpath(container_dir, "/proc"), "proc", MS_NOSUID, NULL) < 0 ) {
-                    singularity_message(ERROR, "Could not mount new procfs into container: %s\n", strerror(errno));
-                    ABORT(255);
-                }
-            }
+        if ( singularity_registry_get("PIDNS_ENABLED") == NULL ) {
+            singularity_message(VERBOSE, "Queuing bind mount of host /proc\n");
+            mountlist_add(mountlist, NULL, strdup("/proc"), NULL, MS_BIND | MS_NOSUID | MS_REC, 0);
         } else {
-            singularity_message(WARNING, "Not mounting /proc, container has no bind directory\n");
+            singularity_message(VERBOSE, "Queuing mount of new procfs\n");
+            mountlist_add(mountlist, strdup("proc"), strdup("/proc"), "proc", MS_NOSUID, 0);
         }
     } else {
         singularity_message(VERBOSE, "Skipping /proc mount\n");
@@ -74,22 +63,12 @@ int _singularity_runtime_mount_kernelfs(void) {
     // Mount /sys if we are configured
     singularity_message(DEBUG, "Checking configuration file for 'mount sys'\n");
     if ( singularity_config_get_bool(MOUNT_SYS) > 0 ) {
-        if ( is_dir(joinpath(container_dir, "/sys")) == 0 ) {
-            if ( singularity_priv_userns_enabled() == 1 ) {
-                singularity_message(VERBOSE, "Mounting /sys\n");
-                if ( singularity_mount("/sys", joinpath(container_dir, "/sys"), NULL, MS_BIND | MS_NOSUID | MS_REC, NULL) < 0 ) {
-                    singularity_message(ERROR, "Could not mount /sys into container: %s\n", strerror(errno));
-                    ABORT(255);
-                }
-            } else {
-                singularity_message(VERBOSE, "Mounting /sys\n");
-                if ( singularity_mount("sysfs", joinpath(container_dir, "/sys"), "sysfs", MS_NOSUID, NULL) < 0 ) {
-                    singularity_message(ERROR, "Could not mount /sys into container: %s\n", strerror(errno));
-                    ABORT(255);
-                }
-            }
+        if ( singularity_priv_userns_enabled() == 1 ) {
+            singularity_message(VERBOSE, "Queuing bind mount of /sys\n");
+            mountlist_add(mountlist, NULL, strdup("/sys"), NULL, MS_BIND | MS_NOSUID | MS_REC, 0);
         } else {
-            singularity_message(WARNING, "Not mounting /sys, container has no bind directory\n");
+            singularity_message(VERBOSE, "Queuing mount of new sysfs\n");
+            mountlist_add(mountlist, strdup("sysfs"), strdup("/sys"), "sysfs", MS_NOSUID, 0);
         }
     } else {
         singularity_message(VERBOSE, "Skipping /sys mount\n");
diff --git a/src/lib/runtime/mounts/kernelfs/kernelfs.h b/src/lib/runtime/mounts/kernelfs/kernelfs.h
index 63143c0..6b49c58 100644
--- a/src/lib/runtime/mounts/kernelfs/kernelfs.h
+++ b/src/lib/runtime/mounts/kernelfs/kernelfs.h
@@ -24,7 +24,9 @@
 #ifndef __SINGULARITY_RUNTIME_MOUNT_KERNELFS_H_
 #define __SINGULARITY_RUNTIME_MOUNT_KERNELFS_H_
 
-extern int _singularity_runtime_mount_kernelfs(void);
+struct mountlist;
+
+extern int _singularity_runtime_mount_kernelfs(struct mountlist *mountlist);
 
 #endif /* __SINGULARITY_RUNTIME_MOUNT_KERNELFS_H */
 
diff --git a/src/lib/runtime/mounts/libs/Makefile.am b/src/lib/runtime/mounts/libs/Makefile.am
new file mode 100644
index 0000000..f54f504
--- /dev/null
+++ b/src/lib/runtime/mounts/libs/Makefile.am
@@ -0,0 +1,12 @@
+MAINTAINERCLEANFILES = Makefile.in 
+DISTCLEANFILES = Makefile
+CLEANFILES = core.* *~ *.la
+
+AM_CFLAGS = -Wall -fpie
+AM_LDFLAGS = -pie
+AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DLIBEXECDIR=\"$(libexecdir)\" $(SINGULARITY_DEFINES)
+
+noinst_LTLIBRARIES = libinternal.la
+libinternal_la_SOURCES = libs.c
+
+EXTRA_DIST = libs.h
diff --git a/src/lib/runtime/mounts/libs/libs.c b/src/lib/runtime/mounts/libs/libs.c
new file mode 100644
index 0000000..7c73771
--- /dev/null
+++ b/src/lib/runtime/mounts/libs/libs.c
@@ -0,0 +1,157 @@
+/* 
+ * Copyright (c) 2017-2018, SyLabs, Inc. All rights reserved.
+ * Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
+ *
+ * Copyright (c) 2015-2017, Gregory M. Kurtzer. All rights reserved.
+ * 
+ * Copyright (c) 2016-2017, The Regents of the University of California,
+ * through Lawrence Berkeley National Laboratory (subject to receipt of any
+ * required approvals from the U.S. Dept. of Energy).  All rights reserved.
+ * 
+ * This software is licensed under a customized 3-clause BSD license.  Please
+ * consult LICENSE file distributed with the sources of this project regarding
+ * your rights to use or distribute this software.
+ * 
+ * NOTICE.  This Software was developed under funding from the U.S. Department of
+ * Energy and the U.S. Government consequently retains certain rights. As such,
+ * the U.S. Government has been granted for itself and others acting on its
+ * behalf a paid-up, nonexclusive, irrevocable, worldwide license in the Software
+ * to reproduce, distribute copies to the public, prepare derivative works, and
+ * perform publicly and display publicly, and to permit other to do so. 
+ * 
+*/
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <linux/limits.h>
+
+#include "config.h"
+#include "util/file.h"
+#include "util/util.h"
+#include "util/message.h"
+#include "util/privilege.h"
+#include "util/config_parser.h"
+#include "util/registry.h"
+#include "util/mount.h"
+#include "util/mountlist.h"
+
+#include "../../runtime.h"
+
+
+int _singularity_runtime_mount_libs(struct mountlist *mountlist) {
+    char *tmpdir = singularity_registry_get("SESSIONDIR");
+    char *includelibs_string;
+
+    if ( ( includelibs_string = singularity_registry_get("CONTAINLIBS") ) != NULL ) {
+        char *libdir = joinpath(tmpdir, "/libs");
+        char *libdir_contained = joinpath(CONTAINER_MOUNTDIR, "/.singularity.d/libs");
+        char *tok = NULL;
+        char *current = strtok_r(strdup(includelibs_string), ",", &tok);
+
+        singularity_message(DEBUG, "Parsing SINGULARITY_CONTAINLIBS for user-specified libraries to include.\n");
+
+        free(includelibs_string);
+
+        singularity_message(DEBUG, "Checking if libdir in container exists: %s\n", libdir_contained);
+        if ( is_dir(libdir_contained) != 0 ) {
+            singularity_message(WARNING, "Library bind directory not present in container, update container\n");
+            char *ld_path = envar_path("LD_LIBRARY_PATH");
+            if ( ld_path == NULL ) {
+                singularity_message(DEBUG, "Setting LD_LIBRARY_PATH to '/.singularity.d/libs'\n");
+                envar_set("LD_LIBRARY_PATH", "/.singularity.d/libs", 1);
+            } else {
+                singularity_message(DEBUG, "Prepending '/.singularity.d/libs' to LD_LIBRARY_PATH\n");
+                envar_set("LD_LIBRARY_PATH", strjoin("/.singularity.d/libs:", ld_path), 1);
+            }
+        }
+        free(libdir_contained);
+
+        singularity_message(DEBUG, "Creating session libdir at: %s\n", libdir);
+        if ( container_mkpath_nopriv(libdir, 0755) != 0 ) {
+            singularity_message(ERROR, "Failed creating temp lib directory at: %s\n", libdir);
+            ABORT(255);
+        }
+
+        while (current != NULL ) {
+            char *dest = NULL;
+            char *source = NULL;
+
+            singularity_message(DEBUG, "Evaluating requested library path: %s\n", current);
+
+            dest = joinpath(libdir, basename(current));
+
+            if ( is_file(dest) == 0 ) {
+                singularity_message(VERBOSE3, "Staged library exists, skipping: %s\n", current);
+                current = strtok_r(NULL, ",", &tok);
+                continue;
+            }
+
+            if ( is_link(current) == 0 ) {
+                char *link_name;
+                ssize_t len;
+
+                link_name = (char *) malloc(PATH_MAX);
+
+                len = readlink(current, link_name, PATH_MAX-1); // Flawfinder: ignore
+                if ( ( len > 0 ) && ( len <= PATH_MAX) ) {
+                    link_name[len] = '\0';
+                    singularity_message(VERBOSE3, "Found library link source: %s -> %s\n", current, link_name);
+                    if ( link_name[0] == '/' ) {
+                        source = strdup(link_name);
+                    } else {
+                        if ( link_name[0] == '/' ) {
+                            source = strdup(link_name);
+                        } else {
+                            source = joinpath(dirname(strdup(current)), link_name);
+                        }
+                    }
+                } else {
+                    singularity_message(WARNING, "Failed reading library link for %s: %s\n", current, strerror(errno));
+                    ABORT(255);
+                }
+                free(link_name);
+
+            } else if (is_file(current) == 0 ) {
+                source = strdup(current);
+                singularity_message(VERBOSE3, "Found library source: %s\n", source);
+            } else {
+                singularity_message(WARNING, "Could not find library: %s\n", current);
+                current = strtok_r(NULL, ",", &tok);
+                continue;
+            }
+
+            singularity_message(DEBUG, "Binding library source here: %s -> %s\n", source, dest);
+
+            if ( fileput_nopriv(dest, "") != 0 ) {
+                singularity_message(ERROR, "Failed creating file at %s: %s\n", dest, strerror(errno));
+                ABORT(255);
+            }
+
+            singularity_message(VERBOSE, "Binding file '%s' to '%s'\n", source, dest);
+            if ( singularity_mount(source, dest, NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0 ) {
+                    singularity_message(ERROR, "There was an error binding %s to %s: %s\n", source, dest, strerror(errno));
+                    ABORT(255);
+            }
+
+            free(source);
+            free(dest);
+            current = strtok_r(NULL, ",", &tok);
+        }
+
+        singularity_message(VERBOSE, "Queueing bind mount of libdir '%s' to '%s'\n", libdir, "/.singularity.d/libs");
+        mountlist_add(mountlist, libdir, strdup("/.singularity.d/libs"), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, 0);
+    }
+
+    return(0);
+}
diff --git a/src/lib/runtime/mounts/libs/libs.h b/src/lib/runtime/mounts/libs/libs.h
new file mode 100644
index 0000000..4a6bdff
--- /dev/null
+++ b/src/lib/runtime/mounts/libs/libs.h
@@ -0,0 +1,32 @@
+/* 
+ * Copyright (c) 2017-2018, SyLabs, Inc. All rights reserved.
+ * Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
+ *
+ * Copyright (c) 2015-2017, Gregory M. Kurtzer. All rights reserved.
+ * 
+ * Copyright (c) 2016-2017, The Regents of the University of California,
+ * through Lawrence Berkeley National Laboratory (subject to receipt of any
+ * required approvals from the U.S. Dept. of Energy).  All rights reserved.
+ * 
+ * This software is licensed under a customized 3-clause BSD license.  Please
+ * consult LICENSE file distributed with the sources of this project regarding
+ * your rights to use or distribute this software.
+ * 
+ * NOTICE.  This Software was developed under funding from the U.S. Department of
+ * Energy and the U.S. Government consequently retains certain rights. As such,
+ * the U.S. Government has been granted for itself and others acting on its
+ * behalf a paid-up, nonexclusive, irrevocable, worldwide license in the Software
+ * to reproduce, distribute copies to the public, prepare derivative works, and
+ * perform publicly and display publicly, and to permit other to do so. 
+ * 
+*/
+
+#ifndef __SINGULARITY_RUNTIME_MOUNT_LIBS_H_
+#define __SINGULARITY_RUNTIME_MOUNT_LIBS_H_
+
+struct mountlist;
+
+extern int _singularity_runtime_mount_libs(struct mountlist *);
+
+#endif /* __SINGULARITY_RUNTIME_MOUNT_LIBS_H */
+
diff --git a/src/lib/runtime/mounts/mounts.c b/src/lib/runtime/mounts/mounts.c
index 4419281..6fa52d1 100644
--- a/src/lib/runtime/mounts/mounts.c
+++ b/src/lib/runtime/mounts/mounts.c
@@ -32,6 +32,7 @@
 #include "util/file.h"
 #include "util/util.h"
 #include "util/message.h"
+#include "util/mountlist.h"
 #include "util/privilege.h"
 
 #include "./binds/binds.h"
@@ -43,21 +44,31 @@
 #include "./cwd/cwd.h"
 #include "./userbinds/userbinds.h"
 #include "./scratch/scratch.h"
+#include "./libs/libs.h"
+#include "./domounts/domounts.h"
 
 
 int _singularity_runtime_mounts(void) {
     int retval = 0;
+    struct mountlist mountlist;
+
+    singularity_runtime_domounts_init(&mountlist);
 
     singularity_message(VERBOSE, "Running all mount components\n");
-    retval += _singularity_runtime_mount_dev();
-    retval += _singularity_runtime_mount_kernelfs();
-    retval += _singularity_runtime_mount_hostfs();
-    retval += _singularity_runtime_mount_binds();
-    retval += _singularity_runtime_mount_home();
-    retval += _singularity_runtime_mount_userbinds();
-    retval += _singularity_runtime_mount_tmp();
-    retval += _singularity_runtime_mount_scratch();
-    retval += _singularity_runtime_mount_cwd();
+    retval += _singularity_runtime_mount_dev(&mountlist);
+    retval += _singularity_runtime_mount_kernelfs(&mountlist);
+    retval += _singularity_runtime_mount_hostfs(&mountlist);
+    retval += _singularity_runtime_mount_binds(&mountlist);
+    retval += _singularity_runtime_mount_home(&mountlist);
+    retval += _singularity_runtime_mount_userbinds(&mountlist);
+    retval += _singularity_runtime_mount_tmp(&mountlist);
+    retval += _singularity_runtime_mount_scratch(&mountlist);
+    retval += _singularity_runtime_mount_cwd(&mountlist);
+    retval += _singularity_runtime_mount_libs(&mountlist);
+
+    retval += _singularity_runtime_domounts(&mountlist);
+
+    mountlist_cleanup(&mountlist);
 
     return(retval);
 }
diff --git a/src/lib/runtime/mounts/scratch/scratch.c b/src/lib/runtime/mounts/scratch/scratch.c
index 66a5f60..4a8c829 100644
--- a/src/lib/runtime/mounts/scratch/scratch.c
+++ b/src/lib/runtime/mounts/scratch/scratch.c
@@ -41,17 +41,15 @@
 #include "util/privilege.h"
 #include "util/config_parser.h"
 #include "util/registry.h"
-#include "util/mount.h"
+#include "util/mountlist.h"
 
 #include "../../runtime.h"
 
 
-int _singularity_runtime_mount_scratch(void) {
-    char *container_dir = CONTAINER_FINALDIR;
+int _singularity_runtime_mount_scratch(struct mountlist *mountlist) {
     char *scratchdir_path;
     char *tmpdir_path;
     char *sourcedir_path;
-    int r;
 
     singularity_message(DEBUG, "Getting SINGULARITY_SCRATCHDIR from environment\n");
     if ( ( scratchdir_path = singularity_registry_get("SCRATCHDIR") ) == NULL ) {
@@ -78,54 +76,20 @@ int _singularity_runtime_mount_scratch(void) {
     free(tmpdir_path);
 
     char *outside_token = NULL;
-    char *current = strtok_r(strdup(scratchdir_path), ",", &outside_token);
-
-    free(scratchdir_path);
+    char *current = strtok_r(scratchdir_path, ",", &outside_token);
 
     while ( current != NULL ) {
-
-        char *full_sourcedir_path = joinpath(sourcedir_path, basename(strdup(current)));
-        char *full_destdir_path = joinpath(container_dir, current);
-
-        singularity_message(DEBUG, "Checking if bind point is already mounted: %s\n", current);
-        if ( check_mounted(current) >= 0 ) {
-            singularity_message(ERROR, "Not mounting requested scratch directory (already mounted in container): %s\n", current);
-            ABORT(255);
-        }
+        char *current_copy = strdup(current);
+        char *full_sourcedir_path = joinpath(sourcedir_path, basename(current_copy));
+        free(current_copy);
 
         if ( container_mkpath_nopriv(full_sourcedir_path, 0750) < 0 ) {
              singularity_message(ERROR, "Could not create scratch working directory %s: %s\n", full_sourcedir_path, strerror(errno));
              ABORT(255);
         }
 
-        if ( is_dir(full_destdir_path) != 0 ) {
-            if ( singularity_registry_get("OVERLAYFS_ENABLED") != NULL ) {
-                singularity_message(DEBUG, "Creating scratch directory inside container\n");
-                r = container_mkpath_priv(full_destdir_path, 0755);
-                if ( r < 0 ) {
-                    singularity_message(VERBOSE, "Skipping scratch directory mount, could not create dir inside container %s: %s\n", current, strerror(errno));
-                    current = strtok_r(NULL, ",", &outside_token);
-                    continue;
-                }
-            } else {
-                singularity_message(WARNING, "Skipping scratch directory mount, target directory does not exist: %s\n", current);
-                current = strtok_r(NULL, ",", &outside_token);
-                continue;
-            }
-        }
-
-        singularity_message(VERBOSE, "Binding '%s' to '%s/%s'\n", full_sourcedir_path, container_dir, current);
-        r = singularity_mount(full_sourcedir_path, joinpath(container_dir, current), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, NULL);
-        if ( singularity_priv_userns_enabled() != 1 ) {
-            r += singularity_mount(NULL, joinpath(container_dir, current), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC|MS_REMOUNT, NULL);
-        }
-        if ( r < 0 ) {
-            singularity_message(WARNING, "Could not bind scratch directory into container %s: %s\n", full_sourcedir_path, strerror(errno));
-            ABORT(255);
-        }
-
-        free(full_sourcedir_path);
-        free(full_destdir_path);
+        singularity_message(VERBOSE, "Queuing bind mount of '%s' to '%s'\n", full_sourcedir_path, current);
+        mountlist_add(mountlist, full_sourcedir_path, strdup(current), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, 0);
 
         current = strtok_r(NULL, ",", &outside_token);
 
@@ -134,6 +98,8 @@ int _singularity_runtime_mount_scratch(void) {
             current = strtok_r(NULL, ",", &outside_token);
         }
     }
+
+    free(scratchdir_path);
     return(0);
 }
 
diff --git a/src/lib/runtime/mounts/scratch/scratch.h b/src/lib/runtime/mounts/scratch/scratch.h
index 00104c4..3ab46e4 100644
--- a/src/lib/runtime/mounts/scratch/scratch.h
+++ b/src/lib/runtime/mounts/scratch/scratch.h
@@ -24,7 +24,9 @@
 #ifndef __SINGULARITY_RUNTIME_MOUNT_SCRATCH_H_
 #define __SINGULARITY_RUNTIME_MOUNT_SCRATCH_H_
 
-extern int _singularity_runtime_mount_scratch(void);
+struct mountlist;
+
+extern int _singularity_runtime_mount_scratch(struct mountlist *mountlist);
 
 #endif /* __SINGULARITY_RUNTIME_MOUNT_SCRATCH_H */
 
diff --git a/src/lib/runtime/mounts/tmp/tmp.c b/src/lib/runtime/mounts/tmp/tmp.c
index 7384b4a..1969306 100644
--- a/src/lib/runtime/mounts/tmp/tmp.c
+++ b/src/lib/runtime/mounts/tmp/tmp.c
@@ -36,16 +36,14 @@
 #include "util/file.h"
 #include "util/util.h"
 #include "util/message.h"
-#include "util/privilege.h"
 #include "util/config_parser.h"
 #include "util/registry.h"
-#include "util/mount.h"
+#include "util/mountlist.h"
 
 #include "../../runtime.h"
 
 
-int _singularity_runtime_mount_tmp(void) {
-    char *container_dir = CONTAINER_FINALDIR;
+int _singularity_runtime_mount_tmp(struct mountlist *mountlist) {
     char *tmp_source;
     char *vartmp_source;
 
@@ -74,60 +72,26 @@ int _singularity_runtime_mount_tmp(void) {
         free(tmpdirpath);
     }
 
-    if ( check_mounted("/tmp") < 0 ) {
-        if ( s_mkpath(tmp_source, 0755) < 0 ) {
-            singularity_message(ERROR, "Could not create source /tmp directory %s: %s\n", tmp_source, strerror(errno));
-            ABORT(255);
-        }
-        if ( is_dir(tmp_source) == 0 ) {
-            if ( is_dir(joinpath(container_dir, "/tmp")) == 0 ) {
-                singularity_message(VERBOSE, "Mounting directory: /tmp\n");
-                if ( singularity_mount(tmp_source, joinpath(container_dir, "/tmp"), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0 ) {
-                    singularity_message(ERROR, "Failed to mount %s -> /tmp: %s\n", tmp_source, strerror(errno));
-                    ABORT(255);
-                }
-                if ( singularity_priv_userns_enabled() != 1 ) {
-                    if ( singularity_mount(NULL, joinpath(container_dir, "/tmp"), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC|MS_REMOUNT, NULL) < 0 ) {
-                        singularity_message(ERROR, "Failed to remount /tmp: %s\n", strerror(errno));
-                        ABORT(255);
-                    }
-                }
-            } else {
-                singularity_message(VERBOSE, "Could not mount container's /tmp directory: does not exist\n");
-            }
-        } else {
-            singularity_message(VERBOSE, "Could not mount host's /tmp directory (%s): does not exist\n", tmp_source);
-        }
+    if ( s_mkpath(tmp_source, 0755) < 0 ) {
+        singularity_message(ERROR, "Could not create source /tmp directory %s: %s\n", tmp_source, strerror(errno));
+        ABORT(255);
+    }
+    if ( is_dir(tmp_source) == 0 ) {
+        singularity_message(VERBOSE, "Queuing bind mount of /tmp\n");
+        mountlist_add(mountlist, strdup(tmp_source), strdup("/tmp"), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, 0);
     } else {
-        singularity_message(VERBOSE, "Not mounting '/tmp', already mounted\n");
+        singularity_message(VERBOSE, "Could not mount host's /tmp directory (%s): does not exist\n", tmp_source);
     }
 
-    if ( check_mounted("/var/tmp") < 0 ) {
-        if ( s_mkpath(vartmp_source, 0755) < 0 ) {
-            singularity_message(ERROR, "Could not create source /var/tmp directory %s: %s\n", vartmp_source, strerror(errno));
-            ABORT(255);
-        }
-        if ( is_dir(vartmp_source) == 0 ) {
-            if ( is_dir(joinpath(container_dir, "/var/tmp")) == 0 ) {
-                singularity_message(VERBOSE, "Mounting directory: /var/tmp\n");
-                if ( singularity_mount(vartmp_source, joinpath(container_dir, "/var/tmp"), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0 ) {
-                    singularity_message(ERROR, "Failed to mount %s -> /var/tmp: %s\n", vartmp_source, strerror(errno));
-                    ABORT(255);
-                }
-                if ( singularity_priv_userns_enabled() != 1 ) {
-                    if ( singularity_mount(NULL, joinpath(container_dir, "/var/tmp"), NULL, MS_BIND|MS_NOSUID|MS_REC|MS_NODEV|MS_REMOUNT, NULL) < 0 ) {
-                        singularity_message(ERROR, "Failed to remount /var/tmp: %s\n", strerror(errno));
-                        ABORT(255);
-                    }
-                }
-            } else {
-                singularity_message(VERBOSE, "Could not mount container's /var/tmp directory: does not exist\n");
-            }
-        } else {
-            singularity_message(VERBOSE, "Could not mount host's /var/tmp directory (%s): does not exist\n", vartmp_source);
-        }
+    if ( s_mkpath(vartmp_source, 0755) < 0 ) {
+        singularity_message(ERROR, "Could not create source /var/tmp directory %s: %s\n", vartmp_source, strerror(errno));
+        ABORT(255);
+    }
+    if ( is_dir(vartmp_source) == 0 ) {
+        singularity_message(VERBOSE, "Queuing bind mount of /var/tmp\n");
+        mountlist_add(mountlist, strdup(vartmp_source), strdup("/var/tmp"), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, 0);
     } else {
-        singularity_message(VERBOSE, "Not mounting '/var/tmp', already mounted\n");
+        singularity_message(VERBOSE, "Could not mount host's /var/tmp directory (%s): does not exist\n", vartmp_source);
     }
 
     free(tmp_source);
diff --git a/src/lib/runtime/mounts/tmp/tmp.h b/src/lib/runtime/mounts/tmp/tmp.h
index d793b79..b6b2590 100644
--- a/src/lib/runtime/mounts/tmp/tmp.h
+++ b/src/lib/runtime/mounts/tmp/tmp.h
@@ -24,7 +24,9 @@
 #ifndef __SINGULARITY_RUNTIME_MOUNT_TMP_H_
 #define __SINGULARITY_RUNTIME_MOUNT_TMP_H_
 
-extern int _singularity_runtime_mount_tmp(void);
+struct mountlist;
+
+extern int _singularity_runtime_mount_tmp(struct mountlist *mountlist);
 
 #endif /* __SINGULARITY_RUNTIME_MOUNT_TMP_H */
 
diff --git a/src/lib/runtime/mounts/userbinds/userbinds.c b/src/lib/runtime/mounts/userbinds/userbinds.c
index 7e6f0b8..f4dfd6b 100644
--- a/src/lib/runtime/mounts/userbinds/userbinds.c
+++ b/src/lib/runtime/mounts/userbinds/userbinds.c
@@ -35,16 +35,14 @@
 #include "util/file.h"
 #include "util/util.h"
 #include "util/message.h"
-#include "util/privilege.h"
 #include "util/config_parser.h"
 #include "util/registry.h"
-#include "util/mount.h"
+#include "util/mountlist.h"
 
 #include "../../runtime.h"
 
 
-int _singularity_runtime_mount_userbinds(void) {
-    char *container_dir = CONTAINER_FINALDIR;
+int _singularity_runtime_mount_userbinds(struct mountlist *mountlist) {
     char *bind_path_string;
 
     singularity_message(DEBUG, "Checking for environment variable 'SINGULARITY_BINDPATH'\n");
@@ -59,12 +57,10 @@ int _singularity_runtime_mount_userbinds(void) {
         singularity_message(DEBUG, "Parsing SINGULARITY_BINDPATH for user-specified bind mounts.\n");
         char *outside_token = NULL;
         char *inside_token = NULL;
-        char *current = strtok_r(strdup(bind_path_string), ",", &outside_token);
-
-        free(bind_path_string);
+        char *current = strtok_r(bind_path_string, ",", &outside_token);
 
         while ( current != NULL ) {
-            int read_only = 0;
+            unsigned long read_only = 0;
             char *source = strtok_r(current, ":", &inside_token);
             char *dest = strtok_r(NULL, ":", &inside_token);
             char *opts = strtok_r(NULL, ":", &inside_token);
@@ -81,7 +77,7 @@ int _singularity_runtime_mount_userbinds(void) {
                 if ( strcmp(opts, "rw") == 0 ) {
                     // This is the default
                 } else if ( strcmp(opts, "ro") == 0 ) {
-                    read_only = 1;
+                    read_only = MS_RDONLY;
                 } else {
                     singularity_message(WARNING, "Not mounting requested bind point, invalid mount option %s: %s\n", opts, dest);
                     continue;
@@ -89,79 +85,12 @@ int _singularity_runtime_mount_userbinds(void) {
             }
 
 
-            singularity_message(DEBUG, "Checking if bind point is already mounted: %s\n", dest);
-            if ( check_mounted(dest) >= 0 ) {
-                singularity_message(WARNING, "Not mounting requested bind point (already mounted in container): %s\n", dest);
-                continue;
-            }
-
-            if ( ( is_file(source) == 0 ) && ( is_file(joinpath(container_dir, dest)) < 0 ) ) {
-                if ( singularity_registry_get("OVERLAYFS_ENABLED") != NULL ) {
-                    char *dir = dirname(strdup(dest));
-                    if ( is_dir(joinpath(container_dir, dir)) < 0 ) {
-                        singularity_message(VERBOSE3, "Creating bind directory on overlay file system: %s\n", dest);
-                        if ( container_mkpath_nopriv(joinpath(container_dir, dir), 0755) < 0 ) {
-                            singularity_message(VERBOSE3, "Retrying with privileges to create bind directory on overlay file system: %s\n", dest);
-                            if ( container_mkpath_priv(joinpath(container_dir, dir), 0755) < 0 ) {
-                                singularity_message(ERROR, "Could not create basedir for file bind %s: %s\n", dest, strerror(errno));
-                                continue;
-                            }
-                        }
-                    }
-                    singularity_message(VERBOSE3, "Creating bind file on overlay file system: %s\n", dest);
-                    if ( fileput_priv(joinpath(container_dir, dest), "") != 0 ) {
-                        continue;
-                    }
-                    singularity_message(DEBUG, "Created bind file: %s\n", dest);
-                } else {
-                    singularity_message(WARNING, "Skipping user bind, non existent bind point (file) in container: '%s'\n", dest);
-                    continue;
-                }
-            } else if ( ( is_dir(source) == 0 ) && ( is_dir(joinpath(container_dir, dest)) < 0 ) ) {
-                if ( singularity_registry_get("OVERLAYFS_ENABLED") != NULL ) {
-                    singularity_message(VERBOSE3, "Creating bind directory on overlay file system: %s\n", dest);
-                    if ( container_mkpath_nopriv(joinpath(container_dir, dest), 0755) < 0 ) {
-                        singularity_message(VERBOSE3, "Retrying with privileges to create bind directory on overlay file system: %s\n", dest);
-                        if ( container_mkpath_priv(joinpath(container_dir, dest), 0755) < 0 ) {
-                            singularity_message(WARNING, "Skipping user bind, could not create bind point %s: %s\n", dest, strerror(errno));
-                            continue;
-                        }
-                    }
-                } else {
-                    singularity_message(WARNING, "Skipping user bind, non existent bind point (directory) in container: '%s'\n", dest);
-                    continue;
-                }
-            }
-
-            singularity_message(VERBOSE, "Binding '%s' to '%s/%s'\n", source, container_dir, dest);
-            if ( singularity_mount(source, joinpath(container_dir, dest), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0 ) {
-                singularity_message(ERROR, "There was an error binding the path %s: %s\n", source, strerror(errno));
-                ABORT(255);
-            }
-            if ( read_only ) {
-                if ( singularity_priv_userns_enabled() == 1 ) {
-                    singularity_message(WARNING, "Can not make bind mount read only within the user namespace: %s\n", dest);
-                } else {
-                    singularity_message(VERBOSE, "Remounting %s read-only\n", dest);
-                    if ( singularity_mount(NULL, joinpath(container_dir, dest), NULL, MS_RDONLY|MS_BIND|MS_NOSUID|MS_NODEV|MS_REC|MS_REMOUNT, NULL) < 0 ) {
-                        singularity_message(ERROR, "There was an error write-protecting the path %s: %s\n", source, strerror(errno));
-                        ABORT(255);
-                    }
-                    if ( access(joinpath(container_dir, dest), W_OK) == 0 || (errno != EROFS && errno != EACCES) ) { // Flawfinder: ignore (precautionary confirmation, not necessary)
-                        singularity_message(ERROR, "Failed to write-protect the path %s: %s\n", source, strerror(errno));
-                        ABORT(255);
-                    }
-                }
-            } else {
-                if ( singularity_priv_userns_enabled() <= 0 ) {
-                    if ( singularity_mount(NULL, joinpath(container_dir, dest), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC|MS_REMOUNT, NULL) < 0 ) {
-                        singularity_message(ERROR, "There was an error remounting the path %s: %s\n", source, strerror(errno));
-                        ABORT(255);
-                    }
-                }
-            }
+            singularity_message(VERBOSE, "Queuing bind mount of '%s' to '%s'\n", source, dest);
+            mountlist_add(mountlist, strdup(source), strdup(dest), NULL, MS_BIND|MS_NOSUID|MS_NODEV|MS_REC|read_only, 0);
         }
 
+        free(bind_path_string);
+
         singularity_message(DEBUG, "Unsetting environment variable 'SINGULARITY_BINDPATH'\n");
         unsetenv("SINGULARITY_BINDPATH");
     } else {
diff --git a/src/lib/runtime/mounts/userbinds/userbinds.h b/src/lib/runtime/mounts/userbinds/userbinds.h
index cd14d5d..34cd52a 100644
--- a/src/lib/runtime/mounts/userbinds/userbinds.h
+++ b/src/lib/runtime/mounts/userbinds/userbinds.h
@@ -24,7 +24,9 @@
 #ifndef __SINGULARITY_RUNTIME_MOUNT_USERBINDS_H_
 #define __SINGULARITY_RUNTIME_MOUNT_USERBINDS_H_
 
-extern int _singularity_runtime_mount_userbinds(void);
+struct mountlist;
+
+extern int _singularity_runtime_mount_userbinds(struct mountlist *mountlist);
 
 #endif /* __SINGULARITY_RUNTIME_MOUNT_USERBINDS_H */
 
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index ad58525..7a78e4f 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -20,6 +20,8 @@ EXTRA_DIST = cleanupd.c \
 			 message.h \
 			 mount.c \
 			 mount.h \
+			 mountlist.c \
+			 mountlist.h \
 			 privilege.c \
 			 privilege.h \
 			 registry.c \
diff --git a/src/util/config_defaults.h.in b/src/util/config_defaults.h.in
index 6bfeb78..b1676f8 100644
--- a/src/util/config_defaults.h.in
+++ b/src/util/config_defaults.h.in
@@ -41,6 +41,9 @@
 #define ENABLE_OVERLAY "enable overlay"
 #define ENABLE_OVERLAY_DEFAULT "try"
 
+#define ENABLE_UNDERLAY "enable underlay"
+#define ENABLE_UNDERLAY_DEFAULT "no"
+
 #define CONFIG_PASSWD "config passwd"
 #define CONFIG_PASSWD_DEFAULT 1
 
diff --git a/src/util/mount.c b/src/util/mount.c
index f609f82..46d2874 100644
--- a/src/util/mount.c
+++ b/src/util/mount.c
@@ -127,7 +127,7 @@ int singularity_mount(const char *source, const char *target,
     return ret;
 }
 
-int check_mounted(char *mountpoint) {
+int check_mounted(const char *mountpoint) {
     int retval = -1;
     FILE *mounts;
     char *line = (char *)malloc(MAX_LINE_LEN);
diff --git a/src/util/mount.h b/src/util/mount.h
index 8c80ea9..afca177 100644
--- a/src/util/mount.h
+++ b/src/util/mount.h
@@ -20,6 +20,6 @@
 int singularity_mount(const char *source, const char *target,
                       const char *filesystemtype, unsigned long mountflags,
                       const void *data);
-int check_mounted(char *mountpoint);
+int check_mounted(const char *mountpoint);
 
 #endif /* __MOUNT_H_ */
diff --git a/src/util/mountlist.c b/src/util/mountlist.c
new file mode 100644
index 0000000..5aded49
--- /dev/null
+++ b/src/util/mountlist.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017-2018, SyLabs, Inc. All rights reserved.
+ * Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
+ * 
+ * See the COPYRIGHT.md file at the top-level directory of this distribution and at
+ * https://github.com/singularityware/singularity/blob/master/COPYRIGHT.md.
+ * 
+ * This file is part of the Singularity Linux container project. It is subject to the license
+ * terms in the LICENSE.md file found in the top-level directory of this distribution and
+ * at https://github.com/singularityware/singularity/blob/master/LICENSE.md. No part
+ * of Singularity, including this file, may be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE.md file.
+ * 
+*/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "util/util.h"
+#include "util/mount.h"
+#include "util/mountlist.h"
+#include "util/message.h"
+
+void mountlist_add(struct mountlist *mountlist,
+                  const char *source, const char *target,
+                  const char *filesystemtype, unsigned long mountflags,
+                  unsigned long mountlistflags) {
+
+    struct mountlist_point *point;
+    point = (struct mountlist_point *) malloc(sizeof(struct mountlist_point));
+    if (mountlist->first == NULL)
+        mountlist->first = point;
+    if (mountlist->last != NULL)
+        mountlist->last->next = point;
+    mountlist->last = point;
+    point->next = NULL;
+    point->source = source;
+    point->target = target;
+    point->filesystemtype = filesystemtype;
+    point->mountflags = mountflags;
+    point->mountlistflags = mountlistflags;
+    point->resolved_target = NULL;
+}
+
+void mountlist_cleanup(struct mountlist *mountlist) {
+    struct mountlist_point *point = mountlist->first;
+
+    while (point != NULL) {
+        if ( point->source != NULL)
+            free((char *)point->source);
+        if ( point->target != NULL)
+            free((char *)point->target);
+        if ( point->resolved_target != NULL)
+            free(point->resolved_target);
+        struct mountlist_point *next = point->next;
+        free(point);
+        point = next;
+    }
+
+    mountlist->first = NULL;
+    mountlist->last = NULL;
+}
+
+int singularity_mount_point(struct mountlist_point *point) {
+
+    int retval;
+    char *target = joinpath(CONTAINER_FINALDIR, point->target);
+    const char *source = point->source;
+    if (source == NULL)
+        source = point->target;
+
+    retval = singularity_mount(source, target,
+        point->filesystemtype, point->mountflags, NULL);
+
+    free(target);
+    return retval;
+}
diff --git a/src/util/mountlist.h b/src/util/mountlist.h
new file mode 100644
index 0000000..66d44a5
--- /dev/null
+++ b/src/util/mountlist.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017-2018, SyLabs, Inc. All rights reserved.
+ * Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
+ * 
+ * See the COPYRIGHT.md file at the top-level directory of this distribution and at
+ * https://github.com/singularityware/singularity/blob/master/COPYRIGHT.md.
+ * 
+ * This file is part of the Singularity Linux container project. It is subject to the license
+ * terms in the LICENSE.md file found in the top-level directory of this distribution and
+ * at https://github.com/singularityware/singularity/blob/master/LICENSE.md. No part
+ * of Singularity, including this file, may be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE.md file.
+ * 
+*/
+
+
+#ifndef __MOUNTLIST_H_
+#define __MOUNTLIST_H_
+
+// mountlist flags
+#define ML_ONLY_IF_POINT_PRESENT 0x01
+
+struct mountlist_point {
+    struct mountlist_point *next;
+    const char *source;
+    const char *target;
+    const char *filesystemtype;
+    unsigned long mountflags;
+    unsigned long mountlistflags;
+    char *resolved_target;
+};
+
+struct mountlist {
+    struct mountlist_point *first;
+    struct mountlist_point *last;
+};
+
+// if source is NULL, it will be copied from target
+// CONTAINER_FINALDIR will be prepended to target
+// target will be freed by mountlist_cleanup, as will source if it isn't NULL
+void mountlist_add(struct mountlist *mountlist,
+                      const char *source, const char *target,
+                      const char *filesystemtype, unsigned long mountflags,
+                      unsigned long mountlistflags);
+void mountlist_cleanup(struct mountlist *mountlist);
+
+int singularity_mount_point(struct mountlist_point *point);
+
+#endif /* __MOUNTLIST_H_ */