]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/analyze/analyze.c
Fix reference to FileDescriptorStoreMax= directive
[thirdparty/systemd.git] / src / analyze / analyze.c
index d2be144f4f493061f36d79498e5f1fdf2c1ddecc..24188311ff49c87ab263d5682a5a26de729f519b 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "alloc-util.h"
 #include "analyze.h"
+#include "analyze-architectures.h"
 #include "analyze-blame.h"
 #include "analyze-calendar.h"
 #include "analyze-capability.h"
@@ -25,6 +26,8 @@
 #include "analyze-exit-status.h"
 #include "analyze-fdstore.h"
 #include "analyze-filesystems.h"
+#include "analyze-has-tpm2.h"
+#include "analyze-image-policy.h"
 #include "analyze-inspect-elf.h"
 #include "analyze-log-control.h"
 #include "analyze-malloc.h"
@@ -32,6 +35,7 @@
 #include "analyze-plot.h"
 #include "analyze-security.h"
 #include "analyze-service-watchdogs.h"
+#include "analyze-smbios11.h"
 #include "analyze-srk.h"
 #include "analyze-syscall-filter.h"
 #include "analyze-time.h"
@@ -41,7 +45,6 @@
 #include "analyze-unit-files.h"
 #include "analyze-unit-paths.h"
 #include "analyze-verify.h"
-#include "analyze-image-policy.h"
 #include "build.h"
 #include "bus-error.h"
 #include "bus-locator.h"
@@ -89,6 +92,7 @@
 #include "verbs.h"
 
 DotMode arg_dot = DEP_ALL;
+CapabilityMode arg_capability = CAPABILITY_LITERAL;
 char **arg_dot_from_patterns = NULL, **arg_dot_to_patterns = NULL;
 usec_t arg_fuzz = 0;
 PagerFlags arg_pager_flags = 0;
@@ -99,6 +103,9 @@ RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
 RecursiveErrors arg_recursive_errors = _RECURSIVE_ERRORS_INVALID;
 bool arg_man = true;
 bool arg_generators = false;
+const char *arg_instance = "test_instance";
+double arg_svg_timescale = 1.0;
+bool arg_detailed_svg = false;
 char *arg_root = NULL;
 static char *arg_image = NULL;
 char *arg_security_policy = NULL;
@@ -107,7 +114,7 @@ unsigned arg_threshold = 100;
 unsigned arg_iterations = 1;
 usec_t arg_base_time = USEC_INFINITY;
 char *arg_unit = NULL;
-JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
+sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
 bool arg_quiet = false;
 char *arg_profile = NULL;
 bool arg_legend = true;
@@ -204,41 +211,53 @@ static int help(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return log_oom();
 
-        printf("%s [OPTIONS...] COMMAND ...\n\n"
-               "%sProfile systemd, show unit dependencies, check unit files.%s\n"
-               "\nCommands:\n"
+        printf("%1$s [OPTIONS...] COMMAND ...\n\n"
+               "%5$sProfile systemd, show unit dependencies, check unit files.%6$s\n"
+               "\n%3$sBoot Analysis:%4$s\n"
                "  [time]                     Print time required to boot the machine\n"
                "  blame                      Print list of running units ordered by\n"
                "                             time to init\n"
                "  critical-chain [UNIT...]   Print a tree of the time critical chain\n"
                "                             of units\n"
+               "\n%3$sDependency Analysis:%4$s\n"
                "  plot                       Output SVG graphic showing service\n"
                "                             initialization\n"
-               "  dot [UNIT...]              Output dependency graph in %s format\n"
+               "  dot [UNIT...]              Output dependency graph in %7$s format\n"
                "  dump [PATTERN...]          Output state serialization of service\n"
                "                             manager\n"
-               "  cat-config                 Show configuration file and drop-ins\n"
+               "\n%3$sConfiguration Files and Search Paths:%4$s\n"
+               "  cat-config NAME|PATH...    Show configuration file and drop-ins\n"
                "  unit-files                 List files and symlinks for units\n"
                "  unit-paths                 List load directories for units\n"
+               "\n%3$sEnumerate OS Concepts:%4$s\n"
                "  exit-status [STATUS...]    List exit status definitions\n"
                "  capability [CAP...]        List capability definitions\n"
                "  syscall-filter [NAME...]   List syscalls in seccomp filters\n"
                "  filesystems [NAME...]      List known filesystems\n"
+               "  architectures [NAME...]    List known architectures\n"
+               "  smbios11                   List strings passed via SMBIOS Type #11\n"
+               "\n%3$sExpression Evaluation:%4$s\n"
                "  condition CONDITION...     Evaluate conditions and asserts\n"
                "  compare-versions VERSION1 [OP] VERSION2\n"
                "                             Compare two version strings\n"
-               "  verify FILE...             Check unit files for correctness\n"
+               "  image-policy POLICY...     Analyze image policy string\n"
+               "\n%3$sClock & Time:%4$s\n"
                "  calendar SPEC...           Validate repetitive calendar time\n"
                "                             events\n"
                "  timestamp TIMESTAMP...     Validate a timestamp\n"
                "  timespan SPAN...           Validate a time span\n"
+               "\n%3$sUnit & Service Analysis:%4$s\n"
+               "  verify FILE...             Check unit files for correctness\n"
                "  security [UNIT...]         Analyze security of unit\n"
-               "  inspect-elf FILE...        Parse and print ELF package metadata\n"
-               "  malloc [D-BUS SERVICE...]  Dump malloc stats of a D-Bus service\n"
                "  fdstore SERVICE...         Show file descriptor store contents of service\n"
+               "  malloc [D-BUS SERVICE...]  Dump malloc stats of a D-Bus service\n"
+               "\n%3$sExecutable Analysis:%4$s\n"
+               "  inspect-elf FILE...        Parse and print ELF package metadata\n"
+               "\n%3$sTPM Operations:%4$s\n"
+               "  has-tpm2                   Report whether TPM2 support is available\n"
                "  pcrs [PCR...]              Show TPM2 PCRs and their names\n"
-               "  srk > FILE                 Write TPM2 SRK to stdout\n"
-               "\nOptions:\n"
+               "  srk [>FILE]                Write TPM2 SRK (to FILE)\n"
+               "\n%3$sOptions:%4$s\n"
                "     --recursive-errors=MODE Control which units are verified\n"
                "     --offline=BOOL          Perform a security review on unit file(s)\n"
                "     --threshold=N           Exit with a non-zero status when overall\n"
@@ -264,12 +283,17 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --man[=BOOL]            Do [not] check for existence of man pages\n"
                "     --generators[=BOOL]     Do [not] run unit generators\n"
                "                             (requires privileges)\n"
+               "     --instance=NAME         Specify fallback instance name for template units\n"
                "     --iterations=N          Show the specified number of iterations\n"
                "     --base-time=TIMESTAMP   Calculate calendar times relative to\n"
                "                             specified time\n"
                "     --profile=name|PATH     Include the specified profile in the\n"
                "                             security review of the unit(s)\n"
+               "     --unit=UNIT             Evaluate conditions and asserts of unit\n"
                "     --table                 Output plot's raw time data as a table\n"
+               "     --scale-svg=FACTOR      Stretch x-axis of plot by FACTOR (default: 1.0)\n"
+               "     --detailed              Add more details to SVG plot,\n"
+               "                             e.g. show activation timestamps\n"
                "  -h --help                  Show this help\n"
                "     --version               Show package version\n"
                "  -q --quiet                 Do not emit hints\n"
@@ -277,12 +301,14 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --root=PATH             Operate on an alternate filesystem root\n"
                "     --image=PATH            Operate on disk image as filesystem root\n"
                "     --image-policy=POLICY   Specify disk image dissection policy\n"
-               "\nSee the %s for details.\n",
+               "\nSee the %2$s for details.\n",
                program_invocation_short_name,
+               link,
+               ansi_underline(),
+               ansi_normal(),
                ansi_highlight(),
                ansi_normal(),
-               dot_link,
-               link);
+               dot_link);
 
         /* When updating this list, including descriptions, apply changes to
          * shell-completion/bash/systemd-analyze and shell-completion/zsh/_systemd-analyze too. */
@@ -307,6 +333,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_NO_PAGER,
                 ARG_MAN,
                 ARG_GENERATORS,
+                ARG_INSTANCE,
                 ARG_ITERATIONS,
                 ARG_BASE_TIME,
                 ARG_RECURSIVE_ERRORS,
@@ -318,6 +345,8 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_TABLE,
                 ARG_NO_LEGEND,
                 ARG_TLDR,
+                ARG_SCALE_FACTOR_SVG,
+                ARG_DETAILED_SVG,
         };
 
         static const struct option options[] = {
@@ -342,6 +371,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "no-pager",         no_argument,       NULL, ARG_NO_PAGER         },
                 { "man",              optional_argument, NULL, ARG_MAN              },
                 { "generators",       optional_argument, NULL, ARG_GENERATORS       },
+                { "instance",         required_argument, NULL, ARG_INSTANCE         },
                 { "host",             required_argument, NULL, 'H'                  },
                 { "machine",          required_argument, NULL, 'M'                  },
                 { "iterations",       required_argument, NULL, ARG_ITERATIONS       },
@@ -352,6 +382,9 @@ static int parse_argv(int argc, char *argv[]) {
                 { "table",            optional_argument, NULL, ARG_TABLE            },
                 { "no-legend",        optional_argument, NULL, ARG_NO_LEGEND        },
                 { "tldr",             no_argument,       NULL, ARG_TLDR             },
+                { "mask",             no_argument,       NULL, 'm'                  },
+                { "scale-svg",        required_argument, NULL, ARG_SCALE_FACTOR_SVG },
+                { "detailed",         no_argument,       NULL, ARG_DETAILED_SVG     },
                 {}
         };
 
@@ -360,7 +393,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "hH:M:U:", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "hqH:M:U:m", options, NULL)) >= 0)
                 switch (c) {
 
                 case 'h':
@@ -467,6 +500,10 @@ static int parse_argv(int argc, char *argv[]) {
                                 return r;
                         break;
 
+                case ARG_INSTANCE:
+                        arg_instance = optarg;
+                        break;
+
                 case ARG_OFFLINE:
                         r = parse_boolean_argument("--offline", optarg, &arg_offline);
                         if (r < 0)
@@ -545,6 +582,18 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_cat_flags = CAT_TLDR;
                         break;
 
+                case 'm':
+                        arg_capability = CAPABILITY_MASK;
+                        break;
+
+                case ARG_SCALE_FACTOR_SVG:
+                        arg_svg_timescale = strtod(optarg, NULL);
+                        break;
+
+                case ARG_DETAILED_SVG:
+                        arg_detailed_svg = true;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -556,18 +605,21 @@ static int parse_argv(int argc, char *argv[]) {
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Option --offline= is only supported for security right now.");
 
-        if (arg_json_format_flags != JSON_FORMAT_OFF && !STRPTR_IN_SET(argv[optind], "security", "inspect-elf", "plot", "fdstore", "pcrs"))
+        if (arg_offline && optind >= argc - 1)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "Option --json= is only supported for security, inspect-elf, plot, fdstore, pcrs right now.");
+                                       "Option --offline= requires one or more units to perform a security review.");
+
+        if (arg_json_format_flags != SD_JSON_FORMAT_OFF && !STRPTR_IN_SET(argv[optind], "security", "inspect-elf", "plot", "fdstore", "pcrs", "architectures", "capability", "exit-status"))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "Option --json= is only supported for security, inspect-elf, plot, fdstore, pcrs, architectures, capability, exit-status right now.");
 
         if (arg_threshold != 100 && !streq_ptr(argv[optind], "security"))
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Option --threshold= is only supported for security right now.");
 
-        if (arg_runtime_scope == RUNTIME_SCOPE_GLOBAL &&
-            !STR_IN_SET(argv[optind] ?: "time", "dot", "unit-paths", "verify"))
+        if (arg_runtime_scope == RUNTIME_SCOPE_GLOBAL && !streq_ptr(argv[optind], "unit-paths"))
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "Option --global only makes sense with verbs dot, unit-paths, verify.");
+                                       "Option --global only makes sense with verb unit-paths.");
 
         if (streq_ptr(argv[optind], "cat-config") && arg_runtime_scope == RUNTIME_SCOPE_USER)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
@@ -577,7 +629,7 @@ static int parse_argv(int argc, char *argv[]) {
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Option --security-policy= is only supported for security.");
 
-        if ((arg_root || arg_image) && (!STRPTR_IN_SET(argv[optind], "cat-config", "verify", "condition")) &&
+        if ((arg_root || arg_image) && (!STRPTR_IN_SET(argv[optind], "cat-config", "verify", "condition", "inspect-elf")) &&
            (!(streq_ptr(argv[optind], "security") && arg_offline)))
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Options --root= and --image= are only supported for cat-config, verify, condition and security when used with --offline= right now.");
@@ -595,16 +647,19 @@ static int parse_argv(int argc, char *argv[]) {
         if (streq_ptr(argv[optind], "condition") && arg_unit && optind < argc - 1)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No conditions can be passed if --unit= is used.");
 
-        if ((!arg_legend && !streq_ptr(argv[optind], "plot")) ||
-           (streq_ptr(argv[optind], "plot") && !arg_legend && !arg_table && FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)))
+        if ((!arg_legend && !STRPTR_IN_SET(argv[optind], "plot", "architectures")) ||
+           (streq_ptr(argv[optind], "plot") && !arg_legend && !arg_table && FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF)))
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Option --no-legend is only supported for plot with either --table or --json=.");
 
         if (arg_table && !streq_ptr(argv[optind], "plot"))
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Option --table is only supported for plot right now.");
 
-        if (arg_table && !FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
+        if (arg_table && !FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF))
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--table and --json= are mutually exclusive.");
 
+        if (arg_capability != CAPABILITY_LITERAL && !streq_ptr(argv[optind], "capability"))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Option --mask is only supported for capability.");
+
         return 1; /* work to do */
 }
 
@@ -647,8 +702,11 @@ static int run(int argc, char *argv[]) {
                 { "malloc",            VERB_ANY, VERB_ANY, 0,            verb_malloc            },
                 { "fdstore",           2,        VERB_ANY, 0,            verb_fdstore           },
                 { "image-policy",      2,        2,        0,            verb_image_policy      },
+                { "has-tpm2",          VERB_ANY, 1,        0,            verb_has_tpm2          },
                 { "pcrs",              VERB_ANY, VERB_ANY, 0,            verb_pcrs              },
                 { "srk",               VERB_ANY, 1,        0,            verb_srk               },
+                { "architectures",     VERB_ANY, VERB_ANY, 0,            verb_architectures     },
+                { "smbios11",          VERB_ANY, 1,        0,            verb_smbios11          },
                 {}
         };
 
@@ -672,7 +730,8 @@ static int run(int argc, char *argv[]) {
                                 arg_image_policy,
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_RELAX_VAR_CHECK |
-                                DISSECT_IMAGE_READ_ONLY,
+                                DISSECT_IMAGE_READ_ONLY |
+                                DISSECT_IMAGE_ALLOW_USERSPACE_VERITY,
                                 &mounted_dir,
                                 /* ret_dir_fd= */ NULL,
                                 &loop_device);