lkml.org 
[lkml]   [2018]   [Mar]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
From
Date
SubjectRe: [PATCH 14/15] x86/fsgsbase/64: Support legacy behavior when FS/GS updated by ptracer
On Mon, Mar 19, 2018 at 5:49 PM, Chang S. Bae <chang.seok.bae@intel.com> wrote:
> When FSGSBASE enabled, ptracer's FS/GS selector update
> fetches FS/GS base from GDT/LDT. This emulation of FS/GS
> segment loading provides backward compatibility for the
> legacy ptracers.
>
> When ptracer sets FS/GS selector, its base is going to be
> (accordingly) reloaded as the tracee resumes. This is without
> FSGSBASE. With FSGSBASE, FS/GS base is preserved regardless
> of its selector. Thus, emulating FS/GS load in ptrace is
> requested to keep compatible with what has been with FS/GS
> setting.
>
> Additionally, whenever a new base value is written, the
> FSGSBASE-enabled kernel allows the tracee effectively carry
> on. This also means that when both selector and base are
> changed, the base is not fetched from GDT/LDT, but
> preserved as given.
>

>
> Suggested-by: Markus T. Metzger <markus.t.metzger@intel.com>
> Suggested-by: H. Peter Anvin <hpa@zytor.com>

I've also suggested something like this myself, but this approach is
far more complicated than the older approach. Was there something
that the old approach would break? If so, what?

> + /*
> + * %fs setting goes to reload its base, when tracee
> + * resumes without FSGSBASE (legacy). Here with FSGSBASE
> + * FS base is (manually) fetched from GDT/LDT when needed.
> + */
> + else if (static_cpu_has(X86_FEATURE_FSGSBASE) &&
> + (value != 0) && (task->thread.fsindex != value))
> + task->thread.fsbase = task_seg_base(task, value);

The comment above should explain why you're checking this particular
condition. I find the fsindex != value check to be *very* surprising.
On a real CPU, writing some nonzero value to %fs does the same thing
regardless of what the old value of %fs was.

> + case USER_REGS_OFFSET(fs):
> + if (fs_fully_covered &&

This is_fully_covered thing is IMO overcomplicated. Why not just make
a separate helper set_fsgs_index_and_base() and have putregs() call it
when both are set at once?

> + static_cpu_has(X86_FEATURE_FSGSBASE)) {
> + if (invalid_selector(*v))
> + return -EIO;
> + /*
> + * Set the flag to fetch fsbase from GDT/LDT
> + * with FSGSBASE
> + */
> + fs_updated = (*v != 0) &&
> + (child->thread.fsindex != *v);

Same here. Why do you care if fs was changed?

\
 
 \ /
  Last update: 2018-03-20 16:05    [W:0.235 / U:0.084 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site