summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ck-manager.c65
-rw-r--r--src/ck-session-leader.c1
-rw-r--r--src/ck-session.c57
-rw-r--r--src/ck-session.h4
-rw-r--r--src/ck-sysdeps-freebsd.c57
-rw-r--r--src/ck-sysdeps-gnu.c12
-rw-r--r--src/ck-sysdeps-linux.c52
-rw-r--r--src/ck-sysdeps-openbsd.c56
-rw-r--r--src/ck-sysdeps-solaris.c12
-rw-r--r--src/ck-sysdeps-unix.c146
-rw-r--r--src/ck-sysdeps.h10
-rw-r--r--src/org.freedesktop.ConsoleKit.Session.xml13
12 files changed, 484 insertions, 1 deletions
diff --git a/src/ck-manager.c b/src/ck-manager.c
index 4a6e511..a72d5a1 100644
--- a/src/ck-manager.c
+++ b/src/ck-manager.c
@@ -1165,6 +1165,40 @@ get_system_num_users (CkManager *manager)
return num_users;
}
+static gboolean
+session_has_user (const char *ssid,
+ CkSession *session,
+ guint *unix_user)
+{
+ guint session_user;
+
+ session_user = console_kit_session_get_unix_user (CONSOLE_KIT_SESSION (session));
+
+ if (session_user == *unix_user) {
+ g_debug ("Found session for user %d", *unix_user);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static const gchar *
+get_runtime_dir_for_user (CkManager *manager,
+ guint unix_user)
+{
+ gpointer session;
+
+ TRACE ();
+
+ session = g_hash_table_find (manager->priv->sessions, (GHRFunc)session_has_user, &unix_user);
+
+ if (session != NULL) {
+ return ck_session_get_runtime_dir (CK_SESSION (session));
+ }
+
+ return NULL;
+}
+
#ifdef ENABLE_RBAC_SHUTDOWN
static gboolean
check_rbac_permissions (CkManager *manager,
@@ -2584,6 +2618,8 @@ open_session_for_leader (CkManager *manager,
CkSeat *seat;
const char *ssid;
const char *cookie;
+ char *runtime_dir;
+ guint unix_user;
ssid = ck_session_leader_peek_session_id (leader);
cookie = ck_session_leader_peek_cookie (leader);
@@ -2598,6 +2634,20 @@ open_session_for_leader (CkManager *manager,
return;
}
+ unix_user = console_kit_session_get_unix_user (CONSOLE_KIT_SESSION (session));
+
+ /* If the user is already logged in, continue to use the same runtime dir.
+ * We need to do this before adding the session to the manager's table. */
+ runtime_dir = g_strdup (get_runtime_dir_for_user (manager, unix_user));
+
+ /* otherwise generate a new one */
+ if (runtime_dir == NULL) {
+ runtime_dir = ck_generate_runtime_dir_for_user (unix_user);
+ }
+
+ g_debug ("XDG_RUNTIME_DIR is %s", runtime_dir);
+ ck_session_set_runtime_dir (session, runtime_dir);
+
/* If supported, add the session leader to a process group so we
* can track it with something better than an environment variable */
pgroup = ck_process_group_get ();
@@ -2631,6 +2681,7 @@ open_session_for_leader (CkManager *manager,
manager);
g_object_unref (session);
+ g_free (runtime_dir);
g_dbus_method_invocation_return_value (context , g_variant_new ("(s)", cookie));
}
@@ -3016,6 +3067,7 @@ remove_session_for_cookie (CkManager *manager,
char *orig_ssid;
CkSessionLeader *leader;
char *sid;
+ guint unix_user;
gboolean res;
gboolean ret;
@@ -3055,6 +3107,11 @@ remove_session_for_cookie (CkManager *manager,
* for seat removals doesn't work.
*/
+ /* Get the session's uid, we'll need this if we have to remove the
+ * runtime dir
+ */
+ unix_user = console_kit_session_get_unix_user (CONSOLE_KIT_SESSION (orig_session));
+
/* remove from seat */
sid = NULL;
ck_session_get_seat_id (orig_session, &sid, NULL);
@@ -3085,6 +3142,14 @@ remove_session_for_cookie (CkManager *manager,
manager_update_system_idle_hint (manager);
+ if (get_runtime_dir_for_user (manager, unix_user) == NULL) {
+ /* We removed the session and now there's no runtime dir
+ * associated with that user.
+ * Remove the runtime dir from the system.
+ */
+ ck_remove_runtime_dir_for_user (unix_user);
+ }
+
ret = TRUE;
out:
if (orig_session != NULL) {
diff --git a/src/ck-session-leader.c b/src/ck-session-leader.c
index 2b392b6..5fd4f96 100644
--- a/src/ck-session-leader.c
+++ b/src/ck-session-leader.c
@@ -62,6 +62,7 @@ struct CkSessionLeaderPrivate
char *service_name;
char *session_id;
char *cookie;
+ char *runtime_dir;
GList *pending_jobs;
gboolean cancelled;
GHashTable *override_parameters;
diff --git a/src/ck-session.c b/src/ck-session.c
index 1b58889..901422f 100644
--- a/src/ck-session.c
+++ b/src/ck-session.c
@@ -53,7 +53,7 @@ struct CkSessionPrivate
char *id;
char *cookie;
char *seat_id;
-
+ char *runtime_dir;
char *login_session_id;
GTimeVal creation_time;
@@ -832,6 +832,58 @@ ck_session_set_seat_id (CkSession *session,
return TRUE;
}
+/**
+ * ck_session_set_runtime_dir
+ * @session: CkSession object
+ * @runtime_dir: The XDG_RUNTIME_DIR for the user of this session. For details, see:
+ * http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
+ * returns: TRUE if successfully set, FALSE on failure.
+ **/
+gboolean
+ck_session_set_runtime_dir (CkSession *session,
+ const char *runtime_dir)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ g_free (session->priv->runtime_dir);
+ session->priv->runtime_dir = g_strdup (runtime_dir);
+
+ return TRUE;
+}
+
+/**
+ * ck_session_get_runtime_dir
+ * @session: CkSession object
+ * returns: The XDG_RUNTIME_DIR. For details, see:
+ * http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
+ **/
+const char *
+ck_session_get_runtime_dir (CkSession *session)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), NULL);
+ return session->priv->runtime_dir;
+}
+
+static gboolean
+dbus_get_runtime_dir (ConsoleKitSession *cksession,
+ GDBusMethodInvocation *context)
+{
+ CkSession *session = CK_SESSION(cksession);
+
+ TRACE ();
+
+ g_return_val_if_fail (CK_IS_SESSION (cksession), FALSE);
+
+ /* if no login session id is set return an empty string */
+ if (session->priv->runtime_dir == NULL) {
+ throw_error (context, CK_SESSION_ERROR_FAILED, _("Failed to create the XDG_RUNTIME_DIR"));
+ return FALSE;
+ }
+
+ console_kit_session_complete_get_xdgruntime_dir (cksession, context, session->priv->runtime_dir);
+ return TRUE;
+}
+
static gboolean
dbus_get_login_session_id (ConsoleKitSession *cksession,
GDBusMethodInvocation *context)
@@ -1087,6 +1139,7 @@ ck_session_iface_init (ConsoleKitSessionIface *iface)
iface->handle_lock = dbus_lock;
iface->handle_unlock = dbus_unlock;
iface->handle_get_idle_hint = dbus_get_idle_hint;
+ iface->handle_get_xdgruntime_dir = dbus_get_runtime_dir;
}
static void
@@ -1108,6 +1161,7 @@ ck_session_finalize (GObject *object)
g_free (session->priv->id);
g_free (session->priv->cookie);
g_free (session->priv->login_session_id);
+ g_free (session->priv->runtime_dir);
G_OBJECT_CLASS (ck_session_parent_class)->finalize (object);
}
@@ -1341,6 +1395,7 @@ ck_session_dump (CkSession *session,
g_key_file_set_boolean (key_file, group_name, "is_active", console_kit_session_get_active (cksession));
g_key_file_set_boolean (key_file, group_name, "is_local", console_kit_session_get_is_local (cksession));
+ g_key_file_set_string (key_file, group_name, "XDG_RUNTIME_DIR", NONULL_STRING (session->priv->runtime_dir));
s = g_time_val_to_iso8601 (&(session->priv->creation_time));
g_key_file_set_string (key_file,
diff --git a/src/ck-session.h b/src/ck-session.h
index d9b35cd..8750e2f 100644
--- a/src/ck-session.h
+++ b/src/ck-session.h
@@ -125,8 +125,12 @@ gboolean ck_session_get_login_session_id (CkSession *se
gboolean ck_session_get_creation_time (CkSession *session,
char **iso8601_datetime,
GError **error);
+const char * ck_session_get_runtime_dir (CkSession *session);
+gboolean ck_session_set_runtime_dir (CkSession *session,
+ const char *runtime_dir);
+
gboolean ck_session_set_id (CkSession *session,
const char *ssid,
GError **error);
diff --git a/src/ck-sysdeps-freebsd.c b/src/ck-sysdeps-freebsd.c
index e7cbb04..b7a93c5 100644
--- a/src/ck-sysdeps-freebsd.c
+++ b/src/ck-sysdeps-freebsd.c
@@ -45,6 +45,15 @@
#endif
#include <sys/consio.h>
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+
#define DEV_ENCODE(M,m) ( \
( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \
)
@@ -598,3 +607,51 @@ ck_system_can_hybrid_sleep (void)
/* TODO: not implemented */
return FALSE;
}
+
+gboolean
+ck_make_tmpfs (guint uid, guint gid, const gchar *dest)
+{
+#ifdef HAVE_SYS_MOUNT_H
+ gchar *opts;
+ int result;
+
+ TRACE ();
+
+ opts = g_strdup_printf ("mode=0700,size=8M,uid=%d,guid=%d", uid, gid);
+
+ result = mount("tmpfs", dest, 0, opts);
+
+ g_free (opts);
+
+ if (result == 0) {
+ return TRUE;
+ } else {
+ g_info ("Failed to create tmpfs mount, reason was: %s", strerror(errno));
+ errno = 0;
+ return FALSE;
+ }
+#endif
+
+ return FALSE;
+}
+
+gboolean
+ck_remove_tmpfs (guint uid, const gchar *dest)
+{
+#ifdef HAVE_SYS_MOUNT_H
+ int result;
+
+ TRACE ();
+
+ result = unmount(dest, 0);
+
+ if (result == 0) {
+ return TRUE;
+ }
+
+ g_info ("Failed to unmount tmpfs mount, reason was: %s", strerror(errno));
+ errno = 0;
+#endif
+
+ return FALSE;
+}
diff --git a/src/ck-sysdeps-gnu.c b/src/ck-sysdeps-gnu.c
index 9437559..2ff9b24 100644
--- a/src/ck-sysdeps-gnu.c
+++ b/src/ck-sysdeps-gnu.c
@@ -421,3 +421,15 @@ ck_system_can_hybrid_sleep (void)
/* TODO: not implemented */
return FALSE;
}
+
+gboolean
+ck_make_tmpfs (guint uid, guint gid, const gchar *dest)
+{
+ return FALSE;
+}
+
+gboolean
+ck_remove_tmpfs (guint uid, const gchar *dest)
+{
+ return FALSE;
+}
diff --git a/src/ck-sysdeps-linux.c b/src/ck-sysdeps-linux.c
index d3d1b5a..aea9ab1 100644
--- a/src/ck-sysdeps-linux.c
+++ b/src/ck-sysdeps-linux.c
@@ -39,6 +39,10 @@
#include <paths.h>
#endif /* HAVE_PATHS_H */
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+
#include "ck-sysdeps.h"
#ifndef ERROR
@@ -900,6 +904,54 @@ ck_system_can_hybrid_sleep (void)
return linux_supports_sleep_state ("suspend-hybrid");
}
+gboolean
+ck_make_tmpfs (guint uid, guint gid, const gchar *dest)
+{
+#ifdef HAVE_SYS_MOUNT_H
+ gchar *opts;
+ int result;
+
+ TRACE ();
+
+ opts = g_strdup_printf ("mode=0700,size=8M,uid=%d,guid=%d", uid, gid);
+
+ result = mount("none", dest, "tmpfs", 0, opts);
+
+ g_free (opts);
+
+ if (result == 0) {
+ return TRUE;
+ } else {
+ g_info ("Failed to create tmpfs mount, reason was: %s", strerror(errno));
+ errno = 0;
+ return FALSE;
+ }
+#endif
+
+ return FALSE;
+}
+
+gboolean
+ck_remove_tmpfs (guint uid, const char* dest)
+{
+#ifdef HAVE_SYS_MOUNT_H
+ int result;
+
+ TRACE ();
+
+ result = umount2(dest, MNT_DETACH);
+
+ if (result == 0) {
+ return TRUE;
+ }
+
+ g_info ("Failed to unmount tmpfs mount, reason was: %s", strerror(errno));
+ errno = 0;
+#endif
+
+ return FALSE;
+}
+
#ifdef HAVE_SYS_VT_SIGNAL
/* For the moment this is Linux only.
* Returns the vt file descriptor or < 0 on failure.
diff --git a/src/ck-sysdeps-openbsd.c b/src/ck-sysdeps-openbsd.c
index c924864..af1ee3a 100644
--- a/src/ck-sysdeps-openbsd.c
+++ b/src/ck-sysdeps-openbsd.c
@@ -43,6 +43,14 @@
#include <sys/stdint.h>
#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
#include <dev/wscons/wsdisplay_usl_io.h>
#define DEV_ENCODE(M,m) ( \
@@ -484,3 +492,51 @@ ck_system_can_hybrid_sleep (void)
/* TODO: not implemented */
return FALSE;
}
+
+gboolean
+ck_make_tmpfs (guint uid, guint gid, const gchar *dest)
+{
+#ifdef HAVE_SYS_MOUNT_H
+ gchar *opts;
+ int result;
+
+ TRACE ();
+
+ opts = g_strdup_printf ("mode=0700,size=8M,uid=%d,guid=%d", uid, gid);
+
+ result = mount("tmpfs", dest, 0, opts);
+
+ g_free (opts);
+
+ if (result == 0) {
+ return TRUE;
+ } else {
+ g_info ("Failed to create tmpfs mount, reason was: %s", strerror(errno));
+ errno = 0;
+ return FALSE;
+ }
+#endif
+
+ return FALSE;
+}
+
+gboolean
+ck_remove_tmpfs (guint uid, const gchar *dest)
+{
+#ifdef HAVE_SYS_MOUNT_H
+ int result;
+
+ TRACE ();
+
+ result = unmount(dest, 0);
+
+ if (result == 0) {
+ return TRUE;
+ }
+
+ g_info ("Failed to unmount tmpfs mount, reason was: %s", strerror(errno));
+ errno = 0;
+#endif
+
+ return FALSE;
+}
diff --git a/src/ck-sysdeps-solaris.c b/src/ck-sysdeps-solaris.c
index 9d26380..0387fca 100644
--- a/src/ck-sysdeps-solaris.c
+++ b/src/ck-sysdeps-solaris.c
@@ -550,3 +550,15 @@ ck_system_can_hybrid_sleep (void)
/* TODO: not implemented */
return FALSE;
}
+
+gboolean
+ck_make_tmpfs (guint uid, guint gid, const gchar *dest)
+{
+ return FALSE;
+}
+
+gboolean
+ck_remove_tmpfs (guint uid, const gchar *dest)
+{
+ return FALSE;
+}
diff --git a/src/ck-sysdeps-unix.c b/src/ck-sysdeps-unix.c
index c24a0e1..a618388 100644
--- a/src/ck-sysdeps-unix.c
+++ b/src/ck-sysdeps-unix.c
@@ -31,6 +31,7 @@
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
+#include <pwd.h>
#ifdef __linux__
#include <linux/kd.h>
@@ -56,6 +57,10 @@
#include <ucred.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
#include "ck-sysdeps.h"
#ifndef ERROR
@@ -328,6 +333,147 @@ ck_is_root_user (void)
return FALSE;
}
+/* Call g_free on string when done using it. [transfer: full] */
+static gchar *
+get_rundir (guint uid)
+{
+ const gchar *base;
+
+ TRACE ();
+
+ base = RUNDIR "/user";
+
+ return g_strdup_printf ("%s/%d", base, uid);
+}
+
+static gboolean
+create_rundir_base (guint uid)
+{
+ const gchar *base;
+
+ TRACE ();
+
+ base = RUNDIR "/user";
+
+ /* Create the base directory that we will own. */
+ if (g_mkdir_with_parents (base, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
+ g_warning ("Failed to create %s, reason was: %s", base, strerror(errno));
+ errno = 0;
+ return FALSE;
+ }
+
+ /* ensure we have ownership */
+ if (chown (base, 0, 0) != 0) {
+ g_warning ("Failed to chown %s, reason was: %s", base, strerror(errno));
+ errno = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+remove_rundir (guint uid, const gchar *dest)
+{
+ gchar *command;
+ GError *error = NULL;
+ gboolean res;
+
+ TRACE ();
+
+ g_return_val_if_fail (dest, FALSE);
+
+ if (uid < 1) {
+ g_debug ("We didn't create a runtime dir for root, nothing to remove");
+ return FALSE;
+ }
+
+ command = g_strdup_printf (LIBEXECDIR "/ck-remove-directory --uid=%d --dest=%s", uid, dest);
+
+ res = g_spawn_command_line_sync (command, NULL, NULL, NULL, &error);
+
+ if (! res) {
+ g_warning ("Unable to remove user runtime dir '%s' error was: %s", dest, error->message);
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gchar *
+ck_generate_runtime_dir_for_user (guint uid)
+{
+ gchar *dest;
+ struct passwd *pwent;
+
+ TRACE ();
+
+ if (uid < 1) {
+ g_debug ("We do not create runtime dirs for root");
+ return NULL;
+ }
+
+ errno = 0;
+ pwent = getpwuid (uid);
+ if (pwent == NULL) {
+ g_warning ("Unable to lookup UID: %s", g_strerror (errno));
+ errno = 0;
+ return NULL;
+ }
+
+ /* ensure we have created the base directory */
+ if (create_rundir_base (uid) == FALSE) {
+ return NULL;
+ }
+
+ dest = get_rundir (uid);
+
+ /* Create the new directory */
+ if (g_mkdir_with_parents (dest, S_IRWXU) != 0) {
+ g_warning ("Failed to create XDG_RUNTIME_DIR, reason was: %s", strerror(errno));
+ errno = 0;
+ g_free (dest);
+ return NULL;
+ }
+
+ g_debug ("setting uid %d, gid %d", uid, pwent->pw_gid);
+
+ /* assign ownership to the user */
+ if (chown (dest, uid, pwent->pw_gid) != 0) {
+ g_warning ("Failed to chown XDG_RUNTIME_DIR, reason was: %s", strerror(errno));
+ errno = 0;
+ g_free (dest);
+ return NULL;
+ }
+
+ /* attempt to make it a small tmpfs location */
+ ck_make_tmpfs (uid, pwent->pw_gid, dest);
+
+ return dest;
+}
+
+gboolean
+ck_remove_runtime_dir_for_user (guint uid)
+{
+ gchar *dest;
+
+ TRACE ();
+
+ dest = get_rundir (uid);
+
+ /* attempt to remove the tmpfs */
+ ck_remove_tmpfs (uid, dest);
+
+ /* remove the user's runtime dir now that all user sessions
+ * are gone */
+ remove_rundir (uid, dest);
+
+ g_free (dest);
+
+ return TRUE;
+}
+
gboolean
ck_wait_for_active_console_num (int console_fd,
guint num)
diff --git a/src/ck-sysdeps.h b/src/ck-sysdeps.h
index bc32631..0390cb4 100644
--- a/src/ck-sysdeps.h
+++ b/src/ck-sysdeps.h
@@ -60,6 +60,16 @@ gboolean ck_fd_is_a_console (int fd);
gboolean ck_is_root_user (void);
+gchar * ck_generate_runtime_dir_for_user (guint uid);
+
+gboolean ck_remove_runtime_dir_for_user (guint uid);
+
+gboolean ck_make_tmpfs (guint uid,
+ guint gid,
+ const gchar *dest);
+gboolean ck_remove_tmpfs (guint uid,
+ const gchar *dest);
+
gboolean ck_get_max_num_consoles (guint *num);
gboolean ck_supports_activatable_consoles (void);
diff --git a/src/org.freedesktop.ConsoleKit.Session.xml b/src/org.freedesktop.ConsoleKit.Session.xml
index 4f5c268..2330de4 100644
--- a/src/org.freedesktop.ConsoleKit.Session.xml
+++ b/src/org.freedesktop.ConsoleKit.Session.xml
@@ -78,6 +78,19 @@
<doc:seealso><doc:ref type="property" to="Session:unix-user">unix-user</doc:ref></doc:seealso>
</doc:doc>
</method>
+ <method name="GetXDGRuntimeDir">
+ <arg name="xdg_runtime_dir" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>XDG_RUNTIME_DIR</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the XDG_RUNTIME_DIR location of the session.
+ The XDG_RUNTIME_DIR is the same for all sessions of the same user and will be automatically
+ removed once the last session of the user is closed.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
<method name="GetX11Display">
<arg name="display" direction="out" type="s">
<doc:doc>