mirror of
https://github.com/opencontainers/runc.git
synced 2026-11-06 05:17:05 +00:00
build(deps): bump github.com/moby/sys/user from 0.4.1 to 0.5.0
Bumps [github.com/moby/sys/user](https://github.com/moby/sys) from 0.4.1 to 0.5.0. - [Release notes](https://github.com/moby/sys/releases) - [Commits](https://github.com/moby/sys/compare/user/v0.4.1...user/v0.5.0) --- updated-dependencies: - dependency-name: github.com/moby/sys/user dependency-version: 0.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
1 parent
acc3f393b3
commit
9425301505
8 files changed
+155
-129
No files matched your search
@@ -12,7 +12,7 @@ require (
|
||||
github.com/godbus/dbus/v5 v5.2.4
|
||||
github.com/moby/sys/capability v0.5.0
|
||||
github.com/moby/sys/mountinfo v0.7.3
|
||||
github.com/moby/sys/user v0.4.1
|
||||
github.com/moby/sys/user v0.5.0
|
||||
github.com/moby/sys/userns v0.2.1
|
||||
github.com/mrunalp/fileutils v0.5.1
|
||||
github.com/opencontainers/cgroups v0.1.0
|
||||
|
||||
@@ -28,8 +28,8 @@ github.com/moby/sys/capability v0.5.0 h1:Bm4oD9xGCtZguPnaoQy1/jvKTSwZHMvM0FrnxNY
|
||||
github.com/moby/sys/capability v0.5.0/go.mod h1:i+0cXvNSriGrL3C6sxnmlmGL5HVU0OdxocizXdC8A+g=
|
||||
github.com/moby/sys/mountinfo v0.7.3 h1:e0lin8d05kLgtUES/4cS/F70KlbZX/G3aZjLsV7WAgA=
|
||||
github.com/moby/sys/mountinfo v0.7.3/go.mod h1:dEJRr+H+hx0lNG0BE+Smz95u/FDzjJv4/RjA2I456Iw=
|
||||
github.com/moby/sys/user v0.4.1 h1:RgjRlaDKi/Xmyrz4t8lyzXT6v2ooFeO/7xtchmhVWE0=
|
||||
github.com/moby/sys/user v0.4.1/go.mod h1:E9QsW5WRe1kUAf7kW8hXKwu1uhsZEAdPLYHYSDudF4Y=
|
||||
github.com/moby/sys/user v0.5.0 h1:5+S4lyoavGyX1DGs68NW8xpx48T9+a7ogSUc0KjZg8Y=
|
||||
github.com/moby/sys/user v0.5.0/go.mod h1:4mQzP5aTmaLjDLp/dc870oNkik6E9vjRtWYwI05gvow=
|
||||
github.com/moby/sys/userns v0.2.1 h1:4OvdM7BcPkASbuouHsbW3aeMJSFlYDldBRnXVZhaRk8=
|
||||
github.com/moby/sys/userns v0.2.1/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||
github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q=
|
||||
|
||||
+31
-37
@@ -12,37 +12,39 @@ type mkdirOptions struct {
|
||||
onlyNew bool
|
||||
}
|
||||
|
||||
// WithOnlyNew is an option for MkdirAllAndChown that will only change ownership and permissions
|
||||
// on newly created directories. If the directory already exists, it will not be modified
|
||||
// WithOnlyNew configures [MkdirAllAndChown] and [MkdirAndChown] to leave
|
||||
// the requested directory unchanged if it already exists. Newly created
|
||||
// directories are still assigned the requested ownership and permissions.
|
||||
func WithOnlyNew(o *mkdirOptions) {
|
||||
o.onlyNew = true
|
||||
}
|
||||
|
||||
// MkdirAllAndChown creates a directory (include any along the path) and then modifies
|
||||
// ownership to the requested uid/gid. By default, if the directory already exists, this
|
||||
// function will still change ownership and permissions. If WithOnlyNew is passed as an
|
||||
// option, then only the newly created directories will have ownership and permissions changed.
|
||||
// MkdirAllAndChown creates a directory named path, along with any necessary
|
||||
// parents, and applies the requested ownership and permission bits to all
|
||||
// directories it creates.
|
||||
//
|
||||
// If path already exists as a directory, its ownership and permission bits
|
||||
// are updated unless [WithOnlyNew] is specified. Existing parent directories
|
||||
// are not modified.
|
||||
//
|
||||
// MkdirAllAndChown is similar to [os.MkdirAll], but also applies ownership and
|
||||
// reapplies the requested permission bits after creation, so the resulting
|
||||
// permissions are not affected by the process umask.
|
||||
func MkdirAllAndChown(path string, mode os.FileMode, uid, gid int, opts ...MkdirOpt) error {
|
||||
var options mkdirOptions
|
||||
for _, opt := range opts {
|
||||
opt(&options)
|
||||
}
|
||||
|
||||
return mkdirAs(path, mode, uid, gid, true, options.onlyNew)
|
||||
return mkdirAs(path, mode, uid, gid, true, opts...)
|
||||
}
|
||||
|
||||
// MkdirAndChown creates a directory and then modifies ownership to the requested uid/gid.
|
||||
// By default, if the directory already exists, this function still changes ownership and permissions.
|
||||
// If WithOnlyNew is passed as an option, then only the newly created directory will have ownership
|
||||
// and permissions changed.
|
||||
// Note that unlike os.Mkdir(), this function does not return IsExist error
|
||||
// in case path already exists.
|
||||
// MkdirAndChown creates a directory named path and applies the requested
|
||||
// ownership and permission bits.
|
||||
//
|
||||
// If path already exists as a directory, its ownership and permission bits
|
||||
// are updated unless [WithOnlyNew] is specified.
|
||||
//
|
||||
// MkdirAndChown is similar to [os.Mkdir], but returns nil if path already
|
||||
// exists as a directory. The resulting permission bits are not affected by
|
||||
// the process umask.
|
||||
func MkdirAndChown(path string, mode os.FileMode, uid, gid int, opts ...MkdirOpt) error {
|
||||
var options mkdirOptions
|
||||
for _, opt := range opts {
|
||||
opt(&options)
|
||||
}
|
||||
return mkdirAs(path, mode, uid, gid, false, options.onlyNew)
|
||||
return mkdirAs(path, mode, uid, gid, false, opts...)
|
||||
}
|
||||
|
||||
// getRootUIDGID retrieves the remapped root uid/gid pair from the set of maps.
|
||||
@@ -106,22 +108,14 @@ func (i IdentityMapping) RootPair() (int, int) {
|
||||
return uid, gid
|
||||
}
|
||||
|
||||
// ToHost returns the host UID and GID for the container uid, gid.
|
||||
// Remapping is only performed if the ids aren't already the remapped root ids
|
||||
// ToHost returns the host UID and GID for the container uid and gid.
|
||||
// An empty mapping is treated as identity.
|
||||
func (i IdentityMapping) ToHost(uid, gid int) (int, int, error) {
|
||||
var err error
|
||||
ruid, rgid := i.RootPair()
|
||||
|
||||
if uid != ruid {
|
||||
ruid, err = toHost(uid, i.UIDMaps)
|
||||
if err != nil {
|
||||
return ruid, rgid, err
|
||||
}
|
||||
}
|
||||
|
||||
if gid != rgid {
|
||||
rgid, err = toHost(gid, i.GIDMaps)
|
||||
ruid, err := toHost(uid, i.UIDMaps)
|
||||
if err != nil {
|
||||
return -1, -1, err
|
||||
}
|
||||
rgid, err := toHost(gid, i.GIDMaps)
|
||||
return ruid, rgid, err
|
||||
}
|
||||
|
||||
|
||||
+7
-2
@@ -10,7 +10,12 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func mkdirAs(path string, mode os.FileMode, uid, gid int, mkAll, onlyNew bool) error {
|
||||
func mkdirAs(path string, mode os.FileMode, uid, gid int, mkAll bool, opts ...MkdirOpt) error {
|
||||
var options mkdirOptions
|
||||
for _, opt := range opts {
|
||||
opt(&options)
|
||||
}
|
||||
|
||||
path, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -21,7 +26,7 @@ func mkdirAs(path string, mode os.FileMode, uid, gid int, mkAll, onlyNew bool) e
|
||||
if !stat.IsDir() {
|
||||
return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR}
|
||||
}
|
||||
if onlyNew {
|
||||
if options.onlyNew {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+19
-6
@@ -2,12 +2,25 @@ package user
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// This is currently a wrapper around [os.MkdirAll] since currently
|
||||
// permissions aren't set through this path, the identity isn't utilized.
|
||||
// Ownership is handled elsewhere, but in the future could be support here
|
||||
// too.
|
||||
func mkdirAs(path string, _ os.FileMode, _, _ int, _, _ bool) error {
|
||||
return os.MkdirAll(path, 0)
|
||||
// mkdirAs creates path, optionally creating any missing parent directories.
|
||||
//
|
||||
// On Windows this is currently a thin wrapper around os.Mkdir and
|
||||
// os.MkdirAll. Unlike the Unix implementation, ownership and permission
|
||||
// bits are not applied.
|
||||
func mkdirAs(path string, _ os.FileMode, _, _ int, mkAll bool, _ ...MkdirOpt) error {
|
||||
if mkAll {
|
||||
return os.MkdirAll(path, 0)
|
||||
}
|
||||
stat, err := os.Stat(path)
|
||||
if err == nil {
|
||||
if !stat.IsDir() {
|
||||
return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return os.Mkdir(path, 0)
|
||||
}
|
||||
+31
-79
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@@ -17,9 +18,9 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNoPasswdEntries is returned if no matching entries were found in /etc/group.
|
||||
// ErrNoPasswdEntries is returned if no matching entries were found in /etc/passwd.
|
||||
ErrNoPasswdEntries = errors.New("no matching entries in passwd file")
|
||||
// ErrNoGroupEntries is returned if no matching entries were found in /etc/passwd.
|
||||
// ErrNoGroupEntries is returned if no matching entries were found in /etc/group.
|
||||
ErrNoGroupEntries = errors.New("no matching entries in group file")
|
||||
// ErrRange is returned if a UID or GID is outside of the valid range.
|
||||
ErrRange = fmt.Errorf("uids and gids must be in range %d-%d", minID, maxID)
|
||||
@@ -243,9 +244,6 @@ func GetExecUserPath(userSpec string, defaults *ExecUser, passwdPath, groupPath
|
||||
//
|
||||
// See https://github.com/containerd/containerd/commit/de1341c201ffb0effebbf51d00376181968c8779
|
||||
func parseNumeric(val string) (int, bool, error) {
|
||||
if val == "" {
|
||||
return 0, false, nil
|
||||
}
|
||||
id, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
if errors.Is(err, strconv.ErrSyntax) {
|
||||
@@ -296,51 +294,40 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
|
||||
user := &ExecUser{
|
||||
Uid: defaults.Uid,
|
||||
Gid: defaults.Gid,
|
||||
Sgids: defaults.Sgids,
|
||||
Sgids: append([]int{}, defaults.Sgids...), // Sgids slice *cannot* be nil.
|
||||
Home: defaults.Home,
|
||||
}
|
||||
|
||||
// Sgids slice *cannot* be nil.
|
||||
if user.Sgids == nil {
|
||||
user.Sgids = []int{}
|
||||
}
|
||||
// Allow for userSpec to have either "user", or optionally "user:group" syntax.
|
||||
usr, grp, _ := strings.Cut(userSpec, ":")
|
||||
|
||||
// Allow for userArg to have either "user" syntax, or optionally "user:group" syntax
|
||||
var userArg, groupArg string
|
||||
parseLine([]byte(userSpec), &userArg, &groupArg)
|
||||
|
||||
// Convert userArg and groupArg to be numeric, so we don't have to execute
|
||||
// Convert usr and grp to be numeric, so we don't have to execute
|
||||
// Atoi *twice* for each iteration over lines.
|
||||
uidArg, isUID, err := parseNumeric(userArg)
|
||||
userArg, err := parseUserArg(usr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gidArg, isGID, err := parseNumeric(groupArg)
|
||||
groupArg, err := parseGroupArg(grp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Find the matching user.
|
||||
users, err := ParsePasswdFilter(passwd, func(u User) bool {
|
||||
if userArg == "" {
|
||||
if userArg == nil {
|
||||
// Default to current state of the user.
|
||||
return u.Uid == user.Uid
|
||||
}
|
||||
|
||||
if isUID {
|
||||
// If the userArg is a valid numeric value, always treat it as a UID.
|
||||
return uidArg == u.Uid
|
||||
}
|
||||
|
||||
return u.Name == userArg
|
||||
return userArg.matches(u)
|
||||
})
|
||||
|
||||
// If we can't find the user, we have to bail.
|
||||
if err != nil && passwd != nil {
|
||||
if userArg == "" {
|
||||
userArg = strconv.Itoa(user.Uid)
|
||||
name := usr
|
||||
if userArg == nil {
|
||||
name = strconv.Itoa(user.Uid)
|
||||
}
|
||||
return nil, fmt.Errorf("unable to find user %s: %w", userArg, err)
|
||||
return nil, fmt.Errorf("unable to find user %s: %w", name, err)
|
||||
}
|
||||
|
||||
var matchedUserName string
|
||||
@@ -350,57 +337,42 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
|
||||
user.Uid = users[0].Uid
|
||||
user.Gid = users[0].Gid
|
||||
user.Home = users[0].Home
|
||||
} else if userArg != "" {
|
||||
} else if userArg != nil {
|
||||
// If we can't find a user with the given username, the only other valid
|
||||
// option is if it's a numeric username with no associated entry in passwd.
|
||||
|
||||
if !isUID {
|
||||
// Not numeric.
|
||||
return nil, fmt.Errorf("unable to find user %s: %w", userArg, ErrNoPasswdEntries)
|
||||
if !userArg.isNumeric {
|
||||
return nil, fmt.Errorf("unable to find user %s: %w", userArg.name, ErrNoPasswdEntries)
|
||||
}
|
||||
user.Uid = uidArg
|
||||
user.Uid = userArg.uid
|
||||
}
|
||||
|
||||
// On to the groups. If we matched a username, we need to do this because of
|
||||
// the supplementary group IDs.
|
||||
if groupArg != "" || matchedUserName != "" {
|
||||
if groupArg != nil || matchedUserName != "" {
|
||||
groups, err := ParseGroupFilter(group, func(g Group) bool {
|
||||
// If the group argument isn't explicit, we'll just search for it.
|
||||
if groupArg == "" {
|
||||
if groupArg == nil {
|
||||
// Check if user is a member of this group.
|
||||
for _, u := range g.List {
|
||||
if u == matchedUserName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(g.List, matchedUserName)
|
||||
}
|
||||
|
||||
if isGID {
|
||||
// If the groupArg is numeric, always treat it as a GID.
|
||||
return gidArg == g.Gid
|
||||
}
|
||||
|
||||
return g.Name == groupArg
|
||||
return groupArg.matches(g)
|
||||
})
|
||||
if err != nil && group != nil {
|
||||
return nil, fmt.Errorf("unable to find groups for spec %v: %w", matchedUserName, err)
|
||||
}
|
||||
|
||||
// Only start modifying user.Gid if it is in explicit form.
|
||||
if groupArg != "" {
|
||||
if groupArg != nil {
|
||||
if len(groups) > 0 {
|
||||
// First match wins, even if there's more than one matching entry.
|
||||
user.Gid = groups[0].Gid
|
||||
} else {
|
||||
// If we can't find a group with the given name, the only other valid
|
||||
// option is if it's a numeric group name with no associated entry in group.
|
||||
|
||||
if !isGID {
|
||||
// Not numeric.
|
||||
return nil, fmt.Errorf("unable to find group %s: %w", groupArg, ErrNoGroupEntries)
|
||||
if !groupArg.isNumeric {
|
||||
return nil, fmt.Errorf("unable to find group %s: %w", groupArg.name, ErrNoGroupEntries)
|
||||
}
|
||||
user.Gid = gidArg
|
||||
user.Gid = groupArg.gid
|
||||
}
|
||||
} else if len(groups) > 0 {
|
||||
// Supplementary group ids only make sense if in the implicit form.
|
||||
@@ -414,39 +386,19 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// groupArg is a parsed group argument for [GetAdditionalGroups].
|
||||
type groupArg struct {
|
||||
name string
|
||||
gid int
|
||||
isNumeric bool
|
||||
}
|
||||
|
||||
// matches reports whether group g satisfies the argument. Numeric arguments
|
||||
// are matched by GID only, others by name.
|
||||
func (ag groupArg) matches(g Group) bool {
|
||||
if ag.isNumeric {
|
||||
return g.Gid == ag.gid
|
||||
}
|
||||
return g.Name == ag.name
|
||||
}
|
||||
|
||||
// GetAdditionalGroups looks up a list of groups by name or group id
|
||||
// against the given /etc/group formatted data. If a group name cannot
|
||||
// be found, an error will be returned. If a group id cannot be found,
|
||||
// or the given group data is nil, the id will be returned as-is
|
||||
// provided it is in the legal range.
|
||||
func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, error) {
|
||||
addtlGroups := make([]groupArg, len(additionalGroups))
|
||||
for i, ag := range additionalGroups {
|
||||
gid, ok, err := parseNumeric(ag)
|
||||
addtlGroups := make([]groupArg, 0, len(additionalGroups))
|
||||
for _, ag := range additionalGroups {
|
||||
groupArg, err := parseGroupArg(ag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addtlGroups[i] = groupArg{
|
||||
name: ag,
|
||||
gid: gid,
|
||||
isNumeric: ok,
|
||||
}
|
||||
addtlGroups = append(addtlGroups, *groupArg)
|
||||
}
|
||||
|
||||
groups := []Group{}
|
||||
|
||||
+62
@@ -62,3 +62,65 @@ func (l *limitedFile) Read(p []byte) (int, error) {
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// userArg is a parsed user argument for [GetExecUser].
|
||||
type userArg struct {
|
||||
name string
|
||||
uid int
|
||||
isNumeric bool
|
||||
}
|
||||
|
||||
// parseUserArg parses a user argument as either a user name or UID.
|
||||
//
|
||||
// If name is empty, parseUserArg returns "nil, nil" to indicate that no user
|
||||
// argument was specified.
|
||||
func parseUserArg(name string) (*userArg, error) {
|
||||
if name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
uid, isNumeric, err := parseNumeric(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &userArg{name: name, uid: uid, isNumeric: isNumeric}, nil
|
||||
}
|
||||
|
||||
// matches reports whether user u satisfies the argument. Numeric arguments
|
||||
// are matched by UID only, others by name.
|
||||
func (ua *userArg) matches(u User) bool {
|
||||
if ua.isNumeric {
|
||||
return u.Uid == ua.uid
|
||||
}
|
||||
return u.Name == ua.name
|
||||
}
|
||||
|
||||
// groupArg is a parsed group argument for [GetAdditionalGroups] or [GetExecUser].
|
||||
type groupArg struct {
|
||||
name string
|
||||
gid int
|
||||
isNumeric bool
|
||||
}
|
||||
|
||||
// parseGroupArg parses a group argument as either a group name or GID.
|
||||
//
|
||||
// If name is empty, parseGroupArg returns "nil, nil" to indicate that no group
|
||||
// argument was specified.
|
||||
func parseGroupArg(name string) (*groupArg, error) {
|
||||
if name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
gid, isNumeric, err := parseNumeric(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &groupArg{name: name, gid: gid, isNumeric: isNumeric}, nil
|
||||
}
|
||||
|
||||
// matches reports whether group g satisfies the argument. Numeric arguments
|
||||
// are matched by GID only, others by name.
|
||||
func (ag groupArg) matches(g Group) bool {
|
||||
if ag.isNumeric {
|
||||
return g.Gid == ag.gid
|
||||
}
|
||||
return g.Name == ag.name
|
||||
}
|
||||
Vendored
+2
-2
@@ -52,8 +52,8 @@ github.com/moby/sys/capability
|
||||
# github.com/moby/sys/mountinfo v0.7.3
|
||||
## explicit; go 1.18
|
||||
github.com/moby/sys/mountinfo
|
||||
# github.com/moby/sys/user v0.4.1
|
||||
## explicit; go 1.18
|
||||
# github.com/moby/sys/user v0.5.0
|
||||
## explicit; go 1.24
|
||||
github.com/moby/sys/user
|
||||
# github.com/moby/sys/userns v0.2.1
|
||||
## explicit; go 1.21
|
||||
|
||||
Reference in new issue
Block a user