Skip to content

Commit 8fc984a

Browse files
committed
Merge tag 'x86-urgent-2020-05-31' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Thomas Gleixner: "A pile of x86 fixes: - Prevent a memory leak in ioperm which was caused by the stupid assumption that the exit cleanup is always called for current, which is not the case when fork fails after taking a reference on the ioperm bitmap. - Fix an arithmething overflow in the DMA code on 32bit systems - Fill gaps in the xstate copy with defaults instead of leaving them uninitialized - Revert: "Make __X32_SYSCALL_BIT be unsigned long" as it turned out that existing user space fails to build" * tag 'x86-urgent-2020-05-31' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/ioperm: Prevent a memory leak when fork fails x86/dma: Fix max PFN arithmetic overflow on 32 bit systems copy_xstate_to_kernel(): don't leave parts of destination uninitialized x86/syscalls: Revert "x86/syscalls: Make __X32_SYSCALL_BIT be unsigned long"
2 parents 3d04282 + aa61b7b commit 8fc984a

File tree

7 files changed

+74
-57
lines changed

7 files changed

+74
-57
lines changed

arch/x86/include/asm/dma.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
#define MAX_DMA_PFN ((16UL * 1024 * 1024) >> PAGE_SHIFT)
7575

7676
/* 4GB broken PCI/AGP hardware bus master zone */
77-
#define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT)
77+
#define MAX_DMA32_PFN (1UL << (32 - PAGE_SHIFT))
7878

7979
#ifdef CONFIG_X86_32
8080
/* The maximum address that we can perform a DMA transfer to on this platform */

arch/x86/include/asm/io_bitmap.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ struct task_struct;
1717

1818
#ifdef CONFIG_X86_IOPL_IOPERM
1919
void io_bitmap_share(struct task_struct *tsk);
20-
void io_bitmap_exit(void);
20+
void io_bitmap_exit(struct task_struct *tsk);
2121

2222
void native_tss_update_io_bitmap(void);
2323

@@ -29,7 +29,7 @@ void native_tss_update_io_bitmap(void);
2929

3030
#else
3131
static inline void io_bitmap_share(struct task_struct *tsk) { }
32-
static inline void io_bitmap_exit(void) { }
32+
static inline void io_bitmap_exit(struct task_struct *tsk) { }
3333
static inline void tss_update_io_bitmap(void) { }
3434
#endif
3535

arch/x86/include/uapi/asm/unistd.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,15 @@
22
#ifndef _UAPI_ASM_X86_UNISTD_H
33
#define _UAPI_ASM_X86_UNISTD_H
44

5-
/* x32 syscall flag bit */
6-
#define __X32_SYSCALL_BIT 0x40000000UL
5+
/*
6+
* x32 syscall flag bit. Some user programs expect syscall NR macros
7+
* and __X32_SYSCALL_BIT to have type int, even though syscall numbers
8+
* are, for practical purposes, unsigned long.
9+
*
10+
* Fortunately, expressions like (nr & ~__X32_SYSCALL_BIT) do the right
11+
* thing regardless.
12+
*/
13+
#define __X32_SYSCALL_BIT 0x40000000
714

815
#ifndef __KERNEL__
916
# ifdef __i386__

arch/x86/kernel/fpu/xstate.c

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -957,18 +957,31 @@ static inline bool xfeatures_mxcsr_quirk(u64 xfeatures)
957957
return true;
958958
}
959959

960-
/*
961-
* This is similar to user_regset_copyout(), but will not add offset to
962-
* the source data pointer or increment pos, count, kbuf, and ubuf.
963-
*/
964-
static inline void
965-
__copy_xstate_to_kernel(void *kbuf, const void *data,
966-
unsigned int offset, unsigned int size, unsigned int size_total)
960+
static void fill_gap(unsigned to, void **kbuf, unsigned *pos, unsigned *count)
967961
{
968-
if (offset < size_total) {
969-
unsigned int copy = min(size, size_total - offset);
962+
if (*pos < to) {
963+
unsigned size = to - *pos;
964+
965+
if (size > *count)
966+
size = *count;
967+
memcpy(*kbuf, (void *)&init_fpstate.xsave + *pos, size);
968+
*kbuf += size;
969+
*pos += size;
970+
*count -= size;
971+
}
972+
}
970973

971-
memcpy(kbuf + offset, data, copy);
974+
static void copy_part(unsigned offset, unsigned size, void *from,
975+
void **kbuf, unsigned *pos, unsigned *count)
976+
{
977+
fill_gap(offset, kbuf, pos, count);
978+
if (size > *count)
979+
size = *count;
980+
if (size) {
981+
memcpy(*kbuf, from, size);
982+
*kbuf += size;
983+
*pos += size;
984+
*count -= size;
972985
}
973986
}
974987

@@ -981,8 +994,9 @@ __copy_xstate_to_kernel(void *kbuf, const void *data,
981994
*/
982995
int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int offset_start, unsigned int size_total)
983996
{
984-
unsigned int offset, size;
985997
struct xstate_header header;
998+
const unsigned off_mxcsr = offsetof(struct fxregs_state, mxcsr);
999+
unsigned count = size_total;
9861000
int i;
9871001

9881002
/*
@@ -998,46 +1012,42 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
9981012
header.xfeatures = xsave->header.xfeatures;
9991013
header.xfeatures &= ~XFEATURE_MASK_SUPERVISOR;
10001014

1015+
if (header.xfeatures & XFEATURE_MASK_FP)
1016+
copy_part(0, off_mxcsr,
1017+
&xsave->i387, &kbuf, &offset_start, &count);
1018+
if (header.xfeatures & (XFEATURE_MASK_SSE | XFEATURE_MASK_YMM))
1019+
copy_part(off_mxcsr, MXCSR_AND_FLAGS_SIZE,
1020+
&xsave->i387.mxcsr, &kbuf, &offset_start, &count);
1021+
if (header.xfeatures & XFEATURE_MASK_FP)
1022+
copy_part(offsetof(struct fxregs_state, st_space), 128,
1023+
&xsave->i387.st_space, &kbuf, &offset_start, &count);
1024+
if (header.xfeatures & XFEATURE_MASK_SSE)
1025+
copy_part(xstate_offsets[XFEATURE_MASK_SSE], 256,
1026+
&xsave->i387.xmm_space, &kbuf, &offset_start, &count);
1027+
/*
1028+
* Fill xsave->i387.sw_reserved value for ptrace frame:
1029+
*/
1030+
copy_part(offsetof(struct fxregs_state, sw_reserved), 48,
1031+
xstate_fx_sw_bytes, &kbuf, &offset_start, &count);
10011032
/*
10021033
* Copy xregs_state->header:
10031034
*/
1004-
offset = offsetof(struct xregs_state, header);
1005-
size = sizeof(header);
1006-
1007-
__copy_xstate_to_kernel(kbuf, &header, offset, size, size_total);
1035+
copy_part(offsetof(struct xregs_state, header), sizeof(header),
1036+
&header, &kbuf, &offset_start, &count);
10081037

1009-
for (i = 0; i < XFEATURE_MAX; i++) {
1038+
for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) {
10101039
/*
10111040
* Copy only in-use xstates:
10121041
*/
10131042
if ((header.xfeatures >> i) & 1) {
10141043
void *src = __raw_xsave_addr(xsave, i);
10151044

1016-
offset = xstate_offsets[i];
1017-
size = xstate_sizes[i];
1018-
1019-
/* The next component has to fit fully into the output buffer: */
1020-
if (offset + size > size_total)
1021-
break;
1022-
1023-
__copy_xstate_to_kernel(kbuf, src, offset, size, size_total);
1045+
copy_part(xstate_offsets[i], xstate_sizes[i],
1046+
src, &kbuf, &offset_start, &count);
10241047
}
10251048

10261049
}
1027-
1028-
if (xfeatures_mxcsr_quirk(header.xfeatures)) {
1029-
offset = offsetof(struct fxregs_state, mxcsr);
1030-
size = MXCSR_AND_FLAGS_SIZE;
1031-
__copy_xstate_to_kernel(kbuf, &xsave->i387.mxcsr, offset, size, size_total);
1032-
}
1033-
1034-
/*
1035-
* Fill xsave->i387.sw_reserved value for ptrace frame:
1036-
*/
1037-
offset = offsetof(struct fxregs_state, sw_reserved);
1038-
size = sizeof(xstate_fx_sw_bytes);
1039-
1040-
__copy_xstate_to_kernel(kbuf, xstate_fx_sw_bytes, offset, size, size_total);
1050+
fill_gap(size_total, &kbuf, &offset_start, &count);
10411051

10421052
return 0;
10431053
}

arch/x86/kernel/ioport.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,28 @@ void io_bitmap_share(struct task_struct *tsk)
3333
set_tsk_thread_flag(tsk, TIF_IO_BITMAP);
3434
}
3535

36-
static void task_update_io_bitmap(void)
36+
static void task_update_io_bitmap(struct task_struct *tsk)
3737
{
38-
struct thread_struct *t = &current->thread;
38+
struct thread_struct *t = &tsk->thread;
3939

4040
if (t->iopl_emul == 3 || t->io_bitmap) {
4141
/* TSS update is handled on exit to user space */
42-
set_thread_flag(TIF_IO_BITMAP);
42+
set_tsk_thread_flag(tsk, TIF_IO_BITMAP);
4343
} else {
44-
clear_thread_flag(TIF_IO_BITMAP);
44+
clear_tsk_thread_flag(tsk, TIF_IO_BITMAP);
4545
/* Invalidate TSS */
4646
preempt_disable();
4747
tss_update_io_bitmap();
4848
preempt_enable();
4949
}
5050
}
5151

52-
void io_bitmap_exit(void)
52+
void io_bitmap_exit(struct task_struct *tsk)
5353
{
54-
struct io_bitmap *iobm = current->thread.io_bitmap;
54+
struct io_bitmap *iobm = tsk->thread.io_bitmap;
5555

56-
current->thread.io_bitmap = NULL;
57-
task_update_io_bitmap();
56+
tsk->thread.io_bitmap = NULL;
57+
task_update_io_bitmap(tsk);
5858
if (iobm && refcount_dec_and_test(&iobm->refcnt))
5959
kfree(iobm);
6060
}
@@ -102,7 +102,7 @@ long ksys_ioperm(unsigned long from, unsigned long num, int turn_on)
102102
if (!iobm)
103103
return -ENOMEM;
104104
refcount_set(&iobm->refcnt, 1);
105-
io_bitmap_exit();
105+
io_bitmap_exit(current);
106106
}
107107

108108
/*
@@ -134,7 +134,7 @@ long ksys_ioperm(unsigned long from, unsigned long num, int turn_on)
134134
}
135135
/* All permissions dropped? */
136136
if (max_long == UINT_MAX) {
137-
io_bitmap_exit();
137+
io_bitmap_exit(current);
138138
return 0;
139139
}
140140

@@ -192,7 +192,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
192192
}
193193

194194
t->iopl_emul = level;
195-
task_update_io_bitmap();
195+
task_update_io_bitmap(current);
196196

197197
return 0;
198198
}

arch/x86/kernel/process.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,15 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
9696
}
9797

9898
/*
99-
* Free current thread data structures etc..
99+
* Free thread data structures etc..
100100
*/
101101
void exit_thread(struct task_struct *tsk)
102102
{
103103
struct thread_struct *t = &tsk->thread;
104104
struct fpu *fpu = &t->fpu;
105105

106106
if (test_thread_flag(TIF_IO_BITMAP))
107-
io_bitmap_exit();
107+
io_bitmap_exit(tsk);
108108

109109
free_vm86(t);
110110

tools/arch/x86/include/uapi/asm/unistd.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#define _UAPI_ASM_X86_UNISTD_H
44

55
/* x32 syscall flag bit */
6-
#define __X32_SYSCALL_BIT 0x40000000UL
6+
#define __X32_SYSCALL_BIT 0x40000000
77

88
#ifndef __KERNEL__
99
# ifdef __i386__

0 commit comments

Comments
 (0)