[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 = δ
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