Bug 16081

Summary: tar: segfault on empty linkname.
Product: Busybox Reporter: Joshua Scarsbrook <jscarsbrook>
Component: OtherAssignee: unassigned
Status: NEW ---    
Severity: normal CC: busybox-cvs
Priority: P5    
Version: unspecified   
Target Milestone: ---   
Hardware: All   
OS: Linux   
Host: Target:
Build:
Attachments: A tar archive that causes a segfault when run on the latest busybox version.

Description Joshua Scarsbrook 2024-05-25 09:52:10 UTC
Created attachment 9745 [details]
A tar archive that causes a segfault when run on the latest busybox version.

When `busybox tar xf` is run on a tar containing a symlink with a empty linkname it segfaults.

I've tested this with the current master compiling with `make defconfig`.

This is the code to generate the attached archive. It can be run with go.

package main

import (
	"archive/tar"
	"os"
)

func main() {
	w := tar.NewWriter(os.Stdout)

	w.WriteHeader(&tar.Header{
		Typeflag: tar.TypeSymlink,
		Name:     "hello",
		Linkname: "",
	})

	w.Close()
}

AddressSanitizer detects the bug.

archival/libarchive/unsafe_symlink_target.c:13:25: runtime error: load of null pointer of type 'const char'
AddressSanitizer:DEADLYSIGNAL
=================================================================
==2324589==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x00000086519c bp 0x0fe895861200 sp 0x7fff2f3616b0 T0)
==2324589==The signal is caused by a READ memory access.
==2324589==Hint: address points to the zero page.
    #0 0x86519c in create_or_remember_link archival/libarchive/unsafe_symlink_target.c:13

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV archival/libarchive/unsafe_symlink_target.c:13 in create_or_remember_link
==2324589==ABORTING

There's a TOOD for this bug in busybox/archival/libarchive/data_extract_all.c on line 176.

A possible fix is adding the following code at line 176.

if (file_header->link_target == NULL)
{
	bb_error_msg_and_die("invalid symlink with empty target: %s", dst_name);
}

This makes it a fatal error rather than a segfault.