Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
3762832
feat: add linux distributions to os context
supervacuus Mar 7, 2024
dac3e9a
Clean up test-allocations like a good boy
supervacuus Mar 7, 2024
80d2c92
separate os-dependent unit-test sources
supervacuus Mar 7, 2024
2d09fff
platform-specfic testing is decided in the translation-units
supervacuus Mar 7, 2024
ef59a2b
Exclude Android too
supervacuus Mar 7, 2024
cafe146
Add documented fallback
supervacuus Mar 7, 2024
1dc898e
Ensure we exhausted the snapshot
supervacuus Mar 7, 2024
40c44d8
DeMorgan
supervacuus Mar 8, 2024
be4b072
format
supervacuus Mar 8, 2024
767f1a9
add valgrind exception for false positive when memmove is an ifunc re…
supervacuus Mar 8, 2024
94c5cfd
Make sure that distributions are only added in Linux not any Unix
supervacuus Mar 8, 2024
de55584
Make sure we don't leak in the error paths
supervacuus Mar 11, 2024
44866bb
Clean up the fall-back from /etc/os-release to /usr/lib/os-release
supervacuus Mar 11, 2024
7c2c9d5
attribute derivative work
supervacuus Mar 25, 2024
9de5325
apply PR feedback
supervacuus Mar 25, 2024
3269200
Extract slice to buffer handling in a new sentry_slice_t function.
supervacuus Mar 25, 2024
5becaee
Make sure we can read a full line of max value and max key.
supervacuus Mar 25, 2024
a646eac
fix classic buffer continuity bug.
supervacuus Mar 29, 2024
2ecabb5
extract parse_line_into_object...
supervacuus Mar 29, 2024
8e1c4e1
Merge branch 'master' into feat/add_linux_distros_to_os_context
supervacuus Mar 29, 2024
fecafa2
Merge branch 'master' into feat/add_linux_distros_to_os_context
supervacuus Apr 16, 2024
ff5452c
ensure line update if we hit the buffer-end correctly.
supervacuus Apr 16, 2024
5c06566
add support for os-release files that don't end with a newline.
supervacuus Apr 16, 2024
c18b5ff
Add comments to the subtler buffer management aspects.
supervacuus Apr 17, 2024
0b226e8
Add a list of tested distribution names for documentation
supervacuus Apr 22, 2024
eb6bc17
Add back eof-newline to valgrind exceptions.
supervacuus Apr 22, 2024
75583ff
Adapt test to new entry in fixture.
supervacuus Apr 22, 2024
8549b1d
Merge branch 'master' into feat/add_linux_distros_to_os_context
supervacuus May 27, 2024
c51c39f
include sentry_utils in sentry_os only on Linux
supervacuus May 27, 2024
bcc633b
Ensure we find close() in unistd.h by including it explicitly.
supervacuus May 27, 2024
4b3f9ca
include sentry_utils in sentry_os on Windows too
supervacuus May 27, 2024
6097e9d
use unistd.h in sentry_os only for Linux
supervacuus May 27, 2024
5f9df80
flattened distribution payload fields
JoshuaMoelans Nov 25, 2024
a841e81
format
JoshuaMoelans Nov 25, 2024
ffad25d
incref for get_by_key calls
JoshuaMoelans Nov 25, 2024
1699009
decref no longer copied os_dist
JoshuaMoelans Nov 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

**Features**:

- Add Linux distributions to the OS context. [#963](https://github.com/getsentry/sentry-native/pull/963)
- Change the timestamp resolution to microseconds. ([#995](https://github.com/getsentry/sentry-native/pull/995))

## 0.7.4
Expand Down
3 changes: 1 addition & 2 deletions src/modulefinder/sentry_modulefinder_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "sentry_path.h"
#include "sentry_string.h"
#include "sentry_sync.h"
#include "sentry_utils.h"
#include "sentry_value.h"

#include <arpa/inet.h>
Expand All @@ -31,8 +32,6 @@ process_vm_readv(pid_t __pid, const struct iovec *__local_iov,
}
#endif

#define MIN(a, b) ((a) < (b) ? (a) : (b))

#define ENSURE(Ptr) \
if (!Ptr) \
goto fail
Expand Down
152 changes: 151 additions & 1 deletion src/sentry_os.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
#include "sentry_os.h"
#include "sentry_slice.h"
#include "sentry_string.h"
#include "sentry_utils.h"
#if defined(SENTRY_PLATFORM_LINUX) || defined(SENTRY_PLATFORM_WINDOWS)
# include "sentry_utils.h"
#endif
#ifdef SENTRY_PLATFORM_LINUX
# include <unistd.h>
#endif

#ifdef SENTRY_PLATFORM_WINDOWS

Expand Down Expand Up @@ -228,8 +234,123 @@ sentry__get_os_context(void)
}
#elif defined(SENTRY_PLATFORM_UNIX)

# include <fcntl.h>
# include <sys/utsname.h>

# if defined(SENTRY_PLATFORM_LINUX)
# define OS_RELEASE_MAX_LINE_SIZE 256
# define OS_RELEASE_MAX_KEY_SIZE 64
# define OS_RELEASE_MAX_VALUE_SIZE 128

static int
parse_os_release_line(const char *line, char *key, char *value)
{
const char *equals = strchr(line, '=');
if (equals == NULL)
return 1;

unsigned long key_length = MIN(equals - line, OS_RELEASE_MAX_KEY_SIZE - 1);
strncpy(key, line, key_length);
key[key_length] = '\0';

sentry_slice_t value_slice
= { .ptr = equals + 1, .len = strlen(equals + 1) };

// some values are wrapped in double quotes
if (value_slice.ptr[0] == '\"') {
value_slice.ptr++;
value_slice.len -= 2;
}

sentry__slice_to_buffer(value_slice, value, OS_RELEASE_MAX_VALUE_SIZE);

return 0;
}

static void
parse_line_into_object(const char *line, sentry_value_t os_dist)
{
char value[OS_RELEASE_MAX_VALUE_SIZE];
char key[OS_RELEASE_MAX_KEY_SIZE];

if (parse_os_release_line(line, key, value) == 0) {
if (strcmp(key, "ID") == 0) {
sentry_value_set_by_key(
os_dist, "name", sentry_value_new_string(value));
}

if (strcmp(key, "VERSION_ID") == 0) {
sentry_value_set_by_key(
os_dist, "version", sentry_value_new_string(value));
}

if (strcmp(key, "PRETTY_NAME") == 0) {
sentry_value_set_by_key(
os_dist, "pretty_name", sentry_value_new_string(value));
}
}
}

# ifndef SENTRY_UNITTEST
static
# endif
sentry_value_t
get_linux_os_release(const char *os_rel_path)
{
const int fd = open(os_rel_path, O_RDONLY);
if (fd == -1) {
return sentry_value_new_null();
}

sentry_value_t os_dist = sentry_value_new_object();
char buffer[OS_RELEASE_MAX_LINE_SIZE];
ssize_t bytes_read;
ssize_t buffer_rest = 0;
const char *line = buffer;
while ((bytes_read = read(
fd, buffer + buffer_rest, sizeof(buffer) - buffer_rest - 1))
> 0) {
ssize_t buffer_end = buffer_rest + bytes_read;
buffer[buffer_end] = '\0';

// extract all lines from the valid buffer-range and parse them
for (char *p = buffer; *p; ++p) {
if (*p != '\n') {
continue;
}
*p = '\0';
parse_line_into_object(line, os_dist);
line = p + 1;
}

if (line < buffer + buffer_end) {
// move the remaining partial line to the start of the buffer
buffer_rest = buffer + buffer_end - line;
memmove(buffer, line, buffer_rest);
} else {
// reset buffer_rest: the line-end coincided with the buffer-end
buffer_rest = 0;
}
line = buffer;
}

if (bytes_read == -1) {
// read() failed and we can't assume to have valid data
sentry_value_decref(os_dist);
os_dist = sentry_value_new_null();
} else if (buffer_rest > 0) {
// the file ended w/o a new-line; we still have a line left to parse
buffer[buffer_rest] = '\0';
parse_line_into_object(line, os_dist);
}

close(fd);

return os_dist;
}

# endif // defined(SENTRY_PLATFORM_LINUX)

sentry_value_t
sentry__get_os_context(void)
{
Expand Down Expand Up @@ -270,6 +391,35 @@ sentry__get_os_context(void)
sentry_value_set_by_key(
os, "version", sentry_value_new_string(uts.release));

# if defined(SENTRY_PLATFORM_LINUX)
/**
* The file /etc/os-release takes precedence over /usr/lib/os-release.
* Applications should check for the former, and exclusively use its data if
* it exists, and only fall back to /usr/lib/os-release if it is missing.
* Applications should not read data from both files at the same time.
*
* From:
* https://www.freedesktop.org/software/systemd/man/latest/os-release.html#Description
*/
sentry_value_t os_dist = get_linux_os_release("/etc/os-release");
if (sentry_value_is_null(os_dist)) {
os_dist = get_linux_os_release("/usr/lib/os-release");
if (sentry_value_is_null(os_dist)) {
return os;
}
}
sentry_value_set_by_key(
os, "distribution_name", sentry_value_get_by_key(os_dist, "name"));
sentry_value_set_by_key(os, "distribution_version",
sentry_value_get_by_key(os_dist, "version"));
sentry_value_set_by_key(os, "distribution_pretty_name",
sentry_value_get_by_key(os_dist, "pretty_name"));
sentry_value_incref(sentry_value_get_by_key(os_dist, "name"));
sentry_value_incref(sentry_value_get_by_key(os_dist, "version"));
sentry_value_incref(sentry_value_get_by_key(os_dist, "pretty_name"));
sentry_value_decref(os_dist);
# endif // defined(SENTRY_PLATFORM_LINUX)

return os;

fail:
Expand Down
9 changes: 9 additions & 0 deletions src/sentry_slice.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "sentry_slice.h"
#include "sentry_string.h"
#include "sentry_utils.h"
#include <stdlib.h>
#include <string.h>

Expand All @@ -18,6 +19,14 @@ sentry__slice_to_owned(sentry_slice_t slice)
return sentry__string_clone_n_unchecked(slice.ptr, slice.len);
}

void
sentry__slice_to_buffer(sentry_slice_t slice, char *buffer, size_t buffer_len)
{
size_t copy_len = MIN(slice.len, buffer_len - 1);
strncpy(buffer, slice.ptr, copy_len);
buffer[copy_len] = 0;
}

bool
sentry__slice_eq(sentry_slice_t a, sentry_slice_t b)
{
Expand Down
8 changes: 8 additions & 0 deletions src/sentry_slice.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ typedef struct {
*/
sentry_slice_t sentry__slice_from_str(const char *str);

/**
* Copies a slice to a pre-allocated buffer. The resulting buffer will contain a
* zero-terminated string. `buffer_len` is expected to be the full length of the
* buffer, so the resulting string can at maximum be `buffer_len - 1` long.
*/
void sentry__slice_to_buffer(
sentry_slice_t slice, char *buffer, size_t buffer_len);

/**
* Creates an owned copy from a slice.
*/
Expand Down
3 changes: 3 additions & 0 deletions src/sentry_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
# include <time.h>
#endif

#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))

/**
* This represents a URL parsed into its different parts.
*/
Expand Down
2 changes: 2 additions & 0 deletions tests/assertions.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ def assert_meta(
event["contexts"]["os"],
{"name": "Linux", "version": version, "build": build},
)
assert "distribution_name" in event["contexts"]["os"]
assert "distribution_version" in event["contexts"]["os"]
elif sys.platform == "darwin":
version = platform.mac_ver()[0].split(".")
if len(version) < 3:
Expand Down
Loading
Loading