On 05/20/2015 10:01 AM, Marat Zakirov wrote:
On 05/12/2015 02:16 PM, Marat Zakirov wrote:
On 04/07/2015 03:22 PM, Jakub Jelinek wrote:
How are the automatic misaligned variables different from say heap
allocated ones, or global vars etc.?
No difference you are right Jakub. Shadow memory initialization for
heap values and globals of course also should be changed but it is a
task for libsanitizer not ASan for which I am sending patch. Fix for
libsanitizer to support unaligned heaps and globals will be committed
by a separate patch.
Well, a RTL solution I've tried at http://gcc.gnu.org/PR22141, but
it gave
mixed results, so either it needs more cost tuning when it is
desirable and
when it is not, or perhaps better do that still on GIMPLE instead,
together
with trying to optimize bitfield accesses and other cases of adjacent
location accesses. But if we handle that on GIMPLE, it won't really
affect
what asan RTL emitting code produces.
Jakub
I fixed the issue with 'movq' you were mentioned in a previous mail.
--Marat
gcc/ChangeLog:
2015-02-25 Marat Zakirov <m.zaki...@samsung.com>
* asan.c (asan_emit_stack_protection): Support for misalign accesses.
(asan_expand_check_ifn): Likewise.
* params.def: New option asan-catch-misaligned.
* params.h: New param ASAN_CATCH_MISALIGNED.
* doc/invoke.texi: New asan param description.
gcc/testsuite/ChangeLog:
2015-02-25 Marat Zakirov <m.zaki...@samsung.com>
* c-c++-common/asan/misalign-catch.c: New test.
diff --git a/gcc/asan.c b/gcc/asan.c
index 9e4a629..f9d052f 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1050,7 +1050,6 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
rtx_code_label *lab;
rtx_insn *insns;
char buf[30];
- unsigned char shadow_bytes[4];
HOST_WIDE_INT base_offset = offsets[length - 1];
HOST_WIDE_INT base_align_bias = 0, offset, prev_offset;
HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset;
@@ -1059,6 +1058,8 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT;
tree str_cst, decl, id;
int use_after_return_class = -1;
+ bool misalign = (flag_sanitize & SANITIZE_KERNEL_ADDRESS)
+ || ASAN_CATCH_MISALIGNED;
if (shadow_ptr_types[0] == NULL_TREE)
asan_init_shadow_ptr_types ();
@@ -1193,11 +1194,37 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
if (STRICT_ALIGNMENT)
set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
prev_offset = base_offset;
+
+ vec<rtx> shadow_mems;
+ vec<unsigned char> shadow_bytes;
+
+ shadow_mems.create (0);
+ shadow_bytes.create (0);
+
for (l = length; l; l -= 2)
{
if (l == 2)
cur_shadow_byte = ASAN_STACK_MAGIC_RIGHT;
offset = offsets[l - 1];
+ if (l != length && misalign)
+ {
+ HOST_WIDE_INT aoff
+ = base_offset + ((offset - base_offset)
+ & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
+ - ASAN_RED_ZONE_SIZE;
+ if (aoff > prev_offset)
+ {
+ shadow_mem = adjust_address (shadow_mem, VOIDmode,
+ (aoff - prev_offset)
+ >> ASAN_SHADOW_SHIFT);
+ prev_offset = aoff;
+ shadow_bytes.safe_push (0);
+ shadow_bytes.safe_push (0);
+ shadow_bytes.safe_push (0);
+ shadow_bytes.safe_push (0);
+ shadow_mems.safe_push (shadow_mem);
+ }
+ }
if ((offset - base_offset) & (ASAN_RED_ZONE_SIZE - 1))
{
int i;
@@ -1212,13 +1239,13 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
if (aoff < offset)
{
if (aoff < offset - (1 << ASAN_SHADOW_SHIFT) + 1)
- shadow_bytes[i] = 0;
+ shadow_bytes.safe_push (0);
else
- shadow_bytes[i] = offset - aoff;
+ shadow_bytes.safe_push (offset - aoff);
}
else
- shadow_bytes[i] = ASAN_STACK_MAGIC_PARTIAL;
- emit_move_insn (shadow_mem, asan_shadow_cst (shadow_bytes));
+ shadow_bytes.safe_push (ASAN_STACK_MAGIC_PARTIAL);
+ shadow_mems.safe_push (shadow_mem);
offset = aoff;
}
while (offset <= offsets[l - 2] - ASAN_RED_ZONE_SIZE)
@@ -1227,12 +1254,21 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
(offset - prev_offset)
>> ASAN_SHADOW_SHIFT);
prev_offset = offset;
- memset (shadow_bytes, cur_shadow_byte, 4);
- emit_move_insn (shadow_mem, asan_shadow_cst (shadow_bytes));
+ shadow_bytes.safe_push (cur_shadow_byte);
+ shadow_bytes.safe_push (cur_shadow_byte);
+ shadow_bytes.safe_push (cur_shadow_byte);
+ shadow_bytes.safe_push (cur_shadow_byte);
+ shadow_mems.safe_push (shadow_mem);
offset += ASAN_RED_ZONE_SIZE;
}
cur_shadow_byte = ASAN_STACK_MAGIC_MIDDLE;
}
+ for (unsigned i = 0; misalign && i < shadow_bytes.length () - 1; i++)
+ if (shadow_bytes[i] == 0 && shadow_bytes[i + 1] > 0)
+ shadow_bytes[i] = 8 + (shadow_bytes[i + 1] > 7 ? 0 : shadow_bytes[i + 1]);
+ for (unsigned i = 0; i < shadow_mems.length (); i++)
+ emit_move_insn (shadow_mems[i], asan_shadow_cst (&shadow_bytes[i * 4]));
+
do_pending_stack_adjust ();
/* Construct epilogue sequence. */
@@ -1285,33 +1321,15 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
if (STRICT_ALIGNMENT)
set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
- prev_offset = base_offset;
- last_offset = base_offset;
- last_size = 0;
- for (l = length; l; l -= 2)
+ for (unsigned i = 0; i < shadow_mems.length (); i++)
{
- offset = base_offset + ((offsets[l - 1] - base_offset)
- & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
- if (last_offset + last_size != offset)
+ if (shadow_bytes[i*4+3] == ASAN_STACK_MAGIC_PARTIAL)
{
- shadow_mem = adjust_address (shadow_mem, VOIDmode,
- (last_offset - prev_offset)
- >> ASAN_SHADOW_SHIFT);
- prev_offset = last_offset;
- asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
- last_offset = offset;
- last_size = 0;
+ asan_clear_shadow (shadow_mems[i], 8);
+ i++;
}
- last_size += base_offset + ((offsets[l - 2] - base_offset)
- & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
- - offset;
- }
- if (last_size)
- {
- shadow_mem = adjust_address (shadow_mem, VOIDmode,
- (last_offset - prev_offset)
- >> ASAN_SHADOW_SHIFT);
- asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
+ else
+ asan_clear_shadow (shadow_mems[i], 4);
}
do_pending_stack_adjust ();
@@ -2546,6 +2564,8 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
gimple g = gsi_stmt (*iter);
location_t loc = gimple_location (g);
+ bool misalign = (flag_sanitize & SANITIZE_KERNEL_ADDRESS)
+ || ASAN_CATCH_MISALIGNED;
bool recover_p
= (flag_sanitize & flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0;
@@ -2643,7 +2663,7 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
tree base_addr = gimple_assign_lhs (g);
tree t = NULL_TREE;
- if (real_size_in_bytes >= 8)
+ if (real_size_in_bytes >= 8 && !misalign)
{
tree shadow = build_shadow_mem_access (&gsi, loc, base_addr,
shadow_ptr_type);
@@ -2662,7 +2682,7 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
/* Aligned (>= 8 bytes) can test just
(real_size_in_bytes - 1 >= shadow), as base_addr & 7 is known
to be 0. */
- if (align < 8)
+ if (align < 8 || misalign)
{
gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR,
base_addr, 7));
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index bf8afad..ee67e45 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -10965,6 +10965,12 @@ is greater or equal to this number, use callbacks instead of inline checks.
E.g. to disable inline code use
@option{--param asan-instrumentation-with-call-threshold=0}.
+@item asan-catch-misaligned
+Catch invalid unaligned memory accesses.
+This option is needed to prevent potential ASan false positives due to
+unaligned to type size memory accesses in some apllication like Linux kernel
+@option{--param asan-catch-misaligned=0}.
+
@item chkp-max-ctor-size
Static constructors generated by Pointer Bounds Checker may become very
large and significantly increase compile time at optimization level
diff --git a/gcc/params.def b/gcc/params.def
index 5e2c769..d96db71 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -1151,6 +1151,11 @@ DEFPARAM (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD,
"in function becomes greater or equal to this number",
7000, 0, INT_MAX)
+DEFPARAM (PARAM_ASAN_CATCH_MISALIGNED,
+ "asan-catch-misaligned",
+ "catch unaligned access",
+ 0, 1, 1)
+
DEFPARAM (PARAM_UNINIT_CONTROL_DEP_ATTEMPTS,
"uninit-control-dep-attempts",
"Maximum number of nested calls to search for control dependencies "
diff --git a/gcc/params.h b/gcc/params.h
index 28d077f..c556ca6 100644
--- a/gcc/params.h
+++ b/gcc/params.h
@@ -240,5 +240,7 @@ extern void init_param_values (int *params);
PARAM_VALUE (PARAM_ASAN_USE_AFTER_RETURN)
#define ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD \
PARAM_VALUE (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD)
+#define ASAN_CATCH_MISALIGNED \
+ PARAM_VALUE (PARAM_ASAN_CATCH_MISALIGNED)
#endif /* ! GCC_PARAMS_H */
diff --git a/gcc/testsuite/c-c++-common/asan/misalign-catch.c b/gcc/testsuite/c-c++-common/asan/misalign-catch.c
new file mode 100644
index 0000000..ae5dfc4
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/misalign-catch.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "--param asan-catch-misaligned=1" } */
+/* { dg-shouldfail "asan" } */
+
+long long *ptr;
+
+__attribute__((noinline))
+void foo () {
+ ptr = ((long long int *)(((char *)ptr) + 1));
+ *ptr = 1;
+}
+
+int main ()
+{
+ long long int local[9];
+ ptr = (long long *)&local[8];
+ foo ();
+ return 0;
+}
+
+/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow.*(\n|\r\n|\r)" } */