TT#48647 Improve fake-uname preloaded shared library

- 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.
- Add functional tests.
- Style changes.

Change-Id: Iaf040edcc704fbc50a15d895276c820e71fe19a5
changes/93/27293/3
Guillem Jover 6 years ago
parent 4930994abd
commit 3f3efb1fcc

@ -8,6 +8,9 @@ all: build
build:
$(MAKE) -C src
check:
$(MAKE) -C src check
syntaxcheck: shellcheck
shellcheck:

@ -4,12 +4,18 @@ CPPFLAGS ?=
CPPFLAGS += -DPACKAGE_VERSION="\"$(PACKAGE_VERSION)\""
CFLAGS ?= -ggdb -O2 -Wall -Wextra -Wno-unused-parameter
CFLAGS += -fPIC -ldl
CFLAGS += -fPIC -ldl -fvisibility=hidden
PLUGIN = fake-uname.so
$(PLUGIN): fake-uname.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ -shared $<
UNAME_CHECK = LD_PRELOAD="$(CURDIR)/$(PLUGIN)" uname
check: $(PLUGIN)
test "0.0.0" = "$(shell $(UNAME_CHECK) -r)"
test "1.2.3" = "$(shell UTS_RELEASE="1.2.3" $(UNAME_CHECK) -r)"
clean:
$(RM) *.o *.so

@ -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;
}

@ -17,5 +17,6 @@ else
fi
make
make check
make syntaxcheck
make script_version

Loading…
Cancel
Save