Merge pull request #47 from rhatdan/master
Allow caller to change the SELinux labels on a directory tree.
This commit is contained in:
commit
48b2a41d76
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue