-
Notifications
You must be signed in to change notification settings - Fork 188
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
Closed
Closed
Changes from 1 commit
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
#include <override_fsattrs.h> | ||
#include <platform.h> | ||
#include <fsattrs.h> | ||
#include <logging.h> | ||
#include <stdlib.h> | ||
#include <files_copy.h> | ||
#include <cf3.defs.h> | ||
#include <string_lib.h> | ||
|
||
bool OverrideImmutableBegin(const char *orig, char *copy, size_t copy_len) | ||
{ | ||
srand(time(NULL)); /* Seed random number generator */ | ||
int rand_number = rand() % 999999; | ||
assert(rand_number >= 0); | ||
|
||
/* Inspired by mkstemp(3) */ | ||
int ret = snprintf(copy, copy_len, "%s.%06d" CF_NEW, orig, rand_number); | ||
if (ret < 0 || (size_t) ret >= copy_len) | ||
{ | ||
Log(LOG_LEVEL_ERR, | ||
"Failed to generate name for temporary copy of '%s': Filename is too long (%d >= %zu)", | ||
orig, | ||
ret, | ||
copy_len); | ||
return false; | ||
} | ||
|
||
/* We'll match the original file permissions on commit */ | ||
if (!CopyRegularFileDiskPerms(orig, copy, 0600)) | ||
{ | ||
Log(LOG_LEVEL_ERR, | ||
"Failed to copy file '%s' to temporary file '%s'", | ||
orig, | ||
copy); | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
bool OverrideImmutableCommit(const char *orig, const char *copy) | ||
{ | ||
struct stat sb; | ||
if (lstat(orig, &sb) == -1) | ||
{ | ||
Log(LOG_LEVEL_ERR, "Failed to stat file '%s'", orig); | ||
larsewi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
unlink(copy); | ||
return false; | ||
} | ||
|
||
if (chmod(copy, sb.st_mode) == -1) | ||
{ | ||
Log(LOG_LEVEL_ERR, | ||
"Failed to change mode bits on file '%s' to %04jo: %s", | ||
larsewi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
orig, | ||
(uintmax_t) sb.st_mode, | ||
GetErrorStr()); | ||
unlink(copy); | ||
return false; | ||
} | ||
|
||
/* If the operations on the file system attributes fails for any reason, | ||
* we can still proceed to try to replace the original file. We will only | ||
* log an actual error in case of an unexpected failure (i.e., when | ||
* FS_ATTRS_FAILURE is returned). Other failures will be logged as verbose | ||
* messages because they can be useful, but are be quite verbose. */ | ||
larsewi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
bool is_immutable; | ||
FSAttrsResult res = FSAttrsGetImmutableFlag(orig, &is_immutable); | ||
if (res == FS_ATTRS_SUCCESS) | ||
{ | ||
if (is_immutable) | ||
{ | ||
res = FSAttrsUpdateImmutableFlag(orig, false); | ||
if (res == FS_ATTRS_SUCCESS) | ||
{ | ||
Log(LOG_LEVEL_VERBOSE, | ||
"Temporarily cleared immutable bit for file '%s'", | ||
orig); | ||
} | ||
else | ||
{ | ||
Log((res == FS_ATTRS_FAILURE) ? LOG_LEVEL_ERR | ||
: LOG_LEVEL_VERBOSE, | ||
"Failed to temporarily clear immutable bit for file '%s': %s", | ||
orig, | ||
FSAttrsErrorCodeToString(res)); | ||
} | ||
} | ||
else | ||
{ | ||
Log(LOG_LEVEL_DEBUG, | ||
"The immutable bit is not set on file '%s'", | ||
orig); | ||
} | ||
} | ||
else | ||
{ | ||
Log((res == FS_ATTRS_FAILURE) ? LOG_LEVEL_ERR : LOG_LEVEL_VERBOSE, | ||
"Failed to get immutable bit from file '%s': %s", | ||
orig, | ||
FSAttrsErrorCodeToString(res)); | ||
} | ||
|
||
if (rename(copy, orig) == -1) | ||
|
||
{ | ||
Log(LOG_LEVEL_ERR, | ||
"Failed to replace original file '%s' with copy '%s'", | ||
larsewi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
orig, | ||
copy); | ||
unlink(copy); | ||
return false; | ||
} | ||
|
||
if ((res == FS_ATTRS_SUCCESS) && is_immutable) | ||
{ | ||
res = FSAttrsUpdateImmutableFlag(orig, true); | ||
if (res == FS_ATTRS_SUCCESS) | ||
{ | ||
Log(LOG_LEVEL_VERBOSE, | ||
"Reset immutable bit after temporarily clearing it from file '%s'", | ||
orig); | ||
} | ||
else | ||
{ | ||
Log((res == FS_ATTRS_FAILURE) ? LOG_LEVEL_ERR : LOG_LEVEL_VERBOSE, | ||
"Failed to reset immutable bit after temporarily clearing it from file '%s': %s", | ||
orig, | ||
FSAttrsErrorCodeToString(res)); | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
bool OverrideImmutableAbort(ARG_UNUSED const char *orig, const char *copy) | ||
{ | ||
assert(copy != NULL); | ||
return unlink(copy) == 0; | ||
} |
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 |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
Copyright 2025 Northern.tech AS | ||
|
||
This file is part of CFEngine 3 - written and maintained by Northern.tech AS. | ||
|
||
This program is free software; you can redistribute it and/or modify it | ||
under the terms of the GNU General Public License as published by the | ||
Free Software Foundation; version 3. | ||
|
||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
|
||
You should have received a copy of the GNU General Public License | ||
along with this program; if not, write to the Free Software | ||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
|
||
To the extent this program is licensed as part of the Enterprise | ||
versions of CFEngine, the applicable Commercial Open Source License | ||
(COSL) may apply to this file if you as a licensee so wish it. See | ||
included file COSL.txt. | ||
*/ | ||
|
||
#ifndef CFENGINE_OVERRIDE_FSATTRS_H | ||
#define CFENGINE_OVERRIDE_FSATTRS_H | ||
|
||
#include <stdbool.h> | ||
#include <stddef.h> | ||
|
||
/** | ||
* @brief Creates a mutable copy of the original file | ||
* @param orig The original file (may be immutable) | ||
* @param copy Updated to contain the filename of the mutable copy | ||
* @param copy_len The size of the buffer to store the filename of the copy | ||
* @return false in case of failure | ||
*/ | ||
bool OverrideImmutableBegin(const char *orig, char *copy, size_t copy_len); | ||
|
||
/** | ||
* @brief Temporarily clears the immutable bit of the original file and | ||
* replaces it with the mutated copy | ||
* @param orig The original file (may be immutable) | ||
* @param copy The mutated copy to replace the original | ||
* @return false in case of failure | ||
* @note The immutable bit is reset to it's original state | ||
*/ | ||
bool OverrideImmutableCommit(const char *orig, const char *copy); | ||
craigcomstock marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** | ||
* @brief Simply unlinks the mutable copy | ||
* @param orig Not used (reserved in for future use) | ||
* @param copy The mutated copy to unlink | ||
* @return false in case of failure (but you probably don't care) | ||
*/ | ||
bool OverrideImmutableAbort(const char *orig, const char *copy); | ||
|
||
#endif /* CFENGINE_OVERRIDE_FSATTRS_H */ |
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.
I think you should change the orig file to immutable just before this copy. Not 100% atomic but pretty close so that between this Begin() and the Commit() no one else can "easily" modify the file without also modifying the immutable bit of course.
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.
Not sure if this is a good idea. Let's discuss in digital F2F format :)