I am writing an answer even though it does not work... but it is probably the right approach and just some detail is wrong which someone might be able to point out.
I had a similar problem. I had to find the process which changed the content of a file (and I was the one who set immutable... ;-) ). This could be done with the audit system:
auditctl -a always,exit -w /root/audit_target -p w
This does have a performance impact, though, so be aware... You can have a look at the currently active audit rules with
start cmd:> auditctl -l
-a always,exit -F arch=b64 -S ioctl -F path=/root/audit_target
-w /root/audit_target -p w
Something like echo foo >/root/audit_target then creates (quite ugly) entries in /var/log/audit/audit.log
Unfortunately chattr does not. I have no idea why. Having a look at strace:
start cmd:> strace chattr +i audit_target
[...]
ioctl(3, FS_IOC_SETFLAGS, [FS_IMMUTABLE_FL|FS_EXTENT_FL]) = 0
[...]
So I assumed that
auditctl -a always,exit -F arch=b64 -S ioctl -F path=/root/audit_target
would catch this. For whatever reason it does not. Maybe someone can correct the call or explain why this might be impossible. Maybe because ioctl does not operate on a path but on a file descriptor? Not surprisingly
auditctl -a always,exit -F arch=b64 -S ioctl
is useless. Floods the log, seems not to provide any useful information.
OK, getting closer. Before the ioctl there must be an openat (or something similar). I thought this might just happen too often so that it would not be useful but immutable can only be set by root (or with the rrespective capability) and openat calls from UID 0 for this path might be rather rare. You could run lsattr every few seconds in order to find out when the change happened.
auditctl -a always,exit -F arch=b64 -S openat -F path=/root/audit_target -F uid=0
gets you a block on entries like these:
type=SYSCALL msg=audit(1737910040.670:669): arch=c000003e syscall=257 success=yes exit=3 a0=ffffff9c a1=7ffd677195d8 a2=20800 a3=0 items=1 ppid=1162 pid=2588 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts4 ses=1 comm="chattr" exe="/usr/bin/chattr" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)^]ARCH=x86_64 SYSCALL=openat AUID="root" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root"
type=CWD msg=audit(1737910040.670:669): cwd="/root"
type=PATH msg=audit(1737910040.670:669): item=0 name="audit_target" inode=18201 dev=fd:01 mode=0100640 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:admin_home_t:s0 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0^]OUID="root" OGID="root"
type=PROCTITLE msg=audit(1737910040.670:669): proctitle=636861747472002D690061756469745F746172676574
They tell you the PID of the process which caused this. The PID alone is useless for your search so you have to run the process accounting (start psacct.service) so that for every new process on the system the PID and binary path are logged. Maybe this can be limited to root processes.
chattr -R +iin cyberpanel source code