All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pedro Alves <palves@redhat.com>
To: Anshuman Khandual <khandual@linux.vnet.ibm.com>
Cc: linux-kernel@vger.kernel.org, hpa@zytor.com, suresh.b.siddha@intel.com
Subject: Re: [PATCH] ptrace: Fix PTRACE_GETREGSET/PTRACE_SETREGSET in code documentation
Date: Tue, 13 May 2014 19:09:58 +0100	[thread overview]
Message-ID: <53725FF6.6060004@redhat.com> (raw)
In-Reply-To: <53670F35.6010502@linux.vnet.ibm.com>

On 05/05/14 05:10, Anshuman Khandual wrote:
> On 05/01/2014 07:43 PM, Pedro Alves wrote:
>> On 04/28/2014 12:00 PM, Anshuman Khandual wrote:
>>> The current documentation is bit misleading and does not explicitly
>>> specify that iov.len need to be initialized failing which kernel
>>> may just ignore the ptrace request and never read from/write into
>>> the user specified buffer. This patch fixes the documentation.
>>
>> Well, it kind of does, here:
>>
>> *      struct iovec iov = { buf, len};
> 
> :) Thats not explicit enough.
> 
>>
>>> @@ -43,8 +43,12 @@
>>>   *
>>>   *	ret = ptrace(PTRACE_GETREGSET/PTRACE_SETREGSET, pid, NT_XXX_TYPE, &iov);
>>>   *
>>> - * On the successful completion, iov.len will be updated by the kernel,
>>> - * specifying how much the kernel has written/read to/from the user's iov.buf.
>>> + * A non-zero value upto the max size of data expected to be written/read by the
>>> + * kernel in response to any NT_XXX_TYPE request type must be assigned to iov.len
>>> + * before initiating the ptrace call. If iov.len is 0, then kernel will neither
>>> + * read from or write into the user buffer specified. On successful completion,
>>> + * iov.len will be updated by the kernel, specifying how much the kernel has
>>> + * written/read to/from the user's iov.buf.
>>
>> I really appreciate that you're trying to make this clearer, but I
>> find the new sentence very hard to read/reason.  :-/
>>
>> I suggest:
>>
>>  * This interface usage is as follows:
>> - *      struct iovec iov = { buf, len};
>> + *      struct iovec iov = { buf, len };
>>  *
>>  *      ret = ptrace(PTRACE_GETREGSET/PTRACE_SETREGSET, pid, NT_XXX_TYPE, &iov);
>>  *
>> - * On the successful completion, iov.len will be updated by the kernel,
>> - * specifying how much the kernel has written/read to/from the user's iov.buf.
>> + * On entry, iov describes the buffer's address and length.  The buffer's
>> + * length must be equal to or shorter than the size of the NT_XXX_TYPE regset.
>> + * On successful completion, iov.len is updated by the kernel, specifying how
>> + * much the kernel has written/read to/from the user's iov.buf.
>>
> 
> Yeah, sounds better. I may add "If the length is zero, the kernel will neither read
> from or write into the buffer"

Well, I think that much should be obvious.  What's not obvious is
whether that is considered success or error (what is the return code?)
I suspect and expect success return if the regset type is known, and
error otherwise.  So that could be used as a way to probe for support
for a given regset without using stack or heap space, if it ever matters.
The kernel never reads/writes beyond iov.len, so better say that, and
then it automatically gets the 0 case handled too, right?

>> I'm not sure I understood what you're saying correctly, though.  Specifically,
>> I don't know whether the buffer's length must really be shorter than the
>> size of the NT_XXX_TYPE regset.
> 
> No, it does not have to. From the code snippet below (ptrace_regset function)
> the buffer length has to be multiple of regset->size for the given NT_XXX_TYPE
> upto the max regset size for the user to see any valid data.

Ah, I guess one could call it a bug.  If the passed in
len is bigger than the whole register set size, then there seems
to be no point in validating whether the length is multiple of
a single register's size.  That unnecessarily prevents coming up
with a register set in the future that has registers of
different sizes...

But given that that's how things are today, I suppose we should
document it...

 The problem what I
> faced was when you use any iovec structure with the length parameter uninitialized,
> the kernel simply ignores and does not return anything.

Ah.  Well, saying "does not return anything" is quite confusing.  It does
return something -- -EINVAL.

> 
>         if (!regset || (kiov->iov_len % regset->size) != 0)
>                 return -EINVAL;

>  
>>
>>> The current documentation is bit misleading and does not explicitly
>>> specify that iov.len need to be initialized failing which kernel
>>> may just ignore the ptrace request and never read from/write into
>>> the user specified buffer.
>>
>> You're saying that if iov.len is larger than the NT_XXX_TYPE regset,
>> then the kernel returns _success_, but actually doesn't fill the
>> buffer?  That sounds like a bug to me.
> 
> No, I am not saying that. The kernel takes care of that situation by capping
> the length to regset size of the NT_XXX_TYPE.
> 
>  kiov->iov_len = min(kiov->iov_len,
>                             (__kernel_size_t) (regset->n * regset->size));
> 
> 

OK, then this is what I suggest instead:

   * This interface usage is as follows:
 - *      struct iovec iov = { buf, len};
 + *      struct iovec iov = { buf, len };
   *
   *      ret = ptrace(PTRACE_GETREGSET/PTRACE_SETREGSET, pid, NT_XXX_TYPE, &iov);
   *
   * On the successful completion, iov.len will be updated by the kernel,
 - * specifying how much the kernel has written/read to/from the user's iov.buf.
 + * On entry, iov describes the buffer's address and length.  The buffer's
 + * length must be a multiple of the size of a single register in the register set.
 + * The kernel never reads or writes more than iov.len, and caps the buffer
 + * length to the register set's size.  In other words, the kernel reads or
 + * writes min(iov.len, regset size).
 + * On successful completion, iov.len is updated by the kernel, specifying how
 + * much the kernel has read from / written to the user's iov.buf.

> Shall I resend the patch with the your proposed changes and your "Signed-off-by" and
> moving myself as "Reported-by" ?

No idea of the actual policy to follow.  Feel free to do that if that's the
standard procedure.

-- 
Pedro Alves


  reply	other threads:[~2014-05-13 18:58 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-28 11:00 [PATCH] ptrace: Fix PTRACE_GETREGSET/PTRACE_SETREGSET in code documentation Anshuman Khandual
2014-05-01 14:13 ` Pedro Alves
2014-05-05  4:10   ` Anshuman Khandual
2014-05-13 18:09     ` Pedro Alves [this message]
2014-05-14  7:10       ` Anshuman Khandual
2014-05-14 10:54         ` [PATCH v2] ptrace: Clarify PTRACE_GETREGSET/PTRACE_SETREGSET, documentation in uapi header Pedro Alves
2014-05-20  8:23           ` Anshuman Khandual
2014-06-12  8:51           ` Anshuman Khandual
2014-06-12 18:05             ` Oleg Nesterov
2014-06-12 18:49               ` Michael Kerrisk (man-pages)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=53725FF6.6060004@redhat.com \
    --to=palves@redhat.com \
    --cc=hpa@zytor.com \
    --cc=khandual@linux.vnet.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=suresh.b.siddha@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.