// Copyright 2009 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifdef UNSAFE_BUFFERS_BUILD // TODO(crbug.com/40284755): Remove this and spanify to fix the errors. #pragma allow_unsafe_buffers #endif // This file implements BSD-style setproctitle() for Linux. // It is written such that it can easily be compiled outside Chromium. // // The Linux kernel sets up two locations in memory to pass arguments and // environment variables to processes. First, there are two char* arrays stored // one after another: argv and environ. A pointer to argv is passed to main(), // while glibc sets the global variable |environ| to point at the latter. Both // of these arrays are terminated by a null pointer; the environment array is // also followed by some empty space to allow additional variables to be added. // // These arrays contain pointers to a second location in memory, where the // strings themselves are stored one after another: first all the arguments, // then the environment variables. // // When the kernel reads the command line arguments for a process, it looks at // the range of memory that it initially used for the argument list. If the // terminating '\0' character is still where it expects, nothing further is // done. If it has been overwritten, the kernel will scan up to the size of // a page looking for another. // // Thus to change the process title, we must move any environment variables out // of the way to make room for a potentially longer title, and then overwrite // the memory pointed to by argv[0] with a single replacement string, making // sure its size does not exceed the available space. // // See the following kernel commit for the details of the contract between // kernel and setproctitle: // https://github.com/torvalds/linux/commit/2954152298c37804dab49d630aa959625b50cf64 // // It is perhaps worth noting that patches to add a system call to Linux for // this, like in BSD, have never made it in: this is the "official" way to do // this on Linux. Presumably it is not in glibc due to some disagreement over // this position within the glibc project, leaving applications caught in the // middle. (Also, only a very few applications need or want this anyway.) #include "base/process/set_process_title_linux.h" #include <stdarg.h> #include <stddef.h> #include <stdint.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <string> #include <vector> #include "base/files/file_util.h" #include "base/no_destructor.h" #include "base/numerics/safe_conversions.h" extern char** environ; // g_orig_argv0 is the original process name found in argv[0]. // It is set to a copy of argv[0] in setproctitle_init. It is nullptr if // setproctitle_init was unsuccessful or not called. static const char* g_orig_argv0 = …; // Following pointers hold the initial argv/envp memory range. // They are initialized in setproctitle_init and are used to overwrite the // argv/envp memory range with a new process title to be read by the kernel. // They are nullptr if setproctitle_init was unsuccessful or not called. // Note that g_envp_start is not necessary because it is the same as g_argv_end. static char* g_argv_start = …; static char* g_argv_end = …; static char* g_envp_end = …; void setproctitle(const char* fmt, ...) { … } // A version of this built into glibc would not need this function, since // it could stash the argv pointer in __libc_start_main(). But we need it. void setproctitle_init(const char** main_argv) { … }