Use new reference count utility throughout gvisor.

This uses the refs_vfs2 template in vfs2 as well as objects common to vfs1 and
vfs2. Note that vfs1-only refcounts are not replaced, since vfs1 will be deleted
soon anyway.

The following structs now use the new tool, with leak check enabled:
devpts:rootInode
fuse:inode
kernfs:Dentry
kernfs:dir
kernfs:readonlyDir
kernfs:StaticDirectory
proc:fdDirInode
proc:fdInfoDirInode
proc:subtasksInode
proc:taskInode
proc:tasksInode
vfs:FileDescription
vfs:MountNamespace
vfs:Filesystem
sys:dir
kernel:FSContext
kernel:ProcessGroup
kernel:Session
shm:Shm
mm:aioMappable
mm:SpecialMappable
transport:queue

And the following use the template, but because they currently are not leak
checked, a TODO is left instead of enabling leak check in this patch:
kernel:FDTable
tun:tunEndpoint

Updates #1486.

PiperOrigin-RevId: 328460377
This commit is contained in:
Dean Deng
2020-08-25 21:04:04 -07:00
committed by gVisor bot
parent 247dcd62d4
commit df3c105f49
39 changed files with 531 additions and 236 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ go_template(
types = [
"T",
],
visibility = ["//pkg/sentry:internal"],
visibility = ["//:sandbox"],
deps = [
"//pkg/log",
"//pkg/refs",
+13 -4
View File
@@ -12,11 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// Package refs_template defines a template that can be used by reference counted
// objects.
// Package refs_template defines a template that can be used by reference
// counted objects. The "owner" template parameter is used in log messages to
// indicate the type of reference-counted object that exhibited a reference
// leak. As a result, structs that are embedded in other structs should not use
// this template, since it will make tracking down leaks more difficult.
package refs_template
import (
"fmt"
"runtime"
"sync/atomic"
@@ -38,6 +42,11 @@ var ownerType *T
// Note that the number of references is actually refCount + 1 so that a default
// zero-value Refs object contains one reference.
//
// TODO(gvisor.dev/issue/1486): Store stack traces when leak check is enabled in
// a map with 16-bit hashes, and store the hash in the top 16 bits of refCount.
// This will allow us to add stack trace information to the leak messages
// without growing the size of Refs.
//
// +stateify savable
type Refs struct {
// refCount is composed of two fields:
@@ -82,7 +91,7 @@ func (r *Refs) ReadRefs() int64 {
//go:nosplit
func (r *Refs) IncRef() {
if v := atomic.AddInt64(&r.refCount, 1); v <= 0 {
panic("Incrementing non-positive ref count")
panic(fmt.Sprintf("Incrementing non-positive ref count %p owned by %T", r, ownerType))
}
}
@@ -122,7 +131,7 @@ func (r *Refs) TryIncRef() bool {
func (r *Refs) DecRef(destroy func()) {
switch v := atomic.AddInt64(&r.refCount, -1); {
case v < -1:
panic("Decrementing non-positive ref count")
panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %T", r, ownerType))
case v == -1:
// Call the destructor.
+15
View File
@@ -1,7 +1,19 @@
load("//tools:defs.bzl", "go_library", "go_test")
load("//tools/go_generics:defs.bzl", "go_template_instance")
licenses(["notice"])
go_template_instance(
name = "root_inode_refs",
out = "root_inode_refs.go",
package = "devpts",
prefix = "rootInode",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "rootInode",
},
)
go_library(
name = "devpts",
srcs = [
@@ -9,6 +21,7 @@ go_library(
"line_discipline.go",
"master.go",
"queue.go",
"root_inode_refs.go",
"slave.go",
"terminal.go",
],
@@ -16,6 +29,8 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
"//pkg/log",
"//pkg/refs",
"//pkg/safemem",
"//pkg/sentry/arch",
"//pkg/sentry/fs/lock",
+7
View File
@@ -83,6 +83,7 @@ func (fstype FilesystemType) newFilesystem(vfsObj *vfs.VirtualFilesystem, creds
}
root.InodeAttrs.Init(creds, linux.UNNAMED_MAJOR, devMinor, 1, linux.ModeDirectory|0555)
root.OrderedChildren.Init(kernfs.OrderedChildrenOptions{})
root.EnableLeakCheck()
root.dentry.Init(root)
// Construct the pts master inode and dentry. Linux always uses inode
@@ -110,6 +111,7 @@ func (fs *filesystem) Release(ctx context.Context) {
// rootInode is the root directory inode for the devpts mounts.
type rootInode struct {
rootInodeRefs
kernfs.AlwaysValid
kernfs.InodeAttrs
kernfs.InodeDirectoryNoNewChildren
@@ -233,3 +235,8 @@ func (i *rootInode) IterDirents(ctx context.Context, cb vfs.IterDirentsCallback,
}
return offset, nil
}
// DecRef implements kernfs.Inode.
func (i *rootInode) DecRef(context.Context) {
i.rootInodeRefs.DecRef(i.Destroy)
}
+13
View File
@@ -15,6 +15,17 @@ go_template_instance(
},
)
go_template_instance(
name = "inode_refs",
out = "inode_refs.go",
package = "fuse",
prefix = "inode",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "inode",
},
)
go_library(
name = "fuse",
srcs = [
@@ -22,6 +33,7 @@ go_library(
"dev.go",
"fusefs.go",
"init.go",
"inode_refs.go",
"register.go",
"request_list.go",
],
@@ -30,6 +42,7 @@ go_library(
"//pkg/abi/linux",
"//pkg/context",
"//pkg/log",
"//pkg/refs",
"//pkg/sentry/fsimpl/devtmpfs",
"//pkg/sentry/fsimpl/kernfs",
"//pkg/sentry/kernel",
+7
View File
@@ -198,6 +198,7 @@ func (fs *filesystem) Release(ctx context.Context) {
// inode implements kernfs.Inode.
type inode struct {
inodeRefs
kernfs.InodeAttrs
kernfs.InodeNoDynamicLookup
kernfs.InodeNotSymlink
@@ -213,6 +214,7 @@ func (fs *filesystem) newInode(creds *auth.Credentials, mode linux.FileMode) *ke
i := &inode{}
i.InodeAttrs.Init(creds, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), linux.ModeDirectory|0755)
i.OrderedChildren.Init(kernfs.OrderedChildrenOptions{})
i.EnableLeakCheck()
i.dentry.Init(i)
return &i.dentry
@@ -324,3 +326,8 @@ func (i *inode) Stat(ctx context.Context, fs *vfs.Filesystem, opts vfs.StatOptio
return statFromFUSEAttr(out.Attr, opts.Mask, fusefs.devMinor), nil
}
// DecRef implements kernfs.Inode.
func (i *inode) DecRef(context.Context) {
i.inodeRefs.DecRef(i.Destroy)
}
+53 -1
View File
@@ -26,9 +26,54 @@ go_template_instance(
},
)
go_template_instance(
name = "dentry_refs",
out = "dentry_refs.go",
package = "kernfs",
prefix = "Dentry",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "Dentry",
},
)
go_template_instance(
name = "static_directory_refs",
out = "static_directory_refs.go",
package = "kernfs",
prefix = "StaticDirectory",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "StaticDirectory",
},
)
go_template_instance(
name = "dir_refs",
out = "dir_refs.go",
package = "kernfs_test",
prefix = "dir",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "dir",
},
)
go_template_instance(
name = "readonly_dir_refs",
out = "readonly_dir_refs.go",
package = "kernfs_test",
prefix = "readonlyDir",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "readonlyDir",
},
)
go_library(
name = "kernfs",
srcs = [
"dentry_refs.go",
"dynamic_bytes_file.go",
"fd_impl_util.go",
"filesystem.go",
@@ -36,6 +81,7 @@ go_library(
"inode_impl_util.go",
"kernfs.go",
"slot_list.go",
"static_directory_refs.go",
"symlink.go",
],
visibility = ["//pkg/sentry:internal"],
@@ -59,11 +105,17 @@ go_library(
go_test(
name = "kernfs_test",
size = "small",
srcs = ["kernfs_test.go"],
srcs = [
"dir_refs.go",
"kernfs_test.go",
"readonly_dir_refs.go",
],
deps = [
":kernfs",
"//pkg/abi/linux",
"//pkg/context",
"//pkg/log",
"//pkg/refs",
"//pkg/sentry/contexttest",
"//pkg/sentry/fsimpl/testutil",
"//pkg/sentry/kernel/auth",
+15 -12
View File
@@ -20,7 +20,6 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/refs"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
@@ -344,8 +343,6 @@ type OrderedChildrenOptions struct {
//
// Must be initialize with Init before first use.
type OrderedChildren struct {
refs.AtomicRefCount
// Can children be modified by user syscalls? It set to false, interface
// methods that would modify the children return EPERM. Immutable.
writable bool
@@ -361,14 +358,14 @@ func (o *OrderedChildren) Init(opts OrderedChildrenOptions) {
o.set = make(map[string]*slot)
}
// DecRef implements Inode.DecRef.
func (o *OrderedChildren) DecRef(ctx context.Context) {
o.AtomicRefCount.DecRefWithDestructor(ctx, func(context.Context) {
o.mu.Lock()
defer o.mu.Unlock()
o.order.Reset()
o.set = nil
})
// Destroy clears the children stored in o. It should be called by structs
// embedding OrderedChildren upon destruction, i.e. when their reference count
// reaches zero.
func (o *OrderedChildren) Destroy() {
o.mu.Lock()
defer o.mu.Unlock()
o.order.Reset()
o.set = nil
}
// Populate inserts children into this OrderedChildren, and d's dentry
@@ -549,6 +546,7 @@ func (InodeSymlink) Open(ctx context.Context, rp *vfs.ResolvingPath, vfsd *vfs.D
//
// +stateify savable
type StaticDirectory struct {
StaticDirectoryRefs
InodeNotSymlink
InodeDirectoryNoNewChildren
InodeAttrs
@@ -594,11 +592,16 @@ func (s *StaticDirectory) Open(ctx context.Context, rp *vfs.ResolvingPath, vfsd
return fd.VFSFileDescription(), nil
}
// SetStat implements Inode.SetStat not allowing inode attributes to be changed.
// SetStat implements kernfs.Inode.SetStat not allowing inode attributes to be changed.
func (*StaticDirectory) SetStat(context.Context, *vfs.Filesystem, *auth.Credentials, vfs.SetStatOptions) error {
return syserror.EPERM
}
// DecRef implements kernfs.Inode.
func (s *StaticDirectory) DecRef(context.Context) {
s.StaticDirectoryRefs.DecRef(s.Destroy)
}
// AlwaysValid partially implements kernfs.inodeDynamicLookup.
type AlwaysValid struct{}
+11 -13
View File
@@ -57,7 +57,6 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/refs"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
@@ -161,9 +160,9 @@ const (
//
// Must be initialized by Init prior to first use.
type Dentry struct {
vfsd vfs.Dentry
DentryRefs
refs.AtomicRefCount
vfsd vfs.Dentry
// flags caches useful information about the dentry from the inode. See the
// dflags* consts above. Must be accessed by atomic ops.
@@ -194,6 +193,7 @@ func (d *Dentry) Init(inode Inode) {
if ftype == linux.ModeSymlink {
d.flags |= dflagsIsSymlink
}
d.EnableLeakCheck()
}
// VFSDentry returns the generic vfs dentry for this kernfs dentry.
@@ -213,16 +213,14 @@ func (d *Dentry) isSymlink() bool {
// DecRef implements vfs.DentryImpl.DecRef.
func (d *Dentry) DecRef(ctx context.Context) {
d.AtomicRefCount.DecRefWithDestructor(ctx, d.destroy)
}
// Precondition: Dentry must be removed from VFS' dentry cache.
func (d *Dentry) destroy(ctx context.Context) {
d.inode.DecRef(ctx) // IncRef from Init.
d.inode = nil
if d.parent != nil {
d.parent.DecRef(ctx) // IncRef from Dentry.InsertChild.
}
// Before the destructor is called, Dentry must be removed from VFS' dentry cache.
d.DentryRefs.DecRef(func() {
d.inode.DecRef(ctx) // IncRef from Init.
d.inode = nil
if d.parent != nil {
d.parent.DecRef(ctx) // IncRef from Dentry.InsertChild.
}
})
}
// InotifyWithParent implements vfs.DentryImpl.InotifyWithParent.
+12
View File
@@ -96,6 +96,7 @@ func (*attrs) SetStat(context.Context, *vfs.Filesystem, *auth.Credentials, vfs.S
}
type readonlyDir struct {
readonlyDirRefs
attrs
kernfs.InodeNotSymlink
kernfs.InodeNoDynamicLookup
@@ -111,6 +112,7 @@ func (fs *filesystem) newReadonlyDir(creds *auth.Credentials, mode linux.FileMod
dir := &readonlyDir{}
dir.attrs.Init(creds, 0 /* devMajor */, 0 /* devMinor */, fs.NextIno(), linux.ModeDirectory|mode)
dir.OrderedChildren.Init(kernfs.OrderedChildrenOptions{})
dir.EnableLeakCheck()
dir.dentry.Init(dir)
dir.IncLinks(dir.OrderedChildren.Populate(&dir.dentry, contents))
@@ -128,7 +130,12 @@ func (d *readonlyDir) Open(ctx context.Context, rp *vfs.ResolvingPath, vfsd *vfs
return fd.VFSFileDescription(), nil
}
func (d *readonlyDir) DecRef(context.Context) {
d.readonlyDirRefs.DecRef(d.Destroy)
}
type dir struct {
dirRefs
attrs
kernfs.InodeNotSymlink
kernfs.InodeNoDynamicLookup
@@ -145,6 +152,7 @@ func (fs *filesystem) newDir(creds *auth.Credentials, mode linux.FileMode, conte
dir.fs = fs
dir.attrs.Init(creds, 0 /* devMajor */, 0 /* devMinor */, fs.NextIno(), linux.ModeDirectory|mode)
dir.OrderedChildren.Init(kernfs.OrderedChildrenOptions{Writable: true})
dir.EnableLeakCheck()
dir.dentry.Init(dir)
dir.IncLinks(dir.OrderedChildren.Populate(&dir.dentry, contents))
@@ -162,6 +170,10 @@ func (d *dir) Open(ctx context.Context, rp *vfs.ResolvingPath, vfsd *vfs.Dentry,
return fd.VFSFileDescription(), nil
}
func (d *dir) DecRef(context.Context) {
d.dirRefs.DecRef(d.Destroy)
}
func (d *dir) NewDir(ctx context.Context, name string, opts vfs.MkdirOptions) (*vfs.Dentry, error) {
creds := auth.CredentialsFromContext(ctx)
dir := d.fs.newDir(creds, opts.Mode, nil)
+61
View File
@@ -1,18 +1,79 @@
load("//tools:defs.bzl", "go_library", "go_test")
load("//tools/go_generics:defs.bzl", "go_template_instance")
licenses(["notice"])
go_template_instance(
name = "fd_dir_inode_refs",
out = "fd_dir_inode_refs.go",
package = "proc",
prefix = "fdDirInode",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "fdDirInode",
},
)
go_template_instance(
name = "fd_info_dir_inode_refs",
out = "fd_info_dir_inode_refs.go",
package = "proc",
prefix = "fdInfoDirInode",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "fdInfoDirInode",
},
)
go_template_instance(
name = "subtasks_inode_refs",
out = "subtasks_inode_refs.go",
package = "proc",
prefix = "subtasksInode",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "subtasksInode",
},
)
go_template_instance(
name = "task_inode_refs",
out = "task_inode_refs.go",
package = "proc",
prefix = "taskInode",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "taskInode",
},
)
go_template_instance(
name = "tasks_inode_refs",
out = "tasks_inode_refs.go",
package = "proc",
prefix = "tasksInode",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "tasksInode",
},
)
go_library(
name = "proc",
srcs = [
"fd_dir_inode_refs.go",
"fd_info_dir_inode_refs.go",
"filesystem.go",
"subtasks.go",
"subtasks_inode_refs.go",
"task.go",
"task_fds.go",
"task_files.go",
"task_inode_refs.go",
"task_net.go",
"tasks.go",
"tasks_files.go",
"tasks_inode_refs.go",
"tasks_sys.go",
],
visibility = ["//pkg/sentry:internal"],
+7
View File
@@ -31,6 +31,7 @@ import (
//
// +stateify savable
type subtasksInode struct {
subtasksInodeRefs
kernfs.InodeNotSymlink
kernfs.InodeDirectoryNoNewChildren
kernfs.InodeAttrs
@@ -57,6 +58,7 @@ func (fs *filesystem) newSubtasks(task *kernel.Task, pidns *kernel.PIDNamespace,
// Note: credentials are overridden by taskOwnedInode.
subInode.InodeAttrs.Init(task.Credentials(), linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), linux.ModeDirectory|0555)
subInode.OrderedChildren.Init(kernfs.OrderedChildrenOptions{})
subInode.EnableLeakCheck()
inode := &taskOwnedInode{Inode: subInode, owner: task}
dentry := &kernfs.Dentry{}
@@ -182,3 +184,8 @@ func (i *subtasksInode) Stat(ctx context.Context, vsfs *vfs.Filesystem, opts vfs
func (*subtasksInode) SetStat(context.Context, *vfs.Filesystem, *auth.Credentials, vfs.SetStatOptions) error {
return syserror.EPERM
}
// DecRef implements kernfs.Inode.
func (i *subtasksInode) DecRef(context.Context) {
i.subtasksInodeRefs.DecRef(i.Destroy)
}
+8
View File
@@ -32,6 +32,7 @@ import (
//
// +stateify savable
type taskInode struct {
taskInodeRefs
kernfs.InodeNotSymlink
kernfs.InodeDirectoryNoNewChildren
kernfs.InodeNoDynamicLookup
@@ -84,6 +85,7 @@ func (fs *filesystem) newTaskInode(task *kernel.Task, pidns *kernel.PIDNamespace
taskInode := &taskInode{task: task}
// Note: credentials are overridden by taskOwnedInode.
taskInode.InodeAttrs.Init(task.Credentials(), linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), linux.ModeDirectory|0555)
taskInode.EnableLeakCheck()
inode := &taskOwnedInode{Inode: taskInode, owner: task}
dentry := &kernfs.Dentry{}
@@ -119,6 +121,11 @@ func (*taskInode) SetStat(context.Context, *vfs.Filesystem, *auth.Credentials, v
return syserror.EPERM
}
// DecRef implements kernfs.Inode.
func (i *taskInode) DecRef(context.Context) {
i.taskInodeRefs.DecRef(i.Destroy)
}
// taskOwnedInode implements kernfs.Inode and overrides inode owner with task
// effective user and group.
type taskOwnedInode struct {
@@ -147,6 +154,7 @@ func (fs *filesystem) newTaskOwnedDir(task *kernel.Task, ino uint64, perm linux.
dir.Init(task.Credentials(), linux.UNNAMED_MAJOR, fs.devMinor, ino, perm, kernfs.GenericDirectoryFDOptions{
SeekEnd: kernfs.SeekEndZero,
})
dir.EnableLeakCheck()
inode := &taskOwnedInode{Inode: dir, owner: task}
d := &kernfs.Dentry{}
+14 -2
View File
@@ -22,7 +22,6 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/refs"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -101,6 +100,7 @@ func (i *fdDir) IterDirents(ctx context.Context, cb vfs.IterDirentsCallback, off
//
// +stateify savable
type fdDirInode struct {
fdDirInodeRefs
kernfs.InodeNotSymlink
kernfs.InodeDirectoryNoNewChildren
kernfs.InodeAttrs
@@ -120,6 +120,7 @@ func (fs *filesystem) newFDDirInode(task *kernel.Task) *kernfs.Dentry {
},
}
inode.InodeAttrs.Init(task.Credentials(), linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), linux.ModeDirectory|0555)
inode.EnableLeakCheck()
dentry := &kernfs.Dentry{}
dentry.Init(inode)
@@ -175,6 +176,11 @@ func (i *fdDirInode) CheckPermissions(ctx context.Context, creds *auth.Credentia
return err
}
// DecRef implements kernfs.Inode.
func (i *fdDirInode) DecRef(context.Context) {
i.fdDirInodeRefs.DecRef(i.Destroy)
}
// fdSymlink is an symlink for the /proc/[pid]/fd/[fd] file.
//
// +stateify savable
@@ -227,6 +233,7 @@ func (s *fdSymlink) Getlink(ctx context.Context, mnt *vfs.Mount) (vfs.VirtualDen
//
// +stateify savable
type fdInfoDirInode struct {
fdInfoDirInodeRefs
kernfs.InodeNotSymlink
kernfs.InodeDirectoryNoNewChildren
kernfs.InodeAttrs
@@ -245,6 +252,7 @@ func (fs *filesystem) newFDInfoDirInode(task *kernel.Task) *kernfs.Dentry {
},
}
inode.InodeAttrs.Init(task.Credentials(), linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), linux.ModeDirectory|0555)
inode.EnableLeakCheck()
dentry := &kernfs.Dentry{}
dentry.Init(inode)
@@ -282,12 +290,16 @@ func (i *fdInfoDirInode) Open(ctx context.Context, rp *vfs.ResolvingPath, vfsd *
return fd.VFSFileDescription(), nil
}
// DecRef implements kernfs.Inode.
func (i *fdInfoDirInode) DecRef(context.Context) {
i.fdInfoDirInodeRefs.DecRef(i.Destroy)
}
// fdInfoData implements vfs.DynamicBytesSource for /proc/[pid]/fdinfo/[fd].
//
// +stateify savable
type fdInfoData struct {
kernfs.DynamicBytesFile
refs.AtomicRefCount
task *kernel.Task
fd int32
+3 -3
View File
@@ -262,7 +262,7 @@ func (n *netUnixData) Generate(ctx context.Context, buf *bytes.Buffer) error {
// For now, we always redact this pointer.
fmt.Fprintf(buf, "%#016p: %08X %08X %08X %04X %02X %8d",
(*unix.SocketOperations)(nil), // Num, pointer to kernel socket struct.
s.Refs()-1, // RefCount, don't count our own ref.
s.ReadRefs()-1, // RefCount, don't count our own ref.
0, // Protocol, always 0 for UDS.
sockFlags, // Flags.
sops.Endpoint().Type(), // Type.
@@ -430,7 +430,7 @@ func commonGenerateTCP(ctx context.Context, buf *bytes.Buffer, k *kernel.Kernel,
// Field: refcount. Don't count the ref we obtain while deferencing
// the weakref to this socket.
fmt.Fprintf(buf, "%d ", s.Refs()-1)
fmt.Fprintf(buf, "%d ", s.ReadRefs()-1)
// Field: Socket struct address. Redacted due to the same reason as
// the 'Num' field in /proc/net/unix, see netUnix.ReadSeqFileData.
@@ -589,7 +589,7 @@ func (d *netUDPData) Generate(ctx context.Context, buf *bytes.Buffer) error {
// Field: ref; reference count on the socket inode. Don't count the ref
// we obtain while deferencing the weakref to this socket.
fmt.Fprintf(buf, "%d ", s.Refs()-1)
fmt.Fprintf(buf, "%d ", s.ReadRefs()-1)
// Field: Socket struct address. Redacted due to the same reason as
// the 'Num' field in /proc/net/unix, see netUnix.ReadSeqFileData.
+7
View File
@@ -37,6 +37,7 @@ const (
//
// +stateify savable
type tasksInode struct {
tasksInodeRefs
kernfs.InodeNotSymlink
kernfs.InodeDirectoryNoNewChildren
kernfs.InodeAttrs
@@ -84,6 +85,7 @@ func (fs *filesystem) newTasksInode(k *kernel.Kernel, pidns *kernel.PIDNamespace
cgroupControllers: cgroupControllers,
}
inode.InodeAttrs.Init(root, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), linux.ModeDirectory|0555)
inode.EnableLeakCheck()
dentry := &kernfs.Dentry{}
dentry.Init(inode)
@@ -226,6 +228,11 @@ func (i *tasksInode) Stat(ctx context.Context, vsfs *vfs.Filesystem, opts vfs.St
return stat, nil
}
// DecRef implements kernfs.Inode.
func (i *tasksInode) DecRef(context.Context) {
i.tasksInodeRefs.DecRef(i.Destroy)
}
// staticFileSetStat implements a special static file that allows inode
// attributes to be set. This is to support /proc files that are readonly, but
// allow attributes to be set.
+15
View File
@@ -1,10 +1,23 @@
load("//tools:defs.bzl", "go_library", "go_test")
load("//tools/go_generics:defs.bzl", "go_template_instance")
licenses(["notice"])
go_template_instance(
name = "dir_refs",
out = "dir_refs.go",
package = "sys",
prefix = "dir",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "dir",
},
)
go_library(
name = "sys",
srcs = [
"dir_refs.go",
"kcov.go",
"sys.go",
],
@@ -13,6 +26,8 @@ go_library(
"//pkg/abi/linux",
"//pkg/context",
"//pkg/coverage",
"//pkg/log",
"//pkg/refs",
"//pkg/sentry/arch",
"//pkg/sentry/fsimpl/kernfs",
"//pkg/sentry/kernel",
+8 -1
View File
@@ -118,6 +118,7 @@ func (fs *filesystem) Release(ctx context.Context) {
// dir implements kernfs.Inode.
type dir struct {
dirRefs
kernfs.InodeAttrs
kernfs.InodeNoDynamicLookup
kernfs.InodeNotSymlink
@@ -133,6 +134,7 @@ func (fs *filesystem) newDir(creds *auth.Credentials, mode linux.FileMode, conte
d := &dir{}
d.InodeAttrs.Init(creds, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), linux.ModeDirectory|0755)
d.OrderedChildren.Init(kernfs.OrderedChildrenOptions{})
d.EnableLeakCheck()
d.dentry.Init(d)
d.IncLinks(d.OrderedChildren.Populate(&d.dentry, contents))
@@ -140,7 +142,7 @@ func (fs *filesystem) newDir(creds *auth.Credentials, mode linux.FileMode, conte
return &d.dentry
}
// SetStat implements Inode.SetStat not allowing inode attributes to be changed.
// SetStat implements kernfs.Inode.SetStat not allowing inode attributes to be changed.
func (*dir) SetStat(context.Context, *vfs.Filesystem, *auth.Credentials, vfs.SetStatOptions) error {
return syserror.EPERM
}
@@ -156,6 +158,11 @@ func (d *dir) Open(ctx context.Context, rp *vfs.ResolvingPath, vfsd *vfs.Dentry,
return fd.VFSFileDescription(), nil
}
// DecRef implements kernfs.Inode.DecRef.
func (d *dir) DecRef(context.Context) {
d.dirRefs.DecRef(d.Destroy)
}
// cpuFile implements kernfs.Inode.
type cpuFile struct {
kernfs.DynamicBytesFile
+48
View File
@@ -74,6 +74,50 @@ go_template_instance(
},
)
go_template_instance(
name = "fd_table_refs",
out = "fd_table_refs.go",
package = "kernel",
prefix = "FDTable",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "FDTable",
},
)
go_template_instance(
name = "fs_context_refs",
out = "fs_context_refs.go",
package = "kernel",
prefix = "FSContext",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "FSContext",
},
)
go_template_instance(
name = "process_group_refs",
out = "process_group_refs.go",
package = "kernel",
prefix = "ProcessGroup",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "ProcessGroup",
},
)
go_template_instance(
name = "session_refs",
out = "session_refs.go",
package = "kernel",
prefix = "Session",
template = "//pkg/refs_vfs2:refs_template",
types = {
"T": "Session",
},
)
proto_library(
name = "uncaught_signal",
srcs = ["uncaught_signal.proto"],
@@ -88,8 +132,10 @@ go_library(
"aio.go",
"context.go",
"fd_table.go",
"fd_table_refs.go",
"fd_table_unsafe.go",
"fs_context.go",
"fs_context_refs.go",
"ipc_namespace.go",
"kcov.go",
"kcov_unsafe.go",
@@ -101,6 +147,7 @@ go_library(
"pending_signals_state.go",
"posixtimer.go",
"process_group_list.go",
"process_group_refs.go",
"ptrace.go",
"ptrace_amd64.go",
"ptrace_arm64.go",
@@ -108,6 +155,7 @@ go_library(
"seccomp.go",
"seqatomic_taskgoroutineschedinfo_unsafe.go",
"session_list.go",
"session_refs.go",
"sessions.go",
"signal.go",
"signal_handlers.go",
+10 -11
View File
@@ -23,7 +23,6 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/refs"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/lock"
"gvisor.dev/gvisor/pkg/sentry/limits"
@@ -78,7 +77,8 @@ type descriptor struct {
//
// +stateify savable
type FDTable struct {
refs.AtomicRefCount
FDTableRefs
k *Kernel
// mu protects below.
@@ -176,16 +176,15 @@ func (k *Kernel) NewFDTable() *FDTable {
return f
}
// destroy removes all of the file descriptors from the map.
func (f *FDTable) destroy(ctx context.Context) {
f.RemoveIf(ctx, func(*fs.File, *vfs.FileDescription, FDFlags) bool {
return true
})
}
// DecRef implements RefCounter.DecRef with destructor f.destroy.
// DecRef implements RefCounter.DecRef.
//
// If f reaches zero references, all of its file descriptors are removed.
func (f *FDTable) DecRef(ctx context.Context) {
f.DecRefWithDestructor(ctx, f.destroy)
f.FDTableRefs.DecRef(func() {
f.RemoveIf(ctx, func(*fs.File, *vfs.FileDescription, FDFlags) bool {
return true
})
})
}
// Size returns the number of file descriptor slots currently allocated.

Some files were not shown because too many files have changed in this diff Show More