[Bugme-new] [Bug 6761] New: adjtimex broken when delta is NULL

bugme-daemon at bugzilla.kernel.org bugme-daemon at bugzilla.kernel.org
Wed Jun 28 06:08:51 PDT 2006


http://bugzilla.kernel.org/show_bug.cgi?id=6761

           Summary: adjtimex broken when delta is NULL
    Kernel Version: 2.6.17
            Status: NEW
          Severity: normal
             Owner: johnstul at us.ibm.com
         Submitter: michael.kerrisk at gmx.net


Most recent kernel where this bug did not occur: occurs in all kernels (also in
2.6.17)
Distribution: n/a (most recently tested on SUSE 10.0)
Hardware Environment: x86 (and probably all others)
Software Environment:
Problem Description:
A long standing bug in the adjtimex() system call causes glibc's 
adjtime(3) function to deliver the wrong results if 'delta' is NULL.

The adjtime(3) manual page says 

       If olddelta is not NULL, then the buffer that it points to 
       is used to return the amount of time remaining from any 
       previous adjustment that has not yet been completed.

The FreeBSD manual pages says similar:

     If olddelta is not a null pointer, the structure pointed to 
     will contain, upon return, the number of microseconds still 
     to be corrected from the earlier call.

This information should be returned in 'olddelta' regardless of 
whether the 'delta' argument is or is not NULL.  However, Linux/glibc
only returns valid information in 'olddelta' if 'delta' is non-NULL;
in other words it is only possible to enquire about 'olddelta' if
we at the same time change 'delta'.  FreeBSD does not have this 
limitation.  

The problem lies in the implementation of adjtimex().  I earlier
suggested a fix for this problem:

--- time.c.orig	2006-03-12 11:03:10.000000000 +1300
+++ time.c	2006-03-12 11:04:26.000000000 +1300
@@ -375,7 +375,9 @@

 		result = TIME_ERROR;
 	
-	if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
+	if(txc->modes == 0)
+	    txc->offset    = time_adjust;
+	else if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
 	    txc->offset	   = save_adjust;
 	else {
 	    txc->offset = shift_right(time_offset, SHIFT_UPDATE);

(the patch line numbers are wrong for 2.6.17, but the fix is the same.)

I made that suggestion in 2002:

http://marc.theaimsgroup.com/?l=linux-kernel&m=102404614411225&w=2

Some follow up acknowledged the problem but implied that the fix is 
more complex (and put off until later):

http://marc.theaimsgroup.com/?l=linux-kernel&m=103674954619484&w=2
http://marc.theaimsgroup.com/?l=linux-kernel&m=103689681229548&w=2

But later has never come, and the problem still exists.  It should 
be fixed.  There is also a relevant glibc report that I made
to get further background on this point: 
http://sourceware.org/bugzilla/show_bug.cgi?id=2449 .

Steps to reproduce:

This problem can be demonstrated with the following program:


/* t_adjtime.c */

#define _GNU_SOURCE
#include <sys/time.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
    struct timeval delta, oldDelta, *deltap;

    oldDelta.tv_sec = oldDelta.tv_usec = 0;

    delta.tv_sec =  (argc > 1) ? atoi(argv[1]) : 0;
    delta.tv_usec = (argc > 2) ? atoi(argv[2]) : 0;

    if (argc > 1)
        deltap = &delta;
    else
        deltap = NULL;

    if (adjtime(deltap, &oldDelta) == -1) {
        perror("adjtime");
        exit(EXIT_FAILURE);
    } 

    printf("old delta %ld.%06ld\n", oldDelta.tv_sec, oldDelta.tv_usec);
    exit(EXIT_SUCCESS);
} /* main */

If given command-line arguments, this program uses them 
to initialise 'delta'.  If no arguments are supplied
then delta is specified as NULL.  In either case, the program
prints the information returned in 'olddelta'.

On Linux we see something like the following:

# ./t_adjtime 2
old delta 0.000000
# ./t_adjtime
old delta 0.000000

The last line of output shows the problem.  When we do similar 
on FreeBSD, we see something like the following

# ./t_adjtime 2
old delta 0.000000
# ./t_adjtime
old delta 1.990000

== END ==

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.



More information about the Bugme-new mailing list