Skip to content

Commit ac115ad

Browse files
committed
Files promise can now modify immutable bit in file system attributes
Ticket: ENT-10961, CFE-1840 Changelog: Title Signed-off-by: Lars Erik Wik <[email protected]>
1 parent 5286027 commit ac115ad

File tree

1 file changed

+148
-0
lines changed

1 file changed

+148
-0
lines changed

cf-agent/verify_files.c

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
#include <known_dirs.h>
6060
#include <evalfunction.h>
6161
#include <changes_chroot.h> /* PrepareChangesChroot(), RecordFileChangedInChroot() */
62+
#include <fsattrs.h>
6263

6364
static PromiseResult FindFilePromiserObjects(EvalContext *ctx, const Promise *pp);
6465
static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promise *pp);
@@ -303,6 +304,7 @@ static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promi
303304
CfLock thislock;
304305
int exists;
305306
bool link = false;
307+
bool is_immutable = false;
306308

307309
Attributes attr = GetFilesAttributes(ctx, pp);
308310

@@ -351,6 +353,82 @@ static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promi
351353
changes_path = chrooted_path;
352354
}
353355

356+
FSAttrsResult res = FileGetImmutableFlag(path, &is_immutable);
357+
switch (res)
358+
{
359+
case FS_ATTRS_SUCCESS:
360+
/* Nothing more to do */
361+
break;
362+
case FS_ATTRS_FAILURE:
363+
Log(LOG_LEVEL_VERBOSE, "Failed to get immutable bit for file '%s': %s", changes_path, GetErrorStr());
364+
break;
365+
case FS_ATTRS_NOTSUPP:
366+
Log(LOG_LEVEL_VERBOSE, "Failed to get immutable bit for file '%s': Operation not supported", changes_path);
367+
break;
368+
case FS_ATTRS_NOENTRY:
369+
/* The file does not exist. Nothing more to do */
370+
break;
371+
}
372+
373+
if (a.havefsattrs && a.fsattrs.haveimmutable)
374+
{
375+
if (a.fsattrs.immutable) /* file should be immutable */
376+
{
377+
if (is_immutable) /* file is already immutable */
378+
{
379+
/* Temporarily remove the immutable flag */
380+
res = FileUpdateImmutableFlag(changes_path, false);
381+
switch (res)
382+
{
383+
case FS_ATTRS_SUCCESS:
384+
Log(LOG_LEVEL_VERBOSE, "Temporarily cleared immutable bit for file '%s'", changes_path);
385+
break;
386+
case FS_ATTRS_FAILURE:
387+
/* Things still may be fine as long as the agent does not try to mutate the file */
388+
Log(LOG_LEVEL_VERBOSE, "Failed to temporarily clear immutable bit for file '%s': %s", changes_path, GetErrorStr());
389+
break;
390+
case FS_ATTRS_NOTSUPP:
391+
/* Things still may be fine as long as the agent does not try to mutate the file */
392+
Log(LOG_LEVEL_VERBOSE, "Failed to temporarily clear immutable bit for file '%s': Operation not supported", changes_path);
393+
break;
394+
case FS_ATTRS_NOENTRY:
395+
/* The file does not exist. Nothing more to do */
396+
break;
397+
}
398+
} /* else then file is not immutable, but we will fix that later */
399+
}
400+
else /* file should not be immutable */
401+
{
402+
if (is_immutable) /* file is immutable */
403+
{
404+
/* Remove immutable flag for good */
405+
res = FileUpdateImmutableFlag(changes_path, false);
406+
switch (res)
407+
{
408+
case FS_ATTRS_SUCCESS:
409+
RecordChange(ctx, pp, &a, "Cleared immutable bit for file '%s'", changes_path);
410+
result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE);
411+
break;
412+
case FS_ATTRS_FAILURE:
413+
RecordFailure(ctx, pp, &a, "Failed to clear immutable bit for file '%s'", changes_path);
414+
result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
415+
break;
416+
case FS_ATTRS_NOTSUPP:
417+
/* We will not treat this as a promise failure because this will happen on many platforms. Instead we will log a verbose message. */
418+
Log(LOG_LEVEL_VERBOSE, "Failed to temporarily clear immutable bit for file '%s': Operation not supported", changes_path);
419+
break;
420+
case FS_ATTRS_NOENTRY:
421+
/* Nothing to do */
422+
break;
423+
}
424+
}
425+
else /* file is not immutable */
426+
{
427+
RecordNoChange(ctx, pp, &a, "Immutable bit is not set for file '%s' as promised", changes_path);
428+
}
429+
}
430+
}
431+
354432
if (lstat(changes_path, &oslb) == -1) /* Careful if the object is a link */
355433
{
356434
if ((a.create) || (a.touch))
@@ -609,6 +687,76 @@ static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promi
609687
}
610688

611689
exit:
690+
; /* A label can only be part of a statement and a declaration is not a
691+
* statement. This is a quirk of standard C grammar. Hence, we put an
692+
* empty statement here. */
693+
bool was_immutable = is_immutable;
694+
is_immutable = false;
695+
res = FileGetImmutableFlag(path, &is_immutable);
696+
switch (res)
697+
{
698+
case FS_ATTRS_SUCCESS:
699+
/* Nothing to do */
700+
break;
701+
case FS_ATTRS_FAILURE:
702+
Log(LOG_LEVEL_VERBOSE, "Failed to get immutable bit for file '%s': %s", changes_path, GetErrorStr());
703+
break;
704+
case FS_ATTRS_NOTSUPP:
705+
Log(LOG_LEVEL_VERBOSE, "Failed to get immutable bit for file '%s': Operation not supported", changes_path);
706+
break;
707+
case FS_ATTRS_NOENTRY:
708+
/* Nothing to do */
709+
break;
710+
}
711+
712+
if (a.havefsattrs && a.fsattrs.haveimmutable && a.fsattrs.immutable) {
713+
if (was_immutable && !is_immutable)
714+
{
715+
/* Reset immutable flag that we cleared before */
716+
res = FileUpdateImmutableFlag(changes_path, true);
717+
switch (res)
718+
{
719+
case FS_ATTRS_SUCCESS:
720+
Log(LOG_LEVEL_VERBOSE, "Reset immutable bit for file '%s' after temporarily clearing it", changes_path);
721+
break;
722+
case FS_ATTRS_FAILURE:
723+
/* Things still may be fine as long as the agent does not try to mutate the file */
724+
Log(LOG_LEVEL_VERBOSE, "Failed to reset immutable bit for file '%s' after temporarily clearing it: %s", changes_path, GetErrorStr());
725+
break;
726+
case FS_ATTRS_NOTSUPP:
727+
/* Things still may be fine as long as the agent does not try to mutate the file */
728+
Log(LOG_LEVEL_VERBOSE, "Failed to reset immutable bit for file '%s' after temporarily clearing it: Operation not supported", changes_path);
729+
break;
730+
case FS_ATTRS_NOENTRY:
731+
/* The file must have been removed by the agent. Nothing more to do */
732+
break;
733+
}
734+
}
735+
else
736+
{
737+
/* The file was never immutable, but should be. We'll fix that now */
738+
res = FileUpdateImmutableFlag(changes_path, true);
739+
switch (res)
740+
{
741+
case FS_ATTRS_SUCCESS:
742+
RecordChange(ctx, pp, &a, "Set immutable bit for file '%s'", changes_path);
743+
result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE);
744+
break;
745+
case FS_ATTRS_FAILURE:
746+
RecordFailure(ctx, pp, &a, "Failed to set immutable bit for file '%s'", changes_path);
747+
result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
748+
break;
749+
case FS_ATTRS_NOTSUPP:
750+
/* We will not treat this as a promise failure because this will happen on many platforms. Instead we will log a verbose message. */
751+
Log(LOG_LEVEL_VERBOSE, "Failed set immutable bit for file '%s': Operation not supported", changes_path);
752+
break;
753+
case FS_ATTRS_NOENTRY:
754+
/* The file must have been removed by the agent. Nothing more to do */
755+
break;
756+
}
757+
}
758+
}
759+
612760
free(chrooted_path);
613761
if (AttrHasNoAction(&a))
614762
{

0 commit comments

Comments
 (0)