Page MenuHomeFreeBSD

Clean up locking around do_jail_attach, fixing zombie jails from jail_attach_jd
Needs ReviewPublic

Authored by jamie on Fri, Jun 19, 5:51 PM.
Tags
None
Referenced Files
F160310297: D57674.id180083.diff
Tue, Jun 23, 3:20 AM
F160307590: D57674.id180083.diff
Tue, Jun 23, 2:47 AM
F160305606: D57674.id180198.diff
Tue, Jun 23, 2:34 AM
F160305572: D57674.id180198.diff
Tue, Jun 23, 2:34 AM
F160295619: D57674.diff
Tue, Jun 23, 12:44 AM
F160293307: D57674.id180079.diff
Tue, Jun 23, 12:17 AM
F160266909: D57674.diff
Mon, Jun 22, 5:54 PM
Unknown Object (File)
Mon, Jun 22, 3:50 AM
Subscribers

Details

Reviewers
markj
Summary

jail_attach_jd passed PD_DEREF to do_jail_attach, assuming it would take care of freeing the held prison. This is not true, as do_jail_attach immediately cleared that flag, leaving the jail stock in dying state when it is later removed. This is largely a documentation problem: add a comment block to do_jail_attach that lays out what it expects and what it returns. And now sys_jail_attach_fd does the right thing, calling prison_deref itself to remove its reference.

Also relax do_jail_attach's requirement, as a locked prison isn't necessary unless the lock is the only hold (it will just hold and unlock). This allows kern_jail_set (which holds a reference) to skip the prison_lock_xlock call.

Test Plan

The existing jaildesc tests tripped the bug, ending up with zombie jails (not reported as an error, but visible after the run). Now the jail list (jls -d) is clean.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

jamie requested review of this revision.Fri, Jun 19, 5:51 PM
sys/kern/kern_jail.c
3246

Ignore these brackets - they're part of a fix for another jail_attach problem that I've decided not to merge with this one.

Removed an unrelated fix to a different jail_attach problem.

Looks right to me. My comments are tangential to the actual change.

sys/kern/kern_jail.c
3110

If we follow this goto, we're passing an uninitialized pr to prison_deref(). I think that happens to work, since prison_deref(pr, PD_LIST_SLOCKED) will not try to dereference pr, but you might defensively assign pr = NULL.

3130

To my taste, it'd be a bit cleaner to pass &drflags to do_jail_attach(), and have do_jail_attach() set/clear lock flags as appropriate before returning.

3154

Unrelated, but is this comment worth addressing? It's hard for me to convince myself that this couldn't be exploited somehow by an already-jailed process attaching to a pair of child jails.

This revision is now accepted and ready to land.Sat, Jun 20, 3:01 PM
jamie added inline comments.
sys/kern/kern_jail.c
3110

Good point, good safe practice.

3130

I though of this, and after some consideration went with option that was cleaner to code. But you're tilting that decision; even with the new comment block at the top of the function, making drflags continue to define the current state can prevent future errors like this.

3154

Yes, I'm looking into this - I've had this comment staring me in the face for a couple days. thread_single seems like the solution.

sys/kern/kern_jail.c
3154

That sounds reasonable to me. I suspect that it's quite rare for a multi-threaded program to call jail_attach() in the first place...

jamie marked an inline comment as done.

New diff with drflags pointer passed to do_jail_attach. I also removed the requirement that the jail be locked, which hasn't been the case since pr_ref and pr_uref went atomic.

This revision now requires review to proceed.Sat, Jun 20, 7:53 PM