Skip to contentSkip to conversation

X32: fix syscall_get_nr while not breaking seccomp BPF

RFC PATCH In review Richard Guy Briggs 6 participants 22 messages Jul 11, 2014

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover X32: fix syscall_get_nr while not breaking seccomp BPF

This set reverts commit 8b4b9f2 which broke audit and potentially other users of syscall_get_nr() which depend on that call as named without being overloaded by architecture bits. It will satisfy other regular users of syscall_get_nr() and syscall_get_arch() without changing the seccomp interface to BPF.

A new ARCH definition, AUDIT_ARCH_X86_X32, was added for syscall_get_arch().

Richard Guy Briggs (3):
audit: add AUDIT_ARCH_X86_X32 arch definition
seccomp: give BPF x32 bit when restoring x32 filter Revert "x86: remove the x32 syscall bitmask from syscall_get_nr()"

 arch/x86/include/asm/syscall.h |    8 ++++++--
 include/uapi/linux/audit.h     |    1 +
 kernel/seccomp.c               |    6 ++++++
 3 files changed, 13 insertions(+), 2 deletions(-)
#1 lore raw

RFC PATCH 1/3 audit: add AUDIT_ARCH_X86_X32 arch definition

Add a definition for 32-bit native system calls under 64-bit x86 architectures. This is distict from 32-bit emulation under 64-bit x86 architectures.

Cc Paul Moore <[email protected]>
Cc Eric Paris <[email protected]>
Cc Al Viro <[email protected]>
Cc Will Drewry <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 include/uapi/linux/audit.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
include/uapi/linux/audit.h +1 -0
index e15d6fc..4f5607f 100644
@@ -374,6 +374,7 @@ enum {
 #define AUDIT_ARCH_SPARC	(EM_SPARC)
 #define AUDIT_ARCH_SPARC64	(EM_SPARCV9|__AUDIT_ARCH_64BIT)
 #define AUDIT_ARCH_X86_64	(EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_X86_X32	(EM_X86_64|__AUDIT_ARCH_LE)
 
 #define AUDIT_PERM_EXEC		1
 #define AUDIT_PERM_WRITE	2
Signature · 1 line
1.7.1
#2 lore raw

Re: [PATCH 1/3] [RFC] audit: add AUDIT_ARCH_X86_X32 arch definition

Quoted 19 lines · Richard Guy Briggs

Add a definition for 32-bit native system calls under 64-bit x86 architectures. This is distict from 32-bit emulation under 64-bit x86 architectures.

Cc Paul Moore <[email protected]>
Cc Eric Paris <[email protected]>
Cc Al Viro <[email protected]>
Cc Will Drewry <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 include/uapi/linux/audit.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
include/uapi/linux/audit.h +0 -0
index e15d6fc..4f5607f 100644

include/uapi/linux/audit.h enum { · line 380

Quoted 7 lines
include/uapi/linux/audit.h +1 -0
@@ -374,6 +374,7 @@ enum {
 #define AUDIT_ARCH_SPARC	(EM_SPARC)
 #define AUDIT_ARCH_SPARC64	(EM_SPARCV9|__AUDIT_ARCH_64BIT)
 #define AUDIT_ARCH_X86_64	(EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_X86_X32	(EM_X86_64|__AUDIT_ARCH_LE)
 
 #define AUDIT_PERM_EXEC		1
 #define AUDIT_PERM_WRITE	2

While I'm opposed to the other patches in this series (comments to follow), I think this is a worthwhile addition and arguably should have been done when x32 was merged.

That said, this change should probably be included in whatever patch first makes use of this new value as this patch does nothing by itself.

Signature · 2 lines
paul moore
security and virtualization @ redhat
#3 lore raw

RFC PATCH 2/3 seccomp: give BPF x32 bit when restoring x32 filter

In reply to Richard Guy Briggs

Commit

	fca460f [email protected] 2012-02-19 07:56:26 -0800
	x32: Handle the x32 system call flag

provided a method to multiplex architecture with the syscall number for X32 calls.

Commit

	8b4b9f2 [email protected] 2013-02-15 12:21:43 -0500
	x86: remove the x32 syscall bitmask from syscall_get_nr()

broke audit and potentially other users of syscall_get_nr() which depend on that call as named.

Commit
audit: add AUDIT_ARCH_X86_X32 arch definition

is required to provide the new ARCH definition AUDIT_ARCH_X86_X32 for syscall_get_arch().

This patch along with reverting 8b4b9f2 should satisfy other regular users of syscall_get_nr() without changing the seccomp interface to BPF.

---
 arch/x86/include/asm/syscall.h |    4 ++++
 kernel/seccomp.c               |    6 ++++++
 2 files changed, 10 insertions(+), 0 deletions(-)
arch/x86/include/asm/syscall.h +4 -0
index d6a756a..d58b6be 100644
@@ -236,6 +236,10 @@ static inline int syscall_get_arch(void)
 		return AUDIT_ARCH_I386;
 #endif
 	/* Both x32 and x86_64 are considered "64-bit". */
+#ifdef CONFIG_X86_X32_ABI
+	if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
+		return AUDIT_ARCH_X86_X32;
+#endif
 	return AUDIT_ARCH_X86_64;
 }
 #endif	/* CONFIG_X86_32 */
kernel/seccomp.c +6 -0
index b35c215..bc18214 100644
@@ -73,6 +73,12 @@ static void populate_seccomp_data(struct seccomp_data *sd)
 
 	sd->nr = syscall_get_nr(task, regs);
 	sd->arch = syscall_get_arch();
+#ifdef CONFIG_X86_X32_ABI
+	if (sd->arch == AUDIT_ARCH_X86_X32) {
+		sd->arch = AUDIT_ARCH_X86_64;
+		sd->nr |= __X32_SYSCALL_BIT;
+	}
+#endif
 	syscall_get_arguments(task, regs, 0, 6, args);
 	sd->args[0] = args[0];
 	sd->args[1] = args[1];
Signature · 1 line
1.7.1
#4 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

Quoted 14 lines · Richard Guy Briggs

Commit

	fca460f [email protected] 2012-02-19 07:56:26 -0800
	x32: Handle the x32 system call flag

provided a method to multiplex architecture with the syscall number for X32 calls.

Commit

	8b4b9f2 [email protected] 2013-02-15 12:21:43 -0500
	x86: remove the x32 syscall bitmask from syscall_get_nr()

broke audit and potentially other users of syscall_get_nr() which depend on that call as named.

Quoted 9 lines

Commit
audit: add AUDIT_ARCH_X86_X32 arch definition

is required to provide the new ARCH definition AUDIT_ARCH_X86_X32 for syscall_get_arch().

This patch along with reverting 8b4b9f2 should satisfy other regular users of syscall_get_nr() without changing the seccomp interface to BPF.

Incidentally: do seccomp users know that on an x86-64 system you can recevie system calls from any of the x86 architectures, regardless of how the program is invoked? (This is unusual, so normally denying those "alien" calls is the right thing to do.)

-hpa

#5 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

Quoted 4 lines · H. Peter Anvin

Incidentally: do seccomp users know that on an x86-64 system you can recevie system calls from any of the x86 architectures, regardless of how the program is invoked? (This is unusual, so normally denying those "alien" calls is the right thing to do.)

I obviously can't speak for all seccomp users, but libseccomp handles this by checking the seccomp_data->arch value at the start of the filter and killing (by default) any non-native architectures. If you want, you can change this default behavior or add support for other architectures (e.g. create a filter that allows both x86-64 and x32 but disallows x86, or any combination of the three for that matter).

Signature · 2 lines
paul moore
security and virtualization @ redhat
#6 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

Quoted 6 lines · Paul Moore
Quoted 4 lines · H. Peter Anvin

Incidentally: do seccomp users know that on an x86-64 system you can recevie system calls from any of the x86 architectures, regardless of how the program is invoked? (This is unusual, so normally denying those "alien" calls is the right thing to do.)

Quoted 7 lines

I obviously can't speak for all seccomp users, but libseccomp handles this by checking the seccomp_data->arch value at the start of the filter and killing (by default) any non-native architectures. If you want, you can change this default behavior or add support for other architectures (e.g. create a filter that allows both x86-64 and x32 but disallows x86, or any combination of the three for that matter).

OK, that seems reasonable.

-hpa

maintainer
#7 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

In reply to Paul Moore
Quoted 6 lines · Paul Moore
Quoted 4 lines · H. Peter Anvin

Incidentally: do seccomp users know that on an x86-64 system you can recevie system calls from any of the x86 architectures, regardless of how the program is invoked? (This is unusual, so normally denying those "alien" calls is the right thing to do.)

Quoted 6 lines

I obviously can't speak for all seccomp users, but libseccomp handles this by checking the seccomp_data->arch value at the start of the filter and killing (by default) any non-native architectures. If you want, you can change this default behavior or add support for other architectures (e.g. create a filter that allows both x86-64 and x32 but disallows x86, or any combination of the three for that matter).

Maybe libseccomp does some HORRIFIC contortions under the hood, but the interface is crap... Since seccomp_data->arch can't distinguish between X32 and X86_64. If I write a seccomp filter which says

KILL arch != x86_64
KILL init_module
ALLOW everything else

I can still call init_module, I just have to use the X32 variant.

If libseccomp is translating:

KILL arch != x86_64 into:

KILL arch != x86_64
KILL syscall_nr >= 2000

That's just showing how dumb the kernel interface is... Good for you
guys, but the kernel is just being dumb :)

#8 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

Quoted 26 lines · Eric Paris
Quoted 6 lines · Paul Moore
Quoted 4 lines · H. Peter Anvin

Incidentally: do seccomp users know that on an x86-64 system you can recevie system calls from any of the x86 architectures, regardless of how the program is invoked? (This is unusual, so normally denying those "alien" calls is the right thing to do.)

Quoted 6 lines

I obviously can't speak for all seccomp users, but libseccomp handles this by checking the seccomp_data->arch value at the start of the filter and killing (by default) any non-native architectures. If you want, you can change this default behavior or add support for other architectures (e.g. create a filter that allows both x86-64 and x32 but disallows x86, or any combination of the three for that matter).

Maybe libseccomp does some HORRIFIC contortions under the hood, but the interface is crap... Since seccomp_data->arch can't distinguish between X32 and X86_64. If I write a seccomp filter which says

KILL arch != x86_64
KILL init_module
ALLOW everything else

I can still call init_module, I just have to use the X32 variant.

If libseccomp is translating:

Quoted 7 lines

KILL arch != x86_64 into:

KILL arch != x86_64
KILL syscall_nr >= 2000

That's just showing how dumb the kernel interface is... Good for you
guys, but the kernel is just being dumb :)

You're not going to hear me ever say that I like how the x32 ABI was done, it is a real mess from a seccomp filter point of view and we have to do some nasty stuff in libseccomp to make it all work correctly (see my comments on the libseccomp-devel list regarding my severe displeasure over x32), but what's done is done.

I think it's too late to change the x32 seccomp filter ABI.

Signature · 2 lines
paul moore
security and virtualization @ redhat
maintainer
#9 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

Quoted 35 lines · Paul Moore
Quoted 26 lines · Eric Paris
Quoted 6 lines · Paul Moore
Quoted 4 lines · H. Peter Anvin

Incidentally: do seccomp users know that on an x86-64 system you can recevie system calls from any of the x86 architectures, regardless of how the program is invoked? (This is unusual, so normally denying those "alien" calls is the right thing to do.)

Quoted 6 lines

I obviously can't speak for all seccomp users, but libseccomp handles this by checking the seccomp_data->arch value at the start of the filter and killing (by default) any non-native architectures. If you want, you can change this default behavior or add support for other architectures (e.g. create a filter that allows both x86-64 and x32 but disallows x86, or any combination of the three for that matter).

Maybe libseccomp does some HORRIFIC contortions under the hood, but the interface is crap... Since seccomp_data->arch can't distinguish between X32 and X86_64. If I write a seccomp filter which says

KILL arch != x86_64
KILL init_module
ALLOW everything else

I can still call init_module, I just have to use the X32 variant.

If libseccomp is translating:

Quoted 7 lines

KILL arch != x86_64 into:

KILL arch != x86_64
KILL syscall_nr >= 2000

That's just showing how dumb the kernel interface is... Good for you
guys, but the kernel is just being dumb :)

Quoted 7 lines

You're not going to hear me ever say that I like how the x32 ABI was done, it is a real mess from a seccomp filter point of view and we have to do some nasty stuff in libseccomp to make it all work correctly (see my comments on the libseccomp-devel list regarding my severe displeasure over x32), but what's done is done.

I think it's too late to change the x32 seccomp filter ABI.

So we have a security interface that is damn near impossible to get right. Perfect.

I think this explains exactly why I support this idea. Make X32 look like everyone else and put these custom horrific hacks in seccomp if we are unwilling to 'do it right'

Honestly, how many people are using seccomp on X32 and would be horribly pissed if we just fixed it?

#10 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

Quoted 12 lines · Eric Paris
Quoted 8 lines

You're not going to hear me ever say that I like how the x32 ABI was done, it is a real mess from a seccomp filter point of view and we have to do some nasty stuff in libseccomp to make it all work correctly (see my comments on the libseccomp-devel list regarding my severe displeasure over x32), but what's done is done.

I think it's too late to change the x32 seccomp filter ABI.

So we have a security interface that is damn near impossible to get right. Perfect.

Quoted 7 lines

I think this explains exactly why I support this idea. Make X32 look like everyone else and put these custom horrific hacks in seccomp if we are unwilling to 'do it right'

Honestly, how many people are using seccomp on X32 and would be horribly pissed if we just fixed it?

The bigger issue is probably if we will open a problem with the older kernels.

-hpa

#11 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

In reply to Eric Paris
Quoted 49 lines · Eric Paris
Quoted 48 lines · Paul Moore
Quoted 33 lines · Eric Paris
Quoted 8 lines · Paul Moore
Quoted 6 lines · H. Peter Anvin

Incidentally: do seccomp users know that on an x86-64 system you can recevie system calls from any of the x86 architectures, regardless of
how the program is invoked? (This is unusual, so normally denying those
"alien" calls is the right thing to do.)

Quoted 11 lines

I obviously can't speak for all seccomp users, but libseccomp handles this
by checking the seccomp_data->arch value at the start of the filter and
killing (by default) any non-native architectures. If you want, you can
change this default behavior or add support for other architectures (e.g.
create a filter that allows both x86-64 and x32 but disallows x86, or any
combination of the three for that matter).

Maybe libseccomp does some HORRIFIC contortions under the hood, but the interface is crap... Since seccomp_data->arch can't distinguish between X32 and X86_64. If I write a seccomp filter which says

KILL arch != x86_64
KILL init_module
ALLOW everything else

I can still call init_module, I just have to use the X32 variant.

If libseccomp is translating:

Quoted 7 lines

KILL arch != x86_64 into:

KILL arch != x86_64
KILL syscall_nr >= 2000

That's just showing how dumb the kernel interface is... Good for you
guys, but the kernel is just being dumb :)

You're not going to hear me ever say that I like how the x32 ABI was done, it is a real mess from a seccomp filter point of view and we have to do some nasty stuff in libseccomp to make it all work correctly (see my comments on the libseccomp-devel list regarding my severe displeasure over x32), but what's done is done.

Quoted 4 lines
Quoted 1 line

I think it's too late to change the x32 seccomp filter ABI.

So we have a security interface that is damn near impossible to get right. Perfect.

What? Having to do two comparisons instead of one is "damn near impossible"? I think that might be a bit of an overreaction don't you think?

Quoted 2 lines

I think this explains exactly why I support this idea. Make X32 look like everyone else ...

You do realize that this patch set makes x32 the odd man out by having syscall_get_nr() return a different syscall number than what was used to make the syscall? I don't understand how that makes "x32 look like everyone else".

Quoted 2 lines

... and put these custom horrific hacks in seccomp if we are unwilling to 'do it right'

If you want to add the new x32 audit arch #define, go for it, like I said that was something that I feel should have been in there from the beginning. As far as I'm concerned you can even put a hack in kernel/seccomp.c to rewrite the arch token value if it makes your life easier.

Quoted 2 lines

Honestly, how many people are using seccomp on X32 and would be horribly pissed if we just fixed it?

Okay, please stop suggesting we break the x32 kernel/user interface to workaround a flaw in audit. I get that it sucks for audit, I really do, but this is audit's problem.

Signature · 2 lines
paul moore
security and virtualization @ redhat
maintainer
#12 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

Quoted 50 lines · Paul Moore
Quoted 49 lines · Eric Paris
Quoted 48 lines · Paul Moore
Quoted 33 lines · Eric Paris
Quoted 8 lines · Paul Moore
Quoted 6 lines · H. Peter Anvin

Incidentally: do seccomp users know that on an x86-64 system you can recevie system calls from any of the x86 architectures, regardless of
how the program is invoked? (This is unusual, so normally denying those
"alien" calls is the right thing to do.)

Quoted 11 lines

I obviously can't speak for all seccomp users, but libseccomp handles this
by checking the seccomp_data->arch value at the start of the filter and
killing (by default) any non-native architectures. If you want, you can
change this default behavior or add support for other architectures (e.g.
create a filter that allows both x86-64 and x32 but disallows x86, or any
combination of the three for that matter).

Maybe libseccomp does some HORRIFIC contortions under the hood, but the interface is crap... Since seccomp_data->arch can't distinguish between X32 and X86_64. If I write a seccomp filter which says

KILL arch != x86_64
KILL init_module
ALLOW everything else

I can still call init_module, I just have to use the X32 variant.

If libseccomp is translating:

Quoted 7 lines

KILL arch != x86_64 into:

KILL arch != x86_64
KILL syscall_nr >= 2000

That's just showing how dumb the kernel interface is... Good for you
guys, but the kernel is just being dumb :)

You're not going to hear me ever say that I like how the x32 ABI was done, it is a real mess from a seccomp filter point of view and we have to do some nasty stuff in libseccomp to make it all work correctly (see my comments on the libseccomp-devel list regarding my severe displeasure over x32), but what's done is done.

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

I think it's too late to change the x32 seccomp filter ABI.

So we have a security interface that is damn near impossible to get right. Perfect.

What? Having to do two comparisons instead of one is "damn near impossible"? I think that might be a bit of an overreaction don't you think?

Actually no. How can a normal userspace application coder POSSIBLY know this? Find this thread on an e-mail list, by accident?

Quoted 7 lines
Quoted 3 lines

I think this explains exactly why I support this idea. Make X32 look like everyone else ...

You do realize that this patch set makes x32 the odd man out by having syscall_get_nr() return a different syscall number than what was used to make the syscall? I don't understand how that makes "x32 look like everyone else".

Ok, I buy the __X32_SYSCALL_BIT argument. It can be dealt with in audit. No problem. We don't need to strip it in syscall_get_nr(). I'll gladly concede that part of the patch series.

But given an x86_64 kernel a seccomp filter writer has to know about X32 and how to write rules to block the X32 ABI. And I stick with my assessment that x32 + seccomp is darn near impossible for a normal developer to handle.

Heck, even chromium took months to realize that x32 was a weird beast. And they got it wrong on their first try. Their original implementation didn't handle __X32_SYSCALL_BIT quite right. Looking at their code I'm still not sure it does the right thing. And they are the EXPERTS. They wrote seccomp!

Quoted 6 lines
Quoted 2 lines

Honestly, how many people are using seccomp on X32 and would be horribly pissed if we just fixed it?

Okay, please stop suggesting we break the x32 kernel/user interface to workaround a flaw in audit. I get that it sucks for audit, I really do, but this is audit's problem.

No one is asking to break X32 to fix audit. Audit can handle itself. I don't want anything in the kernel to pretend that X32 is X86_64. It isn't. It has its own syscall table. Its own syscalls. Its own ABI. I'm suggesting to fix how seccomp exposes X32 information because it is a HORRIBLE interface that even the experts have gotten wrong, over and over and over.

I suggest we accept it as breakage and just return AUDIT_ARCH_X32. (Leaving the _X32_SYSCALL_BIT exposed as it is today)

But I'd love to hear some thoughts on how that is a bad thing. If no one is using the x32 seccomp abi, lets fix it. If someone is, lets see what the fallout from fixing it will be.

-Eric

#13 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

Quoted 2 lines · Eric Paris
Quoted 1 line · Paul Moore

On Friday, July 11, 2014 12:23:33 PM Eric Paris wrote:

...

Quoted 9 lines
Quoted 6 lines
Quoted 2 lines

So we have a security interface that is damn near impossible to get right. Perfect.

What? Having to do two comparisons instead of one is "damn near impossible"? I think that might be a bit of an overreaction don't you think?

Actually no. How can a normal userspace application coder POSSIBLY know this? Find this thread on an e-mail list, by accident?

I suppose some clarification of perspective is in order. Personally, I don't think a "normal" (which brings up the age old question: what is normal anyway?) userspace developer is going to write their own seccomp BPF filter, there is just too much of a barrier to entry and it is way too easy to get it wrong. This is why I started the libseccomp project.

However, I think there *may* be a solution to satisfy us both, see below.

Quoted 8 lines
Quoted 7 lines
Quoted 2 lines

I think this explains exactly why I support this idea. Make X32 look like everyone else ...

You do realize that this patch set makes x32 the odd man out by having syscall_get_nr() return a different syscall number than what was used to make the syscall? I don't understand how that makes "x32 look like everyone else".

Quoted 8 lines

Ok, I buy the __X32_SYSCALL_BIT argument. It can be dealt with in audit. No problem. We don't need to strip it in syscall_get_nr(). I'll gladly concede that part of the patch series.

But given an x86_64 kernel a seccomp filter writer has to know about X32 and how to write rules to block the X32 ABI. And I stick with my assessment that x32 + seccomp is darn near impossible for a normal developer to handle.

No argument here; like I said, I think seccomp BPF filters are too much for most folks regardless of the arch.

Quoted 5 lines

Heck, even chromium took months to realize that x32 was a weird beast. And they got it wrong on their first try. Their original implementation didn't handle __X32_SYSCALL_BIT quite right. Looking at their code I'm still not sure it does the right thing. And they are the EXPERTS. They wrote seccomp!

I think you're helping prove my point. Or I'm providing yours. Or something.

However, my point about breaking userspace still stands. Assuming the kernel interface is functional, regardless of warts, I stand fast in that anything that breaks the kernel/userspace interface is bad.

Quoted 7 lines
Quoted 6 lines
Quoted 2 lines

Honestly, how many people are using seccomp on X32 and would be horribly pissed if we just fixed it?

Okay, please stop suggesting we break the x32 kernel/user interface to workaround a flaw in audit. I get that it sucks for audit, I really do, but this is audit's problem.

Quoted 6 lines

No one is asking to break X32 to fix audit. Audit can handle itself. I don't want anything in the kernel to pretend that X32 is X86_64. It isn't. It has its own syscall table. Its own syscalls. Its own ABI. I'm suggesting to fix how seccomp exposes X32 information because it is a HORRIBLE interface that even the experts have gotten wrong, over and over and over.

See my comments above.

Quoted 6 lines

I suggest we accept it as breakage and just return AUDIT_ARCH_X32. (Leaving the _X32_SYSCALL_BIT exposed as it is today)

But I'd love to hear some thoughts on how that is a bad thing. If no one is using the x32 seccomp abi, lets fix it. If someone is, lets see what the fallout from fixing it will be.

This would break the seccomp filter API and any application that uses it properly. I'm not excited about the idea of "let's just break the interface and see who notices philosophy"; that's a very bad practice IMHO.

Anyway, getting back to the idea I mentioned earlier ... as many of you may know, Kees (added to the CC line) is working on some seccomp filter improvements which will result in a new seccomp syscall. Perhaps one way forward is to preserve everything as it is currently with the prctl() interface, but with the new seccomp() based interface we fixup x32 and use the new AUDIT_ARCH_X32 token? It might result in a bit of ugliness in some of the kernel, but I don't think it would be too bad, and I think it would address both our concerns.

Thoughts?

Signature · 2 lines
paul moore
security and virtualization @ redhat
#14 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

Quoted 8 lines · Paul Moore

Anyway, getting back to the idea I mentioned earlier ... as many of you may know, Kees (added to the CC line) is working on some seccomp filter improvements which will result in a new seccomp syscall. Perhaps one way forward is to preserve everything as it is currently with the prctl() interface, but with the new seccomp() based interface we fixup x32 and use the new AUDIT_ARCH_X32 token? It might result in a bit of ugliness in some of the kernel, but I don't think it would be too bad, and I think it would address both our concerns.

Adding AUDIT_ARCH_X32: yes please. (On that note, the comment "/* Both x32 and x86_64 are considered "64-bit". */" should be changed...)

Just so I understand: currently x86_64 and x32 both present as AUDIT_ARCH_X86_64. The x32 syscalls are seen as in a different range (due to the set high bit).

The seccomp used in Chrome, Chrome OS, and vsftpd should all only do whitelisting by both arch and syscall, so adding AUDIT_ARCH_X32 without setting __X32_SYSCALL_BIT would be totally fine (it would catch the arch instead of the syscall). This sounds similar to how libseccomp is doing things, so these should be fine.

The only project I know of doing blacklisting is lxc, and Eric's example looks a lot like a discussion I saw with lxc and init_module. :) So it sounds like we can get this right there.

I'd like to avoid carrying a delta on filter logic based on the prctl vs syscall entry. Can we find any userspace filters being used that a "correct" fix would break? (If so, then yes, we'll need to do this proposed "via prctl or via syscall?" change.)

-Kees

Signature · 2 lines
Kees Cook
Chrome OS Security
#15 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

Quoted 17 lines · Kees Cook
Quoted 8 lines · Paul Moore

Anyway, getting back to the idea I mentioned earlier ... as many of you may know, Kees (added to the CC line) is working on some seccomp filter improvements which will result in a new seccomp syscall. Perhaps one way forward is to preserve everything as it is currently with the prctl() interface, but with the new seccomp() based interface we fixup x32 and use the new AUDIT_ARCH_X32 token? It might result in a bit of ugliness in some of the kernel, but I don't think it would be too bad, and I think it would address both our concerns.

Adding AUDIT_ARCH_X32: yes please. (On that note, the comment "/* Both x32 and x86_64 are considered "64-bit". */" should be changed...)

Just so I understand: currently x86_64 and x32 both present as AUDIT_ARCH_X86_64. The x32 syscalls are seen as in a different range (due to the set high bit).

Quoted 5 lines

The seccomp used in Chrome, Chrome OS, and vsftpd should all only do whitelisting by both arch and syscall, so adding AUDIT_ARCH_X32 without setting __X32_SYSCALL_BIT would be totally fine (it would catch the arch instead of the syscall). This sounds similar to how libseccomp is doing things, so these should be fine.

I should clarify: seccomp expects to find whatever is sent as the syscall nr... as in the __NR_read used like this:

                BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
                        offsetof(struct seccomp_data, nr)),
                BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_read, 0, 1),
                BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
                BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),

Are there native x32 users yet? What does __NR_read resolve to via the uapi on a native x32 userspace?

-Kees

Quoted 14 lines

The only project I know of doing blacklisting is lxc, and Eric's example looks a lot like a discussion I saw with lxc and init_module. :) So it sounds like we can get this right there.

I'd like to avoid carrying a delta on filter logic based on the prctl vs syscall entry. Can we find any userspace filters being used that a "correct" fix would break? (If so, then yes, we'll need to do this proposed "via prctl or via syscall?" change.)

-Kees

--
Kees Cook
Chrome OS Security

Signature · 2 lines
Kees Cook
Chrome OS Security
#16 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

It includes the X32 bit.

Quoted 61 lines · Kees Cook
Quoted 1 line · Kees Cook

On Fri, Jul 11, 2014 at 12:36 PM, Paul Moore <[email protected]>

Quoted 1 line · wrote:
Quoted 1 line

Anyway, getting back to the idea I mentioned earlier ... as many of

you may

Quoted 2 lines
Quoted 2 lines

know, Kees (added to the CC line) is working on some seccomp filter improvements which will result in a new seccomp syscall. Perhaps

one way

Quoted 1 line
Quoted 1 line

forward is to preserve everything as it is currently with the

prctl()

Quoted 1 line
Quoted 1 line

interface, but with the new seccomp() based interface we fixup x32

and use the

Quoted 1 line
Quoted 1 line

new AUDIT_ARCH_X32 token? It might result in a bit of ugliness in

some of the

Quoted 1 line
Quoted 1 line

kernel, but I don't think it would be too bad, and I think it would

address

Quoted 3 lines
Quoted 1 line

both our concerns.

Adding AUDIT_ARCH_X32: yes please. (On that note, the comment "/*

Both

Quoted 11 lines

x32 and x86_64 are considered "64-bit". */" should be changed...)

Just so I understand: currently x86_64 and x32 both present as AUDIT_ARCH_X86_64. The x32 syscalls are seen as in a different range (due to the set high bit).

The seccomp used in Chrome, Chrome OS, and vsftpd should all only do whitelisting by both arch and syscall, so adding AUDIT_ARCH_X32 without setting __X32_SYSCALL_BIT would be totally fine (it would catch the arch instead of the syscall). This sounds similar to how libseccomp is doing things, so these should be fine.

I should clarify: seccomp expects to find whatever is sent as the syscall nr... as in the __NR_read used like this:

               BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
                       offsetof(struct seccomp_data, nr)),
               BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_read, 0, 1),
               BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
               BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),

Are there native x32 users yet? What does __NR_read resolve to via the uapi on a native x32 userspace?

-Kees

Quoted 14 lines

The only project I know of doing blacklisting is lxc, and Eric's example looks a lot like a discussion I saw with lxc and init_module. :) So it sounds like we can get this right there.

I'd like to avoid carrying a delta on filter logic based on the prctl vs syscall entry. Can we find any userspace filters being used that a "correct" fix would break? (If so, then yes, we'll need to do this proposed "via prctl or via syscall?" change.)

-Kees

--
Kees Cook
Chrome OS Security

Signature · 1 line
Sent from my mobile phone.  Please pardon brevity and lack of formatting.
#17 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

Quoted 1 line · H. Peter Anvin

It includes the X32 bit.

If the uapi for __NR_* includes the x32 bit, then that's what seccomp filters must be seeing. Building seccomp filters is documented to use the __NR_* values.

-Kees

Quoted 66 lines · Kees Cook
Quoted 42 lines
Quoted 1 line · Kees Cook

On Fri, Jul 11, 2014 at 12:36 PM, Paul Moore <[email protected]>

Quoted 1 line · wrote:
Quoted 1 line

Anyway, getting back to the idea I mentioned earlier ... as many of

you may

Quoted 2 lines
Quoted 2 lines

know, Kees (added to the CC line) is working on some seccomp filter improvements which will result in a new seccomp syscall. Perhaps

one way

Quoted 1 line
Quoted 1 line

forward is to preserve everything as it is currently with the

prctl()

Quoted 1 line
Quoted 1 line

interface, but with the new seccomp() based interface we fixup x32

and use the

Quoted 1 line
Quoted 1 line

new AUDIT_ARCH_X32 token? It might result in a bit of ugliness in

some of the

Quoted 1 line
Quoted 1 line

kernel, but I don't think it would be too bad, and I think it would

address

Quoted 3 lines
Quoted 1 line

both our concerns.

Adding AUDIT_ARCH_X32: yes please. (On that note, the comment "/*

Both

Quoted 11 lines

x32 and x86_64 are considered "64-bit". */" should be changed...)

Just so I understand: currently x86_64 and x32 both present as AUDIT_ARCH_X86_64. The x32 syscalls are seen as in a different range (due to the set high bit).

The seccomp used in Chrome, Chrome OS, and vsftpd should all only do whitelisting by both arch and syscall, so adding AUDIT_ARCH_X32 without setting __X32_SYSCALL_BIT would be totally fine (it would catch the arch instead of the syscall). This sounds similar to how libseccomp is doing things, so these should be fine.

I should clarify: seccomp expects to find whatever is sent as the syscall nr... as in the __NR_read used like this:

               BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
                       offsetof(struct seccomp_data, nr)),
               BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_read, 0, 1),
               BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
               BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
Quoted 19 lines

Are there native x32 users yet? What does __NR_read resolve to via the uapi on a native x32 userspace?

-Kees

Quoted 14 lines

The only project I know of doing blacklisting is lxc, and Eric's example looks a lot like a discussion I saw with lxc and init_module. :) So it sounds like we can get this right there.

I'd like to avoid carrying a delta on filter logic based on the prctl vs syscall entry. Can we find any userspace filters being used that a "correct" fix would break? (If so, then yes, we'll need to do this proposed "via prctl or via syscall?" change.)

-Kees

--
Kees Cook
Chrome OS Security

--
Sent from my mobile phone. Please pardon brevity and lack of formatting.

Signature · 2 lines
Kees Cook
Chrome OS Security
#18 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

In reply to Kees Cook
Quoted 11 lines · Kees Cook
Quoted 8 lines · Paul Moore

Anyway, getting back to the idea I mentioned earlier ... as many of you may know, Kees (added to the CC line) is working on some seccomp filter improvements which will result in a new seccomp syscall. Perhaps one way forward is to preserve everything as it is currently with the prctl() interface, but with the new seccomp() based interface we fixup x32 and use the new AUDIT_ARCH_X32 token? It might result in a bit of ugliness in some of the kernel, but I don't think it would be too bad, and I think it would address both our concerns.

Quoted 3 lines

Adding AUDIT_ARCH_X32: yes please. (On that note, the comment "/* Both x32 and x86_64 are considered "64-bit". */" should be changed...)

I admit I'm not convinced that the current situation is really wrong. The "audit arch" uniquely defines a mapping between the actual syscall and nr and the regs. The natural way to convert between seccomp_data and the syscall entry and regs is completely correct.

For things like ARM OABI, the situation is different: OABI and EABI really do work differently wrt the interpretation of the syscall regs. This isn't the case for x32.

Of course, the audit code screws this up completely, but audit is disabled for x32. My upcoming seccomp patchset will clean it up a little. IMO there's no actual audit ABI to preserve for x32, because that code has never been anything other than terminally fvcked.

--Andy

#19 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

In reply to Richard Guy Briggs
Quoted 7 lines · Richard Guy Briggs

Commit

	fca460f [email protected] 2012-02-19 07:56:26 -0800
	x32: Handle the x32 system call flag

provided a method to multiplex architecture with the syscall number for X32 calls.

Quoted 6 lines

Commit

	8b4b9f2 [email protected] 2013-02-15 12:21:43 -0500
	x86: remove the x32 syscall bitmask from syscall_get_nr()

broke audit and potentially other users of syscall_get_nr() which depend on that call as named.

Arguably audit is broken anyway by not correctly treating syscall numbers as 32 bit integers like everyone else.

The commit above, 8b4b9f2, changed syscall_get_nr() so that it returned the same syscall number that is used by the architecture's ABI; just like every* other architecture in the kernel.

* Admittedly I didn't check every architecture's implementation, but after a half dozen I stopped checking as there was a definite trend.

{snip}

arch/x86/include/asm/syscall.h static inline int syscall_get_arch(void) · line 242

Quoted 12 lines
arch/x86/include/asm/syscall.h +4 -0
index d6a756a..d58b6be 100644
@@ -236,6 +236,10 @@ static inline int syscall_get_arch(void)
 		return AUDIT_ARCH_I386;
 #endif
 	/* Both x32 and x86_64 are considered "64-bit". */
+#ifdef CONFIG_X86_X32_ABI
+	if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
+		return AUDIT_ARCH_X86_X32;
+#endif

No. See my comments above and in other parts of this thread.

Quoted 8 lines
arch/x86/include/asm/syscall.h +0 -0
 	return AUDIT_ARCH_X86_64;
 }
 #endif	/* CONFIG_X86_32 */
kernel/seccomp.c +0 -0
index b35c215..bc18214 100644

kernel/seccomp.c static void populate_seccomp_data(struct seccomp_data · line 82

Quoted 10 lines
kernel/seccomp.c +6 -0
@@ -73,6 +73,12 @@ static void populate_seccomp_data(struct seccomp_data
 *sd)
 
 	sd->nr = syscall_get_nr(task, regs);
 	sd->arch = syscall_get_arch();
+#ifdef CONFIG_X86_X32_ABI
+	if (sd->arch == AUDIT_ARCH_X86_X32) {
+		sd->arch = AUDIT_ARCH_X86_64;
+		sd->nr |= __X32_SYSCALL_BIT;
+	}
+#endif

Once again, I'm not really sure I need to comment further here, but don't change syscall_get_nr(), it should return the same syscall number as was used by userspace to initiate the syscall. If you really want to use the new AUDIT_ARCH_X86_X32 macro/define, go ahead, but make sure you rewrite it to the x86-64 value here so as to not break compatibility with existing seccomp filter users.

Signature · 2 lines
paul moore
security and virtualization @ redhat
#20 lore raw

Re: [PATCH 2/3] [RFC] seccomp: give BPF x32 bit when restoring x32 filter

Quoted 4 lines · Paul Moore

Arguably audit is broken anyway by not correctly treating syscall numbers as 32 bit integers like everyone else.

That is really the root cause of the problem. x86 is not the only architecture with a sparse syscall numbering scheme (in fact the x32 method was based on the MIPS syscall numbering scheme.)

What syscall_get_nr() returns becomes a matter of definition at that point.

-hpa

#21 lore raw

RFC PATCH 3/3 Revert "x86: remove the x32 syscall bitmask from syscall_get_nr()"

In reply to Richard Guy Briggs

This reverts commit 8b4b9f27e57584f3d90e0bb84cf800ad81cfe3a1. which broke audit and potentially other users of syscall_get_nr() which depend on that call as named without being overloaded by architecture bits.

This patch along with
seccomp: give BPF x32 bit when restoring x32 filter
will satisfy other regular users of syscall_get_nr() and syscall_get_arch() without changing the seccomp interface to BPF.

---
 arch/x86/include/asm/syscall.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
arch/x86/include/asm/syscall.h +2 -2
index d58b6be..8c1bb2b 100644
@@ -30,13 +30,13 @@ extern const sys_call_ptr_t sys_call_table[];
  */
 static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 {
-	return regs->orig_ax;
+	return regs->orig_ax & __SYSCALL_MASK;
 }
 
 static inline void syscall_rollback(struct task_struct *task,
 				    struct pt_regs *regs)
 {
-	regs->ax = regs->orig_ax;
+	regs->ax = regs->orig_ax & __SYSCALL_MASK;
 }
 
 static inline long syscall_get_error(struct task_struct *task,
Signature · 1 line
1.7.1