07b358f
From 054d9609e1639a725e9a29af086c1585bacc43ff Mon Sep 17 00:00:00 2001
07b358f
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
07b358f
Date: Thu, 6 Aug 2015 21:34:15 -0400
07b358f
Subject: [PATCH] manager: put bin before sbin for user instances
07b358f
07b358f
Traditionally, user logins had a $PATH in which /bin was before /sbin, while
07b358f
root logins had a $PATH with /sbin first. This allows the tricks that
07b358f
consolehelper is doing to work. But even if we ignore consolehelper, having the
07b358f
path in this order might have been used by admins for other purposes, and
07b358f
keeping the order in user sessions will make it easier the adoption of systemd
07b358f
user sessions a bit easier.
07b358f
07b358f
Fixes #733.
07b358f
https://bugzilla.redhat.com/show_bug.cgi?id=1744059
07b358f
07b358f
OOM handling in manager_default_environment wasn't really correct.
07b358f
Now the (theorertical) malloc failure in strv_new() is handled.
07b358f
07b358f
Please note that this has no effect on:
07b358f
- systems with merged /bin-/sbin (e.g. arch)
07b358f
07b358f
- when there are no binaries that differ between the two locations.
07b358f
07b358f
  E.g. on my F30 laptop there is exactly one program that is affected:
07b358f
  /usr/bin/setup -> consolehelper.
07b358f
07b358f
  There is less and less stuff that relies on consolehelper, but there's still
07b358f
  some.
07b358f
07b358f
So for "clean" systems this makes no difference, but helps with legacy setups.
07b358f
07b358f
$ dnf repoquery --releasever=31 --qf %{name} --whatrequires usermode
07b358f
anaconda-live
07b358f
audit-viewer
07b358f
beesu
07b358f
chkrootkit
07b358f
driftnet
07b358f
drobo-utils-gui
07b358f
hddtemp
07b358f
mate-system-log
07b358f
mock
07b358f
pure-ftpd
07b358f
setuptool
07b358f
subscription-manager
07b358f
system-config-httpd
07b358f
system-config-rootpassword
07b358f
system-switch-java
07b358f
system-switch-mail
07b358f
usermode-gtk
07b358f
vpnc-consoleuser
07b358f
wifi-radar
07b358f
xawtv
07b358f
---
07b358f
 man/systemd.exec.xml  | 35 +++++++++++++++++++++--------------
07b358f
 src/basic/path-util.h |  8 ++++++++
07b358f
 src/core/manager.c    | 23 +++++++++++++++++++----
07b358f
 3 files changed, 48 insertions(+), 18 deletions(-)
07b358f
07b358f
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
07b358f
index fbbfd4f5146..5cb83afa578 100644
07b358f
--- a/man/systemd.exec.xml
07b358f
+++ b/man/systemd.exec.xml
07b358f
@@ -2152,16 +2152,17 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
07b358f
       <varlistentry>
07b358f
         <term><varname>LogExtraFields=</varname></term>
07b358f
 
07b358f
-        <listitem><para>Configures additional log metadata fields to include in all log records generated by processes
07b358f
-        associated with this unit. This setting takes one or more journal field assignments in the format
07b358f
-        <literal>FIELD=VALUE</literal> separated by whitespace. See
07b358f
-        <citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
07b358f
-        details on the journal field concept. Even though the underlying journal implementation permits binary field
07b358f
-        values, this setting accepts only valid UTF-8 values. To include space characters in a journal field value,
07b358f
-        enclose the assignment in double quotes ("). The usual specifiers are expanded in all assignments (see
07b358f
-        below). Note that this setting is not only useful for attaching additional metadata to log records of a unit,
07b358f
-        but given that all fields and values are indexed may also be used to implement cross-unit log record
07b358f
-        matching. Assign an empty string to reset the list.</para></listitem>
07b358f
+        <listitem><para>Configures additional log metadata fields to include in all log records generated by
07b358f
+        processes associated with this unit. This setting takes one or more journal field assignments in the
07b358f
+        format <literal>FIELD=VALUE</literal> separated by whitespace. See
07b358f
+        <citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>
07b358f
+        for details on the journal field concept. Even though the underlying journal implementation permits
07b358f
+        binary field values, this setting accepts only valid UTF-8 values. To include space characters in a
07b358f
+        journal field value, enclose the assignment in double quotes ("). 
07b358f
+        The usual specifiers are expanded in all assignments (see below). Note that this setting is not only
07b358f
+        useful for attaching additional metadata to log records of a unit, but given that all fields and
07b358f
+        values are indexed may also be used to implement cross-unit log record matching. Assign an empty
07b358f
+        string to reset the list.</para></listitem>
07b358f
       </varlistentry>
07b358f
 
07b358f
       <varlistentry>
07b358f
@@ -2355,10 +2356,16 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
07b358f
       <varlistentry>
07b358f
         <term><varname>$PATH</varname></term>
07b358f
 
07b358f
-        <listitem><para>Colon-separated list of directories to use
07b358f
-        when launching executables. systemd uses a fixed value of
07b358f
-        <filename>/usr/local/sbin</filename>:<filename>/usr/local/bin</filename>:<filename>/usr/sbin</filename>:<filename>/usr/bin</filename>:<filename>/sbin</filename>:<filename>/bin</filename>.
07b358f
-        </para></listitem>
07b358f
+        <listitem><para>Colon-separated list of directories to use when launching
07b358f
+        executables. <command>systemd</command> uses a fixed value of
07b358f
+        <literal><filename>/usr/local/sbin</filename>:<filename>/usr/local/bin</filename>:<filename>/usr/sbin</filename>:<filename>/usr/bin</filename></literal>
07b358f
+        in the system manager. When compiled for systems with "unmerged /usr" (<filename>/bin</filename> is
07b358f
+        not a symlink to <filename>/usr/bin</filename>),
07b358f
+        <literal>:<filename>/sbin</filename>:<filename>/bin</filename></literal> is appended. In case of the
07b358f
+        the user manager, each <filename>bin/</filename> and <filename>sbin/</filename> pair is switched, so
07b358f
+        that programs from <filename>/usr/bin</filename> have higher priority than programs from
07b358f
+        <filename>/usr/sbin</filename>, etc. It is recommended to not rely on this in any way, and have only
07b358f
+        one program with a given name in <varname>$PATH</varname>.</para></listitem>
07b358f
       </varlistentry>
07b358f
 
07b358f
       <varlistentry>
07b358f
diff --git a/src/basic/path-util.h b/src/basic/path-util.h
07b358f
index 1f46cd65c96..71fb7041a3c 100644
07b358f
--- a/src/basic/path-util.h
07b358f
+++ b/src/basic/path-util.h
07b358f
@@ -11,30 +11,38 @@
07b358f
 #include "time-util.h"
07b358f
 
07b358f
 #define PATH_SPLIT_SBIN_BIN(x) x "sbin:" x "bin"
07b358f
+#define PATH_SPLIT_BIN_SBIN(x) x "bin:" x "sbin"
07b358f
 #define PATH_SPLIT_SBIN_BIN_NULSTR(x) x "sbin\0" x "bin\0"
07b358f
 
07b358f
 #define PATH_NORMAL_SBIN_BIN(x) x "bin"
07b358f
+#define PATH_NORMAL_BIN_SBIN(x) x "bin"
07b358f
 #define PATH_NORMAL_SBIN_BIN_NULSTR(x) x "bin\0"
07b358f
 
07b358f
 #if HAVE_SPLIT_BIN
07b358f
 #  define PATH_SBIN_BIN(x) PATH_SPLIT_SBIN_BIN(x)
07b358f
+#  define PATH_BIN_SBIN(x) PATH_SPLIT_BIN_SBIN(x)
07b358f
 #  define PATH_SBIN_BIN_NULSTR(x) PATH_SPLIT_SBIN_BIN_NULSTR(x)
07b358f
 #else
07b358f
 #  define PATH_SBIN_BIN(x) PATH_NORMAL_SBIN_BIN(x)
07b358f
+#  define PATH_BIN_SBIN(x) PATH_NORMAL_BIN_SBIN(x)
07b358f
 #  define PATH_SBIN_BIN_NULSTR(x) PATH_NORMAL_SBIN_BIN_NULSTR(x)
07b358f
 #endif
07b358f
 
07b358f
 #define DEFAULT_PATH_NORMAL PATH_SBIN_BIN("/usr/local/") ":" PATH_SBIN_BIN("/usr/")
07b358f
+#define DEFAULT_USER_PATH_NORMAL PATH_BIN_SBIN("/usr/local/") ":" PATH_BIN_SBIN("/usr/")
07b358f
 #define DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/usr/local/") PATH_SBIN_BIN_NULSTR("/usr/")
07b358f
 #define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_SBIN_BIN("/")
07b358f
+#define DEFAULT_USER_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_BIN_SBIN("/")
07b358f
 #define DEFAULT_PATH_SPLIT_USR_NULSTR DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/")
07b358f
 #define DEFAULT_PATH_COMPAT PATH_SPLIT_SBIN_BIN("/usr/local/") ":" PATH_SPLIT_SBIN_BIN("/usr/") ":" PATH_SPLIT_SBIN_BIN("/")
07b358f
 
07b358f
 #if HAVE_SPLIT_USR
07b358f
 #  define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR
07b358f
+#  define DEFAULT_USER_PATH DEFAULT_USER_PATH_SPLIT_USR
07b358f
 #  define DEFAULT_PATH_NULSTR DEFAULT_PATH_SPLIT_USR_NULSTR
07b358f
 #else
07b358f
 #  define DEFAULT_PATH DEFAULT_PATH_NORMAL
07b358f
+#  define DEFAULT_USER_PATH DEFAULT_USER_PATH_NORMAL
07b358f
 #  define DEFAULT_PATH_NULSTR DEFAULT_PATH_NORMAL_NULSTR
07b358f
 #endif
07b358f
 
07b358f
diff --git a/src/core/manager.c b/src/core/manager.c
07b358f
index 8d691a19c3d..91a601e8fd8 100644
07b358f
--- a/src/core/manager.c
07b358f
+++ b/src/core/manager.c
07b358f
@@ -603,6 +603,8 @@ static char** sanitize_environment(char **l) {
07b358f
 }
07b358f
 
07b358f
 int manager_default_environment(Manager *m) {
07b358f
+        int r;
07b358f
+
07b358f
         assert(m);
07b358f
 
07b358f
         m->transient_environment = strv_free(m->transient_environment);
07b358f
@@ -616,16 +618,29 @@ int manager_default_environment(Manager *m) {
07b358f
                  * /proc/self/environ valid; it is used for tagging
07b358f
                  * the init process inside containers. */
07b358f
                 m->transient_environment = strv_new("PATH=" DEFAULT_PATH);
07b358f
+                if (!m->transient_environment)
07b358f
+                        return log_oom();
07b358f
 
07b358f
                 /* Import locale variables LC_*= from configuration */
07b358f
                 (void) locale_setup(&m->transient_environment);
07b358f
-        } else
07b358f
+        } else {
07b358f
+                _cleanup_free_ char *k = NULL;
07b358f
+
07b358f
                 /* The user manager passes its own environment
07b358f
-                 * along to its children. */
07b358f
+                 * along to its children, except for $PATH. */
07b358f
                 m->transient_environment = strv_copy(environ);
07b358f
+                if (!m->transient_environment)
07b358f
+                        return log_oom();
07b358f
 
07b358f
-        if (!m->transient_environment)
07b358f
-                return log_oom();
07b358f
+                k = strdup("PATH=" DEFAULT_USER_PATH);
07b358f
+                if (!k)
07b358f
+                        return log_oom();
07b358f
+
07b358f
+                r = strv_env_replace(&m->transient_environment, k);
07b358f
+                if (r < 0)
07b358f
+                        return log_oom();
07b358f
+                TAKE_PTR(k);
07b358f
+        }
07b358f
 
07b358f
         sanitize_environment(m->transient_environment);
07b358f