linux-user: Fix error handling in lock_iovec()
In lock_iovec() if lock_user() failed we were doing an unlock_user but not a free(vec), which is the wrong way round. We were also assuming that free() and unlock_user() don't touch errno, which is not guaranteed. Fix both these problems. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
This commit is contained in:
		
							parent
							
								
									3a5d30bf27
								
							
						
					
					
						commit
						501bb4b0cb
					
				@ -1707,6 +1707,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
 | 
			
		||||
    struct iovec *vec;
 | 
			
		||||
    abi_ulong total_len, max_len;
 | 
			
		||||
    int i;
 | 
			
		||||
    int err = 0;
 | 
			
		||||
 | 
			
		||||
    if (count == 0) {
 | 
			
		||||
        errno = 0;
 | 
			
		||||
@ -1726,7 +1727,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
 | 
			
		||||
    target_vec = lock_user(VERIFY_READ, target_addr,
 | 
			
		||||
                           count * sizeof(struct target_iovec), 1);
 | 
			
		||||
    if (target_vec == NULL) {
 | 
			
		||||
        errno = EFAULT;
 | 
			
		||||
        err = EFAULT;
 | 
			
		||||
        goto fail2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1740,7 +1741,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
 | 
			
		||||
        abi_long len = tswapal(target_vec[i].iov_len);
 | 
			
		||||
 | 
			
		||||
        if (len < 0) {
 | 
			
		||||
            errno = EINVAL;
 | 
			
		||||
            err = EINVAL;
 | 
			
		||||
            goto fail;
 | 
			
		||||
        } else if (len == 0) {
 | 
			
		||||
            /* Zero length pointer is ignored.  */
 | 
			
		||||
@ -1748,7 +1749,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
 | 
			
		||||
        } else {
 | 
			
		||||
            vec[i].iov_base = lock_user(type, base, len, copy);
 | 
			
		||||
            if (!vec[i].iov_base) {
 | 
			
		||||
                errno = EFAULT;
 | 
			
		||||
                err = EFAULT;
 | 
			
		||||
                goto fail;
 | 
			
		||||
            }
 | 
			
		||||
            if (len > max_len - total_len) {
 | 
			
		||||
@ -1763,9 +1764,10 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
 | 
			
		||||
    return vec;
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
    free(vec);
 | 
			
		||||
 fail2:
 | 
			
		||||
    unlock_user(target_vec, target_addr, 0);
 | 
			
		||||
 fail2:
 | 
			
		||||
    free(vec);
 | 
			
		||||
    errno = err;
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user