Skip to content

Commit

Permalink
fixed the race condition that led to concurrent map access in a publi…
Browse files Browse the repository at this point in the history
…cshare manager
  • Loading branch information
2403905 committed Jan 23, 2024
1 parent e8fc07f commit 4c4dcd4
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 16 deletions.
6 changes: 6 additions & 0 deletions changelog/unreleased/fix-concurrent-access-to-map.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Bugfix: Fix concurrent access to a map

We fixed the race condition that led to concurrent map access in a publicshare manager.

https://github.com/cs3org/reva/pull/4472
https://github.com/owncloud/ocis/issues/8255
34 changes: 18 additions & 16 deletions pkg/publicshare/manager/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ func (m *manager) Dump(ctx context.Context, shareChan chan<- *publicshare.WithPa

// Load imports public shares and received shares from channels (e.g. during migration)
func (m *manager) Load(ctx context.Context, shareChan <-chan *publicshare.WithPassword) error {
m.mutex.Lock()
defer m.mutex.Unlock()

db, err := m.persistence.Read(ctx)
if err != nil {
return err
Expand Down Expand Up @@ -414,6 +417,9 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link

// GetPublicShare gets a public share either by ID or Token.
func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference, sign bool) (*link.PublicShare, error) {
m.mutex.Lock()
defer m.mutex.Unlock()

if ref.GetToken() != "" {
ps, pw, err := m.getByToken(ctx, ref.GetToken())
if err != nil {
Expand All @@ -428,9 +434,6 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu
return ps, nil
}

m.mutex.Lock()
defer m.mutex.Unlock()

db, err := m.persistence.Read(ctx)
if err != nil {
return nil, err
Expand Down Expand Up @@ -566,15 +569,13 @@ func (m *manager) cleanupExpiredShares() {
}
}

// revokeExpiredPublicShare doesn't have a lock inside, ensure a lock before call
func (m *manager) revokeExpiredPublicShare(ctx context.Context, s *link.PublicShare, u *user.User) error {
if !m.enableExpiredSharesCleanup {
return nil
}

m.mutex.Unlock()
defer m.mutex.Lock()

err := m.RevokePublicShare(ctx, u, &link.PublicShareReference{
err := m.revokePublicShare(ctx, u, &link.PublicShareReference{
Spec: &link.PublicShareReference_Id{
Id: &link.PublicShareId{
OpaqueId: s.Id.OpaqueId,
Expand All @@ -592,11 +593,16 @@ func (m *manager) revokeExpiredPublicShare(ctx context.Context, s *link.PublicSh
// RevokePublicShare undocumented.
func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) error {
m.mutex.Lock()
defer m.mutex.Unlock()
return m.revokePublicShare(ctx, u, ref)
}

// revokePublicShare doesn't have a lock inside, ensure a lock before call
func (m *manager) revokePublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) error {
db, err := m.persistence.Read(ctx)
if err != nil {
return err
}
m.mutex.Unlock()

switch {
case ref.GetId() != nil && ref.GetId().OpaqueId != "":
Expand All @@ -615,20 +621,16 @@ func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, ref *link
return errors.New("reference does not exist")
}

m.mutex.Lock()
defer m.mutex.Unlock()
return m.persistence.Write(ctx, db)
}

// getByToken doesn't have a lock inside, ensure a lock before call
func (m *manager) getByToken(ctx context.Context, token string) (*link.PublicShare, string, error) {
db, err := m.persistence.Read(ctx)
if err != nil {
return nil, "", err
}

m.mutex.Lock()
defer m.mutex.Unlock()

for _, v := range db {
var local link.PublicShare
if err := utils.UnmarshalJSONToProtoV1([]byte(v.(map[string]interface{})["share"].(string)), &local); err != nil {
Expand All @@ -646,14 +648,14 @@ func (m *manager) getByToken(ctx context.Context, token string) (*link.PublicSha

// GetPublicShareByToken gets a public share by its opaque token.
func (m *manager) GetPublicShareByToken(ctx context.Context, token string, auth *link.PublicShareAuthentication, sign bool) (*link.PublicShare, error) {
m.mutex.Lock()
defer m.mutex.Unlock()

db, err := m.persistence.Read(ctx)
if err != nil {
return nil, err
}

m.mutex.Lock()
defer m.mutex.Unlock()

for _, v := range db {
passDB := v.(map[string]interface{})["password"].(string)
var local link.PublicShare
Expand Down

0 comments on commit 4c4dcd4

Please sign in to comment.