]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #1227 from intelfx/systemctl-legacy-tools-polkit
authorLennart Poettering <lennart@poettering.net>
Thu, 10 Sep 2015 17:53:31 +0000 (19:53 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 10 Sep 2015 17:53:31 +0000 (19:53 +0200)
systemctl: fix various aspects of polkit authorization in legacy tools.

1  2 
src/systemctl/systemctl.c

index e265d0fd13a4bc1d254ba79c8799fc89ce476a44,20ded4dc0aef04d87807e7a4cd6ae0eca2aa5027..d21ba9a56665444f1ab7d5cd4122e7c8a1ec4c42
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 -#include <sys/reboot.h>
 -#include <linux/reboot.h>
 -#include <stdio.h>
 +#include <errno.h>
 +#include <fcntl.h>
  #include <getopt.h>
 +#include <linux/reboot.h>
  #include <locale.h>
  #include <stdbool.h>
 +#include <stddef.h>
 +#include <stdio.h>
  #include <string.h>
 -#include <errno.h>
 -#include <unistd.h>
 -#include <fcntl.h>
 +#include <sys/reboot.h>
  #include <sys/socket.h>
 -#include <stddef.h>
 +#include <unistd.h>
  
 +#include "sd-bus.h"
  #include "sd-daemon.h"
  #include "sd-login.h"
 -#include "sd-bus.h"
 -#include "log.h"
 -#include "util.h"
 -#include "macro.h"
 -#include "set.h"
 -#include "utmp-wtmp.h"
 -#include "special.h"
 -#include "initreq.h"
 -#include "path-util.h"
 -#include "strv.h"
 +
 +#include "build.h"
 +#include "bus-common-errors.h"
 +#include "bus-error.h"
 +#include "bus-message.h"
 +#include "bus-util.h"
  #include "cgroup-show.h"
  #include "cgroup-util.h"
 -#include "list.h"
 -#include "path-lookup.h"
 -#include "exit-status.h"
 -#include "build.h"
 -#include "unit-name.h"
 -#include "pager.h"
 -#include "spawn-ask-password-agent.h"
 -#include "spawn-polkit-agent.h"
 -#include "install.h"
 -#include "logs-show.h"
 -#include "socket-util.h"
 -#include "fileio.h"
  #include "copy.h"
 -#include "env-util.h"
 -#include "bus-util.h"
 -#include "bus-message.h"
 -#include "bus-error.h"
 -#include "bus-common-errors.h"
 -#include "mkdir.h"
  #include "dropin.h"
  #include "efivars.h"
 +#include "env-util.h"
 +#include "exit-status.h"
 +#include "fileio.h"
  #include "formats-util.h"
 -#include "process-util.h"
 -#include "terminal-util.h"
  #include "hostname-util.h"
 +#include "initreq.h"
 +#include "install.h"
 +#include "list.h"
 +#include "log.h"
 +#include "logs-show.h"
 +#include "macro.h"
 +#include "mkdir.h"
 +#include "pager.h"
 +#include "path-lookup.h"
 +#include "path-util.h"
 +#include "process-util.h"
 +#include "set.h"
  #include "signal-util.h"
 +#include "socket-util.h"
 +#include "spawn-ask-password-agent.h"
 +#include "spawn-polkit-agent.h"
 +#include "special.h"
 +#include "strv.h"
 +#include "terminal-util.h"
 +#include "unit-name.h"
 +#include "util.h"
 +#include "utmp-wtmp.h"
  
  static char **arg_types = NULL;
  static char **arg_states = NULL;
@@@ -101,7 -100,7 +101,7 @@@ static bool arg_quiet = false
  static bool arg_full = false;
  static bool arg_recursive = false;
  static int arg_force = 0;
- static bool arg_ask_password = true;
+ static bool arg_ask_password = false;
  static bool arg_runtime = false;
  static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
  static char **arg_wall = NULL;
@@@ -1300,10 -1299,11 +1300,11 @@@ static void output_unit_file_list(cons
                  const char *on, *off;
                  const char *id;
  
-                 if (u->state == UNIT_FILE_MASKED ||
-                     u->state == UNIT_FILE_MASKED_RUNTIME ||
-                     u->state == UNIT_FILE_DISABLED ||
-                     u->state == UNIT_FILE_INVALID) {
+                 if (IN_SET(u->state,
+                            UNIT_FILE_MASKED,
+                            UNIT_FILE_MASKED_RUNTIME,
+                            UNIT_FILE_DISABLED,
+                            UNIT_FILE_INVALID)) {
                          on  = ansi_highlight_red();
                          off = ansi_highlight_off();
                  } else if (u->state == UNIT_FILE_ENABLED) {
@@@ -1477,8 -1477,6 +1478,8 @@@ static int list_dependencies_get_depend
                                         "BindsTo\0",
                  [DEPENDENCY_REVERSE] = "RequiredBy\0"
                                         "RequiredByOverridable\0"
 +                                       "RequisiteOf\0"
 +                                       "RequisiteOfOverridable\0"
                                         "WantedBy\0"
                                         "PartOf\0"
                                         "BoundBy\0",
@@@ -2765,7 -2763,7 +2766,7 @@@ static int start_unit(sd_bus *bus, cha
  static int reboot_with_logind(sd_bus *bus, enum action a) {
  #ifdef HAVE_LOGIND
          _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-         const char *method;
+         const char *method, *description;
          int r;
  
          if (!bus)
  
          case ACTION_REBOOT:
                  method = "Reboot";
+                 description = "reboot system";
                  break;
  
          case ACTION_POWEROFF:
                  method = "PowerOff";
+                 description = "power off system";
                  break;
  
          case ACTION_SUSPEND:
                  method = "Suspend";
+                 description = "suspend system";
                  break;
  
          case ACTION_HIBERNATE:
                  method = "Hibernate";
+                 description = "hibernate system";
                  break;
  
          case ACTION_HYBRID_SLEEP:
                  method = "HybridSleep";
+                 description = "put system into hybrid sleep";
                  break;
  
          default:
                          NULL,
                          "b", arg_ask_password);
          if (r < 0)
-                 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
+                 log_error("Failed to %s via logind: %s", description, bus_error_message(&error, r));
  
          return r;
  #else
@@@ -2901,10 -2904,11 +2907,11 @@@ static int check_inhibitors(sd_bus *bus
                          return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid);
  
                  if (!strv_contains(sv,
-                                   a == ACTION_HALT ||
-                                   a == ACTION_POWEROFF ||
-                                   a == ACTION_REBOOT ||
-                                   a == ACTION_KEXEC ? "shutdown" : "sleep"))
+                                    IN_SET(a,
+                                           ACTION_HALT,
+                                           ACTION_POWEROFF,
+                                           ACTION_REBOOT,
+                                           ACTION_KEXEC) ? "shutdown" : "sleep"))
                          continue;
  
                  get_process_comm(pid, &comm);
@@@ -3025,29 -3029,36 +3032,36 @@@ static int start_special(sd_bus *bus, c
          }
  
          if (arg_force >= 2 &&
-             (a == ACTION_HALT ||
-              a == ACTION_POWEROFF ||
-              a == ACTION_REBOOT))
+             IN_SET(a,
+                    ACTION_HALT,
+                    ACTION_POWEROFF,
+                    ACTION_REBOOT))
                  return halt_now(a);
  
          if (arg_force >= 1 &&
-             (a == ACTION_HALT ||
-              a == ACTION_POWEROFF ||
-              a == ACTION_REBOOT ||
-              a == ACTION_KEXEC ||
-              a == ACTION_EXIT))
+             IN_SET(a,
+                    ACTION_HALT,
+                    ACTION_POWEROFF,
+                    ACTION_REBOOT,
+                    ACTION_KEXEC,
+                    ACTION_EXIT))
                  return daemon_reload(bus, args);
  
          /* first try logind, to allow authentication with polkit */
          if (geteuid() != 0 &&
-             (a == ACTION_POWEROFF ||
-              a == ACTION_REBOOT ||
-              a == ACTION_SUSPEND ||
-              a == ACTION_HIBERNATE ||
-              a == ACTION_HYBRID_SLEEP)) {
+             IN_SET(a,
+                    ACTION_POWEROFF,
+                    ACTION_REBOOT,
+                    ACTION_SUSPEND,
+                    ACTION_HIBERNATE,
+                    ACTION_HYBRID_SLEEP)) {
                  r = reboot_with_logind(bus, a);
-                 if (r >= 0 || IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
+                 if (r >= 0)
                          return r;
+                 if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
+                         /* requested operation is not supported or already in progress */
+                         return r;
+                 /* on all other errors, try low-level operation */
          }
  
          r = start_unit(bus, args);
@@@ -3286,8 -3297,6 +3300,8 @@@ typedef struct UnitStatusInfo 
          uint64_t memory_current;
          uint64_t memory_limit;
          uint64_t cpu_usage_nsec;
 +        uint64_t tasks_current;
 +        uint64_t tasks_max;
  
          LIST_HEAD(ExecStatusInfo, exec);
  } UnitStatusInfo;
@@@ -3546,15 -3555,6 +3560,15 @@@ static void print_status_info
          if (i->status_errno > 0)
                  printf("    Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
  
 +        if (i->tasks_current != (uint64_t) -1) {
 +                printf("    Tasks: %" PRIu64, i->tasks_current);
 +
 +                if (i->tasks_max != (uint64_t) -1)
 +                        printf(" (limit: %" PRIi64 ")\n", i->tasks_max);
 +                else
 +                        printf("\n");
 +        }
 +
          if (i->memory_current != (uint64_t) -1) {
                  char buf[FORMAT_BYTES_MAX];
  
  
          if (i->control_group &&
              (i->main_pid > 0 || i->control_pid > 0 ||
-              ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group) == 0))) {
+              (!IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group) == 0))) {
                  unsigned c;
  
                  printf("   CGroup: %s\n", i->control_group);
  
-                 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
+                 if (IN_SET(arg_transport,
+                            BUS_TRANSPORT_LOCAL,
+                            BUS_TRANSPORT_MACHINE)) {
                          unsigned k = 0;
                          pid_t extra[2];
                          static const char prefix[] = "           ";
@@@ -3788,10 -3790,6 +3804,10 @@@ static int status_property(const char *
                          i->memory_current = u;
                  else if (streq(name, "MemoryLimit"))
                          i->memory_limit = u;
 +                else if (streq(name, "TasksCurrent"))
 +                        i->tasks_current = u;
 +                else if (streq(name, "TasksMax"))
 +                        i->tasks_max = u;
                  else if (streq(name, "CPUUsageNSec"))
                          i->cpu_usage_nsec = u;
  
@@@ -4268,8 -4266,6 +4284,8 @@@ static int show_one
                  .memory_current = (uint64_t) -1,
                  .memory_limit = (uint64_t) -1,
                  .cpu_usage_nsec = (uint64_t) -1,
 +                .tasks_current = (uint64_t) -1,
 +                .tasks_max = (uint64_t) -1,
          };
          ExecStatusInfo *p;
          int r;
@@@ -4487,7 -4483,9 +4503,9 @@@ static int show_system_status(sd_bus *b
                 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
  
          printf("   CGroup: %s\n", mi.control_group ?: "/");
-         if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
+         if (IN_SET(arg_transport,
+                    BUS_TRANSPORT_LOCAL,
+                    BUS_TRANSPORT_MACHINE)) {
                  static const char prefix[] = "           ";
                  unsigned c;
  
@@@ -4643,7 -4641,7 +4661,7 @@@ static int cat_file(const char *filenam
                 ansi_highlight_off());
          fflush(stdout);
  
 -        return copy_bytes(fd, STDOUT_FILENO, (off_t) -1, false);
 +        return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, false);
  }
  
  static int cat(sd_bus *bus, char **args) {
@@@ -5154,9 -5152,10 +5172,10 @@@ static int enable_sysv_units(const cha
          if (arg_scope != UNIT_FILE_SYSTEM)
                  return 0;
  
-         if (!streq(verb, "enable") &&
-             !streq(verb, "disable") &&
-             !streq(verb, "is-enabled"))
+         if (!STR_IN_SET(verb,
+                         "enable",
+                         "disable",
+                         "is-enabled"))
                  return 0;
  
          /* Processes all SysV units, and reshuffles the array so that
@@@ -5656,10 -5655,11 +5675,11 @@@ static int unit_is_enabled(sd_bus *bus
                          if (state < 0)
                                  return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
  
-                         if (state == UNIT_FILE_ENABLED ||
-                             state == UNIT_FILE_ENABLED_RUNTIME ||
-                             state == UNIT_FILE_STATIC ||
-                             state == UNIT_FILE_INDIRECT)
+                         if (IN_SET(state,
+                                    UNIT_FILE_ENABLED,
+                                    UNIT_FILE_ENABLED_RUNTIME,
+                                    UNIT_FILE_STATIC,
+                                    UNIT_FILE_INDIRECT))
                                  enabled = true;
  
                          if (!arg_quiet)
@@@ -6360,6 -6360,9 +6380,9 @@@ static int systemctl_parse_argv(int arg
          assert(argc >= 0);
          assert(argv);
  
+         /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
+         arg_ask_password = true;
          while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
  
                  switch (c) {
@@@ -7373,21 -7376,27 +7396,27 @@@ static int halt_main(sd_bus *bus) 
                  return r;
  
          if (geteuid() != 0) {
+                 if (arg_when > 0 ||
+                     arg_dry ||
+                     arg_force > 0) {
+                         log_error("Must be root.");
+                         return -EPERM;
+                 }
                  /* Try logind if we are a normal user and no special
                   * mode applies. Maybe PolicyKit allows us to shutdown
                   * the machine. */
-                 if (arg_when <= 0 &&
-                     arg_force <= 0 &&
-                     (arg_action == ACTION_POWEROFF ||
-                      arg_action == ACTION_REBOOT)) {
+                 if (IN_SET(arg_action,
+                            ACTION_POWEROFF,
+                            ACTION_REBOOT)) {
                          r = reboot_with_logind(bus, arg_action);
                          if (r >= 0)
                                  return r;
+                         if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
+                                 /* requested operation is not supported or already in progress */
+                                 return r;
+                         /* on all other errors, try low-level operation */
                  }
-                 log_error("Must be root.");
-                 return -EPERM;
          }
  
          if (arg_when > 0) {
                  _cleanup_free_ char *m = NULL;
                  const char *action;
  
+                 assert(geteuid() == 0);
                  if (avoid_bus()) {
                          log_error("Unable to perform operation without bus connection.");
                          return -ENOSYS;
          if (!arg_dry && !arg_force)
                  return start_with_fallback(bus);
  
+         assert(geteuid() == 0);
          if (!arg_no_wtmp) {
                  if (sd_booted() > 0)
                          log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");