struct { /* anonymous struct used by BPF_PROG_TEST_RUN command */
                __u32           prog_fd;
                __u32           retval;
-               __u32           data_size_in;
-               __u32           data_size_out;
+               __u32           data_size_in;   /* input: len of data_in */
+               __u32           data_size_out;  /* input/output: len of data_out
+                                                *   returns ENOSPC if data_out
+                                                *   is too small.
+                                                */
                __aligned_u64   data_in;
                __aligned_u64   data_out;
                __u32           repeat;
 
 {
        void __user *data_out = u64_to_user_ptr(kattr->test.data_out);
        int err = -EFAULT;
+       u32 copy_size = size;
+
+       /* Clamp copy if the user has provided a size hint, but copy the full
+        * buffer if not to retain old behaviour.
+        */
+       if (kattr->test.data_size_out &&
+           copy_size > kattr->test.data_size_out) {
+               copy_size = kattr->test.data_size_out;
+               err = -ENOSPC;
+       }
 
-       if (data_out && copy_to_user(data_out, data, size))
+       if (data_out && copy_to_user(data_out, data, copy_size))
                goto out;
        if (copy_to_user(&uattr->test.data_size_out, &size, sizeof(size)))
                goto out;
                goto out;
        if (copy_to_user(&uattr->test.duration, &duration, sizeof(duration)))
                goto out;
-       err = 0;
+       if (err != -ENOSPC)
+               err = 0;
 out:
        return err;
 }