From owner-freebsd-bugs@freebsd.org Thu Apr 27 11:15:19 2017 Return-Path: Delivered-To: freebsd-bugs@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 37A2ED538C5 for ; Thu, 27 Apr 2017 11:15:19 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from kenobi.freebsd.org (kenobi.freebsd.org [IPv6:2001:1900:2254:206a::16:76]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1CC712DB for ; Thu, 27 Apr 2017 11:15:19 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from bugs.freebsd.org ([127.0.1.118]) by kenobi.freebsd.org (8.15.2/8.15.2) with ESMTP id v3RBFIVw048349 for ; Thu, 27 Apr 2017 11:15:18 GMT (envelope-from bugzilla-noreply@freebsd.org) From: bugzilla-noreply@freebsd.org To: freebsd-bugs@FreeBSD.org Subject: [Bug 218911] [uma] Memory corruption with certain item sizes Date: Thu, 27 Apr 2017 11:15:19 +0000 X-Bugzilla-Reason: AssignedTo X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: Base System X-Bugzilla-Component: kern X-Bugzilla-Version: 11.0-STABLE X-Bugzilla-Keywords: patch X-Bugzilla-Severity: Affects Some People X-Bugzilla-Who: fk@fabiankeil.de X-Bugzilla-Status: New X-Bugzilla-Resolution: X-Bugzilla-Priority: --- X-Bugzilla-Assigned-To: freebsd-bugs@FreeBSD.org X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version rep_platform op_sys bug_status keywords bug_severity priority component assigned_to reporter attachments.created Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: https://bugs.freebsd.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 Apr 2017 11:15:19 -0000 https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D218911 Bug ID: 218911 Summary: [uma] Memory corruption with certain item sizes Product: Base System Version: 11.0-STABLE Hardware: Any OS: Any Status: New Keywords: patch Severity: Affects Some People Priority: --- Component: kern Assignee: freebsd-bugs@FreeBSD.org Reporter: fk@fabiankeil.de Created attachment 182122 --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=3D182122&action= =3Dedit sys/vm: Set UMA_ZONE_OFFPAGE if the offset would be too large to fit into keg->uk_pgoff When creating an uma zone without specifying the UMA_ZONE_OFFPAGE flag uma may use the slab itself for its book-keeping purposes if it contains enough unused space. keg->uk_pgoff is an uint16_t. It can overflow in which case valid writes to correctly allocated items corrupt uma's book-keeping data. With INVARIANTS enabled, this results in a panic in uma_dbg_free(), without INVARIANTS the effect is less obvious. Here's a backtrace from a panic with INVARIANTS enabled using a test zone with item size 129024 which is one of the sizes that trigger the problem: (kgdb) where #0 __curthread () at ./machine/pcpu.h:222 #1 doadump (textdump=3D1) at /usr/src/sys/kern/kern_shutdown.c:298 #2 0xffffffff80555465 in kern_reboot (howto=3D260) at /usr/src/sys/kern/kern_shutdown.c:366 #3 0xffffffff80555a40 in vpanic (fmt=3D, ap=3D0xfffffe0113d= 69980) at /usr/src/sys/kern/kern_shutdown.c:759 #4 0xffffffff80555876 in kassert_panic (fmt=3D0xffffffff808c521f "Assertio= n %s failed at %s:%d") at /usr/src/sys/kern/kern_shutdown.c:649 #5 0xffffffff807dd333 in keg_fetch_slab (keg=3D0xfffff80005b52480, zone=3D0xfffff80005b53700, flags=3D2) at /usr/src/sys/vm/uma_core.c:2343 #6 0xffffffff807dc9ae in zone_fetch_slab (zone=3D0xfffff80005b53700, keg=3D0xfffff80005b52480, flags=3D2) at /usr/src/sys/vm/uma_core.c:2368 #7 0xffffffff807dca40 in zone_import (zone=3D0xfffff80005b53700, bucket=3D0xfffff800d7eae9f8, max=3D1, flags=3D2) at /usr/src/sys/vm/uma_cor= e.c:2494 #8 0xffffffff807d9341 in zone_alloc_bucket (zone=3D0xfffff80005b53700, udata=3D0x0, flags=3D2) at /usr/src/sys/vm/uma_core.c:2524 #9 uma_zalloc_arg (zone=3D0xfffff80005b53700, udata=3D0x0, flags=3D) at /usr/src/sys/vm/uma_core.c:2250 #10 0xffffffff8182329f in uma_zalloc (flags=3D2, zone=3D) at /usr/src/sys/vm/uma.h:336 #11 g_raid_init (mp=3D0xffffffff81856838 ) at /usr/src/sys/modules/geom/geom_raid/../../../geom/raid/g_raid.c:2496 #12 0xffffffff804d1125 in g_load_class (arg=3D, flag=3D) at /usr/src/sys/geom/geom_subr.c:124 #13 0xffffffff804cd7c7 in one_event () at /usr/src/sys/geom/geom_event.c:264 #14 g_run_events () at /usr/src/sys/geom/geom_event.c:286 #15 0xffffffff80517e64 in fork_exit (callout=3D0xffffffff804cfa60 , arg=3D0x0, frame=3D0xfffffe0113d69c00) at /usr/src/sys/kern/kern_fork.c:1040 #16 [...] (kgdb) f 5 #5 0xffffffff807dd333 in keg_fetch_slab (keg=3D0xfffff80005b52480, zone=3D0xfffff80005b53700, flags=3D2) at /usr/src/sys/vm/uma_core.c:2343 2343 MPASS(slab->us_keg =3D=3D keg); (kgdb) p slab->us_keg $1 =3D (uma_keg_t) 0xdeadc0dedeadc0de (kgdb) f 9 #9 uma_zalloc_arg (zone=3D0xfffff80005b53700, udata=3D0x0, flags=3D) at /usr/src/sys/vm/uma_core.c:2250 2250 bucket =3D zone_alloc_bucket(zone, udata, flags); (kgdb) p zone $2 =3D (uma_zone_t) 0xfffff80005b53700 (kgdb) p *zone $3 =3D {uz_lock =3D {lock_object =3D {lo_name =3D 0xffffffff8184f85a "uma_t= est", lo_flags =3D 21168128, lo_data =3D 0, lo_witness =3D 0xfffffe0000a0cf80}, m= tx_lock =3D 4}, uz_lockptr =3D 0xfffff80005b52480, uz_name =3D 0xffffffff8184f85a "uma_test", uz_link =3D {le_next =3D 0x0, = le_prev =3D 0xfffff80005b52510}, uz_buckets =3D {lh_first =3D 0x0}, uz_kegs =3D {lh_fir= st =3D 0xfffff80005b537b0}, uz_klink =3D {kl_link =3D {le_next =3D 0x0, le_prev =3D 0xfffff80005b537a8}, kl_keg =3D 0xfffff80005b52480}, uz_s= lab =3D 0xffffffff807dc940 , uz_ctor =3D 0xffffffff807dd730 , uz_dtor =3D 0xffffffff807dd780 , uz_init =3D 0x0, uz_fini =3D 0x0, uz_import =3D 0xffffffff807dc9f0 , uz_relea= se =3D 0xffffffff807dcc90 , uz_arg =3D 0xfffff80005b53700, uz_flags = =3D 0, uz_size =3D 129024, uz_allocs =3D 0, uz_fails =3D 0, uz_frees =3D 0, uz_sleeps =3D 0, uz_count =3D 1, uz_count_min =3D 1, uz_warning =3D 0x0, = uz_ratecheck =3D {tv_sec =3D 0, tv_usec =3D 0}, uz_maxaction =3D {ta_link =3D {stqe_next= =3D 0x0}, ta_pending =3D 0, ta_priority =3D 0, ta_func =3D 0x0, ta_context =3D 0x0}, 0x0}, uz_cpu =3D {{uc_freebucket =3D 0x0, uc_allocbucket =3D 0x0, uc_allocs =3D= 0, uc_frees =3D 0}}} (kgdb) f 11 #11 g_raid_init (mp=3D0xffffffff81856838 ) at /usr/src/sys/modules/geom/geom_raid/../../../geom/raid/g_raid.c:2496 2496 p =3D uma_zalloc(uma_test_zone, M_WAITOK); (kgdb) p i $4 =3D 0 (kgdb) l - 2491 2492 uma_test_zone =3D uma_zcreate("uma_test", uma_test_zone_item_size, NULL, NULL, 2493 NULL, NULL, 0, 0); 2494 2495 for (i =3D 0; i <=3D uma_test_zone_item_size; i++) { 2496 p =3D uma_zalloc(uma_test_zone, M_WAITOK); 2497 memset(p, 0x10, i); 2498 G_RAID_DEBUG(1, "Freeing item after filling %d byte= s.", i); 2499 uma_zfree(uma_test_zone, p); 2500 } (kgdb) f 9 #9 uma_zalloc_arg (zone=3D0xfffff80005b53700, udata=3D0x0, flags=3D) at /usr/src/sys/vm/uma_core.c:2250 2250 bucket =3D zone_alloc_bucket(zone, udata, flags); (kgdb) p zone->uz_kegs->lh_first->kl_keg $6 =3D (uma_keg_t) 0xfffff80005b52480 (kgdb) p *zone->uz_kegs->lh_first->kl_keg $7 =3D {uk_lock =3D {lock_object =3D {lo_name =3D 0xffffffff8184f85a "uma_t= est", lo_flags =3D 21168128, lo_data =3D 0, lo_witness =3D 0xfffffe0000a0cf80}, m= tx_lock =3D 18446735277663592448}, uk_hash =3D {uh_slab_hash =3D 0x0, uh_hashsize =3D 0, uh_hashmask =3D 0}, uk_zones =3D {lh_first =3D 0xfffff80005b53700}, uk_= part_slab =3D {lh_first =3D 0x0}, uk_free_slab =3D {lh_first =3D 0x0}, uk_full_slab = =3D {lh_first =3D 0x0}, uk_align =3D 0, uk_pages =3D 32, uk_free =3D 1, uk_reserve =3D 0, uk_size =3D 129024, uk_rsize =3D 129024, uk_maxpages =3D 0, uk_init =3D 0xffffffff807dd7b0 , uk_fini =3D 0xffffffff807dd7e0 , uk_allocf =3D 0xffffffff807db690 , uk_freef =3D 0xffffffff807db770 , uk_offset =3D 0, uk_kva =3D = 0, uk_slabzone =3D 0x0, uk_pgoff =3D 65424, uk_ppera =3D 32, uk_ipers =3D 1, u= k_flags =3D 0, uk_name =3D 0xffffffff8184f85a "uma_test", uk_link =3D { le_next =3D 0xfffff80005b52300, le_prev =3D 0xffffffff80f45d00 }} (kgdb) p sizeof(struct uma_slab) $8 =3D 112 (kgdb) p zone->uz_kegs->lh_first->kl_keg->uk_ppera $9 =3D 32 (kgdb) p 4096 * zone->uz_kegs->lh_first->kl_keg->uk_ppera $10 =3D 131072 (kgdb) p 4096 * zone->uz_kegs->lh_first->kl_keg->uk_ppera - sizeof(struct uma_slab) $11 =3D 130960 (kgdb) p 4096 * zone->uz_kegs->lh_first->kl_keg->uk_ppera - sizeof(struct uma_slab) - 65536 $12 =3D 65424 (kgdb) p zone->uz_kegs->lh_first->kl_keg->uk_size $13 =3D 129024 (kgdb) p 4096 * zone->uz_kegs->lh_first->kl_keg->uk_ppera -=20 zone->uz_kegs->lh_first->kl_keg->uk_rsize $14 =3D 2048 The attached patch lets uma set the UMA_ZONE_OFFPAGE if keg->uk_pgoff would otherwise be used but is too small to hold the correct offset. Changing keg->uk_pgoff's type should work as well but I haven't tested it. Obtained from: ElectroBSD --=20 You are receiving this mail because: You are the assignee for the bug.=