The prot flag passed to mmap() is set to PROT_WRITE when the O_RDWR
access flags is used. This assumes that PROT_WRITE grants read
permissions on the mmap'ed region. While this is true on x86, this
causes a segmentation fault on SPARC and, presumably, other
architectures implementing strict access permissions.
CTF Writer needs read permissions since the unaligned integer writes
may use load instructions as the value is read back to perform the
required shifting/masking is performed in the _bt_bitfield_write_*
macros.
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
pos->parent.trace = trace;
break;
case O_RDWR:
pos->parent.trace = trace;
break;
case O_RDWR:
- pos->prot = PROT_WRITE; /* Write has priority */
+ pos->prot = PROT_READ | PROT_WRITE;
pos->flags = MAP_SHARED;
pos->parent.rw_table = write_dispatch_table;
pos->parent.event_cb = ctf_write_event;
pos->flags = MAP_SHARED;
pos->parent.rw_table = write_dispatch_table;
pos->parent.event_cb = ctf_write_event;
int ctf_fini_pos(struct ctf_stream_pos *pos)
{
int ctf_fini_pos(struct ctf_stream_pos *pos)
{
- if (pos->prot == PROT_WRITE && pos->content_size_loc)
+ if ((pos->prot & PROT_WRITE) && pos->content_size_loc)
*pos->content_size_loc = pos->offset;
if (pos->base_mma) {
int ret;
*pos->content_size_loc = pos->offset;
if (pos->base_mma) {
int ret;
- if (pos->prot == PROT_WRITE && pos->content_size_loc)
+ if ((pos->prot & PROT_WRITE) && pos->content_size_loc)
*pos->content_size_loc = pos->offset;
if (pos->base_mma) {
*pos->content_size_loc = pos->offset;
if (pos->base_mma) {
* The caller should never ask for ctf_move_pos across packets,
* except to get exactly at the beginning of the next packet.
*/
* The caller should never ask for ctf_move_pos across packets,
* except to get exactly at the beginning of the next packet.
*/
- if (pos->prot == PROT_WRITE) {
+ if (pos->prot & PROT_WRITE) {
switch (whence) {
case SEEK_CUR:
/* The writer will add padding */
switch (whence) {
case SEEK_CUR:
/* The writer will add padding */
}
/* update trace_packet_header and stream_packet_context */
}
/* update trace_packet_header and stream_packet_context */
- if (pos->prot != PROT_WRITE && file_stream->parent.trace_packet_header) {
+ if (!(pos->prot & PROT_WRITE) &&
+ file_stream->parent.trace_packet_header) {
/* Read packet header */
ret = generic_rw(&pos->parent, &file_stream->parent.trace_packet_header->p);
assert(!ret);
}
/* Read packet header */
ret = generic_rw(&pos->parent, &file_stream->parent.trace_packet_header->p);
assert(!ret);
}
- if (pos->prot != PROT_WRITE && file_stream->parent.stream_packet_context) {
+ if (!(pos->prot & PROT_WRITE) &&
+ file_stream->parent.stream_packet_context) {
/* Read packet context */
ret = generic_rw(&pos->parent, &file_stream->parent.stream_packet_context->p);
assert(!ret);
/* Read packet context */
ret = generic_rw(&pos->parent, &file_stream->parent.stream_packet_context->p);
assert(!ret);
int ret;
/* update trace_packet_header and stream_packet_context */
int ret;
/* update trace_packet_header and stream_packet_context */
- if (pos->prot != PROT_WRITE && file_stream->parent.trace_packet_header) {
+ if (!(pos->prot & PROT_WRITE) &&
+ file_stream->parent.trace_packet_header) {
/* Read packet header */
ret = generic_rw(&pos->parent,
&file_stream->parent.trace_packet_header->p);
/* Read packet header */
ret = generic_rw(&pos->parent,
&file_stream->parent.trace_packet_header->p);
- if (pos->prot != PROT_WRITE && file_stream->parent.stream_packet_context) {
+ if (!(pos->prot & PROT_WRITE) &&
+ file_stream->parent.stream_packet_context) {
/* Read packet context */
ret = generic_rw(&pos->parent,
&file_stream->parent.stream_packet_context->p);
/* Read packet context */
ret = generic_rw(&pos->parent,
&file_stream->parent.stream_packet_context->p);
int fd, int open_flags);
int ctf_fini_pos(struct ctf_stream_pos *pos);
int fd, int open_flags);
int ctf_fini_pos(struct ctf_stream_pos *pos);
+static inline
+int ctf_pos_access_ok(struct ctf_stream_pos *pos, uint64_t bit_len)
+{
+ uint64_t max_len;
+
+ if (unlikely(pos->offset == EOF))
+ return 0;
+ if (pos->prot == PROT_READ) {
+ /*
+ * Reads may only reach up to the "content_size",
+ * regardless of the packet_size.
+ */
+ max_len = pos->content_size;
+ } else {
+ /* Writes may take place up to the end of the packet. */
+ max_len = pos->packet_size;
+ }
+ if (unlikely(pos->offset + bit_len > max_len))
+ return 0;
+ return 1;
+}
+
/*
* move_pos - move position of a relative bit offset
*
/*
* move_pos - move position of a relative bit offset
*
static inline
int ctf_move_pos(struct ctf_stream_pos *pos, uint64_t bit_offset)
{
static inline
int ctf_move_pos(struct ctf_stream_pos *pos, uint64_t bit_offset)
{
printf_debug("ctf_move_pos test EOF: %" PRId64 "\n", pos->offset);
printf_debug("ctf_move_pos test EOF: %" PRId64 "\n", pos->offset);
- if (unlikely(pos->offset == EOF))
- return 0;
- if (pos->prot == PROT_READ)
- max_len = pos->content_size;
- else
- max_len = pos->packet_size;
- if (unlikely(pos->offset + bit_offset > max_len))
- return 0;
-
+ ret = ctf_pos_access_ok(pos, bit_offset);
+ if (!ret) {
+ goto end;
+ }
pos->offset += bit_offset;
printf_debug("ctf_move_pos after increment: %" PRId64 "\n", pos->offset);
pos->offset += bit_offset;
printf_debug("ctf_move_pos after increment: %" PRId64 "\n", pos->offset);
ctf_packet_seek(&pos->parent, 0, SEEK_CUR);
}
ctf_packet_seek(&pos->parent, 0, SEEK_CUR);
}
-static inline
-int ctf_pos_access_ok(struct ctf_stream_pos *pos, uint64_t bit_len)
-{
- uint64_t max_len;
-
- if (unlikely(pos->offset == EOF))
- return 0;
- if (pos->prot == PROT_READ)
- max_len = pos->content_size;
- else
- max_len = pos->packet_size;
- if (unlikely(pos->offset + bit_len > max_len))
- return 0;
- return 1;
-}
-
/*
* Update the stream position to the current event. This moves to
* the next packet if we are located at the end of the current packet.
/*
* Update the stream position to the current event. This moves to
* the next packet if we are located at the end of the current packet.