Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check for a branded ELF note when OS/ABI is NONE #1344

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
36 changes: 35 additions & 1 deletion src/auditor/dynamic_linkage.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
using ObjectFile.ELF

function os_from_elf_note(oh::ELFHandle)
for section in Sections(oh)
section_handle(section) == ELF.SHT_NOTE || continue
seek(oh, section_offset(section))
name_length = read(oh, UInt32)
iszero(name_length) && continue
descriptor_length = read(oh, UInt32)
note_type = read(oh, UInt32)
name = String(read(oh, name_length - 1)) # skip trailing NUL
if note_type == 1
# Technically it's part of the Linux specification that any executable should
# have an ELF note with type 1, name GNU, and descriptor length ≥4, but in
# practice I haven't observed that consistently, especially on musl. So for
# now, only bother checking FreeBSD, which uses an ELF note rather than OS/ABI
# to identify itself on AArch64 and RISC-V.
if name == "FreeBSD" && descriptor_length == 4
return name
end
end
end
return nothing
end

os_from_elf_note(::ObjectHandle) = nothing

"""
platform_for_object(oh::ObjectHandle)

Expand Down Expand Up @@ -39,7 +64,9 @@ function platform_for_object(oh::ObjectHandle)
end
end

if oh.ei.osabi == ELF.ELFOSABI_LINUX || oh.ei.osabi == ELF.ELFOSABI_NONE
if oh.ei.osabi == ELF.ELFOSABI_NONE
Copy link
Member

Choose a reason for hiding this comment

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

Should we just delete platform_for_object since it appears to be unused?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, I can if you'd like me to.

return Platform(arch, os_from_elf_note(oh) == "FreeBSD" ? "freebsd" : "linux")
elseif oh.ei.osabi == ELF.ELFOSABI_LINUX
return Platform(arch, "linux")
elseif oh.ei.osabi == ELF.ELFOSABI_FREEBSD
return Platform(arch, "freebsd")
Expand Down Expand Up @@ -108,6 +135,13 @@ function is_for_platform(h::ObjectHandle, platform::AbstractPlatform)
else
error("Unknown OS ABI type $(typeof(platform))")
end
else
# If no OSABI, check whether it has a matching ELF note
if Sys.isfreebsd(platform)
if os_from_elf_note(h) != "FreeBSD"
return false
end
end
end
# Check that the ELF arch matches our own
m = h.header.e_machine
Expand Down
17 changes: 15 additions & 2 deletions src/auditor/extra_checks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,19 @@ using Dates: DateTime, datetime2unix

function check_os_abi(oh::ObjectHandle, p::AbstractPlatform, rest...; verbose::Bool = false, kwargs...)
if Sys.isfreebsd(p)
if oh.ei.osabi != ELF.ELFOSABI_FREEBSD
# On AArch64 and RISC-V, FreeBSD uses an ELF note section to identify itself rather
# than OS/ABI in the ELF header. In that case, the OS/ABI will be generic Unix (NONE).
# See https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=252490 and
# https://github.com/freebsd/freebsd-src/blob/main/lib/csu/common/crtbrand.S
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# https://github.com/freebsd/freebsd-src/blob/main/lib/csu/common/crtbrand.S
# https://github.com/freebsd/freebsd-src/blob/3c95262007ef934c9e98b87460a48889bf42c1b9/lib/csu/common/crtbrand.S

if oh.ei.osabi == ELF.ELFOSABI_NONE
if os_from_elf_note(oh) != "FreeBSD"
if verbose
@warn("$(basename(path(oh))) does not have a FreeBSD-branded ELF note " *
"and may be unrecognized or unusable on $p")
end
return false
end
elseif oh.ei.osabi != ELF.ELFOSABI_FREEBSD
# The dynamic loader should not have problems in this case, but the
# linker may not appreciate. Let the user know about this.
if verbose
Expand All @@ -17,7 +29,8 @@ function check_os_abi(oh::ObjectHandle, p::AbstractPlatform, rest...; verbose::B
end
return false
end
elseif call_abi(p) == "eabihf"
end
if call_abi(p) == "eabihf"
# Make sure the object file has the hard-float ABI. See Table 4-2 of
# "ELF for the ARM Architecture" document
# (https://developer.arm.com/documentation/ihi0044/e/). Note: `0x000`
Expand Down
Loading