1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <errno.h>
4 #include <unistd.h>
5 
6 #include "alloc-util.h"
7 #include "bus-common-errors.h"
8 #include "bus-error.h"
9 #include "bus-util.h"
10 #include "cgroup-util.h"
11 #include "clean-ipc.h"
12 #include "env-file.h"
13 #include "escape.h"
14 #include "fd-util.h"
15 #include "fileio.h"
16 #include "format-util.h"
17 #include "fs-util.h"
18 #include "hashmap.h"
19 #include "label.h"
20 #include "limits-util.h"
21 #include "logind-dbus.h"
22 #include "logind-user-dbus.h"
23 #include "logind-user.h"
24 #include "mkdir-label.h"
25 #include "parse-util.h"
26 #include "path-util.h"
27 #include "percent-util.h"
28 #include "rm-rf.h"
29 #include "serialize.h"
30 #include "special.h"
31 #include "stdio-util.h"
32 #include "string-table.h"
33 #include "strv.h"
34 #include "tmpfile-util.h"
35 #include "uid-alloc-range.h"
36 #include "unit-name.h"
37 #include "user-util.h"
38 #include "util.h"
39 
user_new(User ** ret,Manager * m,UserRecord * ur)40 int user_new(User **ret,
41              Manager *m,
42              UserRecord *ur) {
43 
44         _cleanup_(user_freep) User *u = NULL;
45         char lu[DECIMAL_STR_MAX(uid_t) + 1];
46         int r;
47 
48         assert(ret);
49         assert(m);
50         assert(ur);
51 
52         if (!ur->user_name)
53                 return -EINVAL;
54 
55         if (!uid_is_valid(ur->uid))
56                 return -EINVAL;
57 
58         u = new(User, 1);
59         if (!u)
60                 return -ENOMEM;
61 
62         *u = (User) {
63                 .manager = m,
64                 .user_record = user_record_ref(ur),
65                 .last_session_timestamp = USEC_INFINITY,
66         };
67 
68         if (asprintf(&u->state_file, "/run/systemd/users/" UID_FMT, ur->uid) < 0)
69                 return -ENOMEM;
70 
71         if (asprintf(&u->runtime_path, "/run/user/" UID_FMT, ur->uid) < 0)
72                 return -ENOMEM;
73 
74         xsprintf(lu, UID_FMT, ur->uid);
75         r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &u->slice);
76         if (r < 0)
77                 return r;
78 
79         r = unit_name_build("user", lu, ".service", &u->service);
80         if (r < 0)
81                 return r;
82 
83         r = unit_name_build("user-runtime-dir", lu, ".service", &u->runtime_dir_service);
84         if (r < 0)
85                 return r;
86 
87         r = hashmap_put(m->users, UID_TO_PTR(ur->uid), u);
88         if (r < 0)
89                 return r;
90 
91         r = hashmap_put(m->user_units, u->slice, u);
92         if (r < 0)
93                 return r;
94 
95         r = hashmap_put(m->user_units, u->service, u);
96         if (r < 0)
97                 return r;
98 
99         r = hashmap_put(m->user_units, u->runtime_dir_service, u);
100         if (r < 0)
101                 return r;
102 
103         *ret = TAKE_PTR(u);
104         return 0;
105 }
106 
user_free(User * u)107 User *user_free(User *u) {
108         if (!u)
109                 return NULL;
110 
111         if (u->in_gc_queue)
112                 LIST_REMOVE(gc_queue, u->manager->user_gc_queue, u);
113 
114         while (u->sessions)
115                 session_free(u->sessions);
116 
117         if (u->service)
118                 hashmap_remove_value(u->manager->user_units, u->service, u);
119 
120         if (u->runtime_dir_service)
121                 hashmap_remove_value(u->manager->user_units, u->runtime_dir_service, u);
122 
123         if (u->slice)
124                 hashmap_remove_value(u->manager->user_units, u->slice, u);
125 
126         hashmap_remove_value(u->manager->users, UID_TO_PTR(u->user_record->uid), u);
127 
128         sd_event_source_unref(u->timer_event_source);
129 
130         u->service_job = mfree(u->service_job);
131 
132         u->service = mfree(u->service);
133         u->runtime_dir_service = mfree(u->runtime_dir_service);
134         u->slice = mfree(u->slice);
135         u->runtime_path = mfree(u->runtime_path);
136         u->state_file = mfree(u->state_file);
137 
138         user_record_unref(u->user_record);
139 
140         return mfree(u);
141 }
142 
user_save_internal(User * u)143 static int user_save_internal(User *u) {
144         _cleanup_free_ char *temp_path = NULL;
145         _cleanup_fclose_ FILE *f = NULL;
146         int r;
147 
148         assert(u);
149         assert(u->state_file);
150 
151         r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0, MKDIR_WARN_MODE);
152         if (r < 0)
153                 goto fail;
154 
155         r = fopen_temporary(u->state_file, &f, &temp_path);
156         if (r < 0)
157                 goto fail;
158 
159         (void) fchmod(fileno(f), 0644);
160 
161         fprintf(f,
162                 "# This is private data. Do not parse.\n"
163                 "NAME=%s\n"
164                 "STATE=%s\n"         /* friendly user-facing state */
165                 "STOPPING=%s\n",     /* low-level state */
166                 u->user_record->user_name,
167                 user_state_to_string(user_get_state(u)),
168                 yes_no(u->stopping));
169 
170         /* LEGACY: no-one reads RUNTIME= anymore, drop it at some point */
171         if (u->runtime_path)
172                 fprintf(f, "RUNTIME=%s\n", u->runtime_path);
173 
174         if (u->service_job)
175                 fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
176 
177         if (u->display)
178                 fprintf(f, "DISPLAY=%s\n", u->display->id);
179 
180         if (dual_timestamp_is_set(&u->timestamp))
181                 fprintf(f,
182                         "REALTIME="USEC_FMT"\n"
183                         "MONOTONIC="USEC_FMT"\n",
184                         u->timestamp.realtime,
185                         u->timestamp.monotonic);
186 
187         if (u->last_session_timestamp != USEC_INFINITY)
188                 fprintf(f, "LAST_SESSION_TIMESTAMP=" USEC_FMT "\n",
189                         u->last_session_timestamp);
190 
191         if (u->sessions) {
192                 bool first;
193 
194                 fputs("SESSIONS=", f);
195                 first = true;
196                 LIST_FOREACH(sessions_by_user, i, u->sessions) {
197                         if (first)
198                                 first = false;
199                         else
200                                 fputc(' ', f);
201 
202                         fputs(i->id, f);
203                 }
204 
205                 fputs("\nSEATS=", f);
206                 first = true;
207                 LIST_FOREACH(sessions_by_user, i, u->sessions) {
208                         if (!i->seat)
209                                 continue;
210 
211                         if (first)
212                                 first = false;
213                         else
214                                 fputc(' ', f);
215 
216                         fputs(i->seat->id, f);
217                 }
218 
219                 fputs("\nACTIVE_SESSIONS=", f);
220                 first = true;
221                 LIST_FOREACH(sessions_by_user, i, u->sessions) {
222                         if (!session_is_active(i))
223                                 continue;
224 
225                         if (first)
226                                 first = false;
227                         else
228                                 fputc(' ', f);
229 
230                         fputs(i->id, f);
231                 }
232 
233                 fputs("\nONLINE_SESSIONS=", f);
234                 first = true;
235                 LIST_FOREACH(sessions_by_user, i, u->sessions) {
236                         if (session_get_state(i) == SESSION_CLOSING)
237                                 continue;
238 
239                         if (first)
240                                 first = false;
241                         else
242                                 fputc(' ', f);
243 
244                         fputs(i->id, f);
245                 }
246 
247                 fputs("\nACTIVE_SEATS=", f);
248                 first = true;
249                 LIST_FOREACH(sessions_by_user, i, u->sessions) {
250                         if (!session_is_active(i) || !i->seat)
251                                 continue;
252 
253                         if (first)
254                                 first = false;
255                         else
256                                 fputc(' ', f);
257 
258                         fputs(i->seat->id, f);
259                 }
260 
261                 fputs("\nONLINE_SEATS=", f);
262                 first = true;
263                 LIST_FOREACH(sessions_by_user, i, u->sessions) {
264                         if (session_get_state(i) == SESSION_CLOSING || !i->seat)
265                                 continue;
266 
267                         if (first)
268                                 first = false;
269                         else
270                                 fputc(' ', f);
271 
272                         fputs(i->seat->id, f);
273                 }
274                 fputc('\n', f);
275         }
276 
277         r = fflush_and_check(f);
278         if (r < 0)
279                 goto fail;
280 
281         if (rename(temp_path, u->state_file) < 0) {
282                 r = -errno;
283                 goto fail;
284         }
285 
286         return 0;
287 
288 fail:
289         (void) unlink(u->state_file);
290 
291         if (temp_path)
292                 (void) unlink(temp_path);
293 
294         return log_error_errno(r, "Failed to save user data %s: %m", u->state_file);
295 }
296 
user_save(User * u)297 int user_save(User *u) {
298         assert(u);
299 
300         if (!u->started)
301                 return 0;
302 
303         return user_save_internal(u);
304 }
305 
user_load(User * u)306 int user_load(User *u) {
307         _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *stopping = NULL, *last_session_timestamp = NULL;
308         int r;
309 
310         assert(u);
311 
312         r = parse_env_file(NULL, u->state_file,
313                            "SERVICE_JOB",            &u->service_job,
314                            "STOPPING",               &stopping,
315                            "REALTIME",               &realtime,
316                            "MONOTONIC",              &monotonic,
317                            "LAST_SESSION_TIMESTAMP", &last_session_timestamp);
318         if (r == -ENOENT)
319                 return 0;
320         if (r < 0)
321                 return log_error_errno(r, "Failed to read %s: %m", u->state_file);
322 
323         if (stopping) {
324                 r = parse_boolean(stopping);
325                 if (r < 0)
326                         log_debug_errno(r, "Failed to parse 'STOPPING' boolean: %s", stopping);
327                 else
328                         u->stopping = r;
329         }
330 
331         if (realtime)
332                 (void) deserialize_usec(realtime, &u->timestamp.realtime);
333         if (monotonic)
334                 (void) deserialize_usec(monotonic, &u->timestamp.monotonic);
335         if (last_session_timestamp)
336                 (void) deserialize_usec(last_session_timestamp, &u->last_session_timestamp);
337 
338         return 0;
339 }
340 
user_start_service(User * u)341 static void user_start_service(User *u) {
342         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
343         int r;
344 
345         assert(u);
346 
347         /* Start the service containing the "systemd --user" instance (user@.service). Note that we don't explicitly
348          * start the per-user slice or the systemd-runtime-dir@.service instance, as those are pulled in both by
349          * user@.service and the session scopes as dependencies. */
350 
351         u->service_job = mfree(u->service_job);
352 
353         r = manager_start_unit(u->manager, u->service, &error, &u->service_job);
354         if (r < 0)
355                 log_full_errno(sd_bus_error_has_name(&error, BUS_ERROR_UNIT_MASKED) ? LOG_DEBUG : LOG_WARNING, r,
356                                "Failed to start user service '%s', ignoring: %s", u->service, bus_error_message(&error, r));
357 }
358 
update_slice_callback(sd_bus_message * m,void * userdata,sd_bus_error * ret_error)359 static int update_slice_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
360         _cleanup_(user_record_unrefp) UserRecord *ur = userdata;
361         const sd_bus_error *e;
362         int r;
363 
364         assert(m);
365         assert(ur);
366 
367         e = sd_bus_message_get_error(m);
368         if (e) {
369                 r = sd_bus_error_get_errno(e);
370                 log_warning_errno(r,
371                                   "Failed to update slice of %s, ignoring: %s",
372                                   ur->user_name,
373                                   bus_error_message(e, r));
374 
375                 return 0;
376         }
377 
378         log_debug("Successfully set slice parameters of %s.", ur->user_name);
379         return 0;
380 }
381 
user_update_slice(User * u)382 static int user_update_slice(User *u) {
383         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
384         int r;
385 
386         assert(u);
387 
388         if (u->user_record->tasks_max == UINT64_MAX &&
389             u->user_record->memory_high == UINT64_MAX &&
390             u->user_record->memory_max == UINT64_MAX &&
391             u->user_record->cpu_weight == UINT64_MAX &&
392             u->user_record->io_weight == UINT64_MAX)
393                 return 0;
394 
395         r = sd_bus_message_new_method_call(
396                         u->manager->bus,
397                         &m,
398                         "org.freedesktop.systemd1",
399                         "/org/freedesktop/systemd1",
400                         "org.freedesktop.systemd1.Manager",
401                         "SetUnitProperties");
402         if (r < 0)
403                 return bus_log_create_error(r);
404 
405         r = sd_bus_message_append(m, "sb", u->slice, true);
406         if (r < 0)
407                 return bus_log_create_error(r);
408 
409         r = sd_bus_message_open_container(m, 'a', "(sv)");
410         if (r < 0)
411                 return bus_log_create_error(r);
412 
413         const struct {
414                 const char *name;
415                 uint64_t value;
416         } settings[] = {
417                 { "TasksMax",   u->user_record->tasks_max   },
418                 { "MemoryMax",  u->user_record->memory_max  },
419                 { "MemoryHigh", u->user_record->memory_high },
420                 { "CPUWeight",  u->user_record->cpu_weight  },
421                 { "IOWeight",   u->user_record->io_weight   },
422         };
423 
424         for (size_t i = 0; i < ELEMENTSOF(settings); i++)
425                 if (settings[i].value != UINT64_MAX) {
426                         r = sd_bus_message_append(m, "(sv)", settings[i].name, "t", settings[i].value);
427                         if (r < 0)
428                                 return bus_log_create_error(r);
429                 }
430 
431         r = sd_bus_message_close_container(m);
432         if (r < 0)
433                 return bus_log_create_error(r);
434 
435         r = sd_bus_call_async(u->manager->bus, NULL, m, update_slice_callback, u->user_record, 0);
436         if (r < 0)
437                 return log_error_errno(r, "Failed to change user slice properties: %m");
438 
439         /* Ref the user record pointer, so that the slot keeps it pinned */
440         user_record_ref(u->user_record);
441 
442         return 0;
443 }
444 
user_start(User * u)445 int user_start(User *u) {
446         assert(u);
447 
448         if (u->started && !u->stopping)
449                 return 0;
450 
451         /* If u->stopping is set, the user is marked for removal and service stop-jobs are queued. We have to clear
452          * that flag before queueing the start-jobs again. If they succeed, the user object can be re-used just fine
453          * (pid1 takes care of job-ordering and proper restart), but if they fail, we want to force another user_stop()
454          * so possibly pending units are stopped. */
455         u->stopping = false;
456 
457         if (!u->started)
458                 log_debug("Starting services for new user %s.", u->user_record->user_name);
459 
460         /* Save the user data so far, because pam_systemd will read the XDG_RUNTIME_DIR out of it while starting up
461          * systemd --user.  We need to do user_save_internal() because we have not "officially" started yet. */
462         user_save_internal(u);
463 
464         /* Set slice parameters */
465         (void) user_update_slice(u);
466 
467         /* Start user@UID.service */
468         user_start_service(u);
469 
470         if (!u->started) {
471                 if (!dual_timestamp_is_set(&u->timestamp))
472                         dual_timestamp_get(&u->timestamp);
473                 user_send_signal(u, true);
474                 u->started = true;
475         }
476 
477         /* Save new user data */
478         user_save(u);
479 
480         return 0;
481 }
482 
user_stop_service(User * u,bool force)483 static void user_stop_service(User *u, bool force) {
484         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
485         int r;
486 
487         assert(u);
488         assert(u->service);
489 
490         /* The reverse of user_start_service(). Note that we only stop user@UID.service here, and let StopWhenUnneeded=
491          * deal with the slice and the user-runtime-dir@.service instance. */
492 
493         u->service_job = mfree(u->service_job);
494 
495         r = manager_stop_unit(u->manager, u->service, force ? "replace" : "fail", &error, &u->service_job);
496         if (r < 0)
497                 log_warning_errno(r, "Failed to stop user service '%s', ignoring: %s", u->service, bus_error_message(&error, r));
498 }
499 
user_stop(User * u,bool force)500 int user_stop(User *u, bool force) {
501         int r = 0;
502 
503         assert(u);
504 
505         /* This is called whenever we begin with tearing down a user record. It's called in two cases: explicit API
506          * request to do so via the bus (in which case 'force' is true) and automatically due to GC, if there's no
507          * session left pinning it (in which case 'force' is false). Note that this just initiates tearing down of the
508          * user, the User object will remain in memory until user_finalize() is called, see below. */
509 
510         if (!u->started)
511                 return 0;
512 
513         if (u->stopping) { /* Stop jobs have already been queued */
514                 user_save(u);
515                 return 0;
516         }
517 
518         LIST_FOREACH(sessions_by_user, s, u->sessions) {
519                 int k;
520 
521                 k = session_stop(s, force);
522                 if (k < 0)
523                         r = k;
524         }
525 
526         user_stop_service(u, force);
527 
528         u->stopping = true;
529 
530         user_save(u);
531 
532         return r;
533 }
534 
user_finalize(User * u)535 int user_finalize(User *u) {
536         int r = 0, k;
537 
538         assert(u);
539 
540         /* Called when the user is really ready to be freed, i.e. when all unit stop jobs and suchlike for it are
541          * done. This is called as a result of an earlier user_done() when all jobs are completed. */
542 
543         if (u->started)
544                 log_debug("User %s logged out.", u->user_record->user_name);
545 
546         LIST_FOREACH(sessions_by_user, s, u->sessions) {
547                 k = session_finalize(s);
548                 if (k < 0)
549                         r = k;
550         }
551 
552         /* Clean SysV + POSIX IPC objects, but only if this is not a system user. Background: in many setups cronjobs
553          * are run in full PAM and thus logind sessions, even if the code run doesn't belong to actual users but to
554          * system components. Since enable RemoveIPC= globally for all users, we need to be a bit careful with such
555          * cases, as we shouldn't accidentally remove a system service's IPC objects while it is running, just because
556          * a cronjob running as the same user just finished. Hence: exclude system users generally from IPC clean-up,
557          * and do it only for normal users. */
558         if (u->manager->remove_ipc && !uid_is_system(u->user_record->uid)) {
559                 k = clean_ipc_by_uid(u->user_record->uid);
560                 if (k < 0)
561                         r = k;
562         }
563 
564         (void) unlink(u->state_file);
565         user_add_to_gc_queue(u);
566 
567         if (u->started) {
568                 user_send_signal(u, false);
569                 u->started = false;
570         }
571 
572         return r;
573 }
574 
user_get_idle_hint(User * u,dual_timestamp * t)575 int user_get_idle_hint(User *u, dual_timestamp *t) {
576         bool idle_hint = true;
577         dual_timestamp ts = DUAL_TIMESTAMP_NULL;
578 
579         assert(u);
580 
581         LIST_FOREACH(sessions_by_user, s, u->sessions) {
582                 dual_timestamp k;
583                 int ih;
584 
585                 ih = session_get_idle_hint(s, &k);
586                 if (ih < 0)
587                         return ih;
588 
589                 if (!ih) {
590                         if (!idle_hint) {
591                                 if (k.monotonic < ts.monotonic)
592                                         ts = k;
593                         } else {
594                                 idle_hint = false;
595                                 ts = k;
596                         }
597                 } else if (idle_hint) {
598 
599                         if (k.monotonic > ts.monotonic)
600                                 ts = k;
601                 }
602         }
603 
604         if (t)
605                 *t = ts;
606 
607         return idle_hint;
608 }
609 
user_check_linger_file(User * u)610 int user_check_linger_file(User *u) {
611         _cleanup_free_ char *cc = NULL;
612         char *p = NULL;
613 
614         cc = cescape(u->user_record->user_name);
615         if (!cc)
616                 return -ENOMEM;
617 
618         p = strjoina("/var/lib/systemd/linger/", cc);
619         if (access(p, F_OK) < 0) {
620                 if (errno != ENOENT)
621                         return -errno;
622 
623                 return false;
624         }
625 
626         return true;
627 }
628 
user_unit_active(User * u)629 static bool user_unit_active(User *u) {
630         int r;
631 
632         assert(u->service);
633         assert(u->runtime_dir_service);
634         assert(u->slice);
635 
636         FOREACH_STRING(i, u->service, u->runtime_dir_service, u->slice) {
637                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
638 
639                 r = manager_unit_is_active(u->manager, i, &error);
640                 if (r < 0)
641                         log_debug_errno(r, "Failed to determine whether unit '%s' is active, ignoring: %s", i, bus_error_message(&error, r));
642                 if (r != 0)
643                         return true;
644         }
645 
646         return false;
647 }
648 
user_get_stop_delay(User * u)649 static usec_t user_get_stop_delay(User *u) {
650         assert(u);
651 
652         if (u->user_record->stop_delay_usec != UINT64_MAX)
653                 return u->user_record->stop_delay_usec;
654 
655         if (user_record_removable(u->user_record) > 0)
656                 return 0; /* For removable users lower the stop delay to zero */
657 
658         return u->manager->user_stop_delay;
659 }
660 
user_may_gc(User * u,bool drop_not_started)661 bool user_may_gc(User *u, bool drop_not_started) {
662         int r;
663 
664         assert(u);
665 
666         if (drop_not_started && !u->started)
667                 return true;
668 
669         if (u->sessions)
670                 return false;
671 
672         if (u->last_session_timestamp != USEC_INFINITY) {
673                 usec_t user_stop_delay;
674 
675                 /* All sessions have been closed. Let's see if we shall leave the user record around for a bit */
676 
677                 user_stop_delay = user_get_stop_delay(u);
678 
679                 if (user_stop_delay == USEC_INFINITY)
680                         return false; /* Leave it around forever! */
681                 if (user_stop_delay > 0 &&
682                     now(CLOCK_MONOTONIC) < usec_add(u->last_session_timestamp, user_stop_delay))
683                         return false; /* Leave it around for a bit longer. */
684         }
685 
686         /* Is this a user that shall stay around forever ("linger")? Before we say "no" to GC'ing for lingering users, let's check
687          * if any of the three units that we maintain for this user is still around. If none of them is,
688          * there's no need to keep this user around even if lingering is enabled. */
689         if (user_check_linger_file(u) > 0 && user_unit_active(u))
690                 return false;
691 
692         /* Check if our job is still pending */
693         if (u->service_job) {
694                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
695 
696                 r = manager_job_is_active(u->manager, u->service_job, &error);
697                 if (r < 0)
698                         log_debug_errno(r, "Failed to determine whether job '%s' is pending, ignoring: %s", u->service_job, bus_error_message(&error, r));
699                 if (r != 0)
700                         return false;
701         }
702 
703         /* Note that we don't care if the three units we manage for each user object are up or not, as we are managing
704          * their state rather than tracking it. */
705 
706         return true;
707 }
708 
user_add_to_gc_queue(User * u)709 void user_add_to_gc_queue(User *u) {
710         assert(u);
711 
712         if (u->in_gc_queue)
713                 return;
714 
715         LIST_PREPEND(gc_queue, u->manager->user_gc_queue, u);
716         u->in_gc_queue = true;
717 }
718 
user_get_state(User * u)719 UserState user_get_state(User *u) {
720         assert(u);
721 
722         if (u->stopping)
723                 return USER_CLOSING;
724 
725         if (!u->started || u->service_job)
726                 return USER_OPENING;
727 
728         if (u->sessions) {
729                 bool all_closing = true;
730 
731                 LIST_FOREACH(sessions_by_user, i, u->sessions) {
732                         SessionState state;
733 
734                         state = session_get_state(i);
735                         if (state == SESSION_ACTIVE)
736                                 return USER_ACTIVE;
737                         if (state != SESSION_CLOSING)
738                                 all_closing = false;
739                 }
740 
741                 return all_closing ? USER_CLOSING : USER_ONLINE;
742         }
743 
744         if (user_check_linger_file(u) > 0 && user_unit_active(u))
745                 return USER_LINGERING;
746 
747         return USER_CLOSING;
748 }
749 
user_kill(User * u,int signo)750 int user_kill(User *u, int signo) {
751         assert(u);
752 
753         return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
754 }
755 
elect_display_filter(Session * s)756 static bool elect_display_filter(Session *s) {
757         /* Return true if the session is a candidate for the user’s ‘primary session’ or ‘display’. */
758         assert(s);
759 
760         return IN_SET(s->class, SESSION_USER, SESSION_GREETER) && s->started && !s->stopping;
761 }
762 
elect_display_compare(Session * s1,Session * s2)763 static int elect_display_compare(Session *s1, Session *s2) {
764         /* Indexed by SessionType. Lower numbers mean more preferred. */
765         static const int type_ranks[_SESSION_TYPE_MAX] = {
766                 [SESSION_UNSPECIFIED] = 0,
767                 [SESSION_TTY] = -2,
768                 [SESSION_X11] = -3,
769                 [SESSION_WAYLAND] = -3,
770                 [SESSION_MIR] = -3,
771                 [SESSION_WEB] = -1,
772         };
773 
774         /* Calculate the partial order relationship between s1 and s2,
775          * returning < 0 if s1 is preferred as the user’s ‘primary session’,
776          * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2
777          * is preferred.
778          *
779          * s1 or s2 may be NULL. */
780         if (!s1 && !s2)
781                 return 0;
782 
783         if ((s1 == NULL) != (s2 == NULL))
784                 return (s1 == NULL) - (s2 == NULL);
785 
786         if (s1->stopping != s2->stopping)
787                 return s1->stopping - s2->stopping;
788 
789         if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER))
790                 return (s1->class != SESSION_USER) - (s2->class != SESSION_USER);
791 
792         if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID))
793                 return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID);
794 
795         if (s1->type != s2->type)
796                 return type_ranks[s1->type] - type_ranks[s2->type];
797 
798         return 0;
799 }
800 
user_elect_display(User * u)801 void user_elect_display(User *u) {
802         assert(u);
803 
804         /* This elects a primary session for each user, which we call the "display". We try to keep the assignment
805          * stable, but we "upgrade" to better choices. */
806         log_debug("Electing new display for user %s", u->user_record->user_name);
807 
808         LIST_FOREACH(sessions_by_user, s, u->sessions) {
809                 if (!elect_display_filter(s)) {
810                         log_debug("Ignoring session %s", s->id);
811                         continue;
812                 }
813 
814                 if (elect_display_compare(s, u->display) < 0) {
815                         log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-");
816                         u->display = s;
817                 }
818         }
819 }
820 
user_stop_timeout_callback(sd_event_source * es,uint64_t usec,void * userdata)821 static int user_stop_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
822         User *u = userdata;
823 
824         assert(u);
825         user_add_to_gc_queue(u);
826 
827         return 0;
828 }
829 
user_update_last_session_timer(User * u)830 void user_update_last_session_timer(User *u) {
831         usec_t user_stop_delay;
832         int r;
833 
834         assert(u);
835 
836         if (u->sessions) {
837                 /* There are sessions, turn off the timer */
838                 u->last_session_timestamp = USEC_INFINITY;
839                 u->timer_event_source = sd_event_source_unref(u->timer_event_source);
840                 return;
841         }
842 
843         if (u->last_session_timestamp != USEC_INFINITY)
844                 return; /* Timer already started */
845 
846         u->last_session_timestamp = now(CLOCK_MONOTONIC);
847 
848         assert(!u->timer_event_source);
849 
850         user_stop_delay = user_get_stop_delay(u);
851         if (!timestamp_is_set(user_stop_delay))
852                 return;
853 
854         if (sd_event_get_state(u->manager->event) == SD_EVENT_FINISHED) {
855                 log_debug("Not allocating user stop timeout, since we are already exiting.");
856                 return;
857         }
858 
859         r = sd_event_add_time(u->manager->event,
860                               &u->timer_event_source,
861                               CLOCK_MONOTONIC,
862                               usec_add(u->last_session_timestamp, user_stop_delay), 0,
863                               user_stop_timeout_callback, u);
864         if (r < 0)
865                 log_warning_errno(r, "Failed to enqueue user stop event source, ignoring: %m");
866 
867         if (DEBUG_LOGGING)
868                 log_debug("Last session of user '%s' logged out, terminating user context in %s.",
869                           u->user_record->user_name,
870                           FORMAT_TIMESPAN(user_stop_delay, USEC_PER_MSEC));
871 }
872 
873 static const char* const user_state_table[_USER_STATE_MAX] = {
874         [USER_OFFLINE] = "offline",
875         [USER_OPENING] = "opening",
876         [USER_LINGERING] = "lingering",
877         [USER_ONLINE] = "online",
878         [USER_ACTIVE] = "active",
879         [USER_CLOSING] = "closing"
880 };
881 
882 DEFINE_STRING_TABLE_LOOKUP(user_state, UserState);
883 
config_parse_tmpfs_size(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)884 int config_parse_tmpfs_size(
885                 const char* unit,
886                 const char *filename,
887                 unsigned line,
888                 const char *section,
889                 unsigned section_line,
890                 const char *lvalue,
891                 int ltype,
892                 const char *rvalue,
893                 void *data,
894                 void *userdata) {
895 
896         uint64_t *sz = data;
897         int r;
898 
899         assert(filename);
900         assert(lvalue);
901         assert(rvalue);
902         assert(data);
903 
904         /* First, try to parse as percentage */
905         r = parse_permyriad(rvalue);
906         if (r > 0)
907                 *sz = physical_memory_scale(r, 10000U);
908         else {
909                 uint64_t k;
910 
911                 /* If the passed argument was not a percentage, or out of range, parse as byte size */
912 
913                 r = parse_size(rvalue, 1024, &k);
914                 if (r >= 0 && (k <= 0 || (uint64_t) (size_t) k != k))
915                         r = -ERANGE;
916                 if (r < 0) {
917                         log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse size value '%s', ignoring: %m", rvalue);
918                         return 0;
919                 }
920 
921                 *sz = PAGE_ALIGN((size_t) k);
922         }
923 
924         return 0;
925 }
926 
config_parse_compat_user_tasks_max(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)927 int config_parse_compat_user_tasks_max(
928                 const char *unit,
929                 const char *filename,
930                 unsigned line,
931                 const char *section,
932                 unsigned section_line,
933                 const char *lvalue,
934                 int ltype,
935                 const char *rvalue,
936                 void *data,
937                 void *userdata) {
938 
939         assert(filename);
940         assert(lvalue);
941         assert(rvalue);
942 
943         log_syntax(unit, LOG_NOTICE, filename, line, 0,
944                    "Support for option %s= has been removed.",
945                    lvalue);
946         log_info("Hint: try creating /etc/systemd/system/user-.slice.d/50-limits.conf with:\n"
947                  "        [Slice]\n"
948                  "        TasksMax=%s",
949                  rvalue);
950         return 0;
951 }
952