...

Source file src/github.com/opencontainers/selinux/go-selinux/label/label_linux.go

Documentation: github.com/opencontainers/selinux/go-selinux/label

     1  package label
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/opencontainers/selinux/go-selinux"
     9  )
    10  
    11  // Valid Label Options
    12  var validOptions = map[string]bool{
    13  	"disable":  true,
    14  	"type":     true,
    15  	"filetype": true,
    16  	"user":     true,
    17  	"role":     true,
    18  	"level":    true,
    19  }
    20  
    21  var ErrIncompatibleLabel = errors.New("Bad SELinux option z and Z can not be used together")
    22  
    23  // InitLabels returns the process label and file labels to be used within
    24  // the container.  A list of options can be passed into this function to alter
    25  // the labels.  The labels returned will include a random MCS String, that is
    26  // guaranteed to be unique.
    27  // If the disabled flag is passed in, the process label will not be set, but the mount label will be set
    28  // to the container_file label with the maximum category. This label is not usable by any confined label.
    29  func InitLabels(options []string) (plabel string, mlabel string, retErr error) {
    30  	if !selinux.GetEnabled() {
    31  		return "", "", nil
    32  	}
    33  	processLabel, mountLabel := selinux.ContainerLabels()
    34  	if processLabel != "" {
    35  		defer func() {
    36  			if retErr != nil {
    37  				selinux.ReleaseLabel(mountLabel)
    38  			}
    39  		}()
    40  		pcon, err := selinux.NewContext(processLabel)
    41  		if err != nil {
    42  			return "", "", err
    43  		}
    44  		mcsLevel := pcon["level"]
    45  		mcon, err := selinux.NewContext(mountLabel)
    46  		if err != nil {
    47  			return "", "", err
    48  		}
    49  		for _, opt := range options {
    50  			if opt == "disable" {
    51  				selinux.ReleaseLabel(mountLabel)
    52  				return "", selinux.PrivContainerMountLabel(), nil
    53  			}
    54  			if i := strings.Index(opt, ":"); i == -1 {
    55  				return "", "", fmt.Errorf("Bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt)
    56  			}
    57  			con := strings.SplitN(opt, ":", 2)
    58  			if !validOptions[con[0]] {
    59  				return "", "", fmt.Errorf("Bad label option %q, valid options 'disable, user, role, level, type, filetype'", con[0])
    60  			}
    61  			if con[0] == "filetype" {
    62  				mcon["type"] = con[1]
    63  				continue
    64  			}
    65  			pcon[con[0]] = con[1]
    66  			if con[0] == "level" || con[0] == "user" {
    67  				mcon[con[0]] = con[1]
    68  			}
    69  		}
    70  		if pcon.Get() != processLabel {
    71  			if pcon["level"] != mcsLevel {
    72  				selinux.ReleaseLabel(processLabel)
    73  			}
    74  			processLabel = pcon.Get()
    75  			selinux.ReserveLabel(processLabel)
    76  		}
    77  		mountLabel = mcon.Get()
    78  	}
    79  	return processLabel, mountLabel, nil
    80  }
    81  
    82  // Deprecated: The GenLabels function is only to be used during the transition
    83  // to the official API. Use InitLabels(strings.Fields(options)) instead.
    84  func GenLabels(options string) (string, string, error) {
    85  	return InitLabels(strings.Fields(options))
    86  }
    87  
    88  // SetFileLabel modifies the "path" label to the specified file label
    89  func SetFileLabel(path string, fileLabel string) error {
    90  	if !selinux.GetEnabled() || fileLabel == "" {
    91  		return nil
    92  	}
    93  	return selinux.SetFileLabel(path, fileLabel)
    94  }
    95  
    96  // SetFileCreateLabel tells the kernel the label for all files to be created
    97  func SetFileCreateLabel(fileLabel string) error {
    98  	if !selinux.GetEnabled() {
    99  		return nil
   100  	}
   101  	return selinux.SetFSCreateLabel(fileLabel)
   102  }
   103  
   104  // Relabel changes the label of path and all the entries beneath the path.
   105  // It changes the MCS label to s0 if shared is true.
   106  // This will allow all containers to share the content.
   107  //
   108  // The path itself is guaranteed to be relabeled last.
   109  func Relabel(path string, fileLabel string, shared bool) error {
   110  	if !selinux.GetEnabled() || fileLabel == "" {
   111  		return nil
   112  	}
   113  
   114  	if shared {
   115  		c, err := selinux.NewContext(fileLabel)
   116  		if err != nil {
   117  			return err
   118  		}
   119  
   120  		c["level"] = "s0"
   121  		fileLabel = c.Get()
   122  	}
   123  	if err := selinux.Chcon(path, fileLabel, true); err != nil {
   124  		return err
   125  	}
   126  	return nil
   127  }
   128  
   129  // DisableSecOpt returns a security opt that can disable labeling
   130  // support for future container processes
   131  // Deprecated: use selinux.DisableSecOpt
   132  var DisableSecOpt = selinux.DisableSecOpt
   133  
   134  // Validate checks that the label does not include unexpected options
   135  func Validate(label string) error {
   136  	if strings.Contains(label, "z") && strings.Contains(label, "Z") {
   137  		return ErrIncompatibleLabel
   138  	}
   139  	return nil
   140  }
   141  
   142  // RelabelNeeded checks whether the user requested a relabel
   143  func RelabelNeeded(label string) bool {
   144  	return strings.Contains(label, "z") || strings.Contains(label, "Z")
   145  }
   146  
   147  // IsShared checks that the label includes a "shared" mark
   148  func IsShared(label string) bool {
   149  	return strings.Contains(label, "z")
   150  }
   151  

View as plain text