On 6/7/22 13:14, Warner Losh wrote:
+void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
+        int count, int copy)
+{
+    struct target_iovec *target_vec;
+
+    target_vec = lock_user(VERIFY_READ, target_addr,
+                           count * sizeof(struct target_iovec), 1);
+    if (target_vec) {

Locking the same region twice seems like a bad idea.

How about something like

typedef struct {
    struct target_iovec *target;
    abi_ulong target_addr;
    int count;
    struct iovec host[];
} IOVecMap;

IOVecMap *lock_iovec(abi_ulong target_addr, int count, bool copy_in)
{
    IOVecMap *map;

    if (count == 0) ...
    if (count < 0) ...

    map = g_try_malloc0(sizeof(IOVecNew) + sizeof(struct iovec) * count);
    if (!map) ...

    map->target = lock_user(...);
    if (!map->target) {
        g_free(map);
        errno = EFAULT;
        return NULL;
    }
    map->target_addr = target_addr;
    map->count = count;

    // lock loop

 fail:
    unlock_iovec(vec, false);
    errno = err;
    return NULL;
}

void unlock_iovec(IOVecMap *map, bool copy_out)
{
    for (int i = 0, count = map->count; i < count; ++i) {
        if (map->host[i].iov_base) {
            abi_ulong target_base = tswapal(map->target[i].iov_base);
            unlock_user(map->host[i].iov_base, target_base,
                        copy_out ? map->host[i].iov_len : 0);
        }
    }
    unlock_user(map->target, map->target_addr, 0);
    g_free(map);
}


r~

Reply via email to