[CRIU] [PATCH v2] lsm: add a --lsm-profile flag
Tycho Andersen
tycho.andersen at canonical.com
Fri Dec 4 07:55:00 PST 2015
In LXD, we use the container name in the LSM profile. If the container name
is changed on migrate (on the host side), we want to use a different LSM
profile name (a. la. --cgroup-root). This flag adds that support.
v2: remove unused field, add comment about double detection in
kerndat_lsm()
Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
cr-restore.c | 36 ++++++++++++++++++++---------------
crtools.c | 6 ++++++
include/cr_options.h | 2 ++
include/lsm.h | 3 ++-
lsm.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++--
5 files changed, 83 insertions(+), 18 deletions(-)
diff --git a/cr-restore.c b/cr-restore.c
index 1c0c641..3c636b9 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -2827,29 +2827,35 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
if (!creds)
goto err;
- if (creds->lsm_profile) {
- char *rendered;
+ if (creds->lsm_profile || opts.lsm_supplied) {
+ char *rendered, *profile;
int ret;
- if (validate_lsm(creds) < 0)
+ profile = creds->lsm_profile;
+ if (opts.lsm_supplied)
+ profile = opts.lsm_profile;
+
+ if (validate_lsm(profile) < 0)
return -1;
- ret = render_lsm_profile(creds->lsm_profile, &rendered);
- if (ret < 0) {
- goto err_nv;
- }
+ if (profile) {
+ ret = render_lsm_profile(profile, &rendered);
+ if (ret < 0) {
+ goto err_nv;
+ }
+
+ lsm_pos = rst_mem_cpos(RM_PRIVATE);
+ lsm_profile_len = strlen(rendered);
+ lsm = rst_mem_alloc(lsm_profile_len + 1, RM_PRIVATE);
+ if (!lsm) {
+ xfree(rendered);
+ goto err_nv;
+ }
- lsm_pos = rst_mem_cpos(RM_PRIVATE);
- lsm_profile_len = strlen(rendered);
- lsm = rst_mem_alloc(lsm_profile_len + 1, RM_PRIVATE);
- if (!lsm) {
+ strncpy(lsm, rendered, lsm_profile_len);
xfree(rendered);
- goto err_nv;
}
- strncpy(lsm, rendered, lsm_profile_len);
- xfree(rendered);
-
}
if (seccomp_filters_get_rst_pos(core, &n_seccomp_filters, &seccomp_filter_pos) < 0)
diff --git a/crtools.c b/crtools.c
index d3812a1..68756a0 100644
--- a/crtools.c
+++ b/crtools.c
@@ -41,6 +41,7 @@
#include "security.h"
#include "irmap.h"
#include "fault-injection.h"
+#include "lsm.h"
#include "setproctitle.h"
@@ -253,6 +254,7 @@ int main(int argc, char *argv[], char *envp[])
{ "freeze-cgroup", required_argument, 0, 1068 },
{ "ghost-limit", required_argument, 0, 1069 },
{ "irmap-scan-path", required_argument, 0, 1070 },
+ { "lsm-profile", required_argument, 0, 1071 },
{ },
};
@@ -498,6 +500,10 @@ int main(int argc, char *argv[], char *envp[])
if (irmap_scan_path_add(optarg))
return -1;
break;
+ case 1071:
+ if (parse_lsm_arg(optarg) < 0)
+ return -1;
+ break;
case 'M':
{
char *aux;
diff --git a/include/cr_options.h b/include/cr_options.h
index eac7283..d0c74fe 100644
--- a/include/cr_options.h
+++ b/include/cr_options.h
@@ -95,6 +95,8 @@ struct cr_options {
bool overlayfs;
size_t ghost_limit;
struct list_head irmap_scan_paths;
+ bool lsm_supplied;
+ char *lsm_profile;
};
extern struct cr_options opts;
diff --git a/include/lsm.h b/include/lsm.h
index 1409acd..bd13ef7 100644
--- a/include/lsm.h
+++ b/include/lsm.h
@@ -23,7 +23,7 @@ extern int collect_lsm_profile(pid_t, CredsEntry *);
* Validate that the LSM profiles can be correctly applied (must happen after
* pstree is set up).
*/
-int validate_lsm(CredsEntry *ce);
+int validate_lsm(char *profile);
/*
* Render the profile name in the way that the LSM wants it written to
@@ -31,4 +31,5 @@ int validate_lsm(CredsEntry *ce);
*/
int render_lsm_profile(char *profile, char **val);
+extern int parse_lsm_arg(char *arg);
#endif /* __CR_LSM_H__ */
diff --git a/lsm.c b/lsm.c
index c960611..de40c7b 100644
--- a/lsm.c
+++ b/lsm.c
@@ -7,6 +7,7 @@
#include "config.h"
#include "pstree.h"
#include "util.h"
+#include "cr_options.h"
#include "protobuf.h"
#include "protobuf/inventory.pb-c.h"
@@ -106,6 +107,14 @@ static int selinux_get_label(pid_t pid, char **output)
void kerndat_lsm(void)
{
+ /* On restore, if someone passes --lsm-profile, we might end up doing
+ * detection twice, once during flag parsing and once for
+ * kerndat_init_rst(). Let's detect when we've already done detection
+ * and not do it again.
+ */
+ if (name)
+ return;
+
if (access("/sys/kernel/security/apparmor", F_OK) == 0) {
get_label = apparmor_get_label;
lsmtype = LSMTYPE__APPARMOR;
@@ -156,7 +165,7 @@ int collect_lsm_profile(pid_t pid, CredsEntry *ce)
// in inventory.c
extern Lsmtype image_lsm;
-int validate_lsm(CredsEntry *ce)
+int validate_lsm(char *lsm_profile)
{
if (image_lsm == LSMTYPE__NO_LSM || image_lsm == lsmtype)
return 0;
@@ -166,7 +175,7 @@ int validate_lsm(CredsEntry *ce)
* specified an LSM profile. If not, we won't restore anything anyway,
* so it's fine.
*/
- if (ce->lsm_profile) {
+ if (lsm_profile) {
pr_err("mismatched lsm types and lsm profile specified\n");
return -1;
}
@@ -197,3 +206,44 @@ int render_lsm_profile(char *profile, char **val)
return 0;
}
+
+int parse_lsm_arg(char *arg)
+{
+ char *aux;
+
+ kerndat_lsm();
+
+ aux = strchr(arg, ':');
+ if (aux == NULL) {
+ pr_err("invalid argument %s for --lsm-profile", arg);
+ return -1;
+ }
+
+ *aux = '\0';
+ aux++;
+
+ if (strcmp(arg, "apparmor") == 0) {
+ if (lsmtype != LSMTYPE__APPARMOR) {
+ pr_err("apparmor LSM specified but apparmor not supported by kernel\n");
+ return -1;
+ }
+
+ opts.lsm_profile = aux;
+ } else if (strcmp(arg, "selinux") == 0) {
+ if (lsmtype != LSMTYPE__SELINUX) {
+ pr_err("selinux LSM specified but selinux not supported by kernel\n");
+ return -1;
+ }
+
+ opts.lsm_profile = aux;
+ } else if (strcmp(arg, "none") == 0) {
+ opts.lsm_profile = NULL;
+ } else {
+ pr_err("unknown lsm %s\n", arg);
+ return -1;
+ }
+
+ opts.lsm_supplied = true;
+
+ return 0;
+}
--
2.6.2
More information about the CRIU
mailing list