-
Notifications
You must be signed in to change notification settings - Fork 58
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
Drop privileges after startup #364
Conversation
9f89234
to
df2b275
Compare
0c9168f
to
1e32557
Compare
let mut fixture = QuoteData::fixture().unwrap(); //#[allow_ci] | ||
|
||
// Create temporary working directory and secure mount | ||
let temp_workdir = tempfile::tempdir().unwrap(); //#[allow_ci] | ||
fixture.secure_mount = | ||
PathBuf::from(&temp_workdir.path().join("tmpfs-dev")); | ||
fs::create_dir(&fixture.secure_mount).unwrap(); //#[allow_ci] |
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 added this because when the secure mount path is passed directly to run_encrypted_payload()
, the directory is expect to exist (since the secure mount should be ready from the beginning).
In the previous implementation the secure_mount
would be created by secure_mount::mount()
. It took me some time to understand what was happening to make the test to fail.
src/ima.rs
Outdated
@@ -57,14 +58,16 @@ impl ImaMeasurementList { | |||
/// was read and the current number of entries in the file. | |||
pub(crate) fn read_measurement_list( | |||
ima_ml: &mut ImaMeasurementList, | |||
filename: &Path, | |||
ima_file: &Option<Arc<Mutex<File>>>, |
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.
Could you explain why Mutex
is necessary here? Is it possible that the file is accessed from multiple threads?
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 case multiple requests for quotes are received in parallel the file would be needed in multiple threads, wouldn't it?
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.
Yeah, I understand that, but in that case I wonder if it might make more sense to handle locking in quotes_handler.rs
(and if it's not feasible at least have some comment in ima.rs
why this interface involves locking)?
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.
Yeah, I understand that, but in that case I wonder if it might make more sense to handle locking in
quotes_handler.rs
(and if it's not feasible at least have some comment inima.rs
why this interface involves locking)?
I have to take some time and think if there is a better way and if your suggestion is feasible. Right now I can't see another way to open a file before dropping the privileges and later share the handle in multiple threads without using a mutex on the handle. That would be possible if I can clone the handle in each thread and operate on them independently. The content of the file is accessed only for reading, but the handle is modified by seek operations. I need to test 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.
Right now I can't see another way to open a file before dropping the privileges and later share the handle in multiple threads without using a mutex on the handle.
I'm not saying that using a mutex is a problem, but suggest calling .lock()
in integrity
(in quotes_handler.rs) rather than read_measurement_list
(in ima.rs). The lock for the other argument (ima_ml
) is already implemented that way.
Here is my attempt (totally untested).
That would be possible if I can clone the handle in each thread and operate on them independently.
I am not sure why this mechanism is necessary. Maybe I am missing something but afaics the only code path that could access the file object is integrity
→ read_measurement_list
, which is even protected by ima_ml.lock()
so there is only one thread that could take this path.
The content of the file is accessed only for reading, but the handle is modified by seek operations.
That makes me think that the handle could be generalized as Read + Seek
, but maybe overkill :-)
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 think I understand now what you were asking. I'll try you approach and move the .lock()
.
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.
Modified as suggested. I followed the same approach for the measured boot log file.
dist/systemd/system/installer.sh
Outdated
# prepare keylime service files and store them in systemd path | ||
sed "s|KEYLIMEDIR|$KEYLIMEDIR|g" $BASEDIR/keylime_agent.service.template > /etc/systemd/system/keylime_agent.service | ||
|
||
# Copy secure mount |
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.
Why not extend the existing GNUmakefile and use install
rather than manual calls to chmod
and chown
?
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.
Because I did it without thinking much :)
I will make the changes in the Makefile.
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.
Removed the installer script completely and added minimal changes to the GNUmakefile
.
d6f2ddf
to
2da579c
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.
Thanks for the update; looks much simpler.
@@ -57,25 +58,18 @@ impl ImaMeasurementList { | |||
/// was read and the current number of entries in the file. | |||
pub(crate) fn read_measurement_list( |
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 tend to think we could make this function as a method of ImaMeasurementList
, but it could be a future refactoring.
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 agree, I'll make the change in a separate PR.
Open files that require root privilege in the beginning of the startup process and pass the handles down instead of using the file paths. This is a preparation for dropping the privileges after opening the files. Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
Add support for the 'run_as' configuration option in 'cloud_agent' section. After executing the operation that require privilege, drop the privileges and run as the user set by the 'run_as' option. Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
This is to allow the agent to use files possibly created by privileged processes. Otherwise the agent will try to set the file ownership and fail. Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
Follow the python implementation and parse the /proc/self/mountinfo content instead of parsing the mount command output. Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
This also updates the agent service to add the secure mount service as a requirement and to enable logging through service environment variable. Fixes keylime#344 Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
The shim.py is used to run python revocation action scripts loaded as modules. This is for backward compatibility with the python agent implementation. Support for python revocation scripts was introduced in 73773e6 Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
@ansasaki can we merge this, or do you plan any further update? |
I think we can merge, I don't plan to add more changes here. |
After finishing operations that require privileges, drop the privileges to run as a normal user.
This adds support to the
run_as
configuration option to select theuser:group
under which the keylime agent will run.This also rewrites
check_mount()
to use the information from/proc/self/mountinfo
instead of the mount output file to check ifsecure
is mounted. The implementation was based on python agent.Fixes: #343, #317, #344