]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
hwclock: use parse_date function
authorJ William Piggott <elseifthen@gmx.com>
Sat, 4 Mar 2017 16:04:10 +0000 (11:04 -0500)
committerJ William Piggott <elseifthen@gmx.com>
Sat, 4 Mar 2017 16:04:10 +0000 (11:04 -0500)
* hwclock.c: replace interpret_date_string() with parse_date().
   Eliminates shell injection vulnerability from popen() date(1).
   Removes system dependency on date(1).
   Reduction in hwclock execution time.
   Significant cleanup of hwclock.c code.

* Bug fix for "hwclock --predict --date 'bad_date'" printing:
    hwclock: No usable set-to time.  Cannot set clock.

  The message now matches date(1) for an invalid --date argument.

Signed-off-by: J William Piggott <elseifthen@gmx.com>
sys-utils/hwclock.c

index 21d1304e11e716763f9746a268595083cc36d655..21559cf41bada416b45155c755e7d86a7f7230aa 100644 (file)
@@ -638,100 +638,6 @@ display_time(const bool hclock_valid, struct timeval hwctime)
        }
 }
 
-/*
- * Interpret the value of the --date option, which is something like
- * "13:05:01". In fact, it can be any of the myriad ASCII strings that
- * specify a time which the "date" program can understand. The date option
- * value in question is our "dateopt" argument.
- *
- * The specified time is in the local time zone.
- *
- * Our output, "*time_p", is a seconds-into-epoch time.
- *
- * We use the "date" program to interpret the date string. "date" must be
- * runnable by issuing the command "date" to the /bin/sh shell. That means
- * in must be in the current PATH.
- *
- * If anything goes wrong (and many things can), we return code 10
- * and arbitrary *time_p. Otherwise, return code is 0 and *time_p is valid.
- */
-static int interpret_date_string(const struct hwclock_control *ctl,
-                                time_t *const time_p)
-{
-       FILE *date_child_fp = NULL;
-       char *date_command = NULL;
-       char *date_resp = NULL;
-       size_t len = 0;
-       const char magic[] = "seconds-into-epoch=";
-       int retcode = 1;
-       long seconds_since_epoch;
-
-       if (!ctl->date_opt) {
-               warnx(_("No --date option specified."));
-               return retcode;
-       }
-
-       /* Quotes in date_opt would ruin the date command we construct. */
-       if (strchr(ctl->date_opt, '"') != NULL ||
-           strchr(ctl->date_opt, '`') != NULL ||
-           strchr(ctl->date_opt, '$') != NULL) {
-               warnx(_
-                     ("The value of the --date option is not a valid date.\n"
-                      "In particular, it contains illegal character(s)."));
-               return retcode;
-       }
-
-       xasprintf(&date_command, "date --date=\"%s\" +%s%%s",
-               ctl->date_opt, magic);
-       if (ctl->debug)
-               printf(_("Issuing date command: %s\n"), date_command);
-
-       date_child_fp = popen(date_command, "r");
-       if (date_child_fp == NULL) {
-               warn(_("Unable to run 'date' program in /bin/sh shell. "
-                           "popen() failed"));
-               goto out;
-       }
-
-       if (getline(&date_resp, &len, date_child_fp) < 0) {
-               warn(_("getline() failed"));
-               goto out;
-       }
-       if (ctl->debug)
-               printf(_("response from date command = %s\n"), date_resp);
-       if (strncmp(date_resp, magic, sizeof(magic) - 1) != 0) {
-               warnx(_("The date command issued by %s returned "
-                                 "unexpected results.\n"
-                                 "The command was:\n  %s\n"
-                                 "The response was:\n  %s"),
-                       program_invocation_short_name, date_command, date_resp);
-               goto out;
-       }
-
-       if (sscanf(date_resp + sizeof(magic) - 1, "%ld", &seconds_since_epoch) < 1) {
-               warnx(_("The date command issued by %s returned "
-                       "something other than an integer where the "
-                       "converted time value was expected.\n"
-                       "The command was:\n  %s\n"
-                       "The response was:\n %s\n"),
-                     program_invocation_short_name, date_command, date_resp);
-       } else {
-               retcode = 0;
-               *time_p = seconds_since_epoch;
-               if (ctl->debug)
-                       printf(_("date string %s equates to "
-                                "%ld seconds since 1969.\n"),
-                              ctl->date_opt, *time_p);
-       }
- out:
-       free(date_command);
-       free(date_resp);
-       if (date_child_fp)
-               pclose(date_child_fp);
-
-       return retcode;
-}
-
 /*
  * Set the System Clock to time 'newtime'.
  *
@@ -1460,6 +1366,7 @@ int main(int argc, char **argv)
        struct hwclock_control ctl = { NULL };
        struct timeval startup_time;
        struct adjtime adjtime = { 0 };
+       struct timespec when = { 0 };
        /*
         * The time we started up, in seconds into the epoch, including
         * fractions.
@@ -1699,11 +1606,10 @@ int main(int argc, char **argv)
 #endif
 
        if (ctl.set || ctl.predict) {
-               rc = interpret_date_string(&ctl, &set_time);
-               /* (time-consuming) */
-               if (rc != 0) {
-                       warnx(_("No usable set-to time.  "
-                               "Cannot set clock."));
+               if (parse_date(&when, ctl.date_opt, NULL))
+                       set_time = when.tv_sec;
+               else {
+                       warnx(_("invalid date '%s'"), ctl.date_opt);
                        hwclock_exit(&ctl, EX_USAGE);
                }
        }