Skip to content

Commit 91672f9

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 <lars.erik.wik@northern.tech>
1 parent 5a17cc1 commit 91672f9

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed

cf-agent/verify_files.c

Lines changed: 146 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);
@@ -351,6 +352,83 @@ static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promi
351352
changes_path = chrooted_path;
352353
}
353354

355+
bool is_immutable = false;
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)
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,74 @@ static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promi
609687
}
610688

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

0 commit comments

Comments
 (0)