When a file on a UFS filesystem is being opened, a decision is made in ufs_open() on whether to give the file a private copy of the superblock or a pointer to a shared copy. In ufs_close() an attempt is made to guess what decision was made in ufs_open(). However, in at least one situation (described below) ufs_close() guesses wrong and deallocates the shared copy while an opened file has a pointer to it. Further use of that opened file results in use-after-free. The specific situation that demonstrates the problem is as follows: 1) Start the machine 2) When the loader menu appears, escape to loader prompt 3) Execute the command "map-vdisk /filesystem.img" This is expected to create a new virtual device named "vdisk0:". The file /filesystem.img must reside on a UFS filesystem. The file itself should contain a valid filesystem whose type is supported by the loader (e.g. UFS). 4) Execute the command "set currdev=vdisk0:" 5) Execute the command "ls /" The "ls" command is expected to complete successfully but it doesn't. A hang may be observed or some unexpected error message.
This use-after-free is related to keeping a file residing on a UFS filesystem open after that filesystem is unmounted. The concept of mounting and unmounting filesystems was introduced in the loader by Toomas Soome. He is also the person who introduced vdisks support in the loader. I'm adding him to the CC list so he can help come up with an idea on how to make these two features work together.
(In reply to Jordan Gordeev from comment #0) hm, based on this description, switching currdev does apparently trigger the "umount" of ufs despite we should have open file from it. We probably want to do something like transfer mount to vdisk (so we avoid leaking the mount on unmapping vdisk) and to make sure we have valid data still. You can verify if keeping currdev as is and accessing vdisk0: directly (example: ls vdisk0:) will work as expected.