Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 30 additions & 10 deletions libwild/src/linker_plugins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ struct FileHandle<'data> {

/// This isn't known initially because we allocate file IDs later.
file_id: AtomicCell<Option<FileId>>,

fd: RawFd,
offset: u64,
name: &'data CStr,
}

#[derive(Default)]
Expand Down Expand Up @@ -249,14 +253,22 @@ impl<'data> LinkerPlugin<'data> {
wrap_symbols: self.wrap_symbols,
};

let name = CString::new(input_ref.file.filename.as_os_str().as_encoded_bytes())?;
let name = CStr::from_bytes_with_nul(
self.herd.get().alloc_slice_copy(name.as_bytes_with_nul()),
)
.unwrap();

let handle = FileHandle {
data,
name,
fd,
offset,
file_id: AtomicCell::new(None),
};

let handle = self.herd.get().alloc(handle);

let name = CString::new(input_ref.file.filename.as_os_str().as_encoded_bytes())?;
let file = LdPluginInputFile {
name: name.as_ptr(),
Comment on lines -259 to 273

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't that use-after-free previously?
CString created allocation and unless I'm missing something due to viewing this on my phone, we only used pointer to it. So the name would be dropped when going out of scope.

With the new code name is stored within the struct, so the allocation is kept alive.

Borrow checker doesn't catch such issues because it's legal and safe to create dangling pointers. The part requiring unsafe code is reading from the pointers.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pointer to name would previously have been valid for the duration of the call into the plugin's claim-file hook. But if the claim-file hook stored the pointer and used it later, then yes, it would have been a use-after-free. AFAIK though it doesn't, but the linker plugin API docs are pretty absent of any mentions of required lifetimes, so who knows.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, this function returns LtoInputInfo, not LdPluginInputFile. Line wrapping in the mobile view tricked me.

fd,
Expand Down Expand Up @@ -913,18 +925,26 @@ fn get_symbol_resolution<'data>(
}
}

// We don't currently implement this. The LLVM plugin gives an error if we don't define it, but then
// it doesn't appear to actually call it. Or maybe we just haven't found a test case that causes it
// to be called.
extern "C" fn get_input_file(
_handle: *const libc::c_void,
_file: *mut LdPluginInputFile,
) -> Status {
Status::Err
extern "C" fn get_input_file(handle: *const libc::c_void, file: *mut LdPluginInputFile) -> Status {
catch_panics(|| {
if handle.is_null() || file.is_null() {
return Status::Err;
}
let handle = unsafe { &*(handle as *const FileHandle) };
let file = unsafe { &mut *file };

file.fd = handle.fd;
file.offset = handle.offset as i64;
file.file_size = handle.data.len() as i64;
file.name = handle.name.as_ptr();

Status::Ok
})
}

extern "C" fn release_input_file(_handle: *const libc::c_void) -> Status {
Status::Err
// We don't allocate in `get_input_file`, so there's nothing to free here.
Status::Ok
}

extern "C" fn get_view(
Expand Down
9 changes: 9 additions & 0 deletions wild/tests/sources/elf/linker-plugin-lto/linker-plugin-lto.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@
//#Object:linker-plugin-lto-2.c
//#DiffIgnore:section.eh_frame.type

//#Config:clang-thin:default
//#Compiler:clang
//#CompArgs:-flto=thin
//#LinkerDriver:clang
//#LinkArgs:-Wl,-znow -flto=thin -nostdlib -O0
//#Object:runtime.c
//#Object:linker-plugin-lto-2.c
//#DiffIgnore:section.eh_frame.type

//#Config:clang-link-gcc:error
//#Compiler:clang
//#CompArgs:-flto
Expand Down
Loading