Skip to content

Instantly share code, notes, and snippets.

@ryancdotorg
Created October 30, 2013 23:20
Show Gist options
  • Select an option

  • Save ryancdotorg/7241987 to your computer and use it in GitHub Desktop.

Select an option

Save ryancdotorg/7241987 to your computer and use it in GitHub Desktop.

Revisions

  1. ryancdotorg created this gist Oct 30, 2013.
    270 changes: 270 additions & 0 deletions dnaas.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,270 @@
    /* This is a wrapper library that will give your server the power of
    * /dev/null as a service, as seen at http://devnull-as-a-service.com/
    *
    * Compile:
    * gcc -ggdb -shared -fPIC dnaas.c -ldl -lcurl -o libdnaas.so
    *
    * Try:
    * LD_PRELOAD=./libdnaas.so dd if=/dev/sda of=/dev/null bs=8192 count=16
    *
    * Install:
    * sudo cp libdnaas.so /usr/lib && echo /usr/lib/libdnaas.so | sudo tee -a /etc/ld.so.preload
    */

    #define _GNU_SOURCE
    #include <stdio.h>
    #include <stdint.h>
    #include <stdarg.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>

    #include <tomcrypt.h>

    #include <curl/curl.h>

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>

    #include <dlfcn.h>

    #ifndef FD_MAX
    #define FD_MAX 65536
    #endif

    #define DEV_NULL_URL "http://devnull-as-a-service.com/dev/null"

    static char _dnaas_loaded = 0;
    static char _dnaas_devnull[] = "/dev/null";

    static FILE * (*_real_fopen)(const char *, const char *);
    static FILE * (*_real_freopen)(const char *, const char *, FILE *);
    static int (*_real_fclose)(FILE *);

    static int (*_real_open)(const char *, int, ...);
    static int (*_real_open64)(const char *, int, ...);
    static int (*_real_close)(int);

    static int (*_real_dup)(int);
    static int (*_real_dup2)(int, int);
    static int (*_real_dup3)(int, int, int);

    static ssize_t (*_real_write)(int, const void *, size_t);

    void _dnaas_load();

    static char _dnaas_fd_tab[FD_MAX];

    void _dnaas_load() {
    if (_real_fopen == NULL)
    _real_fopen = dlsym(RTLD_NEXT, "fopen");
    if (_real_freopen == NULL)
    _real_freopen = dlsym(RTLD_NEXT, "freopen");
    if (_real_fclose == NULL)
    _real_fclose = dlsym(RTLD_NEXT, "fclose");

    if (_real_open == NULL)
    _real_open = dlsym(RTLD_NEXT, "open");
    if (_real_open64 == NULL)
    _real_open64 = dlsym(RTLD_NEXT, "open64");
    if (_real_close == NULL)
    _real_close = dlsym(RTLD_NEXT, "close");

    if (_real_dup == NULL)
    _real_dup = dlsym(RTLD_NEXT, "dup");
    if (_real_dup2 == NULL)
    _real_dup2 = dlsym(RTLD_NEXT, "dup2");
    if (_real_dup3 == NULL)
    _real_dup3 = dlsym(RTLD_NEXT, "dup3");

    if (_real_write == NULL)
    _real_write = dlsym(RTLD_NEXT, "write");

    int i;
    for (i = 0; i < FD_MAX; i++)
    _dnaas_fd_tab[i] = 0;

    _dnaas_loaded = 1; /* curl calls functions we hook, so flip the bit here */

    curl_global_init(CURL_GLOBAL_DEFAULT);
    }

    ssize_t write(int fd, const void *buf, size_t count) {
    if (_dnaas_loaded != 1)
    _dnaas_load();

    if (_dnaas_fd_tab[fd]) {
    ssize_t ret = count;
    CURL *curl;
    CURLcode curl_res;
    struct curl_slist *headers=NULL;
    //fprintf(stderr, "intercepted write of %d bytes\n", (int)count);
    curl = curl_easy_init();
    if (!curl) {
    fprintf(stderr, "Failed to start curl!\n");
    return -1;
    }
    headers = curl_slist_append(headers, "Expect:");
    headers = curl_slist_append(headers, "Content-Type: application/octet-stream");
    curl_easy_setopt(curl, CURLOPT_URL, DEV_NULL_URL);
    curl_easy_setopt(curl, CURLOPT_POST, 1);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buf);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, count);
    if ((curl_res = curl_easy_perform(curl)) != CURLE_OK) {
    fprintf(stderr, "curl_easy_perform() failed: %s\n",
    curl_easy_strerror(curl_res));
    ret = -1;
    }

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    return ret;
    }
    //fprintf(stderr, "write passed through\n");
    return _real_write(fd, buf, count);
    }

    int open(const char *path, int flags, ...) {
    va_list args;
    mode_t mode;

    va_start(args, flags);
    mode = va_arg(args, mode_t);
    va_end(args);

    if (_dnaas_loaded != 1)
    _dnaas_load();

    int override = 0;
    if (strcmp(path, _dnaas_devnull) == 0) {
    path = _dnaas_devnull;
    override = 1;
    }

    int fd;
    fd = _real_open(path, flags, mode);
    _dnaas_fd_tab[fd] = override;
    return fd;
    }

    int open64(const char *path, int flags, ...) {
    va_list args;
    mode_t mode;

    va_start(args, flags);
    mode = va_arg(args, mode_t);
    va_end(args);

    if (_dnaas_loaded != 1)
    _dnaas_load();

    int override = 0;
    if (strcmp(path, _dnaas_devnull) == 0) {
    path = _dnaas_devnull;
    override = 1;
    }

    int fd;
    fd = _real_open64(path, flags, mode);
    _dnaas_fd_tab[fd] = override;
    return fd;
    }

    int close(int fd) {
    if (_dnaas_loaded != 1)
    _dnaas_load();

    _dnaas_fd_tab[fd] = 0;

    return _real_close(fd);
    }

    FILE * fopen(const char *path, const char *mode) {
    if (_dnaas_loaded != 1)
    _dnaas_load();

    int override = 0;
    if (strcmp(path, _dnaas_devnull) == 0) {
    path = _dnaas_devnull;
    override = 1;
    }

    int fd;
    FILE *fstr;
    fstr = _real_fopen(path, mode);
    fd = fileno(fstr);
    _dnaas_fd_tab[fd] = override;
    return fstr;
    }

    FILE * freopen(const char *path, const char *mode, FILE *stream) {
    if (_dnaas_loaded != 1)
    _dnaas_load();

    int override = 0;
    if (strcmp(path, _dnaas_devnull) == 0) {
    path = _dnaas_devnull;
    override = 1;
    }

    int fd;
    FILE *fstr;
    fd = fileno(stream);
    _dnaas_fd_tab[fd] = 0;
    fstr = _real_freopen(path, mode, stream);
    fd = fileno(fstr);
    _dnaas_fd_tab[fd] = override;
    return fstr;
    }

    int fclose(FILE *stream) {
    if (_dnaas_loaded != 1)
    _dnaas_load();

    int fd;
    fd = fileno(stream);
    _dnaas_fd_tab[fd] = 0;

    return _real_fclose(stream);
    }

    int dup(int oldfd) {
    if (_dnaas_loaded != 1)
    _dnaas_load();

    int override = _dnaas_fd_tab[oldfd];
    _dnaas_fd_tab[oldfd] = 0;

    int fd;
    if ((fd = _real_dup(oldfd)) >= 0)
    _dnaas_fd_tab[fd] = override;
    return fd;
    }

    int dup2(int oldfd, int newfd) {
    if (_dnaas_loaded != 1)
    _dnaas_load();

    int override = _dnaas_fd_tab[oldfd];
    _dnaas_fd_tab[oldfd] = 0;

    int fd;
    if ((fd = _real_dup2(oldfd, newfd)) >= 0)
    _dnaas_fd_tab[fd] = override;
    return fd;
    }

    int dup3(int oldfd, int newfd, int flags) {
    if (_dnaas_loaded != 1)
    _dnaas_load();

    int override = _dnaas_fd_tab[oldfd];
    _dnaas_fd_tab[oldfd] = 0;

    int fd;
    if ((fd = _real_dup3(oldfd, newfd, flags)) >= 0)
    _dnaas_fd_tab[fd] = override;
    return fd;
    }