Skip to content

Conversation

@MegaManSec
Copy link
Contributor

If an nmdm device was created by accident such as by running
ls /dev/nmdmAA, it would restrict the module from being unloaded,
despite no data passing through it.

With this patch, kldunload nmdm will still fail if any nmdm device still
exists.

kldunload -f nmdm will try to destroy all nmdm devices before unloading.
If an nmdm modem is either opened in blocking mode or data is being
passed through it, after five seconds of trying, it will not be destroyed
and the unload will also fail.

Likewise, fix an incorrect tty_lock, a typo, and the order of locking.

Also fix the order (which is not important).
Also fix a typo.

Signed-off-by: Joshua Rogers <Joshua@Joshua.Hu>
If an nmdm device was created by accident such as by running
`ls /dev/nmdmAA`, it would restrict the module from being unloaded,
despite no data passing through it.

With this patch, `kldunload nmdm` will still fail if any nmdm device still
exists.

`kldunload -f nmdm` will try to destroy all nmdm devices before unloading.
If an nmdm modem is either opened in blocking mode or data is being
passed through it, after five seconds of trying, it will not be destroyed
and the unload will also fail.

Signed-off-by: Joshua Rogers <Joshua@Joshua.Hu>
Copy link
Member

@bsdimp bsdimp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a good fix to me. @kevans91 is the closest thing we have to a tty expert though.

Copy link
Contributor

@kevans91 kevans91 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some problems with the locking bits, and IMO the other half is working around a bug. I don't see where the current implementation would be intentionally stopping destruction of a nmdm pair that was only ever half open.

@kevans91
Copy link
Contributor

kevans91 commented Aug 7, 2024

Some problems with the locking bits, and IMO the other half is working around a bug. I don't see where the current implementation would be intentionally stopping destruction of a nmdm pair that was only ever half open.

Ah, right- we clone it in response to stat(), nothing actually opened it or ever planned on opening it. Hmm.

Copy link
Contributor

@kevans91 kevans91 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable feedback on a path forward for the other half...

{
struct nmdmsoftc *ns;
sbintime_t start_time = sbinuptime();
sbintime_t timeout = SBT_1S * 5; // Try to force unload for 5 seconds
Copy link
Contributor

@kevans91 kevans91 Aug 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is entirely valid, but I'd really prefer to accomplish it without the timeout by adding some plumbing through the tty layer to drain the deferred destroy_dev taskqueue. kern_conf.c doesn't seem to have quite the KPI that I think I'd like to see.

Ideally, I think we'd have some kind of tty_drain_freed -> destroy_dev_drain_pending -> taskqueue_drain that we can call to force the async bits to run, then we can just EBUSY it if we still have nmdm devices when we get back.


mtx_lock(&nmdmsoftc_lock);
TAILQ_FOREACH(ns, &nmdmsoftc_list, ns_list) {
nmdm_destroy(ns->ns_part1.np_tty);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... and nmdm_destroy should ideally return EBUSY if one of them has both ttys and at least one of the ttys is opened, so that we don't bother waiting at all if we already know it's not going to magically go away.

On entry to nmdm_close(), the tty is already locked. nmdm_destroy()
does not return before the tty is unlocked by tty_rel_gone().
This means that  we need to lock the tty when the nmdm_close()
returns.

nmdm_destroy() assumes that the tty is already locked. Therefore,
nmdm_unload() must lock the tty before calling nmdm_destroy().

Signed-off-by: Joshua Rogers <Joshua@Joshua.Hu>
@bsdimp bsdimp added the needs-review Someone should look at this before proceeding label Aug 23, 2024
@bsdimp
Copy link
Member

bsdimp commented Aug 23, 2024

@kevans91 Looks like this is ready for you to re-review since it looks like your feedback has been applied.

@MegaManSec
Copy link
Contributor Author

The remaining recommendation "Ideally, I think we'd have some kind of tty_drain_freed -> destroy_dev_drain_pending -> taskqueue_drain" is not done yet: I have not had time yet to try this.

@bsdimp
Copy link
Member

bsdimp commented Sep 22, 2024

any update?

@bsdimp bsdimp added changes-required Cannot land as is, change requested of submitter and removed needs-review Someone should look at this before proceeding labels Oct 4, 2024
@bsdimp
Copy link
Member

bsdimp commented Jan 24, 2025

looks like changes are still needed... any upate?

@bsdimp
Copy link
Member

bsdimp commented Jun 12, 2025

last pinged over 6 months ago, with no update. Closing.
Feel free to re-open this or to create a new pull request if the required changes are made. Thanks for your submission. Sorry that it didn't make it in. But we're open to having a fixed version.

@bsdimp bsdimp closed this Jun 12, 2025
@MegaManSec
Copy link
Contributor Author

Unfortunately, I never got time to make the changes requested ("without the timeout by adding some plumbing through the tty layer to drain the deferred destroy_dev taskqueue").

Perhaps a freebsd bug report should be made for this, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changes-required Cannot land as is, change requested of submitter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants