-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
proc-cmdline: filter PID1 arguments on container #26887
Conversation
cc @mrc0mmand |
This comment was marked as off-topic.
This comment was marked as off-topic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to do the trick, I can't reproduce the original issue anymore. Thanks!
e1bb47c
to
0f1eff1
Compare
0f1eff1
to
54fd715
Compare
54fd715
to
d39f30a
Compare
Updated quotation handling, and added tests. Unset the green label. PTAL. @mrc0mmand Please test again. Thank you. |
d39f30a
to
e31b372
Compare
Gave this a spin in both nspawn and QEMU with both coverage and sanitizers enabled (separately, of course), and everything still seems to be working as expected! |
@mrc0mmand Thank you! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fix is both too narrow and too wide in scope. Originally, filter_args()
was added with in a specific context: when we're doing reexecution, so we know what args where we're taking the args from and where we are passing them to. But this patch generalizes the use of this function to pretty much all code that looks at the kernel command line, and I'm not sure if this is appropriate. I would expect at least a lot more discussion why we can and should do this so widely.
On the other hand, it is easy to show that this patch is too narrow. Generally, any code which looks at /proc/1/cmdline
needs to handle all arguments that are supported by pid1, for example --log-level
or --crash-chvt
. This patch does not do this.
It is trivial to show that e.g. --log-level
can be misinterpreted by systemd-debug-generator
:
$ SYSTEMD_LOG_LEVEL=debug SYSTEMD_LOG_TARGET=console SYSTEMD_PROC_CMDLINE='--log-level 5 systemd.debug-shell' build/systemd-debug-generator /tmp/x/
SELinux enabled state cached to: disabled
$ find /tmp/x/
/tmp/x/
/tmp/x/graphical.target.wants
/tmp/x/graphical.target.wants/debug-shell.service
I think we should first think what proc_cmdline()
should return in various contexts. E.g. we use it for ConditionKernelCommandLine=
. Dunno, does it even make sense to try to not pass the full commandline here? To answer "yes", we would need to be able to provide some comprehensive and consistent story what is allowed to be visible to ConditionKernelCommandLine=
and what is not. I doubt we can build such a story.
My instinct would be say that this is a bug in proc_cmdline_parse()
. Looking at various parse_proc_cmdline_item()
implementations, they generally only expect to be called on real /proc/cmdline
items, and would be confused when called over long-option-style arguments and values. E.g. basic/log.c
looks for a long debug
and if that debug would be passed as --log-level debug
it would be parsed unexpectedly there. So I think proc_cmdline_parse()
should be adjusted to drop all long and short dash-options with arguments that are consumed by pid1. But other users of proc_cmdline()
should get the full set and deal with it as appropriate.
I wrote some comments about the implementation before writing the big comment above… I'm leaving them in the review in case they would be still useful.
c031a62
to
0cf6f57
Compare
0cf6f57
to
6cee48b
Compare
6cee48b
to
65486c1
Compare
I'm not sure if #26963 is useful. I commented there. The later parts of this PR LGTM. But needs a rebase now. |
65486c1
to
96c199d
Compare
I dropped #26963. And, the proc_cmdline_get_key_many() is re-implemented in a different way. See the first commit of this PR. PTAL! |
…riend No functional change, just preparation for later commits.
When we are running in a container, we parse the command line of PID1 in proc_cmdline_parse() or friends. Previously, first we merge the command line nulstr as a single string, and then split by using extract_first_word(). That's not only redundant, but also unsafe when the command line argument contain a space. This drops the redundant steps, hence we can safely parse arguments with space.
Otherwise, if getopt() and friends are used before parse_argv(), then the GNU extensions may be ignored. This should not change any behavior at least now, as we usually use getopt_long() only once per invocation. But in the next commit, getopt_long() will be used for other arrays, hence this change will become necessary.
Otherwise, PID1 arguments e.g. "--deserialize 16" may be parsed unexpectedly by generators. Fixes the issue reported at systemd#24452 (comment).
96c199d
to
6339d3e
Compare
To make ConditionKernelCommandLine= or friend not confused when we are running in a container. Addresses systemd/systemd#26887 (comment). (cherry picked from commit d2ebd50)
To make ConditionKernelCommandLine= or friend not confused when we are running in a container. Addresses systemd/systemd#26887 (comment). (cherry picked from commit d2ebd50) (cherry picked from commit 0417b28) [The patch didn't apply cleanly. When fixing stuff, I left the array size as it was. The extra few bytes don't matter and this way it's unlikely to be wrong.]
To make ConditionKernelCommandLine= or friend not confused when we are running in a container. Addresses systemd/systemd#26887 (comment). (cherry picked from commit d2ebd50) (cherry picked from commit 0417b28) [The patch didn't apply cleanly. When fixing stuff, I left the array size as it was. The extra few bytes don't matter and this way it's unlikely to be wrong.] (cherry picked from commit a85ed9a)
LGTM. |
Otherwise, PID1 arguments e.g. "--deserialize 16" may be parsed unexpectedly by generators.
Fixes the issue reported at
#24452 (comment).