appendDevice needs to be called from the last element of OCI linux.resources.devices to the head element.
(dev specs.LinuxDeviceCgroup)
| 88 | |
| 89 | // appendDevice needs to be called from the last element of OCI linux.resources.devices to the head element. |
| 90 | func (p *program) appendDevice(dev specs.LinuxDeviceCgroup) error { |
| 91 | if p.blockID < 0 { |
| 92 | return errors.New("the program is finalized") |
| 93 | } |
| 94 | if p.hasWildCard { |
| 95 | // All entries after wildcard entry are ignored |
| 96 | return nil |
| 97 | } |
| 98 | |
| 99 | bpfType := int32(-1) |
| 100 | hasType := true |
| 101 | switch dev.Type { |
| 102 | case string('c'): |
| 103 | bpfType = int32(unix.BPF_DEVCG_DEV_CHAR) |
| 104 | case string('b'): |
| 105 | bpfType = int32(unix.BPF_DEVCG_DEV_BLOCK) |
| 106 | case string('a'): |
| 107 | hasType = false |
| 108 | default: |
| 109 | // if not specified in OCI json, typ is set to DeviceTypeAll |
| 110 | return fmt.Errorf("invalid DeviceType %q", dev.Type) |
| 111 | } |
| 112 | if *dev.Major > math.MaxUint32 { |
| 113 | return fmt.Errorf("invalid major %d", *dev.Major) |
| 114 | } |
| 115 | if *dev.Minor > math.MaxUint32 { |
| 116 | return fmt.Errorf("invalid minor %d", *dev.Major) |
| 117 | } |
| 118 | hasMajor := *dev.Major >= 0 // if not specified in OCI json, major is set to -1 |
| 119 | hasMinor := *dev.Minor >= 0 |
| 120 | bpfAccess := int32(0) |
| 121 | for _, r := range dev.Access { |
| 122 | switch r { |
| 123 | case 'r': |
| 124 | bpfAccess |= unix.BPF_DEVCG_ACC_READ |
| 125 | case 'w': |
| 126 | bpfAccess |= unix.BPF_DEVCG_ACC_WRITE |
| 127 | case 'm': |
| 128 | bpfAccess |= unix.BPF_DEVCG_ACC_MKNOD |
| 129 | default: |
| 130 | return fmt.Errorf("unknown device access %v", r) |
| 131 | } |
| 132 | } |
| 133 | // If the access is rwm, skip the check. |
| 134 | hasAccess := bpfAccess != (unix.BPF_DEVCG_ACC_READ | unix.BPF_DEVCG_ACC_WRITE | unix.BPF_DEVCG_ACC_MKNOD) |
| 135 | |
| 136 | blockSym := fmt.Sprintf("block-%d", p.blockID) |
| 137 | nextBlockSym := fmt.Sprintf("block-%d", p.blockID+1) |
| 138 | prevBlockLastIdx := len(p.insts) - 1 |
| 139 | if hasType { |
| 140 | p.insts = append(p.insts, |
| 141 | // if (R2 != bpfType) goto next |
| 142 | asm.JNE.Imm(asm.R2, bpfType, nextBlockSym), |
| 143 | ) |
| 144 | } |
| 145 | if hasAccess { |
| 146 | p.insts = append(p.insts, |
| 147 | // if (R3 & bpfAccess == 0 /* use R1 as a temp var */) goto next |
no test coverage detected