binutils: Add the --namespace option to C based aa-exec

Switch to the policy in the namespace specified by the --namespace
option.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
Tyler Hicks 2015-12-17 19:18:37 -06:00
parent 897fa17b0d
commit b75cbff332

View file

@ -19,6 +19,7 @@
#include <errno.h> #include <errno.h>
#include <getopt.h> #include <getopt.h>
#include <libintl.h> #include <libintl.h>
#include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
@ -28,6 +29,7 @@
#define _(s) gettext(s) #define _(s) gettext(s)
static const char *opt_profile = NULL; static const char *opt_profile = NULL;
static const char *opt_namespace = NULL;
static bool opt_debug = false; static bool opt_debug = false;
static bool opt_immediate = false; static bool opt_immediate = false;
static bool opt_verbose = false; static bool opt_verbose = false;
@ -49,6 +51,7 @@ static void usage(const char *name, bool error)
"\n" "\n"
"OPTIONS:\n" "OPTIONS:\n"
" -p PROFILE, --profile=PROFILE PROFILE to confine <prog> with\n" " -p PROFILE, --profile=PROFILE PROFILE to confine <prog> with\n"
" -n NAMESPACE, --namespace=NAMESPACE NAMESPACE to confine <prog> in\n"
" -d, --debug show messages with debugging information\n" " -d, --debug show messages with debugging information\n"
" -i, --immediate change profile immediately instead of at exec\n" " -i, --immediate change profile immediately instead of at exec\n"
" -v, --verbose show messages with stats\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'}, {"debug", no_argument, 0, 'd'},
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"profile", required_argument, 0, 'p'}, {"profile", required_argument, 0, 'p'},
{"namespace", required_argument, 0, 'n'},
{"immediate", no_argument, 0, 'i'}, {"immediate", no_argument, 0, 'i'},
{"verbose", no_argument, 0, 'v'}, {"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) { switch (opt) {
case 'd': case 'd':
opt_debug = true; opt_debug = true;
@ -127,6 +131,9 @@ static char **parse_args(int argc, char **argv)
case 'p': case 'p':
opt_profile = optarg; opt_profile = optarg;
break; break;
case 'n':
opt_namespace = optarg;
break;
case 'i': case 'i':
opt_immediate = true; opt_immediate = true;
break; break;
@ -145,28 +152,58 @@ static char **parse_args(int argc, char **argv)
return argv + optind; 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; /* :<NAMESPACE>:// */
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) int main(int argc, char **argv)
{ {
char name[PATH_MAX];
int rc = 0; int rc = 0;
argv = parse_args(argc, argv); 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; goto exec;
if (opt_immediate) { if (opt_immediate) {
verbose("aa_change_profile(\"%s\")", opt_profile); verbose("aa_change_profile(\"%s\")", name);
rc = aa_change_profile(opt_profile); rc = aa_change_profile(name);
debug("%d = aa_change_profile(\"%s\")", rc, opt_profile); debug("%d = aa_change_profile(\"%s\")", rc, name);
} else { } else {
verbose("aa_change_onexec(\"%s\")", opt_profile); verbose("aa_change_onexec(\"%s\")", name);
rc = aa_change_onexec(opt_profile); rc = aa_change_onexec(name);
debug("%d = aa_change_onexec(\"%s\")", rc, opt_profile); debug("%d = aa_change_onexec(\"%s\")", rc, name);
} }
if (rc) { if (rc) {
if (errno == ENOENT || errno == EACCES) { 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) { } else if (errno == EINVAL) {
error("AppArmor interface not available"); error("AppArmor interface not available");
} else { } else {