Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

Commit

Permalink
Merge pull request #188 from snapcore/aa-support
Browse files Browse the repository at this point in the history
Add apparmor support module
  • Loading branch information
zyga committed Nov 30, 2016
2 parents a0c48f2 + 850f224 commit 267ca91
Show file tree
Hide file tree
Showing 3 changed files with 228 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/Makefile.am
Expand Up @@ -59,7 +59,9 @@ snap_confine_SOURCES = \
mountinfo.c \
mountinfo.h \
ns-support.c \
ns-support.h
ns-support.h \
apparmor-support.c \
apparmor-support.h

snap_confine_CFLAGS = -Wall -Werror $(AM_CFLAGS)
snap_confine_LDFLAGS = $(AM_LDFLAGS)
Expand Down
132 changes: 132 additions & 0 deletions src/apparmor-support.c
@@ -0,0 +1,132 @@
/*
* Copyright (C) 2016 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "apparmor-support.h"

#include <string.h>
#include <errno.h>
#ifdef HAVE_APPARMOR
#include <sys/apparmor.h>
#endif // ifdef HAVE_APPARMOR

#include "cleanup-funcs.h"
#include "utils.h"

// NOTE: Those constants map exactly what apparmor is returning and cannot be
// changed without breaking apparmor functionality.
#define SC_AA_ENFORCE_STR "enforce"
#define SC_AA_COMPLAIN_STR "complain"
#define SC_AA_MIXED_STR "mixed"
#define SC_AA_UNCONFINED_STR "unconfined"

void sc_init_apparmor_support(struct sc_apparmor *apparmor)
{
#ifdef HAVE_APPARMOR
// Use aa_is_enabled() to see if apparmor is available in the kernel and
// enabled at boot time. If it isn't log a diagnostic message and assume
// we're not confined.
if (aa_is_enabled() != true) {
switch (errno) {
case ENOSYS:
debug
("apparmor extensions to the system are not available");
break;
case ECANCELED:
debug
("apparmor is available on the system but has been disabled at boot");
break;
case ENOENT:
debug
("apparmor is available but the interface but the interface is not available");
case EPERM:
// NOTE: fall-through
case EACCES:
debug
("insufficient permissions to determine if apparmor is enabled");
break;
default:
debug("apparmor is not enabled: %s", strerror(errno));
break;
}
apparmor->is_confined = false;
apparmor->mode = SC_AA_NOT_APPLICABLE;
return;
}
// Use aa_getcon() to check the label of the current process and
// confinement type. Note that the returned label must be released with
// free() but the mode is a constant string that must not be freed.
char *label __attribute__ ((cleanup(sc_cleanup_string))) = NULL;
char *mode = NULL;
if (aa_getcon(&label, &mode) < 0) {
die("cannot query current apparmor profile");
}
// The label has a special value "unconfined" that is applied to all
// processes without a dedicated profile. If that label is used then the
// current process is not confined. All other labels imply confinement.
if (label != NULL && strcmp(label, SC_AA_UNCONFINED_STR) == 0) {
apparmor->is_confined = false;
} else {
apparmor->is_confined = true;
}
// There are several possible results for the confinement type (mode) that
// are checked for below.
if (mode != NULL && strcmp(mode, SC_AA_COMPLAIN_STR) == 0) {
apparmor->mode = SC_AA_COMPLAIN;
} else if (mode != NULL && strcmp(mode, SC_AA_ENFORCE_STR) == 0) {
apparmor->mode = SC_AA_ENFORCE;
} else if (mode != NULL && strcmp(mode, SC_AA_MIXED_STR) == 0) {
apparmor->mode = SC_AA_MIXED;
} else {
apparmor->mode = SC_AA_INVALID;
}
#else
apparmor->mode = SC_AA_NOT_APPLICABLE;
apparmor->is_confined = false;
#endif // ifdef HAVE_APPARMOR
}

void
sc_maybe_aa_change_onexec(struct sc_apparmor *apparmor, const char *profile)
{
#ifdef HAVE_APPARMOR
debug("requesting changing of apparmor profile on next exec to %s",
profile);
if (aa_change_onexec(profile) < 0) {
if (secure_getenv("SNAPPY_LAUNCHER_INSIDE_TESTS") == NULL) {
die("cannot change profile for the next exec call");
}
}
#endif // ifdef HAVE_APPARMOR
}

void
sc_maybe_aa_change_hat(struct sc_apparmor *apparmor,
const char *subprofile, unsigned long magic_token)
{
#ifdef HAVE_APPARMOR
if (apparmor->is_confined) {
debug("changing apparmor hat to %s", subprofile);
if (aa_change_hat(subprofile, magic_token) < 0) {
die("cannot change apparmor hat");
}
}
#endif // ifdef HAVE_APPARMOR
}
93 changes: 93 additions & 0 deletions src/apparmor-support.h
@@ -0,0 +1,93 @@
/*
* Copyright (C) 2016 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/

#ifndef SNAP_CONFINE_APPARMOR_SUPPORT_H
#define SNAP_CONFINE_APPARMOR_SUPPORT_H

#include <stdbool.h>

/**
* Type of apparmor confinement.
**/
enum sc_apparmor_mode {
// The enforcement mode was not recognized.
SC_AA_INVALID = -1,
// The enforcement mode is not applicable because apparmor is disabled.
SC_AA_NOT_APPLICABLE = 0,
// The enforcement mode is "enforcing"
SC_AA_ENFORCE = 1,
// The enforcement mode is "complain"
SC_AA_COMPLAIN,
// The enforcement mode is "mixed"
SC_AA_MIXED,
};

/**
* Data required to manage apparmor wrapper.
**/
struct sc_apparmor {
// The mode of enforcement. In addition to the two apparmor defined modes
// can be also SC_AA_INVALID (unknown mode reported by apparmor) and
// SC_AA_NOT_APPLICABLE (when we're not linked with apparmor).
enum sc_apparmor_mode mode;
// Flag indicating that the current process is confined.
bool is_confined;
};

/**
* Initialize apparmor support.
*
* This operation should be done even when apparmor support is disabled at
* compile time. Internally the supplied structure is initialized based on the
* information returned from aa_getcon(2) or if apparmor is disabled at compile
* time, with built-in constants.
*
* The main action performed here is to check if snap-confine is currently
* confined, this information is used later in sc_maybe_change_apparmor_hat()
*
* As with many functions in the snap-confine tree, all errors result in
* process termination.
**/
void sc_init_apparmor_support(struct sc_apparmor *apparmor);

/**
* Maybe call aa_change_onexec(2)
*
* This function does nothing when apparmor support is not enabled at compile
* time. If apparmor is enabled then profile change request is attempted.
*
* As with many functions in the snap-confine tree, all errors result in
* process termination. As an exception, when SNAPPY_LAUNCHER_INSIDE_TESTS
* environment variable is set then the process is not terminated.
**/
void
sc_maybe_aa_change_onexec(struct sc_apparmor *apparmor, const char *profile);

/**
* Maybe call aa_change_hat(2)
*
* This function does nothing when apparmor support is not enabled at compile
* time. If apparmor is enabled then hat change is attempted.
*
* As with many functions in the snap-confine tree, all errors result in
* process termination.
**/
void
sc_maybe_aa_change_hat(struct sc_apparmor *apparmor,
const char *subprofile, unsigned long magic_token);

#endif

0 comments on commit 267ca91

Please sign in to comment.