Linux kernel -stable discussions
 help / color / mirror / Atom feed
* [PATCH v2 1/2] auditsc: audit_krule mask accesses need bounds checking
       [not found] <cover.1401327752.git.luto@amacapital.net>
@ 2014-05-29  1:44 ` Andy Lutomirski
  2014-05-29  2:23   ` Eric Paris
  0 siblings, 1 reply; 5+ messages in thread
From: Andy Lutomirski @ 2014-05-29  1:44 UTC (permalink / raw)
  To: Andy Lutomirski, Philipp Kern, H. Peter Anvin, linux-kernel,
	H. J. Lu, Eric Paris, security, greg, linux-audit
  Cc: stable

Fixes an easy DoS and possible information disclosure.

This does nothing about the broken state of x32 auditing.

Cc: stable@vger.kernel.org
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---
 kernel/auditsc.c | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index f251a5e..7ccd9db 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -728,6 +728,22 @@ static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
 	return AUDIT_BUILD_CONTEXT;
 }
 
+static bool audit_in_mask(const struct audit_krule *rule, unsigned long val)
+{
+	int word, bit;
+
+	if (val > 0xffffffff)
+		return false;
+
+	word = AUDIT_WORD(val);
+	if (word >= AUDIT_BITMASK_SIZE)
+		return false;
+
+	bit = AUDIT_BIT(val);
+
+	return rule->mask[word] & bit;
+}
+
 /* At syscall entry and exit time, this filter is called if the
  * audit_state is not low enough that auditing cannot take place, but is
  * also not high enough that we already know we have to write an audit
@@ -745,11 +761,8 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
 
 	rcu_read_lock();
 	if (!list_empty(list)) {
-		int word = AUDIT_WORD(ctx->major);
-		int bit  = AUDIT_BIT(ctx->major);
-
 		list_for_each_entry_rcu(e, list, list) {
-			if ((e->rule.mask[word] & bit) == bit &&
+			if (audit_in_mask(&e->rule, ctx->major) &&
 			    audit_filter_rules(tsk, &e->rule, ctx, NULL,
 					       &state, false)) {
 				rcu_read_unlock();
@@ -769,20 +782,16 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
 static int audit_filter_inode_name(struct task_struct *tsk,
 				   struct audit_names *n,
 				   struct audit_context *ctx) {
-	int word, bit;
 	int h = audit_hash_ino((u32)n->ino);
 	struct list_head *list = &audit_inode_hash[h];
 	struct audit_entry *e;
 	enum audit_state state;
 
-	word = AUDIT_WORD(ctx->major);
-	bit  = AUDIT_BIT(ctx->major);
-
 	if (list_empty(list))
 		return 0;
 
 	list_for_each_entry_rcu(e, list, list) {
-		if ((e->rule.mask[word] & bit) == bit &&
+		if (audit_in_mask(&e->rule, ctx->major) &&
 		    audit_filter_rules(tsk, &e->rule, ctx, n, &state, false)) {
 			ctx->current_state = state;
 			return 1;
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] auditsc: audit_krule mask accesses need bounds checking
  2014-05-29  1:44 ` [PATCH v2 1/2] auditsc: audit_krule mask accesses need bounds checking Andy Lutomirski
@ 2014-05-29  2:23   ` Eric Paris
  2014-05-29  2:27     ` Andy Lutomirski
  0 siblings, 1 reply; 5+ messages in thread
From: Eric Paris @ 2014-05-29  2:23 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Philipp Kern, H. Peter Anvin, linux-kernel, H. J. Lu, security,
	greg, linux-audit, stable

On Wed, 2014-05-28 at 18:44 -0700, Andy Lutomirski wrote:
> Fixes an easy DoS and possible information disclosure.
> 
> This does nothing about the broken state of x32 auditing.
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
> ---
>  kernel/auditsc.c | 27 ++++++++++++++++++---------
>  1 file changed, 18 insertions(+), 9 deletions(-)
> 
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index f251a5e..7ccd9db 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -728,6 +728,22 @@ static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
>  	return AUDIT_BUILD_CONTEXT;
>  }
>  
> +static bool audit_in_mask(const struct audit_krule *rule, unsigned long val)
> +{
> +	int word, bit;
> +
> +	if (val > 0xffffffff)
> +		return false;

Why is this necessary?  

> +
> +	word = AUDIT_WORD(val);
> +	if (word >= AUDIT_BITMASK_SIZE)
> +		return false;

Since this covers it and it extensible...

> +
> +	bit = AUDIT_BIT(val);
> +
> +	return rule->mask[word] & bit;

Returning an int as a bool creates worse code than just returning the
int.  (although in this case if the compiler chooses to inline it might
be smart enough not to actually convert this int to a bool and make
worse assembly...)   I'd suggest the function here return an int.  bools
usually make the assembly worse...

Otherwise I'd give it an ACK...

> +}
> +
>  /* At syscall entry and exit time, this filter is called if the
>   * audit_state is not low enough that auditing cannot take place, but is
>   * also not high enough that we already know we have to write an audit
> @@ -745,11 +761,8 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
>  
>  	rcu_read_lock();
>  	if (!list_empty(list)) {
> -		int word = AUDIT_WORD(ctx->major);
> -		int bit  = AUDIT_BIT(ctx->major);
> -
>  		list_for_each_entry_rcu(e, list, list) {
> -			if ((e->rule.mask[word] & bit) == bit &&
> +			if (audit_in_mask(&e->rule, ctx->major) &&
>  			    audit_filter_rules(tsk, &e->rule, ctx, NULL,
>  					       &state, false)) {
>  				rcu_read_unlock();
> @@ -769,20 +782,16 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
>  static int audit_filter_inode_name(struct task_struct *tsk,
>  				   struct audit_names *n,
>  				   struct audit_context *ctx) {
> -	int word, bit;
>  	int h = audit_hash_ino((u32)n->ino);
>  	struct list_head *list = &audit_inode_hash[h];
>  	struct audit_entry *e;
>  	enum audit_state state;
>  
> -	word = AUDIT_WORD(ctx->major);
> -	bit  = AUDIT_BIT(ctx->major);
> -
>  	if (list_empty(list))
>  		return 0;
>  
>  	list_for_each_entry_rcu(e, list, list) {
> -		if ((e->rule.mask[word] & bit) == bit &&
> +		if (audit_in_mask(&e->rule, ctx->major) &&
>  		    audit_filter_rules(tsk, &e->rule, ctx, n, &state, false)) {
>  			ctx->current_state = state;
>  			return 1;



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] auditsc: audit_krule mask accesses need bounds checking
  2014-05-29  2:23   ` Eric Paris
@ 2014-05-29  2:27     ` Andy Lutomirski
  2014-05-29  2:43       ` Eric Paris
  0 siblings, 1 reply; 5+ messages in thread
From: Andy Lutomirski @ 2014-05-29  2:27 UTC (permalink / raw)
  To: Eric Paris
  Cc: Philipp Kern, H. Peter Anvin, linux-kernel@vger.kernel.org,
	H. J. Lu, security@kernel.org, Greg Kroah-Hartman, linux-audit,
	stable

On Wed, May 28, 2014 at 7:23 PM, Eric Paris <eparis@redhat.com> wrote:
> On Wed, 2014-05-28 at 18:44 -0700, Andy Lutomirski wrote:
>> Fixes an easy DoS and possible information disclosure.
>>
>> This does nothing about the broken state of x32 auditing.
>>
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
>> ---
>>  kernel/auditsc.c | 27 ++++++++++++++++++---------
>>  1 file changed, 18 insertions(+), 9 deletions(-)
>>
>> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
>> index f251a5e..7ccd9db 100644
>> --- a/kernel/auditsc.c
>> +++ b/kernel/auditsc.c
>> @@ -728,6 +728,22 @@ static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
>>       return AUDIT_BUILD_CONTEXT;
>>  }
>>
>> +static bool audit_in_mask(const struct audit_krule *rule, unsigned long val)
>> +{
>> +     int word, bit;
>> +
>> +     if (val > 0xffffffff)
>> +             return false;
>
> Why is this necessary?

To avoid an integer overflow.  Admittedly, this particular overflow
won't cause a crash, but it will cause incorrect results.

>
>> +
>> +     word = AUDIT_WORD(val);
>> +     if (word >= AUDIT_BITMASK_SIZE)
>> +             return false;
>
> Since this covers it and it extensible...
>
>> +
>> +     bit = AUDIT_BIT(val);
>> +
>> +     return rule->mask[word] & bit;
>
> Returning an int as a bool creates worse code than just returning the
> int.  (although in this case if the compiler chooses to inline it might
> be smart enough not to actually convert this int to a bool and make
> worse assembly...)   I'd suggest the function here return an int.  bools
> usually make the assembly worse...

I'm ambivalent.  The right assembly would use flags on x86, not an int
or a bool, and I don't know what the compiler will do.

--Andy

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] auditsc: audit_krule mask accesses need bounds checking
  2014-05-29  2:27     ` Andy Lutomirski
@ 2014-05-29  2:43       ` Eric Paris
  2014-05-29  2:46         ` Andy Lutomirski
  0 siblings, 1 reply; 5+ messages in thread
From: Eric Paris @ 2014-05-29  2:43 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Philipp Kern, H. Peter Anvin, linux-kernel@vger.kernel.org,
	H. J. Lu, security@kernel.org, Greg Kroah-Hartman, linux-audit,
	stable

On Wed, 2014-05-28 at 19:27 -0700, Andy Lutomirski wrote:
> On Wed, May 28, 2014 at 7:23 PM, Eric Paris <eparis@redhat.com> wrote:
> > On Wed, 2014-05-28 at 18:44 -0700, Andy Lutomirski wrote:
> >> Fixes an easy DoS and possible information disclosure.
> >>
> >> This does nothing about the broken state of x32 auditing.
> >>
> >> Cc: stable@vger.kernel.org
> >> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
> >> ---
> >>  kernel/auditsc.c | 27 ++++++++++++++++++---------
> >>  1 file changed, 18 insertions(+), 9 deletions(-)
> >>
> >> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> >> index f251a5e..7ccd9db 100644
> >> --- a/kernel/auditsc.c
> >> +++ b/kernel/auditsc.c
> >> @@ -728,6 +728,22 @@ static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
> >>       return AUDIT_BUILD_CONTEXT;
> >>  }
> >>
> >> +static bool audit_in_mask(const struct audit_krule *rule, unsigned long val)
> >> +{
> >> +     int word, bit;
> >> +
> >> +     if (val > 0xffffffff)
> >> +             return false;
> >
> > Why is this necessary?
> 
> To avoid an integer overflow.  Admittedly, this particular overflow
> won't cause a crash, but it will cause incorrect results.

You know this code pre-dates git?  I admit, I'm shocked no one ever
noticed it before!  This is ANCIENT.  And clearly broken.

I'll likely ask Richard to add a WARN_ONCE() in both this place, and
below in word > AUDIT_BITMASK_SIZE so we might know if we ever need a
larger bitmask to store syscall numbers....

It'd be nice if lib had a efficient bitmask implementation...

> >
> >> +
> >> +     word = AUDIT_WORD(val);
> >> +     if (word >= AUDIT_BITMASK_SIZE)
> >> +             return false;
> >
> > Since this covers it and it extensible...
> >
> >> +
> >> +     bit = AUDIT_BIT(val);
> >> +
> >> +     return rule->mask[word] & bit;
> >
> > Returning an int as a bool creates worse code than just returning the
> > int.  (although in this case if the compiler chooses to inline it might
> > be smart enough not to actually convert this int to a bool and make
> > worse assembly...)   I'd suggest the function here return an int.  bools
> > usually make the assembly worse...
> 
> I'm ambivalent.  The right assembly would use flags on x86, not an int
> or a bool, and I don't know what the compiler will do.

Also, clearly X86_X32 was implemented without audit support, so we
shouldn't config it in.  What do you think of this?

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 25d2c6f..fa852e2 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -129,7 +129,7 @@ config X86
 	select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64
 	select HAVE_CC_STACKPROTECTOR
 	select GENERIC_CPU_AUTOPROBE
-	select HAVE_ARCH_AUDITSYSCALL
+	select HAVE_ARCH_AUDITSYSCALL if !X86_X32
 
 config INSTRUCTION_DECODER
 	def_bool y



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] auditsc: audit_krule mask accesses need bounds checking
  2014-05-29  2:43       ` Eric Paris
@ 2014-05-29  2:46         ` Andy Lutomirski
  0 siblings, 0 replies; 5+ messages in thread
From: Andy Lutomirski @ 2014-05-29  2:46 UTC (permalink / raw)
  To: Eric Paris
  Cc: Philipp Kern, H. Peter Anvin, linux-kernel@vger.kernel.org,
	H. J. Lu, security@kernel.org, Greg Kroah-Hartman, linux-audit,
	stable

On Wed, May 28, 2014 at 7:43 PM, Eric Paris <eparis@redhat.com> wrote:
> On Wed, 2014-05-28 at 19:27 -0700, Andy Lutomirski wrote:
>> On Wed, May 28, 2014 at 7:23 PM, Eric Paris <eparis@redhat.com> wrote:
>> > On Wed, 2014-05-28 at 18:44 -0700, Andy Lutomirski wrote:
>> >> Fixes an easy DoS and possible information disclosure.
>> >>
>> >> This does nothing about the broken state of x32 auditing.
>> >>
>> >> Cc: stable@vger.kernel.org
>> >> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
>> >> ---
>> >>  kernel/auditsc.c | 27 ++++++++++++++++++---------
>> >>  1 file changed, 18 insertions(+), 9 deletions(-)
>> >>
>> >> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
>> >> index f251a5e..7ccd9db 100644
>> >> --- a/kernel/auditsc.c
>> >> +++ b/kernel/auditsc.c
>> >> @@ -728,6 +728,22 @@ static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
>> >>       return AUDIT_BUILD_CONTEXT;
>> >>  }
>> >>
>> >> +static bool audit_in_mask(const struct audit_krule *rule, unsigned long val)
>> >> +{
>> >> +     int word, bit;
>> >> +
>> >> +     if (val > 0xffffffff)
>> >> +             return false;
>> >
>> > Why is this necessary?
>>
>> To avoid an integer overflow.  Admittedly, this particular overflow
>> won't cause a crash, but it will cause incorrect results.
>
> You know this code pre-dates git?  I admit, I'm shocked no one ever
> noticed it before!  This is ANCIENT.  And clearly broken.
>
> I'll likely ask Richard to add a WARN_ONCE() in both this place, and
> below in word > AUDIT_BITMASK_SIZE so we might know if we ever need a
> larger bitmask to store syscall numbers....
>

Not there, please!  It would make sense to check when rules are
*added*, but any user can trivially invoke the filter with pretty much
any syscall nr.

> It'd be nice if lib had a efficient bitmask implementation...
>
>> >
>> >> +
>> >> +     word = AUDIT_WORD(val);
>> >> +     if (word >= AUDIT_BITMASK_SIZE)
>> >> +             return false;
>> >
>> > Since this covers it and it extensible...
>> >
>> >> +
>> >> +     bit = AUDIT_BIT(val);
>> >> +
>> >> +     return rule->mask[word] & bit;
>> >
>> > Returning an int as a bool creates worse code than just returning the
>> > int.  (although in this case if the compiler chooses to inline it might
>> > be smart enough not to actually convert this int to a bool and make
>> > worse assembly...)   I'd suggest the function here return an int.  bools
>> > usually make the assembly worse...
>>
>> I'm ambivalent.  The right assembly would use flags on x86, not an int
>> or a bool, and I don't know what the compiler will do.
>
> Also, clearly X86_X32 was implemented without audit support, so we
> shouldn't config it in.  What do you think of this?
>
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 25d2c6f..fa852e2 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -129,7 +129,7 @@ config X86
>         select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64
>         select HAVE_CC_STACKPROTECTOR
>         select GENERIC_CPU_AUTOPROBE
> -       select HAVE_ARCH_AUDITSYSCALL
> +       select HAVE_ARCH_AUDITSYSCALL if !X86_X32

I'm fine with that, but I hope that distros will choose x32 over
auditsc, at least until someone makes enabling auditsc be less
intrusive.

Or someone could fix it, modulo the syscall nr 2048 thing.  x32
syscall nrs are *huge*.  So are lots of other architectures', a few of
which probably claim to support auditsc.

--Andy

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-05-29  2:46 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <cover.1401327752.git.luto@amacapital.net>
2014-05-29  1:44 ` [PATCH v2 1/2] auditsc: audit_krule mask accesses need bounds checking Andy Lutomirski
2014-05-29  2:23   ` Eric Paris
2014-05-29  2:27     ` Andy Lutomirski
2014-05-29  2:43       ` Eric Paris
2014-05-29  2:46         ` Andy Lutomirski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox