Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
8c9ed8e1
Commit
8c9ed8e1
authored
Jan 22, 2020
by
Darren Shepherd
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bump rootlesskit
parent
782004be
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
939 additions
and
557 deletions
+939
-557
go.mod
go.mod
+1
-3
go.sum
go.sum
+8
-10
idtools_unix.go
vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go
+0
-231
idtools_windows.go
...r/github.com/docker/docker/pkg/idtools/idtools_windows.go
+0
-25
usergroupadd_linux.go
...ithub.com/docker/docker/pkg/idtools/usergroupadd_linux.go
+0
-164
usergroupadd_unsupported.go
...com/docker/docker/pkg/idtools/usergroupadd_unsupported.go
+0
-12
utils_unix.go
vendor/github.com/docker/docker/pkg/idtools/utils_unix.go
+0
-32
child.go
...ub.com/rootless-containers/rootlesskit/pkg/child/child.go
+48
-22
hosts.go
...ub.com/rootless-containers/rootlesskit/pkg/child/hosts.go
+5
-7
resolvconf.go
...m/rootless-containers/rootlesskit/pkg/child/resolvconf.go
+4
-7
tmpfssymlink.go
...iners/rootlesskit/pkg/copyup/tmpfssymlink/tmpfssymlink.go
+12
-12
slirp4netns.go
...ainers/rootlesskit/pkg/network/slirp4netns/slirp4netns.go
+112
-2
idtools.go
...less-containers/rootlesskit/pkg/parent/idtools/idtools.go
+5
-23
parent.go
....com/rootless-containers/rootlesskit/pkg/parent/parent.go
+7
-5
builtin.go
...otless-containers/rootlesskit/pkg/port/builtin/builtin.go
+0
-0
child.go
...ss-containers/rootlesskit/pkg/port/builtin/child/child.go
+134
-0
msg.go
...otless-containers/rootlesskit/pkg/port/builtin/msg/msg.go
+129
-0
opaque.go
...-containers/rootlesskit/pkg/port/builtin/opaque/opaque.go
+6
-0
parent.go
...-containers/rootlesskit/pkg/port/builtin/parent/parent.go
+145
-0
tcp.go
...containers/rootlesskit/pkg/port/builtin/parent/tcp/tcp.go
+104
-0
udp.go
...containers/rootlesskit/pkg/port/builtin/parent/udp/udp.go
+60
-0
udp_proxy.go
...lesskit/pkg/port/builtin/parent/udp/udpproxy/udp_proxy.go
+150
-0
modules.txt
vendor/modules.txt
+9
-2
No files found.
go.mod
View file @
8c9ed8e1
...
@@ -82,7 +82,6 @@ require (
...
@@ -82,7 +82,6 @@ require (
github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4 // indirect
github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4 // indirect
github.com/go-bindata/go-bindata v3.1.2+incompatible
github.com/go-bindata/go-bindata v3.1.2+incompatible
github.com/go-sql-driver/mysql v1.4.1
github.com/go-sql-driver/mysql v1.4.1
github.com/gofrs/flock v0.7.1 // indirect
github.com/gogo/googleapis v1.3.0 // indirect
github.com/gogo/googleapis v1.3.0 // indirect
github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2
github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2
github.com/gorilla/mux v1.7.3
github.com/gorilla/mux v1.7.3
...
@@ -103,11 +102,10 @@ require (
...
@@ -103,11 +102,10 @@ require (
github.com/rancher/remotedialer v0.2.0
github.com/rancher/remotedialer v0.2.0
github.com/rancher/wrangler v0.4.0
github.com/rancher/wrangler v0.4.0
github.com/rancher/wrangler-api v0.4.0
github.com/rancher/wrangler-api v0.4.0
github.com/rootless-containers/rootlesskit v0.
6.0
github.com/rootless-containers/rootlesskit v0.
7.2
github.com/sirupsen/logrus v1.4.2
github.com/sirupsen/logrus v1.4.2
github.com/spf13/pflag v1.0.5
github.com/spf13/pflag v1.0.5
github.com/tchap/go-patricia v2.3.0+incompatible // indirect
github.com/tchap/go-patricia v2.3.0+incompatible // indirect
github.com/theckman/go-flock v0.7.1 // indirect
github.com/urfave/cli v1.22.2
github.com/urfave/cli v1.22.2
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586
golang.org/x/net v0.0.0-20191204025024-5ee1b9f4859a
golang.org/x/net v0.0.0-20191204025024-5ee1b9f4859a
...
...
go.sum
View file @
8c9ed8e1
This diff is collapsed.
Click to expand it.
vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go
deleted
100644 → 0
View file @
782004be
// +build !windows
package
idtools
// import "github.com/docker/docker/pkg/idtools"
import
(
"bytes"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"sync"
"syscall"
"github.com/docker/docker/pkg/system"
"github.com/opencontainers/runc/libcontainer/user"
)
var
(
entOnce
sync
.
Once
getentCmd
string
)
func
mkdirAs
(
path
string
,
mode
os
.
FileMode
,
owner
Identity
,
mkAll
,
chownExisting
bool
)
error
{
// make an array containing the original path asked for, plus (for mkAll == true)
// all path components leading up to the complete path that don't exist before we MkdirAll
// so that we can chown all of them properly at the end. If chownExisting is false, we won't
// chown the full directory path if it exists
var
paths
[]
string
stat
,
err
:=
system
.
Stat
(
path
)
if
err
==
nil
{
if
!
stat
.
IsDir
()
{
return
&
os
.
PathError
{
Op
:
"mkdir"
,
Path
:
path
,
Err
:
syscall
.
ENOTDIR
}
}
if
!
chownExisting
{
return
nil
}
// short-circuit--we were called with an existing directory and chown was requested
return
lazyChown
(
path
,
owner
.
UID
,
owner
.
GID
,
stat
)
}
if
os
.
IsNotExist
(
err
)
{
paths
=
[]
string
{
path
}
}
if
mkAll
{
// walk back to "/" looking for directories which do not exist
// and add them to the paths array for chown after creation
dirPath
:=
path
for
{
dirPath
=
filepath
.
Dir
(
dirPath
)
if
dirPath
==
"/"
{
break
}
if
_
,
err
:=
os
.
Stat
(
dirPath
);
err
!=
nil
&&
os
.
IsNotExist
(
err
)
{
paths
=
append
(
paths
,
dirPath
)
}
}
if
err
:=
system
.
MkdirAll
(
path
,
mode
);
err
!=
nil
{
return
err
}
}
else
{
if
err
:=
os
.
Mkdir
(
path
,
mode
);
err
!=
nil
&&
!
os
.
IsExist
(
err
)
{
return
err
}
}
// even if it existed, we will chown the requested path + any subpaths that
// didn't exist when we called MkdirAll
for
_
,
pathComponent
:=
range
paths
{
if
err
:=
lazyChown
(
pathComponent
,
owner
.
UID
,
owner
.
GID
,
nil
);
err
!=
nil
{
return
err
}
}
return
nil
}
// CanAccess takes a valid (existing) directory and a uid, gid pair and determines
// if that uid, gid pair has access (execute bit) to the directory
func
CanAccess
(
path
string
,
pair
Identity
)
bool
{
statInfo
,
err
:=
system
.
Stat
(
path
)
if
err
!=
nil
{
return
false
}
fileMode
:=
os
.
FileMode
(
statInfo
.
Mode
())
permBits
:=
fileMode
.
Perm
()
return
accessible
(
statInfo
.
UID
()
==
uint32
(
pair
.
UID
),
statInfo
.
GID
()
==
uint32
(
pair
.
GID
),
permBits
)
}
func
accessible
(
isOwner
,
isGroup
bool
,
perms
os
.
FileMode
)
bool
{
if
isOwner
&&
(
perms
&
0100
==
0100
)
{
return
true
}
if
isGroup
&&
(
perms
&
0010
==
0010
)
{
return
true
}
if
perms
&
0001
==
0001
{
return
true
}
return
false
}
// LookupUser uses traditional local system files lookup (from libcontainer/user) on a username,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func
LookupUser
(
username
string
)
(
user
.
User
,
error
)
{
// first try a local system files lookup using existing capabilities
usr
,
err
:=
user
.
LookupUser
(
username
)
if
err
==
nil
{
return
usr
,
nil
}
// local files lookup failed; attempt to call `getent` to query configured passwd dbs
usr
,
err
=
getentUser
(
fmt
.
Sprintf
(
"%s %s"
,
"passwd"
,
username
))
if
err
!=
nil
{
return
user
.
User
{},
err
}
return
usr
,
nil
}
// LookupUID uses traditional local system files lookup (from libcontainer/user) on a uid,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func
LookupUID
(
uid
int
)
(
user
.
User
,
error
)
{
// first try a local system files lookup using existing capabilities
usr
,
err
:=
user
.
LookupUid
(
uid
)
if
err
==
nil
{
return
usr
,
nil
}
// local files lookup failed; attempt to call `getent` to query configured passwd dbs
return
getentUser
(
fmt
.
Sprintf
(
"%s %d"
,
"passwd"
,
uid
))
}
func
getentUser
(
args
string
)
(
user
.
User
,
error
)
{
reader
,
err
:=
callGetent
(
args
)
if
err
!=
nil
{
return
user
.
User
{},
err
}
users
,
err
:=
user
.
ParsePasswd
(
reader
)
if
err
!=
nil
{
return
user
.
User
{},
err
}
if
len
(
users
)
==
0
{
return
user
.
User
{},
fmt
.
Errorf
(
"getent failed to find passwd entry for %q"
,
strings
.
Split
(
args
,
" "
)[
1
])
}
return
users
[
0
],
nil
}
// LookupGroup uses traditional local system files lookup (from libcontainer/user) on a group name,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func
LookupGroup
(
groupname
string
)
(
user
.
Group
,
error
)
{
// first try a local system files lookup using existing capabilities
group
,
err
:=
user
.
LookupGroup
(
groupname
)
if
err
==
nil
{
return
group
,
nil
}
// local files lookup failed; attempt to call `getent` to query configured group dbs
return
getentGroup
(
fmt
.
Sprintf
(
"%s %s"
,
"group"
,
groupname
))
}
// LookupGID uses traditional local system files lookup (from libcontainer/user) on a group ID,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func
LookupGID
(
gid
int
)
(
user
.
Group
,
error
)
{
// first try a local system files lookup using existing capabilities
group
,
err
:=
user
.
LookupGid
(
gid
)
if
err
==
nil
{
return
group
,
nil
}
// local files lookup failed; attempt to call `getent` to query configured group dbs
return
getentGroup
(
fmt
.
Sprintf
(
"%s %d"
,
"group"
,
gid
))
}
func
getentGroup
(
args
string
)
(
user
.
Group
,
error
)
{
reader
,
err
:=
callGetent
(
args
)
if
err
!=
nil
{
return
user
.
Group
{},
err
}
groups
,
err
:=
user
.
ParseGroup
(
reader
)
if
err
!=
nil
{
return
user
.
Group
{},
err
}
if
len
(
groups
)
==
0
{
return
user
.
Group
{},
fmt
.
Errorf
(
"getent failed to find groups entry for %q"
,
strings
.
Split
(
args
,
" "
)[
1
])
}
return
groups
[
0
],
nil
}
func
callGetent
(
args
string
)
(
io
.
Reader
,
error
)
{
entOnce
.
Do
(
func
()
{
getentCmd
,
_
=
resolveBinary
(
"getent"
)
})
// if no `getent` command on host, can't do anything else
if
getentCmd
==
""
{
return
nil
,
fmt
.
Errorf
(
""
)
}
out
,
err
:=
execCmd
(
getentCmd
,
args
)
if
err
!=
nil
{
exitCode
,
errC
:=
system
.
GetExitCode
(
err
)
if
errC
!=
nil
{
return
nil
,
err
}
switch
exitCode
{
case
1
:
return
nil
,
fmt
.
Errorf
(
"getent reported invalid parameters/database unknown"
)
case
2
:
terms
:=
strings
.
Split
(
args
,
" "
)
return
nil
,
fmt
.
Errorf
(
"getent unable to find entry %q in %s database"
,
terms
[
1
],
terms
[
0
])
case
3
:
return
nil
,
fmt
.
Errorf
(
"getent database doesn't support enumeration"
)
default
:
return
nil
,
err
}
}
return
bytes
.
NewReader
(
out
),
nil
}
// lazyChown performs a chown only if the uid/gid don't match what's requested
// Normally a Chown is a no-op if uid/gid match, but in some cases this can still cause an error, e.g. if the
// dir is on an NFS share, so don't call chown unless we absolutely must.
func
lazyChown
(
p
string
,
uid
,
gid
int
,
stat
*
system
.
StatT
)
error
{
if
stat
==
nil
{
var
err
error
stat
,
err
=
system
.
Stat
(
p
)
if
err
!=
nil
{
return
err
}
}
if
stat
.
UID
()
==
uint32
(
uid
)
&&
stat
.
GID
()
==
uint32
(
gid
)
{
return
nil
}
return
os
.
Chown
(
p
,
uid
,
gid
)
}
vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go
deleted
100644 → 0
View file @
782004be
package
idtools
// import "github.com/docker/docker/pkg/idtools"
import
(
"os"
"github.com/docker/docker/pkg/system"
)
// This is currently a wrapper around MkdirAll, however, 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
,
mode
os
.
FileMode
,
owner
Identity
,
mkAll
,
chownExisting
bool
)
error
{
if
err
:=
system
.
MkdirAll
(
path
,
mode
);
err
!=
nil
{
return
err
}
return
nil
}
// CanAccess takes a valid (existing) directory and a uid, gid pair and determines
// if that uid, gid pair has access (execute bit) to the directory
// Windows does not require/support this function, so always return true
func
CanAccess
(
path
string
,
identity
Identity
)
bool
{
return
true
}
vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go
deleted
100644 → 0
View file @
782004be
package
idtools
// import "github.com/docker/docker/pkg/idtools"
import
(
"fmt"
"regexp"
"sort"
"strconv"
"strings"
"sync"
)
// add a user and/or group to Linux /etc/passwd, /etc/group using standard
// Linux distribution commands:
// adduser --system --shell /bin/false --disabled-login --disabled-password --no-create-home --group <username>
// useradd -r -s /bin/false <username>
var
(
once
sync
.
Once
userCommand
string
cmdTemplates
=
map
[
string
]
string
{
"adduser"
:
"--system --shell /bin/false --no-create-home --disabled-login --disabled-password --group %s"
,
"useradd"
:
"-r -s /bin/false %s"
,
"usermod"
:
"-%s %d-%d %s"
,
}
idOutRegexp
=
regexp
.
MustCompile
(
`uid=([0-9]+).*gid=([0-9]+)`
)
// default length for a UID/GID subordinate range
defaultRangeLen
=
65536
defaultRangeStart
=
100000
userMod
=
"usermod"
)
// AddNamespaceRangesUser takes a username and uses the standard system
// utility to create a system user/group pair used to hold the
// /etc/sub{uid,gid} ranges which will be used for user namespace
// mapping ranges in containers.
func
AddNamespaceRangesUser
(
name
string
)
(
int
,
int
,
error
)
{
if
err
:=
addUser
(
name
);
err
!=
nil
{
return
-
1
,
-
1
,
fmt
.
Errorf
(
"Error adding user %q: %v"
,
name
,
err
)
}
// Query the system for the created uid and gid pair
out
,
err
:=
execCmd
(
"id"
,
name
)
if
err
!=
nil
{
return
-
1
,
-
1
,
fmt
.
Errorf
(
"Error trying to find uid/gid for new user %q: %v"
,
name
,
err
)
}
matches
:=
idOutRegexp
.
FindStringSubmatch
(
strings
.
TrimSpace
(
string
(
out
)))
if
len
(
matches
)
!=
3
{
return
-
1
,
-
1
,
fmt
.
Errorf
(
"Can't find uid, gid from `id` output: %q"
,
string
(
out
))
}
uid
,
err
:=
strconv
.
Atoi
(
matches
[
1
])
if
err
!=
nil
{
return
-
1
,
-
1
,
fmt
.
Errorf
(
"Can't convert found uid (%s) to int: %v"
,
matches
[
1
],
err
)
}
gid
,
err
:=
strconv
.
Atoi
(
matches
[
2
])
if
err
!=
nil
{
return
-
1
,
-
1
,
fmt
.
Errorf
(
"Can't convert found gid (%s) to int: %v"
,
matches
[
2
],
err
)
}
// Now we need to create the subuid/subgid ranges for our new user/group (system users
// do not get auto-created ranges in subuid/subgid)
if
err
:=
createSubordinateRanges
(
name
);
err
!=
nil
{
return
-
1
,
-
1
,
fmt
.
Errorf
(
"Couldn't create subordinate ID ranges: %v"
,
err
)
}
return
uid
,
gid
,
nil
}
func
addUser
(
userName
string
)
error
{
once
.
Do
(
func
()
{
// set up which commands are used for adding users/groups dependent on distro
if
_
,
err
:=
resolveBinary
(
"adduser"
);
err
==
nil
{
userCommand
=
"adduser"
}
else
if
_
,
err
:=
resolveBinary
(
"useradd"
);
err
==
nil
{
userCommand
=
"useradd"
}
})
if
userCommand
==
""
{
return
fmt
.
Errorf
(
"Cannot add user; no useradd/adduser binary found"
)
}
args
:=
fmt
.
Sprintf
(
cmdTemplates
[
userCommand
],
userName
)
out
,
err
:=
execCmd
(
userCommand
,
args
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Failed to add user with error: %v; output: %q"
,
err
,
string
(
out
))
}
return
nil
}
func
createSubordinateRanges
(
name
string
)
error
{
// first, we should verify that ranges weren't automatically created
// by the distro tooling
ranges
,
err
:=
parseSubuid
(
name
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Error while looking for subuid ranges for user %q: %v"
,
name
,
err
)
}
if
len
(
ranges
)
==
0
{
// no UID ranges; let's create one
startID
,
err
:=
findNextUIDRange
()
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Can't find available subuid range: %v"
,
err
)
}
out
,
err
:=
execCmd
(
userMod
,
fmt
.
Sprintf
(
cmdTemplates
[
userMod
],
"v"
,
startID
,
startID
+
defaultRangeLen
-
1
,
name
))
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Unable to add subuid range to user: %q; output: %s, err: %v"
,
name
,
out
,
err
)
}
}
ranges
,
err
=
parseSubgid
(
name
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Error while looking for subgid ranges for user %q: %v"
,
name
,
err
)
}
if
len
(
ranges
)
==
0
{
// no GID ranges; let's create one
startID
,
err
:=
findNextGIDRange
()
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Can't find available subgid range: %v"
,
err
)
}
out
,
err
:=
execCmd
(
userMod
,
fmt
.
Sprintf
(
cmdTemplates
[
userMod
],
"w"
,
startID
,
startID
+
defaultRangeLen
-
1
,
name
))
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Unable to add subgid range to user: %q; output: %s, err: %v"
,
name
,
out
,
err
)
}
}
return
nil
}
func
findNextUIDRange
()
(
int
,
error
)
{
ranges
,
err
:=
parseSubuid
(
"ALL"
)
if
err
!=
nil
{
return
-
1
,
fmt
.
Errorf
(
"Couldn't parse all ranges in /etc/subuid file: %v"
,
err
)
}
sort
.
Sort
(
ranges
)
return
findNextRangeStart
(
ranges
)
}
func
findNextGIDRange
()
(
int
,
error
)
{
ranges
,
err
:=
parseSubgid
(
"ALL"
)
if
err
!=
nil
{
return
-
1
,
fmt
.
Errorf
(
"Couldn't parse all ranges in /etc/subgid file: %v"
,
err
)
}
sort
.
Sort
(
ranges
)
return
findNextRangeStart
(
ranges
)
}
func
findNextRangeStart
(
rangeList
ranges
)
(
int
,
error
)
{
startID
:=
defaultRangeStart
for
_
,
arange
:=
range
rangeList
{
if
wouldOverlap
(
arange
,
startID
)
{
startID
=
arange
.
Start
+
arange
.
Length
}
}
return
startID
,
nil
}
func
wouldOverlap
(
arange
subIDRange
,
ID
int
)
bool
{
low
:=
ID
high
:=
ID
+
defaultRangeLen
if
(
low
>=
arange
.
Start
&&
low
<=
arange
.
Start
+
arange
.
Length
)
||
(
high
<=
arange
.
Start
+
arange
.
Length
&&
high
>=
arange
.
Start
)
{
return
true
}
return
false
}
vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go
deleted
100644 → 0
View file @
782004be
// +build !linux
package
idtools
// import "github.com/docker/docker/pkg/idtools"
import
"fmt"
// AddNamespaceRangesUser takes a name and finds an unused uid, gid pair
// and calls the appropriate helper function to add the group and then
// the user to the group in /etc/group and /etc/passwd respectively.
func
AddNamespaceRangesUser
(
name
string
)
(
int
,
int
,
error
)
{
return
-
1
,
-
1
,
fmt
.
Errorf
(
"No support for adding users or groups on this OS"
)
}
vendor/github.com/docker/docker/pkg/idtools/utils_unix.go
deleted
100644 → 0
View file @
782004be
// +build !windows
package
idtools
// import "github.com/docker/docker/pkg/idtools"
import
(
"fmt"
"os/exec"
"path/filepath"
"strings"
)
func
resolveBinary
(
binname
string
)
(
string
,
error
)
{
binaryPath
,
err
:=
exec
.
LookPath
(
binname
)
if
err
!=
nil
{
return
""
,
err
}
resolvedPath
,
err
:=
filepath
.
EvalSymlinks
(
binaryPath
)
if
err
!=
nil
{
return
""
,
err
}
//only return no error if the final resolved binary basename
//matches what was searched for
if
filepath
.
Base
(
resolvedPath
)
==
binname
{
return
resolvedPath
,
nil
}
return
""
,
fmt
.
Errorf
(
"Binary %q does not resolve to a binary of that name in $PATH (%q)"
,
binname
,
resolvedPath
)
}
func
execCmd
(
cmd
,
args
string
)
([]
byte
,
error
)
{
execCmd
:=
exec
.
Command
(
cmd
,
strings
.
Split
(
args
,
" "
)
...
)
return
execCmd
.
CombinedOutput
()
}
vendor/github.com/rootless-containers/rootlesskit/pkg/child/child.go
View file @
8c9ed8e1
...
@@ -4,6 +4,7 @@ import (
...
@@ -4,6 +4,7 @@ import (
"io/ioutil"
"io/ioutil"
"os"
"os"
"os/exec"
"os/exec"
"os/signal"
"runtime"
"runtime"
"strconv"
"strconv"
"syscall"
"syscall"
...
@@ -43,39 +44,33 @@ func mountSysfs() error {
...
@@ -43,39 +44,33 @@ func mountSysfs() error {
return
errors
.
Wrap
(
err
,
"creating a directory under /tmp"
)
return
errors
.
Wrap
(
err
,
"creating a directory under /tmp"
)
}
}
defer
os
.
RemoveAll
(
tmp
)
defer
os
.
RemoveAll
(
tmp
)
c
mds
:=
[][]
string
{{
"mount"
,
"--rbind"
,
"/sys/fs/cgroup"
,
tmp
}}
c
groupDir
:=
"/sys/fs/cgroup"
if
err
:=
common
.
Execs
(
os
.
Stderr
,
os
.
Environ
(),
cmds
);
err
!=
nil
{
if
err
:=
unix
.
Mount
(
cgroupDir
,
tmp
,
""
,
uintptr
(
unix
.
MS_BIND
|
unix
.
MS_REC
),
""
);
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"
executing %v"
,
cmds
)
return
errors
.
Wrapf
(
err
,
"
failed to create bind mount on %s"
,
cgroupDir
)
}
}
cmds
=
[][]
string
{{
"mount"
,
"-t"
,
"sysfs"
,
"none"
,
"/sys"
}}
if
err
:=
common
.
Execs
(
os
.
Stderr
,
os
.
Environ
(),
cmds
);
err
!=
nil
{
if
err
:=
unix
.
Mount
(
"none"
,
"/sys"
,
"sysfs"
,
0
,
""
);
err
!=
nil
{
// when the sysfs in the parent namespace is RO,
// when the sysfs in the parent namespace is RO,
// we can't mount RW sysfs even in the child namespace.
// we can't mount RW sysfs even in the child namespace.
// https://github.com/rootless-containers/rootlesskit/pull/23#issuecomment-429292632
// https://github.com/rootless-containers/rootlesskit/pull/23#issuecomment-429292632
// https://github.com/torvalds/linux/blob/9f203e2f2f065cd74553e6474f0ae3675f39fb0f/fs/namespace.c#L3326-L3328
// https://github.com/torvalds/linux/blob/9f203e2f2f065cd74553e6474f0ae3675f39fb0f/fs/namespace.c#L3326-L3328
cmdsRo
:=
[][]
string
{{
"mount"
,
"-t"
,
"sysfs"
,
"-o"
,
"ro"
,
"none"
,
"/sys"
}}
logrus
.
Warnf
(
"failed to mount sysfs, falling back to read-only mount: %v"
,
err
)
logrus
.
Warnf
(
"failed to mount sysfs (%v), falling back to read-only mount (%v): %v"
,
if
err
:=
unix
.
Mount
(
"none"
,
"/sys"
,
"sysfs"
,
uintptr
(
unix
.
MS_RDONLY
),
""
);
err
!=
nil
{
cmds
,
cmdsRo
,
err
)
if
err
:=
common
.
Execs
(
os
.
Stderr
,
os
.
Environ
(),
cmdsRo
);
err
!=
nil
{
// when /sys/firmware is masked, even RO sysfs can't be mounted
// when /sys/firmware is masked, even RO sysfs can't be mounted
logrus
.
Warnf
(
"failed to mount sysfs
(%v): %v"
,
cmdsRo
,
err
)
logrus
.
Warnf
(
"failed to mount sysfs
: %v"
,
err
)
}
}
}
}
cmds
=
[][]
string
{{
"mount"
,
"-n"
,
"--move"
,
tmp
,
"/sys/fs/cgroup"
}}
if
err
:=
unix
.
Mount
(
tmp
,
cgroupDir
,
""
,
uintptr
(
unix
.
MS_MOVE
),
""
);
err
!=
nil
{
if
err
:=
common
.
Execs
(
os
.
Stderr
,
os
.
Environ
(),
cmds
);
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"failed to move mount point from %s to %s"
,
tmp
,
cgroupDir
)
return
errors
.
Wrapf
(
err
,
"executing %v"
,
cmds
)
}
}
return
nil
return
nil
}
}
func
mountProcfs
()
error
{
func
mountProcfs
()
error
{
cmds
:=
[][]
string
{{
"mount"
,
"-t"
,
"proc"
,
"none"
,
"/proc"
}}
if
err
:=
unix
.
Mount
(
"none"
,
"/proc"
,
"proc"
,
0
,
""
);
err
!=
nil
{
if
err
:=
common
.
Execs
(
os
.
Stderr
,
os
.
Environ
(),
cmds
);
err
!=
nil
{
logrus
.
Warnf
(
"failed to mount procfs, falling back to read-only mount: %v"
,
err
)
cmdsRo
:=
[][]
string
{{
"mount"
,
"-t"
,
"proc"
,
"-o"
,
"ro"
,
"none"
,
"/proc"
}}
if
err
:=
unix
.
Mount
(
"none"
,
"/proc"
,
"proc"
,
uintptr
(
unix
.
MS_RDONLY
),
""
);
err
!=
nil
{
logrus
.
Warnf
(
"failed to mount procfs (%v), falling back to read-only mount (%v): %v"
,
logrus
.
Warnf
(
"failed to mount procfs: %v"
,
err
)
cmds
,
cmdsRo
,
err
)
if
err
:=
common
.
Execs
(
os
.
Stderr
,
os
.
Environ
(),
cmdsRo
);
err
!=
nil
{
logrus
.
Warnf
(
"failed to mount procfs (%v): %v"
,
cmdsRo
,
err
)
}
}
}
}
return
nil
return
nil
...
@@ -171,6 +166,7 @@ type Opt struct {
...
@@ -171,6 +166,7 @@ type Opt struct {
CopyUpDirs
[]
string
CopyUpDirs
[]
string
PortDriver
port
.
ChildDriver
PortDriver
port
.
ChildDriver
MountProcfs
bool
// needs to be set if (and only if) parent.Opt.CreatePIDNS is set
MountProcfs
bool
// needs to be set if (and only if) parent.Opt.CreatePIDNS is set
Reaper
bool
}
}
func
Child
(
opt
Opt
)
error
{
func
Child
(
opt
Opt
)
error
{
...
@@ -242,8 +238,14 @@ func Child(opt Opt) error {
...
@@ -242,8 +238,14 @@ func Child(opt Opt) error {
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
if
err
:=
cmd
.
Run
();
err
!=
nil
{
if
opt
.
Reaper
{
return
errors
.
Wrapf
(
err
,
"command %v exited"
,
opt
.
TargetCmd
)
if
err
:=
runAndReap
(
cmd
);
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"command %v exited"
,
opt
.
TargetCmd
)
}
}
else
{
if
err
:=
cmd
.
Run
();
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"command %v exited"
,
opt
.
TargetCmd
)
}
}
}
if
opt
.
PortDriver
!=
nil
{
if
opt
.
PortDriver
!=
nil
{
portQuitCh
<-
struct
{}{}
portQuitCh
<-
struct
{}{}
...
@@ -251,3 +253,27 @@ func Child(opt Opt) error {
...
@@ -251,3 +253,27 @@ func Child(opt Opt) error {
}
}
return
nil
return
nil
}
}
func
runAndReap
(
cmd
*
exec
.
Cmd
)
error
{
c
:=
make
(
chan
os
.
Signal
,
32
)
signal
.
Notify
(
c
,
syscall
.
SIGCHLD
)
if
err
:=
cmd
.
Start
();
err
!=
nil
{
return
err
}
result
:=
make
(
chan
error
)
go
func
()
{
defer
close
(
result
)
for
range
c
{
for
{
if
pid
,
err
:=
syscall
.
Wait4
(
-
1
,
nil
,
syscall
.
WNOHANG
,
nil
);
err
!=
nil
||
pid
<=
0
{
break
}
else
{
if
pid
==
cmd
.
Process
.
Pid
{
result
<-
cmd
.
Wait
()
}
}
}
}
}()
return
<-
result
}
vendor/github.com/rootless-containers/rootlesskit/pkg/child/hosts.go
View file @
8c9ed8e1
...
@@ -6,9 +6,9 @@ import (
...
@@ -6,9 +6,9 @@ import (
"os"
"os"
"path/filepath"
"path/filepath"
"g
ithub.com/pkg/errors
"
"g
olang.org/x/sys/unix
"
"github.com/
rootless-containers/rootlesskit/pkg/common
"
"github.com/
pkg/errors
"
)
)
// generateEtcHosts makes sure the current hostname is resolved into
// generateEtcHosts makes sure the current hostname is resolved into
...
@@ -56,11 +56,9 @@ func mountEtcHosts(tempDir string) error {
...
@@ -56,11 +56,9 @@ func mountEtcHosts(tempDir string) error {
if
err
:=
ioutil
.
WriteFile
(
myEtcHosts
,
newEtcHosts
,
0644
);
err
!=
nil
{
if
err
:=
ioutil
.
WriteFile
(
myEtcHosts
,
newEtcHosts
,
0644
);
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"writing %s"
,
myEtcHosts
)
return
errors
.
Wrapf
(
err
,
"writing %s"
,
myEtcHosts
)
}
}
cmds
:=
[][]
string
{
{
"mount"
,
"--bind"
,
myEtcHosts
,
"/etc/hosts"
},
if
err
:=
unix
.
Mount
(
myEtcHosts
,
"/etc/hosts"
,
""
,
uintptr
(
unix
.
MS_BIND
),
""
);
err
!=
nil
{
}
return
errors
.
Wrapf
(
err
,
"failed to create bind mount /etc/hosts for %s"
,
myEtcHosts
)
if
err
:=
common
.
Execs
(
os
.
Stderr
,
os
.
Environ
(),
cmds
);
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"executing %v"
,
cmds
)
}
}
return
nil
return
nil
}
}
vendor/github.com/rootless-containers/rootlesskit/pkg/child/resolvconf.go
View file @
8c9ed8e1
package
child
package
child
import
(
import
(
"golang.org/x/sys/unix"
"io/ioutil"
"io/ioutil"
"os"
"os"
"path/filepath"
"path/filepath"
"github.com/pkg/errors"
"github.com/pkg/errors"
"github.com/rootless-containers/rootlesskit/pkg/common"
)
)
func
generateResolvConf
(
dns
string
)
[]
byte
{
func
generateResolvConf
(
dns
string
)
[]
byte
{
...
@@ -36,11 +35,9 @@ func mountResolvConf(tempDir, dns string) error {
...
@@ -36,11 +35,9 @@ func mountResolvConf(tempDir, dns string) error {
if
err
:=
ioutil
.
WriteFile
(
myResolvConf
,
generateResolvConf
(
dns
),
0644
);
err
!=
nil
{
if
err
:=
ioutil
.
WriteFile
(
myResolvConf
,
generateResolvConf
(
dns
),
0644
);
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"writing %s"
,
myResolvConf
)
return
errors
.
Wrapf
(
err
,
"writing %s"
,
myResolvConf
)
}
}
cmds
:=
[][]
string
{
{
"mount"
,
"--bind"
,
myResolvConf
,
"/etc/resolv.conf"
},
if
err
:=
unix
.
Mount
(
myResolvConf
,
"/etc/resolv.conf"
,
""
,
uintptr
(
unix
.
MS_BIND
),
""
);
err
!=
nil
{
}
return
errors
.
Wrapf
(
err
,
"failed to create bind mount /etc/resolv.conf for %s"
,
myResolvConf
)
if
err
:=
common
.
Execs
(
os
.
Stderr
,
os
.
Environ
(),
cmds
);
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"executing %v"
,
cmds
)
}
}
return
nil
return
nil
}
}
vendor/github.com/rootless-containers/rootlesskit/pkg/copyup/tmpfssymlink/tmpfssymlink.go
View file @
8c9ed8e1
...
@@ -5,9 +5,10 @@ import (
...
@@ -5,9 +5,10 @@ import (
"os"
"os"
"path/filepath"
"path/filepath"
"golang.org/x/sys/unix"
"github.com/pkg/errors"
"github.com/pkg/errors"
"github.com/rootless-containers/rootlesskit/pkg/common"
"github.com/rootless-containers/rootlesskit/pkg/copyup"
"github.com/rootless-containers/rootlesskit/pkg/copyup"
)
)
...
@@ -33,24 +34,23 @@ func (d *childDriver) CopyUp(dirs []string) ([]string, error) {
...
@@ -33,24 +34,23 @@ func (d *childDriver) CopyUp(dirs []string) ([]string, error) {
// TODO: we can support copy-up /tmp by changing bind0TempDir
// TODO: we can support copy-up /tmp by changing bind0TempDir
return
copied
,
errors
.
New
(
"/tmp cannot be copied up"
)
return
copied
,
errors
.
New
(
"/tmp cannot be copied up"
)
}
}
cmds
:=
[][]
string
{
// TODO: read-only bind (does not work well for /run)
if
err
:=
unix
.
Mount
(
d
,
bind0
,
""
,
uintptr
(
unix
.
MS_BIND
|
unix
.
MS_REC
),
""
);
err
!=
nil
{
{
"mount"
,
"--rbind"
,
d
,
bind0
},
return
copied
,
errors
.
Wrapf
(
err
,
"failed to create bind mount on %s"
,
d
)
{
"mount"
,
"-n"
,
"-t"
,
"tmpfs"
,
"none"
,
d
},
}
}
if
err
:=
common
.
Execs
(
os
.
Stderr
,
os
.
Environ
(),
cmds
);
err
!=
nil
{
return
copied
,
errors
.
Wrapf
(
err
,
"executing %v"
,
cmds
)
if
err
:=
unix
.
Mount
(
"none"
,
d
,
"tmpfs"
,
0
,
""
);
err
!=
nil
{
return
copied
,
errors
.
Wrapf
(
err
,
"failed to mount tmpfs on %s"
,
d
)
}
}
bind1
,
err
:=
ioutil
.
TempDir
(
d
,
".ro"
)
bind1
,
err
:=
ioutil
.
TempDir
(
d
,
".ro"
)
if
err
!=
nil
{
if
err
!=
nil
{
return
copied
,
errors
.
Wrapf
(
err
,
"creating a directory under %s"
,
d
)
return
copied
,
errors
.
Wrapf
(
err
,
"creating a directory under %s"
,
d
)
}
}
cmds
=
[][]
string
{
if
err
:=
unix
.
Mount
(
bind0
,
bind1
,
""
,
uintptr
(
unix
.
MS_MOVE
),
""
);
err
!=
nil
{
{
"mount"
,
"-n"
,
"--move"
,
bind0
,
bind1
},
return
copied
,
errors
.
Wrapf
(
err
,
"failed to move mount point from %s to %s"
,
bind0
,
bind1
)
}
if
err
:=
common
.
Execs
(
os
.
Stderr
,
os
.
Environ
(),
cmds
);
err
!=
nil
{
return
copied
,
errors
.
Wrapf
(
err
,
"executing %v"
,
cmds
)
}
}
files
,
err
:=
ioutil
.
ReadDir
(
bind1
)
files
,
err
:=
ioutil
.
ReadDir
(
bind1
)
if
err
!=
nil
{
if
err
!=
nil
{
return
copied
,
errors
.
Wrapf
(
err
,
"reading dir %s"
,
bind1
)
return
copied
,
errors
.
Wrapf
(
err
,
"reading dir %s"
,
bind1
)
...
...
vendor/github.com/rootless-containers/rootlesskit/pkg/network/slirp4netns/slirp4netns.go
View file @
8c9ed8e1
...
@@ -3,12 +3,16 @@ package slirp4netns
...
@@ -3,12 +3,16 @@ package slirp4netns
import
(
import
(
"context"
"context"
"net"
"net"
"os"
"os/exec"
"os/exec"
"strconv"
"strconv"
"strings"
"syscall"
"syscall"
"time"
"github.com/pkg/errors"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
"github.com/rootless-containers/rootlesskit/pkg/common"
"github.com/rootless-containers/rootlesskit/pkg/common"
"github.com/rootless-containers/rootlesskit/pkg/network"
"github.com/rootless-containers/rootlesskit/pkg/network"
...
@@ -16,13 +20,62 @@ import (
...
@@ -16,13 +20,62 @@ import (
"github.com/rootless-containers/rootlesskit/pkg/network/parentutils"
"github.com/rootless-containers/rootlesskit/pkg/network/parentutils"
)
)
type
Features
struct
{
// SupportsCIDR --cidr (v0.3.0)
SupportsCIDR
bool
// SupportsDisableHostLoopback --disable-host-loopback (v0.3.0)
SupportsDisableHostLoopback
bool
// SupportsAPISocket --api-socket (v0.3.0)
SupportsAPISocket
bool
// SupportsEnableSandbox --enable-sandbox (v0.4.0)
SupportsEnableSandbox
bool
// SupportsEnableSeccomp --enable-seccomp (v0.4.0)
SupportsEnableSeccomp
bool
// KernelSupportsSeccomp whether the kernel supports slirp4netns --enable-seccomp
KernelSupportsEnableSeccomp
bool
}
func
DetectFeatures
(
binary
string
)
(
*
Features
,
error
)
{
if
binary
==
""
{
return
nil
,
errors
.
New
(
"got empty slirp4netns binary"
)
}
realBinary
,
err
:=
exec
.
LookPath
(
binary
)
if
err
!=
nil
{
return
nil
,
errors
.
Wrapf
(
err
,
"slirp4netns binary %q is not installed"
,
binary
)
}
cmd
:=
exec
.
Command
(
realBinary
,
"--help"
)
cmd
.
Env
=
os
.
Environ
()
b
,
err
:=
cmd
.
CombinedOutput
()
s
:=
string
(
b
)
if
err
!=
nil
{
return
nil
,
errors
.
Wrapf
(
err
,
"command
\"
%s --help
\"
failed, make sure slirp4netns v0.2.0+ is installed: %q"
,
realBinary
,
s
)
}
kernelSupportsEnableSeccomp
:=
false
if
unix
.
Prctl
(
unix
.
PR_GET_SECCOMP
,
0
,
0
,
0
,
0
)
!=
unix
.
EINVAL
{
kernelSupportsEnableSeccomp
=
unix
.
Prctl
(
unix
.
PR_SET_SECCOMP
,
unix
.
SECCOMP_MODE_FILTER
,
0
,
0
,
0
)
!=
unix
.
EINVAL
}
f
:=
Features
{
SupportsCIDR
:
strings
.
Contains
(
s
,
"--cidr"
),
SupportsDisableHostLoopback
:
strings
.
Contains
(
s
,
"--disable-host-loopback"
),
SupportsAPISocket
:
strings
.
Contains
(
s
,
"--api-socket"
),
SupportsEnableSandbox
:
strings
.
Contains
(
s
,
"--enable-sandbox"
),
SupportsEnableSeccomp
:
strings
.
Contains
(
s
,
"--enable-seccomp"
),
KernelSupportsEnableSeccomp
:
kernelSupportsEnableSeccomp
,
}
return
&
f
,
nil
}
// NewParentDriver instantiates new parent driver.
// NewParentDriver instantiates new parent driver.
// ipnet is supported only for slirp4netns v0.3.0+.
// ipnet is supported only for slirp4netns v0.3.0+.
// ipnet MUST be nil for slirp4netns < v0.3.0.
// ipnet MUST be nil for slirp4netns < v0.3.0.
//
//
// disableHostLoopback is supported only for slirp4netns v0.3.0+
// disableHostLoopback is supported only for slirp4netns v0.3.0+
// apiSocketPath is supported only for slirp4netns v0.3.0+
// apiSocketPath is supported only for slirp4netns v0.3.0+
func
NewParentDriver
(
binary
string
,
mtu
int
,
ipnet
*
net
.
IPNet
,
disableHostLoopback
bool
,
apiSocketPath
string
)
network
.
ParentDriver
{
// enableSandbox is supported only for slirp4netns v0.4.0+
// enableSeccomp is supported only for slirp4netns v0.4.0+
func
NewParentDriver
(
binary
string
,
mtu
int
,
ipnet
*
net
.
IPNet
,
disableHostLoopback
bool
,
apiSocketPath
string
,
enableSandbox
,
enableSeccomp
bool
)
network
.
ParentDriver
{
if
binary
==
""
{
if
binary
==
""
{
panic
(
"got empty slirp4netns binary"
)
panic
(
"got empty slirp4netns binary"
)
}
}
...
@@ -38,6 +91,8 @@ func NewParentDriver(binary string, mtu int, ipnet *net.IPNet, disableHostLoopba
...
@@ -38,6 +91,8 @@ func NewParentDriver(binary string, mtu int, ipnet *net.IPNet, disableHostLoopba
ipnet
:
ipnet
,
ipnet
:
ipnet
,
disableHostLoopback
:
disableHostLoopback
,
disableHostLoopback
:
disableHostLoopback
,
apiSocketPath
:
apiSocketPath
,
apiSocketPath
:
apiSocketPath
,
enableSandbox
:
enableSandbox
,
enableSeccomp
:
enableSeccomp
,
}
}
}
}
...
@@ -47,6 +102,8 @@ type parentDriver struct {
...
@@ -47,6 +102,8 @@ type parentDriver struct {
ipnet
*
net
.
IPNet
ipnet
*
net
.
IPNet
disableHostLoopback
bool
disableHostLoopback
bool
apiSocketPath
string
apiSocketPath
string
enableSandbox
bool
enableSeccomp
bool
}
}
func
(
d
*
parentDriver
)
MTU
()
int
{
func
(
d
*
parentDriver
)
MTU
()
int
{
...
@@ -60,7 +117,14 @@ func (d *parentDriver) ConfigureNetwork(childPID int, stateDir string) (*common.
...
@@ -60,7 +117,14 @@ func (d *parentDriver) ConfigureNetwork(childPID int, stateDir string) (*common.
return
nil
,
common
.
Seq
(
cleanups
),
errors
.
Wrapf
(
err
,
"setting up tap %s"
,
tap
)
return
nil
,
common
.
Seq
(
cleanups
),
errors
.
Wrapf
(
err
,
"setting up tap %s"
,
tap
)
}
}
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
opts
:=
[]
string
{
"--mtu"
,
strconv
.
Itoa
(
d
.
mtu
)}
readyR
,
readyW
,
err
:=
os
.
Pipe
()
if
err
!=
nil
{
return
nil
,
common
.
Seq
(
cleanups
),
err
}
defer
readyR
.
Close
()
defer
readyW
.
Close
()
// -r: readyFD
opts
:=
[]
string
{
"--mtu"
,
strconv
.
Itoa
(
d
.
mtu
),
"-r"
,
"3"
}
if
d
.
disableHostLoopback
{
if
d
.
disableHostLoopback
{
opts
=
append
(
opts
,
"--disable-host-loopback"
)
opts
=
append
(
opts
,
"--disable-host-loopback"
)
}
}
...
@@ -70,10 +134,17 @@ func (d *parentDriver) ConfigureNetwork(childPID int, stateDir string) (*common.
...
@@ -70,10 +134,17 @@ func (d *parentDriver) ConfigureNetwork(childPID int, stateDir string) (*common.
if
d
.
apiSocketPath
!=
""
{
if
d
.
apiSocketPath
!=
""
{
opts
=
append
(
opts
,
"--api-socket"
,
d
.
apiSocketPath
)
opts
=
append
(
opts
,
"--api-socket"
,
d
.
apiSocketPath
)
}
}
if
d
.
enableSandbox
{
opts
=
append
(
opts
,
"--enable-sandbox"
)
}
if
d
.
enableSeccomp
{
opts
=
append
(
opts
,
"--enable-seccomp"
)
}
cmd
:=
exec
.
CommandContext
(
ctx
,
d
.
binary
,
append
(
opts
,
[]
string
{
strconv
.
Itoa
(
childPID
),
tap
}
...
)
...
)
cmd
:=
exec
.
CommandContext
(
ctx
,
d
.
binary
,
append
(
opts
,
[]
string
{
strconv
.
Itoa
(
childPID
),
tap
}
...
)
...
)
cmd
.
SysProcAttr
=
&
syscall
.
SysProcAttr
{
cmd
.
SysProcAttr
=
&
syscall
.
SysProcAttr
{
Pdeathsig
:
syscall
.
SIGKILL
,
Pdeathsig
:
syscall
.
SIGKILL
,
}
}
cmd
.
ExtraFiles
=
append
(
cmd
.
ExtraFiles
,
readyW
)
cleanups
=
append
(
cleanups
,
func
()
error
{
cleanups
=
append
(
cleanups
,
func
()
error
{
logrus
.
Debugf
(
"killing slirp4netns"
)
logrus
.
Debugf
(
"killing slirp4netns"
)
cancel
()
cancel
()
...
@@ -84,6 +155,10 @@ func (d *parentDriver) ConfigureNetwork(childPID int, stateDir string) (*common.
...
@@ -84,6 +155,10 @@ func (d *parentDriver) ConfigureNetwork(childPID int, stateDir string) (*common.
if
err
:=
cmd
.
Start
();
err
!=
nil
{
if
err
:=
cmd
.
Start
();
err
!=
nil
{
return
nil
,
common
.
Seq
(
cleanups
),
errors
.
Wrapf
(
err
,
"executing %v"
,
cmd
)
return
nil
,
common
.
Seq
(
cleanups
),
errors
.
Wrapf
(
err
,
"executing %v"
,
cmd
)
}
}
if
err
:=
waitForReadyFD
(
cmd
.
Process
.
Pid
,
readyR
);
err
!=
nil
{
return
nil
,
common
.
Seq
(
cleanups
),
errors
.
Wrapf
(
err
,
"waiting for ready fd (%v)"
,
cmd
)
}
netmsg
:=
common
.
NetworkMessage
{
netmsg
:=
common
.
NetworkMessage
{
Dev
:
tap
,
Dev
:
tap
,
MTU
:
d
.
mtu
,
MTU
:
d
.
mtu
,
...
@@ -115,6 +190,41 @@ func (d *parentDriver) ConfigureNetwork(childPID int, stateDir string) (*common.
...
@@ -115,6 +190,41 @@ func (d *parentDriver) ConfigureNetwork(childPID int, stateDir string) (*common.
return
&
netmsg
,
common
.
Seq
(
cleanups
),
nil
return
&
netmsg
,
common
.
Seq
(
cleanups
),
nil
}
}
// waitForReady is from libpod
// https://github.com/containers/libpod/blob/e6b843312b93ddaf99d0ef94a7e60ff66bc0eac8/libpod/networking_linux.go#L272-L308
func
waitForReadyFD
(
cmdPid
int
,
r
*
os
.
File
)
error
{
b
:=
make
([]
byte
,
16
)
for
{
if
err
:=
r
.
SetDeadline
(
time
.
Now
()
.
Add
(
1
*
time
.
Second
));
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"error setting slirp4netns pipe timeout"
)
}
if
_
,
err
:=
r
.
Read
(
b
);
err
==
nil
{
break
}
else
{
if
os
.
IsTimeout
(
err
)
{
// Check if the process is still running.
var
status
syscall
.
WaitStatus
pid
,
err
:=
syscall
.
Wait4
(
cmdPid
,
&
status
,
syscall
.
WNOHANG
,
nil
)
if
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"failed to read slirp4netns process status"
)
}
if
pid
!=
cmdPid
{
continue
}
if
status
.
Exited
()
{
return
errors
.
New
(
"slirp4netns failed"
)
}
if
status
.
Signaled
()
{
return
errors
.
New
(
"slirp4netns killed by signal"
)
}
continue
}
return
errors
.
Wrapf
(
err
,
"failed to read from slirp4netns sync pipe"
)
}
}
return
nil
}
func
NewChildDriver
()
network
.
ChildDriver
{
func
NewChildDriver
()
network
.
ChildDriver
{
return
&
childDriver
{}
return
&
childDriver
{}
}
}
...
...
vendor/github.com/
docker/docker/pkg
/idtools/idtools.go
→
vendor/github.com/
rootless-containers/rootlesskit/pkg/parent
/idtools/idtools.go
View file @
8c9ed8e1
package
idtools
// import "github.com/docker/docker/pkg/idtools"
// Package idtools is forked from https://github.com/moby/moby/tree/c12f09bf99b54f274a5ae241dd154fa74020cbab/pkg/idtools
package
idtools
import
(
import
(
"bufio"
"bufio"
"fmt"
"fmt"
"os"
"os"
"sort"
"strconv"
"strconv"
"strings"
"strings"
)
)
...
@@ -33,28 +35,6 @@ const (
...
@@ -33,28 +35,6 @@ const (
subgidFileName
=
"/etc/subgid"
subgidFileName
=
"/etc/subgid"
)
)
// MkdirAllAndChown creates a directory (include any along the path) and then modifies
// ownership to the requested uid/gid. If the directory already exists, this
// function will still change ownership to the requested uid/gid pair.
func
MkdirAllAndChown
(
path
string
,
mode
os
.
FileMode
,
owner
Identity
)
error
{
return
mkdirAs
(
path
,
mode
,
owner
,
true
,
true
)
}
// MkdirAndChown creates a directory and then modifies ownership to the requested uid/gid.
// If the directory already exists, this function still changes ownership.
// Note that unlike os.Mkdir(), this function does not return IsExist error
// in case path already exists.
func
MkdirAndChown
(
path
string
,
mode
os
.
FileMode
,
owner
Identity
)
error
{
return
mkdirAs
(
path
,
mode
,
owner
,
false
,
true
)
}
// MkdirAllAndChownNew creates a directory (include any along the path) and then modifies
// ownership ONLY of newly created directories to the requested uid/gid. If the
// directories along the path exist, no change of ownership will be performed
func
MkdirAllAndChownNew
(
path
string
,
mode
os
.
FileMode
,
owner
Identity
)
error
{
return
mkdirAs
(
path
,
mode
,
owner
,
true
,
false
)
}
// GetRootUIDGID retrieves the remapped root uid/gid pair from the set of maps.
// GetRootUIDGID retrieves the remapped root uid/gid pair from the set of maps.
// If the maps are empty, then the root uid/gid will default to "real" 0/0
// If the maps are empty, then the root uid/gid will default to "real" 0/0
func
GetRootUIDGID
(
uidMap
,
gidMap
[]
IDMap
)
(
int
,
int
,
error
)
{
func
GetRootUIDGID
(
uidMap
,
gidMap
[]
IDMap
)
(
int
,
int
,
error
)
{
...
@@ -202,6 +182,8 @@ func (i *IdentityMapping) GIDs() []IDMap {
...
@@ -202,6 +182,8 @@ func (i *IdentityMapping) GIDs() []IDMap {
func
createIDMap
(
subidRanges
ranges
)
[]
IDMap
{
func
createIDMap
(
subidRanges
ranges
)
[]
IDMap
{
idMap
:=
[]
IDMap
{}
idMap
:=
[]
IDMap
{}
// sort the ranges by lowest ID first
sort
.
Sort
(
subidRanges
)
containerID
:=
0
containerID
:=
0
for
_
,
idrange
:=
range
subidRanges
{
for
_
,
idrange
:=
range
subidRanges
{
idMap
=
append
(
idMap
,
IDMap
{
idMap
=
append
(
idMap
,
IDMap
{
...
...
vendor/github.com/rootless-containers/rootlesskit/pkg/parent/parent.go
View file @
8c9ed8e1
...
@@ -12,7 +12,6 @@ import (
...
@@ -12,7 +12,6 @@ import (
"strconv"
"strconv"
"syscall"
"syscall"
"github.com/docker/docker/pkg/idtools"
"github.com/gorilla/mux"
"github.com/gorilla/mux"
"github.com/pkg/errors"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus"
...
@@ -22,6 +21,7 @@ import (
...
@@ -22,6 +21,7 @@ import (
"github.com/rootless-containers/rootlesskit/pkg/common"
"github.com/rootless-containers/rootlesskit/pkg/common"
"github.com/rootless-containers/rootlesskit/pkg/msgutil"
"github.com/rootless-containers/rootlesskit/pkg/msgutil"
"github.com/rootless-containers/rootlesskit/pkg/network"
"github.com/rootless-containers/rootlesskit/pkg/network"
"github.com/rootless-containers/rootlesskit/pkg/parent/idtools"
"github.com/rootless-containers/rootlesskit/pkg/port"
"github.com/rootless-containers/rootlesskit/pkg/port"
)
)
...
@@ -103,10 +103,6 @@ func Parent(opt Opt) error {
...
@@ -103,10 +103,6 @@ func Parent(opt Opt) error {
if
err
:=
cmd
.
Start
();
err
!=
nil
{
if
err
:=
cmd
.
Start
();
err
!=
nil
{
return
errors
.
Wrap
(
err
,
"failed to start the child"
)
return
errors
.
Wrap
(
err
,
"failed to start the child"
)
}
}
childPIDPath
:=
filepath
.
Join
(
opt
.
StateDir
,
StateFileChildPID
)
if
err
:=
ioutil
.
WriteFile
(
childPIDPath
,
[]
byte
(
strconv
.
Itoa
(
cmd
.
Process
.
Pid
)),
0444
);
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"failed to write the child PID %d to %s"
,
cmd
.
Process
.
Pid
,
childPIDPath
)
}
if
err
:=
setupUIDGIDMap
(
cmd
.
Process
.
Pid
);
err
!=
nil
{
if
err
:=
setupUIDGIDMap
(
cmd
.
Process
.
Pid
);
err
!=
nil
{
return
errors
.
Wrap
(
err
,
"failed to setup UID/GID map"
)
return
errors
.
Wrap
(
err
,
"failed to setup UID/GID map"
)
}
}
...
@@ -176,6 +172,12 @@ func Parent(opt Opt) error {
...
@@ -176,6 +172,12 @@ func Parent(opt Opt) error {
logrus
.
Debugf
(
"published port %v"
,
st
)
logrus
.
Debugf
(
"published port %v"
,
st
)
}
}
}
}
// after child is fully configured, write PID to child_pid file
childPIDPath
:=
filepath
.
Join
(
opt
.
StateDir
,
StateFileChildPID
)
if
err
:=
ioutil
.
WriteFile
(
childPIDPath
,
[]
byte
(
strconv
.
Itoa
(
cmd
.
Process
.
Pid
)),
0444
);
err
!=
nil
{
return
errors
.
Wrapf
(
err
,
"failed to write the child PID %d to %s"
,
cmd
.
Process
.
Pid
,
childPIDPath
)
}
// listens the API
// listens the API
apiSockPath
:=
filepath
.
Join
(
opt
.
StateDir
,
StateFileAPISock
)
apiSockPath
:=
filepath
.
Join
(
opt
.
StateDir
,
StateFileAPISock
)
apiCloser
,
err
:=
listenServeAPI
(
apiSockPath
,
&
router
.
Backend
{
PortDriver
:
opt
.
PortDriver
})
apiCloser
,
err
:=
listenServeAPI
(
apiSockPath
,
&
router
.
Backend
{
PortDriver
:
opt
.
PortDriver
})
...
...
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/builtin.go
View file @
8c9ed8e1
This diff is collapsed.
Click to expand it.
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/child/child.go
0 → 100644
View file @
8c9ed8e1
package
child
import
(
"fmt"
"io"
"net"
"os"
"github.com/pkg/errors"
"golang.org/x/sys/unix"
"github.com/rootless-containers/rootlesskit/pkg/msgutil"
"github.com/rootless-containers/rootlesskit/pkg/port"
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/msg"
opaquepkg
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/opaque"
)
func
NewDriver
(
logWriter
io
.
Writer
)
port
.
ChildDriver
{
return
&
childDriver
{
logWriter
:
logWriter
,
}
}
type
childDriver
struct
{
logWriter
io
.
Writer
}
func
(
d
*
childDriver
)
RunChildDriver
(
opaque
map
[
string
]
string
,
quit
<-
chan
struct
{})
error
{
socketPath
:=
opaque
[
opaquepkg
.
SocketPath
]
if
socketPath
==
""
{
return
errors
.
New
(
"socket path not set"
)
}
childReadyPipePath
:=
opaque
[
opaquepkg
.
ChildReadyPipePath
]
if
childReadyPipePath
==
""
{
return
errors
.
New
(
"child ready pipe path not set"
)
}
childReadyPipeW
,
err
:=
os
.
OpenFile
(
childReadyPipePath
,
os
.
O_WRONLY
,
os
.
ModeNamedPipe
)
if
err
!=
nil
{
return
err
}
ln
,
err
:=
net
.
ListenUnix
(
"unix"
,
&
net
.
UnixAddr
{
Name
:
socketPath
,
Net
:
"unix"
,
})
if
err
!=
nil
{
return
err
}
// write nothing, just close
if
err
=
childReadyPipeW
.
Close
();
err
!=
nil
{
return
err
}
stopAccept
:=
make
(
chan
struct
{},
1
)
go
func
()
{
<-
quit
stopAccept
<-
struct
{}{}
ln
.
Close
()
}()
for
{
c
,
err
:=
ln
.
AcceptUnix
()
if
err
!=
nil
{
select
{
case
<-
stopAccept
:
return
nil
default
:
}
return
err
}
go
func
()
{
if
rerr
:=
d
.
routine
(
c
);
rerr
!=
nil
{
rep
:=
msg
.
Reply
{
Error
:
rerr
.
Error
(),
}
msgutil
.
MarshalToWriter
(
c
,
&
rep
)
}
c
.
Close
()
}()
}
return
nil
}
func
(
d
*
childDriver
)
routine
(
c
*
net
.
UnixConn
)
error
{
var
req
msg
.
Request
if
_
,
err
:=
msgutil
.
UnmarshalFromReader
(
c
,
&
req
);
err
!=
nil
{
return
err
}
switch
req
.
Type
{
case
msg
.
RequestTypeInit
:
return
d
.
handleConnectInit
(
c
,
&
req
)
case
msg
.
RequestTypeConnect
:
return
d
.
handleConnectRequest
(
c
,
&
req
)
default
:
return
errors
.
Errorf
(
"unknown request type %q"
,
req
.
Type
)
}
}
func
(
d
*
childDriver
)
handleConnectInit
(
c
*
net
.
UnixConn
,
req
*
msg
.
Request
)
error
{
_
,
err
:=
msgutil
.
MarshalToWriter
(
c
,
nil
)
return
err
}
func
(
d
*
childDriver
)
handleConnectRequest
(
c
*
net
.
UnixConn
,
req
*
msg
.
Request
)
error
{
switch
req
.
Proto
{
case
"tcp"
:
case
"udp"
:
default
:
return
errors
.
Errorf
(
"unknown proto: %q"
,
req
.
Proto
)
}
var
dialer
net
.
Dialer
targetConn
,
err
:=
dialer
.
Dial
(
req
.
Proto
,
fmt
.
Sprintf
(
"127.0.0.1:%d"
,
req
.
Port
))
if
err
!=
nil
{
return
err
}
defer
targetConn
.
Close
()
// no effect on duplicated FD
targetConnFiler
,
ok
:=
targetConn
.
(
filer
)
if
!
ok
{
return
errors
.
Errorf
(
"unknown target connection: %+v"
,
targetConn
)
}
targetConnFile
,
err
:=
targetConnFiler
.
File
()
if
err
!=
nil
{
return
err
}
oob
:=
unix
.
UnixRights
(
int
(
targetConnFile
.
Fd
()))
f
,
err
:=
c
.
File
()
if
err
!=
nil
{
return
err
}
err
=
unix
.
Sendmsg
(
int
(
f
.
Fd
()),
[]
byte
(
"dummy"
),
oob
,
nil
,
0
)
return
err
}
// filer is implemented by *net.TCPConn and *net.UDPConn
type
filer
interface
{
File
()
(
f
*
os
.
File
,
err
error
)
}
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/msg/msg.go
0 → 100644
View file @
8c9ed8e1
package
msg
import
(
"net"
"time"
"github.com/pkg/errors"
"golang.org/x/sys/unix"
"github.com/rootless-containers/rootlesskit/pkg/msgutil"
"github.com/rootless-containers/rootlesskit/pkg/port"
)
const
(
RequestTypeInit
=
"init"
RequestTypeConnect
=
"connect"
)
// Request and Response are encoded as JSON with uint32le length header.
type
Request
struct
{
Type
string
// "init" or "connect"
Proto
string
// "tcp" or "udp"
Port
int
}
// Reply may contain FD as OOB
type
Reply
struct
{
Error
string
}
// Initiate sends "init" request to the child UNIX socket.
func
Initiate
(
c
*
net
.
UnixConn
)
error
{
req
:=
Request
{
Type
:
RequestTypeInit
,
}
if
_
,
err
:=
msgutil
.
MarshalToWriter
(
c
,
&
req
);
err
!=
nil
{
return
err
}
if
err
:=
c
.
CloseWrite
();
err
!=
nil
{
return
err
}
var
rep
Reply
if
_
,
err
:=
msgutil
.
UnmarshalFromReader
(
c
,
&
rep
);
err
!=
nil
{
return
err
}
return
c
.
CloseRead
()
}
// ConnectToChild connects to the child UNIX socket, and obtains TCP or UDP socket FD
// that corresponds to the port spec.
func
ConnectToChild
(
c
*
net
.
UnixConn
,
spec
port
.
Spec
)
(
int
,
error
)
{
req
:=
Request
{
Type
:
RequestTypeConnect
,
Proto
:
spec
.
Proto
,
Port
:
spec
.
ChildPort
,
}
if
_
,
err
:=
msgutil
.
MarshalToWriter
(
c
,
&
req
);
err
!=
nil
{
return
0
,
err
}
if
err
:=
c
.
CloseWrite
();
err
!=
nil
{
return
0
,
err
}
oobSpace
:=
unix
.
CmsgSpace
(
4
)
oob
:=
make
([]
byte
,
oobSpace
)
_
,
oobN
,
_
,
_
,
err
:=
c
.
ReadMsgUnix
(
nil
,
oob
)
if
err
!=
nil
{
return
0
,
err
}
if
oobN
!=
oobSpace
{
return
0
,
errors
.
Errorf
(
"expected OOB space %d, got %d"
,
oobSpace
,
oobN
)
}
oob
=
oob
[
:
oobN
]
fd
,
err
:=
parseFDFromOOB
(
oob
)
if
err
!=
nil
{
return
0
,
err
}
if
err
:=
c
.
CloseRead
();
err
!=
nil
{
return
0
,
err
}
return
fd
,
nil
}
// ConnectToChildWithSocketPath wraps ConnectToChild
func
ConnectToChildWithSocketPath
(
socketPath
string
,
spec
port
.
Spec
)
(
int
,
error
)
{
var
dialer
net
.
Dialer
conn
,
err
:=
dialer
.
Dial
(
"unix"
,
socketPath
)
if
err
!=
nil
{
return
0
,
err
}
defer
conn
.
Close
()
c
:=
conn
.
(
*
net
.
UnixConn
)
return
ConnectToChild
(
c
,
spec
)
}
// ConnectToChildWithRetry retries ConnectToChild every (i*5) milliseconds.
func
ConnectToChildWithRetry
(
socketPath
string
,
spec
port
.
Spec
,
retries
int
)
(
int
,
error
)
{
for
i
:=
0
;
i
<
retries
;
i
++
{
fd
,
err
:=
ConnectToChildWithSocketPath
(
socketPath
,
spec
)
if
i
==
retries
-
1
&&
err
!=
nil
{
return
0
,
err
}
if
err
==
nil
{
return
fd
,
err
}
// TODO: backoff
time
.
Sleep
(
time
.
Duration
(
i
*
5
)
*
time
.
Millisecond
)
}
// NOT REACHED
return
0
,
errors
.
New
(
"reached max retry"
)
}
func
parseFDFromOOB
(
oob
[]
byte
)
(
int
,
error
)
{
scms
,
err
:=
unix
.
ParseSocketControlMessage
(
oob
)
if
err
!=
nil
{
return
0
,
err
}
if
len
(
scms
)
!=
1
{
return
0
,
errors
.
Errorf
(
"unexpected scms: %v"
,
scms
)
}
scm
:=
scms
[
0
]
fds
,
err
:=
unix
.
ParseUnixRights
(
&
scm
)
if
err
!=
nil
{
return
0
,
err
}
if
len
(
fds
)
!=
1
{
return
0
,
errors
.
Errorf
(
"unexpected fds: %v"
,
fds
)
}
return
fds
[
0
],
nil
}
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/opaque/opaque.go
0 → 100644
View file @
8c9ed8e1
package
opaque
const
(
SocketPath
=
"builtin.socketpath"
ChildReadyPipePath
=
"builtin.readypipepath"
)
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/parent.go
0 → 100644
View file @
8c9ed8e1
package
parent
import
(
"context"
"io"
"io/ioutil"
"net"
"os"
"path/filepath"
"sync"
"syscall"
"github.com/pkg/errors"
"github.com/rootless-containers/rootlesskit/pkg/port"
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/msg"
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/opaque"
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/tcp"
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp"
"github.com/rootless-containers/rootlesskit/pkg/port/portutil"
)
// NewDriver for builtin driver.
func
NewDriver
(
logWriter
io
.
Writer
,
stateDir
string
)
(
port
.
ParentDriver
,
error
)
{
// TODO: consider using socketpair FD instead of socket file
socketPath
:=
filepath
.
Join
(
stateDir
,
".bp.sock"
)
childReadyPipePath
:=
filepath
.
Join
(
stateDir
,
".bp-ready.pipe"
)
// remove the path just in case the previous rootlesskit instance crashed
if
err
:=
os
.
RemoveAll
(
childReadyPipePath
);
err
!=
nil
{
return
nil
,
errors
.
Wrapf
(
err
,
"cannot remove %s"
,
childReadyPipePath
)
}
if
err
:=
syscall
.
Mkfifo
(
childReadyPipePath
,
0600
);
err
!=
nil
{
return
nil
,
errors
.
Wrapf
(
err
,
"cannot mkfifo %s"
,
childReadyPipePath
)
}
d
:=
driver
{
logWriter
:
logWriter
,
socketPath
:
socketPath
,
childReadyPipePath
:
childReadyPipePath
,
ports
:
make
(
map
[
int
]
*
port
.
Status
,
0
),
stoppers
:
make
(
map
[
int
]
func
()
error
,
0
),
nextID
:
1
,
}
return
&
d
,
nil
}
type
driver
struct
{
logWriter
io
.
Writer
socketPath
string
childReadyPipePath
string
mu
sync
.
Mutex
ports
map
[
int
]
*
port
.
Status
stoppers
map
[
int
]
func
()
error
nextID
int
}
func
(
d
*
driver
)
OpaqueForChild
()
map
[
string
]
string
{
return
map
[
string
]
string
{
opaque
.
SocketPath
:
d
.
socketPath
,
opaque
.
ChildReadyPipePath
:
d
.
childReadyPipePath
,
}
}
func
(
d
*
driver
)
RunParentDriver
(
initComplete
chan
struct
{},
quit
<-
chan
struct
{},
_
*
port
.
ChildContext
)
error
{
childReadyPipeR
,
err
:=
os
.
OpenFile
(
d
.
childReadyPipePath
,
os
.
O_RDONLY
,
os
.
ModeNamedPipe
)
if
err
!=
nil
{
return
err
}
if
_
,
err
=
ioutil
.
ReadAll
(
childReadyPipeR
);
err
!=
nil
{
return
err
}
childReadyPipeR
.
Close
()
var
dialer
net
.
Dialer
conn
,
err
:=
dialer
.
Dial
(
"unix"
,
d
.
socketPath
)
if
err
!=
nil
{
return
err
}
err
=
msg
.
Initiate
(
conn
.
(
*
net
.
UnixConn
))
conn
.
Close
()
if
err
!=
nil
{
return
err
}
initComplete
<-
struct
{}{}
<-
quit
return
nil
}
func
(
d
*
driver
)
AddPort
(
ctx
context
.
Context
,
spec
port
.
Spec
)
(
*
port
.
Status
,
error
)
{
d
.
mu
.
Lock
()
err
:=
portutil
.
ValidatePortSpec
(
spec
,
d
.
ports
)
d
.
mu
.
Unlock
()
if
err
!=
nil
{
return
nil
,
err
}
routineStopCh
:=
make
(
chan
struct
{})
routineStop
:=
func
()
error
{
close
(
routineStopCh
)
return
nil
// FIXME
}
switch
spec
.
Proto
{
case
"tcp"
:
err
=
tcp
.
Run
(
d
.
socketPath
,
spec
,
routineStopCh
,
d
.
logWriter
)
case
"udp"
:
err
=
udp
.
Run
(
d
.
socketPath
,
spec
,
routineStopCh
,
d
.
logWriter
)
default
:
// NOTREACHED
return
nil
,
errors
.
New
(
"spec was not validated?"
)
}
if
err
!=
nil
{
return
nil
,
err
}
d
.
mu
.
Lock
()
id
:=
d
.
nextID
st
:=
port
.
Status
{
ID
:
id
,
Spec
:
spec
,
}
d
.
ports
[
id
]
=
&
st
d
.
stoppers
[
id
]
=
routineStop
d
.
nextID
++
d
.
mu
.
Unlock
()
return
&
st
,
nil
}
func
(
d
*
driver
)
ListPorts
(
ctx
context
.
Context
)
([]
port
.
Status
,
error
)
{
var
ports
[]
port
.
Status
d
.
mu
.
Lock
()
for
_
,
p
:=
range
d
.
ports
{
ports
=
append
(
ports
,
*
p
)
}
d
.
mu
.
Unlock
()
return
ports
,
nil
}
func
(
d
*
driver
)
RemovePort
(
ctx
context
.
Context
,
id
int
)
error
{
d
.
mu
.
Lock
()
defer
d
.
mu
.
Unlock
()
stop
,
ok
:=
d
.
stoppers
[
id
]
if
!
ok
{
return
errors
.
Errorf
(
"unknown id: %d"
,
id
)
}
err
:=
stop
()
delete
(
d
.
stoppers
,
id
)
delete
(
d
.
ports
,
id
)
return
err
}
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/tcp/tcp.go
0 → 100644
View file @
8c9ed8e1
package
tcp
import
(
"fmt"
"io"
"net"
"os"
"sync"
"github.com/rootless-containers/rootlesskit/pkg/port"
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/msg"
)
func
Run
(
socketPath
string
,
spec
port
.
Spec
,
stopCh
<-
chan
struct
{},
logWriter
io
.
Writer
)
error
{
ln
,
err
:=
net
.
Listen
(
"tcp"
,
fmt
.
Sprintf
(
"%s:%d"
,
spec
.
ParentIP
,
spec
.
ParentPort
))
if
err
!=
nil
{
fmt
.
Fprintf
(
logWriter
,
"listen: %v
\n
"
,
err
)
return
err
}
newConns
:=
make
(
chan
net
.
Conn
)
go
func
()
{
for
{
c
,
err
:=
ln
.
Accept
()
if
err
!=
nil
{
fmt
.
Fprintf
(
logWriter
,
"accept: %v
\n
"
,
err
)
close
(
newConns
)
return
}
newConns
<-
c
}
}()
go
func
()
{
defer
ln
.
Close
()
for
{
select
{
case
c
,
ok
:=
<-
newConns
:
if
!
ok
{
return
}
go
func
()
{
if
err
:=
copyConnToChild
(
c
,
socketPath
,
spec
,
stopCh
);
err
!=
nil
{
fmt
.
Fprintf
(
logWriter
,
"copyConnToChild: %v
\n
"
,
err
)
return
}
}()
case
<-
stopCh
:
return
}
}
}()
// no wait
return
nil
}
func
copyConnToChild
(
c
net
.
Conn
,
socketPath
string
,
spec
port
.
Spec
,
stopCh
<-
chan
struct
{})
error
{
defer
c
.
Close
()
// get fd from the child as an SCM_RIGHTS cmsg
fd
,
err
:=
msg
.
ConnectToChildWithRetry
(
socketPath
,
spec
,
10
)
if
err
!=
nil
{
return
err
}
f
:=
os
.
NewFile
(
uintptr
(
fd
),
""
)
defer
f
.
Close
()
fc
,
err
:=
net
.
FileConn
(
f
)
if
err
!=
nil
{
return
err
}
defer
fc
.
Close
()
bicopy
(
c
,
fc
,
stopCh
)
return
nil
}
// bicopy is based on libnetwork/cmd/proxy/tcp_proxy.go .
// NOTE: sendfile(2) cannot be used for sockets
func
bicopy
(
x
,
y
net
.
Conn
,
quit
<-
chan
struct
{})
{
var
wg
sync
.
WaitGroup
var
broker
=
func
(
to
,
from
net
.
Conn
)
{
io
.
Copy
(
to
,
from
)
if
fromTCP
,
ok
:=
from
.
(
*
net
.
TCPConn
);
ok
{
fromTCP
.
CloseRead
()
}
if
toTCP
,
ok
:=
to
.
(
*
net
.
TCPConn
);
ok
{
toTCP
.
CloseWrite
()
}
wg
.
Done
()
}
wg
.
Add
(
2
)
go
broker
(
x
,
y
)
go
broker
(
y
,
x
)
finish
:=
make
(
chan
struct
{})
go
func
()
{
wg
.
Wait
()
close
(
finish
)
}()
select
{
case
<-
quit
:
case
<-
finish
:
}
x
.
Close
()
y
.
Close
()
<-
finish
}
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udp.go
0 → 100644
View file @
8c9ed8e1
package
udp
import
(
"fmt"
"io"
"net"
"os"
"github.com/pkg/errors"
"github.com/rootless-containers/rootlesskit/pkg/port"
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/msg"
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udpproxy"
)
func
Run
(
socketPath
string
,
spec
port
.
Spec
,
stopCh
<-
chan
struct
{},
logWriter
io
.
Writer
)
error
{
addr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
fmt
.
Sprintf
(
"%s:%d"
,
spec
.
ParentIP
,
spec
.
ParentPort
))
if
err
!=
nil
{
return
err
}
c
,
err
:=
net
.
ListenUDP
(
"udp"
,
addr
)
if
err
!=
nil
{
return
err
}
udpp
:=
&
udpproxy
.
UDPProxy
{
LogWriter
:
logWriter
,
Listener
:
c
,
BackendDial
:
func
()
(
*
net
.
UDPConn
,
error
)
{
// get fd from the child as an SCM_RIGHTS cmsg
fd
,
err
:=
msg
.
ConnectToChildWithRetry
(
socketPath
,
spec
,
10
)
if
err
!=
nil
{
return
nil
,
err
}
f
:=
os
.
NewFile
(
uintptr
(
fd
),
""
)
defer
f
.
Close
()
fc
,
err
:=
net
.
FileConn
(
f
)
if
err
!=
nil
{
return
nil
,
err
}
uc
,
ok
:=
fc
.
(
*
net
.
UDPConn
)
if
!
ok
{
return
nil
,
errors
.
Errorf
(
"file conn doesn't implement *net.UDPConn: %+v"
,
fc
)
}
return
uc
,
nil
},
}
go
udpp
.
Run
()
go
func
()
{
for
{
select
{
case
<-
stopCh
:
// udpp.Close closes ln as well
udpp
.
Close
()
return
}
}
}()
// no wait
return
nil
}
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udpproxy/udp_proxy.go
0 → 100644
View file @
8c9ed8e1
// Package udpproxy is from https://raw.githubusercontent.com/docker/libnetwork/fec6476dfa21380bf8ee4d74048515d968c1ee63/cmd/proxy/udp_proxy.go
package
udpproxy
import
(
"encoding/binary"
"fmt"
"io"
"net"
"strings"
"sync"
"syscall"
"time"
)
const
(
// UDPConnTrackTimeout is the timeout used for UDP connection tracking
UDPConnTrackTimeout
=
90
*
time
.
Second
// UDPBufSize is the buffer size for the UDP proxy
UDPBufSize
=
65507
)
// A net.Addr where the IP is split into two fields so you can use it as a key
// in a map:
type
connTrackKey
struct
{
IPHigh
uint64
IPLow
uint64
Port
int
}
func
newConnTrackKey
(
addr
*
net
.
UDPAddr
)
*
connTrackKey
{
if
len
(
addr
.
IP
)
==
net
.
IPv4len
{
return
&
connTrackKey
{
IPHigh
:
0
,
IPLow
:
uint64
(
binary
.
BigEndian
.
Uint32
(
addr
.
IP
)),
Port
:
addr
.
Port
,
}
}
return
&
connTrackKey
{
IPHigh
:
binary
.
BigEndian
.
Uint64
(
addr
.
IP
[
:
8
]),
IPLow
:
binary
.
BigEndian
.
Uint64
(
addr
.
IP
[
8
:
]),
Port
:
addr
.
Port
,
}
}
type
connTrackMap
map
[
connTrackKey
]
*
net
.
UDPConn
// UDPProxy is proxy for which handles UDP datagrams.
// From libnetwork udp_proxy.go .
type
UDPProxy
struct
{
LogWriter
io
.
Writer
Listener
*
net
.
UDPConn
BackendDial
func
()
(
*
net
.
UDPConn
,
error
)
connTrackTable
connTrackMap
connTrackLock
sync
.
Mutex
}
func
(
proxy
*
UDPProxy
)
replyLoop
(
proxyConn
*
net
.
UDPConn
,
clientAddr
*
net
.
UDPAddr
,
clientKey
*
connTrackKey
)
{
defer
func
()
{
proxy
.
connTrackLock
.
Lock
()
delete
(
proxy
.
connTrackTable
,
*
clientKey
)
proxy
.
connTrackLock
.
Unlock
()
proxyConn
.
Close
()
}()
readBuf
:=
make
([]
byte
,
UDPBufSize
)
for
{
proxyConn
.
SetReadDeadline
(
time
.
Now
()
.
Add
(
UDPConnTrackTimeout
))
again
:
read
,
err
:=
proxyConn
.
Read
(
readBuf
)
if
err
!=
nil
{
if
err
,
ok
:=
err
.
(
*
net
.
OpError
);
ok
&&
err
.
Err
==
syscall
.
ECONNREFUSED
{
// This will happen if the last write failed
// (e.g: nothing is actually listening on the
// proxied port on the container), ignore it
// and continue until UDPConnTrackTimeout
// expires:
goto
again
}
return
}
for
i
:=
0
;
i
!=
read
;
{
written
,
err
:=
proxy
.
Listener
.
WriteToUDP
(
readBuf
[
i
:
read
],
clientAddr
)
if
err
!=
nil
{
return
}
i
+=
written
}
}
}
// Run starts forwarding the traffic using UDP.
func
(
proxy
*
UDPProxy
)
Run
()
{
proxy
.
connTrackTable
=
make
(
connTrackMap
)
readBuf
:=
make
([]
byte
,
UDPBufSize
)
for
{
read
,
from
,
err
:=
proxy
.
Listener
.
ReadFromUDP
(
readBuf
)
if
err
!=
nil
{
// NOTE: Apparently ReadFrom doesn't return
// ECONNREFUSED like Read do (see comment in
// UDPProxy.replyLoop)
if
!
isClosedError
(
err
)
{
fmt
.
Fprintf
(
proxy
.
LogWriter
,
"Stopping proxy on udp: %v
\n
"
,
err
)
}
break
}
fromKey
:=
newConnTrackKey
(
from
)
proxy
.
connTrackLock
.
Lock
()
proxyConn
,
hit
:=
proxy
.
connTrackTable
[
*
fromKey
]
if
!
hit
{
proxyConn
,
err
=
proxy
.
BackendDial
()
if
err
!=
nil
{
fmt
.
Fprintf
(
proxy
.
LogWriter
,
"Can't proxy a datagram to udp: %v
\n
"
,
err
)
proxy
.
connTrackLock
.
Unlock
()
continue
}
proxy
.
connTrackTable
[
*
fromKey
]
=
proxyConn
go
proxy
.
replyLoop
(
proxyConn
,
from
,
fromKey
)
}
proxy
.
connTrackLock
.
Unlock
()
for
i
:=
0
;
i
!=
read
;
{
written
,
err
:=
proxyConn
.
Write
(
readBuf
[
i
:
read
])
if
err
!=
nil
{
fmt
.
Fprintf
(
proxy
.
LogWriter
,
"Can't proxy a datagram to udp: %v
\n
"
,
err
)
break
}
i
+=
written
}
}
}
// Close stops forwarding the traffic.
func
(
proxy
*
UDPProxy
)
Close
()
{
proxy
.
Listener
.
Close
()
proxy
.
connTrackLock
.
Lock
()
defer
proxy
.
connTrackLock
.
Unlock
()
for
_
,
conn
:=
range
proxy
.
connTrackTable
{
conn
.
Close
()
}
}
func
isClosedError
(
err
error
)
bool
{
/* This comparison is ugly, but unfortunately, net.go doesn't export errClosing.
* See:
* http://golang.org/src/pkg/net/net.go
* https://code.google.com/p/go/issues/detail?id=4337
* https://groups.google.com/forum/#!msg/golang-nuts/0_aaCvBmOcM/SptmDyX1XJMJ
*/
return
strings
.
HasSuffix
(
err
.
Error
(),
"use of closed network connection"
)
}
vendor/modules.txt
View file @
8c9ed8e1
...
@@ -383,7 +383,6 @@ github.com/docker/docker/api/types/volume
...
@@ -383,7 +383,6 @@ github.com/docker/docker/api/types/volume
github.com/docker/docker/client
github.com/docker/docker/client
github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog
github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog
github.com/docker/docker/errdefs
github.com/docker/docker/errdefs
github.com/docker/docker/pkg/idtools
github.com/docker/docker/pkg/jsonmessage
github.com/docker/docker/pkg/jsonmessage
github.com/docker/docker/pkg/longpath
github.com/docker/docker/pkg/longpath
github.com/docker/docker/pkg/mount
github.com/docker/docker/pkg/mount
...
@@ -774,7 +773,7 @@ github.com/rancher/wrangler-api/pkg/generated/controllers/rbac
...
@@ -774,7 +773,7 @@ github.com/rancher/wrangler-api/pkg/generated/controllers/rbac
github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1
github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1
# github.com/robfig/cron v1.1.0
# github.com/robfig/cron v1.1.0
github.com/robfig/cron
github.com/robfig/cron
# github.com/rootless-containers/rootlesskit v0.
6.0
# github.com/rootless-containers/rootlesskit v0.
7.2
github.com/rootless-containers/rootlesskit/pkg/api/client
github.com/rootless-containers/rootlesskit/pkg/api/client
github.com/rootless-containers/rootlesskit/pkg/api/router
github.com/rootless-containers/rootlesskit/pkg/api/router
github.com/rootless-containers/rootlesskit/pkg/child
github.com/rootless-containers/rootlesskit/pkg/child
...
@@ -787,8 +786,16 @@ github.com/rootless-containers/rootlesskit/pkg/network/iputils
...
@@ -787,8 +786,16 @@ github.com/rootless-containers/rootlesskit/pkg/network/iputils
github.com/rootless-containers/rootlesskit/pkg/network/parentutils
github.com/rootless-containers/rootlesskit/pkg/network/parentutils
github.com/rootless-containers/rootlesskit/pkg/network/slirp4netns
github.com/rootless-containers/rootlesskit/pkg/network/slirp4netns
github.com/rootless-containers/rootlesskit/pkg/parent
github.com/rootless-containers/rootlesskit/pkg/parent
github.com/rootless-containers/rootlesskit/pkg/parent/idtools
github.com/rootless-containers/rootlesskit/pkg/port
github.com/rootless-containers/rootlesskit/pkg/port
github.com/rootless-containers/rootlesskit/pkg/port/builtin
github.com/rootless-containers/rootlesskit/pkg/port/builtin
github.com/rootless-containers/rootlesskit/pkg/port/builtin/child
github.com/rootless-containers/rootlesskit/pkg/port/builtin/msg
github.com/rootless-containers/rootlesskit/pkg/port/builtin/opaque
github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent
github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/tcp
github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp
github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udpproxy
github.com/rootless-containers/rootlesskit/pkg/port/portutil
github.com/rootless-containers/rootlesskit/pkg/port/portutil
# github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c
# github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c
github.com/rubiojr/go-vhd/vhd
github.com/rubiojr/go-vhd/vhd
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment