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 | |
| 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')
| -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)) * |
