このページを編集する際は、編集に関する方針に従ってください。

概要

  • linux2.6/arch/i386/kernel/signal.cにて定義
  • 引数で渡されたシグナルコンテキストをレジスタセットに再設定する
    • 問題なく処理が行われた場合は0を、そうでない場合は1を返す

引数

  • regs--レジスタセット
  • sc--シグナルコンテキスト
  • peax--レジスタセットに再設定されたeaxの値を格納する

実装

/*

* Do a signal return; undo the signal stack.
*/

static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax) {

	unsigned int err = 0;
	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

#define COPY(x) err |= __get_user(regs->x, &sc->x)

  • ユーザアドレスsc->xを、カーネルアドレスregs->xにコピーする

#define COPY_SEG(seg) \

	{ unsigned short tmp;						\
	  err |= __get_user(tmp, &sc->seg);				\
	  regs->x##seg = tmp; }
  • ユーザアドレスsc->segを、カーネルアドレスtmpにコピーする

#define COPY_SEG_STRICT(seg) \

	{ unsigned short tmp;						\
	  err |= __get_user(tmp, &sc->seg);				\
	  regs->x##seg = tmp|3; }
  • ユーザアドレスsc->segを、カーネルアドレスtmpにコピーする

#define GET_SEG(seg) \

	{ unsigned short tmp;						\
	  err |= __get_user(tmp, &sc->seg);				\
	  loadsegment(seg,tmp); }
  • ユーザアドレスsc->segを、カーネルアドレスtmpにコピーする
  • セグメントsegをtmpを設定する
    • 不正な値をセグメントにロードさせないために処理を行う
    • 詳細はloadsegment()/linux2.6を参照

#define FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | X86_EFLAGS_DF | \

			 X86_EFLAGS_TF | X86_EFLAGS_SF | X86_EFLAGS_ZF | \
			 X86_EFLAGS_AF | X86_EFLAGS_PF | X86_EFLAGS_CF)
	GET_SEG(gs);
  • セグメントレジスタ名gsにシグナルコンテキストのgs値を設定する
	GET_SEG(fs);
	COPY_SEG(es);
  • セグメントレジスタ名esに該当するシグナルコンテキストのセグメントレジスタ値をレジスタセットregsにコピーする
	COPY_SEG(ds);
	COPY(edi);
  • レジスタ名ediに該当するシグナルコンテキストのレジスタ値をレジスタセットregsにコピーする
	COPY(esi);
	COPY(ebp);
	COPY(esp);
	COPY(ebx);
	COPY(edx);
	COPY(ecx);
	COPY(eip);
	COPY_SEG_STRICT(cs);
	COPY_SEG_STRICT(ss);
	
	{
		unsigned int tmpflags;
		err |= __get_user(tmpflags, &sc->eflags);
  • ユーザアドレスsc->eflagsを、カーネルアドレスtmpflagsにコピーする
		regs->eflags = (regs->eflags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
		regs->orig_eax = -1;		/* disable syscall checks */
	}
	{
		struct _fpstate __user * buf;
		err |= __get_user(buf, &sc->fpstate);
  • ユーザアドレスsc->fpstateを、カーネルアドレスbufにコピーする
		if (buf) {
			if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
				goto badframe;
  • bufのアドレスの範囲がカレントスレッドのリミットを越えていない場合、0を返す
			err |= restore_i387(buf);
		}
	}
	err |= __get_user(*peax, &sc->eax);
  • ユーザアドレスsc->eaxを、カーネルアドレスpeaxにコピーする
	return err;

badframe:

	return 1;

}

呼出元


履歴

  • 作者:ひら
  • 日付:2007/10/31
  • 対象:2.6.10
    更新日更新者更新内容

コメント/タグ?



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2009-11-24 (火) 07:17:53 (2945d)