-
Notifications
You must be signed in to change notification settings - Fork 387
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update keyctl for other arches #675
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Non-blocking, RFC: Maybe add a note here that the package is deprecated, and most callers should call |
||
package keyctl | ||
|
||
import ( | ||
"golang.org/x/sys/unix" | ||
) | ||
|
||
// Keyring is the basic interface to a linux keyctl keyring. | ||
type Keyring interface { | ||
ID | ||
|
@@ -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 | ||
|
@@ -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 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Non-blocking: AFAICS this method can be safely dropped; all There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you're right - the only consumer I'm aware of is elsewhere in the library. Would you like a follow-up PR? |
||
} | ||
|
||
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 | ||
} |
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strictly speaking, this is an API break. Do we need to change this?
int
would certainly be more idiomatic Go; still, the kernelkey_serial_t
is anint32_t
, so this does not seem to hurt anything.Same for
ID.ID
/Keyring.ID
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, you're right. The APIs in
golang.org/x/sys/unix
useint
for key types, so I changed the package to match without considering that.