Commit 6af96c84 authored by Tycho Andersen's avatar Tycho Andersen Committed by Pavel Emelyanov

lsm: add a --lsm-profile flag

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: 's avatarTycho Andersen <tycho.andersen@canonical.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent c5e002d5
...@@ -2827,14 +2827,19 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core) ...@@ -2827,14 +2827,19 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
if (!creds) if (!creds)
goto err; goto err;
if (creds->lsm_profile) { if (creds->lsm_profile || opts.lsm_supplied) {
char *rendered; char *rendered, *profile;
int ret; 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; return -1;
ret = render_lsm_profile(creds->lsm_profile, &rendered); if (profile) {
ret = render_lsm_profile(profile, &rendered);
if (ret < 0) { if (ret < 0) {
goto err_nv; goto err_nv;
} }
...@@ -2849,6 +2854,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core) ...@@ -2849,6 +2854,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
strncpy(lsm, rendered, lsm_profile_len); strncpy(lsm, rendered, lsm_profile_len);
xfree(rendered); xfree(rendered);
}
} }
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "security.h" #include "security.h"
#include "irmap.h" #include "irmap.h"
#include "fault-injection.h" #include "fault-injection.h"
#include "lsm.h"
#include "setproctitle.h" #include "setproctitle.h"
...@@ -253,6 +254,7 @@ int main(int argc, char *argv[], char *envp[]) ...@@ -253,6 +254,7 @@ int main(int argc, char *argv[], char *envp[])
{ "freeze-cgroup", required_argument, 0, 1068 }, { "freeze-cgroup", required_argument, 0, 1068 },
{ "ghost-limit", required_argument, 0, 1069 }, { "ghost-limit", required_argument, 0, 1069 },
{ "irmap-scan-path", required_argument, 0, 1070 }, { "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[]) ...@@ -498,6 +500,10 @@ int main(int argc, char *argv[], char *envp[])
if (irmap_scan_path_add(optarg)) if (irmap_scan_path_add(optarg))
return -1; return -1;
break; break;
case 1071:
if (parse_lsm_arg(optarg) < 0)
return -1;
break;
case 'M': case 'M':
{ {
char *aux; char *aux;
......
...@@ -95,6 +95,8 @@ struct cr_options { ...@@ -95,6 +95,8 @@ struct cr_options {
bool overlayfs; bool overlayfs;
size_t ghost_limit; size_t ghost_limit;
struct list_head irmap_scan_paths; struct list_head irmap_scan_paths;
bool lsm_supplied;
char *lsm_profile;
}; };
extern struct cr_options opts; extern struct cr_options opts;
......
...@@ -23,7 +23,7 @@ extern int collect_lsm_profile(pid_t, CredsEntry *); ...@@ -23,7 +23,7 @@ extern int collect_lsm_profile(pid_t, CredsEntry *);
* Validate that the LSM profiles can be correctly applied (must happen after * Validate that the LSM profiles can be correctly applied (must happen after
* pstree is set up). * 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 * Render the profile name in the way that the LSM wants it written to
...@@ -31,4 +31,5 @@ int validate_lsm(CredsEntry *ce); ...@@ -31,4 +31,5 @@ int validate_lsm(CredsEntry *ce);
*/ */
int render_lsm_profile(char *profile, char **val); int render_lsm_profile(char *profile, char **val);
extern int parse_lsm_arg(char *arg);
#endif /* __CR_LSM_H__ */ #endif /* __CR_LSM_H__ */
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "config.h" #include "config.h"
#include "pstree.h" #include "pstree.h"
#include "util.h" #include "util.h"
#include "cr_options.h"
#include "protobuf.h" #include "protobuf.h"
#include "protobuf/inventory.pb-c.h" #include "protobuf/inventory.pb-c.h"
...@@ -106,6 +107,14 @@ static int selinux_get_label(pid_t pid, char **output) ...@@ -106,6 +107,14 @@ static int selinux_get_label(pid_t pid, char **output)
void kerndat_lsm(void) 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) { if (access("/sys/kernel/security/apparmor", F_OK) == 0) {
get_label = apparmor_get_label; get_label = apparmor_get_label;
lsmtype = LSMTYPE__APPARMOR; lsmtype = LSMTYPE__APPARMOR;
...@@ -156,7 +165,7 @@ int collect_lsm_profile(pid_t pid, CredsEntry *ce) ...@@ -156,7 +165,7 @@ int collect_lsm_profile(pid_t pid, CredsEntry *ce)
// in inventory.c // in inventory.c
extern Lsmtype image_lsm; extern Lsmtype image_lsm;
int validate_lsm(CredsEntry *ce) int validate_lsm(char *lsm_profile)
{ {
if (image_lsm == LSMTYPE__NO_LSM || image_lsm == lsmtype) if (image_lsm == LSMTYPE__NO_LSM || image_lsm == lsmtype)
return 0; return 0;
...@@ -166,7 +175,7 @@ int validate_lsm(CredsEntry *ce) ...@@ -166,7 +175,7 @@ int validate_lsm(CredsEntry *ce)
* specified an LSM profile. If not, we won't restore anything anyway, * specified an LSM profile. If not, we won't restore anything anyway,
* so it's fine. * so it's fine.
*/ */
if (ce->lsm_profile) { if (lsm_profile) {
pr_err("mismatched lsm types and lsm profile specified\n"); pr_err("mismatched lsm types and lsm profile specified\n");
return -1; return -1;
} }
...@@ -197,3 +206,44 @@ int render_lsm_profile(char *profile, char **val) ...@@ -197,3 +206,44 @@ int render_lsm_profile(char *profile, char **val)
return 0; 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;
}
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