Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions common/insn_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,22 @@ insnq_interpret(insn_queue_t *queue)
int num_insns = queue->num_insns;
char *buffer = queue->buffer;

if ((unsigned) size > INSN_BUFFER_MAX) {
WARN("insnq: invalid instruction buffer size. All insns will be ignored.");
return EINSNQ;
}

while (num_insns_executed < num_insns) {
struct ulp_insn *insn = (struct ulp_insn *)&buffer[pc];

/* Make sure we won't go past the buffer. */
if (pc >= INSN_BUFFER_MAX) {
/* Abort if an invalid insn is received. */
WARN("insnq: received instruction surpasses the buffer size. Further"
"insns will be ignored.");
return EINSNQ;
}

if (ulp_insn_valid(insn)) {
pc += insn_interpret(insn);
num_insns_executed++;
Expand Down
6 changes: 3 additions & 3 deletions include/insn_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
#include <stdbool.h>
#include <stdint.h>

/** Define a 2Mb buffer for holding the instructions list. */
#define INSN_BUFFER_MAX (2 * 1024 * 1024)
/** Define a 256Kb buffer for holding the instructions list. */
#define INSN_BUFFER_MAX (256 * 1024)

/** Define the current version of the instruction queue. */
#define INSNQ_CURR_VERSION 1
#define INSNQ_CURR_VERSION 2

/** The ULP instruction queue. This works as follows:
* 1- Libpulp write instructions that should be executed on the `ulp` tool
Expand Down
31 changes: 28 additions & 3 deletions include/msg_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@

#include <stdarg.h>

/** Define a 2Mb buffer for holding the messages. */
#define MSGQ_BUFFER_MAX (2 * 1024 * 1024)
/** Define a 256Kb buffer for holding the messages in the old queue. */
#define MSGQ_BUFFER_MAX (256 * 1024)

/** Define a 2Mb buffer for holding the messages in the old queue. */
#define MSGQ_OLD_BUFFER_MAX (2 * 1024 * 1024)

/** This is the circular message queue datastructure.
*
Expand Down Expand Up @@ -60,10 +63,32 @@
* resulting in the circular queue behaviour. When reading this queue, the user
* should start reading from the bottom position.
*/

/** Define the same structure that is used by old versions of libpulp (<0.3.18) */
struct msg_queue
{
/** Size of the queue. Must match the size of MSGQ_BUFFER_MAX. */
int size;

/** Position pointing to free memory that can be written to. */
int top;

/** Position pointing to the oldest message still in buffer. */
int bottom;

/** Distance betweem top and bottom. Should not be greater than
* MSGQ_BUFFER_MAX. */
int distance;

/** Buffer holding the messages. */
char buffer[MSGQ_BUFFER_MAX];
};

/** Define the same structure that is used by old versions of libpulp (<0.3.18) */
struct msg_queue_old
{
/** Buffer holding the messages. */
char buffer[MSGQ_OLD_BUFFER_MAX];

/** Position pointing to free memory that can be written to. */
int top;
Expand All @@ -76,7 +101,7 @@ struct msg_queue
int distance;
};

extern struct msg_queue __ulp_msg_queue;
extern struct msg_queue __ulp_msg_queue_new;

void msgq_push(const char *format, ...);
void msgq_vpush(const char *format, va_list);
Expand Down
4 changes: 2 additions & 2 deletions include/ulp_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
#define OUT_PATCH_NAME "metadata.ulp"
#define OUT_REVERSE_NAME "reverse.ulp"

/* Use a 512kb buffer for metadata. This should be enough for most case
/* Use a 64kb buffer for metadata. This should be enough for most case
* scenarios. */
#define ULP_METADATA_BUF_LEN (512 * 1024)
#define ULP_METADATA_BUF_LEN (64 * 1024)
#define ULP_PATH_LEN 256

#define ARRAY_LENGTH(v) (sizeof(v) / sizeof(*(v)))
Expand Down
1 change: 1 addition & 0 deletions lib/libpulp.versions
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
__ulp_state;
__ulp_get_global_universe;
__ulp_msg_queue;
__ulp_msg_queue_new;
__ulp_metadata_buffer;
__ulp_error_state;
__ulp_enable_or_disable_patching;
Expand Down
24 changes: 13 additions & 11 deletions lib/msg_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,20 @@
/* Create an externally visible msg_queue object that will be read with ptrace.
* It will be read by ulp_messages (tools/messages.c) using ptrace. */

struct msg_queue __ulp_msg_queue;
struct msg_queue __ulp_msg_queue_new = { .size = MSGQ_BUFFER_MAX };

static char msg[MSGQ_BUFFER_MAX];
/* Define an buffer in which snprintf will expand tokens in strings. */
#define SPRINTF_BUFFER_SIZE 8192
static char msg[SPRINTF_BUFFER_SIZE];

static void
msgq_strpush(const char *msg, size_t msg_size)
{
/* Write the msg_queue values in variables for briefness. */
int top = __ulp_msg_queue.top;
int bottom = __ulp_msg_queue.bottom;
int distance = __ulp_msg_queue.distance;
char *buffer = __ulp_msg_queue.buffer;
int top = __ulp_msg_queue_new.top;
int bottom = __ulp_msg_queue_new.bottom;
int distance = __ulp_msg_queue_new.distance;
char *buffer = __ulp_msg_queue_new.buffer;

/* In case the message is empty or it is too large for the buffer, don't
* bother even trying to insert it. */
Expand Down Expand Up @@ -88,9 +90,9 @@ msgq_strpush(const char *msg, size_t msg_size)
distance += msg_size;
top = (top + msg_size) % MSGQ_BUFFER_MAX;

__ulp_msg_queue.top = top;
__ulp_msg_queue.bottom = bottom;
__ulp_msg_queue.distance = distance;
__ulp_msg_queue_new.top = top;
__ulp_msg_queue_new.bottom = bottom;
__ulp_msg_queue_new.distance = distance;
}

/* Push a message into the message queue.
Expand All @@ -107,7 +109,7 @@ msgq_push(const char *format, ...)
* return the size of the string, therefore, the size of the object will
* be +1 because of the null character in the end of the string. */
va_start(arglist, format);
msg_size = vsnprintf(msg, MSGQ_BUFFER_MAX, format, arglist) + 1;
msg_size = vsnprintf(msg, SPRINTF_BUFFER_SIZE, format, arglist) + 1;
va_end(arglist);

msgq_strpush(msg, msg_size);
Expand All @@ -125,7 +127,7 @@ msgq_vpush(const char *format, va_list arglist)
/* Expand the format string with the arguments provided. vsnprintf will
* return the size of the string, therefore, the size of the object will
* be +1 because of the null character in the end of the string. */
msg_size = vsnprintf(msg, MSGQ_BUFFER_MAX, format, arglist) + 1;
msg_size = vsnprintf(msg, SPRINTF_BUFFER_SIZE, format, arglist) + 1;

msgq_strpush(msg, msg_size);
}
Expand Down
3 changes: 2 additions & 1 deletion tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,8 @@ TESTS = \
seccomp_disable.py \
run_libc.py \
glibc_private.py \
dlopen.py
dlopen.py \
size.sh

XFAIL_TESTS = \
blocked.py \
Expand Down
9 changes: 8 additions & 1 deletion tests/insn_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ test1_parent(int child_pid)
close(1);
if (insnq_interpret_from_process_(child_pid,
(Elf64_Addr)&__ulp_insn_queue)) {
printf("Test 1 fail\n");
abort();
}
fflush(stdout);
Expand All @@ -104,7 +105,10 @@ test1_child(void)
int n = INSN_BUFFER_MAX / 8;
const char *string = "abc";
for (int i = 0; i < n; i++) {
insnq_insert_print(string);
if (insnq_insert_print(string)) {
printf("Error inserting print insn");
abort ();
}
}

send('a');
Expand All @@ -120,6 +124,7 @@ test2_parent(int child_pid)
wait_for('c');
if (insnq_interpret_from_process_(
child_pid, (Elf64_Addr)&__ulp_insn_queue) != EOLDULP) {
printf("Test 2 fail\n");
abort();
}
send('d');
Expand Down Expand Up @@ -180,6 +185,7 @@ test3_child(void)
wait_for('f');

if (memcmp(buf, (void *)write_frame, 8) != 0) {
printf("Test 3 fail\n");
abort();
}
}
Expand All @@ -204,6 +210,7 @@ test4_child(void)

/* Should detect that we are out of memory in the queue and fail. */
if (ret != EINSNQ) {
printf("Test 4 fail\n");
abort();
}

Expand Down
35 changes: 35 additions & 0 deletions tests/size.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/sh
#
# libpulp - User-space Livepatching Library
#
# Copyright (C) 2021-2025 SUSE Software Solutions GmbH
#
# This file is part of libpulp.
#
# libpulp is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# libpulp is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libpulp. If not, see <http://www.gnu.org/licenses/>.

# Check if the code / variable size from libpulp does not surpass 1Mb

SIZE=$(nm --print-size --size-sort --radix=d ../lib/.libs/libpulp.so.0 | awk '{ sum += $2 } END {print sum}')
echo "Size: $SIZE"

if [ "x$SIZE" == "x" ]; then
exit 1
fi

if [ $SIZE -gt $(expr 1024 \* 1024) ]; then
exit 1
fi

exit 0
6 changes: 5 additions & 1 deletion tools/introspection.c
Original file line number Diff line number Diff line change
Expand Up @@ -913,8 +913,12 @@ get_libpulp_extern_symbols(struct ulp_dynobj *obj, int pid)
bitfield |= (1 << 3);
}
else if (!strcmp(remote_name, "_msg_queue")) {
obj->msg_queue_old = ehdr_addr + sym.st_value;
bitfield |= (1 << 4); // Use the same bitfield as the msg_queue.
}
else if (!strcmp(remote_name, "_msg_queue_new")) {
obj->msg_queue = ehdr_addr + sym.st_value;
bitfield |= (1 << 4);
bitfield |= (1 << 4); // Use the same bitfield as the msg_queue.
}
else if (!strcmp(remote_name, "_revert_all")) {
obj->revert_all = ehdr_addr + sym.st_value;
Expand Down
1 change: 1 addition & 0 deletions tools/introspection.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ struct ulp_dynobj
Elf64_Addr check;
Elf64_Addr state;
Elf64_Addr global;
Elf64_Addr msg_queue_old;
Elf64_Addr msg_queue;
Elf64_Addr revert_all;
Elf64_Addr metadata_buffer;
Expand Down
Loading