config_linux.go 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package configs
  2. import (
  3. "errors"
  4. "fmt"
  5. "math"
  6. )
  7. var (
  8. errNoUIDMap = errors.New("User namespaces enabled, but no uid mappings found.")
  9. errNoUserMap = errors.New("User namespaces enabled, but no user mapping found.")
  10. errNoGIDMap = errors.New("User namespaces enabled, but no gid mappings found.")
  11. errNoGroupMap = errors.New("User namespaces enabled, but no group mapping found.")
  12. )
  13. // HostUID gets the translated uid for the process on host which could be
  14. // different when user namespaces are enabled.
  15. func (c Config) HostUID(containerId int) (int, error) {
  16. if c.Namespaces.Contains(NEWUSER) {
  17. if c.UidMappings == nil {
  18. return -1, errNoUIDMap
  19. }
  20. id, found := c.hostIDFromMapping(int64(containerId), c.UidMappings)
  21. if !found {
  22. return -1, errNoUserMap
  23. }
  24. // If we are a 32-bit binary running on a 64-bit system, it's possible
  25. // the mapped user is too large to store in an int, which means we
  26. // cannot do the mapping. We can't just return an int64, because
  27. // os.Setuid() takes an int.
  28. if id > math.MaxInt {
  29. return -1, fmt.Errorf("mapping for uid %d (host id %d) is larger than native integer size (%d)", containerId, id, math.MaxInt)
  30. }
  31. return int(id), nil
  32. }
  33. // Return unchanged id.
  34. return containerId, nil
  35. }
  36. // HostRootUID gets the root uid for the process on host which could be non-zero
  37. // when user namespaces are enabled.
  38. func (c Config) HostRootUID() (int, error) {
  39. return c.HostUID(0)
  40. }
  41. // HostGID gets the translated gid for the process on host which could be
  42. // different when user namespaces are enabled.
  43. func (c Config) HostGID(containerId int) (int, error) {
  44. if c.Namespaces.Contains(NEWUSER) {
  45. if c.GidMappings == nil {
  46. return -1, errNoGIDMap
  47. }
  48. id, found := c.hostIDFromMapping(int64(containerId), c.GidMappings)
  49. if !found {
  50. return -1, errNoGroupMap
  51. }
  52. // If we are a 32-bit binary running on a 64-bit system, it's possible
  53. // the mapped user is too large to store in an int, which means we
  54. // cannot do the mapping. We can't just return an int64, because
  55. // os.Setgid() takes an int.
  56. if id > math.MaxInt {
  57. return -1, fmt.Errorf("mapping for gid %d (host id %d) is larger than native integer size (%d)", containerId, id, math.MaxInt)
  58. }
  59. return int(id), nil
  60. }
  61. // Return unchanged id.
  62. return containerId, nil
  63. }
  64. // HostRootGID gets the root gid for the process on host which could be non-zero
  65. // when user namespaces are enabled.
  66. func (c Config) HostRootGID() (int, error) {
  67. return c.HostGID(0)
  68. }
  69. // Utility function that gets a host ID for a container ID from user namespace map
  70. // if that ID is present in the map.
  71. func (c Config) hostIDFromMapping(containerID int64, uMap []IDMap) (int64, bool) {
  72. for _, m := range uMap {
  73. if (containerID >= m.ContainerID) && (containerID <= (m.ContainerID + m.Size - 1)) {
  74. hostID := m.HostID + (containerID - m.ContainerID)
  75. return hostID, true
  76. }
  77. }
  78. return -1, false
  79. }