File: | build-scan/../src/login/logind-user.c |
Warning: | line 53, column 25 Potential leak of memory pointed to by 'u' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
2 | ||||
3 | #include <errno(*__errno_location ()).h> | |||
4 | #include <string.h> | |||
5 | #include <unistd.h> | |||
6 | #include <stdio_ext.h> | |||
7 | ||||
8 | #include "alloc-util.h" | |||
9 | #include "bus-common-errors.h" | |||
10 | #include "bus-error.h" | |||
11 | #include "bus-util.h" | |||
12 | #include "cgroup-util.h" | |||
13 | #include "clean-ipc.h" | |||
14 | #include "escape.h" | |||
15 | #include "fd-util.h" | |||
16 | #include "fileio.h" | |||
17 | #include "format-util.h" | |||
18 | #include "fs-util.h" | |||
19 | #include "hashmap.h" | |||
20 | #include "label.h" | |||
21 | #include "logind-user.h" | |||
22 | #include "mkdir.h" | |||
23 | #include "parse-util.h" | |||
24 | #include "path-util.h" | |||
25 | #include "rm-rf.h" | |||
26 | #include "special.h" | |||
27 | #include "stdio-util.h" | |||
28 | #include "string-table.h" | |||
29 | #include "unit-name.h" | |||
30 | #include "user-util.h" | |||
31 | #include "util.h" | |||
32 | ||||
33 | int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) { | |||
34 | _cleanup_(user_freep)__attribute__((cleanup(user_freep))) User *u = NULL((void*)0); | |||
35 | char lu[DECIMAL_STR_MAX(uid_t)(2+(sizeof(uid_t) <= 1 ? 3 : sizeof(uid_t) <= 2 ? 5 : sizeof (uid_t) <= 4 ? 10 : sizeof(uid_t) <= 8 ? 20 : sizeof(int [-2*(sizeof(uid_t) > 8)]))) + 1]; | |||
36 | int r; | |||
37 | ||||
38 | assert(out)do { if ((__builtin_expect(!!(!(out)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("out"), "../src/login/logind-user.c", 38 , __PRETTY_FUNCTION__); } while (0); | |||
| ||||
39 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/login/logind-user.c", 39, __PRETTY_FUNCTION__ ); } while (0); | |||
40 | assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("name"), "../src/login/logind-user.c", 40 , __PRETTY_FUNCTION__); } while (0); | |||
41 | ||||
42 | u = new0(User, 1)((User*) calloc((1), sizeof(User))); | |||
43 | if (!u) | |||
44 | return -ENOMEM12; | |||
45 | ||||
46 | u->manager = m; | |||
47 | u->uid = uid; | |||
48 | u->gid = gid; | |||
49 | xsprintf(lu, UID_FMT, uid)do { if ((__builtin_expect(!!(!(((size_t) snprintf(lu, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (lu), typeof(&*(lu))), sizeof(lu)/sizeof((lu)[0]), ((void )0))), "%" "u", uid) < (__extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(lu), typeof(&*(lu) )), sizeof(lu)/sizeof((lu)[0]), ((void)0))))))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("xsprintf: " "lu" "[] must be big enough" ), "../src/login/logind-user.c", 49, __PRETTY_FUNCTION__); } while (0); | |||
50 | ||||
51 | u->name = strdup(name); | |||
52 | if (!u->name) | |||
53 | return -ENOMEM12; | |||
| ||||
54 | ||||
55 | if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT"%" "u", uid) < 0) | |||
56 | return -ENOMEM12; | |||
57 | ||||
58 | if (asprintf(&u->runtime_path, "/run/user/"UID_FMT"%" "u", uid) < 0) | |||
59 | return -ENOMEM12; | |||
60 | ||||
61 | r = slice_build_subslice(SPECIAL_USER_SLICE"user.slice", lu, &u->slice); | |||
62 | if (r < 0) | |||
63 | return r; | |||
64 | ||||
65 | r = unit_name_build("user", lu, ".service", &u->service); | |||
66 | if (r < 0) | |||
67 | return r; | |||
68 | ||||
69 | r = hashmap_put(m->users, UID_TO_PTR(uid)((void*) (((uintptr_t) (uid))+1)), u); | |||
70 | if (r < 0) | |||
71 | return r; | |||
72 | ||||
73 | r = hashmap_put(m->user_units, u->slice, u); | |||
74 | if (r < 0) | |||
75 | return r; | |||
76 | ||||
77 | r = hashmap_put(m->user_units, u->service, u); | |||
78 | if (r < 0) | |||
79 | return r; | |||
80 | ||||
81 | *out = TAKE_PTR(u)({ typeof(u) _ptr_ = (u); (u) = ((void*)0); _ptr_; }); | |||
82 | ||||
83 | return 0; | |||
84 | } | |||
85 | ||||
86 | User *user_free(User *u) { | |||
87 | if (!u) | |||
88 | return NULL((void*)0); | |||
89 | ||||
90 | if (u->in_gc_queue) | |||
91 | LIST_REMOVE(gc_queue, u->manager->user_gc_queue, u)do { typeof(*(u->manager->user_gc_queue)) **_head = & (u->manager->user_gc_queue), *_item = (u); do { if ((__builtin_expect (!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/login/logind-user.c", 91, __PRETTY_FUNCTION__ ); } while (0); if (_item->gc_queue_next) _item->gc_queue_next ->gc_queue_prev = _item->gc_queue_prev; if (_item->gc_queue_prev ) _item->gc_queue_prev->gc_queue_next = _item->gc_queue_next ; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0) )) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item" ), "../src/login/logind-user.c", 91, __PRETTY_FUNCTION__); } while (0); *_head = _item->gc_queue_next; } _item->gc_queue_next = _item->gc_queue_prev = ((void*)0); } while (0); | |||
92 | ||||
93 | while (u->sessions) | |||
94 | session_free(u->sessions); | |||
95 | ||||
96 | if (u->service) | |||
97 | hashmap_remove_value(u->manager->user_units, u->service, u); | |||
98 | ||||
99 | if (u->slice) | |||
100 | hashmap_remove_value(u->manager->user_units, u->slice, u); | |||
101 | ||||
102 | hashmap_remove_value(u->manager->users, UID_TO_PTR(u->uid)((void*) (((uintptr_t) (u->uid))+1)), u); | |||
103 | ||||
104 | u->slice_job = mfree(u->slice_job); | |||
105 | u->service_job = mfree(u->service_job); | |||
106 | ||||
107 | u->service = mfree(u->service); | |||
108 | u->slice = mfree(u->slice); | |||
109 | u->runtime_path = mfree(u->runtime_path); | |||
110 | u->state_file = mfree(u->state_file); | |||
111 | u->name = mfree(u->name); | |||
112 | ||||
113 | return mfree(u); | |||
114 | } | |||
115 | ||||
116 | static int user_save_internal(User *u) { | |||
117 | _cleanup_free___attribute__((cleanup(freep))) char *temp_path = NULL((void*)0); | |||
118 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0); | |||
119 | int r; | |||
120 | ||||
121 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 121, __PRETTY_FUNCTION__); } while (0); | |||
122 | assert(u->state_file)do { if ((__builtin_expect(!!(!(u->state_file)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u->state_file"), "../src/login/logind-user.c" , 122, __PRETTY_FUNCTION__); } while (0); | |||
123 | ||||
124 | r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0, MKDIR_WARN_MODE); | |||
125 | if (r < 0) | |||
126 | goto fail; | |||
127 | ||||
128 | r = fopen_temporary(u->state_file, &f, &temp_path); | |||
129 | if (r < 0) | |||
130 | goto fail; | |||
131 | ||||
132 | (void) __fsetlocking(f, FSETLOCKING_BYCALLERFSETLOCKING_BYCALLER); | |||
133 | (void) fchmod(fileno(f), 0644); | |||
134 | ||||
135 | fprintf(f, | |||
136 | "# This is private data. Do not parse.\n" | |||
137 | "NAME=%s\n" | |||
138 | "STATE=%s\n", | |||
139 | u->name, | |||
140 | user_state_to_string(user_get_state(u))); | |||
141 | ||||
142 | /* LEGACY: no-one reads RUNTIME= anymore, drop it at some point */ | |||
143 | if (u->runtime_path) | |||
144 | fprintf(f, "RUNTIME=%s\n", u->runtime_path); | |||
145 | ||||
146 | if (u->service_job) | |||
147 | fprintf(f, "SERVICE_JOB=%s\n", u->service_job); | |||
148 | ||||
149 | if (u->slice_job) | |||
150 | fprintf(f, "SLICE_JOB=%s\n", u->slice_job); | |||
151 | ||||
152 | if (u->display) | |||
153 | fprintf(f, "DISPLAY=%s\n", u->display->id); | |||
154 | ||||
155 | if (dual_timestamp_is_set(&u->timestamp)) | |||
156 | fprintf(f, | |||
157 | "REALTIME="USEC_FMT"%" "l" "u""\n" | |||
158 | "MONOTONIC="USEC_FMT"%" "l" "u""\n", | |||
159 | u->timestamp.realtime, | |||
160 | u->timestamp.monotonic); | |||
161 | ||||
162 | if (u->sessions) { | |||
163 | Session *i; | |||
164 | bool_Bool first; | |||
165 | ||||
166 | fputs("SESSIONS=", f); | |||
167 | first = true1; | |||
168 | LIST_FOREACH(sessions_by_user, i, u->sessions)for ((i) = (u->sessions); (i); (i) = (i)->sessions_by_user_next ) { | |||
169 | if (first) | |||
170 | first = false0; | |||
171 | else | |||
172 | fputc(' ', f); | |||
173 | ||||
174 | fputs(i->id, f); | |||
175 | } | |||
176 | ||||
177 | fputs("\nSEATS=", f); | |||
178 | first = true1; | |||
179 | LIST_FOREACH(sessions_by_user, i, u->sessions)for ((i) = (u->sessions); (i); (i) = (i)->sessions_by_user_next ) { | |||
180 | if (!i->seat) | |||
181 | continue; | |||
182 | ||||
183 | if (first) | |||
184 | first = false0; | |||
185 | else | |||
186 | fputc(' ', f); | |||
187 | ||||
188 | fputs(i->seat->id, f); | |||
189 | } | |||
190 | ||||
191 | fputs("\nACTIVE_SESSIONS=", f); | |||
192 | first = true1; | |||
193 | LIST_FOREACH(sessions_by_user, i, u->sessions)for ((i) = (u->sessions); (i); (i) = (i)->sessions_by_user_next ) { | |||
194 | if (!session_is_active(i)) | |||
195 | continue; | |||
196 | ||||
197 | if (first) | |||
198 | first = false0; | |||
199 | else | |||
200 | fputc(' ', f); | |||
201 | ||||
202 | fputs(i->id, f); | |||
203 | } | |||
204 | ||||
205 | fputs("\nONLINE_SESSIONS=", f); | |||
206 | first = true1; | |||
207 | LIST_FOREACH(sessions_by_user, i, u->sessions)for ((i) = (u->sessions); (i); (i) = (i)->sessions_by_user_next ) { | |||
208 | if (session_get_state(i) == SESSION_CLOSING) | |||
209 | continue; | |||
210 | ||||
211 | if (first) | |||
212 | first = false0; | |||
213 | else | |||
214 | fputc(' ', f); | |||
215 | ||||
216 | fputs(i->id, f); | |||
217 | } | |||
218 | ||||
219 | fputs("\nACTIVE_SEATS=", f); | |||
220 | first = true1; | |||
221 | LIST_FOREACH(sessions_by_user, i, u->sessions)for ((i) = (u->sessions); (i); (i) = (i)->sessions_by_user_next ) { | |||
222 | if (!session_is_active(i) || !i->seat) | |||
223 | continue; | |||
224 | ||||
225 | if (first) | |||
226 | first = false0; | |||
227 | else | |||
228 | fputc(' ', f); | |||
229 | ||||
230 | fputs(i->seat->id, f); | |||
231 | } | |||
232 | ||||
233 | fputs("\nONLINE_SEATS=", f); | |||
234 | first = true1; | |||
235 | LIST_FOREACH(sessions_by_user, i, u->sessions)for ((i) = (u->sessions); (i); (i) = (i)->sessions_by_user_next ) { | |||
236 | if (session_get_state(i) == SESSION_CLOSING || !i->seat) | |||
237 | continue; | |||
238 | ||||
239 | if (first) | |||
240 | first = false0; | |||
241 | else | |||
242 | fputc(' ', f); | |||
243 | ||||
244 | fputs(i->seat->id, f); | |||
245 | } | |||
246 | fputc('\n', f); | |||
247 | } | |||
248 | ||||
249 | r = fflush_and_check(f); | |||
250 | if (r < 0) | |||
251 | goto fail; | |||
252 | ||||
253 | if (rename(temp_path, u->state_file) < 0) { | |||
254 | r = -errno(*__errno_location ()); | |||
255 | goto fail; | |||
256 | } | |||
257 | ||||
258 | return 0; | |||
259 | ||||
260 | fail: | |||
261 | (void) unlink(u->state_file); | |||
262 | ||||
263 | if (temp_path) | |||
264 | (void) unlink(temp_path); | |||
265 | ||||
266 | return log_error_errno(r, "Failed to save user data %s: %m", u->state_file)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/login/logind-user.c", 266, __func__, "Failed to save user data %s: %m" , u->state_file) : -abs(_e); }); | |||
267 | } | |||
268 | ||||
269 | int user_save(User *u) { | |||
270 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 270, __PRETTY_FUNCTION__); } while (0); | |||
271 | ||||
272 | if (!u->started) | |||
273 | return 0; | |||
274 | ||||
275 | return user_save_internal (u); | |||
276 | } | |||
277 | ||||
278 | int user_load(User *u) { | |||
279 | _cleanup_free___attribute__((cleanup(freep))) char *display = NULL((void*)0), *realtime = NULL((void*)0), *monotonic = NULL((void*)0); | |||
280 | Session *s = NULL((void*)0); | |||
281 | int r; | |||
282 | ||||
283 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 283, __PRETTY_FUNCTION__); } while (0); | |||
284 | ||||
285 | r = parse_env_file(NULL((void*)0), u->state_file, NEWLINE"\n\r", | |||
286 | "SERVICE_JOB", &u->service_job, | |||
287 | "SLICE_JOB", &u->slice_job, | |||
288 | "DISPLAY", &display, | |||
289 | "REALTIME", &realtime, | |||
290 | "MONOTONIC", &monotonic, | |||
291 | NULL((void*)0)); | |||
292 | if (r < 0) { | |||
293 | if (r == -ENOENT2) | |||
294 | return 0; | |||
295 | ||||
296 | return log_error_errno(r, "Failed to read %s: %m", u->state_file)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/login/logind-user.c", 296, __func__, "Failed to read %s: %m" , u->state_file) : -abs(_e); }); | |||
297 | } | |||
298 | ||||
299 | if (display) | |||
300 | s = hashmap_get(u->manager->sessions, display); | |||
301 | ||||
302 | if (s && s->display && display_is_local(s->display)) | |||
303 | u->display = s; | |||
304 | ||||
305 | if (realtime) | |||
306 | timestamp_deserialize(realtime, &u->timestamp.realtime); | |||
307 | if (monotonic) | |||
308 | timestamp_deserialize(monotonic, &u->timestamp.monotonic); | |||
309 | ||||
310 | return r; | |||
311 | } | |||
312 | ||||
313 | static int user_start_service(User *u) { | |||
314 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
315 | char *job; | |||
316 | int r; | |||
317 | ||||
318 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 318, __PRETTY_FUNCTION__); } while (0); | |||
319 | ||||
320 | u->service_job = mfree(u->service_job); | |||
321 | ||||
322 | r = manager_start_unit( | |||
323 | u->manager, | |||
324 | u->service, | |||
325 | &error, | |||
326 | &job); | |||
327 | if (r < 0) | |||
328 | /* we don't fail due to this, let's try to continue */ | |||
329 | log_full_errno(sd_bus_error_has_name(&error, BUS_ERROR_UNIT_MASKED) ? LOG_DEBUG : LOG_WARNING, r,({ int _level = ((sd_bus_error_has_name(&error, "org.freedesktop.systemd1.UnitMasked" ) ? 7 : 4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm (_realm) >= ((_level) & 0x07)) ? log_internal_realm((( _realm) << 10 | (_level)), _e, "../src/login/logind-user.c" , 330, __func__, "Failed to start user service '%s', ignoring: %s" , u->service, bus_error_message(&error, r)) : -abs(_e) ; }) | |||
330 | "Failed to start user service '%s', ignoring: %s", u->service, bus_error_message(&error, r))({ int _level = ((sd_bus_error_has_name(&error, "org.freedesktop.systemd1.UnitMasked" ) ? 7 : 4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm (_realm) >= ((_level) & 0x07)) ? log_internal_realm((( _realm) << 10 | (_level)), _e, "../src/login/logind-user.c" , 330, __func__, "Failed to start user service '%s', ignoring: %s" , u->service, bus_error_message(&error, r)) : -abs(_e) ; }); | |||
331 | else | |||
332 | u->service_job = job; | |||
333 | ||||
334 | return 0; | |||
335 | } | |||
336 | ||||
337 | int user_start(User *u) { | |||
338 | int r; | |||
339 | ||||
340 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 340, __PRETTY_FUNCTION__); } while (0); | |||
341 | ||||
342 | if (u->started && !u->stopping) | |||
343 | return 0; | |||
344 | ||||
345 | /* | |||
346 | * If u->stopping is set, the user is marked for removal and the slice | |||
347 | * and service stop-jobs are queued. We have to clear that flag before | |||
348 | * queing the start-jobs again. If they succeed, the user object can be | |||
349 | * re-used just fine (pid1 takes care of job-ordering and proper | |||
350 | * restart), but if they fail, we want to force another user_stop() so | |||
351 | * possibly pending units are stopped. | |||
352 | * Note that we don't clear u->started, as we have no clue what state | |||
353 | * the user is in on failure here. Hence, we pretend the user is | |||
354 | * running so it will be properly taken down by GC. However, we clearly | |||
355 | * return an error from user_start() in that case, so no further | |||
356 | * reference to the user is taken. | |||
357 | */ | |||
358 | u->stopping = false0; | |||
359 | ||||
360 | if (!u->started) | |||
361 | log_debug("Starting services for new user %s.", u->name)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/login/logind-user.c", 361, __func__, "Starting services for new user %s." , u->name) : -abs(_e); }); | |||
362 | ||||
363 | /* Save the user data so far, because pam_systemd will read the | |||
364 | * XDG_RUNTIME_DIR out of it while starting up systemd --user. | |||
365 | * We need to do user_save_internal() because we have not | |||
366 | * "officially" started yet. */ | |||
367 | user_save_internal(u); | |||
368 | ||||
369 | /* Spawn user systemd */ | |||
370 | r = user_start_service(u); | |||
371 | if (r < 0) | |||
372 | return r; | |||
373 | ||||
374 | if (!u->started) { | |||
375 | if (!dual_timestamp_is_set(&u->timestamp)) | |||
376 | dual_timestamp_get(&u->timestamp); | |||
377 | user_send_signal(u, true1); | |||
378 | u->started = true1; | |||
379 | } | |||
380 | ||||
381 | /* Save new user data */ | |||
382 | user_save(u); | |||
383 | ||||
384 | return 0; | |||
385 | } | |||
386 | ||||
387 | static int user_stop_slice(User *u) { | |||
388 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
389 | char *job; | |||
390 | int r; | |||
391 | ||||
392 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 392, __PRETTY_FUNCTION__); } while (0); | |||
393 | ||||
394 | r = manager_stop_unit(u->manager, u->slice, &error, &job); | |||
395 | if (r < 0) { | |||
396 | log_error("Failed to stop user slice: %s", bus_error_message(&error, r))({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/login/logind-user.c", 396, __func__, "Failed to stop user slice: %s" , bus_error_message(&error, r)) : -abs(_e); }); | |||
397 | return r; | |||
398 | } | |||
399 | ||||
400 | free(u->slice_job); | |||
401 | u->slice_job = job; | |||
402 | ||||
403 | return r; | |||
404 | } | |||
405 | ||||
406 | static int user_stop_service(User *u) { | |||
407 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
408 | char *job; | |||
409 | int r; | |||
410 | ||||
411 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 411, __PRETTY_FUNCTION__); } while (0); | |||
412 | ||||
413 | r = manager_stop_unit(u->manager, u->service, &error, &job); | |||
414 | if (r < 0) { | |||
415 | log_error("Failed to stop user service: %s", bus_error_message(&error, r))({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/login/logind-user.c", 415, __func__, "Failed to stop user service: %s" , bus_error_message(&error, r)) : -abs(_e); }); | |||
416 | return r; | |||
417 | } | |||
418 | ||||
419 | free_and_replace(u->service_job, job)({ free(u->service_job); (u->service_job) = (job); (job ) = ((void*)0); 0; }); | |||
420 | return r; | |||
421 | } | |||
422 | ||||
423 | int user_stop(User *u, bool_Bool force) { | |||
424 | Session *s; | |||
425 | int r = 0, k; | |||
426 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 426, __PRETTY_FUNCTION__); } while (0); | |||
427 | ||||
428 | /* Stop jobs have already been queued */ | |||
429 | if (u->stopping) { | |||
430 | user_save(u); | |||
431 | return r; | |||
432 | } | |||
433 | ||||
434 | LIST_FOREACH(sessions_by_user, s, u->sessions)for ((s) = (u->sessions); (s); (s) = (s)->sessions_by_user_next ) { | |||
435 | k = session_stop(s, force); | |||
436 | if (k < 0) | |||
437 | r = k; | |||
438 | } | |||
439 | ||||
440 | /* Kill systemd */ | |||
441 | k = user_stop_service(u); | |||
442 | if (k < 0) | |||
443 | r = k; | |||
444 | ||||
445 | /* Kill cgroup */ | |||
446 | k = user_stop_slice(u); | |||
447 | if (k < 0) | |||
448 | r = k; | |||
449 | ||||
450 | u->stopping = true1; | |||
451 | ||||
452 | user_save(u); | |||
453 | ||||
454 | return r; | |||
455 | } | |||
456 | ||||
457 | int user_finalize(User *u) { | |||
458 | Session *s; | |||
459 | int r = 0, k; | |||
460 | ||||
461 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 461, __PRETTY_FUNCTION__); } while (0); | |||
462 | ||||
463 | if (u->started) | |||
464 | log_debug("User %s logged out.", u->name)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/login/logind-user.c", 464, __func__, "User %s logged out." , u->name) : -abs(_e); }); | |||
465 | ||||
466 | LIST_FOREACH(sessions_by_user, s, u->sessions)for ((s) = (u->sessions); (s); (s) = (s)->sessions_by_user_next ) { | |||
467 | k = session_finalize(s); | |||
468 | if (k < 0) | |||
469 | r = k; | |||
470 | } | |||
471 | ||||
472 | /* Clean SysV + POSIX IPC objects, but only if this is not a system user. Background: in many setups cronjobs | |||
473 | * are run in full PAM and thus logind sessions, even if the code run doesn't belong to actual users but to | |||
474 | * system components. Since enable RemoveIPC= globally for all users, we need to be a bit careful with such | |||
475 | * cases, as we shouldn't accidentally remove a system service's IPC objects while it is running, just because | |||
476 | * a cronjob running as the same user just finished. Hence: exclude system users generally from IPC clean-up, | |||
477 | * and do it only for normal users. */ | |||
478 | if (u->manager->remove_ipc && !uid_is_system(u->uid)) { | |||
479 | k = clean_ipc_by_uid(u->uid); | |||
480 | if (k < 0) | |||
481 | r = k; | |||
482 | } | |||
483 | ||||
484 | unlink(u->state_file); | |||
485 | user_add_to_gc_queue(u); | |||
486 | ||||
487 | if (u->started) { | |||
488 | user_send_signal(u, false0); | |||
489 | u->started = false0; | |||
490 | } | |||
491 | ||||
492 | return r; | |||
493 | } | |||
494 | ||||
495 | int user_get_idle_hint(User *u, dual_timestamp *t) { | |||
496 | Session *s; | |||
497 | bool_Bool idle_hint = true1; | |||
498 | dual_timestamp ts = DUAL_TIMESTAMP_NULL((struct dual_timestamp) {}); | |||
499 | ||||
500 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 500, __PRETTY_FUNCTION__); } while (0); | |||
501 | ||||
502 | LIST_FOREACH(sessions_by_user, s, u->sessions)for ((s) = (u->sessions); (s); (s) = (s)->sessions_by_user_next ) { | |||
503 | dual_timestamp k; | |||
504 | int ih; | |||
505 | ||||
506 | ih = session_get_idle_hint(s, &k); | |||
507 | if (ih < 0) | |||
508 | return ih; | |||
509 | ||||
510 | if (!ih) { | |||
511 | if (!idle_hint) { | |||
512 | if (k.monotonic < ts.monotonic) | |||
513 | ts = k; | |||
514 | } else { | |||
515 | idle_hint = false0; | |||
516 | ts = k; | |||
517 | } | |||
518 | } else if (idle_hint) { | |||
519 | ||||
520 | if (k.monotonic > ts.monotonic) | |||
521 | ts = k; | |||
522 | } | |||
523 | } | |||
524 | ||||
525 | if (t) | |||
526 | *t = ts; | |||
527 | ||||
528 | return idle_hint; | |||
529 | } | |||
530 | ||||
531 | int user_check_linger_file(User *u) { | |||
532 | _cleanup_free___attribute__((cleanup(freep))) char *cc = NULL((void*)0); | |||
533 | char *p = NULL((void*)0); | |||
534 | ||||
535 | cc = cescape(u->name); | |||
536 | if (!cc) | |||
537 | return -ENOMEM12; | |||
538 | ||||
539 | p = strjoina("/var/lib/systemd/linger/", cc)({ const char *_appendees_[] = { "/var/lib/systemd/linger/", cc }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | |||
540 | ||||
541 | return access(p, F_OK0) >= 0; | |||
542 | } | |||
543 | ||||
544 | bool_Bool user_may_gc(User *u, bool_Bool drop_not_started) { | |||
545 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 545, __PRETTY_FUNCTION__); } while (0); | |||
546 | ||||
547 | if (drop_not_started && !u->started) | |||
548 | return true1; | |||
549 | ||||
550 | if (u->sessions) | |||
551 | return false0; | |||
552 | ||||
553 | if (user_check_linger_file(u) > 0) | |||
554 | return false0; | |||
555 | ||||
556 | if (u->slice_job && manager_job_is_active(u->manager, u->slice_job)) | |||
557 | return false0; | |||
558 | ||||
559 | if (u->service_job && manager_job_is_active(u->manager, u->service_job)) | |||
560 | return false0; | |||
561 | ||||
562 | return true1; | |||
563 | } | |||
564 | ||||
565 | void user_add_to_gc_queue(User *u) { | |||
566 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 566, __PRETTY_FUNCTION__); } while (0); | |||
567 | ||||
568 | if (u->in_gc_queue) | |||
569 | return; | |||
570 | ||||
571 | LIST_PREPEND(gc_queue, u->manager->user_gc_queue, u)do { typeof(*(u->manager->user_gc_queue)) **_head = & (u->manager->user_gc_queue), *_item = (u); do { if ((__builtin_expect (!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/login/logind-user.c", 571, __PRETTY_FUNCTION__ ); } while (0); if ((_item->gc_queue_next = *_head)) _item ->gc_queue_next->gc_queue_prev = _item; _item->gc_queue_prev = ((void*)0); *_head = _item; } while (0); | |||
572 | u->in_gc_queue = true1; | |||
573 | } | |||
574 | ||||
575 | UserState user_get_state(User *u) { | |||
576 | Session *i; | |||
577 | ||||
578 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 578, __PRETTY_FUNCTION__); } while (0); | |||
579 | ||||
580 | if (u->stopping) | |||
581 | return USER_CLOSING; | |||
582 | ||||
583 | if (!u->started || u->slice_job || u->service_job) | |||
584 | return USER_OPENING; | |||
585 | ||||
586 | if (u->sessions) { | |||
587 | bool_Bool all_closing = true1; | |||
588 | ||||
589 | LIST_FOREACH(sessions_by_user, i, u->sessions)for ((i) = (u->sessions); (i); (i) = (i)->sessions_by_user_next ) { | |||
590 | SessionState state; | |||
591 | ||||
592 | state = session_get_state(i); | |||
593 | if (state == SESSION_ACTIVE) | |||
594 | return USER_ACTIVE; | |||
595 | if (state != SESSION_CLOSING) | |||
596 | all_closing = false0; | |||
597 | } | |||
598 | ||||
599 | return all_closing ? USER_CLOSING : USER_ONLINE; | |||
600 | } | |||
601 | ||||
602 | if (user_check_linger_file(u) > 0) | |||
603 | return USER_LINGERING; | |||
604 | ||||
605 | return USER_CLOSING; | |||
606 | } | |||
607 | ||||
608 | int user_kill(User *u, int signo) { | |||
609 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 609, __PRETTY_FUNCTION__); } while (0); | |||
610 | ||||
611 | return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL((void*)0)); | |||
612 | } | |||
613 | ||||
614 | static bool_Bool elect_display_filter(Session *s) { | |||
615 | /* Return true if the session is a candidate for the user’s ‘primary | |||
616 | * session’ or ‘display’. */ | |||
617 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-user.c", 617, __PRETTY_FUNCTION__); } while (0); | |||
618 | ||||
619 | return (s->class == SESSION_USER && !s->stopping); | |||
620 | } | |||
621 | ||||
622 | static int elect_display_compare(Session *s1, Session *s2) { | |||
623 | /* Indexed by SessionType. Lower numbers mean more preferred. */ | |||
624 | const int type_ranks[_SESSION_TYPE_MAX] = { | |||
625 | [SESSION_UNSPECIFIED] = 0, | |||
626 | [SESSION_TTY] = -2, | |||
627 | [SESSION_X11] = -3, | |||
628 | [SESSION_WAYLAND] = -3, | |||
629 | [SESSION_MIR] = -3, | |||
630 | [SESSION_WEB] = -1, | |||
631 | }; | |||
632 | ||||
633 | /* Calculate the partial order relationship between s1 and s2, | |||
634 | * returning < 0 if s1 is preferred as the user’s ‘primary session’, | |||
635 | * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2 | |||
636 | * is preferred. | |||
637 | * | |||
638 | * s1 or s2 may be NULL. */ | |||
639 | if (!s1 && !s2) | |||
640 | return 0; | |||
641 | ||||
642 | if ((s1 == NULL((void*)0)) != (s2 == NULL((void*)0))) | |||
643 | return (s1 == NULL((void*)0)) - (s2 == NULL((void*)0)); | |||
644 | ||||
645 | if (s1->stopping != s2->stopping) | |||
646 | return s1->stopping - s2->stopping; | |||
647 | ||||
648 | if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER)) | |||
649 | return (s1->class != SESSION_USER) - (s2->class != SESSION_USER); | |||
650 | ||||
651 | if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID)) | |||
652 | return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID); | |||
653 | ||||
654 | if (s1->type != s2->type) | |||
655 | return type_ranks[s1->type] - type_ranks[s2->type]; | |||
656 | ||||
657 | return 0; | |||
658 | } | |||
659 | ||||
660 | void user_elect_display(User *u) { | |||
661 | Session *s; | |||
662 | ||||
663 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/login/logind-user.c", 663, __PRETTY_FUNCTION__); } while (0); | |||
664 | ||||
665 | /* This elects a primary session for each user, which we call | |||
666 | * the "display". We try to keep the assignment stable, but we | |||
667 | * "upgrade" to better choices. */ | |||
668 | log_debug("Electing new display for user %s", u->name)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/login/logind-user.c", 668, __func__, "Electing new display for user %s" , u->name) : -abs(_e); }); | |||
669 | ||||
670 | LIST_FOREACH(sessions_by_user, s, u->sessions)for ((s) = (u->sessions); (s); (s) = (s)->sessions_by_user_next ) { | |||
671 | if (!elect_display_filter(s)) { | |||
672 | log_debug("Ignoring session %s", s->id)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/login/logind-user.c", 672, __func__, "Ignoring session %s" , s->id) : -abs(_e); }); | |||
673 | continue; | |||
674 | } | |||
675 | ||||
676 | if (elect_display_compare(s, u->display) < 0) { | |||
677 | log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/login/logind-user.c", 677, __func__, "Choosing session %s in preference to %s" , s->id, u->display ? u->display->id : "-") : -abs (_e); }); | |||
678 | u->display = s; | |||
679 | } | |||
680 | } | |||
681 | } | |||
682 | ||||
683 | static const char* const user_state_table[_USER_STATE_MAX] = { | |||
684 | [USER_OFFLINE] = "offline", | |||
685 | [USER_OPENING] = "opening", | |||
686 | [USER_LINGERING] = "lingering", | |||
687 | [USER_ONLINE] = "online", | |||
688 | [USER_ACTIVE] = "active", | |||
689 | [USER_CLOSING] = "closing" | |||
690 | }; | |||
691 | ||||
692 | DEFINE_STRING_TABLE_LOOKUP(user_state, UserState)const char *user_state_to_string(UserState i) { if (i < 0 || i >= (UserState) __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(user_state_table), typeof(&*(user_state_table))), sizeof(user_state_table)/sizeof((user_state_table)[0]), ((void )0)))) return ((void*)0); return user_state_table[i]; } UserState user_state_from_string(const char *s) { return (UserState) string_table_lookup (user_state_table, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(user_state_table), typeof(&*(user_state_table))), sizeof(user_state_table)/sizeof((user_state_table)[0]), ((void )0))), s); }; | |||
693 | ||||
694 | int config_parse_tmpfs_size( | |||
695 | const char* unit, | |||
696 | const char *filename, | |||
697 | unsigned line, | |||
698 | const char *section, | |||
699 | unsigned section_line, | |||
700 | const char *lvalue, | |||
701 | int ltype, | |||
702 | const char *rvalue, | |||
703 | void *data, | |||
704 | void *userdata) { | |||
705 | ||||
706 | uint64_t *sz = data; | |||
707 | int r; | |||
708 | ||||
709 | assert(filename)do { if ((__builtin_expect(!!(!(filename)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("filename"), "../src/login/logind-user.c" , 709, __PRETTY_FUNCTION__); } while (0); | |||
710 | assert(lvalue)do { if ((__builtin_expect(!!(!(lvalue)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("lvalue"), "../src/login/logind-user.c", 710, __PRETTY_FUNCTION__); } while (0); | |||
711 | assert(rvalue)do { if ((__builtin_expect(!!(!(rvalue)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rvalue"), "../src/login/logind-user.c", 711, __PRETTY_FUNCTION__); } while (0); | |||
712 | assert(data)do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("data"), "../src/login/logind-user.c", 712 , __PRETTY_FUNCTION__); } while (0); | |||
713 | ||||
714 | /* First, try to parse as percentage */ | |||
715 | r = parse_percent(rvalue); | |||
716 | if (r > 0 && r < 100) | |||
717 | *sz = physical_memory_scale(r, 100U); | |||
718 | else { | |||
719 | uint64_t k; | |||
720 | ||||
721 | /* If the passed argument was not a percentage, or out of range, parse as byte size */ | |||
722 | ||||
723 | r = parse_size(rvalue, 1024, &k); | |||
724 | if (r < 0 || k <= 0 || (uint64_t) (size_t) k != k) { | |||
725 | log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue)({ int _level = (3), _e = (r); (log_get_max_level_realm(LOG_REALM_SYSTEMD ) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level , filename, line, _e, "../src/login/logind-user.c", 725, __func__ , "Failed to parse size value, ignoring: %s", rvalue) : -abs( _e); }); | |||
726 | return 0; | |||
727 | } | |||
728 | ||||
729 | *sz = PAGE_ALIGN((size_t) k)ALIGN_TO(((size_t) k), page_size()); | |||
730 | } | |||
731 | ||||
732 | return 0; | |||
733 | } | |||
734 | ||||
735 | int config_parse_compat_user_tasks_max( | |||
736 | const char *unit, | |||
737 | const char *filename, | |||
738 | unsigned line, | |||
739 | const char *section, | |||
740 | unsigned section_line, | |||
741 | const char *lvalue, | |||
742 | int ltype, | |||
743 | const char *rvalue, | |||
744 | void *data, | |||
745 | void *userdata) { | |||
746 | ||||
747 | assert(filename)do { if ((__builtin_expect(!!(!(filename)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("filename"), "../src/login/logind-user.c" , 747, __PRETTY_FUNCTION__); } while (0); | |||
748 | assert(lvalue)do { if ((__builtin_expect(!!(!(lvalue)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("lvalue"), "../src/login/logind-user.c", 748, __PRETTY_FUNCTION__); } while (0); | |||
749 | assert(rvalue)do { if ((__builtin_expect(!!(!(rvalue)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rvalue"), "../src/login/logind-user.c", 749, __PRETTY_FUNCTION__); } while (0); | |||
750 | assert(data)do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("data"), "../src/login/logind-user.c", 750 , __PRETTY_FUNCTION__); } while (0); | |||
751 | ||||
752 | log_syntax(unit, LOG_NOTICE, filename, line, 0,({ int _level = (5), _e = (0); (log_get_max_level_realm(LOG_REALM_SYSTEMD ) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level , filename, line, _e, "../src/login/logind-user.c", 754, __func__ , "Support for option %s= has been removed.", lvalue) : -abs( _e); }) | |||
753 | "Support for option %s= has been removed.",({ int _level = (5), _e = (0); (log_get_max_level_realm(LOG_REALM_SYSTEMD ) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level , filename, line, _e, "../src/login/logind-user.c", 754, __func__ , "Support for option %s= has been removed.", lvalue) : -abs( _e); }) | |||
754 | lvalue)({ int _level = (5), _e = (0); (log_get_max_level_realm(LOG_REALM_SYSTEMD ) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level , filename, line, _e, "../src/login/logind-user.c", 754, __func__ , "Support for option %s= has been removed.", lvalue) : -abs( _e); }); | |||
755 | log_info("Hint: try creating /etc/systemd/system/user-.slice/50-limits.conf with:\n"({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/login/logind-user.c", 758, __func__, "Hint: try creating /etc/systemd/system/user-.slice/50-limits.conf with:\n" " [Slice]\n" " TasksMax=%s", rvalue) : -abs(_e ); }) | |||
756 | " [Slice]\n"({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/login/logind-user.c", 758, __func__, "Hint: try creating /etc/systemd/system/user-.slice/50-limits.conf with:\n" " [Slice]\n" " TasksMax=%s", rvalue) : -abs(_e ); }) | |||
757 | " TasksMax=%s",({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/login/logind-user.c", 758, __func__, "Hint: try creating /etc/systemd/system/user-.slice/50-limits.conf with:\n" " [Slice]\n" " TasksMax=%s", rvalue) : -abs(_e ); }) | |||
758 | rvalue)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/login/logind-user.c", 758, __func__, "Hint: try creating /etc/systemd/system/user-.slice/50-limits.conf with:\n" " [Slice]\n" " TasksMax=%s", rvalue) : -abs(_e ); }); | |||
759 | return 0; | |||
760 | } |