diff options
author | John Stultz <johnstul@us.ibm.com> | 2007-11-26 14:42:19 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2007-11-26 14:42:19 -0500 |
commit | 52bfb36050c8529d9031d2c2513b281a360922ec (patch) | |
tree | 7d116ece2ed21b8319e800efc0c2fd70818f01d3 /kernel/time/ntp.c | |
parent | 8232fd625217dc641ed05dd238a8bb5c82828082 (diff) |
time: add ADJ_OFFSET_SS_READ
Michael Kerrisk reported that a long standing bug in the adjtimex()
system call causes glibc's adjtime(3) function to deliver the wrong
results if 'delta' is NULL.
add the ADJ_OFFSET_SS_READ API detail, which will be used by glibc
to fix this API compatibility bug.
Also see: http://bugzilla.kernel.org/show_bug.cgi?id=6761
[ mingo@elte.hu: added patch description and made it backwards compatible ]
NOTE: the new flag is defined 0xa001 so that it returns -EINVAL on
older kernels - this way glibc can use it safely. Suggested by Ulrich
Drepper.
Acked-by: Ulrich Drepper <drepper@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/time/ntp.c')
-rw-r--r-- | kernel/time/ntp.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 14a2ecf2b318..e64efaf957e8 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -249,10 +249,12 @@ int do_adjtimex(struct timex *txc) | |||
249 | 249 | ||
250 | /* Now we validate the data before disabling interrupts */ | 250 | /* Now we validate the data before disabling interrupts */ |
251 | 251 | ||
252 | if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) | 252 | if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) { |
253 | /* singleshot must not be used with any other mode bits */ | 253 | /* singleshot must not be used with any other mode bits */ |
254 | if (txc->modes != ADJ_OFFSET_SINGLESHOT) | 254 | if (txc->modes != ADJ_OFFSET_SINGLESHOT && |
255 | txc->modes != ADJ_OFFSET_SS_READ) | ||
255 | return -EINVAL; | 256 | return -EINVAL; |
257 | } | ||
256 | 258 | ||
257 | if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET)) | 259 | if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET)) |
258 | /* adjustment Offset limited to +- .512 seconds */ | 260 | /* adjustment Offset limited to +- .512 seconds */ |
@@ -372,7 +374,8 @@ int do_adjtimex(struct timex *txc) | |||
372 | leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0) | 374 | leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0) |
373 | result = TIME_ERROR; | 375 | result = TIME_ERROR; |
374 | 376 | ||
375 | if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) | 377 | if ((txc->modes == ADJ_OFFSET_SINGLESHOT) || |
378 | (txc->modes == ADJ_OFFSET_SS_READ)) | ||
376 | txc->offset = save_adjust; | 379 | txc->offset = save_adjust; |
377 | else | 380 | else |
378 | txc->offset = ((long)shift_right(time_offset, SHIFT_UPDATE)) * | 381 | txc->offset = ((long)shift_right(time_offset, SHIFT_UPDATE)) * |