Merge pull request #47 from rhatdan/master

Allow caller to change the SELinux labels on a directory tree.
This commit is contained in:
Michael Crosby 2014-07-11 11:19:14 -07:00
commit 48b2a41d76
5 changed files with 73 additions and 4 deletions

View File

@ -18,6 +18,10 @@ func SetFileLabel(path string, fileLabel string) error {
return nil
}
func Relabel(path string, fileLabel string, relabel string) error {
return nil
}
func GetPidCon(pid int) (string, error) {
return "", nil
}

View File

@ -66,6 +66,23 @@ func SetFileLabel(path string, fileLabel string) error {
return nil
}
// Change the label of path to the filelabel string. If the relabel string
// is "z", relabel will change the MCS label to s0. This will allow all
// containers to share the content. If the relabel string is a "Z" then
// the MCS label should continue to be used. SELinux will use this field
// to make sure the content can not be shared by other containes.
func Relabel(path string, fileLabel string, relabel string) error {
if fileLabel == "" {
return nil
}
if relabel == "z" {
c := selinux.NewContext(fileLabel)
c["level"] = "s0"
fileLabel = c.Get()
}
return selinux.Chcon(path, fileLabel, true)
}
func GetPidCon(pid int) (string, error) {
if !selinux.SelinuxEnabled() {
return "", nil

View File

@ -44,7 +44,7 @@ func InitializeMountNamespace(rootfs, console string, mountConfig *MountConfig)
if err := mountSystem(rootfs, mountConfig); err != nil {
return fmt.Errorf("mount system %s", err)
}
if err := setupBindmounts(rootfs, mountConfig.Mounts); err != nil {
if err := setupBindmounts(rootfs, mountConfig); err != nil {
return fmt.Errorf("bind mounts %s", err)
}
if err := nodes.CreateDeviceNodes(rootfs, mountConfig.DeviceNodes); err != nil {
@ -144,7 +144,8 @@ func setupDevSymlinks(rootfs string) error {
return nil
}
func setupBindmounts(rootfs string, bindMounts Mounts) error {
func setupBindmounts(rootfs string, mountConfig *MountConfig) error {
bindMounts := mountConfig.Mounts
for _, m := range bindMounts.OfType("bind") {
var (
flags = syscall.MS_BIND | syscall.MS_REC
@ -176,6 +177,11 @@ func setupBindmounts(rootfs string, bindMounts Mounts) error {
return fmt.Errorf("remounting %s into %s %s", m.Source, dest, err)
}
}
if m.Relabel != "" {
if err := label.Relabel(m.Source, mountConfig.MountLabel, m.Relabel); err != nil {
return fmt.Errorf("relabeling %s to %s %s", m.Source, mountConfig.MountLabel, err)
}
}
if m.Private {
if err := system.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
return fmt.Errorf("mounting %s private %s", dest, err)

View File

@ -30,6 +30,7 @@ type Mount struct {
Source string `json:"source,omitempty"` // Source path, in the host namespace
Destination string `json:"destination,omitempty"` // Destination path, in the container
Writable bool `json:"writable,omitempty"`
Relabel string `json:"relabel,omitempty"` // Relabel source if set, "z" indicates shared, "Z" indicates unshared
Private bool `json:"private,omitempty"`
}

View File

@ -9,6 +9,7 @@ import (
"github.com/dotcloud/docker/pkg/system"
"io"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
@ -76,7 +77,7 @@ func SelinuxEnabled() bool {
}
selinuxEnabledChecked = true
if fs := getSelinuxMountPoint(); fs != "" {
if con, _ := getcon(); con != "kernel" {
if con, _ := Getcon(); con != "kernel" {
selinuxEnabled = true
}
}
@ -145,6 +146,12 @@ func Setfilecon(path string, scon string) error {
return system.Lsetxattr(path, xattrNameSelinux, []byte(scon), 0)
}
// Return the SELinux label for this path
func Getfilecon(path string) (string, error) {
con, err := system.Lgetxattr(path, xattrNameSelinux)
return string(con), err
}
func Setfscreatecon(scon string) error {
return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", system.Gettid()), scon)
}
@ -153,7 +160,8 @@ func Getfscreatecon() (string, error) {
return readCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", system.Gettid()))
}
func getcon() (string, error) {
// Return the SELinux label of the current process thread.
func Getcon() (string, error) {
return readCon(fmt.Sprintf("/proc/self/task/%d/attr/current", system.Gettid()))
}
@ -396,3 +404,36 @@ func CopyLevel(src, dest string) (string, error) {
tcon["level"] = scon["level"]
return tcon.Get(), nil
}
// Prevent users from relabing system files
func badPrefix(fpath string) error {
var badprefixes = []string{"/usr"}
for _, prefix := range badprefixes {
if fpath == prefix || strings.HasPrefix(fpath, fmt.Sprintf("%s/", prefix)) {
return fmt.Errorf("Relabeling content in %s is not allowed.", prefix)
}
}
return nil
}
// Change the fpath file object to the SELinux label scon.
// If the fpath is a directory and recurse is true Chcon will walk the
// directory tree setting the label
func Chcon(fpath string, scon string, recurse bool) error {
if !SelinuxEnabled() {
return nil
}
if err := badPrefix(fpath); err != nil {
return err
}
callback := func(p string, info os.FileInfo, err error) error {
return Setfilecon(p, scon)
}
if recurse {
return filepath.Walk(fpath, callback)
}
return Setfilecon(fpath, scon)
}