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

debug/elf: Does not always correctly read DT_BIND_NOW flag. #68144

Closed
slimm609 opened this issue Jun 23, 2024 · 2 comments
Closed

debug/elf: Does not always correctly read DT_BIND_NOW flag. #68144

slimm609 opened this issue Jun 23, 2024 · 2 comments
Labels
compiler/runtime Issues related to the Go compiler and/or runtime.

Comments

@slimm609
Copy link

Go version

go version go1.21.4 darwin/arm64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/slimm609/Library/Caches/go-build'
GOENV='/Users/slimm609/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/slimm609/go/1.21.4/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/slimm609/go/1.21.4'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/Users/slimm609/.goenv/versions/1.21.4'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/Users/slimm609/.goenv/versions/1.21.4/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.21.4'
GCCGO='gccgo'
AR='ar'
CC='clang'
CXX='clang++'
CGO_ENABLED='0'
GOMOD='/Users/slimm609/IdeaProjects/github/checksec.sh/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/cl/88g2hzkn0jxf3v7gvrgkrs8h0000gn/T/go-build19984873=/tmp/go-build -gno-record-gcc-switches -fno-common'

What did you do?

checking for the existing of DT_BIND_NOW flag on binaries does not always properly report.

package main

import (
	"debug/elf"
	"fmt"
	"os"
)
	
file, _ := elf.Open(/usr/bin/wget)
defer file.Close()

bind, _ := file.DynValue(24)
fmt.Println(bind)
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int false__stack_chk_fail(int a) { return a; }

int main(int argc, char** argv) {
  char buf[16];
  int (*op)(int) = false__stack_chk_fail;

  if (argc>1)
    strcpy(buf,argv[1]);
  else
    strcpy(buf,"test");

  printf("%s,%d\n", buf, op(42));

  sleep(2);
  return 0;
}

gcc -o test test.c -w -D_FORTIFY_SOURCE=3 -fstack-protector-strong -fpie -O2 -z relro -z now -z noexecstack -pie -s

What did you see happen?

when compiling with Rocky Linux 9 gcc.

the debug/elf check for file.DynValue(24) returns [0] to indicate that it includes BIND_NOW (This returns properly)

gcc version 11.4.1 20231218 (Red Hat 11.4.1-3) (GCC) on Rocky Linux 9

readelf -d test

Dynamic section at offset 0xfd70 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
...
 0x0000000000000018 (BIND_NOW)
 0x000000006ffffffb (FLAGS_1)            Flags: NOW PIE
 ...

However, when running the same code on ubuntu:22.04, this does NOT return properly

the debug/elf check for file.DynValue(24) returns [] to indicate that it BIND_NOW is not set (This does NOT return properly)

gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)

but readelf shows that the BIND_NOW flag IS set.

readelf -d test

Dynamic section at offset 0xd70 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
...
 0x000000000000001e (FLAGS)              BIND_NOW
 0x000000006ffffffb (FLAGS_1)            Flags: NOW PIE
...

from what it looks like, there are set in different places.

0x000000000000001e (FLAGS) BIND_NOW (ubuntu)
0x0000000000000018 (BIND_NOW) (rocky)

But both of them are proper.

What did you expect to see?

Both would be expected to return [0] to indicate that it is set properly on the binary.

Additional info on RELRO: https://www.redhat.com/en/blog/hardening-elf-binaries-using-relocation-read-only-relro

@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Jun 23, 2024
@gabyhelp
Copy link

@ianlancetaylor
Copy link
Contributor

This is working as expected. ELF is not as simple as one might expect. The File.DynValue function correctly returns the value of the DT_BIND_NOW tag. In the Ubuntu case the executable does not have a DT_BIND_NOW tag. Instead it has set the DF_BIND_NOW flag on the DT_FLAGS tag. To test for that you will have to write something like (untested) file.DynValue(elf.DT_FLAGS) & elf.DF_BIND_NOW != 0.

@ianlancetaylor ianlancetaylor closed this as not planned Won't fix, can't repro, duplicate, stale Jun 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime.
Projects
None yet
Development

No branches or pull requests

4 participants