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

Process.Linux: handle when /proc and the process pid namespace don't match. #100076

Merged
merged 2 commits into from
Jul 16, 2024

Conversation

tmds
Copy link
Member

@tmds tmds commented Mar 21, 2024

Normally the '/proc' filesystem uses the same pid namespace as the process. With rootless containers, it may happen that these pid namespaces do not match because the container doesn't have permissions to change '/proc' but it can create a new pid namespace.

When that happens, the numeric ids used by the /proc filesystem no longer match with the process pid namespace. We can still access information for the current process using '/proc/self'. For other processes, we can't map pids to the proc pids, which leads to reading information for non-existing/wrong/inaccessible processes.

Closes #99887.

@dotnet/area-system-diagnostics-process @stephentoub ptal.

cc @omajid

…match.

Normally the '/proc' filesystem uses the same pid namespace as the process.
With rootless containers, it may happen that these pid namespaces do not match
because the container doesn't have permissions to change '/proc' but it can
create a new pid namespace.

When that happens, the numeric ids used by the /proc filesystem no longer match with
the process pid namespace. We can still access information for the current process
using '/proc/self'. For other processes, we can't map pids to the proc pids, which
leads to reading information for non-existing/wrong/inaccessible processes.
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process
See info in area-owners.md if you want to be subscribed.

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Mar 21, 2024
@tmds
Copy link
Member Author

tmds commented Mar 21, 2024

With rootless containers, it may happen that these pid namespaces do not match

To reproduces the issue without containers, you can run sudo unshare -p --fork /bin/sh.

In that environment you can run a program like:

Console.WriteLine(Process.GetCurrentProcess().PeakWorkingSet64);

When running this, sometimes this will print out a value, sometimes throw InvalidOperationException for an exited process.

In all cases, it is using information from /proc for another process than the current one.

@tmds
Copy link
Member Author

tmds commented Apr 16, 2024

@dotnet/area-system-diagnostics-process can you take a look?

Though it is not a common scenario, I think it's valuable we make .NET behave correct because it can occur in containers and CI. A user can not fix it and diagnosing the root cause may also be a challenge for them.

@am11
Copy link
Member

am11 commented Apr 16, 2024

For "self" case, we could short-circuit to Environment.ProcessId as we are doing that for Environment.ProcessPath in this code. (assuming Environment.ProcessId is returning the correct value in rootless case; I have't tested)

@tmds
Copy link
Member Author

tmds commented Apr 16, 2024

For "self" case, we could short-circuit to Environment.ProcessId as we are doing that for Environment.ProcessPath in this code. (assuming Environment.ProcessId is returning the correct value in rootless case; I have't tested)

To get the current process pid we don't use /proc. I don't understand what you are suggesting.

@am11
Copy link
Member

am11 commented Apr 17, 2024

I don't understand what you are suggesting.

I was looking at this and thought it could be replaced by procPid == Environment.ProcessId:

image

@tmds
Copy link
Member Author

tmds commented Apr 17, 2024

I was looking at this and thought it could be replaced by procPid == Environment.ProcessId:

We're adding ProcPid to represent identifiers as they are used by /proc. Environment.ProcessId is an identifier as used by the pid namespace. We mustn't compare these directly. TryGetProcPid gets us from ProcessId to ProcPid.Self. Then in GetExePath for ProcPid.Self instead of reading from /proc/self we optimize by using Environment.ProcessPath.

@tmds
Copy link
Member Author

tmds commented Apr 29, 2024

@dotnet/area-system-diagnostics-process ptal.

1 similar comment
@tmds
Copy link
Member Author

tmds commented May 21, 2024

@dotnet/area-system-diagnostics-process ptal.

@tmds
Copy link
Member Author

tmds commented Jun 7, 2024

@jeffhandley @adamsitnik can you take a look at this PR please?

@tmds
Copy link
Member Author

tmds commented Jun 14, 2024

@jeffhandley @adamsitnik can you take a look? I assume the review is slow because this is a niche case. I looked into this due to a support case. The root cause was hard to diagnose for the end-user, and they could not work around it.

Copy link
Member

@stephentoub stephentoub left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay. LGTM.

Copy link
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM, but please answer my question before I hit the merge button.

And once again big thanks for your help @tmds and apologies for the delays in my areas (I was 100% focused on the BinaryFormatter removal effort)

{
procSelfPid = pid;
}
Debug.Assert(procSelfPid.HasValue);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug.Assert(procSelfPid.HasValue) assumes that the value will be always present, but the condition below does not follow this assumption and in such case returns 1 ('/proc' and the process pid namespace match).

Why is that?

Copy link
Member Author

@tmds tmds Jul 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's handling the unexpected (should never happen) case where we were unable to determine the proc fs pid for self.

@tmds
Copy link
Member Author

tmds commented Jul 8, 2024

@adamsitnik this should be good to merge.

Copy link
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you @tmds !

@adamsitnik
Copy link
Member

I need to close and re-open the PR so the CI can re-run the failed legs.

@adamsitnik adamsitnik closed this Jul 15, 2024
@adamsitnik adamsitnik reopened this Jul 15, 2024
@adamsitnik adamsitnik merged commit 773f3cd into dotnet:main Jul 16, 2024
146 checks passed
@adamsitnik adamsitnik added this to the 9.0.0 milestone Jul 16, 2024
@@ -8,6 +8,6 @@ namespace System
public static partial class Environment
{
public static long WorkingSet =>
(long)(Interop.procfs.TryReadProcessStatusInfo(ProcessId, out Interop.procfs.ProcessStatusInfo status) ? status.ResidentSetSize : 0);
(long)(Interop.procfs.TryReadProcessStatusInfo(Interop.procfs.ProcPid.Self, out Interop.procfs.ProcessStatusInfo status) ? status.ResidentSetSize : 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks the build on illumos. Was this intentional?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. I assume the fix is straight forward?

Copy link
Member

@am11 am11 Jul 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I will push it to my ongoing branch #105178. Was checking if you had other plans for it, I'll just revert.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@github-actions github-actions bot locked and limited conversation to collaborators Aug 20, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Diagnostics.Process community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Process.Linux: handle when proc mount mismatches with pid namespace
4 participants