kern/152200: Overflow in vmspace_swap_count()
Andrey Zonov
andrey.zonov at gmail.com
Sat Nov 13 13:20:05 UTC 2010
>Number: 152200
>Category: kern
>Synopsis: Overflow in vmspace_swap_count()
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sat Nov 13 13:20:04 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator: Andrey Zonov
>Release: 8.1-RELEASE
>Organization:
>Environment:
FreeBSD xxx.xxx.ru 8.1-RELEASE FreeBSD 8.1-RELEASE #0 r212732M: Tue Mar 30 03:14:51 MSD 2010 root at xxx.xxx.ru:/usr/obj/usr/src/sys/GENERIC amd64
>Description:
When memory exhasted, [pagedaemon] calls src/sys/vm/vm_pageout.c:vm_pageout_oom(), this function calls src/sys/vm/swap_pager.c:vmspace_swap_count() for swap usage calculation of process.
vmspace_swap_count() uses type `int' for address defference and it often leads to `n' variable overflow and system may kill random swapped processes, not only with big memory usage.
>How-To-Repeat:
# swapon /dev/something
# fetch http://zonov.pp.ru/tests/swapped_test.tbz
# tar xyf swapped_test.tbz
# cd swapped_test
# make test
Be carefully, that may hang up your system!
>Fix:
Patch attached with submission follows:
Index: /usr/src/sys/vm/vm_map.h
===================================================================
--- /usr/src/sys/vm/vm_map.h (revision 212732)
+++ /usr/src/sys/vm/vm_map.h (working copy)
@@ -373,6 +373,6 @@
int flags);
int vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end,
int flags);
-int vmspace_swap_count (struct vmspace *vmspace);
+long vmspace_swap_count (struct vmspace *vmspace);
#endif /* _KERNEL */
#endif /* _VM_MAP_ */
Index: /usr/src/sys/vm/swap_pager.c
===================================================================
--- /usr/src/sys/vm/swap_pager.c (revision 212732)
+++ /usr/src/sys/vm/swap_pager.c (working copy)
@@ -2412,12 +2412,12 @@
* if the VM object has any swap use at all the associated map entries
* count for at least 1 swap page.
*/
-int
+long
vmspace_swap_count(struct vmspace *vmspace)
{
vm_map_t map = &vmspace->vm_map;
vm_map_entry_t cur;
- int count = 0;
+ long count = 0;
for (cur = map->header.next; cur != &map->header; cur = cur->next) {
vm_object_t object;
@@ -2427,7 +2427,7 @@
VM_OBJECT_LOCK(object);
if (object->type == OBJT_SWAP &&
object->un_pager.swp.swp_bcount != 0) {
- int n = (cur->end - cur->start) / PAGE_SIZE;
+ vm_offset_t n = (cur->end - cur->start) / PAGE_SIZE;
count += object->un_pager.swp.swp_bcount *
SWAP_META_PAGES * n / object->size + 1;
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list