On 13.07.19 20:10, Ralf Ramsauer wrote:
> Whitelist-based permissions align better with the Jailhouse philosophy.
> 
> This patch switches the permission bitmap (which basically was (almost) a
> duplicate of the final io_bitmap) to a structure that whitelists a port range,
> given a base port and a length.
> 
> As a side effect, this patch drastically reduces the size of config files:
> 8404  -> 224   apic-demo.cell
> 8488  -> 312   e1000-demo.cell
> 11450 -> 3290  f2a88xm-hd3.cell
> 11634 -> 3474  imb-a180.cell
> 8424  -> 252   ioapic-demo.cell
> 8480  -> 296   ivshmem-demo.cell
> 8788  -> 608   linux-x86-demo.cell
> 8488  -> 308   pci-demo.cell
> 9730  -> 1586  qemu-x86.cell
> 8392  -> 212   smp-demo.cell
> 8404  -> 224   tiny-demo.cell
> 
> If no whitelist is given, all PIO access will be denied. Additionally, 
> increase
> the config file revision header.
> 
> Signed-off-by: Ralf Ramsauer <[email protected]>
> ---
>  configs/x86/apic-demo.c         | 16 +++----
>  configs/x86/e1000-demo.c        | 19 +++-----
>  configs/x86/f2a88xm-hd3.c       | 27 +++++------
>  configs/x86/imb-a180.c          | 27 +++++------
>  configs/x86/ioapic-demo.c       | 22 ++++-----
>  configs/x86/ivshmem-demo.c      | 13 ++----
>  configs/x86/linux-x86-demo.c    | 16 +++----
>  configs/x86/pci-demo.c          | 16 +++----
>  configs/x86/qemu-x86.c          | 41 ++++++----------
>  configs/x86/smp-demo.c          | 16 +++----
>  configs/x86/tiny-demo.c         | 16 +++----
>  hypervisor/arch/x86/vcpu.c      | 83 +++++++++++++++++++++------------
>  include/jailhouse/cell-config.h | 17 +++----
>  tools/jailhouse-hardware-check  |  2 +-
>  14 files changed, 151 insertions(+), 180 deletions(-)
> 

[...]

> diff --git a/hypervisor/arch/x86/vcpu.c b/hypervisor/arch/x86/vcpu.c
> index 9caba92f..3a660ef1 100644
> --- a/hypervisor/arch/x86/vcpu.c
> +++ b/hypervisor/arch/x86/vcpu.c
> @@ -26,6 +26,12 @@
>  #include <jailhouse/percpu.h>
>  #include <asm/vcpu.h>
>  
> +#define for_each_pio_whitelist(pio, config, counter)                 \
> +     for ((pio) = jailhouse_cell_pio_whitelist(config),              \
> +          (counter) = 0;                                             \
> +          (counter) < (config)->num_pio_whitelists;                  \
> +          (pio)++, (counter)++)
> +
>  static u8 __attribute__((aligned(PAGE_SIZE))) parking_code[PAGE_SIZE] = {
>       0xfa, /* 1: cli */
>       0xf4, /*    hlt */
> @@ -83,15 +89,26 @@ static inline void vcpu_get_cell_io_bitmap(struct cell 
> *cell,
>       iobm->size = vcpu_vendor_get_io_bitmap_pages() * PAGE_SIZE;
>  }
>  
> +static void pio_allow_access(struct vcpu_io_bitmap *bm,
> +                         const struct jailhouse_pio_whitelist *pio,
> +                         bool access)
> +{
> +     void (*access_method)(unsigned int, volatile unsigned long*) =
> +             access ? clear_bit : set_bit;
> +     unsigned int start_bit = pio->base;
> +     unsigned int length = pio->length;
> +
> +     for (; length; length--, start_bit++)

I would prefer "length > 0" here.

> +             access_method(start_bit, (unsigned long*)bm->data);
> +}
> +
>  int vcpu_cell_init(struct cell *cell)
>  {
>       const unsigned int io_bitmap_pages = vcpu_vendor_get_io_bitmap_pages();
> -     const u8 *pio_bitmap = jailhouse_cell_pio_bitmap(cell->config);
> -     u32 pio_bitmap_size = cell->config->pio_bitmap_size;
> +     const struct jailhouse_pio_whitelist *pio_whitelist;
>       struct vcpu_io_bitmap cell_iobm, root_cell_iobm;
>       unsigned int n, pm_timer_addr;
> -     u32 size;
> -     int err;
> +     int err, i;

You already have "n", can be recycled, and it has the better type.

>       u8 *b;
>  
>       cell->arch.io_bitmap = page_alloc(&mem_pool, io_bitmap_pages);
> @@ -109,19 +126,20 @@ int vcpu_cell_init(struct cell *cell)
>       /* initialize io bitmap to trap all accesses */
>       memset(cell_iobm.data, -1, cell_iobm.size);
>  
> -     /* copy io bitmap from cell config */
> -     size = pio_bitmap_size > cell_iobm.size ?
> -                     cell_iobm.size : pio_bitmap_size;
> -     memcpy(cell_iobm.data, pio_bitmap, size);
> +     /* cells have no access to i8042, unless the port is whitelisted */
> +     cell->arch.pio_i8042_allowed = false;
>  
> -     /* always intercept access to i8042 command register */
> -     cell_iobm.data[I8042_CMD_REG / 8] |= 1 << (I8042_CMD_REG % 8);
> +     for_each_pio_whitelist(pio_whitelist, cell->config, i) {
> +             pio_allow_access(&cell_iobm, pio_whitelist, true);
>  
> -     /* but moderate only if the config allows i8042 access */
> -     cell->arch.pio_i8042_allowed =
> -             pio_bitmap_size >= (I8042_CMD_REG + 7) / 8 ?
> -             !(pio_bitmap[I8042_CMD_REG / 8] & (1 << (I8042_CMD_REG % 8))) :
> -             false;
> +             /* moderate i8042 only if the config allows it */
> +             if (pio_whitelist->base <= I8042_CMD_REG &&
> +                 pio_whitelist->base + pio_whitelist->length > I8042_CMD_REG)
> +                     cell->arch.pio_i8042_allowed = true;
> +     }
> +
> +     /* but always intercept access to i8042 command register */
> +     cell_iobm.data[I8042_CMD_REG / 8] |= 1 << (I8042_CMD_REG % 8);
>  
>       if (cell != &root_cell) {
>               /*
> @@ -129,9 +147,8 @@ int vcpu_cell_init(struct cell *cell)
>                * access rights.
>                */
>               vcpu_get_cell_io_bitmap(&root_cell, &root_cell_iobm);
> -             for (b = root_cell_iobm.data; pio_bitmap_size > 0;
> -                  b++, pio_bitmap++, pio_bitmap_size--)
> -                     *b |= ~*pio_bitmap;
> +             for_each_pio_whitelist(pio_whitelist, cell->config, i)
> +                     pio_allow_access(&root_cell_iobm, pio_whitelist, false);
>       }
>  
>       /* permit access to the PM timer if there is any */
> @@ -148,21 +165,29 @@ int vcpu_cell_init(struct cell *cell)
>  
>  void vcpu_cell_exit(struct cell *cell)
>  {
> -     const u8 *root_pio_bitmap =
> -             jailhouse_cell_pio_bitmap(root_cell.config);
> -     const u8 *pio_bitmap = jailhouse_cell_pio_bitmap(cell->config);
> -     u32 pio_bitmap_size = cell->config->pio_bitmap_size;
> +     const struct jailhouse_pio_whitelist *cell_wl, *root_wl;
> +     struct jailhouse_pio_whitelist refund;
>       struct vcpu_io_bitmap root_cell_iobm;
> -     u8 *b;
> +     unsigned int interval_start, interval_end;
> +     unsigned int i, j;

"i" suggests signed integer. We usually use "n" for unsigned int counter. j may
be m or, if that's too close, k.

Also, the unsigned int vars can go into a single line.

>  
>       vcpu_get_cell_io_bitmap(&root_cell, &root_cell_iobm);
>  
> -     if (root_cell.config->pio_bitmap_size < pio_bitmap_size)
> -             pio_bitmap_size = root_cell.config->pio_bitmap_size;
> -
> -     for (b = root_cell_iobm.data; pio_bitmap_size > 0;
> -          b++, pio_bitmap++, root_pio_bitmap++, pio_bitmap_size--)
> -             *b &= *pio_bitmap | *root_pio_bitmap;
> +     /* Hand back ports to the root cell. But only hand back those ports
> +      * that overlap with the root cell's config. This is done by pairwise
> +      * comparison of the cell's and the root cell's whitelist entries. */
> +     for_each_pio_whitelist(cell_wl, cell->config, i)
> +             for_each_pio_whitelist(root_wl, root_cell.config, j) {
> +                     interval_start = MAX(cell_wl->base, root_wl->base);
> +                     interval_end = MIN(cell_wl->base + cell_wl->length,
> +                                        root_wl->base + root_wl->length);
> +                     if (interval_start < interval_end) {
> +                             refund.base = interval_start;
> +                             refund.length = interval_end - interval_start;
> +                             pio_allow_access(&root_cell_iobm, &refund,
> +                                              true);
> +                     }
> +             }
>  
>       page_free(&mem_pool, cell->arch.io_bitmap,
>                 vcpu_vendor_get_io_bitmap_pages());
> diff --git a/include/jailhouse/cell-config.h b/include/jailhouse/cell-config.h
> index a57fb9ef..b20a2b09 100644
> --- a/include/jailhouse/cell-config.h
> +++ b/include/jailhouse/cell-config.h
> @@ -50,7 +50,7 @@
>   * Incremented on any layout or semantic change of system or cell config.
>   * Also update HEADER_REVISION in tools.
>   */
> -#define JAILHOUSE_CONFIG_REVISION    10
> +#define JAILHOUSE_CONFIG_REVISION    11
>  
>  #define JAILHOUSE_CELL_NAME_MAXLEN   31
>  
> @@ -92,7 +92,7 @@ struct jailhouse_cell_desc {
>       __u32 num_memory_regions;
>       __u32 num_cache_regions;
>       __u32 num_irqchips;
> -     __u32 pio_bitmap_size;
> +     __u32 num_pio_whitelists;

Naming again: we should talk about "pio_regions" here, analogously to the other
regions.

>       __u32 num_pci_devices;
>       __u32 num_pci_caps;
>  
> @@ -277,7 +277,7 @@ jailhouse_cell_config_size(struct jailhouse_cell_desc 
> *cell)
>               cell->num_memory_regions * sizeof(struct jailhouse_memory) +
>               cell->num_cache_regions * sizeof(struct jailhouse_cache) +
>               cell->num_irqchips * sizeof(struct jailhouse_irqchip) +
> -             cell->pio_bitmap_size +
> +             cell->num_pio_whitelists * sizeof(struct 
> jailhouse_pio_whitelist) +
>               cell->num_pci_devices * sizeof(struct jailhouse_pci_device) +
>               cell->num_pci_caps * sizeof(struct jailhouse_pci_capability);
>  }
> @@ -319,10 +319,11 @@ jailhouse_cell_irqchips(const struct 
> jailhouse_cell_desc *cell)
>                cell->num_cache_regions * sizeof(struct jailhouse_cache));
>  }
>  
> -static inline const __u8 *
> -jailhouse_cell_pio_bitmap(const struct jailhouse_cell_desc *cell)
> +static inline const struct jailhouse_pio_whitelist *
> +jailhouse_cell_pio_whitelist(const struct jailhouse_cell_desc *cell)
>  {
> -     return (const __u8 *)((void *)jailhouse_cell_irqchips(cell) +
> +     return (const struct jailhouse_pio_whitelist *)
> +             ((void *)jailhouse_cell_irqchips(cell) +
>               cell->num_irqchips * sizeof(struct jailhouse_irqchip));
>  }
>  
> @@ -330,8 +331,8 @@ static inline const struct jailhouse_pci_device *
>  jailhouse_cell_pci_devices(const struct jailhouse_cell_desc *cell)
>  {
>       return (const struct jailhouse_pci_device *)
> -             ((void *)jailhouse_cell_pio_bitmap(cell) +
> -              cell->pio_bitmap_size);
> +             ((void *)jailhouse_cell_pio_whitelist(cell) +
> +              cell->num_pio_whitelists * sizeof(struct 
> jailhouse_pio_whitelist));
>  }
>  
>  static inline const struct jailhouse_pci_capability *
> diff --git a/tools/jailhouse-hardware-check b/tools/jailhouse-hardware-check
> index b86756ac..afd1139b 100755
> --- a/tools/jailhouse-hardware-check
> +++ b/tools/jailhouse-hardware-check
> @@ -136,7 +136,7 @@ class Sysconfig:
>      X86_MAX_IOMMU_UNITS = 8
>      X86_IOMMU_SIZE = 20
>  
> -    HEADER_REVISION = 10
> +    HEADER_REVISION = 11
>      HEADER_FORMAT = '6sH'
>  
>      def __init__(self, path):
> 

Jan

-- 
Siemens AG, Corporate Technology, CT RDA IOT SES-DE
Corporate Competence Center Embedded Linux

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jailhouse-dev/e049667a-6d1e-cd7b-783b-0739191e227c%40siemens.com.

Reply via email to