1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <sys/eventfd.h>
8 #include "alloc-util.h"
9 #include "bus-common-errors.h"
10 #include "bus-get-properties.h"
11 #include "bus-label.h"
12 #include "bus-object.h"
13 #include "bus-polkit.h"
14 #include "device-util.h"
15 #include "devnum-util.h"
16 #include "errno-util.h"
18 #include "format-util.h"
22 #include "logind-brightness.h"
23 #include "logind-dbus.h"
24 #include "logind-polkit.h"
25 #include "logind-seat.h"
26 #include "logind-seat-dbus.h"
27 #include "logind-session.h"
28 #include "logind-session-dbus.h"
29 #include "logind-session-device.h"
30 #include "logind-user.h"
31 #include "logind-user-dbus.h"
32 #include "path-util.h"
33 #include "signal-util.h"
34 #include "string-util.h"
36 #include "terminal-util.h"
37 #include "user-record.h"
38 #include "user-util.h"
40 static int property_get_user(
43 const char *interface
,
45 sd_bus_message
*reply
,
47 sd_bus_error
*error
) {
49 _cleanup_free_
char *p
= NULL
;
50 Session
*s
= ASSERT_PTR(userdata
);
55 p
= user_bus_path(s
->user
);
59 return sd_bus_message_append(reply
, "(uo)", (uint32_t) s
->user
->user_record
->uid
, p
);
62 static int property_get_name(
65 const char *interface
,
67 sd_bus_message
*reply
,
69 sd_bus_error
*error
) {
71 Session
*s
= ASSERT_PTR(userdata
);
76 return sd_bus_message_append(reply
, "s", s
->user
->user_record
->user_name
);
79 static int property_get_seat(
82 const char *interface
,
84 sd_bus_message
*reply
,
86 sd_bus_error
*error
) {
88 _cleanup_free_
char *p
= NULL
;
89 Session
*s
= ASSERT_PTR(userdata
);
94 p
= s
->seat
? seat_bus_path(s
->seat
) : strdup("/");
98 return sd_bus_message_append(reply
, "(so)", s
->seat
? s
->seat
->id
: "", p
);
101 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type
, session_type
, SessionType
);
102 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class
, session_class
, SessionClass
);
103 static BUS_DEFINE_PROPERTY_GET(property_get_active
, "b", Session
, session_is_active
);
104 static BUS_DEFINE_PROPERTY_GET2(property_get_state
, "s", Session
, session_get_state
, session_state_to_string
);
106 static int property_get_idle_hint(
109 const char *interface
,
110 const char *property
,
111 sd_bus_message
*reply
,
113 sd_bus_error
*error
) {
115 Session
*s
= ASSERT_PTR(userdata
);
120 return sd_bus_message_append(reply
, "b", session_get_idle_hint(s
, NULL
) > 0);
123 static int property_get_can_idle(
126 const char *interface
,
127 const char *property
,
128 sd_bus_message
*reply
,
130 sd_bus_error
*error
) {
132 Session
*s
= ASSERT_PTR(userdata
);
137 return sd_bus_message_append(reply
, "b", SESSION_CLASS_CAN_IDLE(s
->class));
140 static int property_get_can_lock(
143 const char *interface
,
144 const char *property
,
145 sd_bus_message
*reply
,
147 sd_bus_error
*error
) {
149 Session
*s
= ASSERT_PTR(userdata
);
154 return sd_bus_message_append(reply
, "b", SESSION_CLASS_CAN_LOCK(s
->class));
157 static int property_get_idle_since_hint(
160 const char *interface
,
161 const char *property
,
162 sd_bus_message
*reply
,
164 sd_bus_error
*error
) {
166 Session
*s
= ASSERT_PTR(userdata
);
167 dual_timestamp t
= DUAL_TIMESTAMP_NULL
;
174 r
= session_get_idle_hint(s
, &t
);
178 u
= streq(property
, "IdleSinceHint") ? t
.realtime
: t
.monotonic
;
180 return sd_bus_message_append(reply
, "t", u
);
183 static int property_get_locked_hint(
186 const char *interface
,
187 const char *property
,
188 sd_bus_message
*reply
,
190 sd_bus_error
*error
) {
192 Session
*s
= ASSERT_PTR(userdata
);
197 return sd_bus_message_append(reply
, "b", session_get_locked_hint(s
) > 0);
200 int bus_session_method_terminate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
201 Session
*s
= ASSERT_PTR(userdata
);
206 r
= bus_verify_polkit_async_full(
208 "org.freedesktop.login1.manage",
210 s
->user
->user_record
->uid
,
212 &s
->manager
->polkit_registry
,
217 return 1; /* Will call us back */
219 r
= session_stop(s
, /* force = */ true);
223 return sd_bus_reply_method_return(message
, NULL
);
226 int bus_session_method_activate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
227 Session
*s
= ASSERT_PTR(userdata
);
232 r
= check_polkit_chvt(message
, s
->manager
, error
);
236 return 1; /* Will call us back */
238 r
= session_activate(s
);
242 return sd_bus_reply_method_return(message
, NULL
);
245 int bus_session_method_lock(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
246 Session
*s
= ASSERT_PTR(userdata
);
251 r
= bus_verify_polkit_async_full(
253 "org.freedesktop.login1.lock-sessions",
255 s
->user
->user_record
->uid
,
257 &s
->manager
->polkit_registry
,
262 return 1; /* Will call us back */
264 r
= session_send_lock(s
, /* lock= */ strstr(sd_bus_message_get_member(message
), "Lock"));
266 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Session does not support lock screen.");
270 return sd_bus_reply_method_return(message
, NULL
);
273 static int method_set_idle_hint(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
274 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
275 Session
*s
= ASSERT_PTR(userdata
);
281 r
= sd_bus_message_read(message
, "b", &b
);
285 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
289 r
= sd_bus_creds_get_euid(creds
, &uid
);
293 if (uid
!= 0 && uid
!= s
->user
->user_record
->uid
)
294 return sd_bus_error_set(error
, SD_BUS_ERROR_ACCESS_DENIED
, "Only owner of session may set idle hint");
296 r
= session_set_idle_hint(s
, b
);
298 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Idle hint control is not supported on non-graphical and non-user sessions.");
302 return sd_bus_reply_method_return(message
, NULL
);
305 static int method_set_locked_hint(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
306 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
307 Session
*s
= ASSERT_PTR(userdata
);
313 r
= sd_bus_message_read(message
, "b", &b
);
317 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
321 r
= sd_bus_creds_get_euid(creds
, &uid
);
325 if (uid
!= 0 && uid
!= s
->user
->user_record
->uid
)
326 return sd_bus_error_set(error
, SD_BUS_ERROR_ACCESS_DENIED
, "Only owner of session may set locked hint");
328 r
= session_set_locked_hint(s
, b
);
330 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Session does not support lock screen.");
334 return sd_bus_reply_method_return(message
, NULL
);
337 int bus_session_method_kill(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
338 Session
*s
= ASSERT_PTR(userdata
);
346 r
= sd_bus_message_read(message
, "si", &swhom
, &signo
);
353 whom
= kill_whom_from_string(swhom
);
355 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid kill parameter '%s'", swhom
);
358 if (!SIGNAL_VALID(signo
))
359 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid signal %i", signo
);
361 r
= bus_verify_polkit_async_full(
363 "org.freedesktop.login1.manage",
365 s
->user
->user_record
->uid
,
367 &s
->manager
->polkit_registry
,
372 return 1; /* Will call us back */
374 r
= session_kill(s
, whom
, signo
, error
);
378 return sd_bus_reply_method_return(message
, NULL
);
381 static int method_take_control(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
382 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
383 Session
*s
= ASSERT_PTR(userdata
);
389 r
= sd_bus_message_read(message
, "b", &force
);
393 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
397 r
= sd_bus_creds_get_euid(creds
, &uid
);
401 if (uid
!= 0 && (force
|| uid
!= s
->user
->user_record
->uid
))
402 return sd_bus_error_set(error
, SD_BUS_ERROR_ACCESS_DENIED
, "Only owner of session may take control");
404 r
= session_set_controller(s
, sd_bus_message_get_sender(message
), force
, true);
408 return sd_bus_reply_method_return(message
, NULL
);
411 static int method_release_control(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
412 Session
*s
= ASSERT_PTR(userdata
);
416 if (!session_is_controller(s
, sd_bus_message_get_sender(message
)))
417 return sd_bus_error_set(error
, BUS_ERROR_NOT_IN_CONTROL
, "You are not in control of this session");
419 session_drop_controller(s
);
421 return sd_bus_reply_method_return(message
, NULL
);
424 static int method_set_type(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
425 Session
*s
= ASSERT_PTR(userdata
);
432 r
= sd_bus_message_read(message
, "s", &t
);
436 type
= session_type_from_string(t
);
438 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
439 "Invalid session type '%s'", t
);
441 if (!SESSION_CLASS_CAN_CHANGE_TYPE(s
->class))
442 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Session class doesn't support changing type.");
444 if (!session_is_controller(s
, sd_bus_message_get_sender(message
)))
445 return sd_bus_error_set(error
, BUS_ERROR_NOT_IN_CONTROL
, "You must be in control of this session to set type");
447 session_set_type(s
, type
);
449 return sd_bus_reply_method_return(message
, NULL
);
452 static int method_set_class(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
453 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
454 Session
*s
= ASSERT_PTR(userdata
);
462 r
= sd_bus_message_read(message
, "s", &c
);
466 class = session_class_from_string(c
);
468 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
469 "Invalid session class '%s'", c
);
471 /* For now, we'll allow only upgrades user-incomplete → user */
472 if (class != SESSION_USER
)
473 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
474 "Class may only be set to 'user'");
476 if (s
->class == SESSION_USER
) /* No change, shortcut */
477 return sd_bus_reply_method_return(message
, NULL
);
478 if (s
->class != SESSION_USER_INCOMPLETE
)
479 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
480 "Only sessions with class 'user-incomplete' may change class");
482 if (s
->upgrade_message
)
483 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
484 "Set session class operation already in progress");
486 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
490 r
= sd_bus_creds_get_euid(creds
, &uid
);
494 if (uid
!= 0 && uid
!= s
->user
->user_record
->uid
)
495 return sd_bus_error_set(error
, SD_BUS_ERROR_ACCESS_DENIED
, "Only owner of session may change its class");
497 session_set_class(s
, class);
499 s
->upgrade_message
= sd_bus_message_ref(message
);
501 r
= session_send_upgrade_reply(s
, /* error= */ NULL
);
508 static int method_set_display(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
509 Session
*s
= ASSERT_PTR(userdata
);
515 r
= sd_bus_message_read(message
, "s", &display
);
519 if (!session_is_controller(s
, sd_bus_message_get_sender(message
)))
520 return sd_bus_error_set(error
, BUS_ERROR_NOT_IN_CONTROL
, "You must be in control of this session to set display");
522 if (!SESSION_TYPE_IS_GRAPHICAL(s
->type
))
523 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Setting display is only supported for graphical sessions");
525 r
= session_set_display(s
, display
);
529 return sd_bus_reply_method_return(message
, NULL
);
532 static int method_set_tty(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
533 Session
*s
= ASSERT_PTR(userdata
);
535 _cleanup_free_
char *q
= NULL
;
539 r
= sd_bus_message_read(message
, "h", &fd
);
543 if (!session_is_controller(s
, sd_bus_message_get_sender(message
)))
544 return sd_bus_error_set(error
, BUS_ERROR_NOT_IN_CONTROL
, "You must be in control of this session to set tty");
548 flags
= fcntl(fd
, F_GETFL
, 0);
551 if ((flags
& O_ACCMODE_STRICT
) != O_RDWR
)
553 if (FLAGS_SET(flags
, O_PATH
))
556 r
= getttyname_malloc(fd
, &q
);
560 r
= session_set_tty(s
, q
);
564 return sd_bus_reply_method_return(message
, NULL
);
567 static int method_take_device(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
568 Session
*s
= ASSERT_PTR(userdata
);
569 uint32_t major
, minor
;
570 _cleanup_(session_device_freep
) SessionDevice
*sd
= NULL
;
576 r
= sd_bus_message_read(message
, "uu", &major
, &minor
);
580 if (!DEVICE_MAJOR_VALID(major
) || !DEVICE_MINOR_VALID(minor
))
581 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Device major/minor is not valid.");
583 if (!SESSION_CLASS_CAN_TAKE_DEVICE(s
->class))
584 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Session class doesn't support taking device control.");
586 if (!session_is_controller(s
, sd_bus_message_get_sender(message
)))
587 return sd_bus_error_set(error
, BUS_ERROR_NOT_IN_CONTROL
, "You are not in control of this session");
589 dev
= makedev(major
, minor
);
590 sd
= hashmap_get(s
->devices
, &dev
);
592 /* We don't allow retrieving a device multiple times.
593 * The related ReleaseDevice call is not ref-counted.
594 * The caller should use dup() if it requires more
595 * than one fd (it would be functionally
597 return sd_bus_error_set(error
, BUS_ERROR_DEVICE_IS_TAKEN
, "Device already taken");
599 r
= session_device_new(s
, dev
, true, &sd
);
603 r
= session_device_save(sd
);
607 r
= sd_bus_reply_method_return(message
, "hb", sd
->fd
, !sd
->active
);
617 static int method_release_device(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
618 Session
*s
= ASSERT_PTR(userdata
);
619 uint32_t major
, minor
;
626 r
= sd_bus_message_read(message
, "uu", &major
, &minor
);
630 if (!DEVICE_MAJOR_VALID(major
) || !DEVICE_MINOR_VALID(minor
))
631 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Device major/minor is not valid.");
633 if (!session_is_controller(s
, sd_bus_message_get_sender(message
)))
634 return sd_bus_error_set(error
, BUS_ERROR_NOT_IN_CONTROL
, "You are not in control of this session");
636 dev
= makedev(major
, minor
);
637 sd
= hashmap_get(s
->devices
, &dev
);
639 return sd_bus_error_set(error
, BUS_ERROR_DEVICE_NOT_TAKEN
, "Device not taken");
641 session_device_free(sd
);
644 return sd_bus_reply_method_return(message
, NULL
);
647 static int method_pause_device_complete(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
648 Session
*s
= ASSERT_PTR(userdata
);
649 uint32_t major
, minor
;
656 r
= sd_bus_message_read(message
, "uu", &major
, &minor
);
660 if (!DEVICE_MAJOR_VALID(major
) || !DEVICE_MINOR_VALID(minor
))
661 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Device major/minor is not valid.");
663 if (!session_is_controller(s
, sd_bus_message_get_sender(message
)))
664 return sd_bus_error_set(error
, BUS_ERROR_NOT_IN_CONTROL
, "You are not in control of this session");
666 dev
= makedev(major
, minor
);
667 sd
= hashmap_get(s
->devices
, &dev
);
669 return sd_bus_error_set(error
, BUS_ERROR_DEVICE_NOT_TAKEN
, "Device not taken");
671 session_device_complete_pause(sd
);
673 return sd_bus_reply_method_return(message
, NULL
);
676 static int method_set_brightness(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
677 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
678 _cleanup_(sd_device_unrefp
) sd_device
*d
= NULL
;
679 const char *subsystem
, *name
, *seat
;
680 Session
*s
= ASSERT_PTR(userdata
);
687 r
= sd_bus_message_read(message
, "ssu", &subsystem
, &name
, &brightness
);
691 if (!STR_IN_SET(subsystem
, "backlight", "leds"))
692 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Subsystem type %s not supported, must be one of 'backlight' or 'leds'.", subsystem
);
693 if (!filename_is_valid(name
))
694 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not a valid device name %s, refusing.", name
);
697 return sd_bus_error_set(error
, BUS_ERROR_NOT_YOUR_DEVICE
, "Your session has no seat, refusing.");
698 if (s
->seat
->active
!= s
)
699 return sd_bus_error_set(error
, BUS_ERROR_NOT_YOUR_DEVICE
, "Session is not in foreground, refusing.");
701 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
705 r
= sd_bus_creds_get_euid(creds
, &uid
);
709 if (uid
!= 0 && uid
!= s
->user
->user_record
->uid
)
710 return sd_bus_error_set(error
, SD_BUS_ERROR_ACCESS_DENIED
, "Only owner of session may change brightness.");
712 r
= sd_device_new_from_subsystem_sysname(&d
, subsystem
, name
);
714 return sd_bus_error_set_errnof(error
, r
, "Failed to open device %s:%s: %m", subsystem
, name
);
716 r
= device_get_seat(d
, &seat
);
718 return sd_bus_error_set_errnof(error
, r
, "Failed to get seat of %s:%s: %m", subsystem
, name
);
719 if (!streq(seat
, s
->seat
->id
))
720 return sd_bus_error_setf(error
, BUS_ERROR_NOT_YOUR_DEVICE
, "Device %s:%s does not belong to your seat %s, refusing.", subsystem
, name
, s
->seat
->id
);
722 r
= manager_write_brightness(s
->manager
, d
, brightness
, message
);
729 static int session_object_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
730 _cleanup_free_
char *e
= NULL
;
731 sd_bus_message
*message
;
732 Manager
*m
= ASSERT_PTR(userdata
);
742 p
= startswith(path
, "/org/freedesktop/login1/session/");
746 e
= bus_label_unescape(p
);
750 message
= sd_bus_get_current_message(bus
);
752 r
= manager_get_session_from_creds(m
, message
, e
, error
, &session
);
754 sd_bus_error_free(error
);
764 char* session_bus_path(Session
*s
) {
765 _cleanup_free_
char *t
= NULL
;
769 t
= bus_label_escape(s
->id
);
773 return strjoin("/org/freedesktop/login1/session/", t
);
776 static int session_node_enumerator(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
777 _cleanup_strv_free_
char **l
= NULL
;
778 sd_bus_message
*message
;
779 Manager
*m
= userdata
;
787 HASHMAP_FOREACH(session
, m
->sessions
) {
790 p
= session_bus_path(session
);
794 r
= strv_consume(&l
, p
);
799 message
= sd_bus_get_current_message(bus
);
801 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
803 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_SESSION
|SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
805 bool may_auto
= false;
808 r
= sd_bus_creds_get_session(creds
, &name
);
810 session
= hashmap_get(m
->sessions
, name
);
812 r
= strv_extend(&l
, "/org/freedesktop/login1/session/self");
823 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
827 user
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
828 may_auto
= user
&& user
->display
;
833 r
= strv_extend(&l
, "/org/freedesktop/login1/session/auto");
840 *nodes
= TAKE_PTR(l
);
844 int session_send_signal(Session
*s
, bool new_session
) {
845 _cleanup_free_
char *p
= NULL
;
849 p
= session_bus_path(s
);
853 return sd_bus_emit_signal(
855 "/org/freedesktop/login1",
856 "org.freedesktop.login1.Manager",
857 new_session
? "SessionNew" : "SessionRemoved",
861 int session_send_changed_strv(Session
*s
, char **properties
) {
862 _cleanup_free_
char *p
= NULL
;
869 p
= session_bus_path(s
);
873 return sd_bus_emit_properties_changed_strv(s
->manager
->bus
, p
, "org.freedesktop.login1.Session", properties
);
876 int session_send_lock(Session
*s
, bool lock
) {
877 _cleanup_free_
char *p
= NULL
;
881 if (!SESSION_CLASS_CAN_LOCK(s
->class))
884 p
= session_bus_path(s
);
888 return sd_bus_emit_signal(
891 "org.freedesktop.login1.Session",
892 lock
? "Lock" : "Unlock",
896 int session_send_lock_all(Manager
*m
, bool lock
) {
902 HASHMAP_FOREACH(session
, m
->sessions
) {
904 if (!SESSION_CLASS_CAN_LOCK(session
->class))
907 RET_GATHER(r
, session_send_lock(session
, lock
));
913 int session_send_create_reply_bus(Session
*s
, const sd_bus_error
*error
) {
916 /* This is called after the session scope and the user service were successfully created, and
917 * finishes where manager_create_session() left off. */
919 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*c
= TAKE_PTR(s
->create_message
);
923 if (sd_bus_error_is_set(error
))
924 return sd_bus_reply_method_error(c
, error
);
926 /* Prior to v258, logind tracked sessions by installing a fifo in client and subscribe to its EOF.
927 * Now we can fully rely on pidfd for this, but still need to return *something* to the client.
928 * Allocate something lightweight and isolated as placeholder. */
929 _cleanup_close_
int fd
= eventfd(0, EFD_CLOEXEC
);
933 _cleanup_free_
char *p
= session_bus_path(s
);
937 log_debug("Sending D-Bus reply about created session: "
938 "id=%s object_path=%s uid=" UID_FMT
" runtime_path=%s seat=%s vtnr=%u",
941 s
->user
->user_record
->uid
,
942 s
->user
->runtime_path
,
943 s
->seat
? s
->seat
->id
: "",
946 return sd_bus_reply_method_return(
950 s
->user
->runtime_path
,
951 fd
, /* not really used - see comments above */
952 (uint32_t) s
->user
->user_record
->uid
,
953 s
->seat
? s
->seat
->id
: "",
958 int session_send_upgrade_reply(Session
*s
, const sd_bus_error
*error
) {
959 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*c
= NULL
;
962 if (!s
->upgrade_message
)
965 /* See comments in session_send_create_reply */
966 if (!sd_bus_error_is_set(error
) && session_job_pending(s
))
969 c
= TAKE_PTR(s
->upgrade_message
);
971 return sd_bus_reply_method_error(c
, error
);
975 return sd_bus_reply_method_return(c
, NULL
);
978 static const sd_bus_vtable session_vtable
[] = {
979 SD_BUS_VTABLE_START(0),
981 SD_BUS_PROPERTY("Id", "s", NULL
, offsetof(Session
, id
), SD_BUS_VTABLE_PROPERTY_CONST
),
982 SD_BUS_PROPERTY("User", "(uo)", property_get_user
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
983 SD_BUS_PROPERTY("Name", "s", property_get_name
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
984 BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Session
, timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
985 SD_BUS_PROPERTY("VTNr", "u", NULL
, offsetof(Session
, vtnr
), SD_BUS_VTABLE_PROPERTY_CONST
),
986 SD_BUS_PROPERTY("Seat", "(so)", property_get_seat
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
987 SD_BUS_PROPERTY("TTY", "s", NULL
, offsetof(Session
, tty
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
988 SD_BUS_PROPERTY("Display", "s", NULL
, offsetof(Session
, display
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
989 SD_BUS_PROPERTY("Remote", "b", bus_property_get_bool
, offsetof(Session
, remote
), SD_BUS_VTABLE_PROPERTY_CONST
),
990 SD_BUS_PROPERTY("RemoteHost", "s", NULL
, offsetof(Session
, remote_host
), SD_BUS_VTABLE_PROPERTY_CONST
),
991 SD_BUS_PROPERTY("RemoteUser", "s", NULL
, offsetof(Session
, remote_user
), SD_BUS_VTABLE_PROPERTY_CONST
),
992 SD_BUS_PROPERTY("Service", "s", NULL
, offsetof(Session
, service
), SD_BUS_VTABLE_PROPERTY_CONST
),
993 SD_BUS_PROPERTY("Desktop", "s", NULL
, offsetof(Session
, desktop
), SD_BUS_VTABLE_PROPERTY_CONST
),
994 SD_BUS_PROPERTY("Scope", "s", NULL
, offsetof(Session
, scope
), SD_BUS_VTABLE_PROPERTY_CONST
),
995 SD_BUS_PROPERTY("Leader", "u", bus_property_get_pid
, offsetof(Session
, leader
.pid
), SD_BUS_VTABLE_PROPERTY_CONST
),
996 SD_BUS_PROPERTY("LeaderPIDFDId", "t", bus_property_get_pidfdid
, offsetof(Session
, leader
), SD_BUS_VTABLE_PROPERTY_CONST
),
997 SD_BUS_PROPERTY("Audit", "u", NULL
, offsetof(Session
, audit_id
), SD_BUS_VTABLE_PROPERTY_CONST
),
998 SD_BUS_PROPERTY("Type", "s", property_get_type
, offsetof(Session
, type
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
999 SD_BUS_PROPERTY("Class", "s", property_get_class
, offsetof(Session
, class), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1000 SD_BUS_PROPERTY("Active", "b", property_get_active
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1001 SD_BUS_PROPERTY("State", "s", property_get_state
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1002 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1003 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1004 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1005 SD_BUS_PROPERTY("CanIdle", "b", property_get_can_idle
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1006 SD_BUS_PROPERTY("CanLock", "b", property_get_can_lock
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1007 SD_BUS_PROPERTY("LockedHint", "b", property_get_locked_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1009 SD_BUS_METHOD("Terminate",
1012 bus_session_method_terminate
,
1013 SD_BUS_VTABLE_UNPRIVILEGED
),
1014 SD_BUS_METHOD("Activate",
1017 bus_session_method_activate
,
1018 SD_BUS_VTABLE_UNPRIVILEGED
),
1019 SD_BUS_METHOD("Lock",
1022 bus_session_method_lock
,
1023 SD_BUS_VTABLE_UNPRIVILEGED
),
1024 SD_BUS_METHOD("Unlock",
1027 bus_session_method_lock
,
1028 SD_BUS_VTABLE_UNPRIVILEGED
),
1029 SD_BUS_METHOD_WITH_ARGS("SetIdleHint",
1030 SD_BUS_ARGS("b", idle
),
1032 method_set_idle_hint
,
1033 SD_BUS_VTABLE_UNPRIVILEGED
),
1034 SD_BUS_METHOD_WITH_ARGS("SetLockedHint",
1035 SD_BUS_ARGS("b", locked
),
1037 method_set_locked_hint
,
1038 SD_BUS_VTABLE_UNPRIVILEGED
),
1039 SD_BUS_METHOD_WITH_ARGS("Kill",
1040 SD_BUS_ARGS("s", whom
, "i", signal_number
),
1042 bus_session_method_kill
,
1043 SD_BUS_VTABLE_UNPRIVILEGED
),
1044 SD_BUS_METHOD_WITH_ARGS("TakeControl",
1045 SD_BUS_ARGS("b", force
),
1047 method_take_control
,
1048 SD_BUS_VTABLE_UNPRIVILEGED
),
1049 SD_BUS_METHOD("ReleaseControl",
1052 method_release_control
,
1053 SD_BUS_VTABLE_UNPRIVILEGED
),
1054 SD_BUS_METHOD_WITH_ARGS("SetType",
1055 SD_BUS_ARGS("s", type
),
1058 SD_BUS_VTABLE_UNPRIVILEGED
),
1059 SD_BUS_METHOD_WITH_ARGS("SetClass",
1060 SD_BUS_ARGS("s", class),
1063 SD_BUS_VTABLE_UNPRIVILEGED
),
1064 SD_BUS_METHOD_WITH_ARGS("SetDisplay",
1065 SD_BUS_ARGS("s", display
),
1068 SD_BUS_VTABLE_UNPRIVILEGED
),
1069 SD_BUS_METHOD_WITH_ARGS("SetTTY",
1070 SD_BUS_ARGS("h", tty_fd
),
1073 SD_BUS_VTABLE_UNPRIVILEGED
),
1074 SD_BUS_METHOD_WITH_ARGS("TakeDevice",
1075 SD_BUS_ARGS("u", major
, "u", minor
),
1076 SD_BUS_RESULT("h", fd
, "b", inactive
),
1078 SD_BUS_VTABLE_UNPRIVILEGED
),
1079 SD_BUS_METHOD_WITH_ARGS("ReleaseDevice",
1080 SD_BUS_ARGS("u", major
, "u", minor
),
1082 method_release_device
,
1083 SD_BUS_VTABLE_UNPRIVILEGED
),
1084 SD_BUS_METHOD_WITH_ARGS("PauseDeviceComplete",
1085 SD_BUS_ARGS("u", major
, "u", minor
),
1087 method_pause_device_complete
,
1088 SD_BUS_VTABLE_UNPRIVILEGED
),
1089 SD_BUS_METHOD_WITH_ARGS("SetBrightness",
1090 SD_BUS_ARGS("s", subsystem
, "s", name
, "u", brightness
),
1092 method_set_brightness
,
1093 SD_BUS_VTABLE_UNPRIVILEGED
),
1095 SD_BUS_SIGNAL_WITH_ARGS("PauseDevice",
1096 SD_BUS_ARGS("u", major
, "u", minor
, "s", type
),
1098 SD_BUS_SIGNAL_WITH_ARGS("ResumeDevice",
1099 SD_BUS_ARGS("u", major
, "u", minor
, "h", fd
),
1101 SD_BUS_SIGNAL("Lock", NULL
, 0),
1102 SD_BUS_SIGNAL("Unlock", NULL
, 0),
1107 const BusObjectImplementation session_object
= {
1108 "/org/freedesktop/login1/session",
1109 "org.freedesktop.login1.Session",
1110 .fallback_vtables
= BUS_FALLBACK_VTABLES({session_vtable
, session_object_find
}),
1111 .node_enumerator
= session_node_enumerator
,