Skip to content

Instantly share code, notes, and snippets.

@ephemient
Created October 16, 2015 01:49
Show Gist options
  • Save ephemient/daafa8b001a46004f649 to your computer and use it in GitHub Desktop.
Save ephemient/daafa8b001a46004f649 to your computer and use it in GitHub Desktop.
libcmdsdaskpass.so
#/* \
make -C "$(dirname "$0")" -f "$0" "$@"; exit $?
libcmdsdaskpass.so: LDFLAGS += -shared
libcmdsdaskpass.so: LDLIBS += -ldl
libcmdsdaskpass.so: cmdsdaskpass.o
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@
cmdsdaskpass.o: CFLAGS += -fPIC
cmdsdaskpass.o: cmdsdaskpass.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $^
help:
$(info )
$(info LD_PRELOAD to replace $$(systemd-ask-password $$*) with the result of invocation)
$(info in ARGV without being visible in /proc/$$/cmdline, building on code taken from)
$(info http://serverfault.com/a/592941)
$(info http://xrefactor.com/blog/polyglot-in-c-makefile-and-shell-script)
$(info )
.PHONY: help
#*/
#define _GNU_SOURCE
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sysexits.h>
#include <unistd.h>
static int (*real_main)(int, char **, char **);
static const char replace_arg_begin[] = "$(systemd-ask-password";
static const char replace_arg_end[] = ")";
static const char sd_askpass_cmd[] = "/usr/bin/systemd-ask-password";
static const char whitespace[] = " \t\n";
static int preload_main(int argc, char **argv, char **envp) {
int i, j, fds[2];
for (i = 1; i < argc; i++) {
int begin = strlen(replace_arg_begin);
int end = strlen(argv[i]) - strlen(replace_arg_end);
if (begin < end &&
memcmp(argv[i], replace_arg_begin, strlen(replace_arg_begin)) == 0 &&
memcmp(argv[i] + end, replace_arg_end, strlen(replace_arg_end)) == 0) {
pid_t child;
char *s, *args = malloc(end - begin + 1);
const char **arga = calloc((end - begin + 1) / 2 + 2, sizeof(char *));
memcpy(args, argv[i] + begin, end - begin);
args[end - begin] = '\0';
arga[0] = sd_askpass_cmd;
for (j = 1, s = args + strspn(args, whitespace); s[0]; s += strspn(s, whitespace)) {
arga[j++] = s;
if (s[0] == '-' && (s[1] != '-' || s[2] != '\0' && !strchr(whitespace, s[2]))) {
s += strcspn(s, whitespace);
if (s[0]) {
*s++ = '\0';
}
} else if (s[0] == '-' && s[1] == '-') {
(s += 2)[0] = '\0';
if (&s[1] < &args[end - begin]) {
s += 1 + strspn(&s[1], whitespace);
}
if (s < &args[end - begin]) {
arga[j++] = s;
s = &args[end - begin];
}
} else {
break;
}
}
if (pipe2(fds, O_CLOEXEC) < 0) {
perror("pipe2");
exit(EX_OSERR);
}
if ((child = fork()) < 0) {
perror("fork");
exit(EX_OSERR);
} else if (child == 0) {
if (fds[0] != 1) {
close(fds[0]);
}
if (fds[1] != 1) {
dup2(fds[1], 1);
close(fds[1]);
}
execvp(arga[0], (char **)arga);
perror("execv");
_exit(EX_UNAVAILABLE);
} else {
FILE *p;
size_t n = 0;
free(arga);
free(args);
close(fds[1]);
if (!(p = fdopen(fds[0], "r"))) {
perror("child");
exit(EX_NOINPUT);
}
args = NULL;
j = getline(&args, &n, p);
if (j < 0) {
perror("getline");
exit(EX_NOINPUT);
}
fclose(p);
close(fds[0]);
if (args[j - 1] == '\n') {
args[j - 1] = '\0';
}
argv[i] = args;
}
}
}
return real_main(argc, argv, envp);
}
int __libc_start_main(
int (*main)(int, char **, char **),
int argc, char **ubp_av,
void (*init)(void),
void (*fini)(void),
void (*rtld_fini)(void),
void *stack_end) {
int (*next)(
int (*)(int, char **, char **),
int, char **,
void (*)(void),
void (*)(void),
void (*)(void),
void *) =
dlsym(RTLD_NEXT, __func__);
real_main = main;
return next(preload_main, argc, ubp_av, init, fini, rtld_fini, stack_end);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment