From: Arthur Taylor Date: Thu, 8 Feb 2018 23:03:50 +0000 (-0800) Subject: Introduce elogind-uaccess-command to replace uaccess builtin. X-Git-Tag: v235.3~14 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=316e8d849fc1d34b61d27f2967e0ede84fe9f46d;p=elogind.git Introduce elogind-uaccess-command to replace uaccess builtin. 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. --- diff --git a/meson.build b/meson.build index f47def257..469c2b9bc 100644 --- a/meson.build +++ b/meson.build @@ -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 diff --git a/src/basic/login-util.h b/src/basic/login-util.h index a71ebd4ef..b01ee25c8 100644 --- a/src/basic/login-util.h +++ b/src/basic/login-util.h @@ -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 diff --git a/src/login/73-seat-late.rules.in b/src/login/73-seat-late.rules.in index 901df750f..a44976b6d 100644 --- a/src/login/73-seat-late.rules.in +++ b/src/login/73-seat-late.rules.in @@ -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 index 000000000..efb9dcd62 --- /dev/null +++ b/src/uaccess-command/uaccess-command.c @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * manage device node user ACL + * + * Copyright 2010-2012 Kay Sievers + * 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 . + */ + +#include +#include +#include + +#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); +}