chiark / gitweb /
Introduce elogind-uaccess-command to replace uaccess builtin.
authorArthur Taylor <art@ified.ca>
Thu, 8 Feb 2018 23:03:50 +0000 (15:03 -0800)
committerSven Eden <yamakuzure@gmx.net>
Wed, 7 Mar 2018 15:49:51 +0000 (16:49 +0100)
The uaccess udev builtin command is only used by logind and contains
functionality only implemented in logind. As such, while we cannot
write udev-builtin commands in elogind (not being udev), we can write
standalone binaries and rewrite our udev rules to use them instead.

This fixes the feature of granting users access to devices using a user
ACL which is toggled only when the user is associated with an active
session. Currently this functionality is half broken, as while the ACL
is granted and revoked while VT-switching, it is not granted to new
devices as they are plugged in. This issue is fixed by this commit.

meson.build
src/basic/login-util.h
src/login/73-seat-late.rules.in
src/uaccess-command/uaccess-command.c [new file with mode: 0644]

index f47def2579f8185104eef6d27edcc535886a021c..469c2b9bc64f19d768d86b5c3e0ec23c1b209c83 100644 (file)
@@ -205,6 +205,7 @@ conf.set_quoted('SYSTEM_CONFIG_UNIT_PATH',                    join_paths(pkgsysc
 # conf.set_quoted('SYSTEMD_STDIO_BRIDGE_BINARY_PATH',           join_paths(bindir, 'systemd-stdio-bridge'))
 #else
 conf.set_quoted('SYSTEMD_CGROUP_AGENT_PATH',                  join_paths(rootlibexecdir, 'elogind-cgroups-agent'))
+conf.set_quoted('ELOGIND_UACCESS_COMMAND_PATH',               join_paths(rootlibexecdir, 'elogind-uaccess-command'))
 conf.set_quoted('SYSTEMD_BINARY_PATH',                        join_paths(rootlibexecdir, 'elogind'))
 #endif // 0
 conf.set_quoted('ROOTPREFIX',                                 rootprefixdir)
@@ -2519,6 +2520,18 @@ executable('elogind-cgroups-agent',
 #         public_programs += [exe]
 # endif
 #endif // 0
+
+executable('elogind-uaccess-command',
+           'src/uaccess-command/uaccess-command.c',
+           include_directories : includes,
+           link_with : [liblogind_core,
+                        libshared_static],
+           dependencies: [libacl,
+                          libudev],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
 ############################################################
 
 foreach tuple : tests
index a71ebd4ef4734a8f7779208aa2ef860095676d9b..b01ee25c884cee292d2d826fc2c7f57a515e5018 100644 (file)
@@ -24,8 +24,6 @@
 
 bool session_id_valid(const char *id);
 
-#if 0 /// UNNEEDED by elogind
 static inline bool logind_running(void) {
         return access("/run/systemd/seats/", F_OK) >= 0;
 }
-#endif // 0
index 901df750fde32fb9cd9e43a287e45b7c08239e85..a44976b6d07192fdc7a8ed67db13b0e194ee17bc 100644 (file)
@@ -12,6 +12,6 @@ ENV{ID_SEAT}=="", IMPORT{parent}="ID_SEAT"
 
 ENV{ID_SEAT}!="", TAG+="$env{ID_SEAT}"
 
-TAG=="uaccess", ENV{MAJOR}!="", RUN{builtin}+="uaccess"
+TAG=="uaccess", ENV{MAJOR}!="", RUN{program}+="@rootlibexecdir@/elogind-uaccess-command %N $env{ID_SEAT}"
 
 LABEL="seat_late_end"
diff --git a/src/uaccess-command/uaccess-command.c b/src/uaccess-command/uaccess-command.c
new file mode 100644 (file)
index 0000000..efb9dcd
--- /dev/null
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * manage device node user ACL
+ *
+ * Copyright 2010-2012 Kay Sievers <kay@vrfy.org>
+ * Copyright 2010 Lennart Poettering
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "sd-login.h"
+
+#include "login-util.h"
+#include "logind-acl.h"
+#include "util.h"
+
+/*
+ * Copy of builtin_uaccess() from
+ * systemd/src/udev/udev-builtin-uaccess.c
+ */
+static int dev_uaccess(const char *path, const char *seat) {
+        int r;
+        bool changed_acl = false;
+        uid_t uid;
+
+        umask(0022);
+
+        /* don't muck around with ACLs when the system is not running systemd */
+        if (!logind_running())
+                return 0;
+
+        if (!seat || !strlen(seat))
+                seat = "seat0";
+
+        r = sd_seat_get_active(seat, NULL, &uid);
+        if (IN_SET(r, -ENXIO, -ENODATA)) {
+                /* No active session on this seat */
+                r = 0;
+                goto finish;
+        } else if (r < 0) {
+                log_error("Failed to determine active user on seat %s.", seat);
+                goto finish;
+        }
+
+        r = devnode_acl(path, true, false, 0, true, uid);
+        if (r < 0) {
+                log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to apply ACL on %s: %m", path);
+                goto finish;
+        }
+
+        changed_acl = true;
+        r = 0;
+
+finish:
+        if (path && !changed_acl) {
+                int k;
+
+                /* Better be safe than sorry and reset ACL */
+                k = devnode_acl(path, true, false, 0, false, 0);
+                if (k < 0) {
+                        log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, k, "Failed to apply ACL on %s: %m", path);
+                        if (r >= 0)
+                                r = k;
+                }
+        }
+
+        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+int main(int argc, char *argv[]) {
+
+        if (argc < 2) {
+                printf("Usage: %s DEVPATH [SEAT]\n", argv[0]);
+                return 0;
+        }
+
+        elogind_set_program_name(argv[0]);
+        log_set_target(LOG_TARGET_AUTO);
+        log_parse_environment();
+        log_open();
+
+        return dev_uaccess(argv[1], argc > 2 ? argv[2] : NULL);
+}