Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 23 Jul 2023 15:30:05 +0000
From:      bugzilla-noreply@freebsd.org
To:        bugs@FreeBSD.org
Subject:   [Bug 192839] Duplicate entries in an mtree file cause nmtree to coredump
Message-ID:  <bug-192839-227-miEB5YDZtQ@https.bugs.freebsd.org/bugzilla/>
In-Reply-To: <bug-192839-227@https.bugs.freebsd.org/bugzilla/>
References:  <bug-192839-227@https.bugs.freebsd.org/bugzilla/>

next in thread | previous in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D192839

--- Comment #7 from Felix Dietrich <felix.dietrich+freebsd-bugtracker@sperr=
haken.name> ---
The problem that brought me here is a segmentation fault resulting from fee=
ding
the following example to nmtree:

  /set type=3Ddir
  .
    dup
    ..
    dup
      child_entry type=3Dfile


Line numbers in the following paragraph are according to FreeBSD
12.4-RELEASE-p2 (git hash 149768b65d619833331bcf0c2fb121b20643f2f1).

The segmentation fault is caused by using the memory pointed to by centry
(=E2=80=9Clast =3D cenry=E2=80=9D in the =E2=80=9Cspec=E2=80=9D function [s=
pec.c:252]) after it has been freed in
replacenode (=E2=80=9Cfree(new)=E2=80=9D [spec.c:536]).  (A comment in the =
addchild function
[spec.c:775] indicates that at least addchild is aware that replacenode will
free the centry.)  The memory gets reused for the next centry (=E2=80=9Ccen=
try =3D
calloc(=E2=80=A6=E2=80=9D [spec.c:207]) and assigned the global defaults (=
=E2=80=9C*centry =3D ginfo=E2=80=9D
[spec.c:209]).  The parent member of the ginfo record is NULL [spec.c:122],
and, as a consequence of the faulty memory reuse, addchild gets passed NULL
(=E2=80=9Caddchild(last->parent, centry)=E2=80=9D [spec.c:260]) for its pat=
hparent parameter.=20
This results in a segmentation fault early in addchild because of a NULL
dereference (=E2=80=9Ccur =3D pathparent->child=E2=80=9D [spec.c:734]).  Al=
so note that
last->type gets overridden and set to F_FILE [spec.c:215], and, therefore, =
not
the branch =E2=80=9Clast->type =3D=3D F_DIR && !(last->flags & F_DONE)=E2=
=80=9D [spec.c:245] is
taken, as one would expect by correct operation, but the final else branch =
=E2=80=9Cnew
relative child in parent dir=E2=80=9D [spec.c:253].

I have not reasoned much about solutions.  It might be possible for a quick=
 and
dirty fix to dispense with the =E2=80=9Cfree(new)=E2=80=9D call in replacen=
ode [spec.c:536] at
the cost of leaking memory and making the code even harder to reason about.=
=20
Another solutions could make replacenode actually replace the node (removing
=E2=80=9Ccur=E2=80=9D from the data structure and emplacing =E2=80=9Cnew=E2=
=80=9D in its stead) instead of
overwriting the members of the existing =E2=80=9Ccur=E2=80=9D node =E2=80=
=93 but I have not tried to
understand and follow the assumptions addchild makes of replacenode=CA=BCs
operations.

--=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-192839-227-miEB5YDZtQ>