mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-20 17:49:10 +00:00
Merge pull request #100 from justincormack/userns
Add partial user namespace support
This commit is contained in:
commit
ec7e73b304
@ -158,6 +158,9 @@ bind mounted into a container.
|
|||||||
- `sysctl` sets a list of `sysctl` key value pairs that are set inside the container namespace.
|
- `sysctl` sets a list of `sysctl` key value pairs that are set inside the container namespace.
|
||||||
- `rmlimits` sets a list of `rlimit` values in the form `name,soft,hard`, eg `nofile,100,200`. You can use `unlimited` as a value too.
|
- `rmlimits` sets a list of `rlimit` values in the form `name,soft,hard`, eg `nofile,100,200`. You can use `unlimited` as a value too.
|
||||||
|
|
||||||
|
There are experimental `userns`, `uidMappings` and `gidMappings` options for user namespaces but these are not yet supported, and may have
|
||||||
|
permissions issues in use.
|
||||||
|
|
||||||
### Mount Options
|
### Mount Options
|
||||||
When mounting filesystem paths into a container - whether as part of `onboot` or `services` - there are several options of which you need to be aware. Using them properly is necessary for your containers to function properly.
|
When mounting filesystem paths into a container - whether as part of `onboot` or `services` - there are several options of which you need to be aware. Using them properly is necessary for your containers to function properly.
|
||||||
|
|
||||||
|
@ -51,34 +51,37 @@ type File struct {
|
|||||||
|
|
||||||
// Image is the type of an image config
|
// Image is the type of an image config
|
||||||
type Image struct {
|
type Image struct {
|
||||||
Name string `yaml:"name" json:"name"`
|
Name string `yaml:"name" json:"name"`
|
||||||
Image string `yaml:"image" json:"image"`
|
Image string `yaml:"image" json:"image"`
|
||||||
Capabilities *[]string `yaml:"capabilities" json:"capabilities,omitempty"`
|
Capabilities *[]string `yaml:"capabilities" json:"capabilities,omitempty"`
|
||||||
Ambient *[]string `yaml:"ambient" json:"ambient,omitempty"`
|
Ambient *[]string `yaml:"ambient" json:"ambient,omitempty"`
|
||||||
Mounts *[]specs.Mount `yaml:"mounts" json:"mounts,omitempty"`
|
Mounts *[]specs.Mount `yaml:"mounts" json:"mounts,omitempty"`
|
||||||
Binds *[]string `yaml:"binds" json:"binds,omitempty"`
|
Binds *[]string `yaml:"binds" json:"binds,omitempty"`
|
||||||
Tmpfs *[]string `yaml:"tmpfs" json:"tmpfs,omitempty"`
|
Tmpfs *[]string `yaml:"tmpfs" json:"tmpfs,omitempty"`
|
||||||
Command *[]string `yaml:"command" json:"command,omitempty"`
|
Command *[]string `yaml:"command" json:"command,omitempty"`
|
||||||
Env *[]string `yaml:"env" json:"env,omitempty"`
|
Env *[]string `yaml:"env" json:"env,omitempty"`
|
||||||
Cwd string `yaml:"cwd" json:"cwd"`
|
Cwd string `yaml:"cwd" json:"cwd"`
|
||||||
Net string `yaml:"net" json:"net"`
|
Net string `yaml:"net" json:"net"`
|
||||||
Pid string `yaml:"pid" json:"pid"`
|
Pid string `yaml:"pid" json:"pid"`
|
||||||
Ipc string `yaml:"ipc" json:"ipc"`
|
Ipc string `yaml:"ipc" json:"ipc"`
|
||||||
Uts string `yaml:"uts" json:"uts"`
|
Uts string `yaml:"uts" json:"uts"`
|
||||||
Hostname string `yaml:"hostname" json:"hostname"`
|
Userns string `yaml:"userns" json:"userns"`
|
||||||
Readonly *bool `yaml:"readonly" json:"readonly,omitempty"`
|
Hostname string `yaml:"hostname" json:"hostname"`
|
||||||
MaskedPaths *[]string `yaml:"maskedPaths" json:"maskedPaths,omitempty"`
|
Readonly *bool `yaml:"readonly" json:"readonly,omitempty"`
|
||||||
ReadonlyPaths *[]string `yaml:"readonlyPaths" json:"readonlyPaths,omitempty"`
|
MaskedPaths *[]string `yaml:"maskedPaths" json:"maskedPaths,omitempty"`
|
||||||
UID *string `yaml:"uid" json:"uid,omitempty"`
|
ReadonlyPaths *[]string `yaml:"readonlyPaths" json:"readonlyPaths,omitempty"`
|
||||||
GID *string `yaml:"gid" json:"gid,omitempty"`
|
UID *string `yaml:"uid" json:"uid,omitempty"`
|
||||||
AdditionalGids *[]string `yaml:"additionalGids" json:"additionalGids,omitempty"`
|
GID *string `yaml:"gid" json:"gid,omitempty"`
|
||||||
NoNewPrivileges *bool `yaml:"noNewPrivileges" json:"noNewPrivileges,omitempty"`
|
AdditionalGids *[]string `yaml:"additionalGids" json:"additionalGids,omitempty"`
|
||||||
OOMScoreAdj *int `yaml:"oomScoreAdj" json:"oomScoreAdj,omitempty"`
|
NoNewPrivileges *bool `yaml:"noNewPrivileges" json:"noNewPrivileges,omitempty"`
|
||||||
DisableOOMKiller *bool `yaml:"disableOOMKiller" json:"disableOOMKiller,omitempty"`
|
OOMScoreAdj *int `yaml:"oomScoreAdj" json:"oomScoreAdj,omitempty"`
|
||||||
RootfsPropagation *string `yaml:"rootfsPropagation" json:"rootfsPropagation,omitempty"`
|
DisableOOMKiller *bool `yaml:"disableOOMKiller" json:"disableOOMKiller,omitempty"`
|
||||||
CgroupsPath *string `yaml:"cgroupsPath" json:"cgroupsPath,omitempty"`
|
RootfsPropagation *string `yaml:"rootfsPropagation" json:"rootfsPropagation,omitempty"`
|
||||||
Sysctl *map[string]string `yaml:"sysctl" json:"sysctl,omitempty"`
|
CgroupsPath *string `yaml:"cgroupsPath" json:"cgroupsPath,omitempty"`
|
||||||
Rlimits *[]string `yaml:"rlimits" json:"rlimits,omitempty"`
|
Sysctl *map[string]string `yaml:"sysctl" json:"sysctl,omitempty"`
|
||||||
|
Rlimits *[]string `yaml:"rlimits" json:"rlimits,omitempty"`
|
||||||
|
UIDMappings *[]specs.LinuxIDMapping `yaml:"uidMappings" json:"uidMappings,omitempty"`
|
||||||
|
GIDMappings *[]specs.LinuxIDMapping `yaml:"gidMappings" json:"gidMappings,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// github.com/go-yaml/yaml treats map keys as interface{} while encoding/json
|
// github.com/go-yaml/yaml treats map keys as interface{} while encoding/json
|
||||||
@ -390,6 +393,17 @@ func assignString(v1, v2 *string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assignMappings does prdered overrides from UID, GID maps
|
||||||
|
func assignMappings(v1, v2 *[]specs.LinuxIDMapping) []specs.LinuxIDMapping {
|
||||||
|
if v2 != nil {
|
||||||
|
return *v2
|
||||||
|
}
|
||||||
|
if v1 != nil {
|
||||||
|
return *v1
|
||||||
|
}
|
||||||
|
return []specs.LinuxIDMapping{}
|
||||||
|
}
|
||||||
|
|
||||||
// assignStringEmpty does ordered overrides if strings are empty, for
|
// assignStringEmpty does ordered overrides if strings are empty, for
|
||||||
// values where there is always an explicit override eg "none"
|
// values where there is always an explicit override eg "none"
|
||||||
func assignStringEmpty(v1, v2 string) string {
|
func assignStringEmpty(v1, v2 string) string {
|
||||||
@ -604,7 +618,7 @@ func ConfigInspectToOCI(yaml Image, inspect types.ImageInspect, idMap map[string
|
|||||||
namespaces := []specs.LinuxNamespace{}
|
namespaces := []specs.LinuxNamespace{}
|
||||||
// to attach to an existing namespace, easiest to bind mount with nsfs in a system container
|
// to attach to an existing namespace, easiest to bind mount with nsfs in a system container
|
||||||
|
|
||||||
// net, ipc and uts namespaces: default to not creating a new namespace (usually host namespace)
|
// net, ipc, and uts namespaces: default to not creating a new namespace (usually host namespace)
|
||||||
netNS := assignStringEmpty3("root", label.Net, yaml.Net)
|
netNS := assignStringEmpty3("root", label.Net, yaml.Net)
|
||||||
if netNS != "host" && netNS != "root" {
|
if netNS != "host" && netNS != "root" {
|
||||||
if netNS == "none" || netNS == "new" {
|
if netNS == "none" || netNS == "new" {
|
||||||
@ -636,10 +650,19 @@ func ConfigInspectToOCI(yaml Image, inspect types.ImageInspect, idMap map[string
|
|||||||
namespaces = append(namespaces, specs.LinuxNamespace{Type: specs.PIDNamespace, Path: pidNS})
|
namespaces = append(namespaces, specs.LinuxNamespace{Type: specs.PIDNamespace, Path: pidNS})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do not create a user namespace unless asked, needs additional configuration
|
||||||
|
userNS := assignStringEmpty3("root", label.Userns, yaml.Userns)
|
||||||
|
if userNS != "host" && userNS != "root" {
|
||||||
|
if userNS == "new" {
|
||||||
|
userNS = ""
|
||||||
|
}
|
||||||
|
namespaces = append(namespaces, specs.LinuxNamespace{Type: specs.UserNamespace, Path: userNS})
|
||||||
|
}
|
||||||
|
|
||||||
// Always create a new mount namespace
|
// Always create a new mount namespace
|
||||||
namespaces = append(namespaces, specs.LinuxNamespace{Type: specs.MountNamespace})
|
namespaces = append(namespaces, specs.LinuxNamespace{Type: specs.MountNamespace})
|
||||||
|
|
||||||
// TODO user, cgroup namespaces
|
// TODO cgroup namespaces
|
||||||
|
|
||||||
// Capabilities
|
// Capabilities
|
||||||
capCheck := map[string]bool{}
|
capCheck := map[string]bool{}
|
||||||
@ -800,9 +823,9 @@ func ConfigInspectToOCI(yaml Image, inspect types.ImageInspect, idMap map[string
|
|||||||
oci.Mounts = mountList
|
oci.Mounts = mountList
|
||||||
|
|
||||||
oci.Linux = &specs.Linux{
|
oci.Linux = &specs.Linux{
|
||||||
// UIDMappings
|
UIDMappings: assignMappings(label.UIDMappings, yaml.UIDMappings),
|
||||||
// GIDMappings
|
GIDMappings: assignMappings(label.GIDMappings, yaml.GIDMappings),
|
||||||
Sysctl: assignMaps(label.Sysctl, yaml.Sysctl),
|
Sysctl: assignMaps(label.Sysctl, yaml.Sysctl),
|
||||||
Resources: &specs.LinuxResources{
|
Resources: &specs.LinuxResources{
|
||||||
// Devices
|
// Devices
|
||||||
DisableOOMKiller: assignBoolPtr(label.DisableOOMKiller, yaml.DisableOOMKiller),
|
DisableOOMKiller: assignBoolPtr(label.DisableOOMKiller, yaml.DisableOOMKiller),
|
||||||
|
@ -59,6 +59,19 @@ var schema = string(`
|
|||||||
"type": "array",
|
"type": "array",
|
||||||
"items": { "$ref": "#/definitions/mount" }
|
"items": { "$ref": "#/definitions/mount" }
|
||||||
},
|
},
|
||||||
|
"idmapping": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"hostID": { "type": "integer" },
|
||||||
|
"containerID": { "type": "integer" },
|
||||||
|
"size": { "type": "integer" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idmappings": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "$ref": "#/definitions/idmapping" }
|
||||||
|
},
|
||||||
"image": {
|
"image": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
@ -78,6 +91,7 @@ var schema = string(`
|
|||||||
"pid": { "type": "string"},
|
"pid": { "type": "string"},
|
||||||
"ipc": { "type": "string"},
|
"ipc": { "type": "string"},
|
||||||
"uts": { "type": "string"},
|
"uts": { "type": "string"},
|
||||||
|
"userns": { "type": "string"},
|
||||||
"readonly": { "type": "boolean"},
|
"readonly": { "type": "boolean"},
|
||||||
"maskedPaths": { "$ref": "#/definitions/strings" },
|
"maskedPaths": { "$ref": "#/definitions/strings" },
|
||||||
"readonlyPaths": { "$ref": "#/definitions/strings" },
|
"readonlyPaths": { "$ref": "#/definitions/strings" },
|
||||||
@ -97,7 +111,9 @@ var schema = string(`
|
|||||||
"type": "array",
|
"type": "array",
|
||||||
"items": { "$ref": "#/definitions/strings" }
|
"items": { "$ref": "#/definitions/strings" }
|
||||||
},
|
},
|
||||||
"rlimits": { "$ref": "#/definitions/strings" }
|
"rlimits": { "$ref": "#/definitions/strings" },
|
||||||
|
"uidMappings": { "$ref": "#/definitions/idmappings" },
|
||||||
|
"gidMappings": { "$ref": "#/definitions/idmappings" }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"images": {
|
"images": {
|
||||||
|
Loading…
Reference in New Issue
Block a user