Intel® Software Guard Extensions (Intel® SGX)
Discussion board focused on hardware-based isolation and memory encryption to provide extended code protection in solutions.

Returning pointer from ECALL

nickolas_l_
Beginner
1,266 Views

Hello,

In the Intel SGX user guide it mentions that pointers to structures may be returned from ECALLS. On page 43, "pointers returned by an ECALL or OCALL function are not checked by the edge-routines and must be verified by the enclave and application code."

I am not able to get pointers to return from an ECALL, however, and instead get functions that always return sgx_status_t.

Can you please explain how I can return a pointer from an ECALL? Is there an edger8r flag that I need to specify so that ECALLS are not assumed to return sgx_status_t?

 

Example:

enclave.edl

trusted{ 
   public int* returns_int_ptr(void);
}

enclave.c

int* returns_int_ptr(void)
{
    /* do some stuff */
    return int_ptr;
}

enclave_u.h

/* I want int* as return type */
sgx_status_t returns_int_ptr(sgx_enclave_id_t eid, int* retval);

   

 

0 Kudos
1 Solution
Rodolfo_S_
New Contributor III
1,266 Views

Hi, Nickolas.

The SGX Edger8r tool automatically converts your function to the one that you pasted here.
It means that you need to get the "returned" int pointer from the out pointer parameter.

To execute that eCall, your code should look like this:

app.cpp
 

sgx_enclave_id_t eid;

/* create enclave.. */

sgx_status_t ret = SGX_SUCCESS;
int myInt;

ret = returns_int_ptr(eid, &myInt);

/* use myInt */

Now, if you wanted to return several integers instead of only one, your code should look like this:

enclave.edl

enclave{
    trusted{
        public void returns_int_ptr([out, size=len] int *p_return_ptr, size_t len);
    };
};

enclave.cpp

void returns_int_ptr(int *p_return_ptr, size_t len)
{
    int *p_ints = (int *) malloc(len*sizeof(int));

    /* do some stuff */

    memcpy(p_return_ptr, p_ints, len);
    free(p_ints);
}

app.cpp

#define BUFFER_SIZE 100
sgx_enclave_id_t eid;

/* create enclave */

int *p_ints = (int *) malloc(BUFFER_SIZE * sizeof(int));

sgx_status_t ret = SGX_SUCCESS;
ret = returns_int_ptr(eid, p_ints, BUFFER_SIZE);

/* do some stuff with p_ints */

Hope this is helpful.

Best regards,
Rodolfo

View solution in original post

0 Kudos
3 Replies
Rodolfo_S_
New Contributor III
1,267 Views

Hi, Nickolas.

The SGX Edger8r tool automatically converts your function to the one that you pasted here.
It means that you need to get the "returned" int pointer from the out pointer parameter.

To execute that eCall, your code should look like this:

app.cpp
 

sgx_enclave_id_t eid;

/* create enclave.. */

sgx_status_t ret = SGX_SUCCESS;
int myInt;

ret = returns_int_ptr(eid, &myInt);

/* use myInt */

Now, if you wanted to return several integers instead of only one, your code should look like this:

enclave.edl

enclave{
    trusted{
        public void returns_int_ptr([out, size=len] int *p_return_ptr, size_t len);
    };
};

enclave.cpp

void returns_int_ptr(int *p_return_ptr, size_t len)
{
    int *p_ints = (int *) malloc(len*sizeof(int));

    /* do some stuff */

    memcpy(p_return_ptr, p_ints, len);
    free(p_ints);
}

app.cpp

#define BUFFER_SIZE 100
sgx_enclave_id_t eid;

/* create enclave */

int *p_ints = (int *) malloc(BUFFER_SIZE * sizeof(int));

sgx_status_t ret = SGX_SUCCESS;
ret = returns_int_ptr(eid, p_ints, BUFFER_SIZE);

/* do some stuff with p_ints */

Hope this is helpful.

Best regards,
Rodolfo

0 Kudos
Juan_d_Intel
Employee
1,266 Views

When the trusted function returns "int *", the result is the following untrusted bridge:

sgx_status_t returns_int_ptr(sgx_enclave_id_t eid, int** retval);

and the untrusted app could then obtain the pointer as follows:

sgx_status_t ret = SGX_SUCCESS;
int * myInt = NULL;
ret = returns_int_ptr(eid, &myInt);

The documentation is saying that the such pointer is not marshalled, i.e., the untrusted application gets a pointer (address) but it doesn't get the content of the buffer. If you want to get the buffer you have to pass the pointer as a parameter as Rodolfo explained above.

static sgx_status_t SGX_CDECL sgx_returns_int_ptr(void* pms)
{
	ms_returns_int_ptr_t* ms = SGX_CAST(ms_returns_int_ptr_t*, pms);
	sgx_status_t status = SGX_SUCCESS;
	CHECK_REF_POINTER(pms, sizeof(ms_returns_int_ptr_t));
	ms->ms_retval = returns_int_ptr(); // We just get the pointer. No memcpy() below.
	return status;
}

This is important when an OCALL returns a pointer, since the enclave has to check it as if it had the "user_check" attribute.

0 Kudos
nickolas_l_
Beginner
1,266 Views

Thank you for both of your responses. They clear this up perfectly, and shows nicely where I was misunderstanding the SGX framework.

Nick

0 Kudos
Reply