mirror of
https://github.com/containers/podman.git
synced 2025-08-06 03:19:52 +08:00

This includes two new hidden commands: a 9p server, `podman machine server9p`, and a 9p client, `podman machine client9p` with `server9p` currently only configured to run on Windows and serve 9p via HyperV vsock, and `client9p` only configured to run on Linux. The server is run by `podman machine start` and has the same lifespan as gvproxy (waits for the gvproxy PID to die before shutting down). The client is run inside the VM, also by `podman machine start`, and mounts uses kernel 9p mount code to complete the mount. It's unfortunately not possible to use mount directly without the wrapper; we need to set up the vsock and pass it to mount as an FD. In theory this can be generalized so that the server can run anywhere and over almost any transport, but I haven't done this here as I don't think we have a usecase other than HyperV right now. [NO NEW TESTS NEEDED] This requires changes to Podman in the VM, so we need to wait until a build with this lands in FCOS to test. Signed-off-by: Matthew Heon <matthew.heon@pm.me>
183 lines
3.9 KiB
Go
183 lines
3.9 KiB
Go
// Copyright 2016 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package bpf
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
)
|
|
|
|
func aluOpConstant(ins ALUOpConstant, regA uint32) uint32 {
|
|
return aluOpCommon(ins.Op, regA, ins.Val)
|
|
}
|
|
|
|
func aluOpX(ins ALUOpX, regA uint32, regX uint32) (uint32, bool) {
|
|
// Guard against division or modulus by zero by terminating
|
|
// the program, as the OS BPF VM does
|
|
if regX == 0 {
|
|
switch ins.Op {
|
|
case ALUOpDiv, ALUOpMod:
|
|
return 0, false
|
|
}
|
|
}
|
|
|
|
return aluOpCommon(ins.Op, regA, regX), true
|
|
}
|
|
|
|
func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 {
|
|
switch op {
|
|
case ALUOpAdd:
|
|
return regA + value
|
|
case ALUOpSub:
|
|
return regA - value
|
|
case ALUOpMul:
|
|
return regA * value
|
|
case ALUOpDiv:
|
|
// Division by zero not permitted by NewVM and aluOpX checks
|
|
return regA / value
|
|
case ALUOpOr:
|
|
return regA | value
|
|
case ALUOpAnd:
|
|
return regA & value
|
|
case ALUOpShiftLeft:
|
|
return regA << value
|
|
case ALUOpShiftRight:
|
|
return regA >> value
|
|
case ALUOpMod:
|
|
// Modulus by zero not permitted by NewVM and aluOpX checks
|
|
return regA % value
|
|
case ALUOpXor:
|
|
return regA ^ value
|
|
default:
|
|
return regA
|
|
}
|
|
}
|
|
|
|
func jumpIf(ins JumpIf, regA uint32) int {
|
|
return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, ins.Val)
|
|
}
|
|
|
|
func jumpIfX(ins JumpIfX, regA uint32, regX uint32) int {
|
|
return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, regX)
|
|
}
|
|
|
|
func jumpIfCommon(cond JumpTest, skipTrue, skipFalse uint8, regA uint32, value uint32) int {
|
|
var ok bool
|
|
|
|
switch cond {
|
|
case JumpEqual:
|
|
ok = regA == value
|
|
case JumpNotEqual:
|
|
ok = regA != value
|
|
case JumpGreaterThan:
|
|
ok = regA > value
|
|
case JumpLessThan:
|
|
ok = regA < value
|
|
case JumpGreaterOrEqual:
|
|
ok = regA >= value
|
|
case JumpLessOrEqual:
|
|
ok = regA <= value
|
|
case JumpBitsSet:
|
|
ok = (regA & value) != 0
|
|
case JumpBitsNotSet:
|
|
ok = (regA & value) == 0
|
|
}
|
|
|
|
if ok {
|
|
return int(skipTrue)
|
|
}
|
|
|
|
return int(skipFalse)
|
|
}
|
|
|
|
func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) {
|
|
offset := int(ins.Off)
|
|
size := ins.Size
|
|
|
|
return loadCommon(in, offset, size)
|
|
}
|
|
|
|
func loadConstant(ins LoadConstant, regA uint32, regX uint32) (uint32, uint32) {
|
|
switch ins.Dst {
|
|
case RegA:
|
|
regA = ins.Val
|
|
case RegX:
|
|
regX = ins.Val
|
|
}
|
|
|
|
return regA, regX
|
|
}
|
|
|
|
func loadExtension(ins LoadExtension, in []byte) uint32 {
|
|
switch ins.Num {
|
|
case ExtLen:
|
|
return uint32(len(in))
|
|
default:
|
|
panic(fmt.Sprintf("unimplemented extension: %d", ins.Num))
|
|
}
|
|
}
|
|
|
|
func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) {
|
|
offset := int(ins.Off) + int(regX)
|
|
size := ins.Size
|
|
|
|
return loadCommon(in, offset, size)
|
|
}
|
|
|
|
func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) {
|
|
offset := int(ins.Off)
|
|
|
|
// Size of LoadMemShift is always 1 byte
|
|
if !inBounds(len(in), offset, 1) {
|
|
return 0, false
|
|
}
|
|
|
|
// Mask off high 4 bits and multiply low 4 bits by 4
|
|
return uint32(in[offset]&0x0f) * 4, true
|
|
}
|
|
|
|
func inBounds(inLen int, offset int, size int) bool {
|
|
return offset+size <= inLen
|
|
}
|
|
|
|
func loadCommon(in []byte, offset int, size int) (uint32, bool) {
|
|
if !inBounds(len(in), offset, size) {
|
|
return 0, false
|
|
}
|
|
|
|
switch size {
|
|
case 1:
|
|
return uint32(in[offset]), true
|
|
case 2:
|
|
return uint32(binary.BigEndian.Uint16(in[offset : offset+size])), true
|
|
case 4:
|
|
return uint32(binary.BigEndian.Uint32(in[offset : offset+size])), true
|
|
default:
|
|
panic(fmt.Sprintf("invalid load size: %d", size))
|
|
}
|
|
}
|
|
|
|
func loadScratch(ins LoadScratch, regScratch [16]uint32, regA uint32, regX uint32) (uint32, uint32) {
|
|
switch ins.Dst {
|
|
case RegA:
|
|
regA = regScratch[ins.N]
|
|
case RegX:
|
|
regX = regScratch[ins.N]
|
|
}
|
|
|
|
return regA, regX
|
|
}
|
|
|
|
func storeScratch(ins StoreScratch, regScratch [16]uint32, regA uint32, regX uint32) [16]uint32 {
|
|
switch ins.Src {
|
|
case RegA:
|
|
regScratch[ins.N] = regA
|
|
case RegX:
|
|
regScratch[ins.N] = regX
|
|
}
|
|
|
|
return regScratch
|
|
}
|