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

epoll: convert max_user_watches to long

On a 16TB machine, max_user_watches has an integer overflow. Convert it
to use a long and handle the associated fallout.

Signed-off-by: Robin Holt <holt@sgi.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Acked-by: Davide Libenzi <davidel@xmailserver.org>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Robin Holt and committed by
Linus Torvalds
52bd19f7 65329bf4

+13 -9
+12 -8
fs/eventpoll.c
··· 217 217 * Configuration options available inside /proc/sys/fs/epoll/ 218 218 */ 219 219 /* Maximum number of epoll watched descriptors, per user */ 220 - static int max_user_watches __read_mostly; 220 + static long max_user_watches __read_mostly; 221 221 222 222 /* 223 223 * This mutex is used to serialize ep_free() and eventpoll_release_file(). ··· 240 240 241 241 #include <linux/sysctl.h> 242 242 243 - static int zero; 243 + static long zero; 244 + static long long_max = LONG_MAX; 244 245 245 246 ctl_table epoll_table[] = { 246 247 { 247 248 .procname = "max_user_watches", 248 249 .data = &max_user_watches, 249 - .maxlen = sizeof(int), 250 + .maxlen = sizeof(max_user_watches), 250 251 .mode = 0644, 251 - .proc_handler = proc_dointvec_minmax, 252 + .proc_handler = proc_doulongvec_minmax, 252 253 .extra1 = &zero, 254 + .extra2 = &long_max, 253 255 }, 254 256 { } 255 257 }; ··· 563 561 /* At this point it is safe to free the eventpoll item */ 564 562 kmem_cache_free(epi_cache, epi); 565 563 566 - atomic_dec(&ep->user->epoll_watches); 564 + atomic_long_dec(&ep->user->epoll_watches); 567 565 568 566 return 0; 569 567 } ··· 900 898 { 901 899 int error, revents, pwake = 0; 902 900 unsigned long flags; 901 + long user_watches; 903 902 struct epitem *epi; 904 903 struct ep_pqueue epq; 905 904 906 - if (unlikely(atomic_read(&ep->user->epoll_watches) >= 907 - max_user_watches)) 905 + user_watches = atomic_long_read(&ep->user->epoll_watches); 906 + if (unlikely(user_watches >= max_user_watches)) 908 907 return -ENOSPC; 909 908 if (!(epi = kmem_cache_alloc(epi_cache, GFP_KERNEL))) 910 909 return -ENOMEM; ··· 969 966 970 967 spin_unlock_irqrestore(&ep->lock, flags); 971 968 972 - atomic_inc(&ep->user->epoll_watches); 969 + atomic_long_inc(&ep->user->epoll_watches); 973 970 974 971 /* We have to call this outside the lock */ 975 972 if (pwake) ··· 1429 1426 */ 1430 1427 max_user_watches = (((si.totalram - si.totalhigh) / 25) << PAGE_SHIFT) / 1431 1428 EP_ITEM_COST; 1429 + BUG_ON(max_user_watches < 0); 1432 1430 1433 1431 /* Initialize the structure used to perform safe poll wait head wake ups */ 1434 1432 ep_nested_calls_init(&poll_safewake_ncalls);
+1 -1
include/linux/sched.h
··· 683 683 atomic_t fanotify_listeners; 684 684 #endif 685 685 #ifdef CONFIG_EPOLL 686 - atomic_t epoll_watches; /* The number of file descriptors currently watched */ 686 + atomic_long_t epoll_watches; /* The number of file descriptors currently watched */ 687 687 #endif 688 688 #ifdef CONFIG_POSIX_MQUEUE 689 689 /* protected by mq_lock */