Hello Jarkko Sakkinen,

Commit 888d24911787 ("x86/sgx: Add SGX_IOC_ENCLAVE_CREATE") from Nov
13, 2020 (linux-next), leads to the following Smatch static checker
warning:

        arch/x86/kernel/cpu/sgx/ioctl.c:75 sgx_encl_create()
        warn: potential user controlled sizeof overflow 'secs->size + ((1) << 
12)' '0-u64max + 4096'

arch/x86/kernel/cpu/sgx/ioctl.c
    57 static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs)
    58 {
    59         struct sgx_epc_page *secs_epc;
    60         struct sgx_va_page *va_page;
    61         struct sgx_pageinfo pginfo;
    62         struct sgx_secinfo secinfo;
    63         unsigned long encl_size;
    64         struct file *backing;
    65         long ret;
    66 
    67         va_page = sgx_encl_grow(encl, true);
    68         if (IS_ERR(va_page))
    69                 return PTR_ERR(va_page);
    70         else if (va_page)
    71                 list_add(&va_page->list, &encl->va_pages);
    72         /* else the tail page of the VA page list had free slots. */
    73 
    74         /* The extra page goes to SECS. */
--> 75         encl_size = secs->size + PAGE_SIZE;

secs->size is a u64 that comes from the user in sgx_ioc_enclave_create().
If we add PAGE_SIZE that could be an integer overflow.  Also encl_size is
unsigned long so on 32 bits that's another integer overflow.

    76 
    77         backing = shmem_file_setup("SGX backing", encl_size + (encl_size 
>> 5),
                                                         
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Also this can integer overflow.

    78                                    VM_NORESERVE);
    79         if (IS_ERR(backing)) {
    80                 ret = PTR_ERR(backing);
    81                 goto err_out_shrink;
    82         }
    83 
    84         encl->backing = backing;
    85 
    86         secs_epc = sgx_alloc_epc_page(&encl->secs, true);
    87         if (IS_ERR(secs_epc)) {
    88                 ret = PTR_ERR(secs_epc);
    89                 goto err_out_backing;
    90         }
    91 
    92         encl->secs.epc_page = secs_epc;
    93 
    94         pginfo.addr = 0;
    95         pginfo.contents = (unsigned long)secs;
    96         pginfo.metadata = (unsigned long)&secinfo;
    97         pginfo.secs = 0;
    98         memset(&secinfo, 0, sizeof(secinfo));
    99 
    100         ret = __ecreate((void *)&pginfo, 
sgx_get_epc_virt_addr(secs_epc));
    101         if (ret) {
    102                 ret = -EIO;
    103                 goto err_out;
    104         }
    105 
    106         if (secs->attributes & SGX_ATTR_DEBUG)
    107                 set_bit(SGX_ENCL_DEBUG, &encl->flags);
    108 
    109         encl->secs.encl = encl;
    110         encl->secs.type = SGX_PAGE_TYPE_SECS;
    111         encl->base = secs->base;
    112         encl->size = secs->size;
                ^^^^^^^^^^^^^^^^^^^^^^^
Then we re-use secs->size here.  I haven't followed this code through to
see if anything bad happens, but it makes me itch just looking at it.  :P

    113         encl->attributes = secs->attributes;
    114         encl->attributes_mask = SGX_ATTR_UNPRIV_MASK;
    115 
    116         /* Set only after completion, as encl->lock has not been taken. 
*/
    117         set_bit(SGX_ENCL_CREATED, &encl->flags);
    118 
    119         return 0;
    120 
    121 err_out:
    122         sgx_encl_free_epc_page(encl->secs.epc_page);
    123         encl->secs.epc_page = NULL;
    124 
    125 err_out_backing:
    126         fput(encl->backing);
    127         encl->backing = NULL;
    128 
    129 err_out_shrink:
    130         sgx_encl_shrink(encl, va_page);
    131 
    132         return ret;
    133 }

regards,
dan carpenter

Reply via email to