kernel: use lockdep mutexes

PiperOrigin-RevId: 449877248
This commit is contained in:
Andrei Vagin
2022-05-19 18:33:59 -07:00
committed by gVisor bot
parent 1228e6c788
commit 604233c9f6
23 changed files with 198 additions and 39 deletions
+66
View File
@@ -1,8 +1,65 @@
load("//tools:defs.bzl", "go_library", "go_test", "proto_library")
load("//tools/go_generics:defs.bzl", "go_template_instance")
load("//pkg/sync/locking:locking.bzl", "declare_mutex", "declare_rwmutex")
package(licenses = ["notice"])
declare_mutex(
name = "user_counters_mutex",
out = "user_counters_mutex.go",
package = "kernel",
prefix = "userCounters",
)
declare_rwmutex(
name = "taskset_mutex",
out = "taskset_mutex.go",
package = "kernel",
prefix = "taskSet",
)
declare_mutex(
name = "task_mutex",
out = "task_mutex.go",
package = "kernel",
prefix = "task",
)
declare_mutex(
name = "cgroup_mutex",
out = "cgroup_mutex.go",
package = "kernel",
prefix = "cgroup",
)
declare_mutex(
name = "fd_table_mutex",
out = "fd_table_mutex.go",
package = "kernel",
prefix = "fdTable",
)
declare_mutex(
name = "running_tasks_mutex",
out = "running_tasks_mutex.go",
package = "kernel",
prefix = "runningTasks",
)
declare_mutex(
name = "signal_handlers_mutex",
out = "signal_handlers_mutex.go",
package = "kernel",
prefix = "signalHandlers",
)
declare_mutex(
name = "thread_group_timer_mutex",
out = "thread_group_timer_mutex.go",
package = "kernel",
prefix = "threadGroupTimer",
)
go_template_instance(
name = "pending_signals_list",
out = "pending_signals_list.go",
@@ -142,8 +199,10 @@ go_library(
"abstract_socket_namespace.go",
"aio.go",
"cgroup.go",
"cgroup_mutex.go",
"context.go",
"fd_table.go",
"fd_table_mutex.go",
"fd_table_refs.go",
"fd_table_unsafe.go",
"fs_context.go",
@@ -165,6 +224,7 @@ go_library(
"ptrace_amd64.go",
"ptrace_arm64.go",
"rseq.go",
"running_tasks_mutex.go",
"seccheck.go",
"seccomp.go",
"seqatomic_taskgoroutineschedinfo_unsafe.go",
@@ -173,6 +233,7 @@ go_library(
"sessions.go",
"signal.go",
"signal_handlers.go",
"signal_handlers_mutex.go",
"socket_list.go",
"syscalls.go",
"syscalls_state.go",
@@ -190,6 +251,7 @@ go_library(
"task_image.go",
"task_list.go",
"task_log.go",
"task_mutex.go",
"task_net.go",
"task_run.go",
"task_sched.go",
@@ -199,12 +261,15 @@ go_library(
"task_syscall.go",
"task_usermem.go",
"task_work.go",
"taskset_mutex.go",
"thread_group.go",
"thread_group_timer_mutex.go",
"threads.go",
"threads_impl.go",
"timekeeper.go",
"timekeeper_state.go",
"tty.go",
"user_counters_mutex.go",
"uts_namespace.go",
"vdso.go",
"version.go",
@@ -286,6 +351,7 @@ go_library(
"//pkg/state/statefile",
"//pkg/state/wire",
"//pkg/sync",
"//pkg/sync/locking",
"//pkg/syserr",
"//pkg/tcpip",
"//pkg/tcpip/stack",
+13
View File
@@ -42,6 +42,17 @@ go_template_instance(
},
)
go_template_instance(
name = "user_namespace_mutex",
out = "user_namespace_mutex.go",
package = "auth",
prefix = "userNamespace",
substrs = {
"genericMark": "userNamespace",
},
template = "//pkg/sync/locking:generic_mutex",
)
go_library(
name = "auth",
srcs = [
@@ -56,6 +67,7 @@ go_library(
"id_map_range.go",
"id_map_set.go",
"user_namespace.go",
"user_namespace_mutex.go",
],
marshal = True,
visibility = ["//pkg/sentry:internal"],
@@ -68,5 +80,6 @@ go_library(
"//pkg/sentry/seccheck",
"//pkg/sentry/seccheck/points:points_go_proto",
"//pkg/sync",
"//pkg/sync/locking",
],
)
+2 -2
View File
@@ -69,8 +69,8 @@ func (ns *UserNamespace) mapID(m *idMapSet, id uint32) uint32 {
//
// Preconditions: end >= start.
func (ns *UserNamespace) allIDsMapped(m *idMapSet, start, end uint32) bool {
ns.mu.Lock()
defer ns.mu.Unlock()
ns.mu.NestedLock()
defer ns.mu.NestedUnlock()
return m.SpanRange(idMapRange{start, end}) == end-start
}
+1 -2
View File
@@ -18,7 +18,6 @@ import (
"math"
"gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sync"
)
// A UserNamespace represents a user namespace. See user_namespaces(7) for
@@ -38,7 +37,7 @@ type UserNamespace struct {
//
// If mu will be locked in multiple UserNamespaces, it must be locked in
// descendant namespaces before ancestors.
mu sync.Mutex `state:"nosave"`
mu userNamespaceMutex `state:"nosave"`
// Mappings of user/group IDs between this namespace and its parent.
//
+1 -2
View File
@@ -23,7 +23,6 @@ import (
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
)
// InvalidCgroupHierarchyID indicates an uninitialized hierarchy ID.
@@ -218,7 +217,7 @@ type CgroupRegistry struct {
//
lastHierarchyID atomicbitops.Uint32
mu sync.Mutex `state:"nosave"`
mu cgroupMutex `state:"nosave"`
// controllers is the set of currently known cgroup controllers on the
// system. Protected by mu.
+25
View File
@@ -3,6 +3,28 @@ load("//tools/go_generics:defs.bzl", "go_template_instance")
package(licenses = ["notice"])
go_template_instance(
name = "epoll_mutex",
out = "epoll_mutex.go",
package = "epoll",
prefix = "epoll",
substrs = {
"genericMark": "epoll",
},
template = "//pkg/sync/locking:generic_mutex",
)
go_template_instance(
name = "epoll_list_mutex",
out = "epoll_list_mutex.go",
package = "epoll",
prefix = "epollList",
substrs = {
"genericMark": "epollList",
},
template = "//pkg/sync/locking:generic_mutex",
)
go_template_instance(
name = "epoll_list",
out = "epoll_list.go",
@@ -20,6 +42,8 @@ go_library(
srcs = [
"epoll.go",
"epoll_list.go",
"epoll_list_mutex.go",
"epoll_mutex.go",
"epoll_state.go",
],
visibility = ["//pkg/sentry:internal"],
@@ -31,6 +55,7 @@ go_library(
"//pkg/sentry/fs/anon",
"//pkg/sentry/fs/fsutil",
"//pkg/sync",
"//pkg/sync/locking",
"//pkg/usermem",
"//pkg/waiter",
"@org_golang_x_sys//unix:go_default_library",
+2 -2
View File
@@ -109,7 +109,7 @@ type EventPoll struct {
// files is the map of all the files currently being observed, it is
// protected by mu.
mu sync.Mutex `state:"nosave"`
mu epollMutex `state:"nosave"`
files map[FileIdentifier]*pollEntry
// listsMu protects manipulation of the lists below. It needs to be a
@@ -129,7 +129,7 @@ type EventPoll struct {
// called on it before it gets moved to the readyList.
// disabledList -- when the entry is disabled. This happens when
// a one-shot entry gets delivered via readEvents().
listsMu sync.Mutex `state:"nosave"`
listsMu epollListMutex `state:"nosave"`
readyList pollEntryList
waitingList pollEntryList
disabledList pollEntryList
+1 -2
View File
@@ -28,7 +28,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/fs/lock"
"gvisor.dev/gvisor/pkg/sentry/limits"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
)
// FDFlags define flags for an individual descriptor.
@@ -85,7 +84,7 @@ type FDTable struct {
k *Kernel
// mu protects below.
mu sync.Mutex `state:"nosave"`
mu fdTableMutex `state:"nosave"`
// fdBitmap shows which fds are already in use.
fdBitmap bitmap.Bitmap `state:"nosave"`
+13
View File
@@ -3,6 +3,17 @@ load("//tools/go_generics:defs.bzl", "go_template_instance")
package(licenses = ["notice"])
go_template_instance(
name = "futex_mutex",
out = "futex_mutex.go",
package = "futex",
prefix = "futexBucket",
substrs = {
"genericMark": "futexBucket",
},
template = "//pkg/sync/locking:generic_mutex",
)
go_template_instance(
name = "atomicptr_bucket",
out = "atomicptr_bucket_unsafe.go",
@@ -31,6 +42,7 @@ go_library(
srcs = [
"atomicptr_bucket_unsafe.go",
"futex.go",
"futex_mutex.go",
"waiter_list.go",
],
visibility = ["//pkg/sentry:internal"],
@@ -42,6 +54,7 @@ go_library(
"//pkg/log",
"//pkg/sentry/memmap",
"//pkg/sync",
"//pkg/sync/locking",
"//pkg/usermem",
],
)
+4 -5
View File
@@ -23,7 +23,6 @@ import (
"gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sync"
)
// KeyKind indicates the type of a Key.
@@ -252,7 +251,7 @@ func (w *Waiter) woken() bool {
// +stateify savable
type bucket struct {
// mu protects waiters and contained Waiter state. See comment in Waiter.
mu sync.Mutex `state:"nosave"`
mu futexBucketMutex `state:"nosave"`
waiters waiterList `state:"zerovalue"`
}
@@ -426,10 +425,10 @@ func (m *Manager) lockBuckets(k1, k2 *Key) (b1 *bucket, b2 *bucket) {
switch {
case i1 < i2:
b1.mu.Lock()
b2.mu.Lock()
b2.mu.NestedLock()
case i2 < i1:
b2.mu.Lock()
b1.mu.Lock()
b1.mu.NestedLock()
default:
b1.mu.Lock()
}
@@ -452,7 +451,7 @@ func (m *Manager) lockBuckets(k1, k2 *Key) (b1 *bucket, b2 *bucket) {
// +checklocksrelease:b1.mu
// +checklocksrelease:b2.mu
func (m *Manager) unlockBuckets(b1, b2 *bucket) {
b1.mu.Unlock()
b1.mu.NestedUnlock()
if b1 != b2 {
b2.mu.Unlock()
}
+3 -3
View File
@@ -189,7 +189,7 @@ type Kernel struct {
// runningTasksMu is used to exclude critical sections when the timer
// disables itself and when the first active task enables the timer,
// ensuring that tasks always see a valid cpuClock value.
runningTasksMu sync.Mutex `state:"nosave"`
runningTasksMu runningTasksMutex `state:"nosave"`
// runningTasks is the total count of tasks currently in
// TaskGoroutineRunningSys or TaskGoroutineRunningApp. i.e., they are
@@ -330,9 +330,9 @@ type Kernel struct {
// the system.
cgroupRegistry *CgroupRegistry
// userCountersMa maps auth.KUID into a set of user counters.
// userCountersMap maps auth.KUID into a set of user counters.
userCountersMap map[auth.KUID]*userCounters
userCountersMapMu sync.Mutex `state:"nosave"`
userCountersMapMu userCountersMutex `state:"nosave"`
}
// InitKernelArgs holds arguments to Init.
+37
View File
@@ -1,13 +1,49 @@
load("//tools:defs.bzl", "go_library", "go_test")
load("//tools/go_generics:defs.bzl", "go_template_instance")
package(licenses = ["notice"])
go_template_instance(
name = "vfs_mutex",
out = "vfs_mutex.go",
package = "pipe",
prefix = "vfs",
substrs = {
"genericMark": "vfs",
},
template = "//pkg/sync/locking:generic_mutex",
)
go_template_instance(
name = "pipe_mutex",
out = "pipe_mutex.go",
package = "pipe",
prefix = "pipe",
substrs = {
"genericMark": "pipe",
},
template = "//pkg/sync/locking:generic_mutex",
)
go_template_instance(
name = "inode_mutex",
out = "inode_mutex.go",
package = "pipe",
prefix = "inode",
substrs = {
"genericMark": "inode",
},
template = "//pkg/sync/locking:generic_mutex",
)
go_library(
name = "pipe",
srcs = [
"device.go",
"inode_mutex.go",
"node.go",
"pipe.go",
"pipe_mutex.go",
"pipe_unsafe.go",
"pipe_util.go",
"reader.go",
@@ -31,6 +67,7 @@ go_library(
"//pkg/sentry/fs/fsutil",
"//pkg/sentry/vfs",
"//pkg/sync",
"//pkg/sync/locking",
"//pkg/usermem",
"//pkg/waiter",
"@org_golang_x_sys//unix:go_default_library",
+1 -2
View File
@@ -26,7 +26,6 @@ import (
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/waiter"
)
@@ -132,7 +131,7 @@ type Pipe struct {
totalWriters atomicbitops.Int32
// mu protects all pipe internal state below.
mu sync.Mutex `state:"nosave"`
mu pipeMutex `state:"nosave"`
// buf holds the pipe's data. buf is a circular buffer; the first valid
// byte in buf is at offset off, and the pipe contains size valid bytes.
+2 -2
View File
@@ -29,9 +29,9 @@ func lockTwoPipes(x, y *Pipe) {
// Lock the two pipes in order of increasing address.
if uintptr(unsafe.Pointer(x)) < uintptr(unsafe.Pointer(y)) {
x.mu.Lock()
y.mu.Lock()
y.mu.NestedLock()
} else {
y.mu.Lock()
x.mu.Lock()
x.mu.NestedLock()
}
}
+1 -1
View File
@@ -415,7 +415,7 @@ func spliceOrTee(ctx context.Context, dst, src *VFSPipeFD, count int64, removeFr
return uint64(n), err
})
dst.pipe.mu.Unlock()
src.pipe.mu.Unlock()
src.pipe.mu.NestedUnlock()
if n > 0 {
dst.pipe.queue.Notify(waiter.ReadableEvents)
+4 -4
View File
@@ -202,11 +202,11 @@ func (pg *ProcessGroup) handleOrphan() {
if tg.processGroup != pg {
return
}
tg.signalHandlers.mu.Lock()
tg.signalHandlers.mu.NestedLock()
if tg.groupStopComplete {
hasStopped = true
}
tg.signalHandlers.mu.Unlock()
tg.signalHandlers.mu.NestedUnlock()
})
if !hasStopped {
return
@@ -217,10 +217,10 @@ func (pg *ProcessGroup) handleOrphan() {
if tg.processGroup != pg {
return
}
tg.signalHandlers.mu.Lock()
tg.signalHandlers.mu.NestedLock()
tg.leader.sendSignalLocked(SignalInfoPriv(linux.SIGHUP), true /* group */)
tg.leader.sendSignalLocked(SignalInfoPriv(linux.SIGCONT), true /* group */)
tg.signalHandlers.mu.Unlock()
tg.signalHandlers.mu.NestedUnlock()
})
return
+1 -2
View File
@@ -16,7 +16,6 @@ package kernel
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/sync"
)
// SignalHandlers holds information about signal actions.
@@ -26,7 +25,7 @@ type SignalHandlers struct {
// mu protects actions, as well as the signal state of all tasks and thread
// groups using this SignalHandlers object. (See comment on
// ThreadGroup.signalHandlers.)
mu sync.Mutex `state:"nosave"`
mu signalHandlersMutex `state:"nosave"`
// actions is the action to be taken upon receiving each signal.
actions map[linux.Signal]linux.SigAction
+13 -1
View File
@@ -1,10 +1,21 @@
load("//tools:defs.bzl", "go_library")
load("//pkg/sync/locking:locking.bzl", "declare_mutex")
licenses(["notice"])
declare_mutex(
name = "signal_operations_mutex",
out = "signal_operations_mutex.go",
package = "signalfd",
prefix = "operations",
)
go_library(
name = "signalfd",
srcs = ["signalfd.go"],
srcs = [
"signal_operations_mutex.go",
"signalfd.go",
],
visibility = ["//pkg/sentry:internal"],
deps = [
"//pkg/abi/linux",
@@ -15,6 +26,7 @@ go_library(
"//pkg/sentry/fs/fsutil",
"//pkg/sentry/kernel",
"//pkg/sync",
"//pkg/sync/locking",
"//pkg/usermem",
"//pkg/waiter",
],
+1 -2
View File
@@ -23,7 +23,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/fs/anon"
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/usermem"
"gvisor.dev/gvisor/pkg/waiter"
)
@@ -55,7 +54,7 @@ type SignalOperations struct {
queue waiter.Queue
// mu protects below.
mu sync.Mutex `state:"nosave"`
mu operationsMutex `state:"nosave"`
// entry is the entry reigstered with the target.
entry waiter.Entry
+1 -1
View File
@@ -255,7 +255,7 @@ type Task struct {
containerID string
// mu protects some of the following fields.
mu sync.Mutex `state:"nosave"`
mu taskMutex `state:"nosave"`
// image holds task data provided by the ELF loader.
//

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