protonscr

Steam attempts to ptrace other processes running with bubblewrap

steamopen
ValveSoftware/steam-for-linux#11941 · opened 2025-04-24 by mackerel225 · updated 2025-04-29 · 3 comments · github
Mmackerel225 2025-04-24 github

Your system information

  • Steam client version (build number or date): 1.0.0.82-2 (Arch Linux Package)
  • Distribution (e.g. Ubuntu): Arch Linux
  • Opted into Steam client beta?: No
  • Have you checked for system updates?: Yes

Please describe your issue in as much detail as possible:

What happened?
I'm seeing Steam attempt to ptrace other unrelated applications, such as LibreWolf, which is sandboxed using bwrap and AppArmor. This shows up in audit logs as:

type=AVC msg=audit(1745518870.131:2771): apparmor="DENIED" operation="ptrace" class="ptrace" profile="steam" pid=8236 comm="steam" requested_mask="read" denied_mask="read" peer="bwrap//&librewolf//&unpriv_bwrap"

ptrace is commonly used for debugging or interacting with a process's memory, and it should not be applied to unrelated applications.. LibreWolf is not launched or related to Steam in any way. I understand Steam is also using sandboxing which might conflict with the one that is available on the host machine.

What should happen?
Steam should not be ptracing other processes, except the ones started and managed by Steam.

Steps for reproducing this issue:

  1. Launch application with bubblewrap, e.g. Librewolf
  2. Launch Steam
  3. Steam starts ptracing other processes launched with bubblewrap
Ssmcv 2025-04-28 github

This might just be Steam reading process information like command-lines and environment variables out of the pseudo-files in /proc. If I remember correctly, AppArmor mediates and logs that as a ptrace read, even though it isn't really - and I think Steam looks at other processes' environment variables in order to identify which ones are descendants of something that it started. (It can't necessarily just walk the process hierarchy, because programs that daemonize and run in the background can get re-parented to a process "above" Steam.)

Recent AppArmor versions have profiles that get applied to anything that is sandboxed with bubblewrap, allowing them to keep working on distros like Ubuntu, which have a kernel patch that makes ordinary unconfined processes unable to create new user namespaces (and therefore unable to run bubblewrap). (I think this is an odd design choice, because unconfined was previously the most-privileged and least-confined AppArmor profile, hence its name...)

On your system, Steam is running under one of those profiles, and Librewolf is running under another. I suspect that before 2025, Steam and Librewolf were both running on your system as unconfined, meaning that one of them inspecting process information about the other would not be diagnosed in the audit log.

Mmackerel225 2025-04-29 github

This might just be Steam reading process information like command-lines and environment variables out of the pseudo-files in /proc. If I remember correctly, AppArmor mediates and logs that as a ptrace read

I see, thanks for clarification. What you are saying is probably true, entire proc/ r dir is required in AppArmor, otherwise it doesn't start Steam for me at all.

Steam looks at other processes' environment variables in order to identify which ones are descendants of something that it started

Would it be feasible for Steam to restrict its /proc or environment variable access to only its direct child processes, or processes it can confidently identify as part of its runtime? / i.e. narrow the scope down little bit, so it only inspects its own processes?

Ssmcv 2025-04-29 github

entire proc/ r dir is required in AppArmor, otherwise it doesn't start Steam for me at all

In general /proc is effectively part of the Linux user-space API and many programs require it, not just Steam.

Would it be feasible for Steam to restrict its /proc or environment variable access to only its direct child processes, or processes it can confidently identify as part of its runtime? / i.e. narrow the scope down little bit, so it only inspects its own processes?

Not necessarily. I can't see into the proprietary Steam code any more than you can, but I suspect that the inspecting of processes that you're seeing in the audit log is Steam trying to identify which processes belong to it. If my guess is correct, then by definition that inspection can't be limited to processes that belong to Steam, because you have to start somewhere.

Not every process managed by Steam is a direct child: its children can have children, and so on, which are equally under Steam's control. And if a child daemonizes, it will be re-parented "above" Steam, but is still conceptually part of Steam.

On systems that happen to use systemd, it could use scope cgroups, but that isn't portable to systems that use a different init system (sysvinit, etc.), so that can only be used for non-essential features (assuming that Valve want Steam to continue to be runnable on systems that use a different init system, which they presumably do). That would also be Linux-specific code that can't be shared with Steam-on-Windows, whereas environment variable inheritance is portable.

Making more use of prctl PR_SET_CHILD_SUBREAPER might be a way to group child processes without scanning all of /proc, but enumerating descendant processes using the available Linux kernel APIs is surprisingly difficult (the open-source parts of the Steam Runtime tried this, and it turned out that in kernels not configured with CONFIG_PROC_CHILDREN, linearly scanning /proc/*/status is still required - I don't know whether AppArmor mediates that as though it was a ptrace read or not). Again, that would be Linux-specific code that can't be shared with Steam-on-Windows, whereas environment variables are portable.

If you want meaningful privilege separation between Steam and other processes, one option is to create a separate unprivileged user account (perhaps named steam or guest or gamer or similar), and log in as that user when you want to play games. Ordinary Unix DAC prevents processes running as one unprivileged user from opening the /proc/*/environ of a process running as a different user.

Nothing extracted yet.