Hello! The default systemd behavior is to grant/revoke access on devices attached to a seat when the user activates/deactivates a session on the seat.
But sometimes it needs the user has an access to some device when he/she activates a session with ANY seat. For example, I have two seats: seat0 with ordinary monitor/keyboard/mouse/usb hub/usb sound card and seat1 that is using as a music workstation: it has some midi keyboards and sound cards connected. Usually I run midi applications on seat1, but sometimes I run them on seat1. All midi applications require the access to /dev/snd/seq kernel device. So it should be granted when a user activates a session on any seat. My approach to make this is to introduce a special UDEV tag 'shared' that tells logind that this device is attached to all seats and logind has to grant access to all sessions on all seats I've made a patch to systemd/logind that processes the 'shared' tag. After adding the simple udev rule: ---------------------------------------------- KERNEL=="seq", SUBSYSTEM=="sound", TAG+="shared" ---------------------------------------------- /dev/snd/seq becomes accessible from all seats. Could you resolve this patch upstream or propose another way of granting access to /dev/snd/seq on activating sessions?
From: Oleg Samarin <[email protected]> Subject: [PATCH] logind: support of shared devices Supporting of acls on devices shared between all seats (like /dev/snd/seq): A user gets permitions on it when he activates a session on any seat. He/she losses the permitions when no his/her active sessions more exist diff -Naur systemd-217.old/src/login/logind-acl.c systemd-217.new/src/login/logind-acl.c --- systemd-217.old/src/login/logind-acl.c 2014-10-07 17:59:01.469576000 +0400 +++ systemd-217.new/src/login/logind-acl.c 2014-12-17 08:46:05.897064691 +0300 @@ -173,26 +173,56 @@ return r; } +int devset_all_acl( + Set *nodes, bool flush, + const char *seat, + bool del, uid_t old_uid, + bool add, uid_t new_uid +) { + int r = 0; + char *n; + Iterator i; + + SET_FOREACH(n, nodes, i) { + int k; + + log_debug("Changing ACLs at %s for seat %s (uid "UID_FMT"→"UID_FMT"%s%s)", + n, seat, old_uid, new_uid, + del ? " del" : "", add ? " add" : ""); + + k = devnode_acl(n, flush, del, old_uid, add, new_uid); + if (k == -ENOENT) + log_debug("Device %s disappeared while setting ACLs", n); + else if (k < 0 && r == 0) + r = k; + } + return r; +} + int devnode_acl_all(struct udev *udev, const char *seat, bool flush, - bool del, uid_t old_uid, + bool del, bool del_shared, uid_t old_uid, bool add, uid_t new_uid) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; struct udev_list_entry *item = NULL, *first = NULL; _cleanup_set_free_free_ Set *nodes = NULL; + _cleanup_set_free_free_ Set *nodes_shared = NULL; _cleanup_closedir_ DIR *dir = NULL; struct dirent *dent; Iterator i; char *n; - int r; + int r, r1; assert(udev); nodes = set_new(&string_hash_ops); if (!nodes) return -ENOMEM; + nodes_shared = set_new(&string_hash_ops); + if (!nodes_shared) + return -ENOMEM; e = udev_enumerate_new(udev); if (!e) @@ -222,17 +252,25 @@ udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; const char *node, *sn; + bool is_shared; d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!d) return -ENOMEM; - sn = udev_device_get_property_value(d, "ID_SEAT"); - if (isempty(sn)) - sn = "seat0"; - - if (!streq(seat, sn)) - continue; + /* all devices with shared tag are accessible with all seats */ + is_shared = udev_device_has_tag(d, "shared"); + + if (is_shared) + sn = "shared"; + else { + sn = udev_device_get_property_value(d, "ID_SEAT"); + if (isempty(sn)) + sn = "seat0"; + + if (!streq(seat, sn)) + continue; + } node = udev_device_get_devnode(d); /* In case people mistag devices with nodes, we need to ignore this */ @@ -244,7 +282,10 @@ return -ENOMEM; log_debug("Found udev node %s for seat %s", n, seat); - r = set_consume(nodes, n); + if (is_shared) + r = set_consume(nodes_shared, n); + else + r = set_consume(nodes, n); if (r < 0) return r; } @@ -273,20 +314,10 @@ } } - r = 0; - SET_FOREACH(n, nodes, i) { - int k; - - log_debug("Changing ACLs at %s for seat %s (uid "UID_FMT"→"UID_FMT"%s%s)", - n, seat, old_uid, new_uid, - del ? " del" : "", add ? " add" : ""); - - k = devnode_acl(n, flush, del, old_uid, add, new_uid); - if (k == -ENOENT) - log_debug("Device %s disappeared while setting ACLs", n); - else if (k < 0 && r == 0) - r = k; - } + r = devset_all_acl(nodes, flush, seat, del, old_uid, add, new_uid); + r1 = devset_all_acl(nodes_shared, flush, seat, del_shared, old_uid, add, new_uid); + if (r == 0) + r = r1; return r; } diff -Naur systemd-217.old/src/login/logind-acl.h systemd-217.new/src/login/logind-acl.h --- systemd-217.old/src/login/logind-acl.h 2014-02-13 06:42:33.304687000 +0400 +++ systemd-217.new/src/login/logind-acl.h 2014-12-15 23:18:23.267625511 +0300 @@ -35,7 +35,7 @@ int devnode_acl_all(struct udev *udev, const char *seat, bool flush, - bool del, uid_t old_uid, + bool del, bool del_shared, uid_t old_uid, bool add, uid_t new_uid); #else diff -Naur systemd-217.old/src/login/logind-seat.c systemd-217.new/src/login/logind-seat.c --- systemd-217.old/src/login/logind-seat.c 2014-07-10 22:12:34.013021000 +0400 +++ systemd-217.new/src/login/logind-seat.c 2014-12-15 23:22:28.584258478 +0300 @@ -217,7 +217,10 @@ r = devnode_acl_all(s->manager->udev, s->id, false, - !!old_active, old_active ? old_active->user->uid : 0, + !!old_active, + // delete acl on shared devices only if no other active sessions + old_active && user_get_state(old_active->user) != USER_ACTIVE, + old_active ? old_active->user->uid : 0, !!s->active, s->active ? s->active->user->uid : 0); if (r < 0)
_______________________________________________ systemd-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/systemd-devel
