diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ck-manager.c | 65 | ||||
-rw-r--r-- | src/ck-session-leader.c | 1 | ||||
-rw-r--r-- | src/ck-session.c | 57 | ||||
-rw-r--r-- | src/ck-session.h | 4 | ||||
-rw-r--r-- | src/ck-sysdeps-freebsd.c | 57 | ||||
-rw-r--r-- | src/ck-sysdeps-gnu.c | 12 | ||||
-rw-r--r-- | src/ck-sysdeps-linux.c | 52 | ||||
-rw-r--r-- | src/ck-sysdeps-openbsd.c | 56 | ||||
-rw-r--r-- | src/ck-sysdeps-solaris.c | 12 | ||||
-rw-r--r-- | src/ck-sysdeps-unix.c | 146 | ||||
-rw-r--r-- | src/ck-sysdeps.h | 10 | ||||
-rw-r--r-- | src/org.freedesktop.ConsoleKit.Session.xml | 13 |
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> |