blob: f24e58fe0ff368617e0bf736a564aab5f1734157 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Container Security Monitor module
*
* Copyright (c) 2018 Google, Inc
*/
#include "monitor.h"
#include <linux/string.h>
#include <net/sock.h>
#include <net/tcp.h>
#include <net/ipv6.h>
bool pb_encode_string_field(pb_ostream_t *stream, const pb_field_t *field,
void * const *arg)
{
const uint8_t *str = (const uint8_t *)*arg;
/* If the string is not set, skip this string. */
if (!str)
return true;
if (!pb_encode_tag_for_field(stream, field))
return false;
return pb_encode_string(stream, str, strlen(str));
}
bool pb_decode_string_field(pb_istream_t *stream, const pb_field_t *field,
void **arg)
{
size_t size;
void *data;
*arg = NULL;
size = stream->bytes_left;
/* Ensure a null-byte at the end */
if (size + 1 < size)
return false;
data = kzalloc(size + 1, GFP_KERNEL);
if (!data)
return false;
if (!pb_read(stream, data, size)) {
kfree(data);
return false;
}
*arg = data;
return true;
}
bool pb_encode_string_array(pb_ostream_t *stream, const pb_field_t *field,
void * const *arg)
{
char *strs = (char *)*arg;
/* If the string array is not set, skip this string array. */
if (!strs)
return true;
do {
if (!pb_encode_string_field(stream, field,
(void * const *) &strs))
return false;
strs += strlen(strs) + 1;
} while (*strs != 0);
return true;
}
/* Limit the encoded string size and return how many characters were added. */
ssize_t pb_encode_string_field_limit(pb_ostream_t *stream,
const pb_field_t *field,
void * const *arg, size_t limit)
{
char *str = (char *)*arg;
size_t length;
/* If the string is not set, skip this string. */
if (!str)
return 0;
if (!pb_encode_tag_for_field(stream, field))
return -EINVAL;
length = strlen(str);
if (length > limit)
length = limit;
if (!pb_encode_string(stream, (uint8_t *)str, length))
return -EINVAL;
return length;
}
bool pb_decode_string_array(pb_istream_t *stream, const pb_field_t *field,
void **arg)
{
size_t needed, used = 0;
char *data, *strs;
/* String length, and two null-bytes for the end of the list. */
needed = stream->bytes_left + 2;
if (needed < stream->bytes_left)
return false;
if (*arg) {
/* Calculate used space from the current list. */
strs = (char *)*arg;
do {
used += strlen(strs + used) + 1;
} while (strs[used] != 0);
if (used + needed < needed)
return false;
}
data = krealloc(*arg, used + needed, GFP_KERNEL);
if (!data)
return false;
/* Will always be freed by the caller */
*arg = data;
/* Reset the new part of the buffer. */
memset(data + used, 0, needed);
/* Read what's in the stream buffer only. */
if (!pb_read(stream, data + used, stream->bytes_left))
return false;
return true;
}
bool pb_encode_fixed_string(pb_ostream_t *stream, const pb_field_t *field,
const uint8_t *data, size_t length)
{
/* If the data is not set, skip this string. */
if (!data)
return true;
if (!pb_encode_tag_for_field(stream, field))
return false;
return pb_encode_string(stream, data, length);
}
bool pb_encode_uuid_field(pb_ostream_t *stream, const pb_field_t *field,
void * const *arg)
{
return pb_encode_fixed_string(stream, field, (const uint8_t *)*arg,
PROCESS_UUID_SIZE);
}
bool pb_encode_ip4(pb_ostream_t *stream, const pb_field_t *field,
void * const *arg)
{
return pb_encode_fixed_string(stream, field, (const uint8_t *)*arg,
sizeof(struct in_addr));
}
bool pb_encode_ip6(pb_ostream_t *stream, const pb_field_t *field,
void * const *arg)
{
return pb_encode_fixed_string(stream, field, (const uint8_t *)*arg,
sizeof(struct in6_addr));
}