mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-10 21:53:57 +08:00
Merge pull request #5328 from cyphar/1.5-libpathrs-0.2.5-5921
[1.5] deps: update to libpathrs 0.2.5
This commit is contained in:
@@ -15,7 +15,7 @@ permissions:
|
|||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
env:
|
env:
|
||||||
LIBPATHRS_VERSION: "0.2.4"
|
LIBPATHRS_VERSION: "0.2.5"
|
||||||
# Don't ignore C warnings. Note that the output of "go env CGO_CFLAGS" by default is "-g -O2", so we keep them.
|
# Don't ignore C warnings. Note that the output of "go env CGO_CFLAGS" by default is "-g -O2", so we keep them.
|
||||||
CGO_CFLAGS: -g -O2 -Werror
|
CGO_CFLAGS: -g -O2 -Werror
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ permissions:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
GO_VERSION: 1.25
|
GO_VERSION: 1.25
|
||||||
LIBPATHRS_VERSION: "0.2.4"
|
LIBPATHRS_VERSION: "0.2.5"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
keyring:
|
keyring:
|
||||||
|
|||||||
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added ###
|
||||||
|
- `runc version` and `runc features` now provide version information about
|
||||||
|
libpathrs when runc is built with the `libpathrs` build tag. (#5291, #5328)
|
||||||
|
|
||||||
|
### Changed ###
|
||||||
|
- runc now depends on [libpathrs v0.2.5] or later, and attempting to build with
|
||||||
|
older versions will cause compilation errors. (#5291, #5328)
|
||||||
|
|
||||||
|
[libpathrs v0.2.5]: https://github.com/cyphar/libpathrs/releases/tag/v0.2.5
|
||||||
|
|
||||||
## [1.5.0-rc.3] - 2026-06-13
|
## [1.5.0-rc.3] - 2026-06-13
|
||||||
|
|
||||||
> The best way to get a drink out of a Vogon is to stick your finger down his
|
> The best way to get a drink out of a Vogon is to stick your finger down his
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
ARG GO_VERSION=1.25
|
ARG GO_VERSION=1.25
|
||||||
ARG BATS_VERSION=v1.12.0
|
ARG BATS_VERSION=v1.12.0
|
||||||
ARG LIBSECCOMP_VERSION=2.6.0
|
ARG LIBSECCOMP_VERSION=2.6.0
|
||||||
ARG LIBPATHRS_VERSION=0.2.4
|
ARG LIBPATHRS_VERSION=0.2.5
|
||||||
|
|
||||||
FROM golang:${GO_VERSION}-trixie
|
FROM golang:${GO_VERSION}-trixie
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ The following dependencies are optional:
|
|||||||
|
|
||||||
[libpathrs][] is a Rust library runc can optionally use for path safety. As
|
[libpathrs][] is a Rust library runc can optionally use for path safety. As
|
||||||
mentioned in [the build tag section](#build-tags), its use is controlled with
|
mentioned in [the build tag section](#build-tags), its use is controlled with
|
||||||
the `libpathrs` build tag. runc currently requires at least libpathrs 0.2.4 in
|
the `libpathrs` build tag. runc currently requires *at least libpathrs 0.2.5*
|
||||||
order to function properly.
|
in order to function properly.
|
||||||
|
|
||||||
At time of writing, very few distributions have libpathrs packages and so it is
|
At time of writing, very few distributions have libpathrs packages and so it is
|
||||||
usually necessary to build and install it locally. For detailed installation
|
usually necessary to build and install it locally. For detailed installation
|
||||||
@@ -76,7 +76,7 @@ dependencies like `clang` and `lld`), the following steps are all that are
|
|||||||
really necessary to install libpathrs:
|
really necessary to install libpathrs:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
LIBPATHRS_VERSION=0.2.4
|
LIBPATHRS_VERSION=0.2.5
|
||||||
curl -o - -sSL https://github.com/cyphar/libpathrs/releases/download/v${LIBPATHRS_VERSION}/libpathrs-${LIBPATHRS_VERSION}.tar.xz | tar xvfJ -
|
curl -o - -sSL https://github.com/cyphar/libpathrs/releases/download/v${LIBPATHRS_VERSION}/libpathrs-${LIBPATHRS_VERSION}.tar.xz | tar xvfJ -
|
||||||
cd libpathrs-${LIBPATHRS_VERSION}/
|
cd libpathrs-${LIBPATHRS_VERSION}/
|
||||||
make release
|
make release
|
||||||
|
|||||||
@@ -93,6 +93,10 @@ var featuresCommand = cli.Command{
|
|||||||
feat.Annotations[runcfeatures.AnnotationLibseccompVersion] = fmt.Sprintf("%d.%d.%d", major, minor, patch)
|
feat.Annotations[runcfeatures.AnnotationLibseccompVersion] = fmt.Sprintf("%d.%d.%d", major, minor, patch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v := pathrsVersionString(); v != "" {
|
||||||
|
feat.Annotations[runcfeatures.AnnotationLibpathrsVersion] = v
|
||||||
|
}
|
||||||
|
|
||||||
enc := json.NewEncoder(context.App.Writer)
|
enc := json.NewEncoder(context.App.Writer)
|
||||||
enc.SetIndent("", " ")
|
enc.SetIndent("", " ")
|
||||||
return enc.Encode(feat)
|
return enc.Encode(feat)
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
//go:build libpathrs
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cyphar.com/go-pathrs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func pathrsVersionString() string {
|
||||||
|
info, err := pathrs.LibraryVersion()
|
||||||
|
if err != nil {
|
||||||
|
panic(err) // should never happen
|
||||||
|
}
|
||||||
|
return info.VersionString
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
//go:build !libpathrs
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func pathrsVersionString() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
@@ -3,10 +3,11 @@ module github.com/opencontainers/runc
|
|||||||
go 1.25.0
|
go 1.25.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
cyphar.com/go-pathrs v0.2.5
|
||||||
github.com/checkpoint-restore/go-criu/v8 v8.3.0
|
github.com/checkpoint-restore/go-criu/v8 v8.3.0
|
||||||
github.com/containerd/console v1.0.5
|
github.com/containerd/console v1.0.5
|
||||||
github.com/coreos/go-systemd/v22 v22.7.0
|
github.com/coreos/go-systemd/v22 v22.7.0
|
||||||
github.com/cyphar/filepath-securejoin v0.6.1
|
github.com/cyphar/filepath-securejoin v0.7.0
|
||||||
github.com/docker/go-units v0.5.0
|
github.com/docker/go-units v0.5.0
|
||||||
github.com/godbus/dbus/v5 v5.2.2
|
github.com/godbus/dbus/v5 v5.2.2
|
||||||
github.com/moby/sys/capability v0.4.0
|
github.com/moby/sys/capability v0.4.0
|
||||||
@@ -28,7 +29,6 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cyphar.com/go-pathrs v0.2.4 // indirect
|
|
||||||
github.com/aperturerobotics/protobuf-go-lite v0.14.0 // indirect
|
github.com/aperturerobotics/protobuf-go-lite v0.14.0 // indirect
|
||||||
github.com/cilium/ebpf v0.17.3 // indirect
|
github.com/cilium/ebpf v0.17.3 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
cyphar.com/go-pathrs v0.2.4 h1:iD/mge36swa1UFKdINkr1Frkpp6wZsy3YYEildj9cLY=
|
cyphar.com/go-pathrs v0.2.5 h1:SnX9FBvnoyn3lUs1dkMgZ52bAETpirNu3FTRh5HlRik=
|
||||||
cyphar.com/go-pathrs v0.2.4/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
|
cyphar.com/go-pathrs v0.2.5/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
|
||||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
github.com/aperturerobotics/protobuf-go-lite v0.14.0 h1:6YhovtoUZtXgXLHZ2VV2GCYUzFfi8UN6172Vl2flNlE=
|
github.com/aperturerobotics/protobuf-go-lite v0.14.0 h1:6YhovtoUZtXgXLHZ2VV2GCYUzFfi8UN6172Vl2flNlE=
|
||||||
github.com/aperturerobotics/protobuf-go-lite v0.14.0/go.mod h1:lGH3s5ArCTXKI4wJdlNpaybUtwSjfAG0vdWjxOfMcF8=
|
github.com/aperturerobotics/protobuf-go-lite v0.14.0/go.mod h1:lGH3s5ArCTXKI4wJdlNpaybUtwSjfAG0vdWjxOfMcF8=
|
||||||
@@ -13,8 +13,8 @@ github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj
|
|||||||
github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w=
|
github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
|
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE=
|
github.com/cyphar/filepath-securejoin v0.7.0 h1:s0Y3ITPy6sQn5xt54DuYvTF8hu134ooYLUb58DX/HjE=
|
||||||
github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
|
github.com/cyphar/filepath-securejoin v0.7.0/go.mod h1:ymLGms/u3BYaviIiuKFnUx8EkQEZeK6cInNoAPJA3o4=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
|||||||
@@ -51,6 +51,10 @@ func printVersion(c *cli.Context) {
|
|||||||
if major+minor+micro > 0 {
|
if major+minor+micro > 0 {
|
||||||
fmt.Fprintf(w, "libseccomp: %d.%d.%d\n", major, minor, micro)
|
fmt.Fprintf(w, "libseccomp: %d.%d.%d\n", major, minor, micro)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v := pathrsVersionString(); v != "" {
|
||||||
|
fmt.Fprintf(w, "libpathrs: %s\n", v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ declare -A RUST_TARGET_TO_CC=(
|
|||||||
|
|
||||||
# sha256 checksums for libpathrs release tarballs.
|
# sha256 checksums for libpathrs release tarballs.
|
||||||
declare -A LIBPATHRS_SHA256=(
|
declare -A LIBPATHRS_SHA256=(
|
||||||
["0.2.4"]=45aca68e698b844fae0cf7c459bc441519b0e7b48397caa7d3936cfc68d73f77
|
["0.2.5"]=f8f4a9419eb839cd5decbd120b65f0495bf6eac07155477fe39a8c2a23da589d
|
||||||
)
|
)
|
||||||
|
|
||||||
function generate_cargo_config() {
|
function generate_cargo_config() {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ set -e
|
|||||||
# Project-specific options and functions. In *theory* you shouldn't need to
|
# Project-specific options and functions. In *theory* you shouldn't need to
|
||||||
# touch anything else in this script in order to use this elsewhere.
|
# touch anything else in this script in order to use this elsewhere.
|
||||||
: "${LIBSECCOMP_VERSION:=2.6.0}"
|
: "${LIBSECCOMP_VERSION:=2.6.0}"
|
||||||
: "${LIBPATHRS_VERSION:=0.2.4}"
|
: "${LIBPATHRS_VERSION:=0.2.5}"
|
||||||
project="runc"
|
project="runc"
|
||||||
root="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")/..")"
|
root="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")/..")"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# Supports Fedora and EL-based distributions.
|
# Supports Fedora and EL-based distributions.
|
||||||
set -eux -o pipefail
|
set -eux -o pipefail
|
||||||
|
|
||||||
: "${LIBPATHRS_VERSION:=0.2.4}"
|
: "${LIBPATHRS_VERSION:=0.2.5}"
|
||||||
|
|
||||||
# BATS_VERSION is only consumed for the EL8 platform as its bats package is too old.
|
# BATS_VERSION is only consumed for the EL8 platform as its bats package is too old.
|
||||||
: "${BATS_VERSION:=v1.12.0}"
|
: "${BATS_VERSION:=v1.12.0}"
|
||||||
|
|||||||
@@ -22,4 +22,7 @@ const (
|
|||||||
// AnnotationLibseccompVersion is the version of libseccomp, e.g., "2.5.1".
|
// AnnotationLibseccompVersion is the version of libseccomp, e.g., "2.5.1".
|
||||||
// Note that the runtime MAY support seccomp even when this annotation is not present.
|
// Note that the runtime MAY support seccomp even when this annotation is not present.
|
||||||
AnnotationLibseccompVersion = "io.github.seccomp.libseccomp.version"
|
AnnotationLibseccompVersion = "io.github.seccomp.libseccomp.version"
|
||||||
|
|
||||||
|
// AnnotationLibpathrsVersion is the runtime version of libpathrs.
|
||||||
|
AnnotationLibpathrsVersion = "com.cyphar.pathrs.libpathrs.version"
|
||||||
)
|
)
|
||||||
|
|||||||
+5
-3
@@ -17,6 +17,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
"cyphar.com/go-pathrs/internal/fdutils"
|
"cyphar.com/go-pathrs/internal/fdutils"
|
||||||
"cyphar.com/go-pathrs/internal/libpathrs"
|
"cyphar.com/go-pathrs/internal/libpathrs"
|
||||||
)
|
)
|
||||||
@@ -56,11 +58,11 @@ func HandleFromFile(file *os.File) (*Handle, error) {
|
|||||||
// and can be opened multiple times.
|
// and can be opened multiple times.
|
||||||
//
|
//
|
||||||
// The handle returned is only usable for reading, and this is method is
|
// The handle returned is only usable for reading, and this is method is
|
||||||
// shorthand for [Handle.OpenFile] with os.O_RDONLY.
|
// shorthand for [Handle.OpenFile] with [unix.O_RDONLY].
|
||||||
//
|
//
|
||||||
// TODO: Rename these to "Reopen" or something.
|
// TODO: Rename these to "Reopen" or something.
|
||||||
func (h *Handle) Open() (*os.File, error) {
|
func (h *Handle) Open() (*os.File, error) {
|
||||||
return h.OpenFile(os.O_RDONLY)
|
return h.OpenFile(unix.O_RDONLY)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenFile creates an "upgraded" file handle to the file referenced by the
|
// OpenFile creates an "upgraded" file handle to the file referenced by the
|
||||||
@@ -71,7 +73,7 @@ func (h *Handle) Open() (*os.File, error) {
|
|||||||
// handle.
|
// handle.
|
||||||
//
|
//
|
||||||
// TODO: Rename these to "Reopen" or something.
|
// TODO: Rename these to "Reopen" or something.
|
||||||
func (h *Handle) OpenFile(flags int) (*os.File, error) {
|
func (h *Handle) OpenFile(flags uint64) (*os.File, error) {
|
||||||
return fdutils.WithFileFd(h.inner, func(fd uintptr) (*os.File, error) {
|
return fdutils.WithFileFd(h.inner, func(fd uintptr) (*os.File, error) {
|
||||||
newFd, err := libpathrs.Reopen(fd, flags)
|
newFd, err := libpathrs.Reopen(fd, flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+52
-24
@@ -60,8 +60,8 @@ func OpenRoot(path string) (uintptr, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reopen wraps pathrs_reopen.
|
// Reopen wraps pathrs_reopen.
|
||||||
func Reopen(fd uintptr, flags int) (uintptr, error) {
|
func Reopen(fd uintptr, flags uint64) (uintptr, error) {
|
||||||
newFd := C.pathrs_reopen(C.int(fd), C.int(flags))
|
newFd := C.pathrs_reopen(C.int(fd), C.uint64_t(flags))
|
||||||
return uintptr(newFd), fetchError(newFd)
|
return uintptr(newFd), fetchError(newFd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,11 +84,11 @@ func InRootResolveNoFollow(rootFd uintptr, path string) (uintptr, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InRootOpen wraps pathrs_inroot_open.
|
// InRootOpen wraps pathrs_inroot_open.
|
||||||
func InRootOpen(rootFd uintptr, path string, flags int) (uintptr, error) {
|
func InRootOpen(rootFd uintptr, path string, flags uint64) (uintptr, error) {
|
||||||
cPath := C.CString(path)
|
cPath := C.CString(path)
|
||||||
defer C.free(unsafe.Pointer(cPath))
|
defer C.free(unsafe.Pointer(cPath))
|
||||||
|
|
||||||
fd := C.pathrs_inroot_open(C.int(rootFd), cPath, C.int(flags))
|
fd := C.pathrs_inroot_open(C.int(rootFd), cPath, C.uint64_t(flags))
|
||||||
return uintptr(fd), fetchError(fd)
|
return uintptr(fd), fetchError(fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,23 +145,23 @@ func InRootRemoveAll(rootFd uintptr, path string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InRootCreat wraps pathrs_inroot_creat.
|
// InRootCreat wraps pathrs_inroot_creat.
|
||||||
func InRootCreat(rootFd uintptr, path string, flags int, mode uint32) (uintptr, error) {
|
func InRootCreat(rootFd uintptr, path string, flags uint64, mode uint32) (uintptr, error) {
|
||||||
cPath := C.CString(path)
|
cPath := C.CString(path)
|
||||||
defer C.free(unsafe.Pointer(cPath))
|
defer C.free(unsafe.Pointer(cPath))
|
||||||
|
|
||||||
fd := C.pathrs_inroot_creat(C.int(rootFd), cPath, C.int(flags), C.uint(mode))
|
fd := C.pathrs_inroot_creat(C.int(rootFd), cPath, C.uint64_t(flags), C.uint(mode))
|
||||||
return uintptr(fd), fetchError(fd)
|
return uintptr(fd), fetchError(fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InRootRename wraps pathrs_inroot_rename.
|
// InRootRename wraps pathrs_inroot_rename.
|
||||||
func InRootRename(rootFd uintptr, src, dst string, flags uint) error {
|
func InRootRename(oldRootFd uintptr, oldPath string, newRootFd uintptr, newPath string, flags uint64) error {
|
||||||
cSrc := C.CString(src)
|
cOldPath := C.CString(oldPath)
|
||||||
defer C.free(unsafe.Pointer(cSrc))
|
defer C.free(unsafe.Pointer(cOldPath))
|
||||||
|
|
||||||
cDst := C.CString(dst)
|
cNewPath := C.CString(newPath)
|
||||||
defer C.free(unsafe.Pointer(cDst))
|
defer C.free(unsafe.Pointer(cNewPath))
|
||||||
|
|
||||||
err := C.pathrs_inroot_rename(C.int(rootFd), cSrc, cDst, C.uint(flags))
|
err := C.pathrs_inroot_rename(C.int(oldRootFd), cOldPath, C.int(newRootFd), cNewPath, C.uint64_t(flags))
|
||||||
return fetchError(err)
|
return fetchError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,26 +193,26 @@ func InRootMknod(rootFd uintptr, path string, mode uint32, dev uint64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InRootSymlink wraps pathrs_inroot_symlink.
|
// InRootSymlink wraps pathrs_inroot_symlink.
|
||||||
func InRootSymlink(rootFd uintptr, path, target string) error {
|
func InRootSymlink(target string, rootFd uintptr, linkpath string) error {
|
||||||
cPath := C.CString(path)
|
cLinkpath := C.CString(linkpath)
|
||||||
defer C.free(unsafe.Pointer(cPath))
|
defer C.free(unsafe.Pointer(cLinkpath))
|
||||||
|
|
||||||
cTarget := C.CString(target)
|
cTarget := C.CString(target)
|
||||||
defer C.free(unsafe.Pointer(cTarget))
|
defer C.free(unsafe.Pointer(cTarget))
|
||||||
|
|
||||||
err := C.pathrs_inroot_symlink(C.int(rootFd), cPath, cTarget)
|
err := C.pathrs_inroot_symlink(cTarget, C.int(rootFd), cLinkpath)
|
||||||
return fetchError(err)
|
return fetchError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InRootHardlink wraps pathrs_inroot_hardlink.
|
// InRootHardlink wraps pathrs_inroot_hardlink.
|
||||||
func InRootHardlink(rootFd uintptr, path, target string) error {
|
func InRootHardlink(oldRootFd uintptr, oldPath string, newRootFd uintptr, newPath string, flags uint64) error {
|
||||||
cPath := C.CString(path)
|
cNewPath := C.CString(newPath)
|
||||||
defer C.free(unsafe.Pointer(cPath))
|
defer C.free(unsafe.Pointer(cNewPath))
|
||||||
|
|
||||||
cTarget := C.CString(target)
|
cOldPath := C.CString(oldPath)
|
||||||
defer C.free(unsafe.Pointer(cTarget))
|
defer C.free(unsafe.Pointer(cOldPath))
|
||||||
|
|
||||||
err := C.pathrs_inroot_hardlink(C.int(rootFd), cPath, cTarget)
|
err := C.pathrs_inroot_hardlink(C.int(oldRootFd), cOldPath, C.int(newRootFd), cNewPath, C.uint64_t(flags))
|
||||||
return fetchError(err)
|
return fetchError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,13 +277,13 @@ func init() {
|
|||||||
func ProcPid(pid uint32) ProcBase { return ProcBaseTypePid | ProcBase(pid) }
|
func ProcPid(pid uint32) ProcBase { return ProcBaseTypePid | ProcBase(pid) }
|
||||||
|
|
||||||
// ProcOpenat wraps pathrs_proc_openat.
|
// ProcOpenat wraps pathrs_proc_openat.
|
||||||
func ProcOpenat(procRootFd int, base ProcBase, path string, flags int) (uintptr, error) {
|
func ProcOpenat(procRootFd int, base ProcBase, path string, flags uint64) (uintptr, error) {
|
||||||
cBase := C.pathrs_proc_base_t(base)
|
cBase := C.pathrs_proc_base_t(base)
|
||||||
|
|
||||||
cPath := C.CString(path)
|
cPath := C.CString(path)
|
||||||
defer C.free(unsafe.Pointer(cPath))
|
defer C.free(unsafe.Pointer(cPath))
|
||||||
|
|
||||||
fd := C.pathrs_proc_openat(C.int(procRootFd), cBase, cPath, C.int(flags))
|
fd := C.pathrs_proc_openat(C.int(procRootFd), cBase, cPath, C.uint64_t(flags))
|
||||||
return uintptr(fd), fetchError(fd)
|
return uintptr(fd), fetchError(fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,3 +335,31 @@ func ProcfsOpen(how *ProcfsOpenHow) (uintptr, error) {
|
|||||||
fd := C.pathrs_procfs_open((*C.pathrs_procfs_open_how)(how), C.size_t(unsafe.Sizeof(*how)))
|
fd := C.pathrs_procfs_open((*C.pathrs_procfs_open_how)(how), C.size_t(unsafe.Sizeof(*how)))
|
||||||
return uintptr(fd), fetchError(fd)
|
return uintptr(fd), fetchError(fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VersionInfo is a Go-friendly form of pathrs_version_info_t (struct).
|
||||||
|
type VersionInfo struct {
|
||||||
|
VersionString string
|
||||||
|
}
|
||||||
|
|
||||||
|
// versionInfo is pathrs_version_info_t (struct).
|
||||||
|
type versionInfo C.pathrs_version_info_t
|
||||||
|
|
||||||
|
// Version is pathrs_version_info_t (sizeof(version) is passed automatically).
|
||||||
|
func Version() (*VersionInfo, error) {
|
||||||
|
var rawVersion versionInfo
|
||||||
|
size := C.pathrs_version((*C.pathrs_version_info_t)(&rawVersion), C.size_t(unsafe.Sizeof(rawVersion)))
|
||||||
|
switch {
|
||||||
|
case size < 0:
|
||||||
|
return nil, fetchError(size)
|
||||||
|
case size > 0:
|
||||||
|
// TODO(log): Logging?
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
// TODO(log): Add a log statement if sizeof(rawVersion) is bigger than
|
||||||
|
// the number of fields we store in VersionInfo. Otherwise a rebuild
|
||||||
|
// will mask that Go callers cannot see any new fields.
|
||||||
|
return &VersionInfo{
|
||||||
|
VersionString: C.GoString(rawVersion.version_string),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+5
-5
@@ -127,7 +127,7 @@ func (proc *Handle) fd() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Should we expose open?
|
// TODO: Should we expose open?
|
||||||
func (proc *Handle) open(base ProcBase, path string, flags int) (_ *os.File, Closer ThreadCloser, Err error) {
|
func (proc *Handle) open(base ProcBase, path string, flags uint64) (_ *os.File, Closer ThreadCloser, Err error) {
|
||||||
var closer ThreadCloser
|
var closer ThreadCloser
|
||||||
if base == ProcThreadSelf {
|
if base == ProcThreadSelf {
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
@@ -154,7 +154,7 @@ func (proc *Handle) open(base ProcBase, path string, flags int) (_ *os.File, Clo
|
|||||||
// (such as /proc/cpuinfo) or information about other processes (such as
|
// (such as /proc/cpuinfo) or information about other processes (such as
|
||||||
// /proc/1). Accessing your own process information should be done using
|
// /proc/1). Accessing your own process information should be done using
|
||||||
// [Handle.OpenSelf] or [Handle.OpenThreadSelf].
|
// [Handle.OpenSelf] or [Handle.OpenThreadSelf].
|
||||||
func (proc *Handle) OpenRoot(path string, flags int) (*os.File, error) {
|
func (proc *Handle) OpenRoot(path string, flags uint64) (*os.File, error) {
|
||||||
file, closer, err := proc.open(ProcRoot, path, flags)
|
file, closer, err := proc.open(ProcRoot, path, flags)
|
||||||
if closer != nil {
|
if closer != nil {
|
||||||
// should not happen
|
// should not happen
|
||||||
@@ -180,7 +180,7 @@ func (proc *Handle) OpenRoot(path string, flags int) (*os.File, error) {
|
|||||||
// Unlike [Handle.OpenThreadSelf], this method does not involve locking
|
// Unlike [Handle.OpenThreadSelf], this method does not involve locking
|
||||||
// the goroutine to the current OS thread and so is simpler to use and
|
// the goroutine to the current OS thread and so is simpler to use and
|
||||||
// theoretically has slightly less overhead.
|
// theoretically has slightly less overhead.
|
||||||
func (proc *Handle) OpenSelf(path string, flags int) (*os.File, error) {
|
func (proc *Handle) OpenSelf(path string, flags uint64) (*os.File, error) {
|
||||||
file, closer, err := proc.open(ProcSelf, path, flags)
|
file, closer, err := proc.open(ProcSelf, path, flags)
|
||||||
if closer != nil {
|
if closer != nil {
|
||||||
// should not happen
|
// should not happen
|
||||||
@@ -198,7 +198,7 @@ func (proc *Handle) OpenSelf(path string, flags int) (*os.File, error) {
|
|||||||
// Be aware that due to PID recycling, using this is generally not safe except
|
// Be aware that due to PID recycling, using this is generally not safe except
|
||||||
// in certain circumstances. See the documentation of [ProcPid] for more
|
// in certain circumstances. See the documentation of [ProcPid] for more
|
||||||
// details.
|
// details.
|
||||||
func (proc *Handle) OpenPid(pid int, path string, flags int) (*os.File, error) {
|
func (proc *Handle) OpenPid(pid int, path string, flags uint64) (*os.File, error) {
|
||||||
file, closer, err := proc.open(ProcPid(pid), path, flags)
|
file, closer, err := proc.open(ProcPid(pid), path, flags)
|
||||||
if closer != nil {
|
if closer != nil {
|
||||||
// should not happen
|
// should not happen
|
||||||
@@ -225,7 +225,7 @@ func (proc *Handle) OpenPid(pid int, path string, flags int) (*os.File, error) {
|
|||||||
// callback MUST be called AFTER you have finished using the returned
|
// callback MUST be called AFTER you have finished using the returned
|
||||||
// [os.File]. This callback is completely separate to [os.File.Close], so it
|
// [os.File]. This callback is completely separate to [os.File.Close], so it
|
||||||
// must be called regardless of how you close the handle.
|
// must be called regardless of how you close the handle.
|
||||||
func (proc *Handle) OpenThreadSelf(path string, flags int) (*os.File, ThreadCloser, error) {
|
func (proc *Handle) OpenThreadSelf(path string, flags uint64) (*os.File, ThreadCloser, error) {
|
||||||
return proc.open(ProcThreadSelf, path, flags)
|
return proc.open(ProcThreadSelf, path, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
-26
@@ -19,6 +19,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
"cyphar.com/go-pathrs/internal/fdutils"
|
"cyphar.com/go-pathrs/internal/fdutils"
|
||||||
"cyphar.com/go-pathrs/internal/libpathrs"
|
"cyphar.com/go-pathrs/internal/libpathrs"
|
||||||
)
|
)
|
||||||
@@ -27,7 +29,7 @@ import (
|
|||||||
// purpose of this "root handle" is to perform operations within the directory
|
// purpose of this "root handle" is to perform operations within the directory
|
||||||
// tree, or to get a [Handle] to inodes within the directory tree.
|
// tree, or to get a [Handle] to inodes within the directory tree.
|
||||||
//
|
//
|
||||||
// At time of writing, it is considered a *VERY BAD IDEA* to open a [Root]
|
// At time of writing, it is considered a *VERY BAD IDEA* to open a Root
|
||||||
// inside a possibly-attacker-controlled directory tree. While we do have
|
// inside a possibly-attacker-controlled directory tree. While we do have
|
||||||
// protections that should defend against it, it's far more dangerous than just
|
// protections that should defend against it, it's far more dangerous than just
|
||||||
// opening a directory tree which is not inside a potentially-untrusted
|
// opening a directory tree which is not inside a potentially-untrusted
|
||||||
@@ -68,7 +70,7 @@ func RootFromFile(file *os.File) (*Root, error) {
|
|||||||
//
|
//
|
||||||
// All symlinks (including trailing symlinks) are followed, but they are
|
// All symlinks (including trailing symlinks) are followed, but they are
|
||||||
// resolved within the rootfs. If you wish to open a handle to the symlink
|
// resolved within the rootfs. If you wish to open a handle to the symlink
|
||||||
// itself, use [ResolveNoFollow].
|
// itself, use [Root.ResolveNoFollow].
|
||||||
func (r *Root) Resolve(path string) (*Handle, error) {
|
func (r *Root) Resolve(path string) (*Handle, error) {
|
||||||
return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*Handle, error) {
|
return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*Handle, error) {
|
||||||
handleFd, err := libpathrs.InRootResolve(rootFd, path)
|
handleFd, err := libpathrs.InRootResolve(rootFd, path)
|
||||||
@@ -83,10 +85,10 @@ func (r *Root) Resolve(path string) (*Handle, error) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResolveNoFollow is effectively an O_NOFOLLOW version of [Resolve]. Their
|
// ResolveNoFollow is effectively an [unix.O_NOFOLLOW] version of
|
||||||
// behaviour is identical, except that *trailing* symlinks will not be
|
// [Root.Resolve]. Their behaviour is identical, except that *trailing*
|
||||||
// followed. If the final component is a trailing symlink, an O_PATH|O_NOFOLLOW
|
// symlinks will not be followed. If the final component is a trailing symlink,
|
||||||
// handle to the symlink itself is returned.
|
// an [unix.O_PATH]|[unix.O_NOFOLLOW] handle to the symlink itself is returned.
|
||||||
func (r *Root) ResolveNoFollow(path string) (*Handle, error) {
|
func (r *Root) ResolveNoFollow(path string) (*Handle, error) {
|
||||||
return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*Handle, error) {
|
return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*Handle, error) {
|
||||||
handleFd, err := libpathrs.InRootResolveNoFollow(rootFd, path)
|
handleFd, err := libpathrs.InRootResolveNoFollow(rootFd, path)
|
||||||
@@ -101,29 +103,29 @@ func (r *Root) ResolveNoFollow(path string) (*Handle, error) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open is effectively shorthand for [Resolve] followed by [Handle.Open], but
|
// Open is effectively shorthand for [Root.Resolve] followed by [Handle.Open],
|
||||||
// can be slightly more efficient (it reduces CGo overhead and the number of
|
// but can be slightly more efficient (it reduces CGo overhead and the number
|
||||||
// syscalls used when using the openat2-based resolver) and is arguably more
|
// of syscalls used when using the openat2-based resolver) and is arguably more
|
||||||
// ergonomic to use.
|
// ergonomic to use.
|
||||||
//
|
//
|
||||||
// This is effectively equivalent to [os.Open].
|
// This is effectively equivalent to [os.Open].
|
||||||
func (r *Root) Open(path string) (*os.File, error) {
|
func (r *Root) Open(path string) (*os.File, error) {
|
||||||
return r.OpenFile(path, os.O_RDONLY)
|
return r.OpenFile(path, unix.O_RDONLY)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenFile is effectively shorthand for [Resolve] followed by
|
// OpenFile is effectively shorthand for [Root.Resolve] followed by
|
||||||
// [Handle.OpenFile], but can be slightly more efficient (it reduces CGo
|
// [Handle.OpenFile], but can be slightly more efficient (it reduces CGo
|
||||||
// overhead and the number of syscalls used when using the openat2-based
|
// overhead and the number of syscalls used when using the openat2-based
|
||||||
// resolver) and is arguably more ergonomic to use.
|
// resolver) and is arguably more ergonomic to use.
|
||||||
//
|
//
|
||||||
// However, if flags contains os.O_NOFOLLOW and the path is a symlink, then
|
// However, if flags contains [unix.O_NOFOLLOW] and the path is a symlink, then
|
||||||
// OpenFile's behaviour will match that of openat2. In most cases an error will
|
// OpenFile's behaviour will match that of openat2. In most cases an error will
|
||||||
// be returned, but if os.O_PATH is provided along with os.O_NOFOLLOW then a
|
// be returned, but if [unix.O_PATH] is provided along with [unix.O_NOFOLLOW]
|
||||||
// file equivalent to [ResolveNoFollow] will be returned instead.
|
// then a file equivalent to [Root.ResolveNoFollow] will be returned instead.
|
||||||
//
|
//
|
||||||
// This is effectively equivalent to [os.OpenFile], except that os.O_CREAT is
|
// This is effectively equivalent to [os.OpenFile], except that [unix.O_CREAT]
|
||||||
// not supported.
|
// is not supported.
|
||||||
func (r *Root) OpenFile(path string, flags int) (*os.File, error) {
|
func (r *Root) OpenFile(path string, flags uint64) (*os.File, error) {
|
||||||
return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*os.File, error) {
|
return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*os.File, error) {
|
||||||
fd, err := libpathrs.InRootOpen(rootFd, path, flags)
|
fd, err := libpathrs.InRootOpen(rootFd, path, flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -139,7 +141,7 @@ func (r *Root) OpenFile(path string, flags int) (*os.File, error) {
|
|||||||
//
|
//
|
||||||
// Unlike [os.Create], if the file already exists an error is created rather
|
// Unlike [os.Create], if the file already exists an error is created rather
|
||||||
// than the file being opened and truncated.
|
// than the file being opened and truncated.
|
||||||
func (r *Root) Create(path string, flags int, mode os.FileMode) (*os.File, error) {
|
func (r *Root) Create(path string, flags uint64, mode os.FileMode) (*os.File, error) {
|
||||||
unixMode, err := toUnixMode(mode, false)
|
unixMode, err := toUnixMode(mode, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -155,9 +157,9 @@ func (r *Root) Create(path string, flags int, mode os.FileMode) (*os.File, error
|
|||||||
|
|
||||||
// Rename two paths within a [Root]'s directory tree. The flags argument is
|
// Rename two paths within a [Root]'s directory tree. The flags argument is
|
||||||
// identical to the RENAME_* flags to the renameat2(2) system call.
|
// identical to the RENAME_* flags to the renameat2(2) system call.
|
||||||
func (r *Root) Rename(src, dst string, flags uint) error {
|
func (r *Root) Rename(src, dst string, flags uint64) error {
|
||||||
_, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
|
_, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
|
||||||
err := libpathrs.InRootRename(rootFd, src, dst, flags)
|
err := libpathrs.InRootRename(rootFd, src, rootFd, dst, flags)
|
||||||
return struct{}{}, err
|
return struct{}{}, err
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
@@ -277,26 +279,26 @@ func (r *Root) Mknod(path string, mode os.FileMode, dev uint64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Symlink creates a symlink within a [Root]'s directory tree. The symlink is
|
// Symlink creates a symlink within a [Root]'s directory tree. The symlink is
|
||||||
// created at path and is a link to target.
|
// created at newname and is a link to oldname.
|
||||||
//
|
//
|
||||||
// This is effectively equivalent to [os.Symlink].
|
// This is effectively equivalent to [os.Symlink].
|
||||||
func (r *Root) Symlink(path, target string) error {
|
func (r *Root) Symlink(oldname, newname string) error {
|
||||||
_, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
|
_, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
|
||||||
err := libpathrs.InRootSymlink(rootFd, path, target)
|
err := libpathrs.InRootSymlink(oldname, rootFd, newname)
|
||||||
return struct{}{}, err
|
return struct{}{}, err
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hardlink creates a hardlink within a [Root]'s directory tree. The hardlink
|
// Hardlink creates a hardlink within a [Root]'s directory tree. The hardlink
|
||||||
// is created at path and is a link to target. Both paths are within the
|
// is created at newname and is a link to oldname. Both paths are within the
|
||||||
// [Root]'s directory tree (you cannot hardlink to a different [Root] or the
|
// [Root]'s directory tree (you cannot hardlink to a different [Root] or the
|
||||||
// host).
|
// host).
|
||||||
//
|
//
|
||||||
// This is effectively equivalent to [os.Link].
|
// This is effectively equivalent to [os.Link].
|
||||||
func (r *Root) Hardlink(path, target string) error {
|
func (r *Root) Hardlink(oldname, newname string) error {
|
||||||
_, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
|
_, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
|
||||||
err := libpathrs.InRootHardlink(rootFd, path, target)
|
err := libpathrs.InRootHardlink(rootFd, oldname, rootFd, newname, 0)
|
||||||
return struct{}{}, err
|
return struct{}{}, err
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
|
|||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
//go:build linux
|
||||||
|
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
/*
|
||||||
|
* libpathrs: safe path resolution on Linux
|
||||||
|
* Copyright (C) 2026 Aleksa Sarai <cyphar@cyphar.com>
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pathrs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cyphar.com/go-pathrs/internal/libpathrs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LibraryVersionInfo contains information about the version and features
|
||||||
|
// supported by the underlying libpathrs.so library at runtime.
|
||||||
|
type LibraryVersionInfo = libpathrs.VersionInfo
|
||||||
|
|
||||||
|
// LibraryVersion returns information about the version and features supported
|
||||||
|
// by the underlying libpathrs.so library at runtime.
|
||||||
|
func LibraryVersion() (*LibraryVersionInfo, error) {
|
||||||
|
return libpathrs.Version()
|
||||||
|
}
|
||||||
+11
@@ -6,6 +6,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## [Unreleased] ##
|
## [Unreleased] ##
|
||||||
|
|
||||||
|
## [0.7.0] - 2025-06-17 ##
|
||||||
|
|
||||||
|
> You talk of times of peace for all, and then prepare for war.
|
||||||
|
|
||||||
|
### Changed ###
|
||||||
|
- Update to `cyphar.com/go-pathrs@0.2.5`, which included a build-time API
|
||||||
|
breakage that we needed to work around. The API of this library is unchanged
|
||||||
|
by this, but users should make sure to update to `v0.7.0` of
|
||||||
|
`filepath-securejoin` if they use the `libpathrs` built tag and have update
|
||||||
|
to `libpathrs` `v0.2.5`.
|
||||||
|
|
||||||
## [0.6.1] - 2025-11-19 ##
|
## [0.6.1] - 2025-11-19 ##
|
||||||
|
|
||||||
> At last up jumped the cunning spider, and fiercely held her fast.
|
> At last up jumped the cunning spider, and fiercely held her fast.
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
0.6.1
|
0.7.0
|
||||||
|
|||||||
+1
-1
@@ -53,5 +53,5 @@ func Reopen(file *os.File, flags int) (*os.File, error) {
|
|||||||
}
|
}
|
||||||
defer handle.Close() //nolint:errcheck // close failures aren't critical here
|
defer handle.Close() //nolint:errcheck // close failures aren't critical here
|
||||||
|
|
||||||
return handle.OpenFile(flags)
|
return handle.OpenFile(uint64(flags))
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
# cyphar.com/go-pathrs v0.2.4
|
# cyphar.com/go-pathrs v0.2.5
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
cyphar.com/go-pathrs
|
cyphar.com/go-pathrs
|
||||||
cyphar.com/go-pathrs/internal/fdutils
|
cyphar.com/go-pathrs/internal/fdutils
|
||||||
@@ -36,7 +36,7 @@ github.com/coreos/go-systemd/v22/dbus
|
|||||||
# github.com/cpuguy83/go-md2man/v2 v2.0.7
|
# github.com/cpuguy83/go-md2man/v2 v2.0.7
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/cpuguy83/go-md2man/v2/md2man
|
github.com/cpuguy83/go-md2man/v2/md2man
|
||||||
# github.com/cyphar/filepath-securejoin v0.6.1
|
# github.com/cyphar/filepath-securejoin v0.7.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
github.com/cyphar/filepath-securejoin
|
github.com/cyphar/filepath-securejoin
|
||||||
github.com/cyphar/filepath-securejoin/internal/consts
|
github.com/cyphar/filepath-securejoin/internal/consts
|
||||||
|
|||||||
Reference in New Issue
Block a user