diff mbox

[trusty,SRU] x86-64, modify_ldt: Make support for 16-bit segments a runtime option

Message ID 1402935456-69638-1-git-send-email-tim.gardner@canonical.com
State New
Headers show

Commit Message

Tim Gardner June 16, 2014, 4:17 p.m. UTC
From: Linus Torvalds <torvalds@linux-foundation.org>

BugLink: http://bugs.launchpad.net/bugs/1328965

Checkin:

b3b42ac2cbae x86-64, modify_ldt: Ban 16-bit segments on 64-bit kernels

disabled 16-bit segments on 64-bit kernels due to an information
leak.  However, it does seem that people are genuinely using Wine to
run old 16-bit Windows programs on Linux.

A proper fix for this ("espfix64") is coming in the upcoming merge
window, but as a temporary fix, create a sysctl to allow the
administrator to re-enable support for 16-bit segments.

It adds a "/proc/sys/abi/ldt16" sysctl that defaults to zero (off). If
you hit this issue and care about your old Windows program more than
you care about a kernel stack address information leak, you can do

   echo 1 > /proc/sys/abi/ldt16

as root (add it to your startup scripts), and you should be ok.

The sysctl table is only added if you have COMPAT support enabled on
x86-64, but I assume anybody who runs old windows binaries very much
does that ;)

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Link: http://lkml.kernel.org/r/CA%2B55aFw9BPoD10U1LfHbOMpHWZkvJTkMcfCs9s3urPr1YyWBxw@mail.gmail.com
Cc: <stable@vger.kernel.org>
(cherry picked from commit fa81511bb0bbb2b1aace3695ce869da9762624ff)
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
---
 arch/x86/kernel/ldt.c        | 4 +++-
 arch/x86/vdso/vdso32-setup.c | 8 ++++++++
 2 files changed, 11 insertions(+), 1 deletion(-)

Comments

Chris J Arges June 16, 2014, 4:24 p.m. UTC | #1
Will this patch be superseeded by espfix64 when that lands?
--chris

On 06/16/2014 11:17 AM, Tim Gardner wrote:
> From: Linus Torvalds <torvalds@linux-foundation.org>
> 
> BugLink: http://bugs.launchpad.net/bugs/1328965
> 
> Checkin:
> 
> b3b42ac2cbae x86-64, modify_ldt: Ban 16-bit segments on 64-bit kernels
> 
> disabled 16-bit segments on 64-bit kernels due to an information
> leak.  However, it does seem that people are genuinely using Wine to
> run old 16-bit Windows programs on Linux.
> 
> A proper fix for this ("espfix64") is coming in the upcoming merge
> window, but as a temporary fix, create a sysctl to allow the
> administrator to re-enable support for 16-bit segments.
> 
> It adds a "/proc/sys/abi/ldt16" sysctl that defaults to zero (off). If
> you hit this issue and care about your old Windows program more than
> you care about a kernel stack address information leak, you can do
> 
>    echo 1 > /proc/sys/abi/ldt16
> 
> as root (add it to your startup scripts), and you should be ok.
> 
> The sysctl table is only added if you have COMPAT support enabled on
> x86-64, but I assume anybody who runs old windows binaries very much
> does that ;)
> 
> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
> Link: http://lkml.kernel.org/r/CA%2B55aFw9BPoD10U1LfHbOMpHWZkvJTkMcfCs9s3urPr1YyWBxw@mail.gmail.com
> Cc: <stable@vger.kernel.org>
> (cherry picked from commit fa81511bb0bbb2b1aace3695ce869da9762624ff)
> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
> ---
>  arch/x86/kernel/ldt.c        | 4 +++-
>  arch/x86/vdso/vdso32-setup.c | 8 ++++++++
>  2 files changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
> index af1d14a..dcbbaa1 100644
> --- a/arch/x86/kernel/ldt.c
> +++ b/arch/x86/kernel/ldt.c
> @@ -20,6 +20,8 @@
>  #include <asm/mmu_context.h>
>  #include <asm/syscalls.h>
>  
> +int sysctl_ldt16 = 0;
> +
>  #ifdef CONFIG_SMP
>  static void flush_ldt(void *current_mm)
>  {
> @@ -234,7 +236,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
>  	 * IRET leaking the high bits of the kernel stack address.
>  	 */
>  #ifdef CONFIG_X86_64
> -	if (!ldt_info.seg_32bit) {
> +	if (!ldt_info.seg_32bit && !sysctl_ldt16) {
>  		error = -EINVAL;
>  		goto out_unlock;
>  	}
> diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c
> index d6bfb87..f1d633a 100644
> --- a/arch/x86/vdso/vdso32-setup.c
> +++ b/arch/x86/vdso/vdso32-setup.c
> @@ -41,6 +41,7 @@ enum {
>  #ifdef CONFIG_X86_64
>  #define vdso_enabled			sysctl_vsyscall32
>  #define arch_setup_additional_pages	syscall32_setup_pages
> +extern int sysctl_ldt16;
>  #endif
>  
>  /*
> @@ -380,6 +381,13 @@ static struct ctl_table abi_table2[] = {
>  		.mode		= 0644,
>  		.proc_handler	= proc_dointvec
>  	},
> +	{
> +		.procname	= "ldt16",
> +		.data		= &sysctl_ldt16,
> +		.maxlen		= sizeof(int),
> +		.mode		= 0644,
> +		.proc_handler	= proc_dointvec
> +	},
>  	{}
>  };
>  
>
Tim Gardner June 16, 2014, 5:01 p.m. UTC | #2
You're gonna have to provide a bit more detail 'cause I don't know
anything about espfix64.

rtg

On 06/16/2014 10:24 AM, Chris J Arges wrote:
> Will this patch be superseeded by espfix64 when that lands?
> --chris
> 
> On 06/16/2014 11:17 AM, Tim Gardner wrote:
>> From: Linus Torvalds <torvalds@linux-foundation.org>
>>
>> BugLink: http://bugs.launchpad.net/bugs/1328965
>>
>> Checkin:
>>
>> b3b42ac2cbae x86-64, modify_ldt: Ban 16-bit segments on 64-bit kernels
>>
>> disabled 16-bit segments on 64-bit kernels due to an information
>> leak.  However, it does seem that people are genuinely using Wine to
>> run old 16-bit Windows programs on Linux.
>>
>> A proper fix for this ("espfix64") is coming in the upcoming merge
>> window, but as a temporary fix, create a sysctl to allow the
>> administrator to re-enable support for 16-bit segments.
>>
>> It adds a "/proc/sys/abi/ldt16" sysctl that defaults to zero (off). If
>> you hit this issue and care about your old Windows program more than
>> you care about a kernel stack address information leak, you can do
>>
>>    echo 1 > /proc/sys/abi/ldt16
>>
>> as root (add it to your startup scripts), and you should be ok.
>>
>> The sysctl table is only added if you have COMPAT support enabled on
>> x86-64, but I assume anybody who runs old windows binaries very much
>> does that ;)
>>
>> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
>> Link: http://lkml.kernel.org/r/CA%2B55aFw9BPoD10U1LfHbOMpHWZkvJTkMcfCs9s3urPr1YyWBxw@mail.gmail.com
>> Cc: <stable@vger.kernel.org>
>> (cherry picked from commit fa81511bb0bbb2b1aace3695ce869da9762624ff)
>> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
>> ---
>>  arch/x86/kernel/ldt.c        | 4 +++-
>>  arch/x86/vdso/vdso32-setup.c | 8 ++++++++
>>  2 files changed, 11 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
>> index af1d14a..dcbbaa1 100644
>> --- a/arch/x86/kernel/ldt.c
>> +++ b/arch/x86/kernel/ldt.c
>> @@ -20,6 +20,8 @@
>>  #include <asm/mmu_context.h>
>>  #include <asm/syscalls.h>
>>  
>> +int sysctl_ldt16 = 0;
>> +
>>  #ifdef CONFIG_SMP
>>  static void flush_ldt(void *current_mm)
>>  {
>> @@ -234,7 +236,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
>>  	 * IRET leaking the high bits of the kernel stack address.
>>  	 */
>>  #ifdef CONFIG_X86_64
>> -	if (!ldt_info.seg_32bit) {
>> +	if (!ldt_info.seg_32bit && !sysctl_ldt16) {
>>  		error = -EINVAL;
>>  		goto out_unlock;
>>  	}
>> diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c
>> index d6bfb87..f1d633a 100644
>> --- a/arch/x86/vdso/vdso32-setup.c
>> +++ b/arch/x86/vdso/vdso32-setup.c
>> @@ -41,6 +41,7 @@ enum {
>>  #ifdef CONFIG_X86_64
>>  #define vdso_enabled			sysctl_vsyscall32
>>  #define arch_setup_additional_pages	syscall32_setup_pages
>> +extern int sysctl_ldt16;
>>  #endif
>>  
>>  /*
>> @@ -380,6 +381,13 @@ static struct ctl_table abi_table2[] = {
>>  		.mode		= 0644,
>>  		.proc_handler	= proc_dointvec
>>  	},
>> +	{
>> +		.procname	= "ldt16",
>> +		.data		= &sysctl_ldt16,
>> +		.maxlen		= sizeof(int),
>> +		.mode		= 0644,
>> +		.proc_handler	= proc_dointvec
>> +	},
>>  	{}
>>  };
>>  
>>
Chris J Arges June 16, 2014, 5:26 p.m. UTC | #3
On 06/16/2014 12:01 PM, Tim Gardner wrote:
> You're gonna have to provide a bit more detail 'cause I don't know
> anything about espfix64.
> 
> rtg

From the the commit message:

> A proper fix for this ("espfix64") is coming in the upcoming merge
> window, but as a temporary fix, create a sysctl to allow the
> administrator to re-enable support for 16-bit segments.

Which leads to this:
http://comments.gmane.org/gmane.linux.kernel.commits.head/452742

In addition looking at the thread it looks like this commit potentially
broke something Wine related:
http://marc.info/?l=linux-kernel&m=139990057717709&w=2
I'm not sure how that bug was hit since the default functionality should
not change anything.

--chris

> 
> On 06/16/2014 10:24 AM, Chris J Arges wrote:
>> Will this patch be superseeded by espfix64 when that lands?
>> --chris
>>
>> On 06/16/2014 11:17 AM, Tim Gardner wrote:
>>> From: Linus Torvalds <torvalds@linux-foundation.org>
>>>
>>> BugLink: http://bugs.launchpad.net/bugs/1328965
>>>
>>> Checkin:
>>>
>>> b3b42ac2cbae x86-64, modify_ldt: Ban 16-bit segments on 64-bit kernels
>>>
>>> disabled 16-bit segments on 64-bit kernels due to an information
>>> leak.  However, it does seem that people are genuinely using Wine to
>>> run old 16-bit Windows programs on Linux.
>>>
>>> A proper fix for this ("espfix64") is coming in the upcoming merge
>>> window, but as a temporary fix, create a sysctl to allow the
>>> administrator to re-enable support for 16-bit segments.
>>>
>>> It adds a "/proc/sys/abi/ldt16" sysctl that defaults to zero (off). If
>>> you hit this issue and care about your old Windows program more than
>>> you care about a kernel stack address information leak, you can do
>>>
>>>    echo 1 > /proc/sys/abi/ldt16
>>>
>>> as root (add it to your startup scripts), and you should be ok.
>>>
>>> The sysctl table is only added if you have COMPAT support enabled on
>>> x86-64, but I assume anybody who runs old windows binaries very much
>>> does that ;)
>>>
>>> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
>>> Link: 
>>> Cc: <stable@vger.kernel.org>
>>> (cherry picked from commit fa81511bb0bbb2b1aace3695ce869da9762624ff)
>>> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
>>> ---
>>>  arch/x86/kernel/ldt.c        | 4 +++-
>>>  arch/x86/vdso/vdso32-setup.c | 8 ++++++++
>>>  2 files changed, 11 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
>>> index af1d14a..dcbbaa1 100644
>>> --- a/arch/x86/kernel/ldt.c
>>> +++ b/arch/x86/kernel/ldt.c
>>> @@ -20,6 +20,8 @@
>>>  #include <asm/mmu_context.h>
>>>  #include <asm/syscalls.h>
>>>  
>>> +int sysctl_ldt16 = 0;
>>> +
>>>  #ifdef CONFIG_SMP
>>>  static void flush_ldt(void *current_mm)
>>>  {
>>> @@ -234,7 +236,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
>>>  	 * IRET leaking the high bits of the kernel stack address.
>>>  	 */
>>>  #ifdef CONFIG_X86_64
>>> -	if (!ldt_info.seg_32bit) {
>>> +	if (!ldt_info.seg_32bit && !sysctl_ldt16) {
>>>  		error = -EINVAL;
>>>  		goto out_unlock;
>>>  	}
>>> diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c
>>> index d6bfb87..f1d633a 100644
>>> --- a/arch/x86/vdso/vdso32-setup.c
>>> +++ b/arch/x86/vdso/vdso32-setup.c
>>> @@ -41,6 +41,7 @@ enum {
>>>  #ifdef CONFIG_X86_64
>>>  #define vdso_enabled			sysctl_vsyscall32
>>>  #define arch_setup_additional_pages	syscall32_setup_pages
>>> +extern int sysctl_ldt16;
>>>  #endif
>>>  
>>>  /*
>>> @@ -380,6 +381,13 @@ static struct ctl_table abi_table2[] = {
>>>  		.mode		= 0644,
>>>  		.proc_handler	= proc_dointvec
>>>  	},
>>> +	{
>>> +		.procname	= "ldt16",
>>> +		.data		= &sysctl_ldt16,
>>> +		.maxlen		= sizeof(int),
>>> +		.mode		= 0644,
>>> +		.proc_handler	= proc_dointvec
>>> +	},
>>>  	{}
>>>  };
>>>  
>>>
> 
>
Stefan Bader June 17, 2014, 1:08 p.m. UTC | #4
Basically just adds an interface to re-configure the kernel to the old behaviour
of allowing 16bit segments (with the downside of having a potential information
leak).
From the stable discussion that I remember, running some Windows programs
through wine was one thing that still needed those.
Maybe it can be replaced by the proper fix they promise but then postponing it
till after the merge window re-opens sounds like it could be non-trivial.

-Stefan
Brad Figg June 17, 2014, 2:38 p.m. UTC | #5
On 06/16/2014 09:17 AM, Tim Gardner wrote:
> From: Linus Torvalds <torvalds@linux-foundation.org>
> 
> BugLink: http://bugs.launchpad.net/bugs/1328965
> 
> Checkin:
> 
> b3b42ac2cbae x86-64, modify_ldt: Ban 16-bit segments on 64-bit kernels
> 
> disabled 16-bit segments on 64-bit kernels due to an information
> leak.  However, it does seem that people are genuinely using Wine to
> run old 16-bit Windows programs on Linux.
> 
> A proper fix for this ("espfix64") is coming in the upcoming merge
> window, but as a temporary fix, create a sysctl to allow the
> administrator to re-enable support for 16-bit segments.
> 
> It adds a "/proc/sys/abi/ldt16" sysctl that defaults to zero (off). If
> you hit this issue and care about your old Windows program more than
> you care about a kernel stack address information leak, you can do
> 
>    echo 1 > /proc/sys/abi/ldt16
> 
> as root (add it to your startup scripts), and you should be ok.
> 
> The sysctl table is only added if you have COMPAT support enabled on
> x86-64, but I assume anybody who runs old windows binaries very much
> does that ;)
> 
> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
> Link: http://lkml.kernel.org/r/CA%2B55aFw9BPoD10U1LfHbOMpHWZkvJTkMcfCs9s3urPr1YyWBxw@mail.gmail.com
> Cc: <stable@vger.kernel.org>
> (cherry picked from commit fa81511bb0bbb2b1aace3695ce869da9762624ff)
> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
> ---
>  arch/x86/kernel/ldt.c        | 4 +++-
>  arch/x86/vdso/vdso32-setup.c | 8 ++++++++
>  2 files changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
> index af1d14a..dcbbaa1 100644
> --- a/arch/x86/kernel/ldt.c
> +++ b/arch/x86/kernel/ldt.c
> @@ -20,6 +20,8 @@
>  #include <asm/mmu_context.h>
>  #include <asm/syscalls.h>
>  
> +int sysctl_ldt16 = 0;
> +
>  #ifdef CONFIG_SMP
>  static void flush_ldt(void *current_mm)
>  {
> @@ -234,7 +236,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
>  	 * IRET leaking the high bits of the kernel stack address.
>  	 */
>  #ifdef CONFIG_X86_64
> -	if (!ldt_info.seg_32bit) {
> +	if (!ldt_info.seg_32bit && !sysctl_ldt16) {
>  		error = -EINVAL;
>  		goto out_unlock;
>  	}
> diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c
> index d6bfb87..f1d633a 100644
> --- a/arch/x86/vdso/vdso32-setup.c
> +++ b/arch/x86/vdso/vdso32-setup.c
> @@ -41,6 +41,7 @@ enum {
>  #ifdef CONFIG_X86_64
>  #define vdso_enabled			sysctl_vsyscall32
>  #define arch_setup_additional_pages	syscall32_setup_pages
> +extern int sysctl_ldt16;
>  #endif
>  
>  /*
> @@ -380,6 +381,13 @@ static struct ctl_table abi_table2[] = {
>  		.mode		= 0644,
>  		.proc_handler	= proc_dointvec
>  	},
> +	{
> +		.procname	= "ldt16",
> +		.data		= &sysctl_ldt16,
> +		.maxlen		= sizeof(int),
> +		.mode		= 0644,
> +		.proc_handler	= proc_dointvec
> +	},
>  	{}
>  };
>  
>
Tim Gardner June 17, 2014, 2:51 p.m. UTC | #6
Chris - even if this regresses with some Wine users, it at least
preserves existing behavior since they have to change a sysctl to enable
the functionality.

rtg
diff mbox

Patch

diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index af1d14a..dcbbaa1 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -20,6 +20,8 @@ 
 #include <asm/mmu_context.h>
 #include <asm/syscalls.h>
 
+int sysctl_ldt16 = 0;
+
 #ifdef CONFIG_SMP
 static void flush_ldt(void *current_mm)
 {
@@ -234,7 +236,7 @@  static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
 	 * IRET leaking the high bits of the kernel stack address.
 	 */
 #ifdef CONFIG_X86_64
-	if (!ldt_info.seg_32bit) {
+	if (!ldt_info.seg_32bit && !sysctl_ldt16) {
 		error = -EINVAL;
 		goto out_unlock;
 	}
diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c
index d6bfb87..f1d633a 100644
--- a/arch/x86/vdso/vdso32-setup.c
+++ b/arch/x86/vdso/vdso32-setup.c
@@ -41,6 +41,7 @@  enum {
 #ifdef CONFIG_X86_64
 #define vdso_enabled			sysctl_vsyscall32
 #define arch_setup_additional_pages	syscall32_setup_pages
+extern int sysctl_ldt16;
 #endif
 
 /*
@@ -380,6 +381,13 @@  static struct ctl_table abi_table2[] = {
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec
 	},
+	{
+		.procname	= "ldt16",
+		.data		= &sysctl_ldt16,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec
+	},
 	{}
 };