Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 Apr 2007 16:52:21 -0700 (PDT)
From:      Ted Faber <faber@lunabase.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Cc:        faber@lunabase.org
Subject:   i386/111117: kernel clock unset if RTC day of week wrong (patch included)
Message-ID:  <200704012352.l31NqLCs024644@ylum.lunabase.org>
Resent-Message-ID: <200704020030.l320U5ch099597@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         111117
>Category:       i386
>Synopsis:       kernel clock unset if RTC day of week wrong (patch included)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-i386
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Apr 02 00:30:04 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator:     Ted Faber
>Release:        FreeBSD 7.0-CURRENT i386
>Organization:
None
>Environment:
System: FreeBSD ylum.lunabase.org 7.0-CURRENT FreeBSD 7.0-CURRENT #5: Thu Mar 29 22:26:12 PDT 2007 root@ylum.lunabase.org:/usr/obj/usr/src/sys/YLUM i386


>Description:
	clock_ct_to_ts() in sys/kern/subr_clock.c leaves the stuct
	timespec it's initializing unchanged if the day of the week
	passed in is inconsistent with the other values.  The dow is not
	used in the initialization of the struct.  The routine does
	properly set an error code (EINVAL) to let the caller know that
	the struct is uninitialized, and there is a "don't care" value
	(-1) for day of the week that overrides the check.  However,
	sys/i386/isa/clock.c does not check the error code, so i386
	systems that have a wrongly set or calculated day of the week in
	their RTC have their time silently set to a random value.

	Of course this happened to me.

	The patch changed sys/i386/isa/clock.c to check the error code
	and retry the call to clock_ct_to_ts() with the day of the week
	set to -1 if the call failed and the day of the week was not -1.
	I put a couple diagnostics in so the admin is aware that
	something's fishy, even if the second call succeeds.

	The patch is relative to /usr/src against a recent CURRENT.

>How-To-Repeat:
	Get a buggy RTC on an i386.  Alternatively, if your BIOS allows
	setting the day of the week independently, you could do that.
	My buggy BIOS is on an EPIA ME6000 board.

>Fix:

	Patch attached.


--- sys/i386/isa/clock.c.orig	Sun Apr  1 16:20:43 2007
+++ sys/i386/isa/clock.c	Sun Apr  1 16:34:37 2007
@@ -665,6 +665,7 @@
 	int s;
 	struct timespec ts;
 	struct clocktime ct;
+	int conv_error = 0;
 
 	if (base) {
 		printf("base %d\n", base);
@@ -702,7 +703,25 @@
 #else
 	ct.year += 2000;
 #endif
-	clock_ct_to_ts(&ct, &ts);
+	if ( clock_ct_to_ts(&ct, &ts) ) {
+		if ( ct.dow != -1 ) {
+			/* Retry in case only the day of the week was wrong */
+			ct.dow = -1;
+			if ( clock_ct_to_ts(&ct, &ts)) conv_error = 1;
+			else {
+				printf("Real time clock day of week is "
+					"wrong\n");
+				printf("Kernel time should be correct.\n");
+			}
+		}
+		else conv_error = 1;
+	}
+
+	if ( conv_error ) {
+		printf("Real time clock values fail sanity check\n");
+		printf("Kernel time of day is probably wrong\n");
+	}
+	
 	ts.tv_sec += utc_offset();
 	tc_setclock(&ts);
 }
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200704012352.l31NqLCs024644>