Unverified Commit 76a59906 by Stéphane Graber Committed by GitHub

Merge pull request #3518 from brauner/2020-08-12/fixes

lsm: remove the need for atomic operations
parents b7993256 af04d847
......@@ -93,7 +93,7 @@ static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
info->lsm_ops = lsm_init();
info->lsm_label = info->lsm_ops->process_label_get(pid);
info->lsm_label = info->lsm_ops->process_label_get(info->lsm_ops, pid);
info->ns_inherited = 0;
for (int i = 0; i < LXC_NS_MAX; i++)
info->ns_fd[i] = -EBADF;
......@@ -779,7 +779,8 @@ static int attach_child_main(struct attach_clone_payload *payload)
/* Change into our new LSM profile. */
on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? true : false;
ret = init_ctx->lsm_ops->process_label_set_at(lsm_fd, init_ctx->lsm_label, on_exec);
ret = init_ctx->lsm_ops->process_label_set_at(init_ctx->lsm_ops, lsm_fd,
init_ctx->lsm_label, on_exec);
close(lsm_fd);
if (ret < 0)
goto on_error;
......@@ -1244,7 +1245,8 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
ret = -1;
on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? true : false;
labelfd = init_ctx->lsm_ops->process_label_fd_get(attached_pid, on_exec);
labelfd = init_ctx->lsm_ops->process_label_fd_get(init_ctx->lsm_ops,
attached_pid, on_exec);
if (labelfd < 0)
goto close_mainloop;
......
......@@ -19,7 +19,7 @@ struct lxc_proc_context_info {
unsigned long long capability_mask;
int ns_inherited;
int ns_fd[LXC_NS_MAX];
const struct lsm_ops *lsm_ops;
struct lsm_ops *lsm_ops;
};
__hidden extern int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
......
......@@ -3211,15 +3211,15 @@ static int lxc_setup_boot_id(void)
return 0;
}
static int lxc_setup_keyring(const struct lsm_ops *lsm_ops, const struct lxc_conf *conf)
static int lxc_setup_keyring(struct lsm_ops *lsm_ops, const struct lxc_conf *conf)
{
key_serial_t keyring;
int ret = 0;
if (conf->lsm_se_keyring_context)
ret = lsm_ops->keyring_label_set(conf->lsm_se_keyring_context);
ret = lsm_ops->keyring_label_set(lsm_ops, conf->lsm_se_keyring_context);
else if (conf->lsm_se_context)
ret = lsm_ops->keyring_label_set(conf->lsm_se_context);
ret = lsm_ops->keyring_label_set(lsm_ops, conf->lsm_se_context);
if (ret < 0)
return log_error_errno(-1, errno, "Failed to set keyring context");
......
......@@ -4,7 +4,6 @@
#define _GNU_SOURCE 1
#endif
#include <errno.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mount.h>
......@@ -25,15 +24,6 @@
lxc_log_define(apparmor, lsm);
/* set by lsm_apparmor_ops_init if true */
static atomic_int aa_enabled ;
static atomic_int aa_parser_available = -1;
static atomic_int aa_supports_unix;
static atomic_int aa_can_stack;
static atomic_int aa_is_stacked;
static atomic_int aa_admin;
static atomic_int mount_features_enabled;
#define AA_DEF_PROFILE "lxc-container-default"
#define AA_DEF_PROFILE_CGNS "lxc-container-default-cgns"
#define AA_MOUNT_RESTR "/sys/kernel/security/apparmor/features/mount/mask"
......@@ -373,23 +363,18 @@ static const char AA_PROFILE_UNPRIVILEGED[] =
" mount options=(ro,remount),\n"
;
static bool check_mount_feature_enabled(void)
{
return atomic_load(&mount_features_enabled);
}
static void load_mount_features_enabled(void)
static void load_mount_features_enabled(struct lsm_ops *ops)
{
struct stat statbuf;
int ret;
ret = stat(AA_MOUNT_RESTR, &statbuf);
if (ret == 0)
atomic_store(&mount_features_enabled, 1);
ops->aa_mount_features_enabled = 1;
}
/* aa_getcon is not working right now. Use our hand-rolled version below */
static int apparmor_enabled(void)
static int apparmor_enabled(struct lsm_ops *ops)
{
__do_fclose FILE *fin = NULL;
char e;
......@@ -398,16 +383,17 @@ static int apparmor_enabled(void)
fin = fopen_cloexec(AA_ENABLED_FILE, "r");
if (!fin)
return 0;
ret = fscanf(fin, "%c", &e);
if (ret == 1 && e == 'Y') {
load_mount_features_enabled();
load_mount_features_enabled(ops);
return 1;
}
return 0;
}
static char *apparmor_process_label_get(pid_t pid)
static char *apparmor_process_label_get(struct lsm_ops *ops, pid_t pid)
{
char path[100], *space;
int ret;
......@@ -459,9 +445,9 @@ again:
* Probably makes sense to reorganize these to only read
* the label once
*/
static bool apparmor_am_unconfined(void)
static bool apparmor_am_unconfined(struct lsm_ops *ops)
{
char *p = apparmor_process_label_get(lxc_raw_getpid());
char *p = apparmor_process_label_get(ops, lxc_raw_getpid());
bool ret = false;
if (!p || strcmp(p, "unconfined") == 0)
ret = true;
......@@ -542,14 +528,18 @@ static inline char *apparmor_namespace(const char *ctname, const char *lxcpath)
* do not have ERROR/... macros available, so there are some fprintf(stderr)s
* in there.
*/
static bool check_apparmor_parser_version()
static bool check_apparmor_parser_version(struct lsm_ops *ops)
{
int major = 0, minor = 0, micro = 0, ret = 0;
struct lxc_popen_FILE *parserpipe;
int rc;
if (atomic_load(&aa_parser_available) >= 0)
switch (ops->aa_parser_available) {
case 0:
return false;
case 1:
return true;
}
parserpipe = lxc_popen("apparmor_parser --version");
if (!parserpipe) {
......@@ -578,12 +568,12 @@ static bool check_apparmor_parser_version()
}
if ((major > 2) || (major == 2 && minor > 10) || (major == 2 && minor == 10 && micro >= 95))
atomic_store(&aa_supports_unix, 1);
ops->aa_supports_unix = 1;
ret = 1;
out:
atomic_store(&aa_parser_available, ret);
ops->aa_parser_available = ret;
return ret == 1;
}
......@@ -730,7 +720,7 @@ static void append_all_remount_rules(char **profile, size_t *size)
}
}
static char *get_apparmor_profile_content(struct lxc_conf *conf, const char *lxcpath)
static char *get_apparmor_profile_content(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath)
{
char *profile, *profile_name_full;
size_t size;
......@@ -749,7 +739,7 @@ static char *get_apparmor_profile_content(struct lxc_conf *conf, const char *lxc
append_all_remount_rules(&profile, &size);
if (atomic_load(&aa_supports_unix))
if (ops->aa_supports_unix)
must_append_sized(&profile, &size, AA_PROFILE_UNIX_SOCKETS,
STRARRAYLEN(AA_PROFILE_UNIX_SOCKETS));
......@@ -757,7 +747,7 @@ static char *get_apparmor_profile_content(struct lxc_conf *conf, const char *lxc
must_append_sized(&profile, &size, AA_PROFILE_CGROUP_NAMESPACES,
STRARRAYLEN(AA_PROFILE_CGROUP_NAMESPACES));
if (atomic_load(&aa_can_stack) && !atomic_load(&aa_is_stacked)) {
if (ops->aa_can_stack && !ops->aa_is_stacked) {
char *namespace, *temp;
must_append_sized(&profile, &size, AA_PROFILE_STACKING_BASE,
......@@ -780,7 +770,7 @@ static char *get_apparmor_profile_content(struct lxc_conf *conf, const char *lxc
must_append_sized(&profile, &size, AA_PROFILE_NESTING_BASE,
STRARRAYLEN(AA_PROFILE_NESTING_BASE));
if (!atomic_load(&aa_can_stack) || atomic_load(&aa_is_stacked)) {
if (!ops->aa_can_stack || ops->aa_is_stacked) {
char *temp;
temp = must_concat(NULL, " change_profile -> \"",
......@@ -837,11 +827,11 @@ static char *make_apparmor_namespace_path(const char *ctname, const char *lxcpat
return ret;
}
static bool make_apparmor_namespace(struct lxc_conf *conf, const char *lxcpath)
static bool make_apparmor_namespace(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath)
{
char *path;
if (!atomic_load(&aa_can_stack) || atomic_load(&aa_is_stacked))
if (!ops->aa_can_stack || ops->aa_is_stacked)
return true;
path = make_apparmor_namespace_path(conf->name, lxcpath);
......@@ -921,7 +911,7 @@ static void remove_apparmor_profile(struct lxc_conf *conf, const char *lxcpath)
free(path);
}
static int load_apparmor_profile(struct lxc_conf *conf, const char *lxcpath)
static int load_apparmor_profile(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath)
{
struct stat profile_sb;
size_t content_len;
......@@ -930,7 +920,7 @@ static int load_apparmor_profile(struct lxc_conf *conf, const char *lxcpath)
char *profile_path = NULL, *old_content = NULL, *new_content = NULL;
int profile_fd = -1;
if (!make_apparmor_namespace(conf, lxcpath))
if (!make_apparmor_namespace(ops, conf, lxcpath))
return -1;
/* In order to avoid forcing a profile parse (potentially slow) on
......@@ -966,7 +956,7 @@ static int load_apparmor_profile(struct lxc_conf *conf, const char *lxcpath)
goto out;
}
new_content = get_apparmor_profile_content(conf, lxcpath);
new_content = get_apparmor_profile_content(ops, conf, lxcpath);
if (!new_content)
goto out;
......@@ -1024,9 +1014,9 @@ out_ok:
* Ensure that the container's policy namespace is unloaded to free kernel
* memory. This does not delete the policy from disk or cache.
*/
static void apparmor_cleanup(struct lxc_conf *conf, const char *lxcpath)
static void apparmor_cleanup(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath)
{
if (!atomic_load(&aa_admin))
if (!ops->aa_admin)
return;
if (!conf->lsm_aa_profile_created)
......@@ -1038,16 +1028,14 @@ static void apparmor_cleanup(struct lxc_conf *conf, const char *lxcpath)
remove_apparmor_profile(conf, lxcpath);
}
static int apparmor_prepare(struct lxc_conf *conf, const char *lxcpath)
static int apparmor_prepare(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath)
{
int ret = -1;
const char *label;
char *curlabel = NULL, *genlabel = NULL;
if (!atomic_load(&aa_enabled)) {
ERROR("AppArmor not enabled");
return -1;
}
if (!ops->aa_enabled)
return log_error(-1, "AppArmor not enabled");
label = conf->lsm_aa_profile;
......@@ -1059,13 +1047,13 @@ static int apparmor_prepare(struct lxc_conf *conf, const char *lxcpath)
}
if (label && strcmp(label, AA_GENERATED) == 0) {
if (!check_apparmor_parser_version()) {
if (!check_apparmor_parser_version(ops)) {
ERROR("Cannot use generated profile: apparmor_parser not available");
goto out;
}
/* auto-generate profile based on available/requested security features */
if (load_apparmor_profile(conf, lxcpath) != 0) {
if (load_apparmor_profile(ops, conf, lxcpath) != 0) {
ERROR("Failed to load generated AppArmor profile");
goto out;
}
......@@ -1076,7 +1064,7 @@ static int apparmor_prepare(struct lxc_conf *conf, const char *lxcpath)
goto out;
}
if (atomic_load(&aa_can_stack) && !atomic_load(&aa_is_stacked)) {
if (ops->aa_can_stack && !ops->aa_is_stacked) {
char *namespace = apparmor_namespace(conf->name, lxcpath);
size_t llen = strlen(genlabel);
must_append_sized(&genlabel, &llen, "//&:", STRARRAYLEN("//&:"));
......@@ -1088,9 +1076,9 @@ static int apparmor_prepare(struct lxc_conf *conf, const char *lxcpath)
label = genlabel;
}
curlabel = apparmor_process_label_get(lxc_raw_getpid());
curlabel = apparmor_process_label_get(ops, lxc_raw_getpid());
if (!atomic_load(&aa_can_stack) && aa_needs_transition(curlabel)) {
if (!ops->aa_can_stack && aa_needs_transition(curlabel)) {
/* we're already confined, and stacking isn't supported */
if (!label || strcmp(curlabel, label) == 0) {
......@@ -1110,7 +1098,7 @@ static int apparmor_prepare(struct lxc_conf *conf, const char *lxcpath)
label = AA_DEF_PROFILE;
}
if (!check_mount_feature_enabled() && strcmp(label, "unconfined") != 0) {
if (!ops->aa_mount_features_enabled && strcmp(label, "unconfined") != 0) {
WARN("Incomplete AppArmor support in your kernel");
if (!conf->lsm_aa_allow_incomplete) {
ERROR("If you really want to start this container, set");
......@@ -1127,18 +1115,18 @@ out:
if (genlabel) {
free(genlabel);
if (ret != 0)
apparmor_cleanup(conf, lxcpath);
apparmor_cleanup(ops, conf, lxcpath);
}
free(curlabel);
return ret;
}
static int apparmor_keyring_label_set(const char *label)
static int apparmor_keyring_label_set(struct lsm_ops *ops, const char *label)
{
return 0;
}
static int apparmor_process_label_fd_get(pid_t pid, bool on_exec)
static int apparmor_process_label_fd_get(struct lsm_ops *ops, pid_t pid, bool on_exec)
{
int ret = -1;
int labelfd;
......@@ -1158,7 +1146,7 @@ static int apparmor_process_label_fd_get(pid_t pid, bool on_exec)
return labelfd;
}
static int apparmor_process_label_set_at(int label_fd, const char *label, bool on_exec)
static int apparmor_process_label_set_at(struct lsm_ops *ops, int label_fd, const char *label, bool on_exec)
{
int ret = -1;
size_t len;
......@@ -1194,17 +1182,15 @@ static int apparmor_process_label_set_at(int label_fd, const char *label, bool o
*
* Notes: This relies on /proc being available.
*/
static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf,
bool on_exec)
static int apparmor_process_label_set(struct lsm_ops *ops, const char *inlabel,
struct lxc_conf *conf, bool on_exec)
{
int label_fd, ret;
pid_t tid;
const char *label;
if (!atomic_load(&aa_enabled)) {
ERROR("AppArmor not enabled");
return -1;
}
if (!ops->aa_enabled)
return log_error(-1, "AppArmor not enabled");
label = inlabel ? inlabel : conf->lsm_aa_profile_computed;
if (!label) {
......@@ -1218,18 +1204,18 @@ static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf
return 0;
}
if (strcmp(label, "unconfined") == 0 && apparmor_am_unconfined()) {
if (strcmp(label, "unconfined") == 0 && apparmor_am_unconfined(ops)) {
INFO("AppArmor profile unchanged");
return 0;
}
tid = lxc_raw_gettid();
label_fd = apparmor_process_label_fd_get(tid, on_exec);
label_fd = apparmor_process_label_fd_get(ops, tid, on_exec);
if (label_fd < 0) {
SYSERROR("Failed to change AppArmor profile to %s", label);
return -1;
}
ret = apparmor_process_label_set_at(label_fd, label, on_exec);
ret = apparmor_process_label_set_at(ops, label_fd, label, on_exec);
close(label_fd);
if (ret < 0) {
ERROR("Failed to change AppArmor profile to %s", label);
......@@ -1241,44 +1227,49 @@ static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf
}
static struct lsm_ops apparmor_ops = {
.name = "AppArmor",
.cleanup = apparmor_cleanup,
.enabled = apparmor_enabled,
.keyring_label_set = apparmor_keyring_label_set,
.prepare = apparmor_prepare,
.process_label_fd_get = apparmor_process_label_fd_get,
.process_label_get = apparmor_process_label_get,
.process_label_set = apparmor_process_label_set,
.process_label_set_at = apparmor_process_label_set_at,
.name = "AppArmor",
.aa_admin = -1,
.aa_can_stack = -1,
.aa_enabled = -1,
.aa_is_stacked = -1,
.aa_mount_features_enabled = -1,
.aa_parser_available = -1,
.aa_supports_unix = -1,
.cleanup = apparmor_cleanup,
.enabled = apparmor_enabled,
.keyring_label_set = apparmor_keyring_label_set,
.prepare = apparmor_prepare,
.process_label_fd_get = apparmor_process_label_fd_get,
.process_label_get = apparmor_process_label_get,
.process_label_set = apparmor_process_label_set,
.process_label_set_at = apparmor_process_label_set_at,
};
const struct lsm_ops *lsm_apparmor_ops_init(void)
struct lsm_ops *lsm_apparmor_ops_init(void)
{
bool have_mac_admin = false;
bool can_stack, is_stacked;
if (!apparmor_enabled())
apparmor_ops.aa_admin = 0;
apparmor_ops.aa_can_stack = 0;
apparmor_ops.aa_enabled = 0;
apparmor_ops.aa_is_stacked = 0;
apparmor_ops.aa_mount_features_enabled = 0;
apparmor_ops.aa_parser_available = -1;
apparmor_ops.aa_supports_unix = 0;
if (!apparmor_enabled(&apparmor_ops))
return NULL;
can_stack = apparmor_can_stack();
if (can_stack) {
atomic_store(&aa_can_stack, 1);
is_stacked = file_is_yes("/sys/kernel/security/apparmor/.ns_stacked");
if (is_stacked)
atomic_store(&aa_is_stacked, 1);
}
apparmor_ops.aa_can_stack = apparmor_can_stack();
if (apparmor_ops.aa_can_stack)
apparmor_ops.aa_is_stacked = file_is_yes("/sys/kernel/security/apparmor/.ns_stacked");
#if HAVE_LIBCAP
have_mac_admin = lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE);
apparmor_ops.aa_admin = lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE);
#endif
if (!have_mac_admin)
if (!apparmor_ops.aa_admin)
WARN("Per-container AppArmor profiles are disabled because the mac_admin capability is missing");
else if (am_host_unpriv() && !atomic_load(&aa_is_stacked))
else if (am_host_unpriv() && !apparmor_ops.aa_is_stacked)
WARN("Per-container AppArmor profiles are disabled because LXC is running in an unprivileged container without stacking");
else
atomic_store(&aa_admin, 1);
atomic_store(&aa_enabled, 1);
apparmor_ops.aa_enabled = 1;
return &apparmor_ops;
}
......@@ -21,9 +21,9 @@ __hidden extern struct lsm_ops *lsm_apparmor_ops_init(void);
__hidden extern struct lsm_ops *lsm_selinux_ops_init(void);
__hidden extern struct lsm_ops *lsm_nop_ops_init(void);
const struct lsm_ops *lsm_init(void)
struct lsm_ops *lsm_init(void)
{
const struct lsm_ops *ops = NULL;
struct lsm_ops *ops = NULL;
#if HAVE_APPARMOR
ops = lsm_apparmor_ops_init();
......
......@@ -14,16 +14,25 @@ struct lxc_conf;
struct lsm_ops {
const char *name;
int (*enabled)(void);
char *(*process_label_get)(pid_t pid);
int (*process_label_set)(const char *label, struct lxc_conf *conf, bool on_exec);
int (*keyring_label_set)(const char *label);
int (*prepare)(struct lxc_conf *conf, const char *lxcpath);
void (*cleanup)(struct lxc_conf *conf, const char *lxcpath);
int (*process_label_fd_get)(pid_t pid, bool on_exec);
int (*process_label_set_at)(int label_fd, const char *label, bool on_exec);
/* AppArmor specific fields. */
int aa_enabled;
int aa_parser_available;
int aa_supports_unix;
int aa_can_stack;
int aa_is_stacked;
int aa_admin;
int aa_mount_features_enabled;
int (*enabled)(struct lsm_ops *ops);
char *(*process_label_get)(struct lsm_ops *ops, pid_t pid);
int (*process_label_set)(struct lsm_ops *ops, const char *label, struct lxc_conf *conf, bool on_exec);
int (*keyring_label_set)(struct lsm_ops *ops, const char *label);
int (*prepare)(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath);
void (*cleanup)(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath);
int (*process_label_fd_get)(struct lsm_ops *ops, pid_t pid, bool on_exec);
int (*process_label_set_at)(struct lsm_ops *ops, int label_fd, const char *label, bool on_exec);
};
__hidden extern const struct lsm_ops *lsm_init(void);
__hidden extern struct lsm_ops *lsm_init(void);
#endif /* __LXC_LSM_H */
......@@ -8,59 +8,66 @@
#include "config.h"
#include "lsm/lsm.h"
static char *nop_process_label_get(pid_t pid)
static char *nop_process_label_get(struct lsm_ops *ops, pid_t pid)
{
return NULL;
}
static int nop_process_label_set(const char *label, struct lxc_conf *conf,
static int nop_process_label_set(struct lsm_ops *ops, const char *label, struct lxc_conf *conf,
bool on_exec)
{
return 0;
}
static int nop_enabled(void)
static int nop_enabled(struct lsm_ops *ops)
{
return 0;
}
static int nop_keyring_label_set(const char *label)
static int nop_keyring_label_set(struct lsm_ops *ops, const char *label)
{
return 0;
}
static int nop_prepare(struct lxc_conf *conf, const char *lxcpath)
static int nop_prepare(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath)
{
return 0;
}
static void nop_cleanup(struct lxc_conf *conf, const char *lxcpath)
static void nop_cleanup(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath)
{
}
static int nop_process_label_fd_get(pid_t pid, bool on_exec)
static int nop_process_label_fd_get(struct lsm_ops *ops, pid_t pid, bool on_exec)
{
return 0;
}
static int nop_process_label_set_at(int label_fd, const char *label, bool on_exec)
static int nop_process_label_set_at(struct lsm_ops *ops, int label_fd, const char *label, bool on_exec)
{
return 0;
}
static struct lsm_ops nop_ops = {
.name = "nop",
.cleanup = nop_cleanup,
.enabled = nop_enabled,
.keyring_label_set = nop_keyring_label_set,
.prepare = nop_prepare,
.process_label_fd_get = nop_process_label_fd_get,
.process_label_get = nop_process_label_get,
.process_label_set = nop_process_label_set,
.process_label_set_at = nop_process_label_set_at,
.name = "nop",
.aa_admin = -1,
.aa_can_stack = -1,
.aa_enabled = -1,
.aa_is_stacked = -1,
.aa_mount_features_enabled = -1,
.aa_parser_available = -1,
.aa_supports_unix = -1,
.cleanup = nop_cleanup,
.enabled = nop_enabled,
.keyring_label_set = nop_keyring_label_set,
.prepare = nop_prepare,
.process_label_fd_get = nop_process_label_fd_get,
.process_label_get = nop_process_label_get,
.process_label_set = nop_process_label_set,
.process_label_set_at = nop_process_label_set_at,
};
const struct lsm_ops *lsm_nop_ops_init(void)
struct lsm_ops *lsm_nop_ops_init(void)
{
return &nop_ops;
}
......@@ -30,7 +30,7 @@ lxc_log_define(selinux, lsm);
*
* Note that this relies on /proc being available.
*/
static char *selinux_process_label_get(pid_t pid)
static char *selinux_process_label_get(struct lsm_ops *ops, pid_t pid)
{
char *label;
......@@ -52,8 +52,8 @@ static char *selinux_process_label_get(pid_t pid)
*
* Notes: This relies on /proc being available.
*/
static int selinux_process_label_set(const char *inlabel, struct lxc_conf *conf,
bool on_exec)
static int selinux_process_label_set(struct lsm_ops *ops, const char *inlabel,
struct lxc_conf *conf, bool on_exec)
{
int ret;
const char *label;
......@@ -84,21 +84,21 @@ static int selinux_process_label_set(const char *inlabel, struct lxc_conf *conf,
*
* Returns 0 on success, < 0 on failure
*/
static int selinux_keyring_label_set(const char *label)
static int selinux_keyring_label_set(struct lsm_ops *ops, const char *label)
{
return setkeycreatecon_raw(label);
}
static int selinux_prepare(struct lxc_conf *conf, const char *lxcpath)
static int selinux_prepare(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath)
{
return 0;
}
static void selinux_cleanup(struct lxc_conf *conf, const char *lxcpath)
static void selinux_cleanup(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath)
{
}
static int selinux_process_label_fd_get(pid_t pid, bool on_exec)
static int selinux_process_label_fd_get(struct lsm_ops *ops, pid_t pid, bool on_exec)
{
int ret = -1;
int labelfd;
......@@ -118,7 +118,7 @@ static int selinux_process_label_fd_get(pid_t pid, bool on_exec)
return labelfd;
}
static int selinux_process_label_set_at(int label_fd, const char *label, bool on_exec)
static int selinux_process_label_set_at(struct lsm_ops *ops, int label_fd, const char *label, bool on_exec)
{
int ret;
......@@ -133,19 +133,31 @@ static int selinux_process_label_set_at(int label_fd, const char *label, bool on
return 0;
}
static int selinux_enabled(struct lsm_ops *ops)
{
return is_selinux_enabled();
}
static struct lsm_ops selinux_ops = {
.name = "SELinux",
.cleanup = selinux_cleanup,
.enabled = is_selinux_enabled,
.keyring_label_set = selinux_keyring_label_set,
.prepare = selinux_prepare,
.process_label_fd_get = selinux_process_label_fd_get,
.process_label_get = selinux_process_label_get,
.process_label_set = selinux_process_label_set,
.process_label_set_at = selinux_process_label_set_at,
.name = "SELinux",
.aa_admin = -1,
.aa_can_stack = -1,
.aa_enabled = -1,
.aa_is_stacked = -1,
.aa_mount_features_enabled = -1,
.aa_parser_available = -1,
.aa_supports_unix = -1,
.cleanup = selinux_cleanup,
.enabled = selinux_enabled,
.keyring_label_set = selinux_keyring_label_set,
.prepare = selinux_prepare,
.process_label_fd_get = selinux_process_label_fd_get,
.process_label_get = selinux_process_label_get,
.process_label_set = selinux_process_label_set,
.process_label_set_at = selinux_process_label_set_at,
};
const struct lsm_ops *lsm_selinux_ops_init(void)
struct lsm_ops *lsm_selinux_ops_init(void)
{
if (!is_selinux_enabled())
return NULL;
......
......@@ -827,7 +827,7 @@ int lxc_init(const char *name, struct lxc_handler *handler)
return log_error(-1, "Failed loading seccomp policy");
TRACE("Read seccomp policy");
ret = handler->lsm_ops->prepare(conf, handler->lxcpath);
ret = handler->lsm_ops->prepare(handler->lsm_ops, conf, handler->lxcpath);
if (ret < 0) {
ERROR("Failed to initialize LSM");
goto out_delete_terminal;
......@@ -918,7 +918,7 @@ void lxc_end(struct lxc_handler *handler)
while (namespace_count--)
free(namespaces[namespace_count]);
handler->lsm_ops->cleanup(handler->conf, handler->lxcpath);
handler->lsm_ops->cleanup(handler->lsm_ops, handler->conf, handler->lxcpath);
if (cgroup_ops) {
cgroup_ops->payload_destroy(cgroup_ops, handler);
......@@ -1269,7 +1269,7 @@ static int do_start(void *data)
}
/* Set the label to change to when we exec(2) the container's init. */
ret = handler->lsm_ops->process_label_set(NULL, handler->conf, true);
ret = handler->lsm_ops->process_label_set(handler->lsm_ops, NULL, handler->conf, true);
if (ret < 0)
goto out_warn_father;
......
......@@ -128,7 +128,8 @@ struct lxc_handler {
/* Internal fds that always need to stay open. */
int keep_fds[3];
const struct lsm_ops *lsm_ops;
/* Static memory, don't free. */
struct lsm_ops *lsm_ops;
};
struct execute_args {
......
......@@ -47,11 +47,11 @@
static const char *lsm_config_key = NULL;
static const char *lsm_label = NULL;
const struct lsm_ops *lsm_ops;
struct lsm_ops *lsm_ops;
static void test_lsm_detect(void)
{
if (lsm_ops->enabled()) {
if (lsm_ops->enabled(lsm_ops)) {
if (!strcmp(lsm_ops->name, "SELinux")) {
lsm_config_key = "lxc.selinux.context";
lsm_label = "unconfined_u:unconfined_r:lxc_t:s0-s0:c0.c1023";
......@@ -80,7 +80,7 @@ static void test_attach_lsm_set_config(struct lxc_container *ct)
static int test_attach_lsm_func_func(void* payload)
{
TSTOUT("%s", lsm_ops->process_label_get(syscall(SYS_getpid)));
TSTOUT("%s", lsm_ops->process_label_get(lsm_ops, syscall(SYS_getpid)));
return 0;
}
......@@ -330,7 +330,7 @@ static struct lxc_container *test_ct_create(const char *lxcpath,
goto out2;
}
if (lsm_ops->enabled())
if (lsm_ops->enabled(lsm_ops))
test_attach_lsm_set_config(ct);
ct->want_daemonize(ct, true);
......@@ -370,7 +370,7 @@ static int test_attach(const char *lxcpath, const char *name, const char *templa
goto err2;
}
if (lsm_ops->enabled()) {
if (lsm_ops->enabled(lsm_ops)) {
ret = test_attach_lsm_cmd(ct);
if (ret < 0) {
TSTERR("attach lsm cmd test failed");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment