From 4d625ea05ba167d60766f86f2ff2edad2cfd561a Mon Sep 17 00:00:00 2001 From: Michael Prokop Date: Fri, 30 Apr 2021 00:25:44 +0200 Subject: [PATCH] fake-uname: fix gcc argument order and improve preloaded shared library This includes recent changes as integrated at https://github.com/sipwise/deployment-iso Makefile: - Fix gcc argument order: newer gcc versions have become more picky on their argument order, due to the --as-needed default, and require the libraries to be linked to, to be passed after the code/objects that use them, otherwise they will get dropped as unused. This change is required for compiling with gcc v10.2.1-6 as present on Debian/bullseye (otherwise fails to execute with `undefined symbol: dlsym`) - Add `make check` target to run some basic tests - Also get rid of *.o *.so files in clean target, adjust targets accordingly to always clean and then build fake-uname.so afterwards - Mark as serial-only via .NOTPARALLEL fake-uname.c: - Use hidden visibility by default, and export the symbol explicitly. - Resolve real_uname() only once. - Return early if the real_uname() fails, to avoid acting on bogus data. - Call dlerror() before dlsym() to clear any previous errors. - Compute the release member size from the utsname struct instead of hard-coding it. - Always NUL-terminate the relese buffer, so protect against very long environment strings. - Make various variables into const. Acked-by: Guillem Jover Thanks: Guillem Jover --- packer/Makefile | 36 +++++++++++++++++++++++++----------- packer/fake-uname.c | 33 +++++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/packer/Makefile b/packer/Makefile index 6a94be0..9d60c35 100644 --- a/packer/Makefile +++ b/packer/Makefile @@ -1,43 +1,57 @@ GRML_DEBOOTSTRAP_VERSION=latest GRML_DEBOOTSTRAP_LOCAL_PATH=$(shell pwd)/local_dir -compile: fake-uname.so +CFLAGS ?= -ggdb -O2 -Wall -Wextra -Wno-unused-parameter +CFLAGS += -fPIC -fvisibility=hidden +LDLIBS ?= +LDLIBS += -ldl + +PLUGIN = fake-uname.so + +$(PLUGIN): fake-uname.c + $(CC) $(CFLAGS) $(LDFLAGS) $< $(LDLIBS) -o $@ -shared + +UNAME_CHECK = LD_PRELOAD="$(CURDIR)/$(PLUGIN)" uname + +check: $(PLUGIN) + echo "$(UNAME_CHECK)" + test "0.0.0" = "$(shell $(UNAME_CHECK) -r)" + test "1.2.3" = "$(shell UTS_RELEASE="1.2.3" $(UNAME_CHECK) -r)" install: cd .. && make DESTDIR=packer/local_dir install clean: + $(RM) *.o *.so rm -rf local_dir -fake-uname.so: - gcc -shared -fPIC -ldl fake-uname.c -o fake-uname.so - # Debian 11 -bullseye: fake-uname.so clean install +bullseye: clean fake-uname.so install packer build -var debian_version=$@ -var grml_debootstrap_version=$(GRML_DEBOOTSTRAP_VERSION) -var grml_debootstrap_local_path=$(GRML_DEBOOTSTRAP_LOCAL_PATH) debian64.json # Debian 10 -buster: fake-uname.so clean install +buster: clean fake-uname.so install packer build -var debian_version=$@ -var grml_debootstrap_version=$(GRML_DEBOOTSTRAP_VERSION) -var grml_debootstrap_local_path=$(GRML_DEBOOTSTRAP_LOCAL_PATH) debian64.json # Debian 9 -stretch: fake-uname.so clean install +stretch: clean fake-uname.so install packer build -var debian_version=$@ -var grml_debootstrap_version=$(GRML_DEBOOTSTRAP_VERSION) -var grml_debootstrap_local_path=$(GRML_DEBOOTSTRAP_LOCAL_PATH) debian64.json # Debian 8 -jessie: fake-uname.so clean install +jessie: clean fake-uname.so install packer build -var debian_version=$@ -var grml_debootstrap_version=$(GRML_DEBOOTSTRAP_VERSION) -var grml_debootstrap_local_path=$(GRML_DEBOOTSTRAP_LOCAL_PATH) debian64.json # Debian 7 -wheezy: fake-uname.so clean install +wheezy: clean fake-uname.so install packer build -var debian_version=$@ -var grml_debootstrap_version=$(GRML_DEBOOTSTRAP_VERSION) -var grml_debootstrap_local_path=$(GRML_DEBOOTSTRAP_LOCAL_PATH) debian64.json # Debian 6.0 -squeeze: fake-uname.so clean install +squeeze: clean fake-uname.so install packer build -var debian_version=$@ -var grml_debootstrap_version=$(GRML_DEBOOTSTRAP_VERSION) -var grml_debootstrap_local_path=$(GRML_DEBOOTSTRAP_LOCAL_PATH) debian64.json # Debian 5.0 -lenny: fake-uname.so clean install +lenny: clean fake-uname.so install packer build -var debian_version=$@ -var grml_debootstrap_version=$(GRML_DEBOOTSTRAP_VERSION) -var grml_debootstrap_local_path=$(GRML_DEBOOTSTRAP_LOCAL_PATH) debian64.json .PHONY: compile bullseye buster stretch jessie wheezy squeeze lenny +.NOTPARALLEL: diff --git a/packer/fake-uname.c b/packer/fake-uname.c index 7bbcb24..d71a4f4 100644 --- a/packer/fake-uname.c +++ b/packer/fake-uname.c @@ -17,28 +17,45 @@ #define RTLD_NEXT ((void *) -1l) #endif -typedef int (*uname_t) (struct utsname * buf); +#define SYMBOL_EXPORT __attribute__((visibility("default"))) + +typedef int uname_func(struct utsname *buf); static void *get_libc_func(const char *funcname) { void *func; char *error; + /* Clear any previous errors. */ + dlerror(); func = dlsym(RTLD_NEXT, funcname); - if ((error = dlerror()) != NULL) { - fprintf(stderr, "Can't locate libc function `%s' error: %s", funcname, error); + error = dlerror(); + if (error != NULL) { + fprintf(stderr, "Cannot locate libc function '%s' error: %s", + funcname, error); _exit(EXIT_FAILURE); } return func; } -int uname(struct utsname *buf) +int SYMBOL_EXPORT uname(struct utsname *buf) { + static uname_func *real_uname; + const char *release; int ret; - char *env = NULL; - uname_t real_uname = (uname_t) get_libc_func("uname"); - ret = real_uname((struct utsname *) buf); - strncpy(buf->release, ((env = getenv("UTS_RELEASE")) == NULL) ? UTS_RELEASE : env, 65); + if (real_uname == NULL) + real_uname = (uname_func *)get_libc_func("uname"); + + ret = real_uname(buf); + if (ret < 0) + return ret; + + release = getenv("UTS_RELEASE"); + if (release == NULL) + release = UTS_RELEASE; + strncpy(buf->release, release, sizeof(buf->release) - 1); + buf->release[sizeof(buf->release) - 1] = '\0'; + return ret; } -- 2.1.4