...

Source file src/github.com/opencontainers/runc/libcontainer/configs/config_linux.go

Documentation: github.com/opencontainers/runc/libcontainer/configs

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

View as plain text