selinux.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. package selinux
  2. import (
  3. "errors"
  4. )
  5. const (
  6. // Enforcing constant indicate SELinux is in enforcing mode
  7. Enforcing = 1
  8. // Permissive constant to indicate SELinux is in permissive mode
  9. Permissive = 0
  10. // Disabled constant to indicate SELinux is disabled
  11. Disabled = -1
  12. // maxCategory is the maximum number of categories used within containers
  13. maxCategory = 1024
  14. // DefaultCategoryRange is the upper bound on the category range
  15. DefaultCategoryRange = uint32(maxCategory)
  16. )
  17. var (
  18. // ErrMCSAlreadyExists is returned when trying to allocate a duplicate MCS.
  19. ErrMCSAlreadyExists = errors.New("MCS label already exists")
  20. // ErrEmptyPath is returned when an empty path has been specified.
  21. ErrEmptyPath = errors.New("empty path")
  22. // ErrInvalidLabel is returned when an invalid label is specified.
  23. ErrInvalidLabel = errors.New("invalid Label")
  24. // InvalidLabel is returned when an invalid label is specified.
  25. //
  26. // Deprecated: use [ErrInvalidLabel].
  27. InvalidLabel = ErrInvalidLabel
  28. // ErrIncomparable is returned two levels are not comparable
  29. ErrIncomparable = errors.New("incomparable levels")
  30. // ErrLevelSyntax is returned when a sensitivity or category do not have correct syntax in a level
  31. ErrLevelSyntax = errors.New("invalid level syntax")
  32. // ErrContextMissing is returned if a requested context is not found in a file.
  33. ErrContextMissing = errors.New("context does not have a match")
  34. // ErrVerifierNil is returned when a context verifier function is nil.
  35. ErrVerifierNil = errors.New("verifier function is nil")
  36. // CategoryRange allows the upper bound on the category range to be adjusted
  37. CategoryRange = DefaultCategoryRange
  38. privContainerMountLabel string
  39. )
  40. // Context is a representation of the SELinux label broken into 4 parts
  41. type Context map[string]string
  42. // SetDisabled disables SELinux support for the package
  43. func SetDisabled() {
  44. setDisabled()
  45. }
  46. // GetEnabled returns whether SELinux is currently enabled.
  47. func GetEnabled() bool {
  48. return getEnabled()
  49. }
  50. // ClassIndex returns the int index for an object class in the loaded policy,
  51. // or -1 and an error
  52. func ClassIndex(class string) (int, error) {
  53. return classIndex(class)
  54. }
  55. // SetFileLabel sets the SELinux label for this path, following symlinks,
  56. // or returns an error.
  57. func SetFileLabel(fpath string, label string) error {
  58. return setFileLabel(fpath, label)
  59. }
  60. // LsetFileLabel sets the SELinux label for this path, not following symlinks,
  61. // or returns an error.
  62. func LsetFileLabel(fpath string, label string) error {
  63. return lSetFileLabel(fpath, label)
  64. }
  65. // FileLabel returns the SELinux label for this path, following symlinks,
  66. // or returns an error.
  67. func FileLabel(fpath string) (string, error) {
  68. return fileLabel(fpath)
  69. }
  70. // LfileLabel returns the SELinux label for this path, not following symlinks,
  71. // or returns an error.
  72. func LfileLabel(fpath string) (string, error) {
  73. return lFileLabel(fpath)
  74. }
  75. // SetFSCreateLabel tells the kernel what label to use for all file system objects
  76. // created by this task.
  77. // Set the label to an empty string to return to the default label. Calls to SetFSCreateLabel
  78. // should be wrapped in runtime.LockOSThread()/runtime.UnlockOSThread() until file system
  79. // objects created by this task are finished to guarantee another goroutine does not migrate
  80. // to the current thread before execution is complete.
  81. func SetFSCreateLabel(label string) error {
  82. return setFSCreateLabel(label)
  83. }
  84. // FSCreateLabel returns the default label the kernel which the kernel is using
  85. // for file system objects created by this task. "" indicates default.
  86. func FSCreateLabel() (string, error) {
  87. return fsCreateLabel()
  88. }
  89. // CurrentLabel returns the SELinux label of the current process thread, or an error.
  90. func CurrentLabel() (string, error) {
  91. return currentLabel()
  92. }
  93. // PidLabel returns the SELinux label of the given pid, or an error.
  94. func PidLabel(pid int) (string, error) {
  95. return pidLabel(pid)
  96. }
  97. // ExecLabel returns the SELinux label that the kernel will use for any programs
  98. // that are executed by the current process thread, or an error.
  99. func ExecLabel() (string, error) {
  100. return execLabel()
  101. }
  102. // CanonicalizeContext takes a context string and writes it to the kernel
  103. // the function then returns the context that the kernel will use. Use this
  104. // function to check if two contexts are equivalent
  105. func CanonicalizeContext(val string) (string, error) {
  106. return canonicalizeContext(val)
  107. }
  108. // ComputeCreateContext requests the type transition from source to target for
  109. // class from the kernel.
  110. func ComputeCreateContext(source string, target string, class string) (string, error) {
  111. return computeCreateContext(source, target, class)
  112. }
  113. // CalculateGlbLub computes the glb (greatest lower bound) and lub (least upper bound)
  114. // of a source and target range.
  115. // The glblub is calculated as the greater of the low sensitivities and
  116. // the lower of the high sensitivities and the and of each category bitset.
  117. func CalculateGlbLub(sourceRange, targetRange string) (string, error) {
  118. return calculateGlbLub(sourceRange, targetRange)
  119. }
  120. // SetExecLabel sets the SELinux label that the kernel will use for any programs
  121. // that are executed by the current process thread, or an error. Calls to SetExecLabel
  122. // should be wrapped in runtime.LockOSThread()/runtime.UnlockOSThread() until execution
  123. // of the program is finished to guarantee another goroutine does not migrate to the current
  124. // thread before execution is complete.
  125. func SetExecLabel(label string) error {
  126. return writeCon(attrPath("exec"), label)
  127. }
  128. // SetTaskLabel sets the SELinux label for the current thread, or an error.
  129. // This requires the dyntransition permission. Calls to SetTaskLabel should
  130. // be wrapped in runtime.LockOSThread()/runtime.UnlockOSThread() to guarantee
  131. // the current thread does not run in a new mislabeled thread.
  132. func SetTaskLabel(label string) error {
  133. return writeCon(attrPath("current"), label)
  134. }
  135. // SetSocketLabel takes a process label and tells the kernel to assign the
  136. // label to the next socket that gets created. Calls to SetSocketLabel
  137. // should be wrapped in runtime.LockOSThread()/runtime.UnlockOSThread() until
  138. // the socket is created to guarantee another goroutine does not migrate
  139. // to the current thread before execution is complete.
  140. func SetSocketLabel(label string) error {
  141. return writeCon(attrPath("sockcreate"), label)
  142. }
  143. // SocketLabel retrieves the current socket label setting
  144. func SocketLabel() (string, error) {
  145. return readCon(attrPath("sockcreate"))
  146. }
  147. // PeerLabel retrieves the label of the client on the other side of a socket
  148. func PeerLabel(fd uintptr) (string, error) {
  149. return peerLabel(fd)
  150. }
  151. // SetKeyLabel takes a process label and tells the kernel to assign the
  152. // label to the next kernel keyring that gets created. Calls to SetKeyLabel
  153. // should be wrapped in runtime.LockOSThread()/runtime.UnlockOSThread() until
  154. // the kernel keyring is created to guarantee another goroutine does not migrate
  155. // to the current thread before execution is complete.
  156. func SetKeyLabel(label string) error {
  157. return setKeyLabel(label)
  158. }
  159. // KeyLabel retrieves the current kernel keyring label setting
  160. func KeyLabel() (string, error) {
  161. return readCon("/proc/self/attr/keycreate")
  162. }
  163. // Get returns the Context as a string
  164. func (c Context) Get() string {
  165. return c.get()
  166. }
  167. // NewContext creates a new Context struct from the specified label
  168. func NewContext(label string) (Context, error) {
  169. return newContext(label)
  170. }
  171. // ClearLabels clears all reserved labels
  172. func ClearLabels() {
  173. clearLabels()
  174. }
  175. // ReserveLabel reserves the MLS/MCS level component of the specified label
  176. func ReserveLabel(label string) {
  177. reserveLabel(label)
  178. }
  179. // MLSEnabled checks if MLS is enabled.
  180. func MLSEnabled() bool {
  181. return isMLSEnabled()
  182. }
  183. // EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled
  184. func EnforceMode() int {
  185. return enforceMode()
  186. }
  187. // SetEnforceMode sets the current SELinux mode Enforcing, Permissive.
  188. // Disabled is not valid, since this needs to be set at boot time.
  189. func SetEnforceMode(mode int) error {
  190. return setEnforceMode(mode)
  191. }
  192. // DefaultEnforceMode returns the systems default SELinux mode Enforcing,
  193. // Permissive or Disabled. Note this is just the default at boot time.
  194. // EnforceMode tells you the systems current mode.
  195. func DefaultEnforceMode() int {
  196. return defaultEnforceMode()
  197. }
  198. // ReleaseLabel un-reserves the MLS/MCS Level field of the specified label,
  199. // allowing it to be used by another process.
  200. func ReleaseLabel(label string) {
  201. releaseLabel(label)
  202. }
  203. // ROFileLabel returns the specified SELinux readonly file label
  204. func ROFileLabel() string {
  205. return roFileLabel()
  206. }
  207. // KVMContainerLabels returns the default processLabel and mountLabel to be used
  208. // for kvm containers by the calling process.
  209. func KVMContainerLabels() (string, string) {
  210. return kvmContainerLabels()
  211. }
  212. // InitContainerLabels returns the default processLabel and file labels to be
  213. // used for containers running an init system like systemd by the calling process.
  214. func InitContainerLabels() (string, string) {
  215. return initContainerLabels()
  216. }
  217. // ContainerLabels returns an allocated processLabel and fileLabel to be used for
  218. // container labeling by the calling process.
  219. func ContainerLabels() (processLabel string, fileLabel string) {
  220. return containerLabels()
  221. }
  222. // SecurityCheckContext validates that the SELinux label is understood by the kernel
  223. func SecurityCheckContext(val string) error {
  224. return securityCheckContext(val)
  225. }
  226. // CopyLevel returns a label with the MLS/MCS level from src label replaced on
  227. // the dest label.
  228. func CopyLevel(src, dest string) (string, error) {
  229. return copyLevel(src, dest)
  230. }
  231. // Chcon changes the fpath file object to the SELinux label.
  232. // If fpath is a directory and recurse is true, then Chcon walks the
  233. // directory tree setting the label.
  234. //
  235. // The fpath itself is guaranteed to be relabeled last.
  236. func Chcon(fpath string, label string, recurse bool) error {
  237. return chcon(fpath, label, recurse)
  238. }
  239. // DupSecOpt takes an SELinux process label and returns security options that
  240. // can be used to set the SELinux Type and Level for future container processes.
  241. func DupSecOpt(src string) ([]string, error) {
  242. return dupSecOpt(src)
  243. }
  244. // DisableSecOpt returns a security opt that can be used to disable SELinux
  245. // labeling support for future container processes.
  246. func DisableSecOpt() []string {
  247. return []string{"disable"}
  248. }
  249. // GetDefaultContextWithLevel gets a single context for the specified SELinux user
  250. // identity that is reachable from the specified scon context. The context is based
  251. // on the per-user /etc/selinux/{SELINUXTYPE}/contexts/users/<username> if it exists,
  252. // and falls back to the global /etc/selinux/{SELINUXTYPE}/contexts/default_contexts
  253. // file.
  254. func GetDefaultContextWithLevel(user, level, scon string) (string, error) {
  255. return getDefaultContextWithLevel(user, level, scon)
  256. }
  257. // PrivContainerMountLabel returns mount label for privileged containers
  258. func PrivContainerMountLabel() string {
  259. // Make sure label is initialized.
  260. _ = label("")
  261. return privContainerMountLabel
  262. }