1
0
mirror of https://github.com/systemd/systemd synced 2025-11-18 16:24:44 +01:00

Compare commits

..

2 Commits

Author SHA1 Message Date
Yu Watanabe
f03b49b079 core/exec-invoke: relax restriction for process name length
Previously, we limit the length of process name by 8.
This relax the restriction then at least process comm or
program_invocation_name contains the untrucated process name.

Closes #38367.
2025-10-25 18:50:32 +02:00
Yu Watanabe
44b4caad6c test: extend start limit interval
As the modified service requires about ~10 seconds for stopping, the
service never hit the start limit even if we tried to restart the
service more than 5 times.

This also checks that the service is actually triggered by dbus method
call.

Follow-up for 8eefd0f4debc0bcfeea89dd39c43e3318f3f7ae7.
2025-10-25 22:23:59 +09:00
4 changed files with 42 additions and 36 deletions

View File

@ -172,18 +172,19 @@ static int update_argv(const char name[], size_t l) {
return 0; return 0;
} }
int rename_process(const char name[]) { int rename_process_full(const char *comm, const char *invocation) {
bool truncated = false; bool truncated = false;
/* This is a like a poor man's setproctitle(). It changes the comm field, argv[0], and also the glibc's /* This is a like a poor man's setproctitle(). It changes the comm field by the name specified by
* internally used name of the process. For the first one a limit of 16 chars applies; to the second one in * 'comm', and changes argv[0] and the glibc's internally used names of the process
* many cases one of 10 (i.e. length of "/sbin/init") however if we have CAP_SYS_RESOURCES it is unbounded; * (program_invocation_name and program_invocation_short_name) by the name specified by 'invocation'.
* to the third one 7 (i.e. the length of "systemd". If you pass a longer string it will likely be * For the first one a limit of 16 chars applies; to the second one in many cases one of 10 (i.e.
* truncated. * length of "/sbin/init") however if we have CAP_SYS_RESOURCES it is unbounded; to the third one
* 7 (i.e. the length of "systemd". If you pass a longer string it will likely be truncated.
* *
* Returns 0 if a name was set but truncated, > 0 if it was set but not truncated. */ * Returns 0 if a name was set but truncated, > 0 if it was set but not truncated. */
if (isempty(name)) if (isempty(comm))
return -EINVAL; /* let's not confuse users unnecessarily with an empty name */ return -EINVAL; /* let's not confuse users unnecessarily with an empty name */
if (!is_main_thread()) if (!is_main_thread())
@ -191,21 +192,27 @@ int rename_process(const char name[]) {
* cache things without locking, and we make assumptions that PR_SET_NAME sets the * cache things without locking, and we make assumptions that PR_SET_NAME sets the
* process name that isn't correct on any other threads */ * process name that isn't correct on any other threads */
size_t l = strlen(name); size_t l = strlen(comm);
/* First step, change the comm field. The main thread's comm is identical to the process comm. This means we /* First step, change the comm field. The main thread's comm is identical to the process comm. This means we
* can use PR_SET_NAME, which sets the thread name for the calling thread. */ * can use PR_SET_NAME, which sets the thread name for the calling thread. */
if (prctl(PR_SET_NAME, name) < 0) if (prctl(PR_SET_NAME, comm) < 0)
log_debug_errno(errno, "PR_SET_NAME failed: %m"); log_debug_errno(errno, "PR_SET_NAME failed: %m");
if (l >= TASK_COMM_LEN) /* Linux userspace process names can be 15 chars at max */ if (l >= TASK_COMM_LEN) /* Linux userspace process names can be 15 chars at max */
truncated = true; truncated = true;
/* If nothing specified, fall back to comm. */
if (isempty(invocation))
invocation = comm;
l = strlen(invocation);
/* Second step, change glibc's ID of the process name. */ /* Second step, change glibc's ID of the process name. */
if (program_invocation_name) { if (program_invocation_name) {
size_t k; size_t k;
k = strlen(program_invocation_name); k = strlen(program_invocation_name);
strncpy(program_invocation_name, name, k); strncpy(program_invocation_name, invocation, k);
if (l > k) if (l > k)
truncated = true; truncated = true;
@ -217,7 +224,7 @@ int rename_process(const char name[]) {
/* Third step, completely replace the argv[] array the kernel maintains for us. This requires privileges, but /* 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 * 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. */ * the end. This is the best option for changing /proc/self/cmdline. */
(void) update_argv(name, l); (void) update_argv(invocation, l);
/* Fourth step: in all cases we'll also update the original argv[], so that our own code gets it right too if /* 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 */ * it still looks here */
@ -226,7 +233,7 @@ int rename_process(const char name[]) {
size_t k; size_t k;
k = strlen(saved_argv[0]); k = strlen(saved_argv[0]);
strncpy(saved_argv[0], name, k); strncpy(saved_argv[0], invocation, k);
if (l > k) if (l > k)
truncated = true; truncated = true;
} }

View File

@ -12,4 +12,7 @@ bool invoked_as(char *argv[], const char *token);
bool invoked_by_systemd(void); bool invoked_by_systemd(void);
bool argv_looks_like_help(int argc, char **argv); bool argv_looks_like_help(int argc, char **argv);
int rename_process(const char name[]); int rename_process_full(const char *comm, const char *invocation);
static inline int rename_process(const char *name) {
return rename_process_full(name, name);
}

View File

@ -1490,35 +1490,30 @@ fail:
} }
static void rename_process_from_path(const char *path) { static void rename_process_from_path(const char *path) {
_cleanup_free_ char *buf = NULL; int r;
const char *p;
assert(path); assert(path);
/* This resulting string must fit in 10 chars (i.e. the length of "/sbin/init") to look pretty in _cleanup_free_ char *buf = NULL;
* /bin/ps */ r = path_extract_filename(path, &buf);
if (r < 0) {
if (path_extract_filename(path, &buf) < 0) { log_debug_errno(r, "Failed to extract file name from '%s', ignoring: %m", path);
rename_process("(...)"); return (void) rename_process("(...)");
return;
} }
size_t l = strlen(buf); size_t len = strlen(buf);
if (l > 8) { char comm[TASK_COMM_LEN], *p = comm;
/* The end of the process name is usually more interesting, since the first bit might just be *p++ = '(';
* "systemd-" */ p = mempcpy(p, buf + LESS_BY(len, (size_t) (TASK_COMM_LEN - 3)), MIN(len, (size_t) (TASK_COMM_LEN - 3)));
p = buf + l - 8; *p++ = ')';
l = 8; *p = '\0';
} else
p = buf;
char process_name[11]; size_t len_invocation = program_invocation_name ? strlen(program_invocation_name) : SIZE_MAX;
process_name[0] = '('; _cleanup_free_ char *invocation = strjoin("(", buf + LESS_BY(len, len_invocation - 2), ")");
memcpy(process_name+1, p, l); if (!invocation)
process_name[1+l] = ')'; log_oom_debug();
process_name[1+l+1] = 0;
(void) rename_process(process_name); (void) rename_process_full(comm, invocation ?: comm);
} }
static bool context_has_address_families(const ExecContext *c) { static bool context_has_address_families(const ExecContext *c) {

View File

@ -19,7 +19,7 @@ mkdir -p /run/systemd/system/systemd-resolved.service.d/
cat >/run/systemd/system/systemd-resolved.service.d/99-start-limit.conf <<EOF cat >/run/systemd/system/systemd-resolved.service.d/99-start-limit.conf <<EOF
[Unit] [Unit]
StartLimitBurst=5 StartLimitBurst=5
StartLimitInterval=30 StartLimitInterval=100
[Service] [Service]
ExecStopPost=sleep 10 ExecStopPost=sleep 10
@ -39,4 +39,5 @@ for i in {1..5}; do
journalctl -o short-monotonic --no-hostname --no-pager -u systemd-resolved.service -n 15 journalctl -o short-monotonic --no-hostname --no-pager -u systemd-resolved.service -n 15
exit 1 exit 1
fi fi
systemctl is-active systemd-resolved.service
done done