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

Re: [Xen-devel] [PATCH V3 1/3] xen/mem_access: Support for memory-content hiding



On 07/07/2015 04:27 PM, Jan Beulich wrote:
>>>> On 06.07.15 at 17:51, <rcojocaru@xxxxxxxxxxxxxxx> wrote:
>> --- a/xen/arch/x86/domain.c
>> +++ b/xen/arch/x86/domain.c
>> @@ -269,6 +269,7 @@ struct vcpu *alloc_vcpu_struct(void)
>>  
>>  void free_vcpu_struct(struct vcpu *v)
>>  {
>> +    xfree(v->arch.vm_event.emul_read_data);
>>      free_xenheap_page(v);
>>  }
> 
> Please note the function's name - nothing else should be freed here imo.

Ack, moved it to alloc_vcpu() and complete_domain_destroy() (the callers
of free_vcpu_struct(), in xen/common/domain.c).

>> @@ -893,6 +915,24 @@ static int hvmemul_cmpxchg(
>>      unsigned int bytes,
>>      struct x86_emulate_ctxt *ctxt)
>>  {
>> +    struct hvm_emulate_ctxt *hvmemul_ctxt =
>> +        container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
>> +
>> +    if ( unlikely(hvmemul_ctxt->set_context) )
>> +    {
>> +        struct vcpu *curr = current;
>> +
>> +        if ( curr->arch.vm_event.emul_read_data )
>> +        {
> 
> hvmemul_read() returns X86EMUL_UNHANDLEABLE when
> !curr->arch.vm_event.emul_read_data. I think this ought to
> be consistent.

Ack.

>> +            unsigned int safe_bytes = min_t(unsigned int, bytes,
>> +                curr->arch.vm_event.emul_read_data->size);
>> +
>> +            memset(p_new, 0, bytes);
>> +            memcpy(p_new, curr->arch.vm_event.emul_read_data->data,
>> +                   safe_bytes);
> 
> Here as well as in elsewhere - pretty inefficient to zero the
> whole array in order to then possibly overwrite all of it. I'd really
> like to see only the excess bytes to be zeroed.

Ack, now zeroing only the remainder.

>> @@ -935,6 +975,41 @@ static int hvmemul_rep_ins(
>>                                 !!(ctxt->regs->eflags & X86_EFLAGS_DF), gpa);
>>  }
>>  
>> +static int hvmemul_rep_outs_set_context(
>> +    enum x86_segment src_seg,
>> +    unsigned long src_offset,
>> +    uint16_t dst_port,
>> +    unsigned int bytes_per_rep,
>> +    unsigned long *reps,
>> +    struct x86_emulate_ctxt *ctxt)
>> +{
>> +    unsigned int bytes = *reps * bytes_per_rep;
>> +    struct vcpu *curr = current;
>> +    unsigned int safe_bytes;
>> +    char *buf = NULL;
>> +    int rc;
>> +
>> +    if ( !curr->arch.vm_event.emul_read_data )
>> +        return X86EMUL_UNHANDLEABLE;
>> +
>> +    buf = xmalloc_bytes(bytes);
>> +
>> +    if ( buf == NULL )
>> +        return X86EMUL_UNHANDLEABLE;
>> +
>> +    memset(buf, 0, bytes);
> 
> If this were to stay (see above), xzalloc_array() above please. And
> xmalloc_array() otherwise.

Changed it to xmalloc_array() and zeroing out only the reminder.

>> @@ -1063,7 +1142,20 @@ static int hvmemul_rep_movs(
>>       */
>>      rc = hvm_copy_from_guest_phys(buf, sgpa, bytes);
>>      if ( rc == HVMCOPY_okay )
>> +    {
>> +        struct vcpu *curr = current;
>> +
>> +        if ( unlikely(hvmemul_ctxt->set_context) &&
>> +             curr->arch.vm_event.emul_read_data )
>> +        {
>> +            unsigned int safe_bytes = min_t(unsigned int, bytes,
>> +                curr->arch.vm_event.emul_read_data->size);
>> +
>> +            memcpy(buf, curr->arch.vm_event.emul_read_data->data, 
>> safe_bytes);
>> +        }
> 
> This again is inconsistent with what you do above: You need to
> decide whether excess data (beyond safe_bytes) is safe to read
> (like you do here) or should be returned as zeroes (as done above).

An omission, now fixed.

>> @@ -1599,6 +1711,7 @@ static int _hvm_emulate_one(struct hvm_emulate_ctxt 
>> *hvmemul_ctxt,
>>  int hvm_emulate_one(
>>      struct hvm_emulate_ctxt *hvmemul_ctxt)
>>  {
>> +    hvmemul_ctxt->set_context = 0;
> 
> I think this would better go into hvm_emulate_prepare().

Ack.

>> @@ -1616,10 +1736,16 @@ void hvm_mem_access_emulate_one(bool_t nowrite, 
>> unsigned int trapnr,
>>  
>>      hvm_emulate_prepare(&ctx, guest_cpu_user_regs());
>>  
>> -    if ( nowrite )
>> +    switch ( kind ) {
> 
> Coding style (also elsewhere in the patch).

Sorry about that, fixed.

>> +    case EMUL_KIND_NOWRITE:
>>          rc = hvm_emulate_one_no_write(&ctx);
>> -    else
>> +        break;
>> +    case EMUL_KIND_SET_CONTEXT:
>> +        rc = hvm_emulate_one_set_context(&ctx);
> 
> Unless you see future uses for it, please expand the wrapper here.

Now that setting set_context to 0 happens in hvm_emulate_one_no_write()
I'm just setting it to 1 and falling through to the default case here.

>> @@ -1552,9 +1556,15 @@ bool_t p2m_mem_access_check(paddr_t gpa, unsigned 
>> long gla,
>>  
>>      if ( v->arch.vm_event.emulate_flags )
>>      {
>> -        hvm_mem_access_emulate_one((v->arch.vm_event.emulate_flags &
>> -                                    MEM_ACCESS_EMULATE_NOWRITE) != 0,
>> -                                   TRAP_invalid_op, 
>> HVM_DELIVER_NO_ERROR_CODE);
>> +        enum emul_kind kind = EMUL_KIND_NORMAL;
>> +
>> +        if ( v->arch.vm_event.emulate_flags & MEM_ACCESS_SET_EMUL_READ_DATA 
>> )
>> +            kind = EMUL_KIND_SET_CONTEXT;
>> +        else if ( v->arch.vm_event.emulate_flags & 
>> MEM_ACCESS_EMULATE_NOWRITE )
> 
> Is there code in place rejecting both flags being set at once? I don't
> recall having seen any...

No, there isn't. Both flags can be set at once, but if so only the
SET_EMUL_READ_DATA will be honored.


Thanks,
Razvan

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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