So this is a C based version of aa-exec to replace the perl version.

---

/*
 *   Copyright (C) 2013 Canonical Ltd.
 *
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of version 2 of the GNU General Public
 *   License published by the Free Software Foundation.
 */

#define _GNU_SOURCE

#include <errno.h>
#include <getopt.h>
#include <libintl.h>
#include <locale.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/apparmor.h>

#define _(s) gettext(s)

#define aa_verbose(X...)                \
do {                                    \
        if (opt_verbose) {              \
                fprintf(g_outfile, X);  \
        }                               \
} while (0)

#define aa_error(X, Y...)                               \
do {                                                    \
        if (X) {                                        \
                fprintf(g_outfile, "aborting: " Y);     \
                exit(-1);                               \
        }                                               \
} while (0)

/* Internationalization support. Can be defined in Makefile */
#ifndef PACKAGE
#define PACKAGE "apparmor"
#endif
#ifndef LOCALEDIR
#define LOCALEDIR ""
#endif

const char *g_version   = "3.0";
const char *g_copyright = "Copyright (C) 2013 Canonical Ltd.";
FILE *g_outfile;
char *g_progname;
int opt_immediate;
int opt_verbose;
char *opt_debug;
char *opt_file;
char *opt_profile;
char *opt_namespace;

const char *g_options =
        "Options:\n"
        "--------\n"
        "-p PROFILE, --profile=PROFILE          PROFILE to confine <prog> 
with\n"
        "-n NAMESPACE, --namespace=NAMESPACE    NAMESPACE to confine <prog> 
in\n"
        "-f FILE, --file=FILE                   profile file to load\n"
        "-i, --immediate                        change profile immediately 
instead of at exec\n"
        "-v, --verbose                          show messages with stats\n"
        "-d FILE, --debug=FILE                  dump verbose output to FILE\n"
        "-h, --help                             display this help\n";

const char *short_options = "d:hp:n:f:iv";
struct option long_options[] = {
        {"debug",               1, 0, 'd'},
        {"help",                0, 0, 'h'},
        {"profile",             1, 0, 'p'},
        {"namespace",           1, 0, 'n'},
        {"file",                1, 0, 'f'},
        {"immediate",           0, 0, 'i'},
        {"verbose",             0, 0, 'v'},
        {"Version",             0, 0, 'V'},
        {NULL, 0, 0, 0},
};

static void display_version(void)
{
        printf("%s version %s\n%s\n", g_progname, g_version, g_copyright);
}

static void display_usage(void)
{
        display_version();
        printf("\nUsage: %s [options] [--] <prog> <args>\n\n%s", g_progname,
               g_options);
}

static void process_args(int argc, char *argv[])
{
        int c, o;
        int count = 0;

        while ((c = getopt_long(argc, argv, short_options, long_options, &o)) 
!= -1) {
                switch (c) {
                case 0:
                        display_usage();
                        exit(0);
                        break;
                case 'V':
                        display_version();
                        break;
                case 'd':
                        opt_verbose = 1;
                        opt_debug = optarg;
                        break;
                case 'h':
                        display_usage();
                        exit(0);
                        break;
                case 'p':
                        opt_profile = optarg;
                        break;
                case 'n':
                        opt_namespace = optarg;
                        break;
                case 'f':
                        opt_file = optarg;
                        break;
                case 'i':
                        opt_immediate = 1;
                        break;
                case 'v':
                        opt_verbose = 1;
                        break;
                default:
                        printf("Unknown option %c\n\n", c);
                        display_usage();
                        exit(0);
                        break;
                }
                count++;
        }
}

int main(int argc, char *argv[])
{
        int rc = 0;
        char *profile = NULL;

        /* name of executable, for error reporting and usage display */
        g_progname = argv[0];
        g_outfile = stderr;

        setlocale(LC_MESSAGES, "");
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
        
        process_args(argc, argv);

        if (opt_debug) {
                FILE *tmp = fopen(opt_debug, "w+");
                aa_error(tmp == NULL, "could not open debug file %s\n", 
opt_debug);
                aa_error(setvbuf(tmp, NULL, _IONBF, 0) != 0, "could not set 
debug file %s to unbuffered\n", opt_debug);
                g_outfile = tmp;
        }

        if (opt_namespace || opt_profile) {
                if (opt_namespace) {
                        rc = asprintf(&profile, ":%s:%s", opt_namespace, 
opt_profile ? opt_profile : "");
                        aa_error(rc == -1, "%s", strerror(errno));

                } else if (opt_profile) {
                        rc = asprintf(&profile, "%s", opt_profile);
                        aa_error(rc == -1, "%s", strerror(errno));
                }

                if (opt_file) {
                        char *cmd;
                        rc = asprintf(&cmd, "apparmor_parser -r %s", opt_file);
                        aa_error(rc == -1, "%s", strerror(errno));
                        aa_verbose("%s\n", cmd);
                        rc = system(cmd);
                        aa_error(rc == -1, "could not load file %s", opt_file);
                }

                if (opt_immediate) {
                        aa_verbose("aa_change_profile(\"%s\")\n", profile);
                        rc = aa_change_profile(profile);
                } else {
                        aa_verbose("aa_change_onexec(\"%s\")\n", profile);
                        rc = aa_change_onexec(profile);
                }

                if (rc == -1) {
                        if (errno == ENOENT || errno == EACCES)
                                aa_error(1, "\'%s\' does not exist", profile);
                        else if (errno == EINVAL)
                                aa_error(1, "AppArmor interface not available");
                        else
                                aa_error(1, "%s", strerror(errno));
                }
        }

        aa_verbose("exec %s\n", argv[optind]);
        (void)execvpe(argv[optind], &argv[optind], environ);
        /* exec failed, kill outselves to flag parent */

        rc = errno;
        fprintf(g_outfile, "FAIL: exec to '%s' failed (%s)\n", argv[optind],
                strerror(errno));
        return rc;
}



-- 
AppArmor mailing list
AppArmor@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to