-
Notifications
You must be signed in to change notification settings - Fork 189
ENT-10961, CFE-1840: Files promise can now modify immutable bit in file system attributes #5752
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
Open
larsewi
wants to merge
38
commits into
cfengine:master
Choose a base branch
from
larsewi:override-immutable
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,952
−41
Open
Changes from all commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
d7e8ff3
Added utility functions to override immutable bit
larsewi 4ebc7b2
Added body syntax for controlling file system attributes
larsewi 5243590
Files promise can now modify immutable bit in file system attributes
larsewi 1e74204
Added argument to NOOP OverrideImmutable functions
larsewi c07955f
Combined OverrideImmutable[Commit|Abort] functions
larsewi d5ada41
Content attribute can now override immutable bit
larsewi c9ba31d
Store override_immutable variable in EvalContext
larsewi 0c53319
Added function to override immutable bit and rename file
larsewi 83e0ed8
copy_from attribute can now override immutable bit
larsewi b69401b
Added function to override immutable bit and delete file
larsewi f8db2b0
delete attribute can now override immutable bit
larsewi 1e6b326
edit_line and edit_xml attributes can now override immutable bit
larsewi d1f222a
override_fsattrs.c: refactored code
larsewi 2cf862f
Touch attribute can now override immutable bit
larsewi 048e9a6
Made functions for temporarily clear/reset immutable bit public
larsewi d5394a0
Transformer attribute can now override immutable bit
larsewi 81bc75e
OverrideImmutableRename() new file inherits immutable flag of old
larsewi 2db3cf9
Rename attribute can now override immutable bit
larsewi ec88ef0
Perms attribute can now override immutable bit
larsewi 1823cff
acl attribute can now override immutable bit
larsewi dab2d99
evalfunction.c: Removed trailing whitespace
larsewi 983faa4
Added policy function to get ACLs
larsewi 4b6c26e
Added acceptance test for getacls()
larsewi 4053710
Added acceptance test to set immutable bit
larsewi c99718d
Added acceptance test to clear immutable bit
larsewi 5b13fea
Added acceptance test for immutable with content
larsewi 841a313
Added acceptance test for immutable with copy_from
larsewi f75ea3b
Added acceptance test for immutable with delete
larsewi 8e85661
Added acceptance test for immutable with edit_line
larsewi 9f2b689
Added acceptance test for immutable with edit_xml
larsewi 23b6519
Added acceptance test for immutable with perms
larsewi 6b0b70d
Added acceptance test for immutable with touch
larsewi 587ed51
Added acceptance test for immutable with edit_template
larsewi 4369f2f
Added acceptance test for immutable with acl
larsewi 40a4547
Added acceptance test for immutable with transformer
larsewi b0ce49b
Added acceptance test for immutable with rename
larsewi c61fe03
Added context to log messages in OverrideImmutableCommit
larsewi 7dc51ff
Make it more clear what the override argument does
larsewi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -60,6 +60,8 @@ | |||||
#include <evalfunction.h> | ||||||
#include <changes_chroot.h> /* PrepareChangesChroot(), RecordFileChangedInChroot() */ | ||||||
#include <cf3.defs.h> | ||||||
#include <fsattrs.h> | ||||||
#include <override_fsattrs.h> | ||||||
|
||||||
static PromiseResult FindFilePromiserObjects(EvalContext *ctx, const Promise *pp); | ||||||
static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promise *pp); | ||||||
|
@@ -345,6 +347,67 @@ static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promi | |||||
changes_path = chrooted_path; | ||||||
} | ||||||
|
||||||
bool is_immutable = false; /* We assume not in case of failure */ | ||||||
FSAttrsResult res = FSAttrsGetImmutableFlag(changes_path, &is_immutable); | ||||||
if (res != FS_ATTRS_SUCCESS) | ||||||
{ | ||||||
Log((res == FS_ATTRS_FAILURE) ? LOG_LEVEL_ERR : LOG_LEVEL_VERBOSE, | ||||||
"Failed to get the state of the immutable bit from file '%s': %s", | ||||||
changes_path, FSAttrsErrorCodeToString(res)); | ||||||
} | ||||||
|
||||||
if (a.havefsattrs && a.fsattrs.haveimmutable && !a.fsattrs.immutable) | ||||||
{ | ||||||
/* Here we only handle the clearing of the immutable the immutable | ||||||
* bit. Later we'll handle the setting of the immutable bit. */ | ||||||
if (is_immutable) | ||||||
{ | ||||||
res = FSAttrsUpdateImmutableFlag(changes_path, false); | ||||||
switch (res) | ||||||
{ | ||||||
case FS_ATTRS_SUCCESS: | ||||||
RecordChange(ctx, pp, &a, | ||||||
"Cleared the immutable bit on file '%s'", | ||||||
changes_path); | ||||||
result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); | ||||||
break; | ||||||
case FS_ATTRS_FAILURE: | ||||||
RecordFailure(ctx, pp, &a, | ||||||
"Failed to clear the immutable bit on file '%s'", | ||||||
changes_path); | ||||||
result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); | ||||||
break; | ||||||
case FS_ATTRS_NOT_SUPPORTED: | ||||||
/* We will not treat this as a promise failure because this | ||||||
* will happen on many platforms and filesystems. Instead we | ||||||
* will log a verbose message to make it apparent for the | ||||||
* users. */ | ||||||
Log(LOG_LEVEL_VERBOSE, | ||||||
"Failed to clear the immutable bit on file '%s': %s", | ||||||
larsewi marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
changes_path, FSAttrsErrorCodeToString(res)); | ||||||
break; | ||||||
case FS_ATTRS_DOES_NOT_EXIST: | ||||||
/* File does not exist. Nothing to do really, but let's log a | ||||||
* debug message for good measures */ | ||||||
Log(LOG_LEVEL_DEBUG, | ||||||
"Failed to clear the immutable bit on file '%s': %s", | ||||||
larsewi marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
changes_path, FSAttrsErrorCodeToString(res)); | ||||||
break; | ||||||
} | ||||||
} | ||||||
else | ||||||
{ | ||||||
RecordNoChange(ctx, pp, &a, | ||||||
"The immutable bit is not set on file '%s' as promised", | ||||||
changes_path); | ||||||
} | ||||||
} | ||||||
|
||||||
/* If we encounter any promises to mutate the file and the immutable | ||||||
* attribute in body fsattrs is "true", we will override the immutable bit | ||||||
* by temporarily clearing it when ever needed. */ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
EvalContextOverrideImmutableSet(ctx, a.havefsattrs && a.fsattrs.haveimmutable && a.fsattrs.immutable && is_immutable); | ||||||
|
||||||
if (lstat(changes_path, &oslb) == -1) /* Careful if the object is a link */ | ||||||
{ | ||||||
if ((a.create) || (a.touch)) | ||||||
|
@@ -586,6 +649,51 @@ static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promi | |||||
} | ||||||
} | ||||||
|
||||||
if (a.havefsattrs && a.fsattrs.haveimmutable && a.fsattrs.immutable) | ||||||
{ | ||||||
/* Here we only handle the setting of the immutable bit. Previously we | ||||||
* handled the clearing of the immutable bit. */ | ||||||
if (is_immutable) | ||||||
{ | ||||||
RecordNoChange(ctx, pp, &a, | ||||||
"The immutable bit is already set on file '%s' as promised", | ||||||
changes_path); | ||||||
} | ||||||
else | ||||||
{ | ||||||
res = FSAttrsUpdateImmutableFlag(changes_path, true); | ||||||
switch (res) | ||||||
{ | ||||||
case FS_ATTRS_SUCCESS: | ||||||
Log(LOG_LEVEL_VERBOSE, "Set the immutable bit on file '%s'", | ||||||
changes_path); | ||||||
break; | ||||||
case FS_ATTRS_FAILURE: | ||||||
/* Things still may be fine as long as the agent does not try to mutate the file */ | ||||||
Log(LOG_LEVEL_VERBOSE, | ||||||
"Failed to set the immutable bit on file '%s': %s", | ||||||
changes_path, FSAttrsErrorCodeToString(res)); | ||||||
break; | ||||||
case FS_ATTRS_NOT_SUPPORTED: | ||||||
/* We will not treat this as a promise failure because this | ||||||
* will happen on many platforms and filesystems. Instead we | ||||||
* will log a verbose message to make it apparent for the | ||||||
* users. */ | ||||||
Log(LOG_LEVEL_VERBOSE, | ||||||
"Failed to set the immutable bit on file '%s': %s", | ||||||
changes_path, FSAttrsErrorCodeToString(res)); | ||||||
break; | ||||||
case FS_ATTRS_DOES_NOT_EXIST: | ||||||
/* File does not exist. Nothing to do really, but let's log a | ||||||
* debug message for good measures */ | ||||||
Log(LOG_LEVEL_DEBUG, | ||||||
"Failed to set the immutable bit on file '%s': %s", | ||||||
changes_path, FSAttrsErrorCodeToString(res)); | ||||||
break; | ||||||
larsewi marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
// Once more in case a file has been created as a result of editing or copying | ||||||
|
||||||
exists = (lstat(changes_path, &osb) != -1); | ||||||
|
@@ -603,6 +711,9 @@ static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promi | |||||
} | ||||||
|
||||||
exit: | ||||||
/* Reset this to false before next file promise */ | ||||||
EvalContextOverrideImmutableSet(ctx, false); | ||||||
|
||||||
free(chrooted_path); | ||||||
if (AttrHasNoAction(&a)) | ||||||
{ | ||||||
|
@@ -686,37 +797,53 @@ static PromiseResult WriteContentFromString(EvalContext *ctx, const char *path, | |||||
|
||||||
if (!HashesMatch(existing_content_digest, promised_content_digest, CF_DEFAULT_DIGEST)) | ||||||
{ | ||||||
bool override_immutable = EvalContextOverrideImmutableGet(ctx); | ||||||
if (!MakingChanges(ctx, pp, attr, &result, | ||||||
"update file '%s' with content '%s'", | ||||||
path, attr->content)) | ||||||
{ | ||||||
return result; | ||||||
} | ||||||
|
||||||
FILE *f = safe_fopen(changes_path, "w"); | ||||||
char override_path[PATH_MAX]; | ||||||
if (!OverrideImmutableBegin(changes_path, override_path, sizeof(override_path), override_immutable)) | ||||||
{ | ||||||
RecordFailure(ctx, pp, attr, "Failed to override immutable bit on file '%s'", changes_path); | ||||||
return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); | ||||||
} | ||||||
|
||||||
FILE *f = safe_fopen(override_path, "w"); | ||||||
if (f == NULL) | ||||||
{ | ||||||
RecordFailure(ctx, pp, attr, "Cannot open file '%s' for writing", path); | ||||||
OverrideImmutableCommit(changes_path, override_path, override_immutable, true); | ||||||
return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); | ||||||
} | ||||||
|
||||||
bool override_abort = false; | ||||||
Writer *w = FileWriter(f); | ||||||
if (WriterWriteLen(w, attr->content, bytes_to_write) == bytes_to_write ) | ||||||
{ | ||||||
RecordChange(ctx, pp, attr, | ||||||
"Updated file '%s' with content '%s'", | ||||||
path, attr->content); | ||||||
|
||||||
result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); | ||||||
} | ||||||
else | ||||||
{ | ||||||
RecordFailure(ctx, pp, attr, | ||||||
"Failed to update file '%s' with content '%s'", | ||||||
path, attr->content); | ||||||
override_abort = true; | ||||||
result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); | ||||||
} | ||||||
WriterClose(w); | ||||||
|
||||||
if (!OverrideImmutableCommit(changes_path, override_path, override_immutable, override_abort)) | ||||||
{ | ||||||
RecordFailure(ctx, pp, attr, "Failed to override immutable bit on file '%s'", changes_path); | ||||||
result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); | ||||||
} | ||||||
} | ||||||
|
||||||
return result; | ||||||
|
@@ -861,7 +988,7 @@ static PromiseResult RenderTemplateMustache(EvalContext *ctx, | |||||
edcontext->filename, message); | ||||||
result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); | ||||||
} | ||||||
else if (SaveAsFile(SaveBufferCallback, output_buffer, | ||||||
else if (SaveAsFile(ctx, SaveBufferCallback, output_buffer, | ||||||
edcontext->changes_filename, attr, | ||||||
edcontext->new_line_mode)) | ||||||
{ | ||||||
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.