[glick2] If we can't do the final bind mount, instead use a private tmpfs mount and a symlink



commit 0bd1f7ad5c4edfc9f0887421798d25c4fe89aa3f
Author: Alexander Larsson <alexl redhat com>
Date:   Tue Nov 22 14:37:31 2011 +0100

    If we can't do the final bind mount, instead use a private tmpfs mount and a symlink

 helper.c |   55 +++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 47 insertions(+), 8 deletions(-)
---
diff --git a/helper.c b/helper.c
index 67e28db..e3b2446 100644
--- a/helper.c
+++ b/helper.c
@@ -80,6 +80,7 @@ main (int argc,
   char **child_argv;
   int i, j, fd, argv_offset;
   int mount_count;
+  int use_tmpfs;
 
   /* The initial code is run with a high permission euid
      (at least CAP_SYS_ADMIN), so take lots of care. */
@@ -160,27 +161,65 @@ main (int argc,
       }
     }
 
-  __debug__(("mount source\n"));
+  use_tmpfs = 0;
+  __debug__(("mount source %s to %s\n", mount_source, BUNDLE_PREFIX));
   res = mount (mount_source, BUNDLE_PREFIX,
 	       NULL, MS_BIND, NULL);
-  if (res != 0) {
-    perror ("Failed to bind the source directory");
-    goto error_out;
-  }
+  if (res != 0) 
+    {
+      int errsv = errno;
+      printf ("errno: %d\n", errsv);
+      if (errsv == EACCES)
+	{
+	  /* Some older kernels don't allow bind mounting (as root) a file
+	     inside a (non-root) fuse mount (as the uid differs). For these
+	     cases we create a private tmpfs mount with a symlink in */
+	  res = mount ("tmpfs" , BUNDLE_PREFIX,
+		       "tmpfs", MS_NODEV|MS_NOEXEC, NULL);
+	  
+	  if (res != 0)
+	    {
+	      perror ("Failed to mount tmpfs");
+	      goto error_out;
+	    }
+
+	  use_tmpfs = 1;
+	}
+      else
+	{
+	  perror ("Failed to bind the source directory");
+	  goto error_out;
+	}
+    }
   mount_count++; /* Normal mount succeeded */
 
   /* Now we have everything we need CAP_SYS_ADMIN for, so drop setuid */
   setuid (getuid ());
 
+  executable = NULL;
+  child_argv = NULL;
+
+  if (use_tmpfs)
+    {
+      char *mount_source_data = strconcat (mount_source, "/data", NULL);
+      if (mount_source_data == NULL)
+	goto oom;
+      res = symlink (mount_source_data, BUNDLE_PREFIX "/data");
+      if (res != 0)
+	{
+	  perror ("Unable to create symlink");
+	  free (mount_source_data);
+	  goto error_out;
+	}
+      free (mount_source_data);
+    }
+
   if (fd != 0)
     {
       char c = 'x';
       write (fd, &c, 1);
     }
 
-  executable = NULL;
-  child_argv = NULL;
-
   if (executable_relative[0] == '/')
     executable = executable_relative;
   else



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]