• Al Viro's avatar
    do "fold checks into iterate_and_advance()" right · 19f18459
    Al Viro authored
    the only case when we should skip the iterate_and_advance() guts
    is when nothing's left in the iterator, _not_ just when requested
    amount is 0.  Said guts will do nothing in the latter case anyway;
    the problem we tried to deal with in the aforementioned commit is
    that when there's nothing left *and* the amount requested is 0,
    we might end up deferencing one iovec too many; the value we fetch
    from there is discarded in that case, but theoretically it might
    oops if the iovec array ends exactly at the end of page with the
    next page not mapped.
    
    Bailing out on zero size requested had an unexpected side effect -
    zero-length segment in the beginning of iovec array ended up
    throwing do_loop_readv_writev() into infinite spin; we do not
    advance past the empty segment at all.  Reproducer is trivial:
    echo '#include <sys/uio.h>' >a.c
    echo 'main() {char c; struct iovec v[] = {{&c,0},{&c,1}}; readv(0,v,2);}' >>a.c
    cc a.c && ./a.out </proc/uptime
    
    which should end up with the process not hanging.  Probably ought to
    go into LTP or xfstests...
    Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
    19f18459
iov_iter.c 19.4 KB