Logo Search packages:      
Sourcecode: hexec version File versions  Download package

libhexec-hook.c

/***************************************************************************
 *   Copyright (C) 2008 by Alexander Block                                 *
 *   ablock@blocksoftware.net                                              *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "config.h"

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <fnmatch.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>

#include "libhexec-hook.h"
#include "common/args.h"
#include "common/shm.h"
#include "common/buf.h"
#include "common/error.h"
#include "common/locate.h"
#include "common/expr.h"

int (*orig_execve)(const char *filename, char *const argv[], char *const envp[]);
int (*orig_fexecve)(int fd, char *const argv[], char *const envp[]);
int (*orig_execl)(const char *path, const char *arg, ...);
int (*orig_execlp)(const char *file, const char *arg, ...);
int (*orig_execle)(const char *path, const char *arg, ...);
int (*orig_execv)(const char *path, char *const argv[]);
int (*orig_execvp)(const char *file, char *const argv[]);

//#ifndef RTLD_NEXT
//#define RTLD_NEXT ((void*)-1L)
//#endif

#define LOADFUNC(name) *(void**)&orig_##name = dlsym(RTLD_NEXT, #name)

static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
static int is_initialized = 0;

static struct hexec_shm shm;
static struct hexec_buf expr_buf;
static struct hexec_expr_shm_header* expr_header;

static void init()
{
    if (is_initialized)
        return;
    pthread_mutex_lock(&init_mutex);
    if (is_initialized)
    {
        pthread_mutex_unlock(&init_mutex);
        return;
    }

    LOADFUNC(execve);
    LOADFUNC(fexecve);
    LOADFUNC(execl);
    LOADFUNC(execlp);
    LOADFUNC(execle);
    LOADFUNC(execv);
    LOADFUNC(execvp);

    char* shm_name = getenv("HEXEC_EXPR_SHM");
    //hexec_log("loading shm %s\n", shm_name);
    if(!shm_name)
        hexec_fatal("HEXEC_EXPR_SHM is not set\n");
    if(hexec_shm_open(&shm, shm_name))
        hexec_fatal("failed to map expression\n");
    if(hexec_shm_to_buf(&shm, &expr_buf))
    {
        hexec_shm_close(&shm);
        hexec_fatal("failed to get buf from shm\n");
    }

    expr_header = (struct hexec_expr_shm_header*)shm.buf;

    char* log_out_fd_str = getenv("HEXEC_LOG_FD");
    if(log_out_fd_str)
        log_out_fd = atoi(log_out_fd_str);

    is_initialized = 1;
    pthread_mutex_unlock(&init_mutex);
}

static void print_exec(const char* exec_name, struct args_t* args, struct args_t* env)
{
    int i;

    hexec_log("%s: argv = ", exec_name);
    hexec_args_print(args);
    hexec_log("\n");
}

static int hook_execve(int fd, const char* path, int is_absulute_path, struct args_t* args, struct args_t* env)
{
    int err = 0;
    char* path2 = NULL;

    //print_exec("do_hook", args, env); 

    if(fd != -1 && !path)
    {
       hexec_fatal("fd based exec not implemented"); 
    }
    else if(fd == -1 && path)
    {
        if(!is_absulute_path)
        {
            if(err = hexec_locate(path, &path2))
            {
                return err;
            }
        }
    }
    if(!path2)
        path2 = strdup(path);
    int last_exec_status = 0;
    int res = hexec_expr_eval(path2, args, env, &expr_buf, expr_header->root_expr, &last_exec_status);
    if(res == HEXEC_EXPR_RESULT_NOMATCH)
    {
        //hexec_log("path2=%s args=", path2);
        //hexec_args_print(args);
        //hexec_log("\n");
        orig_execve(path2, args->argv, env->argv);
        err = errno;
        free(path2);
        return err;
    }
    if(res == HEXEC_EXPR_RESULT_ERROR)
    {
        hexec_fatal("error in expression\n");
    }
    free(path2);
    if(!err)
        exit(last_exec_status);
    //hexec_log("err=%d\n");
    return err;
}

///////////////////

int execve(const char *path, char *const argv[], char *const envp[])
{
    int err;
    struct args_t args, env;
    init();
    hexec_args_from_array(&args, argv);
    hexec_args_from_array(&env, envp);
    err = hook_execve(-1, path, 1, &args, &env);
    hexec_args_free(&args);
    hexec_args_free(&env);
    errno = err;
    return err == 0;
}

int fexecve(int fd, char *const argv[], char *const envp[])
{
    int err;
    struct args_t args, env;
    init();
    hexec_args_from_array(&args, argv);
    hexec_args_from_array(&env, envp);
    err = hook_execve(-1, NULL, 1, &args, &env);
    hexec_args_free(&args);
    hexec_args_free(&env);
    errno = err;
    return err == 0;
}

int execl(const char *path, const char *arg, ...)
{
    int err;
    va_list va;
    struct args_t args, env;

    init();
    va_start(va, arg);
    hexec_args_from_va_list(&args, arg, &va);
    hexec_args_from_array(&env, environ);
    va_end(va);
    err = hook_execve(-1, path, 1, &args, &env);
    hexec_args_free(&args);
    hexec_args_free(&env);
    errno = err;
    return err == 0;
}

int execlp(const char *file, const char *arg, ...)
{
    int err;
    va_list va;
    struct args_t args, env;

    init();
    va_start(va, arg);
    hexec_args_from_va_list(&args, arg, &va);
    hexec_args_from_array(&env, environ);
    va_end(va);
    err = hook_execve(-1, file, 0, &args, &env);
    hexec_args_free(&args);
    hexec_args_free(&env);
    errno = err;
    return err == 0;
}

int execle(const char *path, const char *arg, ...)
{
    int err;
    va_list va;
    struct args_t args, env;

    init();
    va_start(va, arg);
    hexec_args_from_va_list(&args, arg, &va);
    hexec_args_from_va_list(&env, NULL, &va);
    va_end(va);
    err = hook_execve(-1, path, 1, &args, &env);
    hexec_args_free(&args);
    hexec_args_free(&env);
    errno = err;
    return err == 0;
}

int execv(const char *path, char *const argv[])
{
    int err;
    struct args_t args, env;

    init();
    hexec_args_from_array(&args, argv);
    hexec_args_from_array(&env, environ);
    err = hook_execve(-1, path, 1, &args, &env);
    hexec_args_free(&args);
    hexec_args_free(&env);
    errno = err;
    return err == 0;
}

int execvp(const char *file, char *const argv[])
{
    int err;
    struct args_t args, env;

    init();
    hexec_args_from_array(&args, argv);
    hexec_args_from_array(&env, environ);
    err = hook_execve(-1, file, 0, &args, &env);
    hexec_args_free(&args);
    hexec_args_free(&env);
    errno = err;
    return err == 0;
}



Generated by  Doxygen 1.6.0   Back to index