mirror of
https://github.com/systemd/systemd.git
synced 2025-08-30 05:49:54 +03:00
Merge pull request #4845 from poettering/various-smaller-fixes
Various smaller fixes
This commit is contained in:
@ -27,7 +27,7 @@ Format=raw_btrfs
|
|||||||
Bootable=yes
|
Bootable=yes
|
||||||
|
|
||||||
[Partitions]
|
[Partitions]
|
||||||
RootSize=2G
|
RootSize=3G
|
||||||
|
|
||||||
[Packages]
|
[Packages]
|
||||||
BuildPackages=
|
BuildPackages=
|
||||||
@ -37,6 +37,7 @@ BuildPackages=
|
|||||||
bzip2-devel
|
bzip2-devel
|
||||||
cryptsetup-devel
|
cryptsetup-devel
|
||||||
dbus-devel
|
dbus-devel
|
||||||
|
diffutils
|
||||||
docbook-style-xsl
|
docbook-style-xsl
|
||||||
elfutils-devel
|
elfutils-devel
|
||||||
gcc
|
gcc
|
||||||
@ -69,4 +70,5 @@ BuildPackages=
|
|||||||
python3-devel
|
python3-devel
|
||||||
python3-lxml
|
python3-lxml
|
||||||
qrencode-devel
|
qrencode-devel
|
||||||
|
tree
|
||||||
xz-devel
|
xz-devel
|
||||||
|
@ -149,7 +149,8 @@ TESTS =
|
|||||||
endif
|
endif
|
||||||
AM_TESTS_ENVIRONMENT = \
|
AM_TESTS_ENVIRONMENT = \
|
||||||
export SYSTEMD_KBD_MODEL_MAP=$(abs_top_srcdir)/src/locale/kbd-model-map; \
|
export SYSTEMD_KBD_MODEL_MAP=$(abs_top_srcdir)/src/locale/kbd-model-map; \
|
||||||
export SYSTEMD_LANGUAGE_FALLBACK_MAP=$(abs_top_srcdir)/src/locale/language-fallback-map;
|
export SYSTEMD_LANGUAGE_FALLBACK_MAP=$(abs_top_srcdir)/src/locale/language-fallback-map; \
|
||||||
|
export PATH=$(abs_top_builddir):$$PATH;
|
||||||
|
|
||||||
if ENABLE_BASH_COMPLETION
|
if ENABLE_BASH_COMPLETION
|
||||||
dist_bashcompletion_DATA = $(dist_bashcompletion_data)
|
dist_bashcompletion_DATA = $(dist_bashcompletion_data)
|
||||||
|
37
TODO
37
TODO
@ -12,9 +12,6 @@ Bugfixes:
|
|||||||
Environment=ONE='one' "TWO='two two' too" THREE=
|
Environment=ONE='one' "TWO='two two' too" THREE=
|
||||||
ExecStart=/bin/python3 -c 'import sys;print(sys.argv)' $ONE $TWO $THREE
|
ExecStart=/bin/python3 -c 'import sys;print(sys.argv)' $ONE $TWO $THREE
|
||||||
|
|
||||||
* When systemctl --host is used, underlying ssh connection can remain open.
|
|
||||||
bus_close does not kill children?
|
|
||||||
|
|
||||||
External:
|
External:
|
||||||
|
|
||||||
* Fedora: add an rpmlint check that verifies that all unit files in the RPM are listed in %systemd_post macros.
|
* Fedora: add an rpmlint check that verifies that all unit files in the RPM are listed in %systemd_post macros.
|
||||||
@ -34,6 +31,38 @@ Features:
|
|||||||
* replace all canonicalize_file_name() invocations by chase_symlinks(), in
|
* replace all canonicalize_file_name() invocations by chase_symlinks(), in
|
||||||
particulr those where a rootdir is relevant.
|
particulr those where a rootdir is relevant.
|
||||||
|
|
||||||
|
* maybe introduce gpt auto discovery for /var/tmp?
|
||||||
|
|
||||||
|
* set ProtectSystem=strict for all our usual services.
|
||||||
|
|
||||||
|
* maybe add gpt-partition-based user management: each user gets his own
|
||||||
|
LUKS-encrypted GPT partition with a new GPT type. A small nss module
|
||||||
|
enumerates users via udev partition enumeration. UIDs are assigned in a fixed
|
||||||
|
way: the partition index is added as offset to some fixed base uid. User name
|
||||||
|
is stored in GPT partition name. A PAM module authenticates the user via the
|
||||||
|
LUKS partition password. Benefits: strong per-user security, compatibility
|
||||||
|
with stateless/read-only/verity-enabled root. (other idea: do this based on
|
||||||
|
loopback files in /home, without GPT involvement)
|
||||||
|
|
||||||
|
* gpt-auto logic: introduce support for discovering /var matching an image. For
|
||||||
|
that, use a partition type UUID that is hashed from the OS name (as encoded
|
||||||
|
in /etc/os-release), the architecture, and 4 new bits from the gpt flags
|
||||||
|
field of the root partition. This way can easily support multiple OS
|
||||||
|
installations on the same GPT partition table, without problems with
|
||||||
|
unmatched /var partitions.
|
||||||
|
|
||||||
|
* gpt-auto logic: related to the above, maybe support a "secondary" root
|
||||||
|
partition, that is mounted to / and is writable, and where the actual root's
|
||||||
|
/usr is mounted into.
|
||||||
|
|
||||||
|
* add dm-verity boots, and in nspawn (libcryptsetup knows this, should be relatively straight-forward)
|
||||||
|
|
||||||
|
* machined: add apis to query /etc/machine-info data of a container
|
||||||
|
|
||||||
|
* .mount and .swap units: add Format=yes|no option that formats the partition before mounting/enabling it, implicitly
|
||||||
|
|
||||||
|
* gpt-auto logic: support encrypted swap, add kernel cmdline option to force it, and honour a gpt bit about it, plus maybe a configuration file
|
||||||
|
|
||||||
* drop nss-myhostname in favour of nss-resolve?
|
* drop nss-myhostname in favour of nss-resolve?
|
||||||
|
|
||||||
* drop internal dlopen() based nss-dns fallback in nss-resolve, and rely on the
|
* drop internal dlopen() based nss-dns fallback in nss-resolve, and rely on the
|
||||||
@ -279,8 +308,6 @@ Features:
|
|||||||
* For timer units: add some mechanisms so that timer units that trigger immediately on boot do not have the services
|
* For timer units: add some mechanisms so that timer units that trigger immediately on boot do not have the services
|
||||||
they run added to the initial transaction and thus confuse Type=idle.
|
they run added to the initial transaction and thus confuse Type=idle.
|
||||||
|
|
||||||
* Run most system services with cgroupfs read-only and procfs with a more secure mode (doesn't work, since the hidepid= option is per-pid-namespace, not per-mount)
|
|
||||||
|
|
||||||
* add bus api to query unit file's X fields.
|
* add bus api to query unit file's X fields.
|
||||||
|
|
||||||
* gpt-auto-generator:
|
* gpt-auto-generator:
|
||||||
|
@ -189,10 +189,9 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(
|
|||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Return Value</title>
|
<title>Return Value</title>
|
||||||
|
|
||||||
<para>The four calls return 0 on success or a negative errno-style
|
<para>The five calls return 0 on success or a negative errno-style error code. The <citerefentry
|
||||||
error code. The
|
project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry> variable itself is
|
||||||
<citerefentry project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
not altered.</para>
|
||||||
variable itself is not altered.</para>
|
|
||||||
|
|
||||||
<para>If
|
<para>If
|
||||||
<citerefentry><refentrytitle>systemd-journald</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
<citerefentry><refentrytitle>systemd-journald</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
@ -218,13 +217,11 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(
|
|||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Notes</title>
|
<title>Notes</title>
|
||||||
|
|
||||||
<para>The <function>sd_journal_print()</function>,
|
<para>The <function>sd_journal_print()</function>, <function>sd_journal_printv()</function>,
|
||||||
<function>sd_journal_printv()</function>,
|
<function>sd_journal_send()</function>, <function>sd_journal_sendv()</function> and
|
||||||
<function>sd_journal_send()</function> and
|
<function>sd_journal_perror()</function> interfaces are available as a shared library, which can be compiled and
|
||||||
<function>sd_journal_sendv()</function> interfaces are available
|
linked to with the <constant>libsystemd</constant> <citerefentry
|
||||||
as a shared library, which can be compiled and linked to with the
|
project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
|
||||||
<constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
|
||||||
file.</para>
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
@ -882,17 +882,21 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
|
|||||||
<term><command>show</command> <optional><replaceable>PATTERN</replaceable>…|<replaceable>JOB</replaceable>…</optional></term>
|
<term><command>show</command> <optional><replaceable>PATTERN</replaceable>…|<replaceable>JOB</replaceable>…</optional></term>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>Show properties of one or more units, jobs, or the
|
<para>Show properties of one or more units, jobs, or the manager itself. If no argument is specified,
|
||||||
manager itself. If no argument is specified, properties of
|
properties of the manager will be shown. If a unit name is specified, properties of the unit are shown, and
|
||||||
the manager will be shown. If a unit name is specified,
|
if a job ID is specified, properties of the job are shown. By default, empty properties are suppressed. Use
|
||||||
properties of the unit are shown, and if a job ID is
|
<option>--all</option> to show those too. To select specific properties to show, use
|
||||||
specified, properties of the job are shown. By default, empty
|
<option>--property=</option>. This command is intended to be used whenever computer-parsable output is
|
||||||
properties are suppressed. Use <option>--all</option> to
|
required. Use <command>status</command> if you are looking for formatted human-readable output.</para>
|
||||||
show those too. To select specific properties to show, use
|
|
||||||
<option>--property=</option>. This command is intended to be
|
<para>Many properties shown by <command>systemctl show</command> map directly to configuration settings of
|
||||||
used whenever computer-parsable output is required. Use
|
the system and service manager and its unit files. Note that the properties shown by the command are
|
||||||
<command>status</command> if you are looking for formatted
|
generally more low-level, normalized versions of the original configuration settings and expose runtime
|
||||||
human-readable output.</para>
|
state in addition to configuration. For example, properties shown for service units include the service's
|
||||||
|
current main process identifier as <literal>MainPID</literal> (which is runtime state), and time settings
|
||||||
|
are always exposed as properties ending in the <literal>…USec</literal> suffix even if a matching
|
||||||
|
configuration options end in <literal>…Sec</literal>, because microseconds is the normalized time unit used
|
||||||
|
by the system and service manager.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
10
mkosi.build
10
mkosi.build
@ -22,4 +22,14 @@
|
|||||||
|
|
||||||
./autogen.sh c
|
./autogen.sh c
|
||||||
make -j `nproc`
|
make -j `nproc`
|
||||||
|
|
||||||
|
make check
|
||||||
make install
|
make install
|
||||||
|
|
||||||
|
mkdir -p $DESTDIR/etc
|
||||||
|
|
||||||
|
cat > $DESTDIR/etc/issue <<EOF
|
||||||
|
\S (built from systemd tree)
|
||||||
|
Kernel \r on an \m (\l)
|
||||||
|
|
||||||
|
EOF
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
#include <sys/personality.h>
|
#include <sys/personality.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -274,27 +275,100 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rename_process(const char name[8]) {
|
int rename_process(const char name[]) {
|
||||||
assert(name);
|
static size_t mm_size = 0;
|
||||||
|
static char *mm = NULL;
|
||||||
|
bool truncated = false;
|
||||||
|
size_t l;
|
||||||
|
|
||||||
/* This is a like a poor man's setproctitle(). It changes the
|
/* This is a like a poor man's setproctitle(). It changes the comm field, argv[0], and also the glibc's
|
||||||
* comm field, argv[0], and also the glibc's internally used
|
* internally used name of the process. For the first one a limit of 16 chars applies; to the second one in
|
||||||
* name of the process. For the first one a limit of 16 chars
|
* many cases one of 10 (i.e. length of "/sbin/init") — however if we have CAP_SYS_RESOURCES it is unbounded;
|
||||||
* applies, to the second one usually one of 10 (i.e. length
|
* to the third one 7 (i.e. the length of "systemd". If you pass a longer string it will likely be
|
||||||
* of "/sbin/init"), to the third one one of 7 (i.e. length of
|
* truncated.
|
||||||
* "systemd"). If you pass a longer string it will be
|
*
|
||||||
* truncated */
|
* Returns 0 if a name was set but truncated, > 0 if it was set but not truncated. */
|
||||||
|
|
||||||
|
if (isempty(name))
|
||||||
|
return -EINVAL; /* let's not confuse users unnecessarily with an empty name */
|
||||||
|
|
||||||
|
l = strlen(name);
|
||||||
|
|
||||||
|
/* First step, change the comm field. */
|
||||||
(void) prctl(PR_SET_NAME, name);
|
(void) prctl(PR_SET_NAME, name);
|
||||||
|
if (l > 15) /* Linux process names can be 15 chars at max */
|
||||||
|
truncated = true;
|
||||||
|
|
||||||
if (program_invocation_name)
|
/* Second step, change glibc's ID of the process name. */
|
||||||
strncpy(program_invocation_name, name, strlen(program_invocation_name));
|
if (program_invocation_name) {
|
||||||
|
size_t k;
|
||||||
|
|
||||||
|
k = strlen(program_invocation_name);
|
||||||
|
strncpy(program_invocation_name, name, k);
|
||||||
|
if (l > k)
|
||||||
|
truncated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Third step, completely replace the argv[] array the kernel maintains for us. This requires privileges, but
|
||||||
|
* has the advantage that the argv[] array is exactly what we want it to be, and not filled up with zeros at
|
||||||
|
* the end. This is the best option for changing /proc/self/cmdline.*/
|
||||||
|
if (mm_size < l+1) {
|
||||||
|
size_t nn_size;
|
||||||
|
char *nn;
|
||||||
|
|
||||||
|
/* Let's not bother with this if we don't have euid == 0. Strictly speaking if people do weird stuff
|
||||||
|
* with capabilities this could work even for euid != 0, but our own code generally doesn't do that,
|
||||||
|
* hence let's use this as quick bypass check, to avoid calling mmap() if PR_SET_MM_ARG_START fails
|
||||||
|
* with EPERM later on anyway. After all geteuid() is dead cheap to call, but mmap() is not. */
|
||||||
|
if (geteuid() != 0) {
|
||||||
|
log_debug("Skipping PR_SET_MM_ARG_START, as we don't have privileges.");
|
||||||
|
goto use_saved_argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_size = PAGE_ALIGN(l+1);
|
||||||
|
nn = mmap(NULL, nn_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||||
|
if (nn == MAP_FAILED) {
|
||||||
|
log_debug_errno(errno, "mmap() failed: %m");
|
||||||
|
goto use_saved_argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(nn, name, nn_size);
|
||||||
|
|
||||||
|
/* Now, let's tell the kernel about this new memory */
|
||||||
|
if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) {
|
||||||
|
log_debug_errno(errno, "PR_SET_MM_ARG_START failed, proceeding without: %m");
|
||||||
|
(void) munmap(nn, nn_size);
|
||||||
|
goto use_saved_argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And update the end pointer to the new end, too. If this fails, we don't really know what to do, it's
|
||||||
|
* pretty unlikely that we can rollback, hence we'll just accept the failure, and continue. */
|
||||||
|
if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0)
|
||||||
|
log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
|
||||||
|
|
||||||
|
if (mm)
|
||||||
|
(void) munmap(mm, mm_size);
|
||||||
|
|
||||||
|
mm = nn;
|
||||||
|
mm_size = nn_size;
|
||||||
|
} else
|
||||||
|
strncpy(mm, name, mm_size);
|
||||||
|
|
||||||
|
use_saved_argv:
|
||||||
|
/* Fourth step: in all cases we'll also update the original argv[], so that our own code gets it right too if
|
||||||
|
* it still looks here */
|
||||||
|
|
||||||
if (saved_argc > 0) {
|
if (saved_argc > 0) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (saved_argv[0])
|
if (saved_argv[0]) {
|
||||||
strncpy(saved_argv[0], name, strlen(saved_argv[0]));
|
size_t k;
|
||||||
|
|
||||||
|
k = strlen(saved_argv[0]);
|
||||||
|
strncpy(saved_argv[0], name, k);
|
||||||
|
if (l > k)
|
||||||
|
truncated = true;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 1; i < saved_argc; i++) {
|
for (i = 1; i < saved_argc; i++) {
|
||||||
if (!saved_argv[i])
|
if (!saved_argv[i])
|
||||||
@ -303,6 +377,8 @@ void rename_process(const char name[8]) {
|
|||||||
memzero(saved_argv[i], strlen(saved_argv[i]));
|
memzero(saved_argv[i], strlen(saved_argv[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return !truncated;
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_kernel_thread(pid_t pid) {
|
int is_kernel_thread(pid_t pid) {
|
||||||
|
@ -64,7 +64,7 @@ void sigkill_waitp(pid_t *pid);
|
|||||||
|
|
||||||
int kill_and_sigcont(pid_t pid, int sig);
|
int kill_and_sigcont(pid_t pid, int sig);
|
||||||
|
|
||||||
void rename_process(const char name[8]);
|
int rename_process(const char name[]);
|
||||||
int is_kernel_thread(pid_t pid);
|
int is_kernel_thread(pid_t pid);
|
||||||
|
|
||||||
int getenv_for_pid(pid_t pid, const char *field, char **_value);
|
int getenv_for_pid(pid_t pid, const char *field, char **_value);
|
||||||
|
@ -409,8 +409,7 @@ int detect_container(void) {
|
|||||||
if (cached_found >= 0)
|
if (cached_found >= 0)
|
||||||
return cached_found;
|
return cached_found;
|
||||||
|
|
||||||
/* /proc/vz exists in container and outside of the container,
|
/* /proc/vz exists in container and outside of the container, /proc/bc only outside of the container. */
|
||||||
* /proc/bc only outside of the container. */
|
|
||||||
if (access("/proc/vz", F_OK) >= 0 &&
|
if (access("/proc/vz", F_OK) >= 0 &&
|
||||||
access("/proc/bc", F_OK) < 0) {
|
access("/proc/bc", F_OK) < 0) {
|
||||||
r = VIRTUALIZATION_OPENVZ;
|
r = VIRTUALIZATION_OPENVZ;
|
||||||
@ -418,50 +417,58 @@ int detect_container(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (getpid() == 1) {
|
if (getpid() == 1) {
|
||||||
/* If we are PID 1 we can just check our own
|
/* If we are PID 1 we can just check our own environment variable, and that's authoritative. */
|
||||||
* environment variable */
|
|
||||||
|
|
||||||
e = getenv("container");
|
e = getenv("container");
|
||||||
if (isempty(e)) {
|
if (isempty(e)) {
|
||||||
r = VIRTUALIZATION_NONE;
|
r = VIRTUALIZATION_NONE;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Otherwise, PID 1 dropped this information into a
|
goto translate_name;
|
||||||
* file in /run. This is better than accessing
|
|
||||||
* /proc/1/environ, since we don't need CAP_SYS_PTRACE
|
|
||||||
* for that. */
|
|
||||||
|
|
||||||
r = read_one_line_file("/run/systemd/container", &m);
|
|
||||||
if (r == -ENOENT) {
|
|
||||||
|
|
||||||
/* Fallback for cases where PID 1 was not
|
|
||||||
* systemd (for example, cases where
|
|
||||||
* init=/bin/sh is used. */
|
|
||||||
|
|
||||||
r = getenv_for_pid(1, "container", &m);
|
|
||||||
if (r <= 0) {
|
|
||||||
|
|
||||||
/* If that didn't work, give up,
|
|
||||||
* assume no container manager.
|
|
||||||
*
|
|
||||||
* Note: This means we still cannot
|
|
||||||
* detect containers if init=/bin/sh
|
|
||||||
* is passed but privileges dropped,
|
|
||||||
* as /proc/1/environ is only readable
|
|
||||||
* with privileges. */
|
|
||||||
|
|
||||||
r = VIRTUALIZATION_NONE;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
e = m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Otherwise, PID 1 might have dropped this information into a file in /run. This is better than accessing
|
||||||
|
* /proc/1/environ, since we don't need CAP_SYS_PTRACE for that. */
|
||||||
|
r = read_one_line_file("/run/systemd/container", &m);
|
||||||
|
if (r >= 0) {
|
||||||
|
e = m;
|
||||||
|
goto translate_name;
|
||||||
|
}
|
||||||
|
if (r != -ENOENT)
|
||||||
|
return log_debug_errno(r, "Failed to read /run/systemd/container: %m");
|
||||||
|
|
||||||
|
/* Fallback for cases where PID 1 was not systemd (for example, cases where init=/bin/sh is used. */
|
||||||
|
r = getenv_for_pid(1, "container", &m);
|
||||||
|
if (r > 0) {
|
||||||
|
e = m;
|
||||||
|
goto translate_name;
|
||||||
|
}
|
||||||
|
if (r < 0) /* This only works if we have CAP_SYS_PTRACE, hence let's better ignore failures here */
|
||||||
|
log_debug_errno(r, "Failed to read $container of PID 1, ignoring: %m");
|
||||||
|
|
||||||
|
/* Interestingly /proc/1/sched actually shows the host's PID for what we see as PID 1. Hence, if the PID shown
|
||||||
|
* there is not 1, we know we are in a PID namespace. and hence a container. */
|
||||||
|
r = read_one_line_file("/proc/1/sched", &m);
|
||||||
|
if (r >= 0) {
|
||||||
|
const char *t;
|
||||||
|
|
||||||
|
t = strrchr(m, '(');
|
||||||
|
if (!t)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
if (!startswith(t, "(1,")) {
|
||||||
|
r = VIRTUALIZATION_CONTAINER_OTHER;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
} else if (r != -ENOENT)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
/* If that didn't work, give up, assume no container manager. */
|
||||||
|
r = VIRTUALIZATION_NONE;
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
translate_name:
|
||||||
for (j = 0; j < ELEMENTSOF(value_table); j++)
|
for (j = 0; j < ELEMENTSOF(value_table); j++)
|
||||||
if (streq(e, value_table[j].value)) {
|
if (streq(e, value_table[j].value)) {
|
||||||
r = value_table[j].id;
|
r = value_table[j].id;
|
||||||
@ -471,7 +478,7 @@ int detect_container(void) {
|
|||||||
r = VIRTUALIZATION_CONTAINER_OTHER;
|
r = VIRTUALIZATION_CONTAINER_OTHER;
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
log_debug("Found container virtualization %s", virtualization_to_string(r));
|
log_debug("Found container virtualization %s.", virtualization_to_string(r));
|
||||||
cached_found = r;
|
cached_found = r;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -2318,7 +2318,7 @@ int main(int argc, char *argv[]) {
|
|||||||
if (arg_boot_offset != 0 &&
|
if (arg_boot_offset != 0 &&
|
||||||
sd_journal_has_runtime_files(j) > 0 &&
|
sd_journal_has_runtime_files(j) > 0 &&
|
||||||
sd_journal_has_persistent_files(j) == 0) {
|
sd_journal_has_persistent_files(j) == 0) {
|
||||||
log_info("Specifying boot ID has no effect, no persistent journal was found");
|
log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
|
||||||
r = 0;
|
r = 0;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
@ -2769,7 +2769,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
assert(argv);
|
assert(argv);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
static const char option_string[] = "-hp:als:H:M:qn:o:";
|
static const char option_string[] = "-hp:als:H:M:qn:o:E:";
|
||||||
|
|
||||||
c = getopt_long(argc, argv, option_string + reorder, options, NULL);
|
c = getopt_long(argc, argv, option_string + reorder, options, NULL);
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <sys/reboot.h>
|
#include <sys/reboot.h>
|
||||||
#include <sys/unistd.h>
|
#include <sys/unistd.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
@ -29,7 +30,22 @@
|
|||||||
#include "time-util.h"
|
#include "time-util.h"
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
|
|
||||||
int stub_pid1(void) {
|
static int reset_environ(const char *new_environment, size_t length) {
|
||||||
|
unsigned long start, end;
|
||||||
|
|
||||||
|
start = (unsigned long) new_environment;
|
||||||
|
end = start + length;
|
||||||
|
|
||||||
|
if (prctl(PR_SET_MM, PR_SET_MM_ENV_START, start, 0, 0) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
if (prctl(PR_SET_MM, PR_SET_MM_ENV_END, end, 0, 0) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stub_pid1(sd_id128_t uuid) {
|
||||||
enum {
|
enum {
|
||||||
STATE_RUNNING,
|
STATE_RUNNING,
|
||||||
STATE_REBOOT,
|
STATE_REBOOT,
|
||||||
@ -41,6 +57,11 @@ int stub_pid1(void) {
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
/* The new environment we set up, on the stack. */
|
||||||
|
char new_environment[] =
|
||||||
|
"container=systemd-nspawn\0"
|
||||||
|
"container_uuid=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
|
||||||
|
|
||||||
/* Implements a stub PID 1, that reaps all processes and processes a couple of standard signals. This is useful
|
/* Implements a stub PID 1, that reaps all processes and processes a couple of standard signals. This is useful
|
||||||
* for allowing arbitrary processes run in a container, and still have all zombies reaped. */
|
* for allowing arbitrary processes run in a container, and still have all zombies reaped. */
|
||||||
|
|
||||||
@ -64,6 +85,12 @@ int stub_pid1(void) {
|
|||||||
close_all_fds(NULL, 0);
|
close_all_fds(NULL, 0);
|
||||||
log_open();
|
log_open();
|
||||||
|
|
||||||
|
/* Flush out /proc/self/environ, so that we don't leak the environment from the host into the container. Also,
|
||||||
|
* set $container= and $container_uuid= so that clients in the container that query it from /proc/1/environ
|
||||||
|
* find them set set. */
|
||||||
|
sd_id128_to_string(uuid, new_environment + sizeof(new_environment) - SD_ID128_STRING_MAX);
|
||||||
|
reset_environ(new_environment, sizeof(new_environment));
|
||||||
|
|
||||||
rename_process("STUBINIT");
|
rename_process("STUBINIT");
|
||||||
|
|
||||||
assert_se(sigemptyset(&waitmask) >= 0);
|
assert_se(sigemptyset(&waitmask) >= 0);
|
||||||
|
@ -19,4 +19,6 @@
|
|||||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
int stub_pid1(void);
|
#include "sd-id128.h"
|
||||||
|
|
||||||
|
int stub_pid1(sd_id128_t uuid);
|
||||||
|
@ -2278,7 +2278,7 @@ static int inner_child(
|
|||||||
return log_error_errno(errno, "Failed to change to specified working directory %s: %m", arg_chdir);
|
return log_error_errno(errno, "Failed to change to specified working directory %s: %m", arg_chdir);
|
||||||
|
|
||||||
if (arg_start_mode == START_PID2) {
|
if (arg_start_mode == START_PID2) {
|
||||||
r = stub_pid1();
|
r = stub_pid1(arg_uuid);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -292,8 +292,10 @@ static int sysv_translate_facility(SysvStub *s, unsigned line, const char *name,
|
|||||||
if (!streq(table[i], n))
|
if (!streq(table[i], n))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!table[i+1])
|
if (!table[i+1]) {
|
||||||
|
*ret = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
m = strdup(table[i+1]);
|
m = strdup(table[i+1]);
|
||||||
if (!m)
|
if (!m)
|
||||||
@ -312,7 +314,7 @@ static int sysv_translate_facility(SysvStub *s, unsigned line, const char *name,
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "[%s:%u] Could not build name for facility %s: %m", s->path, line, name);
|
return log_error_errno(r, "[%s:%u] Could not build name for facility %s: %m", s->path, line, name);
|
||||||
|
|
||||||
return r;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Strip ".sh" suffix from file name for comparison */
|
/* Strip ".sh" suffix from file name for comparison */
|
||||||
@ -324,8 +326,10 @@ static int sysv_translate_facility(SysvStub *s, unsigned line, const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Names equaling the file name of the services are redundant */
|
/* Names equaling the file name of the services are redundant */
|
||||||
if (streq_ptr(n, filename))
|
if (streq_ptr(n, filename)) {
|
||||||
|
*ret = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Everything else we assume to be normal service names */
|
/* Everything else we assume to be normal service names */
|
||||||
m = sysv_translate_name(n);
|
m = sysv_translate_name(n);
|
||||||
|
@ -355,10 +355,70 @@ static void test_get_process_cmdline_harder(void) {
|
|||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_rename_process_one(const char *p, int ret) {
|
||||||
|
_cleanup_free_ char *comm = NULL, *cmdline = NULL;
|
||||||
|
pid_t pid;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
assert_se(pid >= 0);
|
||||||
|
|
||||||
|
if (pid > 0) {
|
||||||
|
siginfo_t si;
|
||||||
|
|
||||||
|
assert_se(wait_for_terminate(pid, &si) >= 0);
|
||||||
|
assert_se(si.si_code == CLD_EXITED);
|
||||||
|
assert_se(si.si_status == EXIT_SUCCESS);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* child */
|
||||||
|
r = rename_process(p);
|
||||||
|
|
||||||
|
assert_se(r == ret ||
|
||||||
|
(ret == 0 && r >= 0) ||
|
||||||
|
(ret > 0 && r > 0));
|
||||||
|
|
||||||
|
if (r < 0)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
#ifdef HAVE_VALGRIND_VALGRIND_H
|
||||||
|
/* see above, valgrind is weird, we can't verify what we are doing here */
|
||||||
|
if (RUNNING_ON_VALGRIND)
|
||||||
|
goto finish;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
assert_se(get_process_comm(0, &comm) >= 0);
|
||||||
|
log_info("comm = <%s>", comm);
|
||||||
|
assert_se(strneq(comm, p, 15));
|
||||||
|
|
||||||
|
assert_se(get_process_cmdline(0, 0, false, &cmdline) >= 0);
|
||||||
|
log_info("cmdline = <%s>", cmdline);
|
||||||
|
assert_se(strneq(p, cmdline, strlen("test-process-util")));
|
||||||
|
assert_se(startswith(p, cmdline));
|
||||||
|
|
||||||
|
finish:
|
||||||
|
_exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_rename_process(void) {
|
||||||
|
test_rename_process_one(NULL, -EINVAL);
|
||||||
|
test_rename_process_one("", -EINVAL);
|
||||||
|
test_rename_process_one("foo", 1); /* should always fit */
|
||||||
|
test_rename_process_one("this is a really really long process name, followed by some more words", 0); /* unlikely to fit */
|
||||||
|
test_rename_process_one("1234567", 1); /* should always fit */
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
log_set_max_level(LOG_DEBUG);
|
||||||
log_parse_environment();
|
log_parse_environment();
|
||||||
log_open();
|
log_open();
|
||||||
|
|
||||||
|
saved_argc = argc;
|
||||||
|
saved_argv = argv;
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
pid_t pid = 0;
|
pid_t pid = 0;
|
||||||
|
|
||||||
@ -373,6 +433,7 @@ int main(int argc, char *argv[]) {
|
|||||||
test_pid_is_alive();
|
test_pid_is_alive();
|
||||||
test_personality();
|
test_personality();
|
||||||
test_get_process_cmdline_harder();
|
test_get_process_cmdline_harder();
|
||||||
|
test_rename_process();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user