Discussion:
Auditing the "chattr" command (ioctl syscall?)
Max Williams
2011-08-24 13:57:13 UTC
Permalink
Hi,
I would like to be able to audit the syscalls that the chattr command uses but I'm not having much luck.
In an effort to see the syscalls used, I created a rule to log all syscalls, like this:
# auditctl -a exit,always -F path=/root/file

Then run this:
# chattr +i /root/file

This produces series of two syscalls in the logs, 6 (sys_newlstat) and 2 (sys_open):
node=localhost.localdomain type=SYSCALL msg=audit(1314189320.335:53158): arch=c000003e syscall=6 success=yes exit=0 a0=7ffff0f8886c a1=7ffff0f88250 a2=7ffff0f88250 a3=1 items=1 ppid=15560 pid=15745 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=1198 comm="chattr" exe="/usr/bin/chattr" key=(null)
node=localhost.localdomain type=SYSCALL msg=audit(1314189320.335:53160): arch=c000003e syscall=2 success=yes exit=3 a0=7ffff0f8886c a1=800 a2=7ffff0f88170 a3=1 items=1 ppid=15560 pid=15745 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=1198 comm="chattr" exe="/usr/bin/chattr" key=(null)

I don't think these are the syscalls I want to audit, they would be far too frequent. I also noticed when I run a strace on the chattr command it looks like it uses ioctl, eg:
ioctl(3, EXT2_IOC_SETFLAGS, 0x7fff0314cf3c)

What audit rule could I use to achieve this? Is it a combination of specifying syscall 6 or 2 with some of a0, a1 or a2? Or is this not possible?

I've tried auditing file attribute changes (auditctl -a exit,always -F arch=b64 -p a) but it does not work.

Many thanks,
Max Williams

________________________________________________________________________
In order to protect our email recipients, Betfair Group use SkyScan from
MessageLabs to scan all Incoming and Outgoing mail for viruses.

________________________________________________________________________
Steve Grubb
2011-08-24 14:40:32 UTC
Permalink
Post by Max Williams
Hi,
I would like to be able to audit the syscalls that the chattr command uses
but I'm not having much luck. In an effort to see the syscalls used, I
created a rule to log all syscalls, like this: # auditctl -a exit,always
-F path=/root/file
# chattr +i /root/file
This produces series of two syscalls in the logs, 6 (sys_newlstat) and 2
(sys_open): node=localhost.localdomain type=SYSCALL
msg=audit(1314189320.335:53158): arch=c000003e syscall=6 success=yes
exit=0 a0=7ffff0f8886c a1=7ffff0f88250 a2=7ffff0f88250 a3=1 items=1
ppid=15560 pid=15745 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0
sgid=0 fsgid=0 tty=pts0 ses=1198 comm="chattr" exe="/usr/bin/chattr"
key=(null) node=localhost.localdomain type=SYSCALL
msg=audit(1314189320.335:53160): arch=c000003e syscall=2 success=yes
exit=3 a0=7ffff0f8886c a1=800 a2=7ffff0f88170 a3=1 items=1 ppid=15560
pid=15745 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0
tty=pts0 ses=1198 comm="chattr" exe="/usr/bin/chattr" key=(null)
I don't think these are the syscalls I want to audit,
nope. You can use the autrace program also and get a strace like list of syscalls made
by the process.
Post by Max Williams
they would be far too
frequent. I also noticed when I run a strace on the chattr command it
looks like it uses ioctl, eg: ioctl(3, EXT2_IOC_SETFLAGS, 0x7fff0314cf3c)
What audit rule could I use to achieve this?
It starts off like this:

-a always,exit -F arch=b64 -S ioctl

Then you need to look at the man page for ioctl. The first argument is the FD, so you
will not have a a0 since that could be different from program to program. Then you
need to look in the header files for the definition of EXT2_IOC_SETFLAGS.

/usr/include/linux/ext2_fs.h
#define EXT2_IOC_SETFLAGS FS_IOC_SETFLAGS

/usr/include/linux/fs.h
#define FS_IOC_SETFLAGS _IOW('f', 2, long)

/usr/include/asm-generic/ioctl.h
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOC(dir,type,nr,size) \
(((dir) << _IOC_DIRSHIFT) | \
((type) << _IOC_TYPESHIFT) | \
((nr) << _IOC_NRSHIFT) | \
((size) << _IOC_SIZESHIFT))
# define _IOC_WRITE 1U

Looks hard to figure out? Let's make a program:

#include <stdio.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>

int main(void)
{
printf("%0lX\n", EXT2_IOC_SETFLAGS);
return 0;
}

It returns this: 40086602

So, the rule is:

-a always,exit -F arch=b64 -S ioctl -F a1=40086602

I don't know if the syscall requires more arguments. You would have to look at the
chattr program for more. Also note that you might want a matching b32 rule also. If
you wanted to limit this to a file, then put a -F path= on that also. Adding a key field
helps in searching later.

-Steve
Max Williams
2011-08-24 15:31:10 UTC
Permalink
Hi Steve,
Thanks for the informative reply. I hadn't used autrace before, looks very handy.
I am wondering why this rule would log chattr...
-a always,exit -F arch=b64 -S ioctl -F a1=40086602 -F path=/root/file

...but not this one?
-a exit,always -F path=/root/file

In the second rule, is it not implied that all syscalls would be logged? Wouldn't that include ioctl?

I still can't get auditd to log chattr, I'll show you:

[***@localhost ~]# auditctl -D
No rules
[***@localhost ~]# autrace /usr/bin/chattr +i file
Waiting to execute: /usr/bin/chattr
Cleaning up...
Trace complete. You can locate the records with 'ausearch -i -p 16312'
[***@localhost ~]#
[***@localhost ~]# ausearch -i -p 16312 | grep ioctl
node=localhost.localdomain type=SYSCALL msg=audit(08/24/2011 15:10:29.752:54096) : arch=x86_64 syscall=ioctl success=yes exit=0 a0=3 a1=80086601 a2=7fff1271bf9c a3=1 items=0 ppid=16310 pid=16312 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=pts0 ses=1198 comm=chattr exe=/usr/bin/chattr key=(null)
node=localhost.localdomain type=SYSCALL msg=audit(08/24/2011 15:10:29.752:54100) : arch=x86_64 syscall=ioctl success=yes exit=0 a0=3 a1=40086602 a2=7fff1271bf9c a3=0 items=0 ppid=16310 pid=16312 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=pts0 ses=1198 comm=chattr exe=/usr/bin/chattr key=(null)
[***@localhost ~]#
[***@localhost ~]# auditctl -a exit,always -F arch=b64 -S ioctl -F a1=40086602 -k chattr1
[***@localhost ~]# auditctl -a exit,always -F arch=b64 -S ioctl -F a1=80086601 -k chattr2
[***@localhost ~]#
[***@localhost ~]# chattr +i file
[***@localhost ~]# chattr -i file
[***@localhost ~]#
[***@localhost ~]# tail -4 /var/log/audit/audit.log
node=localhost.localdomain type=CONFIG_CHANGE msg=audit(1314195029.752:54103): auid=0 ses=1198 op="remove rule" key=(null) list=4 res=1
node=localhost.localdomain type=CONFIG_CHANGE msg=audit(1314195029.752:54104): auid=0 ses=1198 op="remove rule" key=(null) list=4 res=1
node=localhost.localdomain type=CONFIG_CHANGE msg=audit(1314195046.666:54105): auid=0 ses=1198 op="add rule" key="chattr1" list=4 res=1
node=localhost.localdomain type=CONFIG_CHANGE msg=audit(1314195054.962:54106): auid=0 ses=1198 op="add rule" key="chattr2" list=4 res=1
[***@localhost ~]#

So it just doesn't log anything after adding the two rules.

I also tried just auditing all ioctl syscalls for a path:
[***@localhost ~]# auditctl -D
No rules
[***@localhost ~]# auditctl -a exit,always -F arch=b64 -S ioctl -F path=/root/temp -k chattr3
[***@localhost ~]# chattr +i /root/temp/file

But still no dice. This is on a standard x86_64 RHEL6 host with audit-2.0.4-1.el6.x86_64.
Am I missing something obvious?
Thanks,
Max

-----Original Message-----
From: Steve Grubb [mailto:***@redhat.com]
Sent: 24 August 2011 15:41
To: linux-***@redhat.com
Cc: Max Williams
Subject: Re: Auditing the "chattr" command (ioctl syscall?)
Post by Max Williams
Hi,
I would like to be able to audit the syscalls that the chattr command
uses but I'm not having much luck. In an effort to see the syscalls
used, I created a rule to log all syscalls, like this: # auditctl -a
exit,always -F path=/root/file
# chattr +i /root/file
This produces series of two syscalls in the logs, 6 (sys_newlstat) and 2
(sys_open): node=localhost.localdomain type=SYSCALL
msg=audit(1314189320.335:53158): arch=c000003e syscall=6 success=yes
exit=0 a0=7ffff0f8886c a1=7ffff0f88250 a2=7ffff0f88250 a3=1 items=1
ppid=15560 pid=15745 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0
sgid=0 fsgid=0 tty=pts0 ses=1198 comm="chattr" exe="/usr/bin/chattr"
key=(null) node=localhost.localdomain type=SYSCALL
msg=audit(1314189320.335:53160): arch=c000003e syscall=2 success=yes
exit=3 a0=7ffff0f8886c a1=800 a2=7ffff0f88170 a3=1 items=1 ppid=15560
pid=15745 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0
tty=pts0 ses=1198 comm="chattr" exe="/usr/bin/chattr" key=(null)
I don't think these are the syscalls I want to audit,
nope. You can use the autrace program also and get a strace like list of syscalls made by the process.
Post by Max Williams
they would be far too
frequent. I also noticed when I run a strace on the chattr command it
looks like it uses ioctl, eg: ioctl(3, EXT2_IOC_SETFLAGS,
0x7fff0314cf3c)
What audit rule could I use to achieve this?
It starts off like this:

-a always,exit -F arch=b64 -S ioctl

Then you need to look at the man page for ioctl. The first argument is the FD, so you will not have a a0 since that could be different from program to program. Then you need to look in the header files for the definition of EXT2_IOC_SETFLAGS.

/usr/include/linux/ext2_fs.h
#define EXT2_IOC_SETFLAGS FS_IOC_SETFLAGS

/usr/include/linux/fs.h
#define FS_IOC_SETFLAGS _IOW('f', 2, long)

/usr/include/asm-generic/ioctl.h
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOC(dir,type,nr,size) \
(((dir) << _IOC_DIRSHIFT) | \
((type) << _IOC_TYPESHIFT) | \
((nr) << _IOC_NRSHIFT) | \
((size) << _IOC_SIZESHIFT))
# define _IOC_WRITE 1U

Looks hard to figure out? Let's make a program:

#include <stdio.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>

int main(void)
{
printf("%0lX\n", EXT2_IOC_SETFLAGS);
return 0;
}

It returns this: 40086602

So, the rule is:

-a always,exit -F arch=b64 -S ioctl -F a1=40086602

I don't know if the syscall requires more arguments. You would have to look at the chattr program for more. Also note that you might want a matching b32 rule also. If you wanted to limit this to a file, then put a -F path= on that also. Adding a key field helps in searching later.

-Steve

________________________________________________________________________
In order to protect our email recipients, Betfair Group use SkyScan from
MessageLabs to scan all Incoming and Outgoing mail for viruses.

________________________________________________________________________
Steve Grubb
2011-08-24 15:50:23 UTC
Permalink
Post by Max Williams
Thanks for the informative reply. I hadn't used autrace before, looks very
handy. I am wondering why this rule would log chattr...
-a always,exit -F arch=b64 -S ioctl -F a1=40086602 -F path=/root/file
...but not this one?
-a exit,always -F path=/root/file
When you do not give a syscall and its a path or directory based rule, it selects the
syscalls for you based on what kind of permissions are passed. No permissions being
passed defaults to all. The resulting list will not include an ioctl.
Post by Max Williams
In the second rule, is it not implied that all syscalls would be logged?
Wouldn't that include ioctl?
No. You could add -S all and then it would.
Post by Max Williams
No rules
But still no dice. This is on a standard x86_64 RHEL6 host with
audit-2.0.4-1.el6.x86_64. Am I missing something obvious?
Then I guess you cannot limit the auditing to a file. The ioctl is passed a fd, which
is an integer. The audit system does not keep any list of associated fd to name
mappings. So, the only time it knows the string is during the open syscall. I guess
you'll have to drop the -F path=/root/temp/file and you will get the chattr, but you
will get all chattr events. I don't think there are too many of those going on for a
normal system.

-Steve
Steve Grubb
2011-08-24 15:53:15 UTC
Permalink
Post by Steve Grubb
-a always,exit -F arch=b64 -S ioctl -F a1=40086602
One correction, you need a 0x in that:

-a always,exit -F arch=b64 -S ioctl -F a1=0x40086602

-Steve
Max Williams
2011-08-24 16:04:39 UTC
Permalink
Ah, the 0x was it! It was producing the wrong rule:

Wrong: LIST_RULES: exit,always arch=3221225534 (0xc000003e) a1=40086602 (0x263ac4a) key=chattr1 syscall=ioctl

Right: LIST_RULES: exit,always arch=3221225534 (0xc000003e) a1=1074292226 (0x40086602) key=chattr3 syscall=ioctl


You are right, if I specify a path for this rule, it stops working.

Thank you very much for your help Steve.

Cheers,
Max


-----Original Message-----
From: linux-audit-***@redhat.com [mailto:linux-audit-***@redhat.com] On Behalf Of Steve Grubb
Sent: 24 August 2011 16:53
To: linux-***@redhat.com
Subject: Re: Auditing the "chattr" command (ioctl syscall?)
Post by Steve Grubb
-a always,exit -F arch=b64 -S ioctl -F a1=40086602
One correction, you need a 0x in that:

-a always,exit -F arch=b64 -S ioctl -F a1=0x40086602

-Steve

--
Linux-audit mailing list
Linux-***@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit

________________________________________________________________________
In order to protect our email recipients, Betfair Group use SkyScan from
MessageLabs to scan all Incoming and Outgoing mail for viruses.

________________________________________________________________________
Loading...