comparison dbutil.c @ 1622:e11ed628708b

- Add adaptive authentication failure delay - Rework monotonic_now/gettime_wrapper and use clock_gettime on more platforms
author Matt Johnston <matt@ucc.asn.au>
date Mon, 05 Nov 2018 23:36:34 +0800
parents e75dab5bec71
children dfbe947bdf0d
comparison
equal deleted inserted replaced
1621:8cdabd7d34aa 1622:e11ed628708b
603 c |= (xa[i] ^ xb[i]); 603 c |= (xa[i] ^ xb[i]);
604 } 604 }
605 return c; 605 return c;
606 } 606 }
607 607
608 #if defined(__linux__) && defined(SYS_clock_gettime) 608 /* higher-resolution monotonic timestamp, falls back to gettimeofday */
609 /* CLOCK_MONOTONIC_COARSE was added in Linux 2.6.32 but took a while to 609 void gettime_wrapper(struct timespec *now) {
610 reach userspace include headers */ 610 struct timeval tv;
611 #ifndef CLOCK_MONOTONIC_COARSE
612 #define CLOCK_MONOTONIC_COARSE 6
613 #endif
614 /* Some old toolchains know SYS_clock_gettime but not CLOCK_MONOTONIC */
615 #ifndef CLOCK_MONOTONIC
616 #define CLOCK_MONOTONIC 1
617 #endif
618 static clockid_t get_linux_clock_source() {
619 struct timespec ts;
620 if (syscall(SYS_clock_gettime, CLOCK_MONOTONIC_COARSE, &ts) == 0) {
621 return CLOCK_MONOTONIC_COARSE;
622 }
623
624 if (syscall(SYS_clock_gettime, CLOCK_MONOTONIC, &ts) == 0) {
625 return CLOCK_MONOTONIC;
626 }
627 return -1;
628 }
629 #endif
630
631 time_t monotonic_now() {
632 #if DROPBEAR_FUZZ 611 #if DROPBEAR_FUZZ
633 if (fuzz.fuzzing) { 612 if (fuzz.fuzzing) {
634 /* time stands still when fuzzing */ 613 /* time stands still when fuzzing */
635 return 5; 614 now->tv_sec = 5;
636 } 615 now->tv_nsec = 0;
637 #endif 616 }
617 #endif
618
619 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
620 /* POSIX monotonic clock. Newer Linux, BSD, MacOSX >10.12 */
621 if (clock_gettime(CLOCK_MONOTONIC, now) == 0) {
622 return;
623 }
624 #endif
625
638 #if defined(__linux__) && defined(SYS_clock_gettime) 626 #if defined(__linux__) && defined(SYS_clock_gettime)
639 { 627 {
640 static clockid_t clock_source = -2; 628 /* Old linux toolchain - kernel might support it but not the build headers */
641 629 /* Also glibc <2.17 requires -lrt which we neglect to add */
642 if (clock_source == -2) { 630 static int linux_monotonic_failed = 0;
643 /* First run, find out which one works. 631 if (!linux_monotonic_failed) {
644 -1 will fall back to time() */ 632 /* CLOCK_MONOTONIC isn't in some headers */
645 clock_source = get_linux_clock_source(); 633 int clock_source_monotonic = 1;
646 } 634 if (syscall(SYS_clock_gettime, clock_source_monotonic, now) == 0) {
647 635 return;
648 if (clock_source >= 0) { 636 } else {
649 struct timespec ts; 637 /* Don't try again */
650 if (syscall(SYS_clock_gettime, clock_source, &ts) != 0) { 638 linux_monotonic_failed = 1;
651 /* Intermittent clock failures should not happen */ 639 }
652 dropbear_exit("Clock broke"); 640 }
653 } 641 }
654 return ts.tv_sec; 642 #endif /* linux fallback clock_gettime */
655 }
656 }
657 #endif /* linux clock_gettime */
658 643
659 #if defined(HAVE_MACH_ABSOLUTE_TIME) 644 #if defined(HAVE_MACH_ABSOLUTE_TIME)
660 { 645 {
661 /* OS X, see https://developer.apple.com/library/mac/qa/qa1398/_index.html */ 646 /* OS X pre 10.12, see https://developer.apple.com/library/mac/qa/qa1398/_index.html */
662 static mach_timebase_info_data_t timebase_info; 647 static mach_timebase_info_data_t timebase_info;
648 uint64_t scaled_time;
663 if (timebase_info.denom == 0) { 649 if (timebase_info.denom == 0) {
664 mach_timebase_info(&timebase_info); 650 mach_timebase_info(&timebase_info);
665 } 651 }
666 return mach_absolute_time() * timebase_info.numer / timebase_info.denom 652 scaled_time = mach_absolute_time() * timebase_info.numer / timebase_info.denom;
667 / 1e9; 653 now->tv_sec = scaled_time / 1000000000;
654 now->tv_nsec = scaled_time % 1000000000;
668 } 655 }
669 #endif /* osx mach_absolute_time */ 656 #endif /* osx mach_absolute_time */
670 657
671 /* Fallback for everything else - this will sometimes go backwards */ 658 /* Fallback for everything else - this will sometimes go backwards */
672 return time(NULL); 659 gettimeofday(&tv, NULL);
660 now->tv_sec = tv.tv_sec;
661 now->tv_nsec = 1000*tv.tv_usec;
662 }
663
664 /* second-resolution monotonic timestamp */
665 time_t monotonic_now() {
666 struct timespec ts;
667 gettime_wrapper(&ts);
668 return ts.tv_sec;
673 } 669 }
674 670
675 void fsync_parent_dir(const char* fn) { 671 void fsync_parent_dir(const char* fn) {
676 #ifdef HAVE_LIBGEN_H 672 #ifdef HAVE_LIBGEN_H
677 char *fn_dir = m_strdup(fn); 673 char *fn_dir = m_strdup(fn);