Skip to content

Commit

Permalink
fix(capabilities): revert to real UID as needed
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuar committed Jun 26, 2023
1 parent 3547eff commit 04167f8
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 6 deletions.
42 changes: 37 additions & 5 deletions capabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,50 @@
package gokbd

import (
"os/user"
"strconv"

"github.com/rs/zerolog/log"

"kernel.org/pub/linux/libs/security/libcap/cap"
)

// taken from https://git.kernel.org/pub/scm/libs/libcap/libcap.git/tree/goapps/setid/setid.go#n32
// TODO: re-write to just elevate to root privileges
func setIDsWithCaps(setUID, setGID int, gids []int) {
if err := cap.SetGroups(setGID, gids...); err != nil {
log.Fatal().Err(err).Msg("Unable to raise gid to root.")
func setIDsWithCaps(setgid, setuid int, gids []int) {

if err := cap.SetGroups(setgid, gids...); err != nil {
log.Fatal().Err(err).Msgf("Unable to set gid to %d.", setgid)
}
if err := cap.SetUID(setuid); err != nil {
log.Fatal().Err(err).Msgf("Unable to set uid to %d.", setuid)
}
}

func getInputGroupGid() int {
inputGroup, err := user.LookupGroup("input")
if err != nil {
log.Fatal().Err(err).Msg("No input group defined.")
}
inputGroupGid, err := strconv.Atoi(inputGroup.Gid)
if err != nil {
log.Fatal().Err(err).Msg("Could not convert gid string to int.")
}
return inputGroupGid
}

func getUserIds() (int, int) {
userDetails, err := user.Current()
if err != nil {
log.Fatal().Err(err).Msg("Could not retrieve user details.")
}
uid, err := strconv.Atoi(userDetails.Uid)
if err != nil {
log.Fatal().Err(err).Msg("Could not convert uid string to int.")
}
if err := cap.SetUID(setUID); err != nil {
log.Fatal().Err(err).Msg("Unable to raise uid to root.")
gid, err := strconv.Atoi(userDetails.Gid)
if err != nil {
log.Fatal().Err(err).Msg("Could not convert gid string to int.")
}
return uid, gid
}
7 changes: 6 additions & 1 deletion keyboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ func NewVirtualKeyboard(name string) (*VirtualKeyboardDevice, error) {
}
var uidev *C.struct_libevdev_uinput

uid, gid := getUserIds()
setIDsWithCaps(0, 0, nil)

dev := C.libevdev_new()
Expand All @@ -227,23 +228,27 @@ func NewVirtualKeyboard(name string) (*VirtualKeyboardDevice, error) {
for k := range runeMap {
C.libevdev_enable_event_code(dev, C.EV_KEY, C.uint(k), nil)
}

// expose some modifier keys (in this case just the left ones, we only need those)
C.libevdev_enable_event_code(dev, C.EV_KEY, C.KEY_LEFTSHIFT, nil)
C.libevdev_enable_event_code(dev, C.EV_KEY, C.KEY_LEFTCTRL, nil)
C.libevdev_enable_event_code(dev, C.EV_KEY, C.KEY_LEFTALT, nil)
C.libevdev_enable_event_code(dev, C.EV_KEY, C.KEY_LEFTMETA, nil)

rv := C.libevdev_uinput_create_from_device(dev, C.LIBEVDEV_UINPUT_OPEN_MANAGED, &uidev)
if rv > 0 {
if rv > 0 || uidev == nil {
return nil, errors.New("failed to create new uinput device")
}
log.Debug().Caller().
Msgf("Virtual keyboard created at %s.",
C.GoString(C.libevdev_uinput_get_devnode(uidev)))
time.Sleep(time.Millisecond * 500)

setIDsWithCaps(uid, gid, []int{getInputGroupGid()})
if err := cap.NewSet().SetProc(); err != nil {
return nil, fmt.Errorf("unable to drop privilege: %v", err)
}

return &VirtualKeyboardDevice{
uidev: uidev,
dev: dev,
Expand Down

0 comments on commit 04167f8

Please sign in to comment.