[systemd-devel] [PATCHv3 2/2] logind: apply ACL's to dead device nodes

2013-07-16 Thread Tom Gundersen
Based on a patch by Kay Sievers.

When a dead device nodes is tagged with uaccess using the static_node 
mechanism,
it's ACL's are managed by logind in the same way as live device nodes.

This allows in particular /dev/snd/{seq,timer} to cause modules to be loaded
on-demand when accessed by a non-privileged user.
---

v3: no change

 src/login/logind-acl.c | 75 ++
 1 file changed, 64 insertions(+), 11 deletions(-)

diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c
index cb045a9..c0ff509 100644
--- a/src/login/logind-acl.c
+++ b/src/login/logind-acl.c
@@ -28,6 +28,7 @@
 #include logind-acl.h
 #include util.h
 #include acl-util.h
+#include set.h
 
 static int flush_acl(acl_t acl) {
 acl_entry_t i;
@@ -179,23 +180,34 @@ int devnode_acl_all(struct udev *udev,
 
 struct udev_list_entry *item = NULL, *first = NULL;
 struct udev_enumerate *e;
+Set *nodes;
+Iterator i;
+char *n;
+DIR *dir;
+struct dirent *dent;
 int r;
 
 assert(udev);
 
-if (isempty(seat))
-seat = seat0;
+nodes = set_new(string_hash_func, string_compare_func);
+if (!nodes) {
+return -ENOMEM;
+}
 
 e = udev_enumerate_new(udev);
-if (!e)
-return -ENOMEM;
+if (!e) {
+r = -ENOMEM;
+goto finish;
+}
+
+if (isempty(seat))
+seat = seat0;
 
 /* We can only match by one tag in libudev. We choose
  * uaccess for that. If we could match for two tags here we
  * could add the seat name as second match tag, but this would
  * be hardly optimizable in libudev, and hence checking the
  * second tag manually in our loop is a good solution. */
-
 r = udev_enumerate_add_match_tag(e, uaccess);
 if (r  0)
 goto finish;
@@ -231,18 +243,59 @@ int devnode_acl_all(struct udev *udev,
 continue;
 }
 
-log_debug(Fixing up %s for seat %s..., node, sn);
-
-r = devnode_acl(node, flush, del, old_uid, add, new_uid);
+n = strdup(node);
 udev_device_unref(d);
+if (!n)
+goto finish;
 
+log_debug(Found udev node %s for seat %s, n, seat);
+r = set_put(nodes, n);
 if (r  0)
 goto finish;
 }
 
-finish:
-if (e)
-udev_enumerate_unref(e);
+/* udev exports dead device nodes to allow module on-demand loading,
+ * these devices are not known to the kernel at this moment */
+dir = opendir(/run/udev/static_node-tags/uaccess);
+if (dir) {
+for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+_cleanup_free_ char *unescaped_devname = NULL;
 
+if (dent-d_name[0] == '.')
+continue;
+
+unescaped_devname = cunescape(dent-d_name);
+if (unescaped_devname == NULL) {
+r = -ENOMEM;
+closedir(dir);
+goto finish;
+}
+
+n = strappend(/dev/, unescaped_devname);
+if (!n) {
+r = -ENOMEM;
+closedir(dir);
+goto finish;
+}
+
+log_debug(Found static node %s for seat %s, n, seat);
+r = set_put(nodes, n);
+if (0  r  0  r != -EEXIST) {
+closedir(dir);
+goto finish;
+} else
+r = 0;
+}
+closedir(dir);
+}
+
+SET_FOREACH(n, nodes, i) {
+log_debug(Fixing up ACLs at %s for seat %s, n, seat);
+r = devnode_acl(n, flush, del, old_uid, add, new_uid);
+}
+
+finish:
+udev_enumerate_unref(e);
+set_free_free(nodes);
 return r;
 }
-- 
1.8.3.3

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCHv3 2/2] logind: apply ACL's to dead device nodes

2013-07-16 Thread Lennart Poettering
On Tue, 16.07.13 19:38, Tom Gundersen (t...@jklm.no) wrote:

 -udev_enumerate_unref(e);
 +/* udev exports dead device nodes to allow module on-demand 
 loading,
 + * these devices are not known to the kernel at this moment */
 +dir = opendir(/run/udev/static_node-tags/uaccess);
 +if (dir) {
 +for (dent = readdir(dir); dent != NULL; dent =
 readdir(dir)) {

Please use FOREACH_DIRENT here!

 +_cleanup_free_ char *unescaped_devname = NULL;
  
 +if (dent-d_name[0] == '.')
 +continue;

This is unnecessary if you use FOREACH_DIRENT.

 +
 +unescaped_devname = cunescape(dent-d_name);
 +if (unescaped_devname == NULL) {
 +r = -ENOMEM;
 +closedir(dir);

Looks like you want to use _cleanup_closedir_ for this?

 +goto finish;
 +}
 +
 +n = strappend(/dev/, unescaped_devname);

Good candidate for strappenda?

Lennart

-- 
Lennart Poettering - Red Hat, Inc.
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCHv3 2/2] logind: apply ACL's to dead device nodes

2013-07-16 Thread Lennart Poettering
On Tue, 16.07.13 20:39, Lennart Poettering (lenn...@poettering.net) wrote:

  +goto finish;
  +}
  +
  +n = strappend(/dev/, unescaped_devname);
 
 Good candidate for strappenda?

I take this back. Awful candidate for strappenda() since this is inside
a loop, and you cannot sanely use alloca() in a loop, since it keeps
appending to the stack.

So, please keep using strappend() for this one.

Lennart

-- 
Lennart Poettering - Red Hat, Inc.
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCHv3 2/2] logind: apply ACL's to dead device nodes

2013-07-16 Thread Tom Gundersen
On Tue, Jul 16, 2013 at 8:39 PM, Lennart Poettering
lenn...@poettering.net wrote:
 On Tue, 16.07.13 19:38, Tom Gundersen (t...@jklm.no) wrote:

 -udev_enumerate_unref(e);
 +/* udev exports dead device nodes to allow module on-demand 
 loading,
 + * these devices are not known to the kernel at this moment */
 +dir = opendir(/run/udev/static_node-tags/uaccess);
 +if (dir) {
 +for (dent = readdir(dir); dent != NULL; dent =
 readdir(dir)) {

 Please use FOREACH_DIRENT here!

 +_cleanup_free_ char *unescaped_devname = NULL;

 +if (dent-d_name[0] == '.')
 +continue;

 This is unnecessary if you use FOREACH_DIRENT.

 +
 +unescaped_devname = cunescape(dent-d_name);
 +if (unescaped_devname == NULL) {
 +r = -ENOMEM;
 +closedir(dir);

 Looks like you want to use _cleanup_closedir_ for this?

Thanks for the suggestions. Will push fix after testing.

 +goto finish;
 +}
 +
 +n = strappend(/dev/, unescaped_devname);

 Good candidate for strappenda?

Except for this one.

-t
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel