diff --git a/binutils/aa_exec.c b/binutils/aa_exec.c index 9bcd62f8f..7e73f45f3 100644 --- a/binutils/aa_exec.c +++ b/binutils/aa_exec.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #define _(s) gettext(s) static const char *opt_profile = NULL; +static const char *opt_namespace = NULL; static bool opt_debug = false; static bool opt_immediate = false; static bool opt_verbose = false; @@ -49,6 +51,7 @@ static void usage(const char *name, bool error) "\n" "OPTIONS:\n" " -p PROFILE, --profile=PROFILE PROFILE to confine with\n" + " -n NAMESPACE, --namespace=NAMESPACE NAMESPACE to confine in\n" " -d, --debug show messages with debugging information\n" " -i, --immediate change profile immediately instead of at exec\n" " -v, --verbose show messages with stats\n" @@ -112,11 +115,12 @@ static char **parse_args(int argc, char **argv) {"debug", no_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {"profile", required_argument, 0, 'p'}, + {"namespace", required_argument, 0, 'n'}, {"immediate", no_argument, 0, 'i'}, {"verbose", no_argument, 0, 'v'}, }; - while ((opt = getopt_long(argc, argv, "+dhp:iv", long_opts, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "+dhp:n:iv", long_opts, NULL)) != -1) { switch (opt) { case 'd': opt_debug = true; @@ -127,6 +131,9 @@ static char **parse_args(int argc, char **argv) case 'p': opt_profile = optarg; break; + case 'n': + opt_namespace = optarg; + break; case 'i': opt_immediate = true; break; @@ -145,28 +152,58 @@ static char **parse_args(int argc, char **argv) return argv + optind; } +static void build_name(char *name, size_t name_len, + const char *namespace, const char *profile) +{ + size_t required_len = 1; /* reserve 1 byte for NUL-terminator */ + + if (namespace) + required_len += 1 + strlen(namespace) + 3; /* ::// */ + + if (profile) + required_len += strlen(profile); + + if (required_len > name_len) + error("name too long (%zu > %zu)", required_len, name_len); + + name[0] = '\0'; + + if (namespace) { + strcat(name, ":"); + strcat(name, namespace); + strcat(name, "://"); + } + + if (profile) + strcat(name, profile); +} + int main(int argc, char **argv) { + char name[PATH_MAX]; int rc = 0; argv = parse_args(argc, argv); - if (!opt_profile) + if (opt_namespace || opt_profile) + build_name(name, sizeof(name), opt_namespace, opt_profile); + else goto exec; if (opt_immediate) { - verbose("aa_change_profile(\"%s\")", opt_profile); - rc = aa_change_profile(opt_profile); - debug("%d = aa_change_profile(\"%s\")", rc, opt_profile); + verbose("aa_change_profile(\"%s\")", name); + rc = aa_change_profile(name); + debug("%d = aa_change_profile(\"%s\")", rc, name); } else { - verbose("aa_change_onexec(\"%s\")", opt_profile); - rc = aa_change_onexec(opt_profile); - debug("%d = aa_change_onexec(\"%s\")", rc, opt_profile); + verbose("aa_change_onexec(\"%s\")", name); + rc = aa_change_onexec(name); + debug("%d = aa_change_onexec(\"%s\")", rc, name); } if (rc) { if (errno == ENOENT || errno == EACCES) { - error("profile '%s' does not exist", opt_profile); + error("%s '%s' does not exist\n", + opt_profile ? "profile" : "namespace", name); } else if (errno == EINVAL) { error("AppArmor interface not available"); } else {