backport of commit c329ed8d3b02b92dfded30065317c82648d3cae3 (#24260)

Co-authored-by: Steven Clark <steven.clark@hashicorp.com>
This commit is contained in:
hc-github-team-secure-vault-core 2023-11-27 16:21:51 -05:00 committed by GitHub
parent 37e064db3d
commit f5fedb026f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 12 deletions

4
changelog/24256.txt Normal file
View File

@ -0,0 +1,4 @@
```release-note:bug
api: Fix deadlock on calls to sys/leader with a namespace configured
on the request.
```

View File

@ -150,30 +150,41 @@ func (c *Core) Leader() (isLeader bool, leaderAddr, clusterAddr string, err erro
if c.Sealed() {
return false, "", "", consts.ErrSealed
}
c.stateLock.RLock()
defer c.stateLock.RUnlock()
return c.LeaderLocked()
}
func (c *Core) LeaderLocked() (isLeader bool, leaderAddr, clusterAddr string, err error) {
// Check if HA enabled. We don't need the lock for this check as it's set
// on startup and never modified
if c.ha == nil {
return false, "", "", ErrHANotEnabled
}
// Check if sealed
if c.Sealed() {
return false, "", "", consts.ErrSealed
}
// Check if we are the leader
if !c.standby {
c.stateLock.RUnlock()
return true, c.redirectAddr, c.ClusterAddr(), nil
}
// Initialize a lock
lock, err := c.ha.LockWith(CoreLockPath, "read")
if err != nil {
c.stateLock.RUnlock()
return false, "", "", err
}
// Read the value
held, leaderUUID, err := lock.Value()
if err != nil {
c.stateLock.RUnlock()
return false, "", "", err
}
if !held {
c.stateLock.RUnlock()
return false, "", "", nil
}
@ -188,13 +199,11 @@ func (c *Core) Leader() (isLeader bool, leaderAddr, clusterAddr string, err erro
// If the leader hasn't changed, return the cached value; nothing changes
// mid-leadership, and the barrier caches anyways
if leaderUUID == localLeaderUUID && localRedirectAddr != "" {
c.stateLock.RUnlock()
return false, localRedirectAddr, localClusterAddr, nil
}
c.logger.Trace("found new active node information, refreshing")
defer c.stateLock.RUnlock()
c.leaderParamsLock.Lock()
defer c.leaderParamsLock.Unlock()

View File

@ -4811,8 +4811,15 @@ type LeaderResponse struct {
}
func (core *Core) GetLeaderStatus() (*LeaderResponse, error) {
core.stateLock.RLock()
defer core.stateLock.RUnlock()
return core.GetLeaderStatusLocked()
}
func (core *Core) GetLeaderStatusLocked() (*LeaderResponse, error) {
haEnabled := true
isLeader, address, clusterAddr, err := core.Leader()
isLeader, address, clusterAddr, err := core.LeaderLocked()
if errwrap.Contains(err, ErrHANotEnabled.Error()) {
haEnabled = false
err = nil
@ -4826,10 +4833,10 @@ func (core *Core) GetLeaderStatus() (*LeaderResponse, error) {
IsSelf: isLeader,
LeaderAddress: address,
LeaderClusterAddress: clusterAddr,
PerfStandby: core.PerfStandby(),
PerfStandby: core.perfStandby,
}
if isLeader {
resp.ActiveTime = core.ActiveTime()
resp.ActiveTime = core.activeTime
}
if resp.PerfStandby {
resp.PerfStandbyLastRemoteWAL = LastRemoteWAL(core)
@ -4837,7 +4844,7 @@ func (core *Core) GetLeaderStatus() (*LeaderResponse, error) {
resp.LastWAL = LastWAL(core)
}
resp.RaftCommittedIndex, resp.RaftAppliedIndex = core.GetRaftIndexes()
resp.RaftCommittedIndex, resp.RaftAppliedIndex = core.GetRaftIndexesLocked()
return resp, nil
}
@ -4861,7 +4868,7 @@ func (b *SystemBackend) handleSealStatus(ctx context.Context, req *logical.Reque
}
func (b *SystemBackend) handleLeaderStatus(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
status, err := b.Core.GetLeaderStatus()
status, err := b.Core.GetLeaderStatusLocked()
if err != nil {
return nil, err
}

View File

@ -70,7 +70,10 @@ func (c *Core) GetRaftNodeID() string {
func (c *Core) GetRaftIndexes() (committed uint64, applied uint64) {
c.stateLock.RLock()
defer c.stateLock.RUnlock()
return c.GetRaftIndexesLocked()
}
func (c *Core) GetRaftIndexesLocked() (committed uint64, applied uint64) {
raftStorage, ok := c.underlyingPhysical.(*raft.RaftBackend)
if !ok {
return 0, 0