func userKeyringIDLookup(uid int) (keyringID int, err error) {
	cacheLock.Lock()
	defer cacheLock.Unlock()
	var ok bool
	if keyringID, ok = keyringIDCache[uid]; ok {
		return
	}

	// Our goals here are to:
	//    - Find the user keyring (for the provided uid)
	//    - Link it into the current process keyring (so we can use it)
	//    - Make no permenant changes to the process privileges
	// Complicating this are the facts that:
	//    - The value of KEY_SPEC_USER_KEYRING is determined by the ruid
	//    - Keyring linking permissions use the euid
	// So we have to change both the ruid and euid to make this work,
	// setting the suid to 0 so that we can later switch back.
	ruid, euid, suid := getUids()
	if ruid != uid || euid != uid {
		if err = setUids(uid, uid, 0); err != nil {
			return
		}
		defer func() {
			resetErr := setUids(ruid, euid, suid)
			if resetErr != nil {
				err = resetErr
			}
		}()
	}

	// We get the value of KEY_SPEC_USER_KEYRING. Note that this will also
	// trigger the creation of the uid keyring if it does not yet exist.
	keyringID, err = unix.KeyctlGetKeyringID(unix.KEY_SPEC_USER_KEYRING, true)
	log.Printf("keyringID(_uid.%d) = %d, %v", uid, keyringID, err)
	if err != nil {
		return 0, err
	}

	// We still want to use this keyring after our privileges are reset. So
	// we link it into the process keyring, preventing a loss of access.
	if err = keyringLink(keyringID, unix.KEY_SPEC_PROCESS_KEYRING); err != nil {
		return 0, err
	}

	keyringIDCache[uid] = keyringID
	return keyringID, nil
}