Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <sys/epoll.h>
#include <fcntl.h>
-#include "logind-session.h"
#include "strv.h"
#include "util.h"
+#include "mkdir.h"
+#include "path-util.h"
#include "cgroup-util.h"
+#include "logind-session.h"
#define IDLE_THRESHOLD_USEC (5*USEC_PER_MINUTE)
return NULL;
}
- s->id = file_name_from_path(s->state_file);
+ s->id = path_get_file_name(s->state_file);
if (hashmap_put(m->sessions, s->id, s) < 0) {
- free(s->id);
+ free(s->state_file);
free(s);
return NULL;
}
free(s->service);
hashmap_remove(s->manager->sessions, s->id);
-
session_remove_fifo(s);
free(s->state_file);
"TYPE=%s\n",
session_type_to_string(s->type));
+ if (s->class >= 0)
+ fprintf(f,
+ "CLASS=%s\n",
+ session_class_to_string(s->class));
+
if (s->cgroup_path)
fprintf(f,
"CGROUP=%s\n",
*vtnr = NULL,
*leader = NULL,
*audit_id = NULL,
- *type = NULL;
+ *type = NULL,
+ *class = NULL;
int k, r;
"VTNR", &vtnr,
"LEADER", &leader,
"TYPE", &type,
+ "CLASS", &class,
NULL);
if (r < 0)
}
if (leader) {
- pid_t pid;
-
- k = parse_pid(leader, &pid);
- if (k >= 0 && pid >= 1) {
- s->leader = pid;
-
- audit_session_from_pid(pid, &s->audit_id);
- }
+ k = parse_pid(leader, &s->leader);
+ if (k >= 0)
+ audit_session_from_pid(s->leader, &s->audit_id);
}
if (type) {
s->type = t;
}
+ if (class) {
+ SessionClass c;
+
+ c = session_class_from_string(class);
+ if (c >= 0)
+ s->class = c;
+ }
+
if (s->fifo_path) {
int fd;
close_nointr_nofail(fd);
}
-
finish:
free(remote);
free(kill_processes);
free(vtnr);
free(leader);
free(audit_id);
+ free(class);
return r;
}
return -ENOENT;
}
+ /* Note that this cannot be in a subdir to avoid
+ * vulnerabilities since we are privileged but the runtime
+ * path is owned by the user */
+
t = strappend(s->user->runtime_path, "/X11-display");
if (!t) {
log_error("Out of memory");
log_error("Failed to kill session cgroup: %s", strerror(-r));
} else {
+ if (s->leader > 0) {
+ Session *t;
+
+ /* We still send a HUP to the leader process,
+ * even if we are not supposed to kill the
+ * whole cgroup. But let's first check the
+ * leader still exists and belongs to our
+ * session... */
+
+ r = manager_get_session_by_pid(s->manager, s->leader, &t);
+ if (r > 0 && t == s) {
+ kill(s->leader, SIGTERM); /* for normal processes */
+ kill(s->leader, SIGHUP); /* for shells */
+ kill(s->leader, SIGCONT); /* in case they are stopped */
+ }
+ }
+
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, true);
if (r < 0)
log_error("Failed to check session cgroup: %s", strerror(-r));
r = cg_delete(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path);
if (r < 0)
log_error("Failed to delete session cgroup: %s", strerror(-r));
- } else
- r = -EBUSY;
+ }
}
STRV_FOREACH(k, s->user->manager->controllers)
free(s->cgroup_path);
s->cgroup_path = NULL;
- return r;
+ return 0;
}
static int session_unlink_x11_socket(Session *s) {
if (s->fifo_fd < 0)
return -errno;
- r = hashmap_put(s->manager->fifo_fds, INT_TO_PTR(s->fifo_fd + 1), s);
+ r = hashmap_put(s->manager->session_fds, INT_TO_PTR(s->fifo_fd + 1), s);
if (r < 0)
return r;
assert(s);
if (s->fifo_fd >= 0) {
- assert_se(hashmap_remove(s->manager->fifo_fds, INT_TO_PTR(s->fifo_fd + 1)) == s);
+ assert_se(hashmap_remove(s->manager->session_fds, INT_TO_PTR(s->fifo_fd + 1)) == s);
assert_se(epoll_ctl(s->manager->epoll_fd, EPOLL_CTL_DEL, s->fifo_fd, NULL) == 0);
close_nointr_nofail(s->fifo_fd);
s->fifo_fd = -1;
DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
+static const char* const session_class_table[_SESSION_CLASS_MAX] = {
+ [SESSION_USER] = "user",
+ [SESSION_GREETER] = "greeter",
+ [SESSION_LOCK_SCREEN] = "lock-screen"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
+
static const char* const kill_who_table[_KILL_WHO_MAX] = {
[KILL_LEADER] = "leader",
[KILL_ALL] = "all"