summary refs log tree commit diff
path: root/qcow_utils
diff options
context:
space:
mode:
authorZach Reizner <zachr@google.com>2018-11-15 14:17:34 -0800
committerchrome-bot <chrome-bot@chromium.org>2018-11-16 05:01:42 -0800
commit94923406ae4af8139a6ee8fcb3c265c26ae69835 (patch)
tree8fc1daff92279a11d54556ff8ea4e6dcab9bbce7 /qcow_utils
parent674504a3de8c076a4a4607399beb30dba13893b0 (diff)
downloadcrosvm-94923406ae4af8139a6ee8fcb3c265c26ae69835.tar
crosvm-94923406ae4af8139a6ee8fcb3c265c26ae69835.tar.gz
crosvm-94923406ae4af8139a6ee8fcb3c265c26ae69835.tar.bz2
crosvm-94923406ae4af8139a6ee8fcb3c265c26ae69835.tar.lz
crosvm-94923406ae4af8139a6ee8fcb3c265c26ae69835.tar.xz
crosvm-94923406ae4af8139a6ee8fcb3c265c26ae69835.tar.zst
crosvm-94923406ae4af8139a6ee8fcb3c265c26ae69835.zip
qcow_utils: do not close given fds in `convert_to_*` functions
The `convert_to_*` functions take ownership of the passed FDs even
though they should not according to the function's contract. This change
clones the passed FDs so that the caller can retain ownership of its
FDs.

This change also wraps most of the implementations in catch_unwind so
that panics do not unwind past FFI boundaries, which is undefined
behavior.

BUG=chromium:905799
TEST=in crosh: `vmc export <vm name> <file name>`

Change-Id: I2f65ebff51243675d0854574d8fd02cec1b237a4
Reviewed-on: https://chromium-review.googlesource.com/1338501
Commit-Ready: Zach Reizner <zachr@chromium.org>
Tested-by: Zach Reizner <zachr@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Diffstat (limited to 'qcow_utils')
-rw-r--r--qcow_utils/src/qcow_utils.rs40
1 files changed, 33 insertions, 7 deletions
diff --git a/qcow_utils/src/qcow_utils.rs b/qcow_utils/src/qcow_utils.rs
index ea84b62..33f20ae 100644
--- a/qcow_utils/src/qcow_utils.rs
+++ b/qcow_utils/src/qcow_utils.rs
@@ -7,11 +7,13 @@
 extern crate libc;
 extern crate qcow;
 
-use libc::{EINVAL, EIO};
+use libc::{EBADFD, EINVAL, EIO};
 use std::ffi::CStr;
 use std::fs::{File, OpenOptions};
+use std::mem::forget;
 use std::os::raw::{c_char, c_int};
 use std::os::unix::io::FromRawFd;
+use std::panic::catch_unwind;
 
 use qcow::{ImageType, QcowFile};
 
@@ -47,23 +49,47 @@ pub unsafe extern "C" fn create_qcow_with_size(path: *const c_char, virtual_size
 #[no_mangle]
 pub unsafe extern "C" fn convert_to_qcow2(src_fd: c_int, dst_fd: c_int) -> c_int {
     // The caller is responsible for passing valid file descriptors.
+    // The caller retains ownership of the file descriptors.
     let src_file = File::from_raw_fd(src_fd);
+    let src_file_owned = src_file.try_clone();
+    forget(src_file);
+
     let dst_file = File::from_raw_fd(dst_fd);
+    let dst_file_owned = dst_file.try_clone();
+    forget(dst_file);
 
-    match qcow::convert(src_file, dst_file, ImageType::Qcow2) {
-        Ok(_) => 0,
-        Err(_) => -EIO,
+    match (src_file_owned, dst_file_owned) {
+        (Ok(src_file), Ok(dst_file)) => {
+            catch_unwind(
+                || match qcow::convert(src_file, dst_file, ImageType::Qcow2) {
+                    Ok(_) => 0,
+                    Err(_) => -EIO,
+                },
+            ).unwrap_or(-EIO)
+        }
+        _ => -EBADFD,
     }
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn convert_to_raw(src_fd: c_int, dst_fd: c_int) -> c_int {
     // The caller is responsible for passing valid file descriptors.
+    // The caller retains ownership of the file descriptors.
     let src_file = File::from_raw_fd(src_fd);
+    let src_file_owned = src_file.try_clone();
+    forget(src_file);
+
     let dst_file = File::from_raw_fd(dst_fd);
+    let dst_file_owned = dst_file.try_clone();
+    forget(dst_file);
 
-    match qcow::convert(src_file, dst_file, ImageType::Raw) {
-        Ok(_) => 0,
-        Err(_) => -EIO,
+    match (src_file_owned, dst_file_owned) {
+        (Ok(src_file), Ok(dst_file)) => {
+            catch_unwind(|| match qcow::convert(src_file, dst_file, ImageType::Raw) {
+                Ok(_) => 0,
+                Err(_) => -EIO,
+            }).unwrap_or(-EIO)
+        }
+        _ => -EBADFD,
     }
 }