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

[Xen-devel] [PATCH v9 3/5] xen/arm: use SYMBOLS_SUBTRACT and SYMBOLS_COMPARE as required



Use SYMBOLS_SUBTRACT and SYMBOLS_COMPARE in cases of comparisons and
subtractions of:

_start, _end, __init_begin, __init_end, _stext, _etext,
__alt_instructions, __alt_instructions_end, __per_cpu_start,
__per_cpu_data_end, _splatform, _eplatform, _sdevice, _edevice,
_asdevice, _aedevice.

as by the C standard [1].

M3CM: Rule-18.2: Subtraction between pointers shall only be applied to
pointers that address elements of the same array

[1] 
https://wiki.sei.cmu.edu/confluence/display/c/ARR36-C.+Do+not+subtract+or+compare+two+pointers+that+do+not+refer+to+the+same+array

QAVerify: 2761
Signed-off-by: Stefano Stabellini <stefanos@xxxxxxxxxx>
CC: JBeulich@xxxxxxxx
CC: andrew.cooper3@xxxxxxxxxx
---
Changes in v9:
- use SYMBOLS_SUBTRACT and SYMBOLS_COMPARE
---
 xen/arch/arm/alternative.c        | 10 +++++++---
 xen/arch/arm/arm32/livepatch.c    | 14 +++++++++++++-
 xen/arch/arm/arm64/livepatch.c    | 14 +++++++++++++-
 xen/arch/arm/device.c             |  8 +++++---
 xen/arch/arm/livepatch.c          | 16 ++++++++++++++--
 xen/arch/arm/mm.c                 |  9 +++++----
 xen/arch/arm/percpu.c             |  7 ++++---
 xen/arch/arm/platform.c           |  6 ++++--
 xen/arch/arm/setup.c              |  5 +++--
 xen/include/asm-arm/grant_table.h |  3 ++-
 10 files changed, 70 insertions(+), 22 deletions(-)

diff --git a/xen/arch/arm/alternative.c b/xen/arch/arm/alternative.c
index 52ed7ed..2cb66d0 100644
--- a/xen/arch/arm/alternative.c
+++ b/xen/arch/arm/alternative.c
@@ -131,7 +131,10 @@ static int __apply_alternatives(const struct alt_region 
*region,
     printk(XENLOG_INFO "alternatives: Patching with alt table %p -> %p\n",
            region->begin, region->end);
 
-    for ( alt = region->begin; alt < region->end; alt++ )
+    /* region->begin and region->end might point to different objects. */
+    for ( alt = region->begin;
+          SYMBOLS_COMPARE(alt, region->end) < 0;
+          alt++ )
     {
         int nr_inst;
 
@@ -188,7 +191,7 @@ static int __apply_alternatives_multi_stop(void *unused)
         int ret;
         struct alt_region region;
         mfn_t xen_mfn = virt_to_mfn(_start);
-        paddr_t xen_size = _end - _start;
+        paddr_t xen_size = SYMBOLS_SUBTRACT(_end, _start);
         unsigned int xen_order = get_order_from_bytes(xen_size);
         void *xenmap;
 
@@ -206,7 +209,8 @@ static int __apply_alternatives_multi_stop(void *unused)
         region.begin = __alt_instructions;
         region.end = __alt_instructions_end;
 
-        ret = __apply_alternatives(&region, xenmap - (void *)_start);
+        ret = __apply_alternatives(&region,
+                                   SYMBOLS_SUBTRACT(xenmap, _start));
         /* The patching is not expected to fail during boot. */
         BUG_ON(ret != 0);
 
diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c
index 41378a5..03ae84b 100644
--- a/xen/arch/arm/arm32/livepatch.c
+++ b/xen/arch/arm/arm32/livepatch.c
@@ -56,7 +56,19 @@ void arch_livepatch_apply(struct livepatch_func *func)
     else
         insn = 0xe1a00000; /* mov r0, r0 */
 
-    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
+    /*
+     * We need to calculate the offset of the address from _start, and
+     * apply that to our own map, to find where we have this mapped.
+     * Doing these kind of games directly with pointers is contrary to
+     * the C rules for what pointers may be compared and computed.  So
+     * we do the offset calculation with integers, which is always
+     * legal.  The subsequent addition of the offset to the
+     * vmap_of_xen_text pointer is legal because the computed pointer is
+     * indeed a valid part of the object referred to by vmap_of_xen_text
+     * - namely, the byte array of our mapping of the Xen text.
+     */
+    new_ptr = (((uintptr_t))func->old_addr, - ((uintptr_t))_start) +
+              vmap_of_xen_text;
     len = len / sizeof(uint32_t);
 
     /* PATCH! */
diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c
index 2247b92..ef362c3 100644
--- a/xen/arch/arm/arm64/livepatch.c
+++ b/xen/arch/arm/arm64/livepatch.c
@@ -43,7 +43,19 @@ void arch_livepatch_apply(struct livepatch_func *func)
     /* Verified in livepatch_verify_distance. */
     ASSERT(insn != AARCH64_BREAK_FAULT);
 
-    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
+    /*
+     * We need to calculate the offset of the address from _start, and
+     * apply that to our own map, to find where we have this mapped.
+     * Doing these kind of games directly with pointers is contrary to
+     * the C rules for what pointers may be compared and computed.  So
+     * we do the offset calculation with integers, which is always
+     * legal.  The subsequent addition of the offset to the
+     * vmap_of_xen_text pointer is legal because the computed pointer is
+     * indeed a valid part of the object referred to by vmap_of_xen_text
+     * - namely, the byte array of our mapping of the Xen text.
+     */
+    new_ptr = (((uintptr_t))func->old_addr, - ((uintptr_t))_start) +
+              vmap_of_xen_text;
     len = len / sizeof(uint32_t);
 
     /* PATCH! */
diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
index 70cd6c1..0f0bb77 100644
--- a/xen/arch/arm/device.c
+++ b/xen/arch/arm/device.c
@@ -35,7 +35,7 @@ int __init device_init(struct dt_device_node *dev, enum 
device_class class,
     if ( !dt_device_is_available(dev) || dt_device_for_passthrough(dev) )
         return  -ENODEV;
 
-    for ( desc = _sdevice; desc != _edevice; desc++ )
+    for ( desc = _sdevice; SYMBOLS_COMPARE(desc, _edevice) != 0; desc++ )
     {
         if ( desc->class != class )
             continue;
@@ -56,7 +56,9 @@ int __init acpi_device_init(enum device_class class, const 
void *data, int class
 {
     const struct acpi_device_desc *desc;
 
-    for ( desc = _asdevice; desc != _aedevice; desc++ )
+    for ( desc = _asdevice;
+          SYMBOLS_COMPARE(desc, _aedevice) != 0;
+          desc++ )
     {
         if ( ( desc->class != class ) || ( desc->class_type != class_type ) )
             continue;
@@ -75,7 +77,7 @@ enum device_class device_get_class(const struct 
dt_device_node *dev)
 
     ASSERT(dev != NULL);
 
-    for ( desc = _sdevice; desc != _edevice; desc++ )
+    for ( desc = _sdevice; SYMBOLS_COMPARE(desc, _edevice) != 0; desc++ )
     {
         if ( dt_match_node(desc->dt_match, dev) )
             return desc->class;
diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
index 279d52c..fb733a4 100644
--- a/xen/arch/arm/livepatch.c
+++ b/xen/arch/arm/livepatch.c
@@ -27,7 +27,7 @@ int arch_livepatch_quiesce(void)
         return -EINVAL;
 
     text_mfn = virt_to_mfn(_start);
-    text_order = get_order_from_bytes(_end - _start);
+    text_order = get_order_from_bytes(SYMBOLS_SUBTRACT(_end, _start));
 
     /*
      * The text section is read-only. So re-map Xen to be able to patch
@@ -78,7 +78,19 @@ void arch_livepatch_revert(const struct livepatch_func *func)
     uint32_t *new_ptr;
     unsigned int len;
 
-    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
+    /*
+     * We need to calculate the offset of the address from _start, and
+     * apply that to our own map, to find where we have this mapped.
+     * Doing these kind of games directly with pointers is contrary to
+     * the C rules for what pointers may be compared and computed.  So
+     * we do the offset calculation with integers, which is always
+     * legal.  The subsequent addition of the offset to the
+     * vmap_of_xen_text pointer is legal because the computed pointer is
+     * indeed a valid part of the object referred to by vmap_of_xen_text
+     * - namely, the byte array of our mapping of the Xen text.
+     */
+    new_ptr = (((uintptr_t))func->old_addr, - ((uintptr_t))_start) +
+              vmap_of_xen_text;
 
     len = livepatch_insn_len(func);
     memcpy(new_ptr, func->opaque, len);
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 01ae2cc..bde57fd 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -1084,8 +1084,8 @@ static void set_pte_flags_on_range(const char *p, 
unsigned long l, enum mg mg)
     ASSERT(!((unsigned long) p & ~PAGE_MASK));
     ASSERT(!(l & ~PAGE_MASK));
 
-    for ( i = (p - _start) / PAGE_SIZE; 
-          i < (p + l - _start) / PAGE_SIZE; 
+    for ( i = (SYMBOLS_SUBTRACT(p, _start)) / PAGE_SIZE;
+          i < ((uintptr_t)p + l - (uintptr_t)_start) / PAGE_SIZE;
           i++ )
     {
         pte = xen_xenmap[i];
@@ -1122,7 +1122,7 @@ static void set_pte_flags_on_range(const char *p, 
unsigned long l, enum mg mg)
 void free_init_memory(void)
 {
     paddr_t pa = virt_to_maddr(__init_begin);
-    unsigned long len = __init_end - __init_begin;
+    unsigned long len = SYMBOLS_SUBTRACT(__init_end, __init_begin);
     uint32_t insn;
     unsigned int i, nr = len / sizeof(insn);
     uint32_t *p;
@@ -1140,7 +1140,8 @@ void free_init_memory(void)
 
     set_pte_flags_on_range(__init_begin, len, mg_clear);
     init_domheap_pages(pa, pa + len);
-    printk("Freed %ldkB init memory.\n", (long)(__init_end-__init_begin)>>10);
+    printk("Freed %ldkB init memory.\n",
+           SYMBOLS_SUBTRACT(__init_end, __init_begin) >> 10);
 }
 
 void arch_dump_shared_mem_info(void)
diff --git a/xen/arch/arm/percpu.c b/xen/arch/arm/percpu.c
index 25442c4..5733a1c 100644
--- a/xen/arch/arm/percpu.c
+++ b/xen/arch/arm/percpu.c
@@ -6,7 +6,8 @@
 
 unsigned long __per_cpu_offset[NR_CPUS];
 #define INVALID_PERCPU_AREA (-(long)__per_cpu_start)
-#define PERCPU_ORDER (get_order_from_bytes(__per_cpu_data_end-__per_cpu_start))
+#define PERCPU_ORDER 
(get_order_from_bytes(SYMBOLS_SUBTRACT(__per_cpu_data_end, \
+                                           __per_cpu_start)))
 
 void __init percpu_init_areas(void)
 {
@@ -22,8 +23,8 @@ static int init_percpu_area(unsigned int cpu)
         return -EBUSY;
     if ( (p = alloc_xenheap_pages(PERCPU_ORDER, 0)) == NULL )
         return -ENOMEM;
-    memset(p, 0, __per_cpu_data_end - __per_cpu_start);
-    __per_cpu_offset[cpu] = p - __per_cpu_start;
+    memset(p, 0, SYMBOLS_SUBTRACT(__per_cpu_data_end, __per_cpu_start));
+    __per_cpu_offset[cpu] = SYMBOLS_SUBTRACT(p, __per_cpu_start);
     return 0;
 }
 
diff --git a/xen/arch/arm/platform.c b/xen/arch/arm/platform.c
index 8eb0b6e..664b573 100644
--- a/xen/arch/arm/platform.c
+++ b/xen/arch/arm/platform.c
@@ -51,14 +51,16 @@ void __init platform_init(void)
     ASSERT(platform == NULL);
 
     /* Looking for the platform description */
-    for ( platform = _splatform; platform != _eplatform; platform++ )
+    for ( platform = _splatform;
+          SYMBOLS_COMPARE(platform, _eplatform) != 0;
+          platform++ )
     {
         if ( platform_is_compatible(platform) )
             break;
     }
 
     /* We don't have specific operations for this platform */
-    if ( platform == _eplatform )
+    if ( SYMBOLS_COMPARE(platform, _eplatform) == 0 )
     {
         /* TODO: dump DT machine compatible node */
         printk(XENLOG_INFO "Platform: Generic System\n");
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 444857a..95fc7aa 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -772,8 +772,9 @@ void __init start_xen(unsigned long boot_phys_offset,
 
     /* Register Xen's load address as a boot module. */
     xen_bootmodule = add_boot_module(BOOTMOD_XEN,
-                             (paddr_t)(uintptr_t)(_start + boot_phys_offset),
-                             (paddr_t)(uintptr_t)(_end - _start + 1), false);
+                             (paddr_t)(_start + boot_phys_offset),
+                             (paddr_t)(SYMBOLS_SUBTRACT(_end, _start) + 1),
+                             false);
     BUG_ON(!xen_bootmodule);
 
     setup_pagetables(boot_phys_offset);
diff --git a/xen/include/asm-arm/grant_table.h 
b/xen/include/asm-arm/grant_table.h
index 816e3c6..fffe934 100644
--- a/xen/include/asm-arm/grant_table.h
+++ b/xen/include/asm-arm/grant_table.h
@@ -31,7 +31,8 @@ void gnttab_mark_dirty(struct domain *d, mfn_t mfn);
  * enough space for a large grant table
  */
 #define gnttab_dom0_frames()                                             \
-    min_t(unsigned int, opt_max_grant_frames, PFN_DOWN(_etext - _stext))
+    min_t(unsigned int, opt_max_grant_frames,                            \
+          PFN_DOWN(SYMBOLS_SUBTRACT(_etext, _stext)))
 
 #define gnttab_init_arch(gt)                                             \
 ({                                                                       \
-- 
1.9.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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