This repository has been archived by the owner on Oct 4, 2023. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #188 from snapcore/aa-support
Add apparmor support module
- Loading branch information
Showing
3 changed files
with
228 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |