[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v5] flask: create unified "flask=" boot parameter



On 09/03/15 17:02, Daniel De Graaf wrote:
> This unifies the flask_enforcing and flask_enabled boot parameters into
> a single parameter with additional states.  Defined options are:
>
>  enforcing - require policy to be loaded at boot time and enforce it
>  permissive - a missing or broken policy does not panic
>  disabled - revert to dummy (no XSM) policy.  Was flask_enabled=0
>  late - bootloader policy is not used; later loadpolicy is enforcing
>
> The default mode remains "permissive" and the flask_enforcing boot
> parameter is retained for compatibility.  If flask_enforcing=1 is
> specified and flask= is not, the bootloader policy will be loaded in
> enforcing mode if present, but errors will disable access controls until
> a successful loadpolicy instead of causing a panic at boot.
>
> Suggested-by: Julien Grall <julien.grall@xxxxxxxxxx>
> Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx>

Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>

Bonus - we gain more command line documentation!

> ---
> Changes from v4:
>  - Use enum and bool_t for parameter globals
>  - Remove duplication of flask=force/enforcing
>  - Move panic out of command line parsing so it is visible
>
> ---
>  docs/man/xl.pod.1                   |  4 ++--
>  docs/misc/xen-command-line.markdown | 30 +++++++++++++++++++++++++-----
>  docs/misc/xsm-flask.txt             | 29 -----------------------------
>  xen/xsm/flask/flask_op.c            | 34 ++++++++++++++++++++++++++++++----
>  xen/xsm/flask/hooks.c               | 32 +++++++++++++++++++++++---------
>  xen/xsm/flask/include/avc.h         |  2 +-
>  xen/xsm/flask/include/security.h    | 10 +++++++++-
>  7 files changed, 90 insertions(+), 51 deletions(-)
>
> diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1
> index cd80ffc..198ee2b 100644
> --- a/docs/man/xl.pod.1
> +++ b/docs/man/xl.pod.1
> @@ -1441,8 +1441,8 @@ Determine if the FLASK security module is loaded and 
> enforcing its policy.
>  =item B<setenforce> I<1|0|Enforcing|Permissive>
>  
>  Enable or disable enforcing of the FLASK access controls. The default is
> -permissive and can be changed using the flask_enforcing option on the
> -hypervisor's command line.
> +permissive, but this can be changed to enforcing by specifying 
> "flask=enforcing"
> +or "flask=late" on the hypervisor's command line.
>  
>  =item B<loadpolicy> I<policy-file>
>  
> diff --git a/docs/misc/xen-command-line.markdown 
> b/docs/misc/xen-command-line.markdown
> index e125212..5044da1 100644
> --- a/docs/misc/xen-command-line.markdown
> +++ b/docs/misc/xen-command-line.markdown
> @@ -638,11 +638,31 @@ hardware domain is architecture dependent.
>  Note that specifying zero as domU value means zero, while for dom0 it means
>  to use the default.
>  
> -### flask\_enabled
> -> `= <integer>`
> -
> -### flask\_enforcing
> -> `= <integer>`
> +### flask
> +> `= permissive | enforcing | late | disabled`
> +
> +> Default: `permissive`
> +
> +Specify how the FLASK security server should be configured.  This option is 
> only
> +available if the hypervisor was compiled with XSM support (which can be 
> enabled
> +by setting XSM\_ENABLE = y in .config).
> +
> +* `permissive`: This is intended for development and is not suitable for use
> +  with untrusted guests.  If a policy is provided by the bootloader, it will 
> be
> +  loaded; errors will be reported to the ring buffer but will not prevent
> +  booting.  The policy can be changed to enforcing mode using "xl 
> setenforce".
> +* `enforcing`: This requires a security policy to be provided by the 
> bootloader
> +  and will enter enforcing mode prior to the creation of domain 0.  If a 
> valid
> +  policy is not provided, the hypervisor will not continue booting.
> +* `late`: This disables loading of the security policy from the bootloader.
> +  FLASK will be enabled but will not enforce access controls until a policy 
> is
> +  loaded by a domain using "xl loadpolicy".  Once a policy is loaded, FLASK 
> will
> +  run in enforcing mode unless "xl setenforce" has changed that setting.
> +* `disabled`: This causes the XSM framework to revert to the dummy module.  
> The
> +  dummy module provides the same security policy as is used when compiling 
> the
> +  hypervisor without support for XSM.  The xsm\_op hypercall can also be 
> used to
> +  switch to this mode after boot, but there is no way to re-enable FLASK once
> +  the dummy module is loaded.
>  
>  ### font
>  > `= <height>` where height is `8x8 | 8x14 | 8x16`
> diff --git a/docs/misc/xsm-flask.txt b/docs/misc/xsm-flask.txt
> index 9559028..ab05913 100644
> --- a/docs/misc/xsm-flask.txt
> +++ b/docs/misc/xsm-flask.txt
> @@ -396,32 +396,3 @@ the ranges being denied to more easily determine what 
> resources are required.
>  When running in permissive mode, only the first denial of a given
>  source/destination is printed to the log, so labeling devices using this 
> method
>  may require multiple passes to find all required ranges.
> -
> -Additional notes on XSM:FLASK
> ------------------------------
> -
> -1) xen command line parameters
> -
> -     a) flask_enforcing
> -     
> -     The default value for flask_enforcing is '0'.  This parameter causes 
> the 
> -     platform to boot in permissive mode which means that the policy is 
> loaded 
> -     but not enforced.  This mode is often helpful for developing new 
> systems 
> -     and policies as the policy violations are reported on the xen console 
> and 
> -     may be viewed in dom0 through 'xl dmesg'.
> -     
> -     To boot the platform into enforcing mode, which means that the policy is
> -     loaded and enforced, append 'flask_enforcing=1' on the grub line.
> -     
> -     This parameter may also be changed through the flask hypercall.
> -     
> -     b) flask_enabled
> -     
> -     The default value for flask_enabled is '1'.  This parameter causes the
> -     platform to enable the FLASK security module under the XSM framework.
> -     The parameter may be enabled/disabled only once per boot.  If the 
> parameter
> -     is set to '0', only a reboot can re-enable flask.  When flask_enabled 
> is '0'
> -     the DUMMY module is enforced.
> -
> -     This parameter may also be changed through the flask hypercall.  But may
> -     only be performed once per boot.
> diff --git a/xen/xsm/flask/flask_op.c b/xen/xsm/flask/flask_op.c
> index 0e89360..84c7fec 100644
> --- a/xen/xsm/flask/flask_op.c
> +++ b/xen/xsm/flask/flask_op.c
> @@ -24,11 +24,12 @@
>  #define _copy_to_guest copy_to_guest
>  #define _copy_from_guest copy_from_guest
>  
> -int flask_enforcing = 0;
> -integer_param("flask_enforcing", flask_enforcing);
> +enum flask_bootparam_t __read_mostly flask_bootparam = 
> FLASK_BOOTPARAM_PERMISSIVE;
> +static void parse_flask_param(char *s);
> +custom_param("flask", parse_flask_param);
>  
> -int flask_enabled = 1;
> -integer_param("flask_enabled", flask_enabled);
> +bool_t __read_mostly flask_enforcing = 0;
> +boolean_param("flask_enforcing", flask_enforcing);
>  
>  #define MAX_POLICY_SIZE 0x4000000
>  
> @@ -60,6 +61,26 @@ extern int ss_initialized;
>  
>  extern struct xsm_operations *original_ops;
>  
> +static void __init parse_flask_param(char *s)
> +{
> +    if ( !strcmp(s, "enforcing") )
> +    {
> +        flask_enforcing = 1;
> +        flask_bootparam = FLASK_BOOTPARAM_ENFORCING;
> +    }
> +    else if ( !strcmp(s, "late") )
> +    {
> +        flask_enforcing = 1;
> +        flask_bootparam = FLASK_BOOTPARAM_LATELOAD;
> +    }
> +    else if ( !strcmp(s, "disabled") )
> +        flask_bootparam = FLASK_BOOTPARAM_DISABLED;
> +    else if ( !strcmp(s, "permissive") )
> +        flask_bootparam = FLASK_BOOTPARAM_PERMISSIVE;
> +    else
> +        flask_bootparam = FLASK_BOOTPARAM_INVALID;
> +}
> +
>  static int domain_has_security(struct domain *d, u32 perms)
>  {
>      struct domain_security_struct *dsec;
> @@ -502,6 +523,7 @@ static int flask_security_load(struct xen_flask_load 
> *load)
>  {
>      int ret;
>      void *buf = NULL;
> +    bool_t is_reload = ss_initialized;
>  
>      ret = domain_has_security(current->domain, SECURITY__LOAD_POLICY);
>      if ( ret )
> @@ -526,6 +548,10 @@ static int flask_security_load(struct xen_flask_load 
> *load)
>      if ( ret )
>          goto out;
>  
> +    if ( !is_reload )
> +        printk(XENLOG_INFO "Flask: Policy loaded, continuing in %s mode.\n",
> +            flask_enforcing ? "enforcing" : "permissive");
> +
>      xfree(bool_pending_values);
>      bool_pending_values = NULL;
>      ret = 0;
> diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
> index dad5deb..05dafed 100644
> --- a/xen/xsm/flask/hooks.c
> +++ b/xen/xsm/flask/hooks.c
> @@ -1628,15 +1628,23 @@ static struct xsm_operations flask_ops = {
>  
>  static __init void flask_init(void)
>  {
> -    int ret = 0;
> +    int ret = -ENOENT;
>  
> -    if ( !flask_enabled )
> +    switch ( flask_bootparam )
>      {
> -        printk("Flask:  Disabled at boot.\n");
> +    case FLASK_BOOTPARAM_DISABLED:
> +        printk(XENLOG_INFO "Flask: Disabled at boot.\n");
>          return;
> -    }
>  
> -    printk("Flask:  Initializing.\n");
> +    case FLASK_BOOTPARAM_PERMISSIVE:
> +    case FLASK_BOOTPARAM_ENFORCING:
> +    case FLASK_BOOTPARAM_LATELOAD:
> +        break;
> +
> +    case FLASK_BOOTPARAM_INVALID:
> +    default:
> +        panic("Flask: Invalid value for flask= boot parameter.\n");
> +    }
>  
>      avc_init();
>  
> @@ -1644,12 +1652,18 @@ static __init void flask_init(void)
>      if ( register_xsm(&flask_ops) )
>          panic("Flask: Unable to register with XSM");
>  
> -    ret = security_load_policy(policy_buffer, policy_size);
> +    if ( policy_size && flask_bootparam != FLASK_BOOTPARAM_LATELOAD )
> +        ret = security_load_policy(policy_buffer, policy_size);
> +
> +    if ( ret && flask_bootparam == FLASK_BOOTPARAM_ENFORCING )
> +        panic("Unable to load FLASK policy");
>  
> -    if ( flask_enforcing )
> -        printk("Flask:  Starting in enforcing mode.\n");
> +    if ( ret )
> +        printk(XENLOG_INFO "Flask:  Access controls disabled until policy is 
> loaded.\n");
> +    else if ( flask_enforcing )
> +        printk(XENLOG_INFO "Flask:  Starting in enforcing mode.\n");
>      else
> -        printk("Flask:  Starting in permissive mode.\n");
> +        printk(XENLOG_INFO "Flask:  Starting in permissive mode.\n");
>  }
>  
>  xsm_initcall(flask_init);
> diff --git a/xen/xsm/flask/include/avc.h b/xen/xsm/flask/include/avc.h
> index a00a6eb..c7a99fc 100644
> --- a/xen/xsm/flask/include/avc.h
> +++ b/xen/xsm/flask/include/avc.h
> @@ -17,7 +17,7 @@
>  #include "av_permissions.h"
>  #include "security.h"
>  
> -extern int flask_enforcing;
> +extern bool_t flask_enforcing;
>  
>  /*
>   * An entry in the AVC.
> diff --git a/xen/xsm/flask/include/security.h 
> b/xen/xsm/flask/include/security.h
> index dea0143..d07bae0 100644
> --- a/xen/xsm/flask/include/security.h
> +++ b/xen/xsm/flask/include/security.h
> @@ -35,7 +35,15 @@
>  #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
>  #define POLICYDB_VERSION_MAX   POLICYDB_VERSION_BOUNDARY
>  
> -extern int flask_enabled;
> +enum flask_bootparam_t {
> +    FLASK_BOOTPARAM_PERMISSIVE,
> +    FLASK_BOOTPARAM_ENFORCING,
> +    FLASK_BOOTPARAM_LATELOAD,
> +    FLASK_BOOTPARAM_DISABLED,
> +    FLASK_BOOTPARAM_INVALID,
> +};
> +
> +extern enum flask_bootparam_t flask_bootparam;
>  extern int flask_mls_enabled;
>  
>  int security_load_policy(void * data, size_t len);


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.