Re: [PATCH] process_vm_{read,write}v(3): initial man pages

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Mike,

On Sat, Apr 14, 2012 at 4:36 PM, Mike Frysinger <vapier@xxxxxxxxxx> wrote:
> On Friday 13 April 2012 21:07:28 Michael Kerrisk wrote:
>> On Fri, Mar 30, 2012 at 8:17 AM, Mike Frysinger wrote:
>> > On Thursday 29 March 2012 14:42:49 Michael Kerrisk wrote:
>> >> .\" FIXME: What does the following sentence mean?
>> >
>> > heh, i was just about to suggest a clarification.  consider the case
>> > where you want to read a C string from a remote process.  you don't know
>> > its length, so it is probably cheaper to read too much data and then
>> > discard the rest than it is to read it byte by byte in a single syscall.
>> >
>> > further consider the string lies in the last page of a valid mapping.
>> >  you don't want to always say "read 500 bytes" because if the first 200
>> > bytes are the last 200 bytes of the last page, the remaining 300 bytes
>> > cover invalid memory, and so no data will be read.
>> >
>> > instead, you'd split the remote read array into two elements and have
>> > them merge back into a single write array entry.  the first read entry
>> > goes up to the page boundary while the second starts on the next page
>> > boundary.
>> >
>> >> Keep this in mind when attempting to
>> >> extract data of unknown length (such as C strings which are
>> >> null-terminated) by avoiding spanning memory pages (typically 4KiB).
>> >
>> > ... by avoiding spanning memory pages (typically 4KiB) in a single iovec
>> > element.
>>
>> Thanks for the clear explanation, and the crisp addition to the
>> man-page text. I also adapted a piece of your explanation to add into
>> the page after the above sentence:
>>
>> ==
>> (Instead, split the remote read array into two
>> .I iovec
>> elements and have them merge back into a single write array entry.
>> The first read entry goes up to the page boundary,
>> while the second starts on the next page boundary.)
>> ==
>>
>> However, as I look at the text, there is still a nagging doubt. The
>> paragraph starts
>> ==
>> The count arguments and
>> .IR local_iov
>> are checked before doing any transfers.
>> If the counts are too big, or
>> .I local_iov
>> is invalid,
>> or the addresses refer to regions that are inaccessible to the local
>> process, none of the vectors will be processed and an
>> error will be returned immediately.
>> ==
>>
>> That seems to contradict the advice "Instead, split the remote read
>> array", because surely if the second of the iovec elements refers to
>> an inaccessible region, then as stated in the early part of the
>> paragraph, "none of the vectors will be processed". And the advice
>> refers to the "remote read array".
>>
>> What am I missing? I suspect the advice should instead apply to the
>> *remote_iov*, and perhaps be placed in the following paragraph.
>
> the new text you added describes the remote args (the stuff that needs
> splitting).  the existing text you refer to describes the local args.  i don't
> see any contradiction here -- the kernel first checks the local memory regions
> to make sure the local process has full access to its own regions before
> processing anything, and then it processes the remote memory regions one
> element at a time while doing the actual transfers.

I think you've missed my point. The text starts out with a sentence
describing the checks performed on the count arguments and local_iov.
Then it says "Keep this in mind" (i.e., the aforementioned point) and
gives some advice about how to avoid a certain kind of error when
specifying remote_iov. All of the technical details are correct, but
the logic of the explanation is (it seems to me) broken. The "Keep
this in mind" suggests that the second part of the text is dependent
on the explanation given in the first part, when in fact it is not. If
you still don't see what I mean, can you describe to me what "this" in
"Keep this in mind" refers to.

It seems to me that the "Keep this in mind" part belons with the
*following* paragraph, like so:

==
The count arguments and
.IR local_iov
are checked before doing any transfers.
If the counts are too big, or
.I local_iov
is invalid,
or the addresses refer to regions that are inaccessible to the local process,
none of the vectors will be processed
and an error will be returned immediately.

Note, however, that these system calls do not check the memory regions
in the remote process until just before doing the read/write.
Consequently, a partial read/write may result if one of the
.I remote_iov
elements points to an invalid memory region in the remote process.
No further reads/writes will be attempted beyond that point.
Keep this in mind when attempting to
read data of unknown length (such as C strings that are null-terminated)
from a remote process,
by avoiding spanning memory pages (typically 4KiB) in a single
.I iovec
element.
(Instead, split the remote read into two
.I remote_iov
elements and have them merge back into a single write array entry.
The first read entry goes up to the page boundary,
while the second starts on the next page boundary.)
==

Does that not make better sense?

>> >> Note, however, that these system calls do not check the memory regions
>> >> in the remote process until just before doing the read/write.
>> >> Consequently, a partial read/write may result if one of the
>> >> .I remote_vec
>> >> elements points to an invalid memory region in the remote process.
>> >> No further reads/writes will be attempted beyond that point.
>> >
>> > should clarify that the partial read/write applies to iovec elements
>> > granularity and not byte granularity.  i.e. the syscall won't return a
>> > partial read that splits a single iovect element.
>>
>> I added this text under RETURN VALUE:
>>
>> ==
>> (Partial transfers apply at the granularity of
>> .I iovec
>> elements.
>> These system calls won't perform a partial
>> transfer that splits a single
>> .I iovec
>> element.)
>> ==
>>
>> And again a question does "a single iovec element" here apply to the
>> remove iovec elements, the local iovec elements, or both?
>
> if any local iovec element is invalid, then it returns immediately without any
> transferring of data.  this is because the local process should know what
> is/isn't valid about itself before making any requests.  however, it's hard
> for it to know about the remote process, so the remote elements are "looser"
> in checking (which is a good thing).

Perhaps I'm too clogged up with a cold, but I couldn't draw an answer
to the question " does "a single iovec element" here apply to the
remote iovec elements, the local iovec elements, or both?" from your
reply.

Mike, thanks for persisting so far with trying to clarify things.

Cheers,

Michael



-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Author of "The Linux Programming Interface"; http://man7.org/tlpi/
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Kernel Documentation]     [Netdev]     [Linux Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux