[glick2] Add glick-session-launcher
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glick2] Add glick-session-launcher
- Date: Thu, 13 Oct 2011 18:30:02 +0000 (UTC)
commit c6a3a85f691d0aeabac7078b4e83bd3517186d79
Author: Alexander Larsson <alexl redhat com>
Date: Thu Oct 13 15:02:02 2011 +0200
Add glick-session-launcher
Makefile.am | 5 ++
session.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 206 insertions(+), 0 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 50de9c6..d5ad777 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,6 +14,7 @@ AM_CPPFLAGS = \
bin_PROGRAMS = \
glick-launcher \
+ glick-session-launcher \
glick-mkbundle \
glick-runner \
glick-fs \
@@ -31,6 +32,8 @@ glick_helper_LDADD = $(GLIB_LIBS)
glick_launcher_SOURCES = launcher.c
glick_launcher_LDADD = $(GLIB_LIBS) $(X11_LIBS)
+glick_session_launcher_SOURCES = session.c
+
glick_makershared_SOURCES = makershared.c
glick_runner_SOURCES = runner.c
@@ -49,6 +52,8 @@ install-data-local:
install-exec-hook:
chown root $(DESTDIR)$(libexecdir)/glick-helper
chmod 4755 $(DESTDIR)$(libexecdir)/glick-helper
+ chown root $(DESTDIR)$(libexecdir)/glick-session-launcher
+ chmod 4755 $(DESTDIR)$(libexecdir)/glick-session-launcher
ChangeLog:
$(AM_V_GEN) if test -d "$(srcdir)/.git"; then \
diff --git a/session.c b/session.c
new file mode 100644
index 0000000..ab2bb92
--- /dev/null
+++ b/session.c
@@ -0,0 +1,201 @@
+#include "config.h"
+
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <sched.h>
+
+static const char *
+get_homedir (void)
+{
+ const char *home;
+
+ home = getenv ("HOME");
+ if (home == NULL)
+ {
+ /* try from the user database */
+ struct passwd *user = getpwuid (getuid());
+ if (user != NULL)
+ home = user->pw_dir;
+ }
+
+ return home;
+}
+
+static char *
+build_path (const char *dir, const char *file)
+{
+ char *path;
+
+ path = malloc (strlen (dir) + 1 + strlen (file) + 1);
+
+ if (path != NULL)
+ {
+ strcpy (path, dir);
+ strcat (path, "/");
+ strcat (path, file);
+ }
+ return path;
+}
+
+static void
+make_symlink (const char *dest_dir, const char *dest_file,
+ const char *src_dir, const char *src_file)
+{
+ char *d, *s;
+
+ d = build_path (dest_dir, dest_file);
+ if (d)
+ {
+ s = build_path (src_dir, src_file);
+ if (s)
+ {
+ if (symlink (s, d) == -1 && errno != EEXIST)
+ perror ("Failed to symlink");
+ free (s);
+ }
+ free (d);
+ }
+}
+
+static int
+mount_rprivate (const char *path)
+{
+ return mount (path, path, NULL, MS_PRIVATE|MS_REC, NULL);
+}
+
+static int
+mount_rshared (const char *path)
+{
+ return mount (path, path, NULL, MS_SHARED|MS_REC, NULL);
+}
+
+static int
+mount_bind (const char *src, const char *dest)
+{
+ return mount (src, dest, NULL, MS_BIND, NULL);
+}
+
+int
+main(int argc, char **argv)
+{
+ char *session_dir;
+ const char *runtime_dir;
+ const char *homedir;
+ int res;
+
+ /* The initial code is run with a high permission euid
+ (at least CAP_SYS_ADMIN), so take lots of care. */
+
+ /* Switch effective uid to the user */
+ seteuid (getuid ());
+
+ if (argc == 1)
+ {
+ fprintf (stderr, "No executable specified\n");
+ return 1;
+ }
+
+
+ homedir = get_homedir ();
+ if (homedir == NULL)
+ goto error;
+
+ runtime_dir = getenv ("XDG_RUNTIME_DIR");
+ if (runtime_dir != NULL)
+ {
+ session_dir = build_path (runtime_dir, "sessiondir");
+ if (session_dir == NULL)
+ {
+ fprintf (stderr, "Out of memory\n");
+ goto error;
+ }
+
+ if (mkdir (session_dir, 0700) == -1 && errno != EEXIST)
+ {
+ fprintf (stderr, "Unable to create temporary session directory\n");
+ goto error;
+ }
+ }
+ else
+ {
+ /* Fall back to /tmp dir */
+ char tmpdir[] = "/tmp/.sessionXXXXXX";
+ session_dir = mkdtemp(tmpdir);
+ if (session_dir == NULL)
+ {
+ fprintf (stderr, "Unable to create temporary session directory\n");
+ goto error;
+ }
+ }
+
+ if (setuid (0) == -1)
+ {
+ perror ("Unable to regain root priviledges");
+ goto error;
+ }
+
+ /* Create a new mount namespace for the session */
+ res = unshare (CLONE_NEWNS);
+ if (res != 0)
+ {
+ perror ("Creating new namespace failed");
+ goto error;
+ }
+
+ /* Start with a clean slate, all mounts private */
+ res = mount_rprivate ("/");
+ if (res != 0)
+ {
+ perror ("Failed to make rprivate");
+ goto error;
+ }
+
+ /* Make /opt/session point to the session directory.
+ This will not propagate dure to the rprivate above. */
+ res = mount_bind (session_dir, SESSION_PREFIX);
+ if (res != 0)
+ {
+ perror ("Failed to bind session dir");
+ goto error;
+ }
+
+ /* Make the whole new namespace rshared so that later session
+ mounts are propagated to child bundle namespaces */
+ res = mount_rshared ("/");
+ if (res != 0)
+ {
+ perror ("Failed to make rshared");
+ goto error;
+ }
+
+ /* Except the session dir. */
+ res = mount (SESSION_PREFIX, SESSION_PREFIX,
+ NULL, MS_PRIVATE, NULL);
+ if (res != 0)
+ {
+ perror ("Failed to make session dir private");
+ goto error;
+ }
+
+ /* Now we have everything we need CAP_SYS_ADMIN for, so drop setuid */
+ setuid (getuid ());
+
+ make_symlink (session_dir, "bundles",
+ homedir, ".glick/bundles");
+ make_symlink (session_dir, "exports",
+ homedir, ".glick/exports");
+
+ return execvp (argv[1], argv+1);
+ error:
+ /* Now we have everything we need CAP_SYS_ADMIN for, so drop setuid */
+ setuid (getuid ());
+
+ return execvp (argv[1], argv+1);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]