cap_freebsd.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright 2017 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build freebsd
  5. package unix
  6. import (
  7. "errors"
  8. "fmt"
  9. )
  10. // Go implementation of C mostly found in /usr/src/sys/kern/subr_capability.c
  11. const (
  12. // This is the version of CapRights this package understands. See C implementation for parallels.
  13. capRightsGoVersion = CAP_RIGHTS_VERSION_00
  14. capArSizeMin = CAP_RIGHTS_VERSION_00 + 2
  15. capArSizeMax = capRightsGoVersion + 2
  16. )
  17. var (
  18. bit2idx = []int{
  19. -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1,
  20. 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  21. }
  22. )
  23. func capidxbit(right uint64) int {
  24. return int((right >> 57) & 0x1f)
  25. }
  26. func rightToIndex(right uint64) (int, error) {
  27. idx := capidxbit(right)
  28. if idx < 0 || idx >= len(bit2idx) {
  29. return -2, fmt.Errorf("index for right 0x%x out of range", right)
  30. }
  31. return bit2idx[idx], nil
  32. }
  33. func caprver(right uint64) int {
  34. return int(right >> 62)
  35. }
  36. func capver(rights *CapRights) int {
  37. return caprver(rights.Rights[0])
  38. }
  39. func caparsize(rights *CapRights) int {
  40. return capver(rights) + 2
  41. }
  42. // CapRightsSet sets the permissions in setrights in rights.
  43. func CapRightsSet(rights *CapRights, setrights []uint64) error {
  44. // This is essentially a copy of cap_rights_vset()
  45. if capver(rights) != CAP_RIGHTS_VERSION_00 {
  46. return fmt.Errorf("bad rights version %d", capver(rights))
  47. }
  48. n := caparsize(rights)
  49. if n < capArSizeMin || n > capArSizeMax {
  50. return errors.New("bad rights size")
  51. }
  52. for _, right := range setrights {
  53. if caprver(right) != CAP_RIGHTS_VERSION_00 {
  54. return errors.New("bad right version")
  55. }
  56. i, err := rightToIndex(right)
  57. if err != nil {
  58. return err
  59. }
  60. if i >= n {
  61. return errors.New("index overflow")
  62. }
  63. if capidxbit(rights.Rights[i]) != capidxbit(right) {
  64. return errors.New("index mismatch")
  65. }
  66. rights.Rights[i] |= right
  67. if capidxbit(rights.Rights[i]) != capidxbit(right) {
  68. return errors.New("index mismatch (after assign)")
  69. }
  70. }
  71. return nil
  72. }
  73. // CapRightsClear clears the permissions in clearrights from rights.
  74. func CapRightsClear(rights *CapRights, clearrights []uint64) error {
  75. // This is essentially a copy of cap_rights_vclear()
  76. if capver(rights) != CAP_RIGHTS_VERSION_00 {
  77. return fmt.Errorf("bad rights version %d", capver(rights))
  78. }
  79. n := caparsize(rights)
  80. if n < capArSizeMin || n > capArSizeMax {
  81. return errors.New("bad rights size")
  82. }
  83. for _, right := range clearrights {
  84. if caprver(right) != CAP_RIGHTS_VERSION_00 {
  85. return errors.New("bad right version")
  86. }
  87. i, err := rightToIndex(right)
  88. if err != nil {
  89. return err
  90. }
  91. if i >= n {
  92. return errors.New("index overflow")
  93. }
  94. if capidxbit(rights.Rights[i]) != capidxbit(right) {
  95. return errors.New("index mismatch")
  96. }
  97. rights.Rights[i] &= ^(right & 0x01FFFFFFFFFFFFFF)
  98. if capidxbit(rights.Rights[i]) != capidxbit(right) {
  99. return errors.New("index mismatch (after assign)")
  100. }
  101. }
  102. return nil
  103. }
  104. // CapRightsIsSet checks whether all the permissions in setrights are present in rights.
  105. func CapRightsIsSet(rights *CapRights, setrights []uint64) (bool, error) {
  106. // This is essentially a copy of cap_rights_is_vset()
  107. if capver(rights) != CAP_RIGHTS_VERSION_00 {
  108. return false, fmt.Errorf("bad rights version %d", capver(rights))
  109. }
  110. n := caparsize(rights)
  111. if n < capArSizeMin || n > capArSizeMax {
  112. return false, errors.New("bad rights size")
  113. }
  114. for _, right := range setrights {
  115. if caprver(right) != CAP_RIGHTS_VERSION_00 {
  116. return false, errors.New("bad right version")
  117. }
  118. i, err := rightToIndex(right)
  119. if err != nil {
  120. return false, err
  121. }
  122. if i >= n {
  123. return false, errors.New("index overflow")
  124. }
  125. if capidxbit(rights.Rights[i]) != capidxbit(right) {
  126. return false, errors.New("index mismatch")
  127. }
  128. if (rights.Rights[i] & right) != right {
  129. return false, nil
  130. }
  131. }
  132. return true, nil
  133. }
  134. func capright(idx uint64, bit uint64) uint64 {
  135. return ((1 << (57 + idx)) | bit)
  136. }
  137. // CapRightsInit returns a pointer to an initialised CapRights structure filled with rights.
  138. // See man cap_rights_init(3) and rights(4).
  139. func CapRightsInit(rights []uint64) (*CapRights, error) {
  140. var r CapRights
  141. r.Rights[0] = (capRightsGoVersion << 62) | capright(0, 0)
  142. r.Rights[1] = capright(1, 0)
  143. err := CapRightsSet(&r, rights)
  144. if err != nil {
  145. return nil, err
  146. }
  147. return &r, nil
  148. }
  149. // CapRightsLimit reduces the operations permitted on fd to at most those contained in rights.
  150. // The capability rights on fd can never be increased by CapRightsLimit.
  151. // See man cap_rights_limit(2) and rights(4).
  152. func CapRightsLimit(fd uintptr, rights *CapRights) error {
  153. return capRightsLimit(int(fd), rights)
  154. }
  155. // CapRightsGet returns a CapRights structure containing the operations permitted on fd.
  156. // See man cap_rights_get(3) and rights(4).
  157. func CapRightsGet(fd uintptr) (*CapRights, error) {
  158. r, err := CapRightsInit(nil)
  159. if err != nil {
  160. return nil, err
  161. }
  162. err = capRightsGet(capRightsGoVersion, int(fd), r)
  163. if err != nil {
  164. return nil, err
  165. }
  166. return r, nil
  167. }