Is it possible to detect use of "unsafe" by inspecting the object code?

Technical questions regarding the XTC tools and programming with XMOS.
Post Reply
User avatar
aclassifier
Respected Member
Posts: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Is it possible to detect use of "unsafe" by inspecting the object code?

Post by aclassifier »

Is it possible to detect use of unsafe (etc.) by inspecting the object code?

This was a question that came to me just now when I sit here doing some blogging over that theme. Over this book, actually [1].

Could some external program be made to clinically analyse the binary image and see that there may be security holes? Assuming unsafe might constitute one of those.
Off Topic
Provided that it were possible to get the binary out of the xCORE chip. I always get

Code: Select all

Warning: F03098 Factory image and boot loader cannot be write-protected on flash device on node 0
but then that's ok for my boxes. I assume I would have to pay licence to get that enabled?
[1] The Huawei and Snowden Questions. Can Electronic Equipment from Untrusted Vendors be Verified? Can an Untrusted Vendor Build Trust into Electronic Equipment? by Olav Lysne (2017)


--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
User avatar
CousinItt
Respected Member
Posts: 360
Joined: Wed May 31, 2017 6:55 pm

Post by CousinItt »

I'm not sure that it would be detectable in all cases: if the compiler can be sure that a safe pointer is being used safely then there would be no need to include any run-time overhead. If that safe pointer is then changed to an unsafe one, I don't see why the compiler would need to drop different code.

However, in the case that a safe pointer is used for access to an array and the compiler can't be sure of safe access, there has to be some run-time bounds-checking code included. See the XMOS programming guide 5.2.2.
User avatar
aclassifier
Respected Member
Posts: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Post by aclassifier »

Thanks!

But is an unsafe pointer any different from a safe pointer in the object code? I would be surprised if it were.

Plus, will the compiler always include bounds checking for an unsafe used unsafely?
Off Topic
I know I could do research and try to figure it out myself, but then I wouldn't be able to lean on the knowledge this forum has
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
User avatar
CousinItt
Respected Member
Posts: 360
Joined: Wed May 31, 2017 6:55 pm

Post by CousinItt »

As far as I know there's no difference in the way a pointer is stored - it's the code that uses it that would vary.

There's no checking for an unsafe pointer, whether it's used safely or not. An unsafe declaration is telling the compiler that you're taking responsibility.
User avatar
aclassifier
Respected Member
Posts: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Post by aclassifier »

Thanks, again. I conclude that it is not possible to be able to distinguish a potentially "safe" object image from a potentially "unsafe".

I don't even know enough about this to know if it would be possible. I assume the means then is to protect that image as much as possible by making it not accessible in some way or another, or not useful, even for somebody attempting to try a trojan strategy. I would be surprised if the xcore.ai (AIoT) architecture would not have some interesting things to add.

I am satisfied by having scratched the surface on this theme.

Thanks!
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
User avatar
fabriceo
XCore Addict
Posts: 181
Joined: Mon Jan 08, 2018 4:14 pm

Post by fabriceo »

Hi Guys, as you may know, unsafe pointer takes only 4 bytes memory whereas others takes 12. see code below for proof:

Code: Select all

void testptr(int *p){
    printf("sizeof p = %d\n",sizeof(p));  }

void testunsafe(int * unsafe p){
    printf("sizeof p = %d\n",sizeof(p)); }

void task1(){
int X = 3;
    testptr(&X);
    unsafe { testunsafe(&X); }
User avatar
aclassifier
Respected Member
Posts: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Post by aclassifier »

No, I did not know! Great! Now we need to look at the instructions. I could do that today, if nobody beats me.

And then somebody could tell whether that unsafe pointer instruction is used elsewhere.

It is probably not very fruitful to proceed, but it is very interesting since it's always nice to know more than one thinks one need to know. So hang on!
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
User avatar
CousinItt
Respected Member
Posts: 360
Joined: Wed May 31, 2017 6:55 pm

Post by CousinItt »

Thanks fabriceo. Now I need to understand why.
User avatar
aclassifier
Respected Member
Posts: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Post by aclassifier »

I did the following source from fabriceo's original code, and then compiled different versions.

I have attached the project and the two interesting results in two external directories, containing ..map.txt and .s and .xi files. Just download and do a compare.

I am not able to analyse the build files. But I see the for the safe version it does an out of range check of the pointer.

Might the not-unsafe pointer of 4*3 bytes contain the pointer plus full range (low and high)?

The .xi files just shows the difference in what's compiled.
The .s files are vastly different. I don't know the assembler, so I would be blank. I always get impressed by these files!
The ..map.txt files are equal except for one value: 000400f4 00000000 .text $d.46 or $d.59

I took out the printing for these builds, to hold that code away.
And I wanted to just do something (increment) to make sure(?) that the functions were not optimized away.
The code looks like this. I have stored away for TEST_SAFE 1 only and TEST_UNSAFE 1 only.

Code: Select all

 #include <stdio.h>    // printf

// ---
// Control printing
// See https://stackoverflow.com/questions/1644868/define-macro-for-debug-printing-in-c
// ---
#define DEBUG_PRINT_TEST 0
#define debug_print(fmt, ...) do { if(DEBUG_PRINT_TEST) printf(fmt, __VA_ARGS__); } while (0)

// See Fabriceo 10Apr2020 at https://xcore.com/viewtopic.php?f=26&t=7886#top

#define TEST_SAFE   0
#define TEST_UNSAFE 1

#if (TEST_SAFE == 1)
    void test_ptr (int *ptr) {
        debug_print ("sizeof ptr = %d\n",sizeof(ptr));
        *ptr++; // Just do something
    }
#endif

#if (TEST_UNSAFE == 1)
    void test_unsafe_ptr (int * unsafe ptr) {
        debug_print ("sizeof unsafe ptr = %d\n",sizeof(ptr));
        unsafe {
            *ptr++; // Just do something
        }
    }
#endif

// === Prints ===
// sizeof ptr = 12
// sizeof unsafe ptr = 4

void task1 () {
    int x_val = 0;

    #if (TEST_SAFE == 1)
        test_ptr (&x_val);
    #endif

    #if (TEST_UNSAFE == 1)
        unsafe {
            test_unsafe_ptr (&x_val);
        }
    #endif
}

// xTIMEcomposer 14.4.1
//     DEBUG_PRINT_TEST
//       TEST_SAFE
//         TEST_UNSUAFE
//     0 1 1   Constraints: C:8/1 T:10/1 C:32/0 M:2768 S:348 C:1972 D:448
//     1 1 1   Constraints: C:8/1 T:10/1 C:32/0 M:8320 S:596 C:7104 D:620
//     0 1 0   Constraints: C:8/1 T:10/1 C:32/0 M:2768 S:348 C:1972 D:448 strange
//     0 0 1   Constraints: C:8/1 T:10/1 C:32/0 M:2768 S:348 C:1972 D:448 strange
//     0 0 0   Constraints: C:8/1 T:10/1 C:32/0 M:880  S:348 C:456  D:76

// This costs no extra code, as compared to just making task1 the main
// But it looks more idiomatic XC:

int main() {
    par {
        task1 ();
    }
    return 0;
}
Attachments
2020 04 12 test safe and unsafe.zip
fabriceo's source, result precompiled with safe and unsafe only
(100.86 KiB) Downloaded 157 times
2020 04 12 test safe and unsafe.zip
fabriceo's source, result precompiled with safe and unsafe only
(100.86 KiB) Downloaded 157 times
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
Post Reply