aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2006-03-25 06:06:35 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-25 11:22:49 -0500
commit7d99b7d634d81bb372e03e4561c80430aa4cfac2 (patch)
tree905654bd7cb4940126606cf212c61079eeca722b
parentc08b8a49100715b20e6f7c997e992428b5e06078 (diff)
[PATCH] Validate and sanitze itimer timeval from userspace
According to the specification the timevals must be validated and an errorcode -EINVAL returned in case the timevals are not in canonical form. This check was never done in Linux. The pre 2.6.16 code converted invalid timevals silently. Negative timeouts were converted by the timeval_to_jiffies conversion to the maximum timeout. hrtimers and the ktime_t operations expect timevals in canonical form. Otherwise random results might happen on 32 bits machines due to the optimized ktime_add/sub operations. Negative timeouts are treated as already expired. This might break applications which work on pre 2.6.16. To prevent random behaviour and API breakage the timevals are checked and invalid timevals sanitized in a simliar way as the pre 2.6.16 code did. Invalid timevals are reported with a per boot limited number of kernel messages so applications which use this misfeature can be corrected. After a grace period of one year the sanitizing should be replaced by a correct validation check. This is also documented in Documentation/feature-removal-schedule.txt The validation and sanitizing is done inside do_setitimer so all callers (sys_setitimer, compat_sys_setitimer, osf_setitimer) are catched. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--Documentation/feature-removal-schedule.txt12
-rw-r--r--kernel/itimer.c66
2 files changed, 78 insertions, 0 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 21272e4b4a5c..495858b236b6 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -176,6 +176,18 @@ Who: Richard Knutsson <ricknu-0@student.ltu.se> and Greg Kroah-Hartman <gregkh@s
176 176
177--------------------------- 177---------------------------
178 178
179What: Usage of invalid timevals in setitimer
180When: March 2007
181Why: POSIX requires to validate timevals in the setitimer call. This
182 was never done by Linux. The invalid (e.g. negative timevals) were
183 silently converted to more or less random timeouts and intervals.
184 Until the removal a per boot limited number of warnings is printed
185 and the timevals are sanitized.
186
187Who: Thomas Gleixner <tglx@linutronix.de>
188
189---------------------------
190
179What: I2C interface of the it87 driver 191What: I2C interface of the it87 driver
180When: January 2007 192When: January 2007
181Why: The ISA interface is faster and should be always available. The I2C 193Why: The ISA interface is faster and should be always available. The I2C
diff --git a/kernel/itimer.c b/kernel/itimer.c
index a2dc375927d8..680e6b70c872 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -143,6 +143,60 @@ int it_real_fn(void *data)
143 return HRTIMER_NORESTART; 143 return HRTIMER_NORESTART;
144} 144}
145 145
146/*
147 * We do not care about correctness. We just sanitize the values so
148 * the ktime_t operations which expect normalized values do not
149 * break. This converts negative values to long timeouts similar to
150 * the code in kernel versions < 2.6.16
151 *
152 * Print a limited number of warning messages when an invalid timeval
153 * is detected.
154 */
155static void fixup_timeval(struct timeval *tv, int interval)
156{
157 static int warnlimit = 10;
158 unsigned long tmp;
159
160 if (warnlimit > 0) {
161 warnlimit--;
162 printk(KERN_WARNING
163 "setitimer: %s (pid = %d) provided "
164 "invalid timeval %s: tv_sec = %ld tv_usec = %ld\n",
165 current->comm, current->pid,
166 interval ? "it_interval" : "it_value",
167 tv->tv_sec, (long) tv->tv_usec);
168 }
169
170 tmp = tv->tv_usec;
171 if (tmp >= USEC_PER_SEC) {
172 tv->tv_usec = tmp % USEC_PER_SEC;
173 tv->tv_sec += tmp / USEC_PER_SEC;
174 }
175
176 tmp = tv->tv_sec;
177 if (tmp > LONG_MAX)
178 tv->tv_sec = LONG_MAX;
179}
180
181/*
182 * Returns true if the timeval is in canonical form
183 */
184#define timeval_valid(t) \
185 (((t)->tv_sec >= 0) && (((unsigned long) (t)->tv_usec) < USEC_PER_SEC))
186
187/*
188 * Check for invalid timevals, sanitize them and print a limited
189 * number of warnings.
190 */
191static void check_itimerval(struct itimerval *value) {
192
193 if (unlikely(!timeval_valid(&value->it_value)))
194 fixup_timeval(&value->it_value, 0);
195
196 if (unlikely(!timeval_valid(&value->it_interval)))
197 fixup_timeval(&value->it_interval, 1);
198}
199
146int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) 200int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
147{ 201{
148 struct task_struct *tsk = current; 202 struct task_struct *tsk = current;
@@ -150,6 +204,18 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
150 ktime_t expires; 204 ktime_t expires;
151 cputime_t cval, cinterval, nval, ninterval; 205 cputime_t cval, cinterval, nval, ninterval;
152 206
207 /*
208 * Validate the timevals in value.
209 *
210 * Note: Although the spec requires that invalid values shall
211 * return -EINVAL, we just fixup the value and print a limited
212 * number of warnings in order not to break users of this
213 * historical misfeature.
214 *
215 * Scheduled for replacement in March 2007
216 */
217 check_itimerval(value);
218
153 switch (which) { 219 switch (which) {
154 case ITIMER_REAL: 220 case ITIMER_REAL:
155again: 221again: