LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel
User Name
Password
Linux - Kernel This forum is for all discussion relating to the Linux kernel.

Notices


Reply
  Search this Thread
Old 04-12-2009, 06:30 PM   #1
titan22
LQ Newbie
 
Registered: Apr 2009
Posts: 17

Rep: Reputation: 3
when is CPL changed to 0 when a user program divide by zero exception happens?


Does anyone know when CPL is changed when divide by zero exception happens? Thanks.

divide by zero exception handler can only be accessed when the thread's CPL is 0 because divide_erro is initialized by set_trap_gate(0,&divide_error);

It looks like that user mode is switching to kernel stack at step 5 (below). I assume that is when CPL is set to 0 (kernel mode). The question is how can the user application pass the DPL check at step 4. User application should be still in CPL 3 and fail to pass the divide_error DPL 0 check at step 4?

=== From page 142 Understanding Linux kernel

4. Makes sure the interrupt was issued by an authorized source. First, it compares the Current Privilege Level (CPL), which is stored in the two least significant bits of the cs register, with the Descriptor Privilege Level (DPL ) of the Segment Descriptor included in the GDT. Raises a "General protection " exception if the CPL is lower than the DPL, because the interrupt handler cannot have a lower privilege than the program that caused the interrupt. For programmed exceptions, makes a further security check: compares the CPL with the DPL of the gate descriptor included in the IDT and raises a "General protection" exception if the DPL is lower than the CPL. This last check makes it possible to prevent access by user applications to specific trap or interrupt gates.

--> User application CPL 3. How to use divide_error DPL 0?

5. Checks whether a change of privilege level is taking place that is, if CPL is different from the selected Segment Descriptor's DPL. If so, the control unit must start using the stack that is associated with the new privilege level. It does this by performing the following steps:

a. Reads the tr register to access the TSS segment of the running process.
b. Loads the ss and esp registers with the proper values for the stack segment and stack pointer associated with the new privilege level. These values are found in the TSS (see the section "Task State Segment" in Chapter 3).
c. In the new stack, it saves the previous values of ss and esp, which define the logical address of the stack associated with the old privilege level.

Last edited by titan22; 04-12-2009 at 06:32 PM.
 
Old 04-13-2009, 08:17 AM   #2
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,659
Blog Entries: 4

Rep: Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940
Intel views a divide-by-zero exception as a trap, not an interrupt.

When the interrupt happens, the kernel will switch to a known-good stack in order to save state, because the privilege-level will be different. Then, it prepares to send the notification on to your process in the form of a SIGFPE signal.

So, it's a two-step process: the hardware traps the event and sends it to the kernel; then the kernel sends a signal to your program.

(See: man sigaction.)
 
Old 04-13-2009, 08:54 AM   #3
titan22
LQ Newbie
 
Registered: Apr 2009
Posts: 17

Original Poster
Rep: Reputation: 3
sundialsvcs, Thanks. But you seemed to miss my question.

divide by zero IDT entry is set by set_trap_gate(0,&divide_error) which requires the caller with CPL 0.

However the hardware handling checks caller's CPL privilege (step 4 above) before switching to kernel stack(step 5 above). do_divide_error can only be accessed by caller with the right permission. Otherwise it fails the check without switching to the kennel stack.

The user application thread must have been set to CPL 0 before step 4. If that is the case I don't see the difference of using set_trap_gate(CPL 0 permission) and set_system_gate(CPL 3 permission) because every user thread is granted CPL 0 by the hardware exception(trap) handling.

Last edited by titan22; 04-13-2009 at 09:00 AM.
 
Old 04-14-2009, 01:54 PM   #4
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,659
Blog Entries: 4

Rep: Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940
The CPL difference causes a switch to the kernel stack. It does not disallow the trap: it merely prevents the trap from being handled directly on the user stack.

When a process experiences any sort of error for which the proper kernel response is "to send a signal to the process," the architectural response is always multi-stage:
  • The architecture sends control to the kernel (CPL becomes 0; status is temporarily on kernel stack).
  • The kernel determines that the user process has just received a signal.
  • When the process is redispatched, it is executing the appointed signal handler (or, it has just died).
 
Old 04-14-2009, 03:07 PM   #5
titan22
LQ Newbie
 
Registered: Apr 2009
Posts: 17

Original Poster
Rep: Reputation: 3
That still does not answer my question.

If hardware exceptions switch to CPL 0 and use kernel stack immediately when application trips hardware errors. What are the differences between set_trap_gate(CPL 0 permission) and set_system_gate(CPL 3 permission)?

set_trap_gate(0,&divide_error); CPL 0 permission
set_system_gate(0,&overflow); CPL 3 permission

When a user application hit devide_by_zero or overflow both lead to exception which calls exceptional handler to sends a signal. Both exceptional handler are in __KERNEL_CS. Why would divide_error be initialized with set_trap_gate(0,&divide_error) and overflow with set_system_gate(0,&overflow);

Why wouldn't both overflow and divide_error be initialized with set_trap_gate() or with set_system_gate()? I cannot tell why divide_error needs a higher permission than overflow and I don't know when are these permissions checked.

Last edited by titan22; 04-17-2009 at 09:47 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
I Need a program do try-catch for Exception In Linux? saeedeh1363 Programming 2 09-04-2007 05:49 AM
user@localhost has changed daiver Linux - Networking 6 02-21-2006 01:24 PM
C program to see user log on in system and print user with real user name also naveen245 Programming 2 12-21-2005 12:53 AM
help createing exception class from base STL exception qwijibow Programming 4 04-20-2005 05:23 AM
Check if user has changed PW fenriswolf Linux - Security 3 04-29-2003 09:01 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel

All times are GMT -5. The time now is 07:24 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration