github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/runc/libcontainer/label/label_selinux.go (about) 1 // +build selinux,linux 2 3 package label 4 5 import ( 6 "fmt" 7 "strings" 8 9 "github.com/opencontainers/runc/libcontainer/selinux" 10 ) 11 12 // Valid Label Options 13 var validOptions = map[string]bool{ 14 "disable": true, 15 "type": true, 16 "user": true, 17 "role": true, 18 "level": true, 19 } 20 21 var ErrIncompatibleLabel = fmt.Errorf("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 func InitLabels(options []string) (string, string, error) { 28 if !selinux.SelinuxEnabled() { 29 return "", "", nil 30 } 31 processLabel, mountLabel := selinux.GetLxcContexts() 32 if processLabel != "" { 33 pcon := selinux.NewContext(processLabel) 34 mcon := selinux.NewContext(mountLabel) 35 for _, opt := range options { 36 val := strings.SplitN(opt, "=", 2) 37 if val[0] != "label" { 38 continue 39 } 40 if len(val) < 2 { 41 return "", "", fmt.Errorf("bad label option %q, valid options 'disable' or \n'user, role, level, type' followed by ':' and a value", opt) 42 } 43 if val[1] == "disable" { 44 return "", "", nil 45 } 46 con := strings.SplitN(val[1], ":", 2) 47 if len(con) < 2 || !validOptions[con[0]] { 48 return "", "", fmt.Errorf("bad label option %q, valid options 'disable, user, role, level, type'", con[0]) 49 50 } 51 pcon[con[0]] = con[1] 52 if con[0] == "level" || con[0] == "user" { 53 mcon[con[0]] = con[1] 54 } 55 } 56 processLabel = pcon.Get() 57 mountLabel = mcon.Get() 58 } 59 return processLabel, mountLabel, nil 60 } 61 62 func GetROMountLabel() string { 63 return selinux.GetROFileLabel() 64 } 65 66 // DEPRECATED: The GenLabels function is only to be used during the transition to the official API. 67 func GenLabels(options string) (string, string, error) { 68 return InitLabels(strings.Fields(options)) 69 } 70 71 // FormatMountLabel returns a string to be used by the mount command. 72 // The format of this string will be used to alter the labeling of the mountpoint. 73 // The string returned is suitable to be used as the options field of the mount command. 74 // If you need to have additional mount point options, you can pass them in as 75 // the first parameter. Second parameter is the label that you wish to apply 76 // to all content in the mount point. 77 func FormatMountLabel(src, mountLabel string) string { 78 if mountLabel != "" { 79 switch src { 80 case "": 81 src = fmt.Sprintf("context=%q", mountLabel) 82 default: 83 src = fmt.Sprintf("%s,context=%q", src, mountLabel) 84 } 85 } 86 return src 87 } 88 89 // SetProcessLabel takes a process label and tells the kernel to assign the 90 // label to the next program executed by the current process. 91 func SetProcessLabel(processLabel string) error { 92 if processLabel == "" { 93 return nil 94 } 95 return selinux.Setexeccon(processLabel) 96 } 97 98 // GetProcessLabel returns the process label that the kernel will assign 99 // to the next program executed by the current process. If "" is returned 100 // this indicates that the default labeling will happen for the process. 101 func GetProcessLabel() (string, error) { 102 return selinux.Getexeccon() 103 } 104 105 // GetFileLabel returns the label for specified path 106 func GetFileLabel(path string) (string, error) { 107 return selinux.Getfilecon(path) 108 } 109 110 // SetFileLabel modifies the "path" label to the specified file label 111 func SetFileLabel(path string, fileLabel string) error { 112 if selinux.SelinuxEnabled() && fileLabel != "" { 113 return selinux.Setfilecon(path, fileLabel) 114 } 115 return nil 116 } 117 118 // SetFileCreateLabel tells the kernel the label for all files to be created 119 func SetFileCreateLabel(fileLabel string) error { 120 if selinux.SelinuxEnabled() { 121 return selinux.Setfscreatecon(fileLabel) 122 } 123 return nil 124 } 125 126 // Relabel changes the label of path to the filelabel string. 127 // It changes the MCS label to s0 if shared is true. 128 // This will allow all containers to share the content. 129 func Relabel(path string, fileLabel string, shared bool) error { 130 if !selinux.SelinuxEnabled() { 131 return nil 132 } 133 134 if fileLabel == "" { 135 return nil 136 } 137 138 exclude_paths := map[string]bool{"/": true, "/usr": true, "/etc": true} 139 if exclude_paths[path] { 140 return fmt.Errorf("SELinux relabeling of %s is not allowed", path) 141 } 142 143 if shared { 144 c := selinux.NewContext(fileLabel) 145 c["level"] = "s0" 146 fileLabel = c.Get() 147 } 148 if err := selinux.Chcon(path, fileLabel, true); err != nil { 149 return fmt.Errorf("SELinux relabeling of %s is not allowed: %q", path, err) 150 } 151 return nil 152 } 153 154 // GetPidLabel will return the label of the process running with the specified pid 155 func GetPidLabel(pid int) (string, error) { 156 return selinux.Getpidcon(pid) 157 } 158 159 // Init initialises the labeling system 160 func Init() { 161 selinux.SelinuxEnabled() 162 } 163 164 // ReserveLabel will record the fact that the MCS label has already been used. 165 // This will prevent InitLabels from using the MCS label in a newly created 166 // container 167 func ReserveLabel(label string) error { 168 selinux.ReserveLabel(label) 169 return nil 170 } 171 172 // UnreserveLabel will remove the reservation of the MCS label. 173 // This will allow InitLabels to use the MCS label in a newly created 174 // containers 175 func UnreserveLabel(label string) error { 176 selinux.FreeLxcContexts(label) 177 return nil 178 } 179 180 // DupSecOpt takes an process label and returns security options that 181 // can be used to set duplicate labels on future container processes 182 func DupSecOpt(src string) []string { 183 return selinux.DupSecOpt(src) 184 } 185 186 // DisableSecOpt returns a security opt that can disable labeling 187 // support for future container processes 188 func DisableSecOpt() []string { 189 return selinux.DisableSecOpt() 190 } 191 192 // Validate checks that the label does not include unexpected options 193 func Validate(label string) error { 194 if strings.Contains(label, "z") && strings.Contains(label, "Z") { 195 return ErrIncompatibleLabel 196 } 197 return nil 198 } 199 200 // RelabelNeeded checks whether the user requested a relabel 201 func RelabelNeeded(label string) bool { 202 return strings.Contains(label, "z") || strings.Contains(label, "Z") 203 } 204 205 // IsShared checks that the label includes a "shared" mark 206 func IsShared(label string) bool { 207 return strings.Contains(label, "z") 208 }