Add new field to libpod to indicate whether or not to use labelling

Also update some missing fields libpod.conf obtions in man pages.

Fix sort order of security options and add a note about disabling
labeling.

When a process requests a new label.  libpod needs to reserve all
labels to make sure that their are no conflicts.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>

Closes: #1406
Approved by: mheon
This commit is contained in:
Daniel J Walsh 2018-09-18 09:06:40 -04:00 committed by Atomic Bot
parent 2cbb8c216a
commit fbfcc7842e
11 changed files with 84 additions and 25 deletions

View File

@ -317,7 +317,7 @@ func parseSecurityOpt(config *cc.CreateConfig, securityOpts []string) error {
}
}
}
config.ProcessLabel, config.MountLabel, err = label.InitLabels(labelOpts)
config.LabelOpts = labelOpts
return err
}

View File

@ -59,6 +59,9 @@ libpod to manage containers.
The default namespace is "", which corresponds to no namespace. When no namespace is set, all
containers and pods are visible.
**label**="true|false"
Indicates whether the containers should use label separation.
## FILES
`/usr/share/containers/libpod.conf`, default libpod configuration path

View File

@ -506,6 +506,8 @@ Security Options
"seccomp=unconfined" : Turn off seccomp confinement for the container
"seccomp=profile.json : White listed syscalls seccomp Json file to be used as a seccomp filter
Note: Labelling can be disabled for all containers by setting label=false in the **libpod.conf** (`/etc/containers/libpod.conf`) file.
**--shm-size**=""
Size of `/dev/shm`. The format is `<number><unit>`. `number` must be greater than `0`.
@ -736,7 +738,7 @@ $ podman create --uidmap 0:30000:7000 --gidmap 0:30000:7000 fedora echo hello
**/etc/subgid**
## SEE ALSO
subgid(5), subuid(5)
subgid(5), subuid(5), libpod.conf(5)
## HISTORY
October 2017, converted from Docker documentation to podman by Dan Walsh for podman <dwalsh@redhat.com>

View File

@ -528,6 +528,8 @@ Security Options
- `seccomp=unconfined` : Turn off seccomp confinement for the container
- `seccomp=profile.json` : White listed syscalls seccomp Json file to be used as a seccomp filter
Note: Labelling can be disabled for all containers by setting label=false in the **libpod.conf** (`/etc/containers/libpod.conf`) file.
**--shm-size**=""
Size of `/dev/shm`. The format is `<number><unit>`. `number` must be greater than `0`.
@ -1025,7 +1027,7 @@ $ podman run --uidmap 0:30000:7000 --gidmap 0:30000:7000 fedora echo hello
**/etc/subgid**
## SEE ALSO
subgid(5), subuid(5)
subgid(5), subuid(5), libpod.conf(5)
## HISTORY
October 2017, converted from Docker documentation to podman by Dan Walsh for podman <dwalsh@redhat.com>

View File

@ -88,3 +88,6 @@ pause_command = "/pause"
# significant memory usage if a container has many ports forwarded to it.
# Disabling this can save memory.
#enable_port_reservation = true
# Default libpod support for container labeling
# label=true

View File

@ -98,6 +98,28 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
}
}
// Check if the spec file mounts contain the label Relabel flags z or Z.
// If they do, relabel the source directory and then remove the option.
for _, m := range g.Mounts() {
var options []string
for _, o := range m.Options {
switch o {
case "z":
fallthrough
case "Z":
if err := label.Relabel(m.Source, c.MountLabel(), label.IsShared(o)); err != nil {
return nil, errors.Wrapf(err, "relabel failed %q", m.Source)
}
default:
options = append(options, o)
}
}
m.Options = options
}
g.SetProcessSelinuxLabel(c.ProcessLabel())
g.SetLinuxMountLabel(c.MountLabel())
// Remove the default /dev/shm mount to ensure we overwrite it
g.RemoveMount("/dev/shm")

View File

@ -373,15 +373,17 @@ func WithPrivileged(privileged bool) CtrCreateOption {
}
}
// WithSELinuxLabels sets the mount label for SELinux.
func WithSELinuxLabels(processLabel, mountLabel string) CtrCreateOption {
// WithSecLabels sets the labels for SELinux.
func WithSecLabels(labelOpts []string) CtrCreateOption {
return func(ctr *Container) error {
if ctr.valid {
return ErrCtrFinalized
}
ctr.config.ProcessLabel = processLabel
ctr.config.MountLabel = mountLabel
var err error
ctr.config.ProcessLabel, ctr.config.MountLabel, err = ctr.runtime.initLabels(labelOpts)
if err != nil {
return errors.Wrapf(err, "failed to init labels")
}
return nil
}
}

View File

@ -172,6 +172,8 @@ type RuntimeConfig struct {
// However, this can cause significant memory usage if a container has
// many ports forwarded to it. Disabling this can save memory.
EnablePortReservation bool `toml:"enable_port_reservation"`
// EnableLabeling indicates wether libpod will support container labeling
EnableLabeling bool `toml:"label"`
}
var (
@ -209,6 +211,7 @@ var (
InfraCommand: DefaultInfraCommand,
InfraImage: DefaultInfraImage,
EnablePortReservation: true,
EnableLabeling: true,
}
)

View File

@ -11,6 +11,7 @@ import (
"github.com/containers/storage"
"github.com/containers/storage/pkg/stringid"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/ulule/deepcopier"
@ -77,6 +78,7 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options ..
ctr.config.Namespace = r.config.Namespace
}
ctr.runtime = r
for _, option := range options {
if err := option(ctr); err != nil {
return nil, errors.Wrapf(err, "error running container create option")
@ -85,7 +87,6 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options ..
ctr.valid = true
ctr.state.State = ContainerStateConfigured
ctr.runtime = r
var pod *Pod
if ctr.config.Pod != "" {
@ -327,6 +328,10 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool)
}
}
if r.config.EnableLabeling {
label.ReleaseLabel(c.ProcessLabel())
r.reserveLabels()
}
// Delete the container
// Only do this if we're not ContainerStateConfigured - if we are,
// we haven't been created in the runtime yet
@ -460,3 +465,28 @@ func (r *Runtime) GetLatestContainer() (*Container, error) {
}
return ctrs[lastCreatedIndex], nil
}
// reserveLabels walks the list o fcontainers and reserves the label, so new containers will not
// get them.
// TODO Performance wise this should only run if the state has changed since the last time it was run.
func (r *Runtime) reserveLabels() error {
containers, err := r.state.AllContainers()
if err != nil {
return err
}
for _, ctr := range containers {
label.ReserveLabel(ctr.ProcessLabel())
}
return nil
}
// initLabels allocates an new label to return to the caller
func (r *Runtime) initLabels(labelOpts []string) (string, string, error) {
if !r.config.EnableLabeling {
return "", "", nil
}
if err := r.reserveLabels(); err != nil {
return "", "", errors.Wrapf(err, "unable to reserve labels")
}
return label.InitLabels(labelOpts)
}

View File

@ -15,7 +15,6 @@ import (
"github.com/docker/go-connections/nat"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
@ -126,12 +125,11 @@ type CreateConfig struct {
UtsMode namespaces.UTSMode //uts
Volumes []string //volume
VolumesFrom []string
WorkDir string //workdir
MountLabel string //SecurityOpts
ProcessLabel string //SecurityOpts
NoNewPrivs bool //SecurityOpts
ApparmorProfile string //SecurityOpts
SeccompProfilePath string //SecurityOpts
WorkDir string //workdir
LabelOpts []string //SecurityOpts
NoNewPrivs bool //SecurityOpts
ApparmorProfile string //SecurityOpts
SeccompProfilePath string //SecurityOpts
SecurityOpts []string
Rootfs string
LocalVolumes []string //Keeps track of the built-in volumes of container used in the --volumes-from flag
@ -179,14 +177,10 @@ func (c *CreateConfig) GetVolumeMounts(specMounts []spec.Mount) ([]spec.Mount, e
options = append(options, "rw")
}
if foundz {
if err := label.Relabel(spliti[0], c.MountLabel, true); err != nil {
return nil, errors.Wrapf(err, "relabel failed %q", spliti[0])
}
options = append(options, "z")
}
if foundZ {
if err := label.Relabel(spliti[0], c.MountLabel, false); err != nil {
return nil, errors.Wrapf(err, "relabel failed %q", spliti[0])
}
options = append(options, "Z")
}
if rootProp == "" {
options = append(options, "rprivate")
@ -449,7 +443,7 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib
useImageVolumes := c.ImageVolumeType == "bind"
// Gather up the options for NewContainer which consist of With... funcs
options = append(options, libpod.WithRootFSFromImage(c.ImageID, c.Image, useImageVolumes))
options = append(options, libpod.WithSELinuxLabels(c.ProcessLabel, c.MountLabel))
options = append(options, libpod.WithSecLabels(c.LabelOpts))
options = append(options, libpod.WithConmonPidFile(c.ConmonPidFile))
options = append(options, libpod.WithLabels(c.Labels))
options = append(options, libpod.WithUser(c.User))

View File

@ -211,8 +211,6 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint
// SECURITY OPTS
g.SetProcessNoNewPrivileges(config.NoNewPrivs)
g.SetProcessApparmorProfile(config.ApparmorProfile)
g.SetProcessSelinuxLabel(config.ProcessLabel)
g.SetLinuxMountLabel(config.MountLabel)
if canAddResources {
blockAccessToKernelFilesystems(config, &g)