Page MenuHomeFreeBSD

Don't invoke semunload() if seminit() fails during MOD_LOAD.
ClosedPublic

Authored by jhb on Oct 6 2020, 4:58 PM.
Tags
None
Referenced Files
Unknown Object (File)
Sep 23 2024, 10:10 PM
Unknown Object (File)
Sep 23 2024, 10:10 PM
Unknown Object (File)
Sep 23 2024, 10:10 PM
Unknown Object (File)
Sep 23 2024, 10:00 PM
Unknown Object (File)
Sep 18 2024, 12:41 AM
Unknown Object (File)
Sep 8 2024, 9:15 AM
Unknown Object (File)
Sep 6 2024, 2:31 AM
Unknown Object (File)
Aug 30 2024, 9:14 AM
Subscribers

Details

Summary

The module handler code invokes a MOD_UNLOAD event immediately if
MOD_LOAD fails. The result was that if seminit() failed, semunload()
was invoked twice. semunload() is not idempotent however and would
try to remove it's process_exit eventhandler twice resulting in a
panic.

Test Plan
  • in a branch of CheriBSD we had a bug that caused seminit to fail which then exposed this as a boot-time panic
  • we don't appear to have sysvsem tests in kyua directly, but I ran the sys/audit/interprocess tests which test audit record generation for sysvsem and those all passed

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

jhb requested review of this revision.Oct 6 2020, 4:58 PM
jhb created this revision.

The behavior that MOD_UNLOAD gets invoked for a failed MOD_LOAD is perhaps surprising. Most of our other APIs aren't quite like that (e.g. we don't call device_detach() if device_attach() fails but instead require device_attach() to clean up if an error occurs).

Hm, seminit() fails if either sem_syscalls or sem32_syscalls registration fails. In this case, there are a lot of resources allocated that needs to be freed.
On the other hand it seems that syscall_helper_register/unregister is not safe to do if register failed. I believe this is what should be fixed somehow.

This revision is now accepted and ready to land.Oct 6 2020, 5:25 PM
In D26696#594852, @jhb wrote:

The behavior that MOD_UNLOAD gets invoked for a failed MOD_LOAD is perhaps surprising. Most of our other APIs aren't quite like that (e.g. we don't call device_detach() if device_attach() fails but instead require device_attach() to clean up if an error occurs).

Yeah, I think this has tripped me up before. It might be nice to mention it in MODULE.9.

In D26696#594853, @kib wrote:

Hm, seminit() fails if either sem_syscalls or sem32_syscalls registration fails. In this case, there are a lot of resources allocated that needs to be freed.
On the other hand it seems that syscall_helper_register/unregister is not safe to do if register failed. I believe this is what should be fixed somehow.

This does get cleaned up because of this code in module_register_init():

	MOD_SUNLOCK;
	error = MOD_EVENT(mod, MOD_LOAD);
	if (error) {
		MOD_EVENT(mod, MOD_UNLOAD);

Also, syscall_helper_deregister() does DTRT since there is a per-syscall "is registered" flag.

The bug here is that it gets cleaned up twice, and semunload() can't be safely called twice.