Most recent kernel where this bug did not occur: Distribution: Hardware Environment: Systems with 896MB of memory or more Software Environment: Problem Description: There is a unsigned long overflow in page_alloc.c in setup_per_zone_pages_min. unsigned long tmp; spin_lock_irqsave(&zone->lru_lock, flags); tmp = (pages_min * zone->present_pages) / lowmem_pages; If min_free_kbytes is changed to a value slightly larger then 76260 the tmp = (... calculation will overflow on a 32bit arch resulting in setting pages_min for the normal zone to a bad value. There is no check in min_free_kbytes_sysctl_handler to cap min_free_kbytes to prevent this from happening. something like tmp = (pages_min * (zone->present_pages >> 3))/(lowmem_pages >> 3) will give the same result +- 1 page without overflowing for larger min_free_kbytes. Steps to reproduce: Look at /proc/zoneinfo increase min_free_kbytes to 131072 Look at /proc/zoneinfo
I think it's actually worse than this. Surely zone->present_pages could be 2^24 on a 64GB system (OK, 63 highmem, but who's counting), which means that min_free_kbytes is limited to about 1024K to make it still work? I'd be tempted to just do tmp = pages_min * (zone->present_pages / lowmem_pages), which will lose us a little granularity, but do we really care? Worst case we could do something like: tmp = (pages_min * ((zone->present_pages << 4) / lowmem_pages)) >> 4 What's the worst case for min_free_kbytes?
This should have been fixed by commit ac924c6034d9095f95ee889f7e31bbb9145da0c2 in kernel 2.6.17, this bug should then be closed.