lkml.org 
[lkml]   [2018]   [Mar]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 06/15] x86/fsgsbase/64: Add putregs() to handle multiple elements' setting
    Date
    putregs() can be used to handle multiple elements flexibly.

    It is useful when inter-dependency lies in updating a
    group of context entries. There will be a case with FSGSBASE.

    Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
    Cc: Markus T. Metzger <markus.t.metzger@intel.com>
    Cc: H. Peter Anvin <hpa@zytor.com>
    Cc: Andi Kleen <ak@linux.intel.com>
    Cc: Andy Lutomirski <luto@kernel.org>
    ---
    arch/x86/kernel/ptrace.c | 51 +++++++++++++++++++++++++++++++++++++-----------
    1 file changed, 40 insertions(+), 11 deletions(-)

    diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
    index d8a1e1b..9c09bf0 100644
    --- a/arch/x86/kernel/ptrace.c
    +++ b/arch/x86/kernel/ptrace.c
    @@ -421,6 +421,22 @@ static int putreg(struct task_struct *child,
    return 0;
    }

    +static int putregs(struct task_struct *child,
    + unsigned int offset,
    + unsigned int count,
    + const unsigned long *values)
    +{
    + const unsigned long *v = values;
    + int ret = 0;
    +
    + while (count >= sizeof(*v) && !ret) {
    + ret = putreg(child, offset, *v++);
    + count -= sizeof(*v);
    + offset += sizeof(*v);
    + }
    + return ret;
    +}
    +
    static unsigned long getreg(struct task_struct *task, unsigned long offset)
    {
    switch (offset) {
    @@ -477,24 +493,37 @@ static int genregs_set(struct task_struct *target,
    const void *kbuf, const void __user *ubuf)
    {
    int ret = 0;
    +
    if (kbuf) {
    - const unsigned long *k = kbuf;
    - while (count >= sizeof(*k) && !ret) {
    - ret = putreg(target, pos, *k++);
    - count -= sizeof(*k);
    - pos += sizeof(*k);
    - }
    + ret = putregs(target, pos, count, kbuf);
    } else {
    const unsigned long __user *u = ubuf;
    - while (count >= sizeof(*u) && !ret) {
    + const unsigned long *genregs = NULL;
    + unsigned long *buf = NULL;
    + unsigned int remains = 0;
    +
    + buf = kmalloc(count, GFP_KERNEL);
    +
    + if (unlikely(!buf))
    + return -ENOMEM;
    +
    + genregs = buf;
    + remains = count;
    +
    + while (remains >= sizeof(*u) && !ret) {
    unsigned long word;
    +
    ret = __get_user(word, u++);
    - if (ret)
    + if (unlikely(ret))
    break;
    - ret = putreg(target, pos, word);
    - count -= sizeof(*u);
    - pos += sizeof(*u);
    + memcpy(buf++, &word, sizeof(*u));
    + remains -= sizeof(*u);
    }
    +
    + if (likely(!ret))
    + /* Allows to handle multiple elements accordingly. */
    + ret = putregs(target, pos, count, genregs);
    + kfree(genregs);
    }
    return ret;
    }
    --
    2.7.4
    \
     
     \ /
      Last update: 2018-03-19 21:56    [W:2.482 / U:0.260 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site