-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
kernel: fix bug in cmdline setup #2716
kernel: fix bug in cmdline setup #2716
Conversation
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.
Looks good!
src/kernel/src/cmdline/mod.rs
Outdated
self.end_push(); | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Validates and inserts a string to the end of the current command line. | ||
/// Validates and inserts a string into the commandline. The position of the | ||
/// string depends on the presence of "--". |
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.
I would also specify here that string is inserted before --
, if present. It's not clear from the description.
9850bc4
to
c24f542
Compare
c24f542
to
4e6884c
Compare
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.
@luminitavoicu @serban300 take a look at this new version. Thanks!
@@ -102,7 +102,7 @@ impl BootConfig { | |||
Some(str) => str.as_str(), | |||
}; | |||
cmdline | |||
.insert_str(boot_args) | |||
.prepend_str(boot_args) |
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.
Nitish: We might get away with this because this step is peformed before adding the virtio devices. But in order to make absolutelty certain that everything is ok we would need to make sure that the boot_args
are actually appended and everything else is prepended. So do you think we should also have an append_str()
method ?
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.
The cmdline is empty when the boot args are "prepended". This is actualy a workaround to the fact the Cmdline does not have a way of getting initialized to a certain value.
However, I just gave it a second thought and it might be that the prepend method is not a very nice choice. Take a look at this:
firecracker/src/vmm/src/builder.rs
Line 849 in 200c2db
let flags = if locked.is_read_only() { "ro" } else { "rw" }; |
We are appending the ro/rw to the string specifying the root device. With the new prepend method, we would need to first create the entire string (i.e "root=/dev/vda ro/rw") and after that call into the
Cmdline
. IMO this makes things a little counterintuitive.So I am thinking of reverting to the previous
insert_str
version. WDYT?
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.
I see. There are other options. We can have 2 "regions" in the string:
- one for the firecracker custom args (virtio devices, etc) at the beginning
- one for the boot_args at the end
We can keep track of them by keeping the end index for each one. And have 2 groups of methods: - some that insert firecracker custom args. These would go in the first region.
- some that insert boot_args. These would go in the second region
Or there might be simpler methods to keep track of the regions. Or we can have 2 strings and concat them when as_string
is called. It shouldn't add a significant overhead.
What do you think ?
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.
In rust-vmm we already started adding helper methods on top of insert*
functions. For example, we have a function for add_virtio_mmio_device
.
Having a new function for insert_boot_args
sounds like a good idea to me, as it is inline with existing helpers. This would come with the advantage that the existing Cmdline
interface stays the same, so we do not introduce breaking changes for existing customers. With this, most of the changes will be in the implementation details of Cmdline
.
In the future we would like to look at other improvements to Cmdline
as well such as having it implemented with the builder pattern and allow even more custom/commonly used parameters as specified here: rust-vmm/linux-loader#25.
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.
Nice info! ok, so since the direction in which rust-vmm's linux-loader has already shifted in the same way we want to go with this PR, I will open a PR there, merge it there and then bring the changes here. Thanks @andreeaflorescu for the heads up
Since in #2470 we are preparing to consume the upstream linux-loader, should we fix this in upstream rust-vmm? LE: here is the cmdline functionality: https://github.com/rust-vmm/linux-loader/blob/main/src/cmdline/mod.rs |
I am thinking of fixing it in both repos in order to unblock things here. |
Nice, thanks for opening the issue in rust-vmm as well. I'll have a look at the PR as well in this case so we can keep both implementations aligned. |
4e6884c
to
b002c13
Compare
As per the latest comment in rust-vmm's linux-loader, we agreed that the cmdline implementation needs to be refactored in order to cleanly accommodate the changes required for this fix. As such we decided to implement a temporary fix in Firecracker. The fix was provided by @andreeaflorescu, thanks a lot for this! |
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.
Looks good, nice fix!
|
||
# We will override the init with /bin/cat so that we try to read the | ||
# Ubuntu version from the /etc/issue file. | ||
vm.basic_config( |
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.
Can we think of another test that doesn't involve the use of the serial device? With our future efforts to phase out the serial device, we will eventually have to refactor all tests using it, so it would be great if we could do this now instead of later.
Some examples I can think of are using touch
to create an empty file or starting a daemon process, then check for their existence using ssh.
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.
Ok, I will switch to using ssh.
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.
With our future efforts to phase out the serial device,
@georgepisaltu would you be so kind and point me to some discussion and rationale behind this decision if it's publicly available? I'm just curious what future holds for us.
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.
Removing the serial device is something that came up in team discussion as a way to simplify the device model. It is mainly a debugging tool and is not intended for production use-cases, as outlined in our prod-host-setup.md. Gives its relatively large attack surface and poor performance, there are other tools, such as ssh over the net device, to interact with the guest. Even if we remove the serial device as you see it now, the console functionality might be implemented in some other way (maybe through virtio-console).
This is just an idea for now. When making significant changes (e.g. removing the serial device) we will surely reach out to the community for input, as always. So far, we have not yet committed to this idea or scheduled any work in this space, but for the purposes of this PR, using ssh is just the better route regardless of what we decide on the serial device matter.
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.
@georgepisaltu init=
will execute the touch and then the vm will exit so I cannot use ssh to check for its existence. There may be some options to check the touch
succeeded but the serial one is the most clean one for the moment. Any other suggestions are welcome.
76fb208
to
e0b2e06
Compare
if let Some(init) = init_params { | ||
boot_cmdline.insert_str(format!("--{}", init))?; | ||
} | ||
|
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.
Do we need all the logic above (starting from split("--")
) ? Instead could we just do boot_cmdline.insert_str(boot_config.cmdline.as_str())?;
here ? This way, if the string provided by the user is correct, the part after --
should always be placed at the end of the kernel cmdline.
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.
Are you suggesting just creating an empty command line and just insert everything at the end? That could also work, and would simplify this code. We can have the split between init args and regular args just in linux loader.
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.
Yes, starting with an empty command line, adding the virtio devices and then adding boot_config.cmdline
at the end.
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.
Sounds good to me. @dianpopa what do you say?
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.
I am not necessarily a fan of adding the device related info at the start of the commandline just because it is not the usual practice to have them there. Also, I think we need to be consistent with what the commandline will look like when the fix is done in rust-vmm which I guess will not put them at the beginning... @serban300 what are your concerns with current solution? The doc explicitly mentions that the presence of a "--" will be used to specify init params.
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.
I don't have a concern, I just wanted to avoid complicating the code if possible. As long as there are no risks. Also this could eliminate the need for a rust-vmm fix. I'm not sure how much the order of the parameters matter though.
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.
Going back to what Diana said, I think it is better to not invest more time in this and merge it as is. In the end there's just a few lines of code, and it makes more sense to see the command line in dmesg in the order from this PR: first the parameters you set via boot_args
, then the virtio configuration that we are adding on top, and lastly the init.
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.
It's ok for me. I agree it's not a blocker.
e0b2e06
to
93f81c6
Compare
This split is needed because we're altering the kernel commandline passed by Firecracker customers to add virtio device configuration (on x86_64). The virtio config needs to be specified *before* the init. This is not the ideal implementation of the fix, as it would make more sense to have it in rust-vmm/linux-loader. Due to existing technical debt implementing it directly in upstream is not straightforward. See: rust-vmm/linux-loader#92. Fixes: firecracker-microvm#2709 Signed-off-by: Andreea Florescu <fandree@amazon.com>
Signed-off-by: Diana Popa <dpopa@amazon.com>
Signed-off-by: Diana Popa <dpopa@amazon.com>
2d90c69
to
0062f13
Compare
if let Some(init) = init_params { | ||
boot_cmdline.insert_str(format!("--{}", init))?; | ||
} | ||
|
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.
It's ok for me. I agree it's not a blocker.
Reason for This PR
Fixes #2709.
As per the documentation, everything that is
passed after "--" to the commandline is considered
an argument to init.
However, in Firecracker we are dynamically adjusting the
commandline by appending the virtio mmio devices and the
root device. As such, using "--" with Firecracker would result
in faulty behavior.
Description of Changes
[Author TODO: add description of changes.]
rust-vmm
.License Acceptance
By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache 2.0 license.
PR Checklist
[Author TODO: Meet these criteria.]
[Reviewer TODO: Verify that these criteria are met. Request changes if not]
git commit -s
).unsafe
code is properly documented.firecracker/swagger.yaml
.CHANGELOG.md
.