1
0
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:
Zbigniew Jędrzejewski-Szmek
2016-12-17 13:36:00 -05:00
committed by GitHub
16 changed files with 307 additions and 89 deletions

View File

@ -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

View File

@ -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
View File

@ -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:

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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;
} }

View File

@ -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);

View File

@ -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;
} }