gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

cap_freebsd.go (5149B)


      1 // Copyright 2017 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 //go:build freebsd
      6 // +build freebsd
      7 
      8 package unix
      9 
     10 import (
     11 	"errors"
     12 	"fmt"
     13 )
     14 
     15 // Go implementation of C mostly found in /usr/src/sys/kern/subr_capability.c
     16 
     17 const (
     18 	// This is the version of CapRights this package understands. See C implementation for parallels.
     19 	capRightsGoVersion = CAP_RIGHTS_VERSION_00
     20 	capArSizeMin       = CAP_RIGHTS_VERSION_00 + 2
     21 	capArSizeMax       = capRightsGoVersion + 2
     22 )
     23 
     24 var (
     25 	bit2idx = []int{
     26 		-1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1,
     27 		4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     28 	}
     29 )
     30 
     31 func capidxbit(right uint64) int {
     32 	return int((right >> 57) & 0x1f)
     33 }
     34 
     35 func rightToIndex(right uint64) (int, error) {
     36 	idx := capidxbit(right)
     37 	if idx < 0 || idx >= len(bit2idx) {
     38 		return -2, fmt.Errorf("index for right 0x%x out of range", right)
     39 	}
     40 	return bit2idx[idx], nil
     41 }
     42 
     43 func caprver(right uint64) int {
     44 	return int(right >> 62)
     45 }
     46 
     47 func capver(rights *CapRights) int {
     48 	return caprver(rights.Rights[0])
     49 }
     50 
     51 func caparsize(rights *CapRights) int {
     52 	return capver(rights) + 2
     53 }
     54 
     55 // CapRightsSet sets the permissions in setrights in rights.
     56 func CapRightsSet(rights *CapRights, setrights []uint64) error {
     57 	// This is essentially a copy of cap_rights_vset()
     58 	if capver(rights) != CAP_RIGHTS_VERSION_00 {
     59 		return fmt.Errorf("bad rights version %d", capver(rights))
     60 	}
     61 
     62 	n := caparsize(rights)
     63 	if n < capArSizeMin || n > capArSizeMax {
     64 		return errors.New("bad rights size")
     65 	}
     66 
     67 	for _, right := range setrights {
     68 		if caprver(right) != CAP_RIGHTS_VERSION_00 {
     69 			return errors.New("bad right version")
     70 		}
     71 		i, err := rightToIndex(right)
     72 		if err != nil {
     73 			return err
     74 		}
     75 		if i >= n {
     76 			return errors.New("index overflow")
     77 		}
     78 		if capidxbit(rights.Rights[i]) != capidxbit(right) {
     79 			return errors.New("index mismatch")
     80 		}
     81 		rights.Rights[i] |= right
     82 		if capidxbit(rights.Rights[i]) != capidxbit(right) {
     83 			return errors.New("index mismatch (after assign)")
     84 		}
     85 	}
     86 
     87 	return nil
     88 }
     89 
     90 // CapRightsClear clears the permissions in clearrights from rights.
     91 func CapRightsClear(rights *CapRights, clearrights []uint64) error {
     92 	// This is essentially a copy of cap_rights_vclear()
     93 	if capver(rights) != CAP_RIGHTS_VERSION_00 {
     94 		return fmt.Errorf("bad rights version %d", capver(rights))
     95 	}
     96 
     97 	n := caparsize(rights)
     98 	if n < capArSizeMin || n > capArSizeMax {
     99 		return errors.New("bad rights size")
    100 	}
    101 
    102 	for _, right := range clearrights {
    103 		if caprver(right) != CAP_RIGHTS_VERSION_00 {
    104 			return errors.New("bad right version")
    105 		}
    106 		i, err := rightToIndex(right)
    107 		if err != nil {
    108 			return err
    109 		}
    110 		if i >= n {
    111 			return errors.New("index overflow")
    112 		}
    113 		if capidxbit(rights.Rights[i]) != capidxbit(right) {
    114 			return errors.New("index mismatch")
    115 		}
    116 		rights.Rights[i] &= ^(right & 0x01FFFFFFFFFFFFFF)
    117 		if capidxbit(rights.Rights[i]) != capidxbit(right) {
    118 			return errors.New("index mismatch (after assign)")
    119 		}
    120 	}
    121 
    122 	return nil
    123 }
    124 
    125 // CapRightsIsSet checks whether all the permissions in setrights are present in rights.
    126 func CapRightsIsSet(rights *CapRights, setrights []uint64) (bool, error) {
    127 	// This is essentially a copy of cap_rights_is_vset()
    128 	if capver(rights) != CAP_RIGHTS_VERSION_00 {
    129 		return false, fmt.Errorf("bad rights version %d", capver(rights))
    130 	}
    131 
    132 	n := caparsize(rights)
    133 	if n < capArSizeMin || n > capArSizeMax {
    134 		return false, errors.New("bad rights size")
    135 	}
    136 
    137 	for _, right := range setrights {
    138 		if caprver(right) != CAP_RIGHTS_VERSION_00 {
    139 			return false, errors.New("bad right version")
    140 		}
    141 		i, err := rightToIndex(right)
    142 		if err != nil {
    143 			return false, err
    144 		}
    145 		if i >= n {
    146 			return false, errors.New("index overflow")
    147 		}
    148 		if capidxbit(rights.Rights[i]) != capidxbit(right) {
    149 			return false, errors.New("index mismatch")
    150 		}
    151 		if (rights.Rights[i] & right) != right {
    152 			return false, nil
    153 		}
    154 	}
    155 
    156 	return true, nil
    157 }
    158 
    159 func capright(idx uint64, bit uint64) uint64 {
    160 	return ((1 << (57 + idx)) | bit)
    161 }
    162 
    163 // CapRightsInit returns a pointer to an initialised CapRights structure filled with rights.
    164 // See man cap_rights_init(3) and rights(4).
    165 func CapRightsInit(rights []uint64) (*CapRights, error) {
    166 	var r CapRights
    167 	r.Rights[0] = (capRightsGoVersion << 62) | capright(0, 0)
    168 	r.Rights[1] = capright(1, 0)
    169 
    170 	err := CapRightsSet(&r, rights)
    171 	if err != nil {
    172 		return nil, err
    173 	}
    174 	return &r, nil
    175 }
    176 
    177 // CapRightsLimit reduces the operations permitted on fd to at most those contained in rights.
    178 // The capability rights on fd can never be increased by CapRightsLimit.
    179 // See man cap_rights_limit(2) and rights(4).
    180 func CapRightsLimit(fd uintptr, rights *CapRights) error {
    181 	return capRightsLimit(int(fd), rights)
    182 }
    183 
    184 // CapRightsGet returns a CapRights structure containing the operations permitted on fd.
    185 // See man cap_rights_get(3) and rights(4).
    186 func CapRightsGet(fd uintptr) (*CapRights, error) {
    187 	r, err := CapRightsInit(nil)
    188 	if err != nil {
    189 		return nil, err
    190 	}
    191 	err = capRightsGet(capRightsGoVersion, int(fd), r)
    192 	if err != nil {
    193 		return nil, err
    194 	}
    195 	return r, nil
    196 }