* [PATCH] fix broken class-based syscall audit
@ 2007-05-14 15:46 Klaus Weidner
2007-05-14 15:51 ` Marcus Meissner
0 siblings, 1 reply; 6+ messages in thread
From: Klaus Weidner @ 2007-05-14 15:46 UTC (permalink / raw)
To: linux-audit
Bug description: When I add an audit watch on a file with no arguments, I
get perm=rwxa but on ia64, changes to the mode and context aren't
audited. I get audit records on i386 and x86_64.
See also: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=239887
The sanity check in audit_match_class() is wrong, AUDIT_BITMASK_SIZE is
64, providing space for 2048 syscalls in 64 * 32bit integers. The
comparison only supports 256 syscalls (sizeof __u32 is 4), and silently
returns "no match" for valid higher-numbered syscalls.
This breaks class-based audit for all syscalls on ia64 since on that
architecture syscall numbers start at 1024. It breaks some syscall audit
on other architectures also, for example __NR_fchmodat is 306 on x86.
I'd suggest adding a printk() in addition to returning 0 - you don't want
to silently ignore unknown or unsupported syscalls when auditing.
Signed-off-by: Klaus Weidner <klaus@atsec.com>
--- linux-2.6.18.i686/kernel/auditfilter.c.lspp.80 2007-05-11 17:06:08.000000000 -0500
+++ linux-2.6.18.i686/kernel/auditfilter.c 2007-05-11 17:09:37.000000000 -0500
@@ -306,7 +306,7 @@
int audit_match_class(int class, unsigned syscall)
{
- if (unlikely(syscall >= AUDIT_BITMASK_SIZE * sizeof(__u32)))
+ if (unlikely(syscall >= AUDIT_BITMASK_SIZE * 32))
return 0;
if (unlikely(class >= AUDIT_SYSCALL_CLASSES || !classes[class]))
return 0;
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] fix broken class-based syscall audit 2007-05-14 15:46 [PATCH] fix broken class-based syscall audit Klaus Weidner @ 2007-05-14 15:51 ` Marcus Meissner 2007-05-14 15:56 ` Klaus Weidner 0 siblings, 1 reply; 6+ messages in thread From: Marcus Meissner @ 2007-05-14 15:51 UTC (permalink / raw) To: Klaus Weidner; +Cc: linux-audit On Mon, May 14, 2007 at 10:46:36AM -0500, Klaus Weidner wrote: > Bug description: When I add an audit watch on a file with no arguments, I > get perm=rwxa but on ia64, changes to the mode and context aren't > audited. I get audit records on i386 and x86_64. > > See also: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=239887 > > The sanity check in audit_match_class() is wrong, AUDIT_BITMASK_SIZE is > 64, providing space for 2048 syscalls in 64 * 32bit integers. The > comparison only supports 256 syscalls (sizeof __u32 is 4), and silently > returns "no match" for valid higher-numbered syscalls. > > This breaks class-based audit for all syscalls on ia64 since on that > architecture syscall numbers start at 1024. It breaks some syscall audit > on other architectures also, for example __NR_fchmodat is 306 on x86. > > I'd suggest adding a printk() in addition to returning 0 - you don't want > to silently ignore unknown or unsupported syscalls when auditing. > > Signed-off-by: Klaus Weidner <klaus@atsec.com> > > --- linux-2.6.18.i686/kernel/auditfilter.c.lspp.80 2007-05-11 17:06:08.000000000 -0500 > +++ linux-2.6.18.i686/kernel/auditfilter.c 2007-05-11 17:09:37.000000000 -0500 > @@ -306,7 +306,7 @@ > > int audit_match_class(int class, unsigned syscall) > { > - if (unlikely(syscall >= AUDIT_BITMASK_SIZE * sizeof(__u32))) > + if (unlikely(syscall >= AUDIT_BITMASK_SIZE * 32)) > return 0; > if (unlikely(class >= AUDIT_SYSCALL_CLASSES || !classes[class])) > return 0; You likely need to fix audit_register_class() if this is true. Ciao, Marcus ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] fix broken class-based syscall audit 2007-05-14 15:51 ` Marcus Meissner @ 2007-05-14 15:56 ` Klaus Weidner 2007-05-14 20:47 ` Eric Paris 0 siblings, 1 reply; 6+ messages in thread From: Klaus Weidner @ 2007-05-14 15:56 UTC (permalink / raw) To: Marcus Meissner; +Cc: linux-audit On Mon, May 14, 2007 at 05:51:50PM +0200, Marcus Meissner wrote: > On Mon, May 14, 2007 at 10:46:36AM -0500, Klaus Weidner wrote: > > The sanity check in audit_match_class() is wrong, AUDIT_BITMASK_SIZE is > > 64, providing space for 2048 syscalls in 64 * 32bit integers. The > > comparison only supports 256 syscalls (sizeof __u32 is 4), and silently > > returns "no match" for valid higher-numbered syscalls. [...] > > --- linux-2.6.18.i686/kernel/auditfilter.c.lspp.80 2007-05-11 17:06:08.000000000 -0500 > > +++ linux-2.6.18.i686/kernel/auditfilter.c 2007-05-11 17:09:37.000000000 -0500 > > @@ -306,7 +306,7 @@ > > > > int audit_match_class(int class, unsigned syscall) > > { > > - if (unlikely(syscall >= AUDIT_BITMASK_SIZE * sizeof(__u32))) > > + if (unlikely(syscall >= AUDIT_BITMASK_SIZE * 32)) > > return 0; > > if (unlikely(class >= AUDIT_SYSCALL_CLASSES || !classes[class])) > > return 0; > > You likely need to fix audit_register_class() if this is true. I don't see a problem in audit_register_class() - it correctly uses sizeof(__u32) for allocating the memory since that's counted in bytes, only the comparison needs to count bits. -Klaus ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] fix broken class-based syscall audit 2007-05-14 15:56 ` Klaus Weidner @ 2007-05-14 20:47 ` Eric Paris 2007-05-14 21:32 ` Klaus Weidner 0 siblings, 1 reply; 6+ messages in thread From: Eric Paris @ 2007-05-14 20:47 UTC (permalink / raw) To: Klaus Weidner; +Cc: linux-audit On Mon, 2007-05-14 at 10:56 -0500, Klaus Weidner wrote: > On Mon, May 14, 2007 at 05:51:50PM +0200, Marcus Meissner wrote: > > On Mon, May 14, 2007 at 10:46:36AM -0500, Klaus Weidner wrote: > > > The sanity check in audit_match_class() is wrong, AUDIT_BITMASK_SIZE is > > > 64, providing space for 2048 syscalls in 64 * 32bit integers. The > > > comparison only supports 256 syscalls (sizeof __u32 is 4), and silently > > > returns "no match" for valid higher-numbered syscalls. > [...] > > > --- linux-2.6.18.i686/kernel/auditfilter.c.lspp.80 2007-05-11 17:06:08.000000000 -0500 > > > +++ linux-2.6.18.i686/kernel/auditfilter.c 2007-05-11 17:09:37.000000000 -0500 > > > @@ -306,7 +306,7 @@ > > > > > > int audit_match_class(int class, unsigned syscall) > > > { > > > - if (unlikely(syscall >= AUDIT_BITMASK_SIZE * sizeof(__u32))) > > > + if (unlikely(syscall >= AUDIT_BITMASK_SIZE * 32)) > > > return 0; > > > if (unlikely(class >= AUDIT_SYSCALL_CLASSES || !classes[class])) > > > return 0; > > > > You likely need to fix audit_register_class() if this is true. > > I don't see a problem in audit_register_class() - it correctly uses > sizeof(__u32) for allocating the memory since that's counted in bytes, > only the comparison needs to count bits. If that's the problem wouldn't we be better to use sizeof(__u32) *8 rather than hard code the 32 in there? (sidebar: is it portable to assume sizeof() returns bytes and *8 is the right way to go on all archs?) That would make it easier to do u32 search/replace in the future if we ever have to grow this stuff.... -Eric ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] fix broken class-based syscall audit 2007-05-14 20:47 ` Eric Paris @ 2007-05-14 21:32 ` Klaus Weidner 2007-05-15 14:14 ` Alexander Viro 0 siblings, 1 reply; 6+ messages in thread From: Klaus Weidner @ 2007-05-14 21:32 UTC (permalink / raw) To: Eric Paris; +Cc: linux-audit On Mon, May 14, 2007 at 04:47:29PM -0400, Eric Paris wrote: > On Mon, 2007-05-14 at 10:56 -0500, Klaus Weidner wrote: > > On Mon, May 14, 2007 at 05:51:50PM +0200, Marcus Meissner wrote: > > > On Mon, May 14, 2007 at 10:46:36AM -0500, Klaus Weidner wrote: > > > > The sanity check in audit_match_class() is wrong, AUDIT_BITMASK_SIZE is > > > > 64, providing space for 2048 syscalls in 64 * 32bit integers. The > > > > comparison only supports 256 syscalls (sizeof __u32 is 4), and silently > > > > returns "no match" for valid higher-numbered syscalls. > > [...] > > > > --- linux-2.6.18.i686/kernel/auditfilter.c.lspp.80 2007-05-11 17:06:08.000000000 -0500 > > > > +++ linux-2.6.18.i686/kernel/auditfilter.c 2007-05-11 17:09:37.000000000 -0500 > > > > @@ -306,7 +306,7 @@ > > > > > > > > int audit_match_class(int class, unsigned syscall) > > > > { > > > > - if (unlikely(syscall >= AUDIT_BITMASK_SIZE * sizeof(__u32))) > > > > + if (unlikely(syscall >= AUDIT_BITMASK_SIZE * 32)) > > > > return 0; > > > > if (unlikely(class >= AUDIT_SYSCALL_CLASSES || !classes[class])) > > > > return 0; > > > > > > You likely need to fix audit_register_class() if this is true. > > > > I don't see a problem in audit_register_class() - it correctly uses > > sizeof(__u32) for allocating the memory since that's counted in bytes, > > only the comparison needs to count bits. > > If that's the problem wouldn't we be better to use sizeof(__u32) *8 > rather than hard code the 32 in there? (sidebar: is it portable to > assume sizeof() returns bytes and *8 is the right way to go on all > archs?) That would make it easier to do u32 search/replace in the > future if we ever have to grow this stuff.... The AUDIT_WORD and AUDIT_BIT macros in include/linux/audit.h assume that they'll fit 32 bits into each __u32: #define AUDIT_WORD(nr) ((__u32)((nr)/32)) #define AUDIT_BIT(nr) (1 << ((nr) - AUDIT_WORD(nr)*32)) (If the actual capacity of the __u32 were larger they would continue using only 32 bits.) I think the hardcoded 32 is appropriate. I'm not sure about the exact sizeof() standard semantics, but I remember that the standard doesn't assume 8-bit bytes. However, I think it's safe to assume that a __u32 can fit 32 bits, if not a lot of other code would break also. -Klaus ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] fix broken class-based syscall audit 2007-05-14 21:32 ` Klaus Weidner @ 2007-05-15 14:14 ` Alexander Viro 0 siblings, 0 replies; 6+ messages in thread From: Alexander Viro @ 2007-05-15 14:14 UTC (permalink / raw) To: Klaus Weidner; +Cc: linux-audit On Mon, May 14, 2007 at 04:32:22PM -0500, Klaus Weidner wrote: > On Mon, May 14, 2007 at 04:47:29PM -0400, Eric Paris wrote: > > On Mon, 2007-05-14 at 10:56 -0500, Klaus Weidner wrote: > > > On Mon, May 14, 2007 at 05:51:50PM +0200, Marcus Meissner wrote: > > > > On Mon, May 14, 2007 at 10:46:36AM -0500, Klaus Weidner wrote: > > > > > The sanity check in audit_match_class() is wrong, AUDIT_BITMASK_SIZE is > > > > > 64, providing space for 2048 syscalls in 64 * 32bit integers. The > > > > > comparison only supports 256 syscalls (sizeof __u32 is 4), and silently > > > > > returns "no match" for valid higher-numbered syscalls. > > > [...] > > > > > --- linux-2.6.18.i686/kernel/auditfilter.c.lspp.80 2007-05-11 17:06:08.000000000 -0500 > > > > > +++ linux-2.6.18.i686/kernel/auditfilter.c 2007-05-11 17:09:37.000000000 -0500 > > > > > @@ -306,7 +306,7 @@ > > > > > > > > > > int audit_match_class(int class, unsigned syscall) > > > > > { > > > > > - if (unlikely(syscall >= AUDIT_BITMASK_SIZE * sizeof(__u32))) > > > > > + if (unlikely(syscall >= AUDIT_BITMASK_SIZE * 32)) > > > > > return 0; > > > > > if (unlikely(class >= AUDIT_SYSCALL_CLASSES || !classes[class])) > > > > > return 0; > > > > > > > > You likely need to fix audit_register_class() if this is true. > > > > > > I don't see a problem in audit_register_class() - it correctly uses > > > sizeof(__u32) for allocating the memory since that's counted in bytes, > > > only the comparison needs to count bits. > > > > If that's the problem wouldn't we be better to use sizeof(__u32) *8 > > rather than hard code the 32 in there? (sidebar: is it portable to > > assume sizeof() returns bytes and *8 is the right way to go on all > > archs?) That would make it easier to do u32 search/replace in the > > future if we ever have to grow this stuff.... > > The AUDIT_WORD and AUDIT_BIT macros in include/linux/audit.h assume that > they'll fit 32 bits into each __u32: > > #define AUDIT_WORD(nr) ((__u32)((nr)/32)) > #define AUDIT_BIT(nr) (1 << ((nr) - AUDIT_WORD(nr)*32)) > > (If the actual capacity of the __u32 were larger they would continue > using only 32 bits.) > > I think the hardcoded 32 is appropriate. I'm not sure about the exact > sizeof() standard semantics, but I remember that the standard doesn't > assume 8-bit bytes. However, I think it's safe to assume that a __u32 > can fit 32 bits, if not a lot of other code would break also. Precisely. Nice catch and an obvious fix; patch from the beginning of this thread it can go to Linus right now. Acked-by: Al Viro <viro@zeniv.linux.org.uk> (to match the signoff I'm normally using on kernel submits). Or I could pass it to Linus myself, if you wish. ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2007-05-15 14:14 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-05-14 15:46 [PATCH] fix broken class-based syscall audit Klaus Weidner 2007-05-14 15:51 ` Marcus Meissner 2007-05-14 15:56 ` Klaus Weidner 2007-05-14 20:47 ` Eric Paris 2007-05-14 21:32 ` Klaus Weidner 2007-05-15 14:14 ` Alexander Viro
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).