Messages in this thread | | | From | Andy Lutomirski <> | Date | Tue, 20 Mar 2018 15:04:49 +0000 | Subject | Re: [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?
| |