Skip to content

Commit

Permalink
lsm: rework lsm handling
Browse files Browse the repository at this point in the history
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
  • Loading branch information
Christian Brauner committed Aug 11, 2020
1 parent d333aeb commit d701d72
Show file tree
Hide file tree
Showing 13 changed files with 236 additions and 279 deletions.
10 changes: 6 additions & 4 deletions src/lxc/attach.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
if (!found)
return log_error_errno(NULL, ENOENT, "Failed to read capability bounding set from %s", proc_fn);

info->lsm_label = lsm_process_label_get(pid);
info->lsm_ops = lsm_init();

info->lsm_label = info->lsm_ops->process_label_get(pid);
info->ns_inherited = 0;
for (int i = 0; i < LXC_NS_MAX; i++)
info->ns_fd[i] = -EBADF;
Expand Down Expand Up @@ -777,12 +779,12 @@ 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 = lsm_process_label_set_at(lsm_fd, init_ctx->lsm_label, on_exec);
ret = init_ctx->lsm_ops->process_label_set_at(lsm_fd, init_ctx->lsm_label, on_exec);
close(lsm_fd);
if (ret < 0)
goto on_error;

TRACE("Set %s LSM label to \"%s\"", lsm_name(), init_ctx->lsm_label);
TRACE("Set %s LSM label to \"%s\"", init_ctx->lsm_ops->name, init_ctx->lsm_label);
}

if ((init_ctx->container && init_ctx->container->lxc_conf &&
Expand Down Expand Up @@ -1242,7 +1244,7 @@ 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 = lsm_process_label_fd_get(attached_pid, on_exec);
labelfd = init_ctx->lsm_ops->process_label_fd_get(attached_pid, on_exec);
if (labelfd < 0)
goto close_mainloop;

Expand Down
1 change: 1 addition & 0 deletions src/lxc/attach.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +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;
};

__hidden extern int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
Expand Down
48 changes: 39 additions & 9 deletions src/lxc/conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -3211,13 +3211,49 @@ 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)
{
key_serial_t keyring;
int ret = 0;

if (conf->lsm_se_keyring_context)
ret = lsm_ops->keyring_label_set(conf->lsm_se_keyring_context);
else if (conf->lsm_se_context)
ret = lsm_ops->keyring_label_set(conf->lsm_se_context);
if (ret < 0)
return log_error_errno(-1, errno, "Failed to set keyring context");

/*
* Try to allocate a new session keyring for the container to prevent
* information leaks.
*/
keyring = keyctl(KEYCTL_JOIN_SESSION_KEYRING, prctl_arg(0),
prctl_arg(0), prctl_arg(0), prctl_arg(0));
if (keyring < 0) {
switch (errno) {
case ENOSYS:
DEBUG("The keyctl() syscall is not supported or blocked");
break;
case EACCES:
__fallthrough;
case EPERM:
DEBUG("Failed to access kernel keyring. Continuing...");
break;
default:
SYSERROR("Failed to create kernel keyring");
break;
}
}

return ret;
}

int lxc_setup(struct lxc_handler *handler)
{
__do_close int pty_mnt_fd = -EBADF;
int ret;
const char *lxcpath = handler->lxcpath, *name = handler->name;
struct lxc_conf *lxc_conf = handler->conf;
char *keyring_context = NULL;

ret = lxc_setup_rootfs_prepare_root(lxc_conf, name, lxcpath);
if (ret < 0)
Expand All @@ -3230,15 +3266,9 @@ int lxc_setup(struct lxc_handler *handler)
}

if (!lxc_conf->keyring_disable_session) {
if (lxc_conf->lsm_se_keyring_context) {
keyring_context = lxc_conf->lsm_se_keyring_context;
} else if (lxc_conf->lsm_se_context) {
keyring_context = lxc_conf->lsm_se_context;
}

ret = lxc_setup_keyring(keyring_context);
ret = lxc_setup_keyring(handler->lsm_ops, lxc_conf);
if (ret < 0)
return -1;
return log_error(-1, "Failed to setup container keyring");
}

if (handler->ns_clone_flags & CLONE_NEWNET) {
Expand Down
76 changes: 64 additions & 12 deletions src/lxc/lsm/apparmor.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

lxc_log_define(apparmor, lsm);

/* set by lsm_apparmor_drv_init if true */
/* set by lsm_apparmor_ops_init if true */
static int aa_enabled = 0;
static bool aa_parser_available = false;
static bool aa_supports_unix = false;
Expand Down Expand Up @@ -1128,6 +1128,55 @@ static int apparmor_prepare(struct lxc_conf *conf, const char *lxcpath)
return ret;
}

static int apparmor_keyring_label_set(const char *label)
{
return 0;
}

static int apparmor_process_label_fd_get(pid_t pid, bool on_exec)
{
int ret = -1;
int labelfd;
char path[LXC_LSMATTRLEN];

if (on_exec)
TRACE("On-exec not supported with AppArmor");

ret = snprintf(path, LXC_LSMATTRLEN, "/proc/%d/attr/current", pid);
if (ret < 0 || ret >= LXC_LSMATTRLEN)
return -1;

labelfd = open(path, O_RDWR);
if (labelfd < 0)
return log_error_errno(-errno, errno, "Unable to open AppArmor LSM label file descriptor");

return labelfd;
}

static int apparmor_process_label_set_at(int label_fd, const char *label, bool on_exec)
{
int ret = -1;
size_t len;
__do_free char *command = NULL;

if (on_exec)
log_trace(0, "Changing AppArmor profile on exec not supported");

len = strlen(label) + strlen("changeprofile ") + 1;
command = malloc(len);
if (!command)
return ret_errno(ENOMEM);

ret = snprintf(command, len, "changeprofile %s", label);
if (ret < 0 || (size_t)ret >= len)
return -EFBIG;

ret = lxc_write_nointr(label_fd, command, len - 1);

INFO("Set AppArmor label to \"%s\"", label);
return 0;
}

/*
* apparmor_process_label_set: Set AppArmor process profile
*
Expand Down Expand Up @@ -1169,13 +1218,13 @@ static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf
return 0;
}
tid = lxc_raw_gettid();
label_fd = lsm_process_label_fd_get(tid, on_exec);
label_fd = apparmor_process_label_fd_get(tid, on_exec);
if (label_fd < 0) {
SYSERROR("Failed to change AppArmor profile to %s", label);
return -1;
}

ret = lsm_process_label_set_at(label_fd, label, on_exec);
ret = apparmor_process_label_set_at(label_fd, label, on_exec);
close(label_fd);
if (ret < 0) {
ERROR("Failed to change AppArmor profile to %s", label);
Expand All @@ -1186,16 +1235,19 @@ static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf
return 0;
}

static struct lsm_drv apparmor_drv = {
.name = "AppArmor",
.enabled = apparmor_enabled,
.process_label_get = apparmor_process_label_get,
.process_label_set = apparmor_process_label_set,
.prepare = apparmor_prepare,
.cleanup = apparmor_cleanup,
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,
};

struct lsm_drv *lsm_apparmor_drv_init(void)
const struct lsm_ops *lsm_apparmor_ops_init(void)
{
bool have_mac_admin = false;

Expand Down Expand Up @@ -1225,5 +1277,5 @@ struct lsm_drv *lsm_apparmor_drv_init(void)

out:
aa_enabled = 1;
return &apparmor_drv;
return &apparmor_ops;
}
Loading

0 comments on commit d701d72

Please sign in to comment.