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

Reply via email to