runc aways open "/proc/sys/kernel/cap_last_cap"
Description
runc aways open "/proc/sys/kernel/cap_last_cap" because it it done it init().
func init() {
var hdr capHeader
capget(&hdr, nil)
capVers = hdr.version
if initLastCap() == nil {
CAP_LAST_CAP = capLastCap
if capLastCap > 31 {
capUpperMask = (uint32(1) << (uint(capLastCap) - 31)) - 1
} else {
capUpperMask = 0
}
}
}
func initLastCap() error {
if capLastCap != 0 {
return nil
}
f, err := os.Open("/proc/sys/kernel/cap_last_cap")
if err != nil {
return err
}
defer f.Close()
var b []byte = make([]byte, 11)
_, err = f.Read(b)
if err != nil {
return err
}
fmt.Sscanf(string(b), "%d", &capLastCap)
return nil
}
Steps to reproduce the issue
1.runc --help will read /proc/sys/kernel/cap_last_cap
Describe the results you received and expected
read /proc/sys/kernel/cap_last_cap when needed
What version of runc are you using?
1.1.12
Host OS information
linux
Host kernel information
any
ping @lifubang @kolyshkin
This is a bug in https://github.com/syndtr/gocapability. You would just need to switch to using sync.Once.
EDIT: Ah, you already made a bug (syndtr/gocapability#26). Please link related bugs so they're easier to find.
this library hasn't been updated for a long time. maybe nobody will maintain it. Can we move it to github.com/opencontainers/runc/libcontainer/capabilities ? use sync.Once is not a good idea. I want use it only when we need it. if use sync.Once runc version also call it.
I mean to do sync.Once like this (which is what we usually do elsewhere in runc):
var (
someBoolOnce sync.Once
someBool bool
)
func getSomeBool() bool {
someBoolOnce.Do(func() { ... })
return someBool
}
A slightly more modern way is to use sync.OnceValue. For usage example, see #4358.
Alas there's no way to stop init() functions from vendored packages to be run at startup.
Re github.com/syndtr/gocapability, I have 4 easy-to-review PRs in there opened Feb 2023, and it seems the original maintainer is not interested. Guess it's time to fork it.