Skip to content
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

Recursive pinning can lose existing direct pin #4650

Closed
ghost opened this issue Feb 4, 2018 · 6 comments · Fixed by #6708
Closed

Recursive pinning can lose existing direct pin #4650

ghost opened this issue Feb 4, 2018 · 6 comments · Fixed by #6708
Labels
exp/expert Having worked on the specific codebase is important help wanted Seeking public contribution on this issue kind/bug A bug in existing code (including security flaws) topic/repo Topic repo

Comments

@ghost
Copy link

ghost commented Feb 4, 2018

Version information: 0.4.14-dev

Type: bug

Description:

This bit looks like it'll lose the existing direct pin if the attempt to add the recursive pin fails. The direct pin will have been removed, and the expected recursive pin won't have succeeded: https://github.com/ipfs/go-ipfs/blob/864c960aa641bff2820b59b5eeb9d93be5d0998d/pin/pin.go#L213-L228

directPin.Remove() should probably happen after recursePin.Add()

@ghost ghost added kind/bug A bug in existing code (including security flaws) topic/repo Topic repo labels Feb 4, 2018
@ghost
Copy link
Author

ghost commented Feb 4, 2018

And we probably want to guard against blocks being removed between FetchGraph() and recursePin.Add(), however unlikely it is to occur.

@ghost ghost added help wanted Seeking public contribution on this issue exp/novice Someone with a little familiarity can pick up labels Feb 14, 2018
@schomatis
Copy link
Contributor

@lgierth Is someone working on this? I'd like to make a try, it will help me to learn more about the pinning system.

@ghost
Copy link
Author

ghost commented Feb 24, 2018

@schomatis thanks, please go for it :)

@Kubuxu
Copy link
Member

Kubuxu commented Feb 24, 2018

@lgierth pinner is locked during this time and any access to pins does require locking (or at least it should, not true about: https://github.com/ipfs/go-ipfs/blob/864c960aa641bff2820b59b5eeb9d93be5d0998d/pin/pin.go#L491-L498), so there should not be any inconsistency.

The fact that those two functions do not require locking will lead to concurrent map modification/read panic and should be fixed.

@schomatis
Copy link
Contributor

schomatis commented Feb 25, 2018

@lgierth

directPin.Remove() should probably happen after recursePin.Add()

I agree. Maybe a function could be added to add recursive pins (e.g., addRecursePin) that would abstract the requirement that a pin can only be of only one type (e.g., direct or recursive) performing the atomic check p.directPin.Has(c) inside the function.

And we probably want to guard against blocks being removed between FetchGraph() and recursePin.Add(), however unlikely it is to occur.

As @Kubuxu commented the Pin function is protected by a lock and, for example, a direct attempt to remove the block being pinned with ipfs block rm will check for pins and block when it tries to call CheckIfPinned. However, if the garbage collection is run while adding the pin (ipfs repo gc), as RecursiveKeys is not protected, there is a chance that the block is removed before it is pinned (i.e., added to recursePin).

So both DirectKeys and RecursiveKeys (and probably any other exported function that manipulates the pin sets) should be locked to prevent similar issues (although they may be quite rare). Locking those getter pin functions may have some performance impact over other parts of the code that will stall while the pinner is working (from what I'm seeing adding a recursive pin is an expensive operation).

@schomatis
Copy link
Contributor

Looking more carefully into the issue I have to correct myself, ipfs pin add locks the GC so the above mentioned race condition should not happen, I still think DirectKeys and RecursiveKeys should be locked, as there may be other code paths that could lead to a similar situation.

@ghost ghost added exp/expert Having worked on the specific codebase is important and removed exp/novice Someone with a little familiarity can pick up labels Oct 5, 2018
Stebalien added a commit that referenced this issue Oct 8, 2019
Otherwise, we could abort while fetching the graph and stay in a state where the
direct pin is removed.

fixes #4650
Stebalien added a commit that referenced this issue Jan 17, 2020
Otherwise, we could abort while fetching the graph and stay in a state where the
direct pin is removed.

fixes #4650
Stebalien added a commit that referenced this issue Jan 17, 2020
Otherwise, we could abort while fetching the graph and stay in a state where the
direct pin is removed.

fixes #4650
Stebalien added a commit that referenced this issue Jan 17, 2020
Otherwise, we could abort while fetching the graph and stay in a state where the
direct pin is removed.

fixes #4650
ralendor pushed a commit to ralendor/go-ipfs that referenced this issue Jun 6, 2020
Otherwise, we could abort while fetching the graph and stay in a state where the
direct pin is removed.

fixes ipfs#4650
ralendor pushed a commit to ralendor/go-ipfs that referenced this issue Jun 6, 2020
Otherwise, we could abort while fetching the graph and stay in a state where the
direct pin is removed.

fixes ipfs#4650
ralendor pushed a commit to ralendor/go-ipfs that referenced this issue Jun 8, 2020
Otherwise, we could abort while fetching the graph and stay in a state where the
direct pin is removed.

fixes ipfs#4650
ralendor pushed a commit to ralendor/go-ipfs that referenced this issue Jun 8, 2020
Otherwise, we could abort while fetching the graph and stay in a state where the
direct pin is removed.

fixes ipfs#4650
ralendor pushed a commit to ralendor/go-ipfs that referenced this issue Jun 8, 2020
Otherwise, we could abort while fetching the graph and stay in a state where the
direct pin is removed.

fixes ipfs#4650
ralendor pushed a commit to ralendor/go-ipfs that referenced this issue Jun 8, 2020
Otherwise, we could abort while fetching the graph and stay in a state where the
direct pin is removed.

fixes ipfs#4650
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
exp/expert Having worked on the specific codebase is important help wanted Seeking public contribution on this issue kind/bug A bug in existing code (including security flaws) topic/repo Topic repo
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants