From 4f2f44320f9b96bdc8c0fb25c116104ea501ab8b Mon Sep 17 00:00:00 2001 From: Nicolas Lacasse Date: Tue, 2 Jul 2019 12:53:47 -0700 Subject: [PATCH] Simplify (and fix) refcounts in createAt. fileOpAt holds references on the Dirents passed as arguments to the callback, and drops refs when finished, so we don't need to DecRef those Dirents ourselves However, all Dirents that we get from FindInode/FindLink must be DecRef'd. This CL cleans up the ref-counting logic, and fixes some refcount issues in the process. PiperOrigin-RevId: 256220882 --- pkg/sentry/syscalls/linux/sys_file.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/pkg/sentry/syscalls/linux/sys_file.go b/pkg/sentry/syscalls/linux/sys_file.go index 3410af69c..2776fdec7 100644 --- a/pkg/sentry/syscalls/linux/sys_file.go +++ b/pkg/sentry/syscalls/linux/sys_file.go @@ -326,6 +326,7 @@ func createAt(t *kernel.Task, dirFD kdefs.FD, addr usermem.Addr, flags uint, mod if err != nil { break } + defer found.DecRef() // We found something (possibly a symlink). If the // O_EXCL flag was passed, then we can immediately @@ -346,17 +347,18 @@ func createAt(t *kernel.Task, dirFD kdefs.FD, addr usermem.Addr, flags uint, mod } // Try to resolve the symlink directly to a Dirent. - resolved, err := found.Inode.Getlink(t) - if err == nil || err != fs.ErrResolveViaReadlink { + var resolved *fs.Dirent + resolved, err = found.Inode.Getlink(t) + if err == nil { // No more resolution necessary. - found.DecRef() - found = resolved + defer resolved.DecRef() break + } else if err != fs.ErrResolveViaReadlink { + return err } // Are we able to resolve further? if remainingTraversals == 0 { - found.DecRef() return syscall.ELOOP } @@ -373,10 +375,10 @@ func createAt(t *kernel.Task, dirFD kdefs.FD, addr usermem.Addr, flags uint, mod if err != nil { break } + defer newParent.DecRef() // Repeat the process with the parent and name of the // symlink target. - parent.DecRef() parent = newParent name = newName } @@ -384,9 +386,6 @@ func createAt(t *kernel.Task, dirFD kdefs.FD, addr usermem.Addr, flags uint, mod var newFile *fs.File switch err { case nil: - // The file existed. - defer found.DecRef() - // Like sys_open, check for a few things about the // filesystem before trying to get a reference to the // fs.File. The same constraints on Check apply.