• Al Viro's avatar
    saner iov_iter initialization primitives · bc917be8
    Al Viro authored
    iovec-backed iov_iter instances are assumed to satisfy several properties:
    	* no more than UIO_MAXIOV elements in iovec array
    	* total size of all ranges is no more than MAX_RW_COUNT
    	* all ranges pass access_ok().
    
    The problem is, invariants of data structures should be established in the
    primitives creating those data structures, not in the code using those
    primitives.  And iov_iter_init() violates that principle.  For a while we
    managed to get away with that, but once the use of iov_iter started to
    spread, it didn't take long for shit to hit the fan - missed check in
    sys_sendto() had introduced a roothole.
    
    We _do_ have primitives for importing and validating iovecs (both native and
    compat ones) and those primitives are almost always followed by shoving the
    resulting iovec into iov_iter.  Life would be considerably simpler (and safer)
    if we combined those primitives with initializing iov_iter.
    
    That gives us two new primitives - import_iovec() and compat_import_iovec().
    Calling conventions:
    	iovec = iov_array;
    	err = import_iovec(direction, uvec, nr_segs,
    			   ARRAY_SIZE(iov_array), &iovec,
    			   &iter);
    imports user vector into kernel space (into iov_array if it fits, allocated
    if it doesn't fit or if iovec was NULL), validates it and sets iter up to
    refer to it.  On success 0 is returned and allocated kernel copy (or NULL
    if the array had fit into caller-supplied one) is returned via iovec.
    On failure all allocations are undone and -E... is returned.  If the total
    size of ranges exceeds MAX_RW_COUNT, the excess is silently truncated.
    
    compat_import_iovec() expects uvec to be a pointer to user array of compat_iovec;
    otherwise it's identical to import_iovec().
    
    Finally, import_single_range() sets iov_iter backed by single-element iovec
    covering a user-supplied range -
    
    	err = import_single_range(direction, address, size, iovec, &iter);
    
    does validation and sets iter up.  Again, size in excess of MAX_RW_COUNT gets
    silently truncated.
    
    Next commits will be switching the things up to use of those and reducing
    the amount of iov_iter_init() instances.
    Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
    bc917be8
iov_iter.c 19.1 KB