Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e2e6fe7b authored by Robin Holt's avatar Robin Holt Committed by Tony Luck
Browse files

[IA64] Improve unwind checking.



This patch adds some sanity checks to keep register and memory stack
pointers in the unw_frame_info structure within the tasks stack address
range.

Signed-off-by: default avatarRobin Holt <holt@sgi.com>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent a8c8be08
Loading
Loading
Loading
Loading
+14 −7
Original line number Original line Diff line number Diff line
@@ -1860,7 +1860,7 @@ int
unw_unwind (struct unw_frame_info *info)
unw_unwind (struct unw_frame_info *info)
{
{
	unsigned long prev_ip, prev_sp, prev_bsp;
	unsigned long prev_ip, prev_sp, prev_bsp;
	unsigned long ip, pr, num_regs;
	unsigned long ip, pr, num_regs, rp_loc, pfs_loc;
	STAT(unsigned long start, flags;)
	STAT(unsigned long start, flags;)
	int retval;
	int retval;


@@ -1870,14 +1870,16 @@ unw_unwind (struct unw_frame_info *info)
	prev_sp = info->sp;
	prev_sp = info->sp;
	prev_bsp = info->bsp;
	prev_bsp = info->bsp;


	/* restore the ip */
	/* validate the return IP pointer */
	if (!info->rp_loc) {
	rp_loc = (unsigned long) info->rp_loc;
	if ((rp_loc < info->regstk.limit) || (rp_loc > info->regstk.top)) {
		/* FIXME: should really be level 0 but it occurs too often. KAO */
		/* 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",
		UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n",
			   __FUNCTION__, info->ip);
			   __FUNCTION__, info->ip);
		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
		return -1;
		return -1;
	}
	}
	/* restore the ip */
	ip = info->ip = *info->rp_loc;
	ip = info->ip = *info->rp_loc;
	if (ip < GATE_ADDR) {
	if (ip < GATE_ADDR) {
		UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __FUNCTION__, ip);
		UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __FUNCTION__, ip);
@@ -1885,12 +1887,14 @@ unw_unwind (struct unw_frame_info *info)
		return -1;
		return -1;
	}
	}


	/* restore the cfm: */
	/* validate the previous stack frame pointer */
	if (!info->pfs_loc) {
	pfs_loc = (unsigned long) info->pfs_loc;
	if ((pfs_loc < info->regstk.limit) || (pfs_loc > info->regstk.top)) {
		UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __FUNCTION__);
		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));
		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
		return -1;
		return -1;
	}
	}
	/* restore the cfm: */
	info->cfm_loc = info->pfs_loc;
	info->cfm_loc = info->pfs_loc;


	/* restore the bsp: */
	/* restore the bsp: */
@@ -1992,13 +1996,16 @@ init_frame_info (struct unw_frame_info *info, struct task_struct *t,
	memset(info, 0, sizeof(*info));
	memset(info, 0, sizeof(*info));


	rbslimit = (unsigned long) t + IA64_RBS_OFFSET;
	rbslimit = (unsigned long) t + IA64_RBS_OFFSET;
	stklimit = (unsigned long) t + IA64_STK_OFFSET;

	rbstop   = sw->ar_bspstore;
	rbstop   = sw->ar_bspstore;
	if (rbstop - (unsigned long) t >= IA64_STK_OFFSET)
	if (rbstop > stklimit || rbstop < rbslimit)
		rbstop = rbslimit;
		rbstop = rbslimit;


	stklimit = (unsigned long) t + IA64_STK_OFFSET;
	if (stktop <= rbstop)
	if (stktop <= rbstop)
		stktop = rbstop;
		stktop = rbstop;
	if (stktop > stklimit)
		stktop = stklimit;


	info->regstk.limit = rbslimit;
	info->regstk.limit = rbslimit;
	info->regstk.top   = rbstop;
	info->regstk.top   = rbstop;