Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 27 Apr 2017 11:15:19 +0000
From:      bugzilla-noreply@freebsd.org
To:        freebsd-bugs@FreeBSD.org
Subject:   [Bug 218911] [uma] Memory corruption with certain item sizes
Message-ID:  <bug-218911-8@https.bugs.freebsd.org/bugzilla/>

next in thread | raw e-mail | index | archive | help
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<optimized out>, 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<optimi=
zed out>)
at /usr/src/sys/vm/uma_core.c:2250
#10 0xffffffff8182329f in uma_zalloc (flags=3D2, zone=3D<optimized out>) at
/usr/src/sys/vm/uma.h:336
#11 g_raid_init (mp=3D0xffffffff81856838 <g_raid_class>) at
/usr/src/sys/modules/geom/geom_raid/../../../geom/raid/g_raid.c:2496
#12 0xffffffff804d1125 in g_load_class (arg=3D<optimized out>, flag=3D<opti=
mized
out>) 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
<g_event_procbody>, arg=3D0x0, frame=3D0xfffffe0113d69c00) at
/usr/src/sys/kern/kern_fork.c:1040
#16 <signal handler called>
[...]
(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<optimi=
zed out>)
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 <zone_fetch_slab>, uz_ctor =3D 0xffffffff807dd730
<trash_ctor>, uz_dtor =3D 0xffffffff807dd780 <trash_dtor>, uz_init =3D 0x0,
  uz_fini =3D 0x0, uz_import =3D 0xffffffff807dc9f0 <zone_import>, uz_relea=
se =3D
0xffffffff807dcc90 <zone_release>, 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 <g_raid_class>) 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<optimi=
zed out>)
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 <trash_init>, uk_fini =3D 0xffffffff807dd7e0 <trash_fini=
>,
uk_allocf =3D 0xffffffff807db690 <page_alloc>,
  uk_freef =3D 0xffffffff807db770 <page_free>, 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 <uma_keg=
s>}}
(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.=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-218911-8>