mirror of https://github.com/containers/podman.git
				
				
				
			
		
			
				
	
	
		
			91 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
| // +build linux
 | |
| 
 | |
| package cgroups
 | |
| 
 | |
| import (
 | |
| 	"bufio"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 	"strings"
 | |
| 	"sync"
 | |
| 	"syscall"
 | |
| 
 | |
| 	"github.com/pkg/errors"
 | |
| 	"golang.org/x/sys/unix"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	isUnifiedOnce sync.Once
 | |
| 	isUnified     bool
 | |
| 	isUnifiedErr  error
 | |
| )
 | |
| 
 | |
| // IsCgroup2UnifiedMode returns whether we are running in cgroup 2 cgroup2 mode.
 | |
| func IsCgroup2UnifiedMode() (bool, error) {
 | |
| 	isUnifiedOnce.Do(func() {
 | |
| 		var st syscall.Statfs_t
 | |
| 		if err := syscall.Statfs("/sys/fs/cgroup", &st); err != nil {
 | |
| 			isUnified, isUnifiedErr = false, err
 | |
| 		} else {
 | |
| 			isUnified, isUnifiedErr = st.Type == unix.CGROUP2_SUPER_MAGIC, nil
 | |
| 		}
 | |
| 	})
 | |
| 	return isUnified, isUnifiedErr
 | |
| }
 | |
| 
 | |
| // UserOwnsCurrentSystemdCgroup checks whether the current EUID owns the
 | |
| // current cgroup.
 | |
| func UserOwnsCurrentSystemdCgroup() (bool, error) {
 | |
| 	uid := os.Geteuid()
 | |
| 
 | |
| 	cgroup2, err := IsCgroup2UnifiedMode()
 | |
| 	if err != nil {
 | |
| 		return false, err
 | |
| 	}
 | |
| 
 | |
| 	f, err := os.Open("/proc/self/cgroup")
 | |
| 	if err != nil {
 | |
| 		return false, errors.Wrapf(err, "open file /proc/self/cgroup")
 | |
| 	}
 | |
| 	defer f.Close()
 | |
| 
 | |
| 	scanner := bufio.NewScanner(f)
 | |
| 	for scanner.Scan() {
 | |
| 		line := scanner.Text()
 | |
| 		parts := strings.SplitN(line, ":", 3)
 | |
| 
 | |
| 		if len(parts) < 3 {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		var cgroupPath string
 | |
| 
 | |
| 		if cgroup2 {
 | |
| 			cgroupPath = filepath.Join(cgroupRoot, parts[2])
 | |
| 		} else {
 | |
| 			if parts[1] != "name=systemd" {
 | |
| 				continue
 | |
| 			}
 | |
| 			cgroupPath = filepath.Join(cgroupRoot, "systemd", parts[2])
 | |
| 		}
 | |
| 
 | |
| 		st, err := os.Stat(cgroupPath)
 | |
| 		if err != nil {
 | |
| 			return false, err
 | |
| 		}
 | |
| 		s := st.Sys()
 | |
| 		if s == nil {
 | |
| 			return false, fmt.Errorf("error stat cgroup path %s", cgroupPath)
 | |
| 		}
 | |
| 
 | |
| 		if int(s.(*syscall.Stat_t).Uid) != uid {
 | |
| 			return false, nil
 | |
| 		}
 | |
| 	}
 | |
| 	if err := scanner.Err(); err != nil {
 | |
| 		return false, errors.Wrapf(err, "parsing file /proc/self/cgroup")
 | |
| 	}
 | |
| 	return true, nil
 | |
| }
 |