dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.15k stars 4.71k forks source link

Self-contained linux-x64 binary cannot be edited with obj copy #54947

Open argium opened 3 years ago

argium commented 3 years ago

Description

We use .NET5 to create self-contained linux binaries. Our linux service engineers have asked us to stamp ELF metadata on all files that run in production. .NET5 produces binaries that are non-standard and cannot be modified using tools like objcopy.

  1. Create a console application using the .NET Console Application template in VS2019
  2. Add <PublishSingleFile>true</PublishSingleFile> to the csproj
  3. run dotnet publish -r linux-x64
  4. run objcopy ConsoleApp1 ConsoleApp2

Expected: ConsoleApp2 should run

Actual:

$ objcopy ConsoleApp1 ConsoleApp2
$ ll
total 71384
-rwxrwxrwx 1 rifuller rifuller 62584280 Jun 25 22:32 ConsoleApp1*
-rwxrwxrwx 1 rifuller rifuller     9628 Jun 25 22:32 ConsoleApp1.pdb*
-rwxrwxrwx 1 rifuller rifuller 10497152 Jun 25  2021 ConsoleApp2*

$ ./ConsoleApp2
Failure processing application bundle; possible file corruption.
Arithmetic overflow while reading bundle.
A fatal error occured while processing application bundle

Configuration

.net version = 5.0.301

Regression?

Unsure.

Other information

N/A

ghost commented 3 years ago

Tagging subscribers to this area: @dotnet/area-system-console See info in area-owners.md if you want to be subscribed.

Issue Details
### Description We use .NET5 to create self-contained linux binaries. Our linux service engineers have asked us to stamp ELF metadata on all files that run in production. .NET5 produces binaries that are non-standard and cannot be modified using tools like objcopy. 1. Create a console application using the .NET Console Application template in VS2019 2. Add `true` to the csproj 3. run `dotnet publish -r linux-x64` 4. run `objcopy ConsoleApp1 ConsoleApp2` Expected: ConsoleApp2 should run Actual: ``` $ objcopy ConsoleApp1 ConsoleApp2 $ ll total 71384 -rwxrwxrwx 1 rifuller rifuller 62584280 Jun 25 22:32 ConsoleApp1* -rwxrwxrwx 1 rifuller rifuller 9628 Jun 25 22:32 ConsoleApp1.pdb* -rwxrwxrwx 1 rifuller rifuller 10497152 Jun 25 2021 ConsoleApp2* $ ./ConsoleApp2 Failure processing application bundle; possible file corruption. Arithmetic overflow while reading bundle. A fatal error occured while processing application bundle ``` ### Configuration .net version = 5.0.301 ### Regression? Unsure. ### Other information N/A
Author: requilium
Assignees: -
Labels: `area-System.Console`, `untriaged`
Milestone: -
argium commented 3 years ago

@jkotas followup from email.

ghost commented 3 years ago

Tagging subscribers to this area: @agocke, @vitek-karas, @vsadov See info in area-owners.md if you want to be subscribed.

Issue Details
### Description We use .NET5 to create self-contained linux binaries. Our linux service engineers have asked us to stamp ELF metadata on all files that run in production. .NET5 produces binaries that are non-standard and cannot be modified using tools like objcopy. 1. Create a console application using the .NET Console Application template in VS2019 2. Add `true` to the csproj 3. run `dotnet publish -r linux-x64` 4. run `objcopy ConsoleApp1 ConsoleApp2` Expected: ConsoleApp2 should run Actual: ``` $ objcopy ConsoleApp1 ConsoleApp2 $ ll total 71384 -rwxrwxrwx 1 rifuller rifuller 62584280 Jun 25 22:32 ConsoleApp1* -rwxrwxrwx 1 rifuller rifuller 9628 Jun 25 22:32 ConsoleApp1.pdb* -rwxrwxrwx 1 rifuller rifuller 10497152 Jun 25 2021 ConsoleApp2* $ ./ConsoleApp2 Failure processing application bundle; possible file corruption. Arithmetic overflow while reading bundle. A fatal error occured while processing application bundle ``` ### Configuration .net version = 5.0.301 ### Regression? Unsure. ### Other information N/A
Author: requilium
Assignees: -
Labels: `area-Single-File`, `area-System.Console`, `untriaged`
Milestone: -
vitek-karas commented 3 years ago

This is unfortunately expected right now. On Linux (and on Windows) the single-file is created by simply appending to existing executable. We don't modify the headers in any way in this case. That means that the file is technically not valid per the file format specification, but OS loaders don't care. Some other tools do care though.

@VSadov to comment on possible ideas on how complex it would be to fixup the ELF and PE headers (similar to what we do on macOS), but I don't think this will be possible in .NET 6.

VSadov commented 3 years ago

It should be possible to put single-file payload into a file section in both ELF and PE case and could be more straightforward than in the case of Mach-O. The difficulties will be in carefully patching the existing file structure for the presence of another section.

Right now HostModel has very little support for parsing/writing these formats, especially for ELF, this is basically all of it. Some additional support will need to be built up. This does not look like something we would try to fit in 6.0

jkotas commented 3 years ago

Ideally, you would want it arrange it such that the OS maps the payload in exactly as we need it, with the right executable permissions and relocs.