[lxc-devel] [PATCH] attach: join apparmor profile

Stéphane Graber stgraber at ubuntu.com
Fri Mar 1 23:20:13 UTC 2013


On 03/01/2013 03:25 PM, Serge Hallyn wrote:
> This patch enables lxc-attach to join the profile of the container it
> is attaching to.  Builds/runs fine with apparmor enabled and disabled.
> 
> Export new aa_get_profile(), and use it for attach_apparmor, but also
> handle profile names longer than 100 chars in lxc_start apparmor
> support.
> 
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>

Looks good, test built with/without apparmor to confirm that we don't
get weird failures and it all looks good.

Acked-by: Stéphane Graber <stgraber at ubuntu.com>

> ---
>  src/lxc/apparmor.c   | 105 ++++++++++++++++++++++++++++++++++++++++-----------
>  src/lxc/apparmor.h   |  22 ++++++++++-
>  src/lxc/attach.c     |   2 +
>  src/lxc/attach.h     |   1 +
>  src/lxc/lxc_attach.c |   6 +++
>  5 files changed, 111 insertions(+), 25 deletions(-)
> 
> diff --git a/src/lxc/apparmor.c b/src/lxc/apparmor.c
> index ae3d8f7..c2d1d2f 100644
> --- a/src/lxc/apparmor.c
> +++ b/src/lxc/apparmor.c
> @@ -1,4 +1,5 @@
>  #include <stdio.h>
> +#include <stdlib.h>
>  #include <unistd.h>
>  #include <errno.h>
>  #include <sys/types.h>
> @@ -16,21 +17,58 @@ lxc_log_define(lxc_apparmor, lxc);
>  #define AA_MOUNT_RESTR "/sys/kernel/security/apparmor/features/mount/mask"
>  #define AA_ENABLED_FILE "/sys/module/apparmor/parameters/enabled"
>  
> -static int aa_am_unconfined(void)
> +
> +/* caller must free the returned profile */
> +extern char *aa_get_profile(pid_t pid)
>  {
> +	char path[100], *space;
>  	int ret;
> -	char path[100], p[100];
> -	sprintf(path, "/proc/%d/attr/current", getpid());
> -	FILE *f = fopen(path, "r");
> -	if (!f)
> -		return 0;
> -	ret = fscanf(f, "%99s", p);
> +	char *buf = NULL;
> +	int sz = 0;
> +	FILE *f;
> +
> +	ret = snprintf(path, 100, "/proc/%d/attr/current", pid);
> +	if (ret < 0 || ret >= 100) {
> +		ERROR("path name too long");
> +		return NULL;
> +	}
> +again:
> +	f = fopen(path, "r");
> +	if (!f) {
> +		SYSERROR("opening %s\n", path);
> +		return NULL;
> +	}
> +	sz += 1024;
> +	buf = realloc(buf, sz);
> +	if (!buf) {
> +		ERROR("out of memory");
> +		fclose(f);
> +		return NULL;
> +	}
> +	ret = fread(buf, 1, sz, f);
>  	fclose(f);
> -	if (ret < 1)
> -		return 0;
> -	if (strcmp(p, "unconfined") == 0)
> -		return 1;
> -	return 0;
> +	if (ret >= sz)
> +		goto again;
> +	if (ret < 0) {
> +		ERROR("reading %s\n", path);
> +		free(buf);
> +		return NULL;
> +	}
> +	space = index(buf, ' ');
> +	if (space)
> +		*space = '\0';
> +	return buf;
> +}
> +
> +static int aa_am_unconfined(void)
> +{
> +	char *p = aa_get_profile(getpid());
> +	int ret = 0;
> +	if (!p || strcmp(p, "unconfined") == 0)
> +		ret = 1;
> +	if (p)
> +		free(p);
> +	return ret;
>  }
>  
>  /* aa_getcon is not working right now.  Use our hand-rolled version below */
> @@ -61,36 +99,57 @@ extern void apparmor_handler_init(struct lxc_handler *handler)
>  }
>  
>  #define AA_DEF_PROFILE "lxc-container-default"
> -extern int apparmor_load(struct lxc_handler *handler)
> +
> +extern int do_apparmor_load(int aa_enabled, char *aa_profile,
> +				   int umount_proc, int dropprivs)
>  {
> -	if (!handler->aa_enabled) {
> +	if (!aa_enabled) {
>  		INFO("apparmor not enabled");
>  		return 0;
>  	}
>  	INFO("setting up apparmor");
>  
> -	if (!handler->conf->aa_profile)
> -		handler->conf->aa_profile = AA_DEF_PROFILE;
> +	if (!aa_profile)
> +		aa_profile = AA_DEF_PROFILE;
>  
> -	if (strcmp(handler->conf->aa_profile, "unconfined") == 0 &&
> -	    aa_am_unconfined()) {
> +	if (strcmp(aa_profile, "unconfined") == 0 && !dropprivs && aa_am_unconfined()) {
>  		INFO("apparmor profile unchanged");
>  		return 0;
>  	}
>  
> -	//if (aa_change_onexec(handler->conf->aa_profile) < 0) {
> -	if (aa_change_profile(handler->conf->aa_profile) < 0) {
> -		SYSERROR("failed to change apparmor profile to %s", handler->conf->aa_profile);
> +	//if (aa_change_onexec(aa_profile) < 0) {
> +	if (aa_change_profile(aa_profile) < 0) {
> +		SYSERROR("failed to change apparmor profile to %s", aa_profile);
>  		return -1;
>  	}
> -	if (handler->conf->lsm_umount_proc == 1)
> +	if (umount_proc == 1)
>  		umount("/proc");
>  
> -	INFO("changed apparmor profile to %s", handler->conf->aa_profile);
> +	INFO("changed apparmor profile to %s", aa_profile);
>  
>  	return 0;
>  }
>  
> +extern int apparmor_load(struct lxc_handler *handler)
> +{
> +	if (!handler->conf->aa_profile)
> +		handler->conf->aa_profile = AA_DEF_PROFILE;
> +	return do_apparmor_load(handler->aa_enabled, 
> +				handler->conf->aa_profile,
> +				handler->conf->lsm_umount_proc, 0);
> +}
> +
> +extern int attach_apparmor(char *profile)
> +{
> +	if (!profile)
> +		return 0;
> +	if (!check_apparmor_enabled())
> +		return 0;
> +	if (strcmp(profile, "unconfined") == 0)
> +		return 0;
> +	return do_apparmor_load(1, profile, 0, 1);
> +}
> +
>  /*
>   * this will likely move to a generic lsm.c, as selinux and smack will both
>   * also want proc mounted in the container so as to transition
> diff --git a/src/lxc/apparmor.h b/src/lxc/apparmor.h
> index af879c0..d714478 100644
> --- a/src/lxc/apparmor.h
> +++ b/src/lxc/apparmor.h
> @@ -3,16 +3,34 @@
>  
>  struct lxc_handler;
>  
> +/*
> + * apparmor_handler_init is really just a wrapper around check_apparmor_enabled
> + * to allow us to keep from having #ifdef APPARMOR in start.c
> + */
> +extern void apparmor_handler_init(struct lxc_handler *handler);
> +
>  #if HAVE_APPARMOR
> +extern char *aa_get_profile(pid_t pid);
> +extern int do_apparmor_load(int aa_enabled, char *aa_profile,
> +				   int umount_proc, int dropprivs);
>  extern int apparmor_load(struct lxc_handler *handler);
> +extern int attach_apparmor(char *profile);
>  extern int lsm_mount_proc_if_needed(char *root_src, char *rootfs_tgt);
> -extern void apparmor_handler_init(struct lxc_handler *handler);
>  #else
> +static inline char *aa_get_profile(pid_t pid) {
> +	return NULL;
> +}
> +static inline int do_apparmor_load(int aa_enabled, char *aa_profile,
> +				   int umount_proc, int dropprivs) {
> +	return 0;
> +}
> +static inline int attach_apparmor(char *profile) {
> +	return 0;
> +}
>  static inline int apparmor_load(struct lxc_handler *handler) {
>  	return 0;
>  }
>  static inline int lsm_mount_proc_if_needed(char *root_src, char *rootfs_tgt) {
>  	return 0;
>  }
> -extern void apparmor_handler_init(struct lxc_handler *handler);
>  #endif
> diff --git a/src/lxc/attach.c b/src/lxc/attach.c
> index b86d2f4..af3d7a0 100644
> --- a/src/lxc/attach.c
> +++ b/src/lxc/attach.c
> @@ -44,6 +44,7 @@
>  #include "caps.h"
>  #include "cgroup.h"
>  #include "config.h"
> +#include "apparmor.h"
>  
>  lxc_log_define(lxc_attach, lxc);
>  
> @@ -137,6 +138,7 @@ struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
>  		errno = ENOENT;
>  		goto out_error;
>  	}
> +	info->aa_profile = aa_get_profile(pid);
>  
>  	return info;
>  
> diff --git a/src/lxc/attach.h b/src/lxc/attach.h
> index aab47e3..4d4f719 100644
> --- a/src/lxc/attach.h
> +++ b/src/lxc/attach.h
> @@ -27,6 +27,7 @@
>  #include <sys/types.h>
>  
>  struct lxc_proc_context_info {
> +	char *aa_profile;
>  	unsigned long personality;
>  	unsigned long long capability_mask;
>  };
> diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
> index 370bfbc..e1511ef 100644
> --- a/src/lxc/lxc_attach.c
> +++ b/src/lxc/lxc_attach.c
> @@ -41,6 +41,7 @@
>  #include "sync.h"
>  #include "log.h"
>  #include "namespace.h"
> +#include "apparmor.h"
>  
>  #if HAVE_SYS_PERSONALITY_H
>  #include <sys/personality.h>
> @@ -265,6 +266,11 @@ int main(int argc, char *argv[])
>  		lxc_sync_fini_parent(handler);
>  		lxc_cgroup_dispose_attach(cgroup_data);
>  
> +		if (attach_apparmor(init_ctx->aa_profile) < 0) {
> +			ERROR("failed switching apparmor profiles");
> +			return -1;
> +		}
> +
>  		/* A description of the purpose of this functionality is
>  		 * provided in the lxc-attach(1) manual page. We have to
>  		 * remount here and not in the parent process, otherwise
> 


-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 901 bytes
Desc: OpenPGP digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20130301/ed2d0258/attachment.pgp>


More information about the lxc-devel mailing list