Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=66fa9b107e259d01929fe647796b3021d3a83c4a
Commit:     66fa9b107e259d01929fe647796b3021d3a83c4a
Parent:     9be26f4c4b138c425598bd3cc50411bd87fce287
Author:     Keith Owens <[EMAIL PROTECTED]>
AuthorDate: Tue Jun 26 16:25:22 2007 +1000
Committer:  Tony Luck <[EMAIL PROTECTED]>
CommitDate: Tue Jun 26 13:33:10 2007 -0700

    [IA64] Correct unwind validation code
    
    Both rp_loc and pfs_loc can be in the register stack area _or_ they can
    be in the memory stack area, the latter occurs when a struct pt_regs is
    pushed.  Correct the validation check on these fields to check for both
    stack areas.  Not allowing for memory stack locations means no
    backtrace past ia64_leave_kernel, or any other code that uses
    PT_REGS_UNWIND_INFO.
    
    Signed-off-by: Keith Owens <[EMAIL PROTECTED]>
    Signed-off-by: Tony Luck <[EMAIL PROTECTED]>
---
 arch/ia64/kernel/unwind.c |   16 +++++++++++-----
 1 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index b0b08b5..c1bdb51 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -1856,11 +1856,19 @@ find_save_locs (struct unw_frame_info *info)
        return 0;
 }
 
+static int
+unw_valid(const struct unw_frame_info *info, unsigned long* p)
+{
+       unsigned long loc = (unsigned long)p;
+       return (loc >= info->regstk.limit && loc < info->regstk.top) ||
+              (loc >= info->memstk.top && loc < info->memstk.limit);
+}
+
 int
 unw_unwind (struct unw_frame_info *info)
 {
        unsigned long prev_ip, prev_sp, prev_bsp;
-       unsigned long ip, pr, num_regs, rp_loc, pfs_loc;
+       unsigned long ip, pr, num_regs;
        STAT(unsigned long start, flags;)
        int retval;
 
@@ -1871,8 +1879,7 @@ unw_unwind (struct unw_frame_info *info)
        prev_bsp = info->bsp;
 
        /* validate the return IP pointer */
-       rp_loc = (unsigned long) info->rp_loc;
-       if ((rp_loc < info->regstk.limit) || (rp_loc > info->regstk.top)) {
+       if (!unw_valid(info, info->rp_loc)) {
                /* FIXME: should really be level 0 but it occurs too often. KAO 
*/
                UNW_DPRINT(1, "unwind.%s: failed to locate return link 
(ip=0x%lx)!\n",
                           __FUNCTION__, info->ip);
@@ -1888,8 +1895,7 @@ unw_unwind (struct unw_frame_info *info)
        }
 
        /* validate the previous stack frame pointer */
-       pfs_loc = (unsigned long) info->pfs_loc;
-       if ((pfs_loc < info->regstk.limit) || (pfs_loc > info->regstk.top)) {
+       if (!unw_valid(info, info->pfs_loc)) {
                UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", 
__FUNCTION__);
                STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; 
local_irq_restore(flags));
                return -1;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to