utils_unix.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // +build !windows
  2. package caps
  3. import (
  4. "fmt"
  5. "strings"
  6. "github.com/syndtr/gocapability/capability"
  7. )
  8. var capabilityList Capabilities
  9. func init() {
  10. last := capability.CAP_LAST_CAP
  11. // hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
  12. if last == capability.Cap(63) {
  13. last = capability.CAP_BLOCK_SUSPEND
  14. }
  15. for _, cap := range capability.List() {
  16. if cap > last {
  17. continue
  18. }
  19. capabilityList = append(capabilityList,
  20. &CapabilityMapping{
  21. Key: "CAP_" + strings.ToUpper(cap.String()),
  22. Value: cap,
  23. },
  24. )
  25. }
  26. }
  27. type (
  28. // CapabilityMapping maps linux capability name to its value of capability.Cap type
  29. // Capabilities is one of the security systems in Linux Security Module (LSM)
  30. // framework provided by the kernel.
  31. // For more details on capabilities, see http://man7.org/linux/man-pages/man7/capabilities.7.html
  32. CapabilityMapping struct {
  33. Key string `json:"key,omitempty"`
  34. Value capability.Cap `json:"value,omitempty"`
  35. }
  36. // Capabilities contains all CapabilityMapping
  37. Capabilities []*CapabilityMapping
  38. )
  39. // String returns <key> of CapabilityMapping
  40. func (c *CapabilityMapping) String() string {
  41. return c.Key
  42. }
  43. // GetCapability returns CapabilityMapping which contains specific key
  44. func GetCapability(key string) *CapabilityMapping {
  45. for _, capp := range capabilityList {
  46. if capp.Key == key {
  47. cpy := *capp
  48. return &cpy
  49. }
  50. }
  51. return nil
  52. }
  53. // GetAllCapabilities returns all of the capabilities
  54. func GetAllCapabilities() []string {
  55. output := make([]string, len(capabilityList))
  56. for i, capability := range capabilityList {
  57. output[i] = capability.String()
  58. }
  59. return output
  60. }
  61. // inSlice tests whether a string is contained in a slice of strings or not.
  62. // Comparison is case insensitive
  63. func inSlice(slice []string, s string) bool {
  64. for _, ss := range slice {
  65. if strings.ToLower(s) == strings.ToLower(ss) {
  66. return true
  67. }
  68. }
  69. return false
  70. }
  71. // TweakCapabilities can tweak capabilities by adding or dropping capabilities
  72. // based on the basics capabilities.
  73. func TweakCapabilities(basics, adds, drops []string) ([]string, error) {
  74. var (
  75. newCaps []string
  76. allCaps = GetAllCapabilities()
  77. )
  78. // FIXME(tonistiigi): docker format is without CAP_ prefix, oci is with prefix
  79. // Currently they are mixed in here. We should do conversion in one place.
  80. // look for invalid cap in the drop list
  81. for _, cap := range drops {
  82. if strings.ToLower(cap) == "all" {
  83. continue
  84. }
  85. if !inSlice(allCaps, "CAP_"+cap) {
  86. return nil, fmt.Errorf("Unknown capability drop: %q", cap)
  87. }
  88. }
  89. // handle --cap-add=all
  90. if inSlice(adds, "all") {
  91. basics = allCaps
  92. }
  93. if !inSlice(drops, "all") {
  94. for _, cap := range basics {
  95. // skip `all` already handled above
  96. if strings.ToLower(cap) == "all" {
  97. continue
  98. }
  99. // if we don't drop `all`, add back all the non-dropped caps
  100. if !inSlice(drops, cap[4:]) {
  101. newCaps = append(newCaps, strings.ToUpper(cap))
  102. }
  103. }
  104. }
  105. for _, cap := range adds {
  106. // skip `all` already handled above
  107. if strings.ToLower(cap) == "all" {
  108. continue
  109. }
  110. cap = "CAP_" + cap
  111. if !inSlice(allCaps, cap) {
  112. return nil, fmt.Errorf("Unknown capability to add: %q", cap)
  113. }
  114. // add cap if not already in the list
  115. if !inSlice(newCaps, cap) {
  116. newCaps = append(newCaps, strings.ToUpper(cap))
  117. }
  118. }
  119. return newCaps, nil
  120. }