Skip to content

Commit

Permalink
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
Browse files Browse the repository at this point in the history
  • Loading branch information
Steve French committed Jul 16, 2009
2 parents 65bc98b + 35b5c55 commit f6c4338
Show file tree
Hide file tree
Showing 519 changed files with 6,250 additions and 5,845 deletions.
4 changes: 2 additions & 2 deletions Documentation/driver-model/driver.txt
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,8 @@ Attributes
~~~~~~~~~~
struct driver_attribute {
struct attribute attr;
ssize_t (*show)(struct device_driver *, char * buf, size_t count, loff_t off);
ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off);
ssize_t (*show)(struct device_driver *driver, char *buf);
ssize_t (*store)(struct device_driver *, const char * buf, size_t count);
};

Device drivers can export attributes via their sysfs directories.
Expand Down
4 changes: 2 additions & 2 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1720,8 +1720,8 @@ and is between 256 and 4096 characters. It is defined in the file
oprofile.cpu_type= Force an oprofile cpu type
This might be useful if you have an older oprofile
userland or if you want common events.
Format: { archperfmon }
archperfmon: [X86] Force use of architectural
Format: { arch_perfmon }
arch_perfmon: [X86] Force use of architectural
perfmon on Intel CPUs instead of the
CPU specific event set.

Expand Down
2 changes: 2 additions & 0 deletions Documentation/x86/00-INDEX
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
- this file
mtrr.txt
- how to use x86 Memory Type Range Registers to increase performance
exception-tables.txt
- why and how Linux kernel uses exception tables on x86
202 changes: 101 additions & 101 deletions Documentation/exception.txt → Documentation/x86/exception-tables.txt
Original file line number Diff line number Diff line change
@@ -1,123 +1,123 @@
Kernel level exception handling in Linux 2.1.8
Kernel level exception handling in Linux
Commentary by Joerg Pommnitz <joerg@raleigh.ibm.com>

When a process runs in kernel mode, it often has to access user
mode memory whose address has been passed by an untrusted program.
When a process runs in kernel mode, it often has to access user
mode memory whose address has been passed by an untrusted program.
To protect itself the kernel has to verify this address.

In older versions of Linux this was done with the
int verify_area(int type, const void * addr, unsigned long size)
In older versions of Linux this was done with the
int verify_area(int type, const void * addr, unsigned long size)
function (which has since been replaced by access_ok()).

This function verified that the memory area starting at address
This function verified that the memory area starting at address
'addr' and of size 'size' was accessible for the operation specified
in type (read or write). To do this, verify_read had to look up the
virtual memory area (vma) that contained the address addr. In the
normal case (correctly working program), this test was successful.
in type (read or write). To do this, verify_read had to look up the
virtual memory area (vma) that contained the address addr. In the
normal case (correctly working program), this test was successful.
It only failed for a few buggy programs. In some kernel profiling
tests, this normally unneeded verification used up a considerable
amount of time.

To overcome this situation, Linus decided to let the virtual memory
To overcome this situation, Linus decided to let the virtual memory
hardware present in every Linux-capable CPU handle this test.

How does this work?

Whenever the kernel tries to access an address that is currently not
accessible, the CPU generates a page fault exception and calls the
page fault handler
Whenever the kernel tries to access an address that is currently not
accessible, the CPU generates a page fault exception and calls the
page fault handler

void do_page_fault(struct pt_regs *regs, unsigned long error_code)

in arch/i386/mm/fault.c. The parameters on the stack are set up by
the low level assembly glue in arch/i386/kernel/entry.S. The parameter
regs is a pointer to the saved registers on the stack, error_code
in arch/x86/mm/fault.c. The parameters on the stack are set up by
the low level assembly glue in arch/x86/kernel/entry_32.S. The parameter
regs is a pointer to the saved registers on the stack, error_code
contains a reason code for the exception.

do_page_fault first obtains the unaccessible address from the CPU
control register CR2. If the address is within the virtual address
space of the process, the fault probably occurred, because the page
was not swapped in, write protected or something similar. However,
we are interested in the other case: the address is not valid, there
is no vma that contains this address. In this case, the kernel jumps
to the bad_area label.

There it uses the address of the instruction that caused the exception
(i.e. regs->eip) to find an address where the execution can continue
(fixup). If this search is successful, the fault handler modifies the
return address (again regs->eip) and returns. The execution will
do_page_fault first obtains the unaccessible address from the CPU
control register CR2. If the address is within the virtual address
space of the process, the fault probably occurred, because the page
was not swapped in, write protected or something similar. However,
we are interested in the other case: the address is not valid, there
is no vma that contains this address. In this case, the kernel jumps
to the bad_area label.

There it uses the address of the instruction that caused the exception
(i.e. regs->eip) to find an address where the execution can continue
(fixup). If this search is successful, the fault handler modifies the
return address (again regs->eip) and returns. The execution will
continue at the address in fixup.

Where does fixup point to?

Since we jump to the contents of fixup, fixup obviously points
to executable code. This code is hidden inside the user access macros.
I have picked the get_user macro defined in include/asm/uaccess.h as an
example. The definition is somewhat hard to follow, so let's peek at
Since we jump to the contents of fixup, fixup obviously points
to executable code. This code is hidden inside the user access macros.
I have picked the get_user macro defined in arch/x86/include/asm/uaccess.h
as an example. The definition is somewhat hard to follow, so let's peek at
the code generated by the preprocessor and the compiler. I selected
the get_user call in drivers/char/console.c for a detailed examination.
the get_user call in drivers/char/sysrq.c for a detailed examination.

The original code in console.c line 1405:
The original code in sysrq.c line 587:
get_user(c, buf);

The preprocessor output (edited to become somewhat readable):

(
{
long __gu_err = - 14 , __gu_val = 0;
const __typeof__(*( ( buf ) )) *__gu_addr = ((buf));
if (((((0 + current_set[0])->tss.segment) == 0x18 ) ||
(((sizeof(*(buf))) <= 0xC0000000UL) &&
((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf)))))))
{
long __gu_err = - 14 , __gu_val = 0;
const __typeof__(*( ( buf ) )) *__gu_addr = ((buf));
if (((((0 + current_set[0])->tss.segment) == 0x18 ) ||
(((sizeof(*(buf))) <= 0xC0000000UL) &&
((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf)))))))
do {
__gu_err = 0;
switch ((sizeof(*(buf)))) {
case 1:
__asm__ __volatile__(
"1: mov" "b" " %2,%" "b" "1\n"
"2:\n"
".section .fixup,\"ax\"\n"
"3: movl %3,%0\n"
" xor" "b" " %" "b" "1,%" "b" "1\n"
" jmp 2b\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,3b\n"
__gu_err = 0;
switch ((sizeof(*(buf)))) {
case 1:
__asm__ __volatile__(
"1: mov" "b" " %2,%" "b" "1\n"
"2:\n"
".section .fixup,\"ax\"\n"
"3: movl %3,%0\n"
" xor" "b" " %" "b" "1,%" "b" "1\n"
" jmp 2b\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,3b\n"
".text" : "=r"(__gu_err), "=q" (__gu_val): "m"((*(struct __large_struct *)
( __gu_addr )) ), "i"(- 14 ), "0"( __gu_err )) ;
break;
case 2:
( __gu_addr )) ), "i"(- 14 ), "0"( __gu_err )) ;
break;
case 2:
__asm__ __volatile__(
"1: mov" "w" " %2,%" "w" "1\n"
"2:\n"
".section .fixup,\"ax\"\n"
"3: movl %3,%0\n"
" xor" "w" " %" "w" "1,%" "w" "1\n"
" jmp 2b\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,3b\n"
"1: mov" "w" " %2,%" "w" "1\n"
"2:\n"
".section .fixup,\"ax\"\n"
"3: movl %3,%0\n"
" xor" "w" " %" "w" "1,%" "w" "1\n"
" jmp 2b\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,3b\n"
".text" : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
( __gu_addr )) ), "i"(- 14 ), "0"( __gu_err ));
break;
case 4:
__asm__ __volatile__(
"1: mov" "l" " %2,%" "" "1\n"
"2:\n"
".section .fixup,\"ax\"\n"
"3: movl %3,%0\n"
" xor" "l" " %" "" "1,%" "" "1\n"
" jmp 2b\n"
".section __ex_table,\"a\"\n"
" .align 4\n" " .long 1b,3b\n"
( __gu_addr )) ), "i"(- 14 ), "0"( __gu_err ));
break;
case 4:
__asm__ __volatile__(
"1: mov" "l" " %2,%" "" "1\n"
"2:\n"
".section .fixup,\"ax\"\n"
"3: movl %3,%0\n"
" xor" "l" " %" "" "1,%" "" "1\n"
" jmp 2b\n"
".section __ex_table,\"a\"\n"
" .align 4\n" " .long 1b,3b\n"
".text" : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
( __gu_addr )) ), "i"(- 14 ), "0"(__gu_err));
break;
default:
(__gu_val) = __get_user_bad();
}
} while (0) ;
((c)) = (__typeof__(*((buf))))__gu_val;
( __gu_addr )) ), "i"(- 14 ), "0"(__gu_err));
break;
default:
(__gu_val) = __get_user_bad();
}
} while (0) ;
((c)) = (__typeof__(*((buf))))__gu_val;
__gu_err;
}
);
Expand All @@ -127,12 +127,12 @@ see what code gcc generates:

> xorl %edx,%edx
> movl current_set,%eax
> cmpl $24,788(%eax)
> je .L1424
> cmpl $24,788(%eax)
> je .L1424
> cmpl $-1073741825,64(%esp)
> ja .L1423
> ja .L1423
> .L1424:
> movl %edx,%eax
> movl %edx,%eax
> movl 64(%esp),%ebx
> #APP
> 1: movb (%ebx),%dl /* this is the actual user access */
Expand All @@ -149,17 +149,17 @@ see what code gcc generates:
> .L1423:
> movzbl %dl,%esi

The optimizer does a good job and gives us something we can actually
understand. Can we? The actual user access is quite obvious. Thanks
to the unified address space we can just access the address in user
The optimizer does a good job and gives us something we can actually
understand. Can we? The actual user access is quite obvious. Thanks
to the unified address space we can just access the address in user
memory. But what does the .section stuff do?????

To understand this we have to look at the final kernel:

> objdump --section-headers vmlinux
>
>
> vmlinux: file format elf32-i386
>
>
> Sections:
> Idx Name Size VMA LMA File off Algn
> 0 .text 00098f40 c0100000 c0100000 00001000 2**4
Expand Down Expand Up @@ -198,18 +198,18 @@ final kernel executable:

The whole user memory access is reduced to 10 x86 machine instructions.
The instructions bracketed in the .section directives are no longer
in the normal execution path. They are located in a different section
in the normal execution path. They are located in a different section
of the executable file:

> objdump --disassemble --section=.fixup vmlinux
>
>
> c0199ff5 <.fixup+10b5> movl $0xfffffff2,%eax
> c0199ffa <.fixup+10ba> xorb %dl,%dl
> c0199ffc <.fixup+10bc> jmp c017e7a7 <do_con_write+e3>

And finally:
> objdump --full-contents --section=__ex_table vmlinux
>
>
> c01aa7c4 93c017c0 e09f19c0 97c017c0 99c017c0 ................
> c01aa7d4 f6c217c0 e99f19c0 a5e717c0 f59f19c0 ................
> c01aa7e4 080a18c0 01a019c0 0a0a18c0 04a019c0 ................
Expand All @@ -235,8 +235,8 @@ sections in the ELF object file. So the instructions
ended up in the .fixup section of the object file and the addresses
.long 1b,3b
ended up in the __ex_table section of the object file. 1b and 3b
are local labels. The local label 1b (1b stands for next label 1
backward) is the address of the instruction that might fault, i.e.
are local labels. The local label 1b (1b stands for next label 1
backward) is the address of the instruction that might fault, i.e.
in our case the address of the label 1 is c017e7a5:
the original assembly code: > 1: movb (%ebx),%dl
and linked in vmlinux : > c017e7a5 <do_con_write+e1> movb (%ebx),%dl
Expand All @@ -254,7 +254,7 @@ The assembly code
becomes the value pair
> c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5 ................
^this is ^this is
1b 3b
1b 3b
c017e7a5,c0199ff5 in the exception table of the kernel.

So, what actually happens if a fault from kernel mode with no suitable
Expand All @@ -266,9 +266,9 @@ vma occurs?
3.) CPU calls do_page_fault
4.) do page fault calls search_exception_table (regs->eip == c017e7a5);
5.) search_exception_table looks up the address c017e7a5 in the
exception table (i.e. the contents of the ELF section __ex_table)
exception table (i.e. the contents of the ELF section __ex_table)
and returns the address of the associated fault handle code c0199ff5.
6.) do_page_fault modifies its own return address to point to the fault
6.) do_page_fault modifies its own return address to point to the fault
handle code and returns.
7.) execution continues in the fault handling code.
8.) 8a) EAX becomes -EFAULT (== -14)
Expand Down
11 changes: 7 additions & 4 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -3287,11 +3287,11 @@ F: include/linux/ivtv*

JFS FILESYSTEM
P: Dave Kleikamp
M: shaggy@austin.ibm.com
M: shaggy@linux.vnet.ibm.com
L: jfs-discussion@lists.sourceforge.net
W: http://jfs.sourceforge.net/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git
S: Supported
S: Maintained
F: Documentation/filesystems/jfs.txt
F: fs/jfs/

Expand Down Expand Up @@ -4407,7 +4407,7 @@ W: http://www.nongnu.org/orinoco/
S: Maintained
F: drivers/net/wireless/orinoco/

OSD LIBRARY
OSD LIBRARY and FILESYSTEM
P: Boaz Harrosh
M: bharrosh@panasas.com
P: Benny Halevy
Expand All @@ -4416,6 +4416,9 @@ L: osd-dev@open-osd.org
W: http://open-osd.org
T: git git://git.open-osd.org/open-osd.git
S: Maintained
F: drivers/scsi/osd/
F: drivers/include/scsi/osd_*
F: fs/exofs/

P54 WIRELESS DRIVER
P: Michael Wu
Expand Down Expand Up @@ -5851,7 +5854,7 @@ UBI FILE SYSTEM (UBIFS)
P: Artem Bityutskiy
M: dedekind@infradead.org
P: Adrian Hunter
M: ext-adrian.hunter@nokia.com
M: adrian.hunter@nokia.com
L: linux-mtd@lists.infradead.org
T: git git://git.infradead.org/ubifs-2.6.git
W: http://www.linux-mtd.infradead.org/doc/ubifs.html
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 31
EXTRAVERSION = -rc2
EXTRAVERSION = -rc3
NAME = Man-Eating Seals of Antiquity

# *DOCUMENTATION*
Expand Down Expand Up @@ -565,7 +565,7 @@ KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,)

# disable invalid "can't wrap" optimizations for signed / pointers
KBUILD_CFLAGS += $(call cc-option,-fwrapv)
KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)

# revert to pre-gcc-4.4 behaviour of .eh_frame
KBUILD_CFLAGS += $(call cc-option,-fno-dwarf2-cfi-asm)
Expand Down
1 change: 1 addition & 0 deletions arch/alpha/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ struct thread_info {
.task = &tsk, \
.exec_domain = &default_exec_domain, \
.addr_limit = KERNEL_DS, \
.preempt_count = INIT_PREEMPT_COUNT, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
Expand Down
Loading

0 comments on commit f6c4338

Please sign in to comment.