From 3e0ca68d10dfe6319b39a5e647a36a05ddd007a8 Mon Sep 17 00:00:00 2001 From: 65a <65a@localhost.localdomain> Date: Wed, 29 Dec 2021 03:30:10 +0000 Subject: [PATCH] Support attaching the kernel persistent keyring to an existing keyring (for example, session keyring). Currently, this will always use the persistent keyring associated with the UID executing the process. Specifying UID is supportable but use case unclear. The AttachPersistent() function will return a Keyring pointing to the kernel persistent keyring, or an error. --- keyring.go | 9 +++++++++ keyring_test.go | 12 ++++++++++++ sys_linux.go | 17 +++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/keyring.go b/keyring.go index 6761087..981ef1d 100644 --- a/keyring.go +++ b/keyring.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux // +build linux // A Go interface to linux kernel keyrings (keyctl interface) @@ -21,6 +22,7 @@ type Keyring interface { Add(string, []byte) (*Key, error) Search(string) (*Key, error) SetDefaultTimeout(uint) + AttachPersistent() (Keyring, error) } // Named keyrings are user-created keyrings linked to a parent keyring. The @@ -93,6 +95,13 @@ func (kr *keyring) Search(name string) (*Key, error) { return nil, err } +// AttachPersistent attaches the current executing context's persistent +// keyring to this keyring. See persistent-keyring(7) for more info. +// It returns either an error, or the persistent Keyring. +func (kr *keyring) AttachPersistent() (Keyring, error) { + return attachPersistent(kr.id) +} + // Return the current login session keyring func SessionKeyring() (Keyring, error) { return newKeyring(keySpecSessionKeyring) diff --git a/keyring_test.go b/keyring_test.go index a78d43c..5513fc1 100644 --- a/keyring_test.go +++ b/keyring_test.go @@ -112,6 +112,18 @@ func TestCreateKeyring(t *testing.T) { } } +func TestAttachPersistentKeyring(t *testing.T) { + kr, err := SessionKeyring() + if err != nil { + t.Fatalf("unexpected test failure: could not create session keyring: %v", err) + } + pkr, err := kr.AttachPersistent() + if err != nil { + t.Fatalf("unexpected test failure: could not attach persistent keyring: %v", err) + } + t.Logf("found persistent keyring %d", pkr.Id()) +} + func TestCreateNestedKeyring(t *testing.T) { ring := helperTestCreateKeyring(nil, "", t) diff --git a/sys_linux.go b/sys_linux.go index 0c4c194..9e8abbb 100644 --- a/sys_linux.go +++ b/sys_linux.go @@ -37,6 +37,12 @@ const ( keyctlSetReqKeyKeyring keyctlSetTimeout keyctlAssumeAuthority + keyctlGetSecurity + keyctlSessionToParent + keyctlReject + keyctlInstantiateIOV + keyctlInvalidate + keyctlGetPersistent ) var debugSyscalls bool @@ -81,6 +87,8 @@ func (cmd keyctlCommand) String() string { return "keyctlSetTimeout" case keyctlAssumeAuthority: return "keyctlAssumeAuthority" + case keyctlGetPersistent: + return "keyctlGetPersistent" } panic("bad arg") } @@ -294,3 +302,12 @@ func updateKey(id keyId, payload []byte) error { } return nil } + +func attachPersistent(id keyId) (*keyring, error) { + uid := int32(-1) + r1, _, errno := syscall.Syscall(syscall_keyctl, uintptr(keyctlGetPersistent), uintptr(uid), uintptr(id)) + if errno != 0 { + return nil, errno + } + return &keyring{id: keyId(r1)}, nil +}