浏览代码

vendor: github.com/opencontainers/selinux v1.9.1

full diff: https://github.com/opencontainers/selinux/compare/v1.8.2...v1.9.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 3 年之前
父节点
当前提交
615ff22437
共有 24 个文件被更改,包括 384 次插入1529 次删除
  1. 1 2
      vendor.conf
  2. 0 27
      vendor/github.com/bits-and-blooms/bitset/LICENSE
  3. 0 93
      vendor/github.com/bits-and-blooms/bitset/README.md
  4. 0 952
      vendor/github.com/bits-and-blooms/bitset/bitset.go
  5. 0 3
      vendor/github.com/bits-and-blooms/bitset/go.mod
  6. 0 53
      vendor/github.com/bits-and-blooms/bitset/popcnt.go
  7. 0 45
      vendor/github.com/bits-and-blooms/bitset/popcnt_19.go
  8. 0 68
      vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go
  9. 0 104
      vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s
  10. 0 24
      vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go
  11. 0 14
      vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go
  12. 0 9
      vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go
  13. 8 5
      vendor/github.com/opencontainers/selinux/go-selinux/label/label_linux.go
  14. 22 0
      vendor/github.com/opencontainers/selinux/go-selinux/rchcon.go
  15. 21 0
      vendor/github.com/opencontainers/selinux/go-selinux/rchcon_go115.go
  16. 7 1
      vendor/github.com/opencontainers/selinux/go-selinux/selinux.go
  17. 126 115
      vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
  18. 4 2
      vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
  19. 2 2
      vendor/github.com/opencontainers/selinux/go-selinux/xattrs_linux.go
  20. 1 5
      vendor/github.com/opencontainers/selinux/go.mod
  21. 6 0
      vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md
  22. 16 5
      vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go
  23. 54 0
      vendor/github.com/opencontainers/selinux/pkg/pwalkdir/README.md
  24. 116 0
      vendor/github.com/opencontainers/selinux/pkg/pwalkdir/pwalkdir.go

+ 1 - 2
vendor.conf

@@ -175,8 +175,7 @@ github.com/morikuni/aec                             39771216ff4c63d11f5e604076f9
 # metrics
 # metrics
 github.com/docker/go-metrics                        b619b3592b65de4f087d9f16863a7e6ff905973c # v0.0.1
 github.com/docker/go-metrics                        b619b3592b65de4f087d9f16863a7e6ff905973c # v0.0.1
 
 
-github.com/opencontainers/selinux                   76bc82e11d854d3e40c08889d13c98abcea72ea2 # v1.8.2
-github.com/bits-and-blooms/bitset                   59de210119f50cedaa42d175dc88b6335fcf63f6 # v1.2.0
+github.com/opencontainers/selinux                   95d3852f356b31cbb2d84040ffca303911d08273 # v1.9.1
 
 
 
 
 # archive/tar
 # archive/tar

+ 0 - 27
vendor/github.com/bits-and-blooms/bitset/LICENSE

@@ -1,27 +0,0 @@
-Copyright (c) 2014 Will Fitzgerald. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-   * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-   * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 0 - 93
vendor/github.com/bits-and-blooms/bitset/README.md

@@ -1,93 +0,0 @@
-# bitset
-
-*Go language library to map between non-negative integers and boolean values*
-
-[![Test](https://github.com/bits-and-blooms/bitset/workflows/Test/badge.svg)](https://github.com/willf/bitset/actions?query=workflow%3ATest)
-[![Go Report Card](https://goreportcard.com/badge/github.com/willf/bitset)](https://goreportcard.com/report/github.com/willf/bitset)
-[![PkgGoDev](https://pkg.go.dev/badge/github.com/bits-and-blooms/bitset?tab=doc)](https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc)
-
-
-## Description
-
-Package bitset implements bitsets, a mapping between non-negative integers and boolean values.
-It should be more efficient than map[uint] bool.
-
-It provides methods for setting, clearing, flipping, and testing individual integers.
-
-But it also provides set intersection, union, difference, complement, and symmetric operations, as well as tests to check whether any, all, or no bits are set, and querying a bitset's current length and number of positive bits.
-
-BitSets are expanded to the size of the largest set bit; the memory allocation is approximately Max bits, where Max is the largest set bit. BitSets are never shrunk. On creation, a hint can be given for the number of bits that will be used.
-
-Many of the methods, including Set, Clear, and Flip, return a BitSet pointer, which allows for chaining.
-
-### Example use:
-
-```go
-package main
-
-import (
-	"fmt"
-	"math/rand"
-
-	"github.com/bits-and-blooms/bitset"
-)
-
-func main() {
-	fmt.Printf("Hello from BitSet!\n")
-	var b bitset.BitSet
-	// play some Go Fish
-	for i := 0; i < 100; i++ {
-		card1 := uint(rand.Intn(52))
-		card2 := uint(rand.Intn(52))
-		b.Set(card1)
-		if b.Test(card2) {
-			fmt.Println("Go Fish!")
-		}
-		b.Clear(card1)
-	}
-
-	// Chaining
-	b.Set(10).Set(11)
-
-	for i, e := b.NextSet(0); e; i, e = b.NextSet(i + 1) {
-		fmt.Println("The following bit is set:", i)
-	}
-	if b.Intersection(bitset.New(100).Set(10)).Count() == 1 {
-		fmt.Println("Intersection works.")
-	} else {
-		fmt.Println("Intersection doesn't work???")
-	}
-}
-```
-
-As an alternative to BitSets, one should check out the 'big' package, which provides a (less set-theoretical) view of bitsets.
-
-Package documentation is at: https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc
-
-## Memory Usage
-
-The memory usage of a bitset using N bits is at least N/8 bytes. The number of bits in a bitset is at least as large as one plus the greatest bit index you have accessed. Thus it is possible to run out of memory while using a bitset. If you have lots of bits, you might prefer compressed bitsets, like the [Roaring bitmaps](http://roaringbitmap.org) and its [Go implementation](https://github.com/RoaringBitmap/roaring).
-
-## Implementation Note
-
-Go 1.9 introduced a native `math/bits` library. We provide backward compatibility to Go 1.7, which might be removed.
-
-It is possible that a later version will match the `math/bits` return signature for counts (which is `int`, rather than our library's `unit64`). If so, the version will be bumped.
-
-## Installation
-
-```bash
-go get github.com/bits-and-blooms/bitset
-```
-
-## Contributing
-
-If you wish to contribute to this project, please branch and issue a pull request against master ("[GitHub Flow](https://guides.github.com/introduction/flow/)")
-
-## Running all tests
-
-Before committing the code, please check if it passes tests, has adequate coverage, etc.
-```bash
-go test
-go test -cover
-```

+ 0 - 952
vendor/github.com/bits-and-blooms/bitset/bitset.go

@@ -1,952 +0,0 @@
-/*
-Package bitset implements bitsets, a mapping
-between non-negative integers and boolean values. It should be more
-efficient than map[uint] bool.
-
-It provides methods for setting, clearing, flipping, and testing
-individual integers.
-
-But it also provides set intersection, union, difference,
-complement, and symmetric operations, as well as tests to
-check whether any, all, or no bits are set, and querying a
-bitset's current length and number of positive bits.
-
-BitSets are expanded to the size of the largest set bit; the
-memory allocation is approximately Max bits, where Max is
-the largest set bit. BitSets are never shrunk. On creation,
-a hint can be given for the number of bits that will be used.
-
-Many of the methods, including Set,Clear, and Flip, return
-a BitSet pointer, which allows for chaining.
-
-Example use:
-
-	import "bitset"
-	var b BitSet
-	b.Set(10).Set(11)
-	if b.Test(1000) {
-		b.Clear(1000)
-	}
-	if B.Intersection(bitset.New(100).Set(10)).Count() > 1 {
-		fmt.Println("Intersection works.")
-	}
-
-As an alternative to BitSets, one should check out the 'big' package,
-which provides a (less set-theoretical) view of bitsets.
-
-*/
-package bitset
-
-import (
-	"bufio"
-	"bytes"
-	"encoding/base64"
-	"encoding/binary"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"io"
-	"strconv"
-)
-
-// the wordSize of a bit set
-const wordSize = uint(64)
-
-// log2WordSize is lg(wordSize)
-const log2WordSize = uint(6)
-
-// allBits has every bit set
-const allBits uint64 = 0xffffffffffffffff
-
-// default binary BigEndian
-var binaryOrder binary.ByteOrder = binary.BigEndian
-
-// default json encoding base64.URLEncoding
-var base64Encoding = base64.URLEncoding
-
-// Base64StdEncoding Marshal/Unmarshal BitSet with base64.StdEncoding(Default: base64.URLEncoding)
-func Base64StdEncoding() { base64Encoding = base64.StdEncoding }
-
-// LittleEndian Marshal/Unmarshal Binary as Little Endian(Default: binary.BigEndian)
-func LittleEndian() { binaryOrder = binary.LittleEndian }
-
-// A BitSet is a set of bits. The zero value of a BitSet is an empty set of length 0.
-type BitSet struct {
-	length uint
-	set    []uint64
-}
-
-// Error is used to distinguish errors (panics) generated in this package.
-type Error string
-
-// safeSet will fixup b.set to be non-nil and return the field value
-func (b *BitSet) safeSet() []uint64 {
-	if b.set == nil {
-		b.set = make([]uint64, wordsNeeded(0))
-	}
-	return b.set
-}
-
-// From is a constructor used to create a BitSet from an array of integers
-func From(buf []uint64) *BitSet {
-	return &BitSet{uint(len(buf)) * 64, buf}
-}
-
-// Bytes returns the bitset as array of integers
-func (b *BitSet) Bytes() []uint64 {
-	return b.set
-}
-
-// wordsNeeded calculates the number of words needed for i bits
-func wordsNeeded(i uint) int {
-	if i > (Cap() - wordSize + 1) {
-		return int(Cap() >> log2WordSize)
-	}
-	return int((i + (wordSize - 1)) >> log2WordSize)
-}
-
-// New creates a new BitSet with a hint that length bits will be required
-func New(length uint) (bset *BitSet) {
-	defer func() {
-		if r := recover(); r != nil {
-			bset = &BitSet{
-				0,
-				make([]uint64, 0),
-			}
-		}
-	}()
-
-	bset = &BitSet{
-		length,
-		make([]uint64, wordsNeeded(length)),
-	}
-
-	return bset
-}
-
-// Cap returns the total possible capacity, or number of bits
-func Cap() uint {
-	return ^uint(0)
-}
-
-// Len returns the number of bits in the BitSet.
-// Note the difference to method Count, see example.
-func (b *BitSet) Len() uint {
-	return b.length
-}
-
-// extendSetMaybe adds additional words to incorporate new bits if needed
-func (b *BitSet) extendSetMaybe(i uint) {
-	if i >= b.length { // if we need more bits, make 'em
-		if i >= Cap() {
-			panic("You are exceeding the capacity")
-		}
-		nsize := wordsNeeded(i + 1)
-		if b.set == nil {
-			b.set = make([]uint64, nsize)
-		} else if cap(b.set) >= nsize {
-			b.set = b.set[:nsize] // fast resize
-		} else if len(b.set) < nsize {
-			newset := make([]uint64, nsize, 2*nsize) // increase capacity 2x
-			copy(newset, b.set)
-			b.set = newset
-		}
-		b.length = i + 1
-	}
-}
-
-// Test whether bit i is set.
-func (b *BitSet) Test(i uint) bool {
-	if i >= b.length {
-		return false
-	}
-	return b.set[i>>log2WordSize]&(1<<(i&(wordSize-1))) != 0
-}
-
-// Set bit i to 1, the capacity of the bitset is automatically
-// increased accordingly.
-// If i>= Cap(), this function will panic.
-// Warning: using a very large value for 'i'
-// may lead to a memory shortage and a panic: the caller is responsible
-// for providing sensible parameters in line with their memory capacity.
-func (b *BitSet) Set(i uint) *BitSet {
-	b.extendSetMaybe(i)
-	b.set[i>>log2WordSize] |= 1 << (i & (wordSize - 1))
-	return b
-}
-
-// Clear bit i to 0
-func (b *BitSet) Clear(i uint) *BitSet {
-	if i >= b.length {
-		return b
-	}
-	b.set[i>>log2WordSize] &^= 1 << (i & (wordSize - 1))
-	return b
-}
-
-// SetTo sets bit i to value.
-// If i>= Cap(), this function will panic.
-// Warning: using a very large value for 'i'
-// may lead to a memory shortage and a panic: the caller is responsible
-// for providing sensible parameters in line with their memory capacity.
-func (b *BitSet) SetTo(i uint, value bool) *BitSet {
-	if value {
-		return b.Set(i)
-	}
-	return b.Clear(i)
-}
-
-// Flip bit at i.
-// If i>= Cap(), this function will panic.
-// Warning: using a very large value for 'i'
-// may lead to a memory shortage and a panic: the caller is responsible
-// for providing sensible parameters in line with their memory capacity.
-func (b *BitSet) Flip(i uint) *BitSet {
-	if i >= b.length {
-		return b.Set(i)
-	}
-	b.set[i>>log2WordSize] ^= 1 << (i & (wordSize - 1))
-	return b
-}
-
-// FlipRange bit in [start, end).
-// If end>= Cap(), this function will panic.
-// Warning: using a very large value for 'end'
-// may lead to a memory shortage and a panic: the caller is responsible
-// for providing sensible parameters in line with their memory capacity.
-func (b *BitSet) FlipRange(start, end uint) *BitSet {
-	if start >= end {
-		return b
-	}
-
-	b.extendSetMaybe(end - 1)
-	var startWord uint = start >> log2WordSize
-	var endWord uint = end >> log2WordSize
-	b.set[startWord] ^= ^(^uint64(0) << (start & (wordSize - 1)))
-	for i := startWord; i < endWord; i++ {
-		b.set[i] = ^b.set[i]
-	}
-	b.set[endWord] ^= ^uint64(0) >> (-end & (wordSize - 1))
-	return b
-}
-
-// Shrink shrinks BitSet so that the provided value is the last possible
-// set value. It clears all bits > the provided index and reduces the size
-// and length of the set.
-//
-// Note that the parameter value is not the new length in bits: it is the
-// maximal value that can be stored in the bitset after the function call.
-// The new length in bits is the parameter value + 1. Thus it is not possible
-// to use this function to set the length to 0, the minimal value of the length
-// after this function call is 1.
-//
-// A new slice is allocated to store the new bits, so you may see an increase in
-// memory usage until the GC runs. Normally this should not be a problem, but if you
-// have an extremely large BitSet its important to understand that the old BitSet will
-// remain in memory until the GC frees it.
-func (b *BitSet) Shrink(lastbitindex uint) *BitSet {
-	length := lastbitindex + 1
-	idx := wordsNeeded(length)
-	if idx > len(b.set) {
-		return b
-	}
-	shrunk := make([]uint64, idx)
-	copy(shrunk, b.set[:idx])
-	b.set = shrunk
-	b.length = length
-	b.set[idx-1] &= (allBits >> (uint64(64) - uint64(length&(wordSize-1))))
-	return b
-}
-
-// Compact shrinks BitSet to so that we preserve all set bits, while minimizing
-// memory usage. Compact calls Shrink.
-func (b *BitSet) Compact() *BitSet {
-	idx := len(b.set) - 1
-	for ; idx >= 0 && b.set[idx] == 0; idx-- {
-	}
-	newlength := uint((idx + 1) << log2WordSize)
-	if newlength >= b.length {
-		return b // nothing to do
-	}
-	if newlength > 0 {
-		return b.Shrink(newlength - 1)
-	}
-	// We preserve one word
-	return b.Shrink(63)
-}
-
-// InsertAt takes an index which indicates where a bit should be
-// inserted. Then it shifts all the bits in the set to the left by 1, starting
-// from the given index position, and sets the index position to 0.
-//
-// Depending on the size of your BitSet, and where you are inserting the new entry,
-// this method could be extremely slow and in some cases might cause the entire BitSet
-// to be recopied.
-func (b *BitSet) InsertAt(idx uint) *BitSet {
-	insertAtElement := (idx >> log2WordSize)
-
-	// if length of set is a multiple of wordSize we need to allocate more space first
-	if b.isLenExactMultiple() {
-		b.set = append(b.set, uint64(0))
-	}
-
-	var i uint
-	for i = uint(len(b.set) - 1); i > insertAtElement; i-- {
-		// all elements above the position where we want to insert can simply by shifted
-		b.set[i] <<= 1
-
-		// we take the most significant bit of the previous element and set it as
-		// the least significant bit of the current element
-		b.set[i] |= (b.set[i-1] & 0x8000000000000000) >> 63
-	}
-
-	// generate a mask to extract the data that we need to shift left
-	// within the element where we insert a bit
-	dataMask := ^(uint64(1)<<uint64(idx&(wordSize-1)) - 1)
-
-	// extract that data that we'll shift
-	data := b.set[i] & dataMask
-
-	// set the positions of the data mask to 0 in the element where we insert
-	b.set[i] &= ^dataMask
-
-	// shift data mask to the left and insert its data to the slice element
-	b.set[i] |= data << 1
-
-	// add 1 to length of BitSet
-	b.length++
-
-	return b
-}
-
-// String creates a string representation of the Bitmap
-func (b *BitSet) String() string {
-	// follows code from https://github.com/RoaringBitmap/roaring
-	var buffer bytes.Buffer
-	start := []byte("{")
-	buffer.Write(start)
-	counter := 0
-	i, e := b.NextSet(0)
-	for e {
-		counter = counter + 1
-		// to avoid exhausting the memory
-		if counter > 0x40000 {
-			buffer.WriteString("...")
-			break
-		}
-		buffer.WriteString(strconv.FormatInt(int64(i), 10))
-		i, e = b.NextSet(i + 1)
-		if e {
-			buffer.WriteString(",")
-		}
-	}
-	buffer.WriteString("}")
-	return buffer.String()
-}
-
-// DeleteAt deletes the bit at the given index position from
-// within the bitset
-// All the bits residing on the left of the deleted bit get
-// shifted right by 1
-// The running time of this operation may potentially be
-// relatively slow, O(length)
-func (b *BitSet) DeleteAt(i uint) *BitSet {
-	// the index of the slice element where we'll delete a bit
-	deleteAtElement := i >> log2WordSize
-
-	// generate a mask for the data that needs to be shifted right
-	// within that slice element that gets modified
-	dataMask := ^((uint64(1) << (i & (wordSize - 1))) - 1)
-
-	// extract the data that we'll shift right from the slice element
-	data := b.set[deleteAtElement] & dataMask
-
-	// set the masked area to 0 while leaving the rest as it is
-	b.set[deleteAtElement] &= ^dataMask
-
-	// shift the previously extracted data to the right and then
-	// set it in the previously masked area
-	b.set[deleteAtElement] |= (data >> 1) & dataMask
-
-	// loop over all the consecutive slice elements to copy each
-	// lowest bit into the highest position of the previous element,
-	// then shift the entire content to the right by 1
-	for i := int(deleteAtElement) + 1; i < len(b.set); i++ {
-		b.set[i-1] |= (b.set[i] & 1) << 63
-		b.set[i] >>= 1
-	}
-
-	b.length = b.length - 1
-
-	return b
-}
-
-// NextSet returns the next bit set from the specified index,
-// including possibly the current index
-// along with an error code (true = valid, false = no set bit found)
-// for i,e := v.NextSet(0); e; i,e = v.NextSet(i + 1) {...}
-//
-// Users concerned with performance may want to use NextSetMany to
-// retrieve several values at once.
-func (b *BitSet) NextSet(i uint) (uint, bool) {
-	x := int(i >> log2WordSize)
-	if x >= len(b.set) {
-		return 0, false
-	}
-	w := b.set[x]
-	w = w >> (i & (wordSize - 1))
-	if w != 0 {
-		return i + trailingZeroes64(w), true
-	}
-	x = x + 1
-	for x < len(b.set) {
-		if b.set[x] != 0 {
-			return uint(x)*wordSize + trailingZeroes64(b.set[x]), true
-		}
-		x = x + 1
-
-	}
-	return 0, false
-}
-
-// NextSetMany returns many next bit sets from the specified index,
-// including possibly the current index and up to cap(buffer).
-// If the returned slice has len zero, then no more set bits were found
-//
-//    buffer := make([]uint, 256) // this should be reused
-//    j := uint(0)
-//    j, buffer = bitmap.NextSetMany(j, buffer)
-//    for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j,buffer) {
-//     for k := range buffer {
-//      do something with buffer[k]
-//     }
-//     j += 1
-//    }
-//
-//
-// It is possible to retrieve all set bits as follow:
-//
-//    indices := make([]uint, bitmap.Count())
-//    bitmap.NextSetMany(0, indices)
-//
-// However if bitmap.Count() is large, it might be preferable to
-// use several calls to NextSetMany, for performance reasons.
-func (b *BitSet) NextSetMany(i uint, buffer []uint) (uint, []uint) {
-	myanswer := buffer
-	capacity := cap(buffer)
-	x := int(i >> log2WordSize)
-	if x >= len(b.set) || capacity == 0 {
-		return 0, myanswer[:0]
-	}
-	skip := i & (wordSize - 1)
-	word := b.set[x] >> skip
-	myanswer = myanswer[:capacity]
-	size := int(0)
-	for word != 0 {
-		r := trailingZeroes64(word)
-		t := word & ((^word) + 1)
-		myanswer[size] = r + i
-		size++
-		if size == capacity {
-			goto End
-		}
-		word = word ^ t
-	}
-	x++
-	for idx, word := range b.set[x:] {
-		for word != 0 {
-			r := trailingZeroes64(word)
-			t := word & ((^word) + 1)
-			myanswer[size] = r + (uint(x+idx) << 6)
-			size++
-			if size == capacity {
-				goto End
-			}
-			word = word ^ t
-		}
-	}
-End:
-	if size > 0 {
-		return myanswer[size-1], myanswer[:size]
-	}
-	return 0, myanswer[:0]
-}
-
-// NextClear returns the next clear bit from the specified index,
-// including possibly the current index
-// along with an error code (true = valid, false = no bit found i.e. all bits are set)
-func (b *BitSet) NextClear(i uint) (uint, bool) {
-	x := int(i >> log2WordSize)
-	if x >= len(b.set) {
-		return 0, false
-	}
-	w := b.set[x]
-	w = w >> (i & (wordSize - 1))
-	wA := allBits >> (i & (wordSize - 1))
-	index := i + trailingZeroes64(^w)
-	if w != wA && index < b.length {
-		return index, true
-	}
-	x++
-	for x < len(b.set) {
-		index = uint(x)*wordSize + trailingZeroes64(^b.set[x])
-		if b.set[x] != allBits && index < b.length {
-			return index, true
-		}
-		x++
-	}
-	return 0, false
-}
-
-// ClearAll clears the entire BitSet
-func (b *BitSet) ClearAll() *BitSet {
-	if b != nil && b.set != nil {
-		for i := range b.set {
-			b.set[i] = 0
-		}
-	}
-	return b
-}
-
-// wordCount returns the number of words used in a bit set
-func (b *BitSet) wordCount() int {
-	return len(b.set)
-}
-
-// Clone this BitSet
-func (b *BitSet) Clone() *BitSet {
-	c := New(b.length)
-	if b.set != nil { // Clone should not modify current object
-		copy(c.set, b.set)
-	}
-	return c
-}
-
-// Copy into a destination BitSet
-// Returning the size of the destination BitSet
-// like array copy
-func (b *BitSet) Copy(c *BitSet) (count uint) {
-	if c == nil {
-		return
-	}
-	if b.set != nil { // Copy should not modify current object
-		copy(c.set, b.set)
-	}
-	count = c.length
-	if b.length < c.length {
-		count = b.length
-	}
-	return
-}
-
-// Count (number of set bits).
-// Also known as "popcount" or "population count".
-func (b *BitSet) Count() uint {
-	if b != nil && b.set != nil {
-		return uint(popcntSlice(b.set))
-	}
-	return 0
-}
-
-// Equal tests the equivalence of two BitSets.
-// False if they are of different sizes, otherwise true
-// only if all the same bits are set
-func (b *BitSet) Equal(c *BitSet) bool {
-	if c == nil || b == nil {
-		return c == b
-	}
-	if b.length != c.length {
-		return false
-	}
-	if b.length == 0 { // if they have both length == 0, then could have nil set
-		return true
-	}
-	// testing for equality shoud not transform the bitset (no call to safeSet)
-
-	for p, v := range b.set {
-		if c.set[p] != v {
-			return false
-		}
-	}
-	return true
-}
-
-func panicIfNull(b *BitSet) {
-	if b == nil {
-		panic(Error("BitSet must not be null"))
-	}
-}
-
-// Difference of base set and other set
-// This is the BitSet equivalent of &^ (and not)
-func (b *BitSet) Difference(compare *BitSet) (result *BitSet) {
-	panicIfNull(b)
-	panicIfNull(compare)
-	result = b.Clone() // clone b (in case b is bigger than compare)
-	l := int(compare.wordCount())
-	if l > int(b.wordCount()) {
-		l = int(b.wordCount())
-	}
-	for i := 0; i < l; i++ {
-		result.set[i] = b.set[i] &^ compare.set[i]
-	}
-	return
-}
-
-// DifferenceCardinality computes the cardinality of the differnce
-func (b *BitSet) DifferenceCardinality(compare *BitSet) uint {
-	panicIfNull(b)
-	panicIfNull(compare)
-	l := int(compare.wordCount())
-	if l > int(b.wordCount()) {
-		l = int(b.wordCount())
-	}
-	cnt := uint64(0)
-	cnt += popcntMaskSlice(b.set[:l], compare.set[:l])
-	cnt += popcntSlice(b.set[l:])
-	return uint(cnt)
-}
-
-// InPlaceDifference computes the difference of base set and other set
-// This is the BitSet equivalent of &^ (and not)
-func (b *BitSet) InPlaceDifference(compare *BitSet) {
-	panicIfNull(b)
-	panicIfNull(compare)
-	l := int(compare.wordCount())
-	if l > int(b.wordCount()) {
-		l = int(b.wordCount())
-	}
-	for i := 0; i < l; i++ {
-		b.set[i] &^= compare.set[i]
-	}
-}
-
-// Convenience function: return two bitsets ordered by
-// increasing length. Note: neither can be nil
-func sortByLength(a *BitSet, b *BitSet) (ap *BitSet, bp *BitSet) {
-	if a.length <= b.length {
-		ap, bp = a, b
-	} else {
-		ap, bp = b, a
-	}
-	return
-}
-
-// Intersection of base set and other set
-// This is the BitSet equivalent of & (and)
-func (b *BitSet) Intersection(compare *BitSet) (result *BitSet) {
-	panicIfNull(b)
-	panicIfNull(compare)
-	b, compare = sortByLength(b, compare)
-	result = New(b.length)
-	for i, word := range b.set {
-		result.set[i] = word & compare.set[i]
-	}
-	return
-}
-
-// IntersectionCardinality computes the cardinality of the union
-func (b *BitSet) IntersectionCardinality(compare *BitSet) uint {
-	panicIfNull(b)
-	panicIfNull(compare)
-	b, compare = sortByLength(b, compare)
-	cnt := popcntAndSlice(b.set, compare.set)
-	return uint(cnt)
-}
-
-// InPlaceIntersection destructively computes the intersection of
-// base set and the compare set.
-// This is the BitSet equivalent of & (and)
-func (b *BitSet) InPlaceIntersection(compare *BitSet) {
-	panicIfNull(b)
-	panicIfNull(compare)
-	l := int(compare.wordCount())
-	if l > int(b.wordCount()) {
-		l = int(b.wordCount())
-	}
-	for i := 0; i < l; i++ {
-		b.set[i] &= compare.set[i]
-	}
-	for i := l; i < len(b.set); i++ {
-		b.set[i] = 0
-	}
-	if compare.length > 0 {
-		b.extendSetMaybe(compare.length - 1)
-	}
-}
-
-// Union of base set and other set
-// This is the BitSet equivalent of | (or)
-func (b *BitSet) Union(compare *BitSet) (result *BitSet) {
-	panicIfNull(b)
-	panicIfNull(compare)
-	b, compare = sortByLength(b, compare)
-	result = compare.Clone()
-	for i, word := range b.set {
-		result.set[i] = word | compare.set[i]
-	}
-	return
-}
-
-// UnionCardinality computes the cardinality of the uniton of the base set
-// and the compare set.
-func (b *BitSet) UnionCardinality(compare *BitSet) uint {
-	panicIfNull(b)
-	panicIfNull(compare)
-	b, compare = sortByLength(b, compare)
-	cnt := popcntOrSlice(b.set, compare.set)
-	if len(compare.set) > len(b.set) {
-		cnt += popcntSlice(compare.set[len(b.set):])
-	}
-	return uint(cnt)
-}
-
-// InPlaceUnion creates the destructive union of base set and compare set.
-// This is the BitSet equivalent of | (or).
-func (b *BitSet) InPlaceUnion(compare *BitSet) {
-	panicIfNull(b)
-	panicIfNull(compare)
-	l := int(compare.wordCount())
-	if l > int(b.wordCount()) {
-		l = int(b.wordCount())
-	}
-	if compare.length > 0 {
-		b.extendSetMaybe(compare.length - 1)
-	}
-	for i := 0; i < l; i++ {
-		b.set[i] |= compare.set[i]
-	}
-	if len(compare.set) > l {
-		for i := l; i < len(compare.set); i++ {
-			b.set[i] = compare.set[i]
-		}
-	}
-}
-
-// SymmetricDifference of base set and other set
-// This is the BitSet equivalent of ^ (xor)
-func (b *BitSet) SymmetricDifference(compare *BitSet) (result *BitSet) {
-	panicIfNull(b)
-	panicIfNull(compare)
-	b, compare = sortByLength(b, compare)
-	// compare is bigger, so clone it
-	result = compare.Clone()
-	for i, word := range b.set {
-		result.set[i] = word ^ compare.set[i]
-	}
-	return
-}
-
-// SymmetricDifferenceCardinality computes the cardinality of the symmetric difference
-func (b *BitSet) SymmetricDifferenceCardinality(compare *BitSet) uint {
-	panicIfNull(b)
-	panicIfNull(compare)
-	b, compare = sortByLength(b, compare)
-	cnt := popcntXorSlice(b.set, compare.set)
-	if len(compare.set) > len(b.set) {
-		cnt += popcntSlice(compare.set[len(b.set):])
-	}
-	return uint(cnt)
-}
-
-// InPlaceSymmetricDifference creates the destructive SymmetricDifference of base set and other set
-// This is the BitSet equivalent of ^ (xor)
-func (b *BitSet) InPlaceSymmetricDifference(compare *BitSet) {
-	panicIfNull(b)
-	panicIfNull(compare)
-	l := int(compare.wordCount())
-	if l > int(b.wordCount()) {
-		l = int(b.wordCount())
-	}
-	if compare.length > 0 {
-		b.extendSetMaybe(compare.length - 1)
-	}
-	for i := 0; i < l; i++ {
-		b.set[i] ^= compare.set[i]
-	}
-	if len(compare.set) > l {
-		for i := l; i < len(compare.set); i++ {
-			b.set[i] = compare.set[i]
-		}
-	}
-}
-
-// Is the length an exact multiple of word sizes?
-func (b *BitSet) isLenExactMultiple() bool {
-	return b.length%wordSize == 0
-}
-
-// Clean last word by setting unused bits to 0
-func (b *BitSet) cleanLastWord() {
-	if !b.isLenExactMultiple() {
-		b.set[len(b.set)-1] &= allBits >> (wordSize - b.length%wordSize)
-	}
-}
-
-// Complement computes the (local) complement of a biset (up to length bits)
-func (b *BitSet) Complement() (result *BitSet) {
-	panicIfNull(b)
-	result = New(b.length)
-	for i, word := range b.set {
-		result.set[i] = ^word
-	}
-	result.cleanLastWord()
-	return
-}
-
-// All returns true if all bits are set, false otherwise. Returns true for
-// empty sets.
-func (b *BitSet) All() bool {
-	panicIfNull(b)
-	return b.Count() == b.length
-}
-
-// None returns true if no bit is set, false otherwise. Returns true for
-// empty sets.
-func (b *BitSet) None() bool {
-	panicIfNull(b)
-	if b != nil && b.set != nil {
-		for _, word := range b.set {
-			if word > 0 {
-				return false
-			}
-		}
-		return true
-	}
-	return true
-}
-
-// Any returns true if any bit is set, false otherwise
-func (b *BitSet) Any() bool {
-	panicIfNull(b)
-	return !b.None()
-}
-
-// IsSuperSet returns true if this is a superset of the other set
-func (b *BitSet) IsSuperSet(other *BitSet) bool {
-	for i, e := other.NextSet(0); e; i, e = other.NextSet(i + 1) {
-		if !b.Test(i) {
-			return false
-		}
-	}
-	return true
-}
-
-// IsStrictSuperSet returns true if this is a strict superset of the other set
-func (b *BitSet) IsStrictSuperSet(other *BitSet) bool {
-	return b.Count() > other.Count() && b.IsSuperSet(other)
-}
-
-// DumpAsBits dumps a bit set as a string of bits
-func (b *BitSet) DumpAsBits() string {
-	if b.set == nil {
-		return "."
-	}
-	buffer := bytes.NewBufferString("")
-	i := len(b.set) - 1
-	for ; i >= 0; i-- {
-		fmt.Fprintf(buffer, "%064b.", b.set[i])
-	}
-	return buffer.String()
-}
-
-// BinaryStorageSize returns the binary storage requirements
-func (b *BitSet) BinaryStorageSize() int {
-	return binary.Size(uint64(0)) + binary.Size(b.set)
-}
-
-// WriteTo writes a BitSet to a stream
-func (b *BitSet) WriteTo(stream io.Writer) (int64, error) {
-	length := uint64(b.length)
-
-	// Write length
-	err := binary.Write(stream, binaryOrder, length)
-	if err != nil {
-		return 0, err
-	}
-
-	// Write set
-	err = binary.Write(stream, binaryOrder, b.set)
-	return int64(b.BinaryStorageSize()), err
-}
-
-// ReadFrom reads a BitSet from a stream written using WriteTo
-func (b *BitSet) ReadFrom(stream io.Reader) (int64, error) {
-	var length uint64
-
-	// Read length first
-	err := binary.Read(stream, binaryOrder, &length)
-	if err != nil {
-		return 0, err
-	}
-	newset := New(uint(length))
-
-	if uint64(newset.length) != length {
-		return 0, errors.New("unmarshalling error: type mismatch")
-	}
-
-	// Read remaining bytes as set
-	err = binary.Read(stream, binaryOrder, newset.set)
-	if err != nil {
-		return 0, err
-	}
-
-	*b = *newset
-	return int64(b.BinaryStorageSize()), nil
-}
-
-// MarshalBinary encodes a BitSet into a binary form and returns the result.
-func (b *BitSet) MarshalBinary() ([]byte, error) {
-	var buf bytes.Buffer
-	writer := bufio.NewWriter(&buf)
-
-	_, err := b.WriteTo(writer)
-	if err != nil {
-		return []byte{}, err
-	}
-
-	err = writer.Flush()
-
-	return buf.Bytes(), err
-}
-
-// UnmarshalBinary decodes the binary form generated by MarshalBinary.
-func (b *BitSet) UnmarshalBinary(data []byte) error {
-	buf := bytes.NewReader(data)
-	reader := bufio.NewReader(buf)
-
-	_, err := b.ReadFrom(reader)
-
-	return err
-}
-
-// MarshalJSON marshals a BitSet as a JSON structure
-func (b *BitSet) MarshalJSON() ([]byte, error) {
-	buffer := bytes.NewBuffer(make([]byte, 0, b.BinaryStorageSize()))
-	_, err := b.WriteTo(buffer)
-	if err != nil {
-		return nil, err
-	}
-
-	// URLEncode all bytes
-	return json.Marshal(base64Encoding.EncodeToString(buffer.Bytes()))
-}
-
-// UnmarshalJSON unmarshals a BitSet from JSON created using MarshalJSON
-func (b *BitSet) UnmarshalJSON(data []byte) error {
-	// Unmarshal as string
-	var s string
-	err := json.Unmarshal(data, &s)
-	if err != nil {
-		return err
-	}
-
-	// URLDecode string
-	buf, err := base64Encoding.DecodeString(s)
-	if err != nil {
-		return err
-	}
-
-	_, err = b.ReadFrom(bytes.NewReader(buf))
-	return err
-}

+ 0 - 3
vendor/github.com/bits-and-blooms/bitset/go.mod

@@ -1,3 +0,0 @@
-module github.com/bits-and-blooms/bitset
-
-go 1.14

+ 0 - 53
vendor/github.com/bits-and-blooms/bitset/popcnt.go

@@ -1,53 +0,0 @@
-package bitset
-
-// bit population count, take from
-// https://code.google.com/p/go/issues/detail?id=4988#c11
-// credit: https://code.google.com/u/arnehormann/
-func popcount(x uint64) (n uint64) {
-	x -= (x >> 1) & 0x5555555555555555
-	x = (x>>2)&0x3333333333333333 + x&0x3333333333333333
-	x += x >> 4
-	x &= 0x0f0f0f0f0f0f0f0f
-	x *= 0x0101010101010101
-	return x >> 56
-}
-
-func popcntSliceGo(s []uint64) uint64 {
-	cnt := uint64(0)
-	for _, x := range s {
-		cnt += popcount(x)
-	}
-	return cnt
-}
-
-func popcntMaskSliceGo(s, m []uint64) uint64 {
-	cnt := uint64(0)
-	for i := range s {
-		cnt += popcount(s[i] &^ m[i])
-	}
-	return cnt
-}
-
-func popcntAndSliceGo(s, m []uint64) uint64 {
-	cnt := uint64(0)
-	for i := range s {
-		cnt += popcount(s[i] & m[i])
-	}
-	return cnt
-}
-
-func popcntOrSliceGo(s, m []uint64) uint64 {
-	cnt := uint64(0)
-	for i := range s {
-		cnt += popcount(s[i] | m[i])
-	}
-	return cnt
-}
-
-func popcntXorSliceGo(s, m []uint64) uint64 {
-	cnt := uint64(0)
-	for i := range s {
-		cnt += popcount(s[i] ^ m[i])
-	}
-	return cnt
-}

+ 0 - 45
vendor/github.com/bits-and-blooms/bitset/popcnt_19.go

@@ -1,45 +0,0 @@
-// +build go1.9
-
-package bitset
-
-import "math/bits"
-
-func popcntSlice(s []uint64) uint64 {
-	var cnt int
-	for _, x := range s {
-		cnt += bits.OnesCount64(x)
-	}
-	return uint64(cnt)
-}
-
-func popcntMaskSlice(s, m []uint64) uint64 {
-	var cnt int
-	for i := range s {
-		cnt += bits.OnesCount64(s[i] &^ m[i])
-	}
-	return uint64(cnt)
-}
-
-func popcntAndSlice(s, m []uint64) uint64 {
-	var cnt int
-	for i := range s {
-		cnt += bits.OnesCount64(s[i] & m[i])
-	}
-	return uint64(cnt)
-}
-
-func popcntOrSlice(s, m []uint64) uint64 {
-	var cnt int
-	for i := range s {
-		cnt += bits.OnesCount64(s[i] | m[i])
-	}
-	return uint64(cnt)
-}
-
-func popcntXorSlice(s, m []uint64) uint64 {
-	var cnt int
-	for i := range s {
-		cnt += bits.OnesCount64(s[i] ^ m[i])
-	}
-	return uint64(cnt)
-}

+ 0 - 68
vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go

@@ -1,68 +0,0 @@
-// +build !go1.9
-// +build amd64,!appengine
-
-package bitset
-
-// *** the following functions are defined in popcnt_amd64.s
-
-//go:noescape
-
-func hasAsm() bool
-
-// useAsm is a flag used to select the GO or ASM implementation of the popcnt function
-var useAsm = hasAsm()
-
-//go:noescape
-
-func popcntSliceAsm(s []uint64) uint64
-
-//go:noescape
-
-func popcntMaskSliceAsm(s, m []uint64) uint64
-
-//go:noescape
-
-func popcntAndSliceAsm(s, m []uint64) uint64
-
-//go:noescape
-
-func popcntOrSliceAsm(s, m []uint64) uint64
-
-//go:noescape
-
-func popcntXorSliceAsm(s, m []uint64) uint64
-
-func popcntSlice(s []uint64) uint64 {
-	if useAsm {
-		return popcntSliceAsm(s)
-	}
-	return popcntSliceGo(s)
-}
-
-func popcntMaskSlice(s, m []uint64) uint64 {
-	if useAsm {
-		return popcntMaskSliceAsm(s, m)
-	}
-	return popcntMaskSliceGo(s, m)
-}
-
-func popcntAndSlice(s, m []uint64) uint64 {
-	if useAsm {
-		return popcntAndSliceAsm(s, m)
-	}
-	return popcntAndSliceGo(s, m)
-}
-
-func popcntOrSlice(s, m []uint64) uint64 {
-	if useAsm {
-		return popcntOrSliceAsm(s, m)
-	}
-	return popcntOrSliceGo(s, m)
-}
-
-func popcntXorSlice(s, m []uint64) uint64 {
-	if useAsm {
-		return popcntXorSliceAsm(s, m)
-	}
-	return popcntXorSliceGo(s, m)
-}

+ 0 - 104
vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s

@@ -1,104 +0,0 @@
-// +build !go1.9
-// +build amd64,!appengine
-
-TEXT ·hasAsm(SB),4,$0-1
-MOVQ $1, AX
-CPUID
-SHRQ $23, CX
-ANDQ $1, CX
-MOVB CX, ret+0(FP)
-RET
-
-#define POPCNTQ_DX_DX BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0xd2
-
-TEXT ·popcntSliceAsm(SB),4,$0-32
-XORQ	AX, AX
-MOVQ	s+0(FP), SI
-MOVQ	s_len+8(FP), CX
-TESTQ	CX, CX
-JZ		popcntSliceEnd
-popcntSliceLoop:
-BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0x16 // POPCNTQ (SI), DX
-ADDQ	DX, AX
-ADDQ	$8, SI
-LOOP	popcntSliceLoop
-popcntSliceEnd:
-MOVQ	AX, ret+24(FP)
-RET
-
-TEXT ·popcntMaskSliceAsm(SB),4,$0-56
-XORQ	AX, AX
-MOVQ	s+0(FP), SI
-MOVQ	s_len+8(FP), CX
-TESTQ	CX, CX
-JZ		popcntMaskSliceEnd
-MOVQ	m+24(FP), DI
-popcntMaskSliceLoop:
-MOVQ	(DI), DX
-NOTQ	DX
-ANDQ	(SI), DX
-POPCNTQ_DX_DX
-ADDQ	DX, AX
-ADDQ	$8, SI
-ADDQ	$8, DI
-LOOP	popcntMaskSliceLoop
-popcntMaskSliceEnd:
-MOVQ	AX, ret+48(FP)
-RET
-
-TEXT ·popcntAndSliceAsm(SB),4,$0-56
-XORQ	AX, AX
-MOVQ	s+0(FP), SI
-MOVQ	s_len+8(FP), CX
-TESTQ	CX, CX
-JZ		popcntAndSliceEnd
-MOVQ	m+24(FP), DI
-popcntAndSliceLoop:
-MOVQ	(DI), DX
-ANDQ	(SI), DX
-POPCNTQ_DX_DX
-ADDQ	DX, AX
-ADDQ	$8, SI
-ADDQ	$8, DI
-LOOP	popcntAndSliceLoop
-popcntAndSliceEnd:
-MOVQ	AX, ret+48(FP)
-RET
-
-TEXT ·popcntOrSliceAsm(SB),4,$0-56
-XORQ	AX, AX
-MOVQ	s+0(FP), SI
-MOVQ	s_len+8(FP), CX
-TESTQ	CX, CX
-JZ		popcntOrSliceEnd
-MOVQ	m+24(FP), DI
-popcntOrSliceLoop:
-MOVQ	(DI), DX
-ORQ		(SI), DX
-POPCNTQ_DX_DX
-ADDQ	DX, AX
-ADDQ	$8, SI
-ADDQ	$8, DI
-LOOP	popcntOrSliceLoop
-popcntOrSliceEnd:
-MOVQ	AX, ret+48(FP)
-RET
-
-TEXT ·popcntXorSliceAsm(SB),4,$0-56
-XORQ	AX, AX
-MOVQ	s+0(FP), SI
-MOVQ	s_len+8(FP), CX
-TESTQ	CX, CX
-JZ		popcntXorSliceEnd
-MOVQ	m+24(FP), DI
-popcntXorSliceLoop:
-MOVQ	(DI), DX
-XORQ	(SI), DX
-POPCNTQ_DX_DX
-ADDQ	DX, AX
-ADDQ	$8, SI
-ADDQ	$8, DI
-LOOP	popcntXorSliceLoop
-popcntXorSliceEnd:
-MOVQ	AX, ret+48(FP)
-RET

+ 0 - 24
vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go

@@ -1,24 +0,0 @@
-// +build !go1.9
-// +build !amd64 appengine
-
-package bitset
-
-func popcntSlice(s []uint64) uint64 {
-	return popcntSliceGo(s)
-}
-
-func popcntMaskSlice(s, m []uint64) uint64 {
-	return popcntMaskSliceGo(s, m)
-}
-
-func popcntAndSlice(s, m []uint64) uint64 {
-	return popcntAndSliceGo(s, m)
-}
-
-func popcntOrSlice(s, m []uint64) uint64 {
-	return popcntOrSliceGo(s, m)
-}
-
-func popcntXorSlice(s, m []uint64) uint64 {
-	return popcntXorSliceGo(s, m)
-}

+ 0 - 14
vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go

@@ -1,14 +0,0 @@
-// +build !go1.9
-
-package bitset
-
-var deBruijn = [...]byte{
-	0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
-	62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,
-	63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,
-	54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6,
-}
-
-func trailingZeroes64(v uint64) uint {
-	return uint(deBruijn[((v&-v)*0x03f79d71b4ca8b09)>>58])
-}

+ 0 - 9
vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go

@@ -1,9 +0,0 @@
-// +build go1.9
-
-package bitset
-
-import "math/bits"
-
-func trailingZeroes64(v uint64) uint {
-	return uint(bits.TrailingZeros64(v))
-}

+ 8 - 5
vendor/github.com/opencontainers/selinux/go-selinux/label/label_linux.go

@@ -1,12 +1,13 @@
 package label
 package label
 
 
 import (
 import (
+	"errors"
+	"fmt"
 	"os"
 	"os"
 	"os/user"
 	"os/user"
 	"strings"
 	"strings"
 
 
 	"github.com/opencontainers/selinux/go-selinux"
 	"github.com/opencontainers/selinux/go-selinux"
-	"github.com/pkg/errors"
 )
 )
 
 
 // Valid Label Options
 // Valid Label Options
@@ -53,11 +54,11 @@ func InitLabels(options []string) (plabel string, mlabel string, retErr error) {
 				return "", selinux.PrivContainerMountLabel(), nil
 				return "", selinux.PrivContainerMountLabel(), nil
 			}
 			}
 			if i := strings.Index(opt, ":"); i == -1 {
 			if i := strings.Index(opt, ":"); i == -1 {
-				return "", "", errors.Errorf("Bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt)
+				return "", "", fmt.Errorf("Bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt)
 			}
 			}
 			con := strings.SplitN(opt, ":", 2)
 			con := strings.SplitN(opt, ":", 2)
 			if !validOptions[con[0]] {
 			if !validOptions[con[0]] {
-				return "", "", errors.Errorf("Bad label option %q, valid options 'disable, user, role, level, type, filetype'", con[0])
+				return "", "", fmt.Errorf("Bad label option %q, valid options 'disable, user, role, level, type, filetype'", con[0])
 			}
 			}
 			if con[0] == "filetype" {
 			if con[0] == "filetype" {
 				mcon["type"] = con[1]
 				mcon["type"] = con[1]
@@ -102,9 +103,11 @@ func SetFileCreateLabel(fileLabel string) error {
 	return selinux.SetFSCreateLabel(fileLabel)
 	return selinux.SetFSCreateLabel(fileLabel)
 }
 }
 
 
-// Relabel changes the label of path to the filelabel string.
+// Relabel changes the label of path and all the entries beneath the path.
 // It changes the MCS label to s0 if shared is true.
 // It changes the MCS label to s0 if shared is true.
 // This will allow all containers to share the content.
 // This will allow all containers to share the content.
+//
+// The path itself is guaranteed to be relabeled last.
 func Relabel(path string, fileLabel string, shared bool) error {
 func Relabel(path string, fileLabel string, shared bool) error {
 	if !selinux.GetEnabled() || fileLabel == "" {
 	if !selinux.GetEnabled() || fileLabel == "" {
 		return nil
 		return nil
@@ -151,7 +154,7 @@ func Relabel(path string, fileLabel string, shared bool) error {
 		path = strings.TrimSuffix(path, "/")
 		path = strings.TrimSuffix(path, "/")
 	}
 	}
 	if exclude_paths[path] {
 	if exclude_paths[path] {
-		return errors.Errorf("SELinux relabeling of %s is not allowed", path)
+		return fmt.Errorf("SELinux relabeling of %s is not allowed", path)
 	}
 	}
 
 
 	if shared {
 	if shared {

+ 22 - 0
vendor/github.com/opencontainers/selinux/go-selinux/rchcon.go

@@ -0,0 +1,22 @@
+// +build linux,go1.16
+
+package selinux
+
+import (
+	"errors"
+	"io/fs"
+	"os"
+
+	"github.com/opencontainers/selinux/pkg/pwalkdir"
+)
+
+func rchcon(fpath, label string) error {
+	return pwalkdir.Walk(fpath, func(p string, _ fs.DirEntry, _ error) error {
+		e := setFileLabel(p, label)
+		// Walk a file tree can race with removal, so ignore ENOENT.
+		if errors.Is(e, os.ErrNotExist) {
+			return nil
+		}
+		return e
+	})
+}

+ 21 - 0
vendor/github.com/opencontainers/selinux/go-selinux/rchcon_go115.go

@@ -0,0 +1,21 @@
+// +build linux,!go1.16
+
+package selinux
+
+import (
+	"errors"
+	"os"
+
+	"github.com/opencontainers/selinux/pkg/pwalk"
+)
+
+func rchcon(fpath, label string) error {
+	return pwalk.Walk(fpath, func(p string, _ os.FileInfo, _ error) error {
+		e := setFileLabel(p, label)
+		// Walk a file tree can race with removal, so ignore ENOENT.
+		if errors.Is(e, os.ErrNotExist) {
+			return nil
+		}
+		return e
+	})
+}

+ 7 - 1
vendor/github.com/opencontainers/selinux/go-selinux/selinux.go

@@ -1,7 +1,7 @@
 package selinux
 package selinux
 
 
 import (
 import (
-	"github.com/pkg/errors"
+	"errors"
 )
 )
 
 
 const (
 const (
@@ -38,6 +38,8 @@ var (
 
 
 	// CategoryRange allows the upper bound on the category range to be adjusted
 	// CategoryRange allows the upper bound on the category range to be adjusted
 	CategoryRange = DefaultCategoryRange
 	CategoryRange = DefaultCategoryRange
+
+	privContainerMountLabel string
 )
 )
 
 
 // Context is a representation of the SELinux label broken into 4 parts
 // Context is a representation of the SELinux label broken into 4 parts
@@ -253,6 +255,8 @@ func CopyLevel(src, dest string) (string, error) {
 // Chcon changes the fpath file object to the SELinux label label.
 // Chcon changes the fpath file object to the SELinux label label.
 // If fpath is a directory and recurse is true, then Chcon walks the
 // If fpath is a directory and recurse is true, then Chcon walks the
 // directory tree setting the label.
 // directory tree setting the label.
+//
+// The fpath itself is guaranteed to be relabeled last.
 func Chcon(fpath string, label string, recurse bool) error {
 func Chcon(fpath string, label string, recurse bool) error {
 	return chcon(fpath, label, recurse)
 	return chcon(fpath, label, recurse)
 }
 }
@@ -280,5 +284,7 @@ func GetDefaultContextWithLevel(user, level, scon string) (string, error) {
 
 
 // PrivContainerMountLabel returns mount label for privileged containers
 // PrivContainerMountLabel returns mount label for privileged containers
 func PrivContainerMountLabel() string {
 func PrivContainerMountLabel() string {
+	// Make sure label is initialized.
+	_ = label("")
 	return privContainerMountLabel
 	return privContainerMountLabel
 }
 }

+ 126 - 115
vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go

@@ -5,20 +5,18 @@ import (
 	"bytes"
 	"bytes"
 	"crypto/rand"
 	"crypto/rand"
 	"encoding/binary"
 	"encoding/binary"
+	"errors"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
 	"io/ioutil"
 	"io/ioutil"
+	"math/big"
 	"os"
 	"os"
 	"path"
 	"path"
 	"path/filepath"
 	"path/filepath"
-	"regexp"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
 
 
-	"github.com/bits-and-blooms/bitset"
-	"github.com/opencontainers/selinux/pkg/pwalk"
-	"github.com/pkg/errors"
 	"golang.org/x/sys/unix"
 	"golang.org/x/sys/unix"
 )
 )
 
 
@@ -35,8 +33,6 @@ const (
 	xattrNameSelinux = "security.selinux"
 	xattrNameSelinux = "security.selinux"
 )
 )
 
 
-var policyRoot = filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
-
 type selinuxState struct {
 type selinuxState struct {
 	enabledSet    bool
 	enabledSet    bool
 	enabled       bool
 	enabled       bool
@@ -48,7 +44,7 @@ type selinuxState struct {
 
 
 type level struct {
 type level struct {
 	sens uint
 	sens uint
-	cats *bitset.BitSet
+	cats *big.Int
 }
 }
 
 
 type mlsRange struct {
 type mlsRange struct {
@@ -71,7 +67,6 @@ const (
 )
 )
 
 
 var (
 var (
-	assignRegex       = regexp.MustCompile(`^([^=]+)=(.*)$`)
 	readOnlyFileLabel string
 	readOnlyFileLabel string
 	state             = selinuxState{
 	state             = selinuxState{
 		mcsList: make(map[string]bool),
 		mcsList: make(map[string]bool),
@@ -80,8 +75,24 @@ var (
 	// for attrPath()
 	// for attrPath()
 	attrPathOnce   sync.Once
 	attrPathOnce   sync.Once
 	haveThreadSelf bool
 	haveThreadSelf bool
+
+	// for policyRoot()
+	policyRootOnce sync.Once
+	policyRootVal  string
+
+	// for label()
+	loadLabelsOnce sync.Once
+	labels         map[string]string
 )
 )
 
 
+func policyRoot() string {
+	policyRootOnce.Do(func() {
+		policyRootVal = filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
+	})
+
+	return policyRootVal
+}
+
 func (s *selinuxState) setEnable(enabled bool) bool {
 func (s *selinuxState) setEnable(enabled bool) bool {
 	s.Lock()
 	s.Lock()
 	defer s.Unlock()
 	defer s.Unlock()
@@ -120,7 +131,7 @@ func verifySELinuxfsMount(mnt string) bool {
 		if err == nil {
 		if err == nil {
 			break
 			break
 		}
 		}
-		if err == unix.EAGAIN || err == unix.EINTR {
+		if err == unix.EAGAIN || err == unix.EINTR { //nolint:errorlint // unix errors are bare
 			continue
 			continue
 		}
 		}
 		return false
 		return false
@@ -223,7 +234,7 @@ func readConfig(target string) string {
 	scanner := bufio.NewScanner(in)
 	scanner := bufio.NewScanner(in)
 
 
 	for scanner.Scan() {
 	for scanner.Scan() {
-		line := strings.TrimSpace(scanner.Text())
+		line := bytes.TrimSpace(scanner.Bytes())
 		if len(line) == 0 {
 		if len(line) == 0 {
 			// Skip blank lines
 			// Skip blank lines
 			continue
 			continue
@@ -232,11 +243,12 @@ func readConfig(target string) string {
 			// Skip comments
 			// Skip comments
 			continue
 			continue
 		}
 		}
-		if groups := assignRegex.FindStringSubmatch(line); groups != nil {
-			key, val := strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2])
-			if key == target {
-				return strings.Trim(val, "\"")
-			}
+		fields := bytes.SplitN(line, []byte{'='}, 2)
+		if len(fields) != 2 {
+			continue
+		}
+		if bytes.Equal(fields[0], []byte(target)) {
+			return string(bytes.Trim(fields[1], `"`))
 		}
 		}
 	}
 	}
 	return ""
 	return ""
@@ -250,12 +262,12 @@ func isProcHandle(fh *os.File) error {
 		if err == nil {
 		if err == nil {
 			break
 			break
 		}
 		}
-		if err != unix.EINTR {
-			return errors.Wrapf(err, "statfs(%q) failed", fh.Name())
+		if err != unix.EINTR { //nolint:errorlint // unix errors are bare
+			return &os.PathError{Op: "fstatfs", Path: fh.Name(), Err: err}
 		}
 		}
 	}
 	}
 	if buf.Type != unix.PROC_SUPER_MAGIC {
 	if buf.Type != unix.PROC_SUPER_MAGIC {
-		return errors.Errorf("file %q is not on procfs", fh.Name())
+		return fmt.Errorf("file %q is not on procfs", fh.Name())
 	}
 	}
 
 
 	return nil
 	return nil
@@ -275,12 +287,15 @@ func readCon(fpath string) (string, error) {
 	if err := isProcHandle(in); err != nil {
 	if err := isProcHandle(in); err != nil {
 		return "", err
 		return "", err
 	}
 	}
+	return readConFd(in)
+}
 
 
-	var retval string
-	if _, err := fmt.Fscanf(in, "%s", &retval); err != nil {
+func readConFd(in *os.File) (string, error) {
+	data, err := ioutil.ReadAll(in)
+	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
-	return strings.Trim(retval, "\x00"), nil
+	return string(bytes.TrimSuffix(data, []byte{0})), nil
 }
 }
 
 
 // classIndex returns the int index for an object class in the loaded policy,
 // classIndex returns the int index for an object class in the loaded policy,
@@ -311,8 +326,8 @@ func setFileLabel(fpath string, label string) error {
 		if err == nil {
 		if err == nil {
 			break
 			break
 		}
 		}
-		if err != unix.EINTR {
-			return errors.Wrapf(err, "failed to set file label on %s", fpath)
+		if err != unix.EINTR { //nolint:errorlint // unix errors are bare
+			return &os.PathError{Op: "lsetxattr", Path: fpath, Err: err}
 		}
 		}
 	}
 	}
 
 
@@ -327,7 +342,7 @@ func fileLabel(fpath string) (string, error) {
 
 
 	label, err := lgetxattr(fpath, xattrNameSelinux)
 	label, err := lgetxattr(fpath, xattrNameSelinux)
 	if err != nil {
 	if err != nil {
-		return "", err
+		return "", &os.PathError{Op: "lgetxattr", Path: fpath, Err: err}
 	}
 	}
 	// Trim the NUL byte at the end of the byte buffer, if present.
 	// Trim the NUL byte at the end of the byte buffer, if present.
 	if len(label) > 0 && label[len(label)-1] == '\x00' {
 	if len(label) > 0 && label[len(label)-1] == '\x00' {
@@ -390,7 +405,7 @@ func writeCon(fpath, val string) error {
 		_, err = out.Write(nil)
 		_, err = out.Write(nil)
 	}
 	}
 	if err != nil {
 	if err != nil {
-		return errors.Wrapf(err, "failed to set %s on procfs", fpath)
+		return err
 	}
 	}
 	return nil
 	return nil
 }
 }
@@ -440,8 +455,8 @@ func computeCreateContext(source string, target string, class string) (string, e
 }
 }
 
 
 // catsToBitset stores categories in a bitset.
 // catsToBitset stores categories in a bitset.
-func catsToBitset(cats string) (*bitset.BitSet, error) {
-	bitset := &bitset.BitSet{}
+func catsToBitset(cats string) (*big.Int, error) {
+	bitset := new(big.Int)
 
 
 	catlist := strings.Split(cats, ",")
 	catlist := strings.Split(cats, ",")
 	for _, r := range catlist {
 	for _, r := range catlist {
@@ -456,14 +471,14 @@ func catsToBitset(cats string) (*bitset.BitSet, error) {
 				return nil, err
 				return nil, err
 			}
 			}
 			for i := catstart; i <= catend; i++ {
 			for i := catstart; i <= catend; i++ {
-				bitset.Set(i)
+				bitset.SetBit(bitset, int(i), 1)
 			}
 			}
 		} else {
 		} else {
 			cat, err := parseLevelItem(ranges[0], category)
 			cat, err := parseLevelItem(ranges[0], category)
 			if err != nil {
 			if err != nil {
 				return nil, err
 				return nil, err
 			}
 			}
-			bitset.Set(cat)
+			bitset.SetBit(bitset, int(cat), 1)
 		}
 		}
 	}
 	}
 
 
@@ -489,13 +504,13 @@ func (l *level) parseLevel(levelStr string) error {
 	lvl := strings.SplitN(levelStr, ":", 2)
 	lvl := strings.SplitN(levelStr, ":", 2)
 	sens, err := parseLevelItem(lvl[0], sensitivity)
 	sens, err := parseLevelItem(lvl[0], sensitivity)
 	if err != nil {
 	if err != nil {
-		return errors.Wrap(err, "failed to parse sensitivity")
+		return fmt.Errorf("failed to parse sensitivity: %w", err)
 	}
 	}
 	l.sens = sens
 	l.sens = sens
 	if len(lvl) > 1 {
 	if len(lvl) > 1 {
 		cats, err := catsToBitset(lvl[1])
 		cats, err := catsToBitset(lvl[1])
 		if err != nil {
 		if err != nil {
-			return errors.Wrap(err, "failed to parse categories")
+			return fmt.Errorf("failed to parse categories: %w", err)
 		}
 		}
 		l.cats = cats
 		l.cats = cats
 	}
 	}
@@ -513,14 +528,14 @@ func rangeStrToMLSRange(rangeStr string) (*mlsRange, error) {
 	case 2:
 	case 2:
 		mlsRange.high = &level{}
 		mlsRange.high = &level{}
 		if err := mlsRange.high.parseLevel(levelSlice[1]); err != nil {
 		if err := mlsRange.high.parseLevel(levelSlice[1]); err != nil {
-			return nil, errors.Wrapf(err, "failed to parse high level %q", levelSlice[1])
+			return nil, fmt.Errorf("failed to parse high level %q: %w", levelSlice[1], err)
 		}
 		}
 		fallthrough
 		fallthrough
 	// rangeStr that is single level, e.g. s6:c0,c3,c5,c30.c1023
 	// rangeStr that is single level, e.g. s6:c0,c3,c5,c30.c1023
 	case 1:
 	case 1:
 		mlsRange.low = &level{}
 		mlsRange.low = &level{}
 		if err := mlsRange.low.parseLevel(levelSlice[0]); err != nil {
 		if err := mlsRange.low.parseLevel(levelSlice[0]); err != nil {
-			return nil, errors.Wrapf(err, "failed to parse low level %q", levelSlice[0])
+			return nil, fmt.Errorf("failed to parse low level %q: %w", levelSlice[0], err)
 		}
 		}
 	}
 	}
 
 
@@ -533,37 +548,30 @@ func rangeStrToMLSRange(rangeStr string) (*mlsRange, error) {
 
 
 // bitsetToStr takes a category bitset and returns it in the
 // bitsetToStr takes a category bitset and returns it in the
 // canonical selinux syntax
 // canonical selinux syntax
-func bitsetToStr(c *bitset.BitSet) string {
+func bitsetToStr(c *big.Int) string {
 	var str string
 	var str string
-	i, e := c.NextSet(0)
-	len := 0
-	for e {
-		if len == 0 {
+
+	length := 0
+	for i := int(c.TrailingZeroBits()); i < c.BitLen(); i++ {
+		if c.Bit(i) == 0 {
+			continue
+		}
+		if length == 0 {
 			if str != "" {
 			if str != "" {
 				str += ","
 				str += ","
 			}
 			}
-			str += "c" + strconv.Itoa(int(i))
+			str += "c" + strconv.Itoa(i)
 		}
 		}
-
-		next, e := c.NextSet(i + 1)
-		if e {
-			// consecutive cats
-			if next == i+1 {
-				len++
-				i = next
-				continue
-			}
-		}
-		if len == 1 {
-			str += ",c" + strconv.Itoa(int(i))
-		} else if len > 1 {
-			str += ".c" + strconv.Itoa(int(i))
+		if c.Bit(i+1) == 1 {
+			length++
+			continue
 		}
 		}
-		if !e {
-			break
+		if length == 1 {
+			str += ",c" + strconv.Itoa(i)
+		} else if length > 1 {
+			str += ".c" + strconv.Itoa(i)
 		}
 		}
-		len = 0
-		i = next
+		length = 0
 	}
 	}
 
 
 	return str
 	return str
@@ -576,13 +584,16 @@ func (l1 *level) equal(l2 *level) bool {
 	if l1.sens != l2.sens {
 	if l1.sens != l2.sens {
 		return false
 		return false
 	}
 	}
-	return l1.cats.Equal(l2.cats)
+	if l2.cats == nil || l1.cats == nil {
+		return l2.cats == l1.cats
+	}
+	return l1.cats.Cmp(l2.cats) == 0
 }
 }
 
 
 // String returns an mlsRange as a string.
 // String returns an mlsRange as a string.
 func (m mlsRange) String() string {
 func (m mlsRange) String() string {
 	low := "s" + strconv.Itoa(int(m.low.sens))
 	low := "s" + strconv.Itoa(int(m.low.sens))
-	if m.low.cats != nil && m.low.cats.Count() > 0 {
+	if m.low.cats != nil && m.low.cats.BitLen() > 0 {
 		low += ":" + bitsetToStr(m.low.cats)
 		low += ":" + bitsetToStr(m.low.cats)
 	}
 	}
 
 
@@ -591,7 +602,7 @@ func (m mlsRange) String() string {
 	}
 	}
 
 
 	high := "s" + strconv.Itoa(int(m.high.sens))
 	high := "s" + strconv.Itoa(int(m.high.sens))
-	if m.high.cats != nil && m.high.cats.Count() > 0 {
+	if m.high.cats != nil && m.high.cats.BitLen() > 0 {
 		high += ":" + bitsetToStr(m.high.cats)
 		high += ":" + bitsetToStr(m.high.cats)
 	}
 	}
 
 
@@ -641,10 +652,12 @@ func calculateGlbLub(sourceRange, targetRange string) (string, error) {
 
 
 	/* find the intersecting categories */
 	/* find the intersecting categories */
 	if s.low.cats != nil && t.low.cats != nil {
 	if s.low.cats != nil && t.low.cats != nil {
-		outrange.low.cats = s.low.cats.Intersection(t.low.cats)
+		outrange.low.cats = new(big.Int)
+		outrange.low.cats.And(s.low.cats, t.low.cats)
 	}
 	}
 	if s.high.cats != nil && t.high.cats != nil {
 	if s.high.cats != nil && t.high.cats != nil {
-		outrange.high.cats = s.high.cats.Intersection(t.high.cats)
+		outrange.high.cats = new(big.Int)
+		outrange.high.cats.And(s.high.cats, t.high.cats)
 	}
 	}
 
 
 	return outrange.String(), nil
 	return outrange.String(), nil
@@ -665,11 +678,7 @@ func readWriteCon(fpath string, val string) (string, error) {
 		return "", err
 		return "", err
 	}
 	}
 
 
-	var retval string
-	if _, err := fmt.Fscanf(f, "%s", &retval); err != nil {
-		return "", err
-	}
-	return strings.Trim(retval, "\x00"), nil
+	return readConFd(f)
 }
 }
 
 
 // setExecLabel sets the SELinux label that the kernel will use for any programs
 // setExecLabel sets the SELinux label that the kernel will use for any programs
@@ -697,17 +706,21 @@ func socketLabel() (string, error) {
 
 
 // peerLabel retrieves the label of the client on the other side of a socket
 // peerLabel retrieves the label of the client on the other side of a socket
 func peerLabel(fd uintptr) (string, error) {
 func peerLabel(fd uintptr) (string, error) {
-	return unix.GetsockoptString(int(fd), unix.SOL_SOCKET, unix.SO_PEERSEC)
+	label, err := unix.GetsockoptString(int(fd), unix.SOL_SOCKET, unix.SO_PEERSEC)
+	if err != nil {
+		return "", &os.PathError{Op: "getsockopt", Path: "fd " + strconv.Itoa(int(fd)), Err: err}
+	}
+	return label, nil
 }
 }
 
 
 // setKeyLabel takes a process label and tells the kernel to assign the
 // setKeyLabel takes a process label and tells the kernel to assign the
 // label to the next kernel keyring that gets created
 // label to the next kernel keyring that gets created
 func setKeyLabel(label string) error {
 func setKeyLabel(label string) error {
 	err := writeCon("/proc/self/attr/keycreate", label)
 	err := writeCon("/proc/self/attr/keycreate", label)
-	if os.IsNotExist(errors.Cause(err)) {
+	if errors.Is(err, os.ErrNotExist) {
 		return nil
 		return nil
 	}
 	}
-	if label == "" && os.IsPermission(errors.Cause(err)) {
+	if label == "" && errors.Is(err, os.ErrPermission) {
 		return nil
 		return nil
 	}
 	}
 	return err
 	return err
@@ -720,10 +733,10 @@ func keyLabel() (string, error) {
 
 
 // get returns the Context as a string
 // get returns the Context as a string
 func (c Context) get() string {
 func (c Context) get() string {
-	if c["level"] != "" {
-		return fmt.Sprintf("%s:%s:%s:%s", c["user"], c["role"], c["type"], c["level"])
+	if level := c["level"]; level != "" {
+		return c["user"] + ":" + c["role"] + ":" + c["type"] + ":" + level
 	}
 	}
-	return fmt.Sprintf("%s:%s:%s", c["user"], c["role"], c["type"])
+	return c["user"] + ":" + c["role"] + ":" + c["type"]
 }
 }
 
 
 // newContext creates a new Context struct from the specified label
 // newContext creates a new Context struct from the specified label
@@ -784,7 +797,7 @@ func enforceMode() int {
 // setEnforceMode sets the current SELinux mode Enforcing, Permissive.
 // setEnforceMode sets the current SELinux mode Enforcing, Permissive.
 // Disabled is not valid, since this needs to be set at boot time.
 // Disabled is not valid, since this needs to be set at boot time.
 func setEnforceMode(mode int) error {
 func setEnforceMode(mode int) error {
-	return ioutil.WriteFile(selinuxEnforcePath(), []byte(strconv.Itoa(mode)), 0644)
+	return ioutil.WriteFile(selinuxEnforcePath(), []byte(strconv.Itoa(mode)), 0o644)
 }
 }
 
 
 // defaultEnforceMode returns the systems default SELinux mode Enforcing,
 // defaultEnforceMode returns the systems default SELinux mode Enforcing,
@@ -888,24 +901,21 @@ func openContextFile() (*os.File, error) {
 	if f, err := os.Open(contextFile); err == nil {
 	if f, err := os.Open(contextFile); err == nil {
 		return f, nil
 		return f, nil
 	}
 	}
-	lxcPath := filepath.Join(policyRoot, "/contexts/lxc_contexts")
-	return os.Open(lxcPath)
+	return os.Open(filepath.Join(policyRoot(), "/contexts/lxc_contexts"))
 }
 }
 
 
-var labels, privContainerMountLabel = loadLabels()
-
-func loadLabels() (map[string]string, string) {
-	labels := make(map[string]string)
+func loadLabels() {
+	labels = make(map[string]string)
 	in, err := openContextFile()
 	in, err := openContextFile()
 	if err != nil {
 	if err != nil {
-		return labels, ""
+		return
 	}
 	}
 	defer in.Close()
 	defer in.Close()
 
 
 	scanner := bufio.NewScanner(in)
 	scanner := bufio.NewScanner(in)
 
 
 	for scanner.Scan() {
 	for scanner.Scan() {
-		line := strings.TrimSpace(scanner.Text())
+		line := bytes.TrimSpace(scanner.Bytes())
 		if len(line) == 0 {
 		if len(line) == 0 {
 			// Skip blank lines
 			// Skip blank lines
 			continue
 			continue
@@ -914,38 +924,47 @@ func loadLabels() (map[string]string, string) {
 			// Skip comments
 			// Skip comments
 			continue
 			continue
 		}
 		}
-		if groups := assignRegex.FindStringSubmatch(line); groups != nil {
-			key, val := strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2])
-			labels[key] = strings.Trim(val, "\"")
+		fields := bytes.SplitN(line, []byte{'='}, 2)
+		if len(fields) != 2 {
+			continue
 		}
 		}
+		key, val := bytes.TrimSpace(fields[0]), bytes.TrimSpace(fields[1])
+		labels[string(key)] = string(bytes.Trim(val, `"`))
 	}
 	}
 
 
 	con, _ := NewContext(labels["file"])
 	con, _ := NewContext(labels["file"])
 	con["level"] = fmt.Sprintf("s0:c%d,c%d", maxCategory-2, maxCategory-1)
 	con["level"] = fmt.Sprintf("s0:c%d,c%d", maxCategory-2, maxCategory-1)
-	reserveLabel(con.get())
-	return labels, con.get()
+	privContainerMountLabel = con.get()
+	reserveLabel(privContainerMountLabel)
+}
+
+func label(key string) string {
+	loadLabelsOnce.Do(func() {
+		loadLabels()
+	})
+	return labels[key]
 }
 }
 
 
 // kvmContainerLabels returns the default processLabel and mountLabel to be used
 // kvmContainerLabels returns the default processLabel and mountLabel to be used
 // for kvm containers by the calling process.
 // for kvm containers by the calling process.
 func kvmContainerLabels() (string, string) {
 func kvmContainerLabels() (string, string) {
-	processLabel := labels["kvm_process"]
+	processLabel := label("kvm_process")
 	if processLabel == "" {
 	if processLabel == "" {
-		processLabel = labels["process"]
+		processLabel = label("process")
 	}
 	}
 
 
-	return addMcs(processLabel, labels["file"])
+	return addMcs(processLabel, label("file"))
 }
 }
 
 
 // initContainerLabels returns the default processLabel and file labels to be
 // initContainerLabels returns the default processLabel and file labels to be
 // used for containers running an init system like systemd by the calling process.
 // used for containers running an init system like systemd by the calling process.
 func initContainerLabels() (string, string) {
 func initContainerLabels() (string, string) {
-	processLabel := labels["init_process"]
+	processLabel := label("init_process")
 	if processLabel == "" {
 	if processLabel == "" {
-		processLabel = labels["process"]
+		processLabel = label("process")
 	}
 	}
 
 
-	return addMcs(processLabel, labels["file"])
+	return addMcs(processLabel, label("file"))
 }
 }
 
 
 // containerLabels returns an allocated processLabel and fileLabel to be used for
 // containerLabels returns an allocated processLabel and fileLabel to be used for
@@ -955,9 +974,9 @@ func containerLabels() (processLabel string, fileLabel string) {
 		return "", ""
 		return "", ""
 	}
 	}
 
 
-	processLabel = labels["process"]
-	fileLabel = labels["file"]
-	readOnlyFileLabel = labels["ro_file"]
+	processLabel = label("process")
+	fileLabel = label("file")
+	readOnlyFileLabel = label("ro_file")
 
 
 	if processLabel == "" || fileLabel == "" {
 	if processLabel == "" || fileLabel == "" {
 		return "", fileLabel
 		return "", fileLabel
@@ -985,7 +1004,7 @@ func addMcs(processLabel, fileLabel string) (string, string) {
 
 
 // securityCheckContext validates that the SELinux label is understood by the kernel
 // securityCheckContext validates that the SELinux label is understood by the kernel
 func securityCheckContext(val string) error {
 func securityCheckContext(val string) error {
-	return ioutil.WriteFile(path.Join(getSelinuxMountPoint(), "context"), []byte(val), 0644)
+	return ioutil.WriteFile(path.Join(getSelinuxMountPoint(), "context"), []byte(val), 0o644)
 }
 }
 
 
 // copyLevel returns a label with the MLS/MCS level from src label replaced on
 // copyLevel returns a label with the MLS/MCS level from src label replaced on
@@ -1023,7 +1042,7 @@ func badPrefix(fpath string) error {
 	badPrefixes := []string{"/usr"}
 	badPrefixes := []string{"/usr"}
 	for _, prefix := range badPrefixes {
 	for _, prefix := range badPrefixes {
 		if strings.HasPrefix(fpath, prefix) {
 		if strings.HasPrefix(fpath, prefix) {
-			return errors.Errorf("relabeling content in %s is not allowed", prefix)
+			return fmt.Errorf("relabeling content in %s is not allowed", prefix)
 		}
 		}
 	}
 	}
 	return nil
 	return nil
@@ -1044,17 +1063,10 @@ func chcon(fpath string, label string, recurse bool) error {
 	}
 	}
 
 
 	if !recurse {
 	if !recurse {
-		return SetFileLabel(fpath, label)
+		return setFileLabel(fpath, label)
 	}
 	}
 
 
-	return pwalk.Walk(fpath, func(p string, info os.FileInfo, err error) error {
-		e := SetFileLabel(p, label)
-		// Walk a file tree can race with removal, so ignore ENOENT
-		if os.IsNotExist(errors.Cause(e)) {
-			return nil
-		}
-		return e
-	})
+	return rchcon(fpath, label)
 }
 }
 
 
 // dupSecOpt takes an SELinux process label and returns security options that
 // dupSecOpt takes an SELinux process label and returns security options that
@@ -1072,7 +1084,8 @@ func dupSecOpt(src string) ([]string, error) {
 		con["type"] == "" {
 		con["type"] == "" {
 		return nil, nil
 		return nil, nil
 	}
 	}
-	dup := []string{"user:" + con["user"],
+	dup := []string{
+		"user:" + con["user"],
 		"role:" + con["role"],
 		"role:" + con["role"],
 		"type:" + con["type"],
 		"type:" + con["type"],
 	}
 	}
@@ -1140,9 +1153,8 @@ func findUserInContext(context Context, r io.Reader, verifier func(string) error
 			return outConn, nil
 			return outConn, nil
 		}
 		}
 	}
 	}
-
 	if err := scanner.Err(); err != nil {
 	if err := scanner.Err(); err != nil {
-		return "", errors.Wrap(err, "failed to scan for context")
+		return "", fmt.Errorf("failed to scan for context: %w", err)
 	}
 	}
 
 
 	return "", nil
 	return "", nil
@@ -1155,7 +1167,7 @@ func getDefaultContextFromReaders(c *defaultSECtx) (string, error) {
 
 
 	context, err := newContext(c.scon)
 	context, err := newContext(c.scon)
 	if err != nil {
 	if err != nil {
-		return "", errors.Wrapf(err, "failed to create label for %s", c.scon)
+		return "", fmt.Errorf("failed to create label for %s: %w", c.scon, err)
 	}
 	}
 
 
 	// set so the verifier validates the matched context with the provided user and level.
 	// set so the verifier validates the matched context with the provided user and level.
@@ -1180,19 +1192,18 @@ func getDefaultContextFromReaders(c *defaultSECtx) (string, error) {
 		return conn, nil
 		return conn, nil
 	}
 	}
 
 
-	return "", errors.Wrapf(ErrContextMissing, "context not found: %q", c.scon)
+	return "", fmt.Errorf("context %q not found: %w", c.scon, ErrContextMissing)
 }
 }
 
 
 func getDefaultContextWithLevel(user, level, scon string) (string, error) {
 func getDefaultContextWithLevel(user, level, scon string) (string, error) {
-	userPath := filepath.Join(policyRoot, selinuxUsersDir, user)
-	defaultPath := filepath.Join(policyRoot, defaultContexts)
-
+	userPath := filepath.Join(policyRoot(), selinuxUsersDir, user)
 	fu, err := os.Open(userPath)
 	fu, err := os.Open(userPath)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
 	defer fu.Close()
 	defer fu.Close()
 
 
+	defaultPath := filepath.Join(policyRoot(), defaultContexts)
 	fd, err := os.Open(defaultPath)
 	fd, err := os.Open(defaultPath)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err

+ 4 - 2
vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go

@@ -2,8 +2,6 @@
 
 
 package selinux
 package selinux
 
 
-const privContainerMountLabel = ""
-
 func setDisabled() {
 func setDisabled() {
 }
 }
 
 
@@ -152,3 +150,7 @@ func disableSecOpt() []string {
 func getDefaultContextWithLevel(user, level, scon string) (string, error) {
 func getDefaultContextWithLevel(user, level, scon string) (string, error) {
 	return "", nil
 	return "", nil
 }
 }
+
+func label(_ string) string {
+	return ""
+}

+ 2 - 2
vendor/github.com/opencontainers/selinux/go-selinux/xattrs_linux.go

@@ -10,7 +10,7 @@ func lgetxattr(path, attr string) ([]byte, error) {
 	// Start with a 128 length byte array
 	// Start with a 128 length byte array
 	dest := make([]byte, 128)
 	dest := make([]byte, 128)
 	sz, errno := doLgetxattr(path, attr, dest)
 	sz, errno := doLgetxattr(path, attr, dest)
-	for errno == unix.ERANGE {
+	for errno == unix.ERANGE { //nolint:errorlint // unix errors are bare
 		// Buffer too small, use zero-sized buffer to get the actual size
 		// Buffer too small, use zero-sized buffer to get the actual size
 		sz, errno = doLgetxattr(path, attr, []byte{})
 		sz, errno = doLgetxattr(path, attr, []byte{})
 		if errno != nil {
 		if errno != nil {
@@ -31,7 +31,7 @@ func lgetxattr(path, attr string) ([]byte, error) {
 func doLgetxattr(path, attr string, dest []byte) (int, error) {
 func doLgetxattr(path, attr string, dest []byte) (int, error) {
 	for {
 	for {
 		sz, err := unix.Lgetxattr(path, attr, dest)
 		sz, err := unix.Lgetxattr(path, attr, dest)
-		if err != unix.EINTR {
+		if err != unix.EINTR { //nolint:errorlint // unix errors are bare
 			return sz, err
 			return sz, err
 		}
 		}
 	}
 	}

+ 1 - 5
vendor/github.com/opencontainers/selinux/go.mod

@@ -2,8 +2,4 @@ module github.com/opencontainers/selinux
 
 
 go 1.13
 go 1.13
 
 
-require (
-	github.com/bits-and-blooms/bitset v1.2.0
-	github.com/pkg/errors v0.9.1
-	golang.org/x/sys v0.0.0-20191115151921-52ab43148777
-)
+require golang.org/x/sys v0.0.0-20191115151921-52ab43148777

+ 6 - 0
vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md

@@ -8,6 +8,12 @@ By default, it utilizes 2\*runtime.NumCPU() goroutines for callbacks.
 This can be changed by using WalkN function which has the additional
 This can be changed by using WalkN function which has the additional
 parameter, specifying the number of goroutines (concurrency).
 parameter, specifying the number of goroutines (concurrency).
 
 
+### pwalk vs pwalkdir
+
+This package is deprecated in favor of
+[pwalkdir](https://pkg.go.dev/github.com/opencontainers/selinux/pkg/pwalkdir),
+which is faster, but requires at least Go 1.16.
+
 ### Caveats
 ### Caveats
 
 
 Please note the following limitations of this code:
 Please note the following limitations of this code:

+ 16 - 5
vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go

@@ -1,12 +1,11 @@
 package pwalk
 package pwalk
 
 
 import (
 import (
+	"fmt"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
 	"runtime"
 	"runtime"
 	"sync"
 	"sync"
-
-	"github.com/pkg/errors"
 )
 )
 
 
 type WalkFunc = filepath.WalkFunc
 type WalkFunc = filepath.WalkFunc
@@ -20,7 +19,7 @@ type WalkFunc = filepath.WalkFunc
 //
 //
 // Note that this implementation only supports primitive error handling:
 // Note that this implementation only supports primitive error handling:
 //
 //
-// - no errors are ever passed to WalkFn;
+// - no errors are ever passed to walkFn;
 //
 //
 // - once a walkFn returns any error, all further processing stops
 // - once a walkFn returns any error, all further processing stops
 // and the error is returned to the caller of Walk;
 // and the error is returned to the caller of Walk;
@@ -42,7 +41,7 @@ func Walk(root string, walkFn WalkFunc) error {
 func WalkN(root string, walkFn WalkFunc, num int) error {
 func WalkN(root string, walkFn WalkFunc, num int) error {
 	// make sure limit is sensible
 	// make sure limit is sensible
 	if num < 1 {
 	if num < 1 {
-		return errors.Errorf("walk(%q): num must be > 0", root)
+		return fmt.Errorf("walk(%q): num must be > 0", root)
 	}
 	}
 
 
 	files := make(chan *walkArgs, 2*num)
 	files := make(chan *walkArgs, 2*num)
@@ -52,6 +51,9 @@ func WalkN(root string, walkFn WalkFunc, num int) error {
 	var (
 	var (
 		err error
 		err error
 		wg  sync.WaitGroup
 		wg  sync.WaitGroup
+
+		rootLen   = len(root)
+		rootEntry *walkArgs
 	)
 	)
 	wg.Add(1)
 	wg.Add(1)
 	go func() {
 	go func() {
@@ -60,6 +62,11 @@ func WalkN(root string, walkFn WalkFunc, num int) error {
 				close(files)
 				close(files)
 				return err
 				return err
 			}
 			}
+			if len(p) == rootLen {
+				// Root entry is processed separately below.
+				rootEntry = &walkArgs{path: p, info: &info}
+				return nil
+			}
 			// add a file to the queue unless a callback sent an error
 			// add a file to the queue unless a callback sent an error
 			select {
 			select {
 			case e := <-errCh:
 			case e := <-errCh:
@@ -93,10 +100,14 @@ func WalkN(root string, walkFn WalkFunc, num int) error {
 
 
 	wg.Wait()
 	wg.Wait()
 
 
+	if err == nil {
+		err = walkFn(rootEntry.path, *rootEntry.info, nil)
+	}
+
 	return err
 	return err
 }
 }
 
 
-// walkArgs holds the arguments that were passed to the Walk or WalkLimit
+// walkArgs holds the arguments that were passed to the Walk or WalkN
 // functions.
 // functions.
 type walkArgs struct {
 type walkArgs struct {
 	path string
 	path string

+ 54 - 0
vendor/github.com/opencontainers/selinux/pkg/pwalkdir/README.md

@@ -0,0 +1,54 @@
+## pwalkdir: parallel implementation of filepath.WalkDir
+
+This is a wrapper for [filepath.WalkDir](https://pkg.go.dev/path/filepath#WalkDir)
+which may speed it up by calling multiple callback functions (WalkDirFunc)
+in parallel, utilizing goroutines.
+
+By default, it utilizes 2\*runtime.NumCPU() goroutines for callbacks.
+This can be changed by using WalkN function which has the additional
+parameter, specifying the number of goroutines (concurrency).
+
+### pwalk vs pwalkdir
+
+This package is very similar to
+[pwalk](https://pkg.go.dev/github.com/opencontainers/selinux/pkg/pwalkdir),
+but utilizes `filepath.WalkDir` (added to Go 1.16), which does not call stat(2)
+on every entry and is therefore faster (up to 3x, depending on usage scenario).
+
+Users who are OK with requiring Go 1.16+ should switch to this
+implementation.
+
+### Caveats
+
+Please note the following limitations of this code:
+
+* Unlike filepath.WalkDir, the order of calls is non-deterministic;
+
+* Only primitive error handling is supported:
+
+  * fs.SkipDir is not supported;
+
+  * no errors are ever passed to WalkDirFunc;
+
+  * once any error is returned from any walkDirFunc instance, no more calls
+    to WalkDirFunc are made, and the error is returned to the caller of WalkDir;
+
+  * if more than one WalkDirFunc instance will return an error, only one
+    of such errors will be propagated to and returned by WalkDir, others
+    will be silently discarded.
+
+### Documentation
+
+For the official documentation, see
+https://pkg.go.dev/github.com/opencontainers/selinux/pkg/pwalkdir
+
+### Benchmarks
+
+For a WalkDirFunc that consists solely of the return statement, this
+implementation is about 15% slower than the standard library's
+filepath.WalkDir.
+
+Otherwise (if a WalkDirFunc is actually doing something) this is usually
+faster, except when the WalkDirN(..., 1) is used. Run `go test -bench .`
+to see how different operations can benefit from it, as well as how the
+level of paralellism affects the speed.

+ 116 - 0
vendor/github.com/opencontainers/selinux/pkg/pwalkdir/pwalkdir.go

@@ -0,0 +1,116 @@
+//go:build go1.16
+// +build go1.16
+
+package pwalkdir
+
+import (
+	"fmt"
+	"io/fs"
+	"path/filepath"
+	"runtime"
+	"sync"
+)
+
+// Walk is a wrapper for filepath.WalkDir which can call multiple walkFn
+// in parallel, allowing to handle each item concurrently. A maximum of
+// twice the runtime.NumCPU() walkFn will be called at any one time.
+// If you want to change the maximum, use WalkN instead.
+//
+// The order of calls is non-deterministic.
+//
+// Note that this implementation only supports primitive error handling:
+//
+// - no errors are ever passed to walkFn;
+//
+// - once a walkFn returns any error, all further processing stops
+// and the error is returned to the caller of Walk;
+//
+// - filepath.SkipDir is not supported;
+//
+// - if more than one walkFn instance will return an error, only one
+// of such errors will be propagated and returned by Walk, others
+// will be silently discarded.
+func Walk(root string, walkFn fs.WalkDirFunc) error {
+	return WalkN(root, walkFn, runtime.NumCPU()*2)
+}
+
+// WalkN is a wrapper for filepath.WalkDir which can call multiple walkFn
+// in parallel, allowing to handle each item concurrently. A maximum of
+// num walkFn will be called at any one time.
+//
+// Please see Walk documentation for caveats of using this function.
+func WalkN(root string, walkFn fs.WalkDirFunc, num int) error {
+	// make sure limit is sensible
+	if num < 1 {
+		return fmt.Errorf("walk(%q): num must be > 0", root)
+	}
+
+	files := make(chan *walkArgs, 2*num)
+	errCh := make(chan error, 1) // Get the first error, ignore others.
+
+	// Start walking a tree asap.
+	var (
+		err error
+		wg  sync.WaitGroup
+
+		rootLen   = len(root)
+		rootEntry *walkArgs
+	)
+	wg.Add(1)
+	go func() {
+		err = filepath.WalkDir(root, func(p string, entry fs.DirEntry, err error) error {
+			if err != nil {
+				close(files)
+				return err
+			}
+			if len(p) == rootLen {
+				// Root entry is processed separately below.
+				rootEntry = &walkArgs{path: p, entry: entry}
+				return nil
+			}
+			// Add a file to the queue unless a callback sent an error.
+			select {
+			case e := <-errCh:
+				close(files)
+				return e
+			default:
+				files <- &walkArgs{path: p, entry: entry}
+				return nil
+			}
+		})
+		if err == nil {
+			close(files)
+		}
+		wg.Done()
+	}()
+
+	wg.Add(num)
+	for i := 0; i < num; i++ {
+		go func() {
+			for file := range files {
+				if e := walkFn(file.path, file.entry, nil); e != nil {
+					select {
+					case errCh <- e: // sent ok
+					default: // buffer full
+					}
+				}
+			}
+			wg.Done()
+		}()
+	}
+
+	wg.Wait()
+
+	if err == nil {
+		err = walkFn(rootEntry.path, rootEntry.entry, nil)
+	}
+
+	return err
+}
+
+// walkArgs holds the arguments that were passed to the Walk or WalkN
+// functions.
+type walkArgs struct {
+	path  string
+	entry fs.DirEntry
+}