Commit 52bfb36050c8529d9031d2c2513b281a360922ec

Authored by John Stultz
Committed by Ingo Molnar
1 parent 8232fd6252

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>

Showing 2 changed files with 7 additions and 3 deletions Side-by-side Diff

include/linux/timex.h
... ... @@ -137,6 +137,7 @@
137 137 #define ADJ_TIMECONST 0x0020 /* pll time constant */
138 138 #define ADJ_TICK 0x4000 /* tick value */
139 139 #define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */
  140 +#define ADJ_OFFSET_SS_READ 0xa001 /* read-only adjtime */
140 141  
141 142 /* xntp 3.4 compatibility names */
142 143 #define MOD_OFFSET ADJ_OFFSET
... ... @@ -249,10 +249,12 @@
249 249  
250 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 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 256 return -EINVAL;
  257 + }
256 258  
257 259 if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET))
258 260 /* adjustment Offset limited to +- .512 seconds */
... ... @@ -372,7 +374,8 @@
372 374 leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
373 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 379 txc->offset = save_adjust;
377 380 else
378 381 txc->offset = ((long)shift_right(time_offset, SHIFT_UPDATE)) *