aboutsummaryrefslogtreecommitdiffstats
path: root/fs/timerfd.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/timerfd.c')
-rw-r--r--fs/timerfd.c45
1 files changed, 21 insertions, 24 deletions
diff --git a/fs/timerfd.c b/fs/timerfd.c
index dffeb3795af1..d03822bbf190 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -234,19 +234,17 @@ static const struct file_operations timerfd_fops = {
234 .llseek = noop_llseek, 234 .llseek = noop_llseek,
235}; 235};
236 236
237static struct file *timerfd_fget(int fd) 237static int timerfd_fget(int fd, struct fd *p)
238{ 238{
239 struct file *file; 239 struct fd f = fdget(fd);
240 240 if (!f.file)
241 file = fget(fd); 241 return -EBADF;
242 if (!file) 242 if (f.file->f_op != &timerfd_fops) {
243 return ERR_PTR(-EBADF); 243 fdput(f);
244 if (file->f_op != &timerfd_fops) { 244 return -EINVAL;
245 fput(file);
246 return ERR_PTR(-EINVAL);
247 } 245 }
248 246 *p = f;
249 return file; 247 return 0;
250} 248}
251 249
252SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) 250SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
@@ -284,7 +282,7 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
284 const struct itimerspec __user *, utmr, 282 const struct itimerspec __user *, utmr,
285 struct itimerspec __user *, otmr) 283 struct itimerspec __user *, otmr)
286{ 284{
287 struct file *file; 285 struct fd f;
288 struct timerfd_ctx *ctx; 286 struct timerfd_ctx *ctx;
289 struct itimerspec ktmr, kotmr; 287 struct itimerspec ktmr, kotmr;
290 int ret; 288 int ret;
@@ -297,10 +295,10 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
297 !timespec_valid(&ktmr.it_interval)) 295 !timespec_valid(&ktmr.it_interval))
298 return -EINVAL; 296 return -EINVAL;
299 297
300 file = timerfd_fget(ufd); 298 ret = timerfd_fget(ufd, &f);
301 if (IS_ERR(file)) 299 if (ret)
302 return PTR_ERR(file); 300 return ret;
303 ctx = file->private_data; 301 ctx = f.file->private_data;
304 302
305 timerfd_setup_cancel(ctx, flags); 303 timerfd_setup_cancel(ctx, flags);
306 304
@@ -334,7 +332,7 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
334 ret = timerfd_setup(ctx, flags, &ktmr); 332 ret = timerfd_setup(ctx, flags, &ktmr);
335 333
336 spin_unlock_irq(&ctx->wqh.lock); 334 spin_unlock_irq(&ctx->wqh.lock);
337 fput(file); 335 fdput(f);
338 if (otmr && copy_to_user(otmr, &kotmr, sizeof(kotmr))) 336 if (otmr && copy_to_user(otmr, &kotmr, sizeof(kotmr)))
339 return -EFAULT; 337 return -EFAULT;
340 338
@@ -343,14 +341,13 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
343 341
344SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) 342SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr)
345{ 343{
346 struct file *file; 344 struct fd f;
347 struct timerfd_ctx *ctx; 345 struct timerfd_ctx *ctx;
348 struct itimerspec kotmr; 346 struct itimerspec kotmr;
349 347 int ret = timerfd_fget(ufd, &f);
350 file = timerfd_fget(ufd); 348 if (ret)
351 if (IS_ERR(file)) 349 return ret;
352 return PTR_ERR(file); 350 ctx = f.file->private_data;
353 ctx = file->private_data;
354 351
355 spin_lock_irq(&ctx->wqh.lock); 352 spin_lock_irq(&ctx->wqh.lock);
356 if (ctx->expired && ctx->tintv.tv64) { 353 if (ctx->expired && ctx->tintv.tv64) {
@@ -362,7 +359,7 @@ SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr)
362 kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); 359 kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
363 kotmr.it_interval = ktime_to_timespec(ctx->tintv); 360 kotmr.it_interval = ktime_to_timespec(ctx->tintv);
364 spin_unlock_irq(&ctx->wqh.lock); 361 spin_unlock_irq(&ctx->wqh.lock);
365 fput(file); 362 fdput(f);
366 363
367 return copy_to_user(otmr, &kotmr, sizeof(kotmr)) ? -EFAULT: 0; 364 return copy_to_user(otmr, &kotmr, sizeof(kotmr)) ? -EFAULT: 0;
368} 365}