Skip to content

Commit

Permalink
Lookup devices cgroup path of target process
Browse files Browse the repository at this point in the history
At least starting from OpenShift v3.6, origin/k8s creates its own cgroup
hierarchy for QoS purposes:

    # find /sys/fs/cgroup/devices/ -type d -iname 'kube*'
    /sys/fs/cgroup/devices/kubepods.slice
    /sys/fs/cgroup/devices/kubepods.slice/kubepods-besteffort.slice
    /sys/fs/cgroup/devices/kubepods.slice/kubepods-burstable.slice

Sub-slices are created per pod in either directories depending on the
QoS class assigned.

This means that the hardcoded `system.slice` path will not be correct
for pod processes. One can reproduce this from a simple `oc cluster up`
setup.

This patch basically fixes the related TODO in the codebase to make the
hook work in the OpenShift case.

Closes #4
  • Loading branch information
jlebon authored and stefwalter committed Feb 2, 2018
1 parent 535cd3c commit 7968b1c
Showing 1 changed file with 63 additions and 10 deletions.
73 changes: 63 additions & 10 deletions oci-kvm-hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
package main

import (
"bufio"
"encoding/json"
"fmt"
"log"
"log/syslog"
"os"
"os/exec"
"strings"
)

// {"version":"","id":"96c1870d5c21c324db0a5b350f5a8f5571cf514205b6d3647b893b6580a05018","pid":27146,"root":"/opt/docker/devicemapper/mnt/a45fd0cb88f52620f94215e8e19b806f787f0c649be8e5c13b737dc2d8278daf/rootfs"}
Expand All @@ -24,22 +26,73 @@ type Process struct {
Env []string `json:"env"`
}

func allowKvm(state State) {
// TODO: Use state.Pid and /proc/$pid/cgroup to determine the right devices.allow file
allow_path := fmt.Sprintf("/sys/fs/cgroup/devices/system.slice/docker-%s.scope/devices.allow", state.ID)
allow, err := os.OpenFile(allow_path, os.O_APPEND|os.O_WRONLY, 0600)
func stringInArray(str string, arr []string) bool {
for _, item := range arr {
if item == str {
return true
}
}
return false
}

func getProcessDevicesCgroupPath(pid int) (string, error) {

pid_cgroup_path := fmt.Sprintf("/proc/%d/cgroup", pid)
pid_cgroup, err := os.Open(pid_cgroup_path)
if err != nil {
log.Printf("Failed to open file: %s: %v", allow_path, err.Error())
return
return "", err
}
defer pid_cgroup.Close()

scanner := bufio.NewScanner(pid_cgroup)
for scanner.Scan() {
entry := strings.SplitN(scanner.Text(), ":", 3)
if entry[0] == "0" {
// let's just ignore cgroups v2 for now -- e.g. systemd still uses
// v1 for the devices subsystem
continue
}
controllers := strings.Split(entry[1], ",")
if stringInArray("devices", controllers) {
// note systemd leaves a symlink even in the case it's comounted
return fmt.Sprintf("/sys/fs/cgroup/devices/%s", entry[2]), nil
}
}

_, err = allow.WriteString("c 10:232 rwm")
if err := scanner.Err(); err != nil {
return "", err
}

return "", nil
}

func allowKvm(state State) {

cgroup_path, err := getProcessDevicesCgroupPath(state.Pid)
if err != nil {
log.Printf("Failed to write to group file: %s: %v", allow_path, err.Error())
log.Printf("Failed to get process %d devices cgroup path: %v", state.Pid, err.Error())
return
}

allow.Close()
if cgroup_path == "" {
log.Printf("Process does not belong to any devices cgroup, yay!")
} else {
allow_path := fmt.Sprintf("%s/devices.allow", cgroup_path)
allow, err := os.OpenFile(allow_path, os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
log.Printf("Failed to open file for writing: %s: %v", allow_path, err.Error())
return
}
defer allow.Close()

_, err = allow.WriteString("c 10:232 rwm")
if err != nil {
log.Printf("Failed to write to group file: %s: %v", allow_path, err.Error())
return
}

log.Printf("Added kvm whitelist into %s", allow_path)
}

// Get info about /dev/kvm
info, err := os.Stat("/dev/kvm")
Expand All @@ -59,7 +112,7 @@ func allowKvm(state State) {
return
}

log.Printf("Allowed /dev/kvm in new container: %s %s %s", kvm_path, allow_path, state.ID)
log.Printf("Allowed /dev/kvm in new container: %s %s", kvm_path, state.ID)
}

func main() {
Expand Down

0 comments on commit 7968b1c

Please sign in to comment.