github.com/AbhinandanKurakure/podman/v3@v3.4.10/libpod/oci_util.go (about)

     1  package libpod
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"os"
     7  	"regexp"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/containers/podman/v3/libpod/define"
    12  	"github.com/cri-o/ocicni/pkg/ocicni"
    13  	"github.com/pkg/errors"
    14  	"github.com/sirupsen/logrus"
    15  )
    16  
    17  // Timeout before declaring that runtime has failed to kill a given
    18  // container
    19  const killContainerTimeout = 5 * time.Second
    20  
    21  // ociError is used to parse the OCI runtime JSON log.  It is not part of the
    22  // OCI runtime specifications, it follows what runc does
    23  type ociError struct {
    24  	Level string `json:"level,omitempty"`
    25  	Time  string `json:"time,omitempty"`
    26  	Msg   string `json:"msg,omitempty"`
    27  }
    28  
    29  // Create systemd unit name for cgroup scopes
    30  func createUnitName(prefix string, name string) string {
    31  	return fmt.Sprintf("%s-%s.scope", prefix, name)
    32  }
    33  
    34  // Bind ports to keep them closed on the host
    35  func bindPorts(ports []ocicni.PortMapping) ([]*os.File, error) {
    36  	var files []*os.File
    37  	notifySCTP := false
    38  	for _, i := range ports {
    39  		isV6 := net.ParseIP(i.HostIP).To4() == nil
    40  		if i.HostIP == "" {
    41  			isV6 = false
    42  		}
    43  		switch i.Protocol {
    44  		case "udp":
    45  			var (
    46  				addr *net.UDPAddr
    47  				err  error
    48  			)
    49  			if isV6 {
    50  				addr, err = net.ResolveUDPAddr("udp6", fmt.Sprintf("[%s]:%d", i.HostIP, i.HostPort))
    51  			} else {
    52  				addr, err = net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%d", i.HostIP, i.HostPort))
    53  			}
    54  			if err != nil {
    55  				return nil, errors.Wrapf(err, "cannot resolve the UDP address")
    56  			}
    57  
    58  			proto := "udp4"
    59  			if isV6 {
    60  				proto = "udp6"
    61  			}
    62  			server, err := net.ListenUDP(proto, addr)
    63  			if err != nil {
    64  				return nil, errors.Wrapf(err, "cannot listen on the UDP port")
    65  			}
    66  			f, err := server.File()
    67  			if err != nil {
    68  				return nil, errors.Wrapf(err, "cannot get file for UDP socket")
    69  			}
    70  			files = append(files, f)
    71  			// close the listener
    72  			// note that this does not affect the fd, see the godoc for server.File()
    73  			err = server.Close()
    74  			if err != nil {
    75  				logrus.Warnf("failed to close connection: %v", err)
    76  			}
    77  
    78  		case "tcp":
    79  			var (
    80  				addr *net.TCPAddr
    81  				err  error
    82  			)
    83  			if isV6 {
    84  				addr, err = net.ResolveTCPAddr("tcp6", fmt.Sprintf("[%s]:%d", i.HostIP, i.HostPort))
    85  			} else {
    86  				addr, err = net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%d", i.HostIP, i.HostPort))
    87  			}
    88  			if err != nil {
    89  				return nil, errors.Wrapf(err, "cannot resolve the TCP address")
    90  			}
    91  
    92  			proto := "tcp4"
    93  			if isV6 {
    94  				proto = "tcp6"
    95  			}
    96  			server, err := net.ListenTCP(proto, addr)
    97  			if err != nil {
    98  				return nil, errors.Wrapf(err, "cannot listen on the TCP port")
    99  			}
   100  			f, err := server.File()
   101  			if err != nil {
   102  				return nil, errors.Wrapf(err, "cannot get file for TCP socket")
   103  			}
   104  			files = append(files, f)
   105  			// close the listener
   106  			// note that this does not affect the fd, see the godoc for server.File()
   107  			err = server.Close()
   108  			if err != nil {
   109  				logrus.Warnf("failed to close connection: %v", err)
   110  			}
   111  
   112  		case "sctp":
   113  			if !notifySCTP {
   114  				notifySCTP = true
   115  				logrus.Warnf("port reservation for SCTP is not supported")
   116  			}
   117  		default:
   118  			return nil, fmt.Errorf("unknown protocol %s", i.Protocol)
   119  		}
   120  	}
   121  	return files, nil
   122  }
   123  
   124  func getOCIRuntimeError(runtimeMsg string) error {
   125  	includeFullOutput := logrus.GetLevel() == logrus.DebugLevel
   126  
   127  	if match := regexp.MustCompile("(?i).*permission denied.*|.*operation not permitted.*").FindString(runtimeMsg); match != "" {
   128  		errStr := match
   129  		if includeFullOutput {
   130  			errStr = runtimeMsg
   131  		}
   132  		return errors.Wrapf(define.ErrOCIRuntimePermissionDenied, "%s", strings.Trim(errStr, "\n"))
   133  	}
   134  	if match := regexp.MustCompile("(?i).*executable file not found in.*|.*no such file or directory.*").FindString(runtimeMsg); match != "" {
   135  		errStr := match
   136  		if includeFullOutput {
   137  			errStr = runtimeMsg
   138  		}
   139  		return errors.Wrapf(define.ErrOCIRuntimeNotFound, "%s", strings.Trim(errStr, "\n"))
   140  	}
   141  	if match := regexp.MustCompile("`/proc/[a-z0-9-].+/attr.*`").FindString(runtimeMsg); match != "" {
   142  		errStr := match
   143  		if includeFullOutput {
   144  			errStr = runtimeMsg
   145  		}
   146  		if strings.HasSuffix(match, "/exec`") {
   147  			return errors.Wrapf(define.ErrSetSecurityAttribute, "%s", strings.Trim(errStr, "\n"))
   148  		} else if strings.HasSuffix(match, "/current`") {
   149  			return errors.Wrapf(define.ErrGetSecurityAttribute, "%s", strings.Trim(errStr, "\n"))
   150  		}
   151  		return errors.Wrapf(define.ErrSecurityAttribute, "%s", strings.Trim(errStr, "\n"))
   152  	}
   153  	return errors.Wrapf(define.ErrOCIRuntime, "%s", strings.Trim(runtimeMsg, "\n"))
   154  }