@@ -192,9 +192,9 @@ func (t *Task) Clone(args *linux.CloneArgs) (ThreadID, *SyscallControl, error) {
192192
193193 var fsContext * FSContext
194194 if args .Flags & linux .CLONE_FS == 0 || args .Flags & linux .CLONE_NEWNS != 0 {
195- fsContext = t .fsContext .Fork ()
195+ fsContext = t .FSContext () .Fork ()
196196 } else {
197- fsContext = t .fsContext
197+ fsContext = t .FSContext ()
198198 if ! fsContext .share () {
199199 // Linux fails clone with EAGAIN if there is a concurrent execve, see kernel/fork.c:copy_fs().
200200 return 0 , nil , linuxerr .EAGAIN
@@ -518,7 +518,7 @@ func (t *Task) Setns(fd *vfs.FileDescription, flags int32) error {
518518 ! t .Credentials ().HasCapability (linux .CAP_SYS_ADMIN ) {
519519 return linuxerr .EPERM
520520 }
521- oldFSContext := t .fsContext
521+ oldFSContext := t .FSContext ()
522522 // The current task has to be an exclusive owner of its fs context.
523523 if oldFSContext .ReadRefs () != 1 {
524524 return linuxerr .EINVAL
@@ -535,7 +535,7 @@ func (t *Task) Setns(fd *vfs.FileDescription, flags int32) error {
535535 ns .IncRef ()
536536 t .mu .Lock ()
537537 t .mountNamespace = ns
538- t .fsContext = fsContext
538+ t .fsContext . Store ( fsContext )
539539 t .mu .Unlock ()
540540 oldNS .DecRef (t )
541541 oldFSContext .DecRef (t )
@@ -671,7 +671,6 @@ func (t *Task) Unshare(flags int32) error {
671671 defer cu .Clean ()
672672 t .mu .Lock ()
673673 defer t .mu .Unlock ()
674- // Can't defer unlock: DecRefs must occur without holding t.mu.
675674 if flags & linux .CLONE_NEWUTS != 0 {
676675 if ! haveCapSysAdmin {
677676 return linuxerr .EPERM
@@ -701,16 +700,21 @@ func (t *Task) Unshare(flags int32) error {
701700 cu .Add (func () { oldFDTable .DecRef (t ) })
702701 }
703702 if flags & linux .CLONE_FS != 0 || flags & linux .CLONE_NEWNS != 0 {
704- oldFSContext := t .fsContext
705- t .fsContext = oldFSContext .Fork ()
706- cu .Add (func () { oldFSContext .DecRef (t ) })
703+ oldFSContext := t .FSContext ()
704+ // unshareFromTask() lowers the old fs context's ref count, but its for us to
705+ // destroy it if there are no other references.
706+ if oldFSContext .unshareFromTask (t , oldFSContext .Fork ()) {
707+ // destroy() requires t.mu to not be held, hence the deferral.
708+ cu .Add (func () { oldFSContext .destroy (t ) })
709+ }
707710 }
708711 if flags & linux .CLONE_NEWNS != 0 {
709712 if ! haveCapSysAdmin {
710713 return linuxerr .EPERM
711714 }
712715 oldMountNS := t .mountNamespace
713- mntns , err := t .k .vfs .CloneMountNamespace (t , creds .UserNamespace , oldMountNS , & t .fsContext .root , & t .fsContext .cwd , t .k )
716+ fsContext := t .FSContext ()
717+ mntns , err := t .k .vfs .CloneMountNamespace (t , creds .UserNamespace , oldMountNS , & fsContext .root , & fsContext .cwd , t .k )
714718 if err != nil {
715719 return err
716720 }
0 commit comments