summaryrefslogtreecommitdiffstats
path: root/sys-utils/hwclock.c
diff options
context:
space:
mode:
authorJ William Piggott2017-03-04 17:04:10 +0100
committerJ William Piggott2017-03-04 17:04:10 +0100
commit7a3000f7ba548cf7d74ac77cc63fe8de228a669e (patch)
tree9b53ef9b18a581dda3099ba66b4d3e8e3d50e2df /sys-utils/hwclock.c
parentbuild-sys: add parse-date.y (diff)
downloadkernel-qcow2-util-linux-7a3000f7ba548cf7d74ac77cc63fe8de228a669e.tar.gz
kernel-qcow2-util-linux-7a3000f7ba548cf7d74ac77cc63fe8de228a669e.tar.xz
kernel-qcow2-util-linux-7a3000f7ba548cf7d74ac77cc63fe8de228a669e.zip
hwclock: use parse_date function
* 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>
Diffstat (limited to 'sys-utils/hwclock.c')
-rw-r--r--sys-utils/hwclock.c104
1 files changed, 5 insertions, 99 deletions
diff --git a/sys-utils/hwclock.c b/sys-utils/hwclock.c
index 21d1304e1..21559cf41 100644
--- a/sys-utils/hwclock.c
+++ b/sys-utils/hwclock.c
@@ -639,100 +639,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'.
*
* Also set the kernel time zone value to the value indicated by the TZ
@@ -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);
}
}