Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

timerfd: add flags check

As requested by Michael, add a missing check for valid flags in
timerfd_settime(), and make it return EINVAL in case some extra bits are
set.

Michael said:
If this is to be any use to userland apps that want to check flag
support (perhaps it is too late already), then the sooner we get it
into the kernel the better: 2.6.29 would be good; earlier stables as
well would be even better.

[akpm@linux-foundation.org: remove unused TFD_FLAGS_SET]
Acked-by: Michael Kerrisk <mtk.manpages@gmail.com>
Signed-off-by: Davide Libenzi <davidel@xmailserver.org>
Cc: <stable@kernel.org> [2.6.27.x, 2.6.28.x]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Davide Libenzi and committed by
Linus Torvalds
610d18f4 ef35ce23

+18 -10
+6 -6
fs/timerfd.c
··· 186 186 BUILD_BUG_ON(TFD_CLOEXEC != O_CLOEXEC); 187 187 BUILD_BUG_ON(TFD_NONBLOCK != O_NONBLOCK); 188 188 189 - if (flags & ~(TFD_CLOEXEC | TFD_NONBLOCK)) 190 - return -EINVAL; 191 - if (clockid != CLOCK_MONOTONIC && 192 - clockid != CLOCK_REALTIME) 189 + if ((flags & ~TFD_CREATE_FLAGS) || 190 + (clockid != CLOCK_MONOTONIC && 191 + clockid != CLOCK_REALTIME)) 193 192 return -EINVAL; 194 193 195 194 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ··· 200 201 hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS); 201 202 202 203 ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx, 203 - flags & (O_CLOEXEC | O_NONBLOCK)); 204 + flags & TFD_SHARED_FCNTL_FLAGS); 204 205 if (ufd < 0) 205 206 kfree(ctx); 206 207 ··· 218 219 if (copy_from_user(&ktmr, utmr, sizeof(ktmr))) 219 220 return -EFAULT; 220 221 221 - if (!timespec_valid(&ktmr.it_value) || 222 + if ((flags & ~TFD_SETTIME_FLAGS) || 223 + !timespec_valid(&ktmr.it_value) || 222 224 !timespec_valid(&ktmr.it_interval)) 223 225 return -EINVAL; 224 226
+12 -4
include/linux/timerfd.h
··· 11 11 /* For O_CLOEXEC and O_NONBLOCK */ 12 12 #include <linux/fcntl.h> 13 13 14 - /* Flags for timerfd_settime. */ 14 + /* 15 + * CAREFUL: Check include/asm-generic/fcntl.h when defining 16 + * new flags, since they might collide with O_* ones. We want 17 + * to re-use O_* flags that couldn't possibly have a meaning 18 + * from eventfd, in order to leave a free define-space for 19 + * shared O_* flags. 20 + */ 15 21 #define TFD_TIMER_ABSTIME (1 << 0) 16 - 17 - /* Flags for timerfd_create. */ 18 22 #define TFD_CLOEXEC O_CLOEXEC 19 23 #define TFD_NONBLOCK O_NONBLOCK 20 24 25 + #define TFD_SHARED_FCNTL_FLAGS (TFD_CLOEXEC | TFD_NONBLOCK) 26 + /* Flags for timerfd_create. */ 27 + #define TFD_CREATE_FLAGS TFD_SHARED_FCNTL_FLAGS 28 + /* Flags for timerfd_settime. */ 29 + #define TFD_SETTIME_FLAGS TFD_TIMER_ABSTIME 21 30 22 31 #endif /* _LINUX_TIMERFD_H */ 23 -