From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754761AbYK1L34 (ORCPT ); Fri, 28 Nov 2008 06:29:56 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752343AbYK1L3s (ORCPT ); Fri, 28 Nov 2008 06:29:48 -0500 Received: from mx3.mail.elte.hu ([157.181.1.138]:36823 "EHLO mx3.mail.elte.hu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752234AbYK1L3r (ORCPT ); Fri, 28 Nov 2008 06:29:47 -0500 Date: Fri, 28 Nov 2008 12:29:34 +0100 From: Ingo Molnar To: Vegard Nossum Cc: Pekka Enberg , Eugene Teo , Linux Kernel Mailing List Subject: Re: [RFC] kmemcheck: TODO for stack tracking Message-ID: <20081128112934.GA18333@elte.hu> References: <19f34abd0811280316y13dd8dfcm3cf77b6b2171612b@mail.gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <19f34abd0811280316y13dd8dfcm3cf77b6b2171612b@mail.gmail.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-ELTE-VirusStatus: clean X-ELTE-SpamScore: -1.5 X-ELTE-SpamLevel: X-ELTE-SpamCheck: no X-ELTE-SpamVersion: ELTE 2.0 X-ELTE-SpamCheck-Details: score=-1.5 required=5.9 tests=BAYES_00 autolearn=no SpamAssassin version=3.2.3 -1.5 BAYES_00 BODY: Bayesian spam probability is 0 to 1% [score: 0.0000] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org * Vegard Nossum wrote: > Hi, > > Here's a plan for how to do stack tracking with kmemcheck. It is not > entirely trivial, but as far as I can see, it SHOULD be possible. > Please let me know if you can spot any fallacies or other problems. > I've probably missed something... > > /* > * TODO for stack tracking in kmemcheck: > * > * 1. Make kernel run at CPL = 1 > * > * This includes (I guess) changing the various privilege levels in most > * system descriptors and descriptor tables, and probably the IOPL. Are there > * any CPU features which always require CPL = 0 to work? Paging requires no > * change, as the U/S flag distinguishes between CPL = 0, 1, 2 and CPL = 3 > * only. hm, a ton of instructions need ring-0/supervisor privilege. OTOH, the 32-bit Xen hypervisor runs the guest kernel on ring 1 so all these places are abstracted out to a fair degree already via paravirt_ops. > * > * 2. Modify TSS to use separate stacks for CPL = 0 and CPL = 1 > * 3. Install a Call Gate for Page Faults in the GDT with DPL = 0 > * 4. Change IDT entry for #PF to point to Call Gate in GDT > * > * Now when a #PF occurs in kernel mode, CPU will look up the IDT entry for > * #PF. It points to our Call Gate in the GDT, which has a different privilege > * level, so the CPU will look up the new stack to use in the TSS. In the new > * stack, SS, ESP, CS, and EIP are saved. Note: page_fault() will have to take > * care of handling the extra SS/ESP parameters. End of note. Observe that the > * old stack has not been touched by the CPU at all (this would lead to a #DF, > * Double Fault, which is irrecoverable). Observe also that none of the > * interrupted task's registers have been modified. Now the CPU transfers > * control to page_fault(), which must save all registers, etc. as usual. > * > * do_page_fault() must NOT be allowed to enable interrupts, otherwise we > * could take interrupts that would use the new stack. If the interrupt > * handler takes another page fault, the CPU will already be in CPL = 0 and no > * stack switch will occur! > * > * I think we need to make the kernel switch stacks on ALL interrupts. When > * the CPU is interrupted, it will attempt to push CS/EIP on the current > * stack. If the PTE of the current stack is non-present, a Page Fault will be > * generated (not a Double Fault!). However, we have no way to tell if the #PF > * was generated by an interrupt. > * > * 5. Implement support for PUSHA/POPA instruction handling in kmemcheck. No > * extra support will be needed for IRET, as interrupts must not be allowed > * to occur when the stack is located in a non-present page. > * > * Note that it is possible to track POPF/IRET instructions (even though they > * modify EFLAGS and the Trap Flag), because the CPU does the right thing and > * raises the Debug Exception based on the previous setting of TF. > * > * 6. The kernel stack tracer would need to be modified to understand stack > * changes/boundaries. > */ Sounds like a lot of work. I'm wondering, how about a non-fault-driven approach: for example the function tracer could be modified to poison stack frames as we return from a function, and it could also check the poison value when we enter a function call. This is a high-overhead approach too - but ftrace could be modified to provide a stack frame size parameter so it would only involve the stack frame that is entered/exited. This would not have the same quality as kmemcheck, but would cover the common cases to a fair degree. (and would also be fairly false-positive-safe) Hm? Ingo