|
|
Subscribe / Log in / New account

Missed some rows

Missed some rows

Posted May 4, 2011 5:03 UTC (Wed) by wahern (subscriber, #37304)
In reply to: Missed some rows by Cyberax
Parent article: Poettering: Why systemd?

I'm confused then. Say I have a new process which I want to add to a cgroup. How do I assign the process to a cgroup? All the documentation I can find says to echo the PID to a cgroup control file. But if I'm using a PID--and I'm not the process with that PID--then I'm still subject to a race--the PID can become stale between acquiring the value and communicating it to the cgroup subsystem.

cgroup inheritance I can understand. A process forked from a process already assigned to a particular cgroup atomically inherits membership in the cgroup, just as it would atomically inherit a session id and process group id. But now, say, I want to reassign that process to a different cgroup PID. It seems like there's the same problem as above. What am I missing?


to post comments

Missed some rows

Posted May 4, 2011 5:44 UTC (Wed) by Cyberax (✭ supporter ✭, #52523) [Link] (1 responses)

That's a trick question.

You need to somehow have a unique process handle, which PID is definitely not. On Linux it can be done using the /proc/PID/ directory. The sequence would be:
1) Change current directory to /proc/PID
2) Look around and check that this PID is still the correct one. That's safe because if the process its /proc/PID directory becomes empty - and stays that way.
3) Write to /proc/PID/cgroup.

Of course, it's better to create a process directly in the required group in the first place.

Missed some rows

Posted May 4, 2011 8:26 UTC (Wed) by wahern (subscriber, #37304) [Link]

I thought /proc/$PID/cgroup was read-only; to add a process to a group you needed to write to /dev/cgroup/$TASK/tasks. In such case, you're left with a race condition. (I tried confirming or disproving this, but can't even get the example in cgroups.txt to work.)

My proposal was to make PID a unique quasi-handle the same way random UUIDs are unique.

Missed some rows

Posted May 4, 2011 19:31 UTC (Wed) by njs (subscriber, #40338) [Link] (2 responses)

> Say I have a new process which I want to add to a cgroup. How do I assign the process to a cgroup? All the documentation I can find says to echo the PID to a cgroup control file. But if I'm using a PID--and I'm not the process with that PID--then I'm still subject to a race--the PID can become stale between acquiring the value and communicating it to the cgroup subsystem.

In the above scheme, if you're the one who's spawning this new process that you want to end up in a cgroup, then you can do
1) fork
2) the child adds itself to the desired cgroup
3) the child calls exec()

That's race-free.

Missed some rows

Posted May 4, 2011 21:08 UTC (Wed) by wahern (subscriber, #37304) [Link] (1 responses)

Sure. But the issue is handling arbitrary, non-well behaving processes. And AFAICT there's still no provably safe way to handle that on Unix systems. With only a 16-bit (or 15-bit, or 22-bit) PID space, it's trivial to write a program to sit around and wait to take advantage of a race. (I don't have an attacker mindset, but I wouldn't bet against the proposition that it could be a useful vector.)

Of course, "who cares" is a valid reply; we've been living with it for 40 years. But that response challenges the value added by systemd's reliance on esoteric Linux subsystems. For example, when we talk about how a service manager is so much better than a race-prone PID file, nobody ever considers that the race condition is easily avoided by not using root. If you create a user per daemon--_www, _ftp, etc--then even if you read a stale PID and signal the wrong process, as long as you're sending the signal with a service-delegated UID then it will never be delivered.

I never brought it up before because it's arguably not very elegant. I'm loath to defend PID files. But if we're going to replace them with something, I'd like it to be generic and tailored to the specific issue, rather than lauding some supposed panacean init replacement.

The past decade in Linux-land has seen a parade of sophisticated daemon services intended to patch over some clunky Unix interface (device management, process management, etc, etc). They each require application developers to change from portable POSIX patterns to using some new API or library or protocol. But they come and go like the wind. Worthy solutions tend to be so obviously beneficial that all the free unices eagerly adopt or mimic them.

Missed some rows

Posted May 5, 2011 1:06 UTC (Thu) by njs (subscriber, #40338) [Link]

I guess I don't understand what you mean by "managing arbitrary, non-well behaving processes".

IIUC, when systemd starts a service, that service gets stuck (reliably, and race-freely) into its own cgroup, from which it cannot escape. Then you can kill it or whatever reliably, even if it's badly behaved (spawning children that double-fork and end up as orphans, forking to a new PID every 100 ms, whatever you like).

If you're trying to go after a process that was started outside of a cgroup, then this doesn't work so well, but not much does. That process that keeps switching PIDs as quickly as possible can't easily be killed even if you have a collision-free PID space.


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds