mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-03 23:40:03 +00:00 
			
		
		
		
	This fixes a race condition in runc/systemd at container creation time opencontainers/runc#1683 Signed-off-by: vikaschoudhary16 <vichoudh@redhat.com>
		
			
				
	
	
		
			94 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			94 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build linux
 | 
						|
 | 
						|
package utils
 | 
						|
 | 
						|
/*
 | 
						|
 * Copyright 2016, 2017 SUSE LLC
 | 
						|
 *
 | 
						|
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
 * you may not use this file except in compliance with the License.
 | 
						|
 * You may obtain a copy of the License at
 | 
						|
 *
 | 
						|
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 *
 | 
						|
 * Unless required by applicable law or agreed to in writing, software
 | 
						|
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
 * See the License for the specific language governing permissions and
 | 
						|
 * limitations under the License.
 | 
						|
 */
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"os"
 | 
						|
 | 
						|
	"golang.org/x/sys/unix"
 | 
						|
)
 | 
						|
 | 
						|
// MaxSendfdLen is the maximum length of the name of a file descriptor being
 | 
						|
// sent using SendFd. The name of the file handle returned by RecvFd will never
 | 
						|
// be larger than this value.
 | 
						|
const MaxNameLen = 4096
 | 
						|
 | 
						|
// oobSpace is the size of the oob slice required to store a single FD. Note
 | 
						|
// that unix.UnixRights appears to make the assumption that fd is always int32,
 | 
						|
// so sizeof(fd) = 4.
 | 
						|
var oobSpace = unix.CmsgSpace(4)
 | 
						|
 | 
						|
// RecvFd waits for a file descriptor to be sent over the given AF_UNIX
 | 
						|
// socket. The file name of the remote file descriptor will be recreated
 | 
						|
// locally (it is sent as non-auxiliary data in the same payload).
 | 
						|
func RecvFd(socket *os.File) (*os.File, error) {
 | 
						|
	// For some reason, unix.Recvmsg uses the length rather than the capacity
 | 
						|
	// when passing the msg_controllen and other attributes to recvmsg.  So we
 | 
						|
	// have to actually set the length.
 | 
						|
	name := make([]byte, MaxNameLen)
 | 
						|
	oob := make([]byte, oobSpace)
 | 
						|
 | 
						|
	sockfd := socket.Fd()
 | 
						|
	n, oobn, _, _, err := unix.Recvmsg(int(sockfd), name, oob, 0)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	if n >= MaxNameLen || oobn != oobSpace {
 | 
						|
		return nil, fmt.Errorf("recvfd: incorrect number of bytes read (n=%d oobn=%d)", n, oobn)
 | 
						|
	}
 | 
						|
 | 
						|
	// Truncate.
 | 
						|
	name = name[:n]
 | 
						|
	oob = oob[:oobn]
 | 
						|
 | 
						|
	scms, err := unix.ParseSocketControlMessage(oob)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	if len(scms) != 1 {
 | 
						|
		return nil, fmt.Errorf("recvfd: number of SCMs is not 1: %d", len(scms))
 | 
						|
	}
 | 
						|
	scm := scms[0]
 | 
						|
 | 
						|
	fds, err := unix.ParseUnixRights(&scm)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	if len(fds) != 1 {
 | 
						|
		return nil, fmt.Errorf("recvfd: number of fds is not 1: %d", len(fds))
 | 
						|
	}
 | 
						|
	fd := uintptr(fds[0])
 | 
						|
 | 
						|
	return os.NewFile(fd, string(name)), nil
 | 
						|
}
 | 
						|
 | 
						|
// SendFd sends a file descriptor over the given AF_UNIX socket. In
 | 
						|
// addition, the file.Name() of the given file will also be sent as
 | 
						|
// non-auxiliary data in the same payload (allowing to send contextual
 | 
						|
// information for a file descriptor).
 | 
						|
func SendFd(socket *os.File, name string, fd uintptr) error {
 | 
						|
	if len(name) >= MaxNameLen {
 | 
						|
		return fmt.Errorf("sendfd: filename too long: %s", name)
 | 
						|
	}
 | 
						|
	oob := unix.UnixRights(int(fd))
 | 
						|
	return unix.Sendmsg(int(socket.Fd()), []byte(name), oob, nil, 0)
 | 
						|
}
 |