Skip to content

Commit

Permalink
Merge pull request #675 from nalind/keyctl-arches
Browse files Browse the repository at this point in the history
Update keyctl for other arches
  • Loading branch information
rhatdan authored Aug 5, 2019
2 parents ea74a03 + d47f2a0 commit dd01136
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 141 deletions.
11 changes: 5 additions & 6 deletions pkg/keyctl/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
// license that can be found in the LICENSE file.

// +build linux
// +build 386 amd64

package keyctl

import (
"unsafe"
"golang.org/x/sys/unix"
)

// Key represents a single key linked to one or more kernel keyrings.
Expand All @@ -20,8 +19,8 @@ type Key struct {
}

// ID returns the 32-bit kernel identifier for a specific key
func (k *Key) ID() int32 {
return int32(k.id)
func (k *Key) ID() int {
return int(k.id)
}

// Get the key's value as a byte slice
Expand All @@ -41,7 +40,7 @@ func (k *Key) Get() ([]byte, error) {
b = make([]byte, int(size))
sizeRead = size + 1
for sizeRead > size {
r1, _, err := keyctl(keyctlRead, uintptr(k.id), uintptr(unsafe.Pointer(&b[0])), uintptr(size))
r1, err := unix.KeyctlBuffer(unix.KEYCTL_READ, int(k.id), b, size)
if err != nil {
return nil, err
}
Expand All @@ -60,6 +59,6 @@ func (k *Key) Get() ([]byte, error) {
// Unlink a key from the keyring it was loaded from (or added to). If the key
// is not linked to any other keyrings, it is destroyed.
func (k *Key) Unlink() error {
_, _, err := keyctl(keyctlUnlink, uintptr(k.id), uintptr(k.ring))
_, err := unix.KeyctlInt(unix.KEYCTL_UNLINK, int(k.id), int(k.ring), 0, 0)
return err
}
25 changes: 14 additions & 11 deletions pkg/keyctl/keyring.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
// license that can be found in the LICENSE file.

// +build linux
// +build 386 amd64

// Package keyctl is a Go interface to linux kernel keyrings (keyctl interface)
package keyctl

import (
"golang.org/x/sys/unix"
)

// Keyring is the basic interface to a linux keyctl keyring.
type Keyring interface {
ID
Expand All @@ -21,12 +24,12 @@ type keyring struct {

// ID is unique 32-bit serial number identifiers for all Keys and Keyrings have.
type ID interface {
ID() int32
ID() int
}

// Add a new key to a keyring. The key can be searched for later by name.
func (kr *keyring) Add(name string, key []byte) (*Key, error) {
r, err := addkey("user", name, key, int32(kr.id))
r, err := unix.AddKey("user", name, key, int(kr.id))
if err == nil {
key := &Key{Name: name, id: keyID(r), ring: kr.id}
return key, nil
Expand All @@ -38,36 +41,36 @@ func (kr *keyring) Add(name string, key []byte) (*Key, error) {
// one. The key, if found, is linked to the top keyring that Search() was called
// from.
func (kr *keyring) Search(name string) (*Key, error) {
id, err := searchKeyring(kr.id, name, "user")
id, err := unix.KeyctlSearch(int(kr.id), "user", name, 0)
if err == nil {
return &Key{Name: name, id: id, ring: kr.id}, nil
return &Key{Name: name, id: keyID(id), ring: kr.id}, nil
}
return nil, err
}

// ID returns the 32-bit kernel identifier of a keyring
func (kr *keyring) ID() int32 {
return int32(kr.id)
func (kr *keyring) ID() int {
return int(kr.id)
}

// SessionKeyring returns the current login session keyring
func SessionKeyring() (Keyring, error) {
return newKeyring(keySpecSessionKeyring)
return newKeyring(unix.KEY_SPEC_SESSION_KEYRING)
}

// UserKeyring returns the keyring specific to the current user.
func UserKeyring() (Keyring, error) {
return newKeyring(keySpecUserKeyring)
return newKeyring(unix.KEY_SPEC_USER_KEYRING)
}

// Unlink an object from a keyring
func Unlink(parent Keyring, child ID) error {
_, _, err := keyctl(keyctlUnlink, uintptr(child.ID()), uintptr(parent.ID()))
_, err := unix.KeyctlInt(unix.KEYCTL_UNLINK, child.ID(), parent.ID(), 0, 0)
return err
}

// Link a key into a keyring
func Link(parent Keyring, child ID) error {
_, _, err := keyctl(keyctlLink, uintptr(child.ID()), uintptr(parent.ID()))
_, err := unix.KeyctlInt(unix.KEYCTL_LINK, child.ID(), parent.ID(), 0, 0)
return err
}
4 changes: 3 additions & 1 deletion pkg/keyctl/keyring_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// +build linux
// +build 386 amd64

package keyctl

Expand Down Expand Up @@ -82,6 +81,9 @@ func TestLink(t *testing.T) {
}

_, err = userKeyring.Search(testname)
if err == nil {
t.Fatalf("Expected error, but got key %v", testname)
}
ExpectedError := "required key not available"
if err.Error() != ExpectedError {
t.Fatal(err)
Expand Down
6 changes: 5 additions & 1 deletion pkg/keyctl/perm.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

package keyctl

import (
"golang.org/x/sys/unix"
)

// KeyPerm represents in-kernel access control permission to keys and keyrings
// as a 32-bit integer broken up into four permission sets, one per byte.
// In MSB order, the perms are: Processor, User, Group, Other.
Expand All @@ -24,6 +28,6 @@ const (

// SetPerm sets the permissions on a key or keyring.
func SetPerm(k ID, p KeyPerm) error {
_, _, err := keyctl(keyctlSetPerm, uintptr(k.ID()), uintptr(p))
err := unix.KeyctlSetperm(k.ID(), uint32(p))
return err
}
104 changes: 6 additions & 98 deletions pkg/keyctl/sys_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,119 +3,27 @@
// license that can be found in the LICENSE file.

// +build linux
// +build 386 amd64

package keyctl

import (
"syscall"
"unsafe"
"golang.org/x/sys/unix"
)

type keyctlCommand int
type keyID int

type keyID int32

const (
keySpecSessionKeyring keyID = -3
keySpecUserKeyring keyID = -4
)

const (
keyctlGetKeyringID keyctlCommand = 0
keyctlSetPerm keyctlCommand = 5
keyctlLink keyctlCommand = 8
keyctlUnlink keyctlCommand = 9
keyctlSearch keyctlCommand = 10
keyctlRead keyctlCommand = 11
)

func (id keyID) ID() int32 {
return int32(id)
}

func keyctl(cmd keyctlCommand, args ...uintptr) (r1 int32, r2 int32, err error) {
a := make([]uintptr, 6)
l := len(args)
if l > 5 {
l = 5
}
a[0] = uintptr(cmd)
for idx, v := range args[:l] {
a[idx+1] = v
}
v1, v2, errno := syscall.Syscall6(syscallKeyctl, a[0], a[1], a[2], a[3], a[4], a[5])
if errno != 0 {
err = errno
return
}

r1 = int32(v1)
r2 = int32(v2)
return
}

func addkey(keyType, keyDesc string, payload []byte, id int32) (int32, error) {
var (
err error
errno syscall.Errno
b1, b2 *byte
r1 uintptr
pptr unsafe.Pointer
)

if b1, err = syscall.BytePtrFromString(keyType); err != nil {
return 0, err
}

if b2, err = syscall.BytePtrFromString(keyDesc); err != nil {
return 0, err
}

if len(payload) > 0 {
pptr = unsafe.Pointer(&payload[0])
}
r1, _, errno = syscall.Syscall6(syscallAddKey,
uintptr(unsafe.Pointer(b1)),
uintptr(unsafe.Pointer(b2)),
uintptr(pptr),
uintptr(len(payload)),
uintptr(id),
0)

if errno != 0 {
err = errno
return 0, err
}
return int32(r1), nil
func (id keyID) ID() int {
return int(id)
}

func newKeyring(id keyID) (*keyring, error) {
r1, _, err := keyctl(keyctlGetKeyringID, uintptr(id), uintptr(1))
r1, err := unix.KeyctlGetKeyringID(int(id), true)
if err != nil {
return nil, err
}

if id < 0 {
r1 = int32(id)
r1 = int(id)
}
return &keyring{id: keyID(r1)}, nil
}

func searchKeyring(id keyID, name, keyType string) (keyID, error) {
var (
r1 int32
b1, b2 *byte
err error
)

if b1, err = syscall.BytePtrFromString(keyType); err != nil {
return 0, err
}
if b2, err = syscall.BytePtrFromString(name); err != nil {
return 0, err
}

r1, _, err = keyctl(keyctlSearch, uintptr(id), uintptr(unsafe.Pointer(b1)), uintptr(unsafe.Pointer(b2)))
return keyID(r1), err
}
12 changes: 0 additions & 12 deletions pkg/keyctl/sys_linux_386.go

This file was deleted.

12 changes: 0 additions & 12 deletions pkg/keyctl/sys_linux_amd64.go

This file was deleted.

0 comments on commit dd01136

Please sign in to comment.