From f4b4008495211c60bda7e1edda45beb36a553bc7 Mon Sep 17 00:00:00 2001
From: licunlong<licunlong1@huawei.com>
Date: Thu, 14 Jan 2021 15:57:59 +0800
Subject: [PATCH] process-util: log more information when running
 systemctl.

 Print the PID and its cmdline to the system log when a process
 runs systemctl command.
---
 src/basic/process-util.c     | 31 +++++++++++++++++++++++++++++++
 src/basic/process-util.h     |  1 +
 src/systemctl/systemctl.c    | 12 ++++++++++++
 src/test/test-process-util.c | 22 ++++++++++++++++++++++
 4 files changed, 66 insertions(+)

diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index 4e93c9b..78ad30b 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -54,6 +54,7 @@
 #include "stdio-util.h"
 #include "string-table.h"
 #include "string-util.h"
+#include "strv.h"
 #include "terminal-util.h"
 #include "user-util.h"
 #include "utf8.h"
@@ -342,6 +343,36 @@ int pidref_get_cmdline_strv(const PidRef *pid, ProcessCmdlineFlags flags, char *
         return 0;
 }
 
+int print_process_cmdline_with_arg(pid_t pid, int argc, char *argv[], const char * const *filter) {
+      bool is_filtered = false;
+      int r;
+      const char *arg_cmdline = "[";
+      _cleanup_free_ char *cmdline = NULL;
+
+      r = pid_get_cmdline(pid, SIZE_MAX, 0, &cmdline);
+      if (r < 0) {
+              syslog(LOG_INFO, "Failed to get cmdline of PID %d. Ignoring.", pid);
+              return r;
+      } else {
+              for (int i = 0; i < argc; i++ ) {
+                      if (filter && strv_find((char * const *) filter, argv[i])) {
+                              is_filtered = true;
+                              break;
+                      }
+                      if (i == 0) {
+                              arg_cmdline = strjoina(arg_cmdline, argv[i]);
+                      } else {
+                              arg_cmdline = strjoina(arg_cmdline, " ", argv[i]);
+                      }
+              }
+              if (!is_filtered) {
+                      syslog(LOG_INFO, "%s] called by PID %d (%s)", arg_cmdline, pid, cmdline);
+              }
+              return 0;
+      }
+
+}
+
 int container_get_leader(const char *machine, pid_t *pid) {
         _cleanup_free_ char *s = NULL, *class = NULL;
         const char *p;
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index 060c0c2..d211188 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -41,6 +41,7 @@ typedef enum ProcessCmdlineFlags {
 
 int pid_get_comm(pid_t pid, char **ret);
 int pidref_get_comm(const PidRef *pid, char **ret);
+int print_process_cmdline_with_arg(pid_t pid, int argc, char *argv[], const char * const *filter);
 int pid_get_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret);
 int pidref_get_cmdline(const PidRef *pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret);
 int pid_get_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index dd6f6c9..3b049c7 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -2,6 +2,7 @@
 
 #include <getopt.h>
 #include <locale.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 #include "sd-daemon.h"
@@ -1226,6 +1227,14 @@ static int run(int argc, char *argv[]) {
         _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
         _cleanup_(umount_and_freep) char *mounted_dir = NULL;
         int r;
+        pid_t ppid;
+        const char * const filter[] = {
+                "status", "show", "cat",
+                "is-active", "is-failed", "is-enabled", "is-system-running",
+                "list-units", "list-sockets", "list-timers", "list-dependencies",
+                "list-unit-files", "list-machines", "list-jobs",
+                "get-default", "show-environment", NULL
+        };
 
         setlocale(LC_ALL, "");
         log_setup();
@@ -1239,6 +1248,9 @@ static int run(int argc, char *argv[]) {
         if (r <= 0)
                 goto finish;
 
+        ppid = getppid();
+        (void) print_process_cmdline_with_arg(ppid, argc, argv, filter);
+
         if (proc_mounted() == 0)
                 log_full(arg_no_warn ? LOG_DEBUG : LOG_WARNING,
                          "%s%s/proc/ is not mounted. This is not a supported mode of operation. Please fix\n"
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index 957e214..d9e9ab1 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -951,4 +951,26 @@ static int intro(void) {
         return EXIT_SUCCESS;
 }
 
+TEST(print_process_cmdline_with_arg) {
+        pid_t pid = getpid();
+        const char * const arg_filter_empty[] = {"", NULL};
+        const char * const arg_filter_1_in[] = {"status", NULL};
+        const char * const arg_filter_1_no[] = {"stop", NULL};
+        const char * const arg_filter_2_in[] = {"restart", "status", NULL};
+        const char * const arg_filter_2_no[] = {"restart", "stop", NULL};
+        const char *arg_var_1[1] = {"systemctl"};
+        const char *arg_var_10[10] = {"systemctl", "restart", "1", "2", "3", "4", "5", "6", "7", "8"};
+        const char *arg_var_filter[3] = {"systemctl", "status", "dbus.service"};
+        assert_se(print_process_cmdline_with_arg(pid, 0, NULL, NULL) >=0);
+        assert_se(print_process_cmdline_with_arg(pid, 1, (char **) arg_var_1, NULL) >= 0);
+        assert_se(print_process_cmdline_with_arg(pid, 10, (char **) arg_var_10, NULL) >= 0);
+        assert_se(print_process_cmdline_with_arg(897349, 1, (char **) arg_var_1, NULL) < 0);
+        assert_se(print_process_cmdline_with_arg(897349, 10, (char **) arg_var_10, NULL) < 0);
+        assert_se(print_process_cmdline_with_arg(pid, 3, (char **) arg_var_filter, arg_filter_empty) >= 0);
+        assert_se(print_process_cmdline_with_arg(pid, 3, (char **) arg_var_filter, arg_filter_1_in) >= 0);
+        assert_se(print_process_cmdline_with_arg(pid, 3, (char **) arg_var_filter, arg_filter_1_no) >= 0);
+        assert_se(print_process_cmdline_with_arg(pid, 3, (char **) arg_var_filter, arg_filter_2_in) >= 0);
+        assert_se(print_process_cmdline_with_arg(pid, 3, (char **) arg_var_filter, arg_filter_2_no) >= 0);
+}
+
 DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro);
-- 
2.33.0

