Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rpc: Convert attribute value for portability #67

Merged
merged 1 commit into from
May 22, 2017

Conversation

ueno
Copy link
Member

@ueno ueno commented May 11, 2017

When using the RPC across multiple architectures, where data models
are different, say LP64 vs ILP32, there can be unwanted truncation of
attribute values.

This patch converts the values into portable format for the known
attributes.

@ueno ueno force-pushed the wip/dueno/portable-attribute branch from f71ef1b to 3d45b04 Compare May 12, 2017 09:20
CK_ULONG ulong_value;

memcpy (&ulong_value, value, value_length);
if (ulong_value > 0xFFFFFFFFFFFFFFFF)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That inequality is only true if value length > 8. Is the intention there to detect calls where value_length > 8? If yes, why not have that explicitly, such as:

if (value_length > 8)
...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here the code converts the value to the wire format in two steps: first it converts void * into CK_ULONG and then CK_ULONG to uint64_t. So there should be separate checks for those. I have added them to all encoding functions.

unsigned char validity;
size_t total = 0;
static const p11_rpc_attribute_value_encoder encoders[] = {
p11_rpc_buffer_add_attribute_value_byte,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A suggestion to make that easier to read; there is a (C99) form that allows to make the mappings apparent:

static const p11_rpc_attribute_value_encoder encoders[] = {
    [P11_RPC_ATTR_BYTE] = p11_rpc_buffer_add_attribute_value_byte,
    [P11_RPC_ATTR_ULONG] = p11_rpc_buffer_add_attribute_value_ulong,
...
}

That form guarrantees that any unset values will be zero.


/* The attribute length and value */
p11_rpc_buffer_add_uint32 (buffer, attr->ulValueLen);
encoder = encoders[map_attribute_type_to_value_type (attr->type)];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems like error prone on future revisions (when new RPC types are added), with a jump to an invalid address confusing debuggers. Maybe separate into an assign part to allow error checking? e.g.

if (attr->type > P11_RPC_ATTR_MAX)
  error();

mapval = map_attribute_type_to_value_type (attr->type);
encoder = encoders[mapval]
if (encoder == NULL)
  error();

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a couple of asserts there.


/* Decode the attribute value */
value_type = map_attribute_type_to_value_type (type);
decoder = decoders[value_type];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as for the encoder for safety.

{
CK_BYTE byte_value;

memcpy (&byte_value, value, value_length);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if value_length > 1?

static bool
p11_rpc_buffer_get_attribute_value_byte (p11_buffer *buffer,
size_t *offset,
uint32_t expected,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are both expected and value_length needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, the expected length is tracked in buffer, so I removed expected.

} else {
attrs[i].pValue = NULL;
attrs[i].ulValueLen = -1;
}

msg->parsed = offset;
}

*result = attrs;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a test suite of the new changes would be quite needed. I attach a minimal one for the byte and ulong types.
test-suite.patch.gz

Something related, is that since we go through systems we would also need a fuzzer for the server and client to ensure there is no compromise possible; we can use AFL or even oss-fuzz project for that. An example fuzzer that can be used as base is at gnutls repo devel/fuzz/gnutls_server_fuzzer.cc.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the review. It's embarrassing that the patch didn't have any additional tests. I have merged the patch and added tests for other value types. I will give it a try with AFL.

@ueno ueno force-pushed the wip/dueno/portable-attribute branch 3 times, most recently from 1f367bd to 87d4114 Compare May 16, 2017 12:43
When using the RPC across multiple architectures, where data models
are different, say LP64 vs ILP32, there can be unwanted truncation of
attribute values.

This patch converts the values into portable format for the known
attributes.

Co-authored-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
@ueno ueno force-pushed the wip/dueno/portable-attribute branch from 87d4114 to e94524f Compare May 22, 2017 15:02
@ueno ueno merged commit ba49b85 into p11-glue:master May 22, 2017
@ueno
Copy link
Member Author

ueno commented May 22, 2017

Merging this. The fuzzer based on AFL was added as #73 .

@ueno ueno deleted the wip/dueno/portable-attribute branch May 23, 2017 07:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants