├── .clang-format ├── .github └── workflows │ ├── coding-style.yml │ └── test-suite.yml ├── .gitignore ├── LICENSE ├── Makefile.am ├── Makefile.common ├── README.md ├── bootstrap ├── common ├── Makefile.am ├── common.c └── insn_queue.c ├── config └── .gitignore ├── configure.ac ├── docs ├── Doxyfile.in └── Makefile.am ├── examples ├── README.md └── cplusplus │ ├── 1-class │ ├── Makefile │ ├── README.md │ ├── a_livepatch1.cpp │ ├── a_livepatch1.dsc │ └── class.cpp │ ├── 2-private_class │ ├── Makefile │ ├── README.md │ ├── a_livepatch1.cpp │ ├── a_livepatch1.dsc │ └── class.cpp │ ├── 3-indirect_call │ ├── Makefile │ ├── README.md │ ├── a_livepatch1.cpp │ ├── a_livepatch1.dsc │ └── class.cpp │ ├── 4-global_var │ ├── Makefile │ ├── README.md │ ├── a_livepatch1.cpp │ ├── a_livepatch1.dsc │ └── test.cpp │ └── 5-queue │ ├── Makefile │ ├── README.md │ ├── a_livepatch1.cpp │ ├── a_livepatch1.dsc │ └── class.cpp ├── include ├── .gitignore ├── Makefile.am ├── arch │ ├── powerpc64le │ │ └── arch_common.h │ └── x86_64 │ │ └── arch_common.h ├── error.h ├── error_common.h ├── insn_queue.h ├── insn_queue_lib.h ├── interpose.h ├── ld_rtld.h ├── minielf.h ├── msg_queue.h ├── terminal_colors.h ├── ulp.h └── ulp_common.h ├── lib ├── Makefile.am ├── arch │ ├── powerpc64le │ │ ├── patch.c │ │ ├── ulp_interface.S │ │ └── ulp_prologue.S │ └── x86_64 │ │ ├── patch.c │ │ └── ulp_interface.S ├── error.c ├── gdb_interface.c ├── insn_queue.c ├── interpose.c ├── libpulp.versions ├── minielf.c ├── msg_queue.c └── ulp.c ├── man ├── Makefile.am ├── libpulp.7 └── ulp.1 ├── patches └── gcc │ └── fix-pfe-section-flags.diff ├── scripts ├── Makefile.am ├── collect.sh ├── common_lib.sh ├── dispatcher.lua ├── extract_function.sh ├── glibc.sh ├── setup_package.sh └── ulp_apply.sh ├── tests ├── Makefile.am ├── README.Makefile.am ├── access.c ├── access.py ├── access2.c ├── access2.py ├── asunsafe_conversion.c ├── asunsafe_conversion.py ├── block_mprotect.c ├── blocked.c ├── blocked.py ├── buildid.c ├── buildid.py ├── cancel.c ├── cancel.py ├── chroot.c ├── chroot.py ├── comments.c ├── comments.py ├── constructor-template.c ├── constructor.c ├── constructor.py ├── contract.c ├── contract.py ├── deadlock.c ├── deadlock.py ├── dlsym.c ├── dlsym_lock.py ├── dozens.c ├── dozens.h ├── endbr64.c ├── endbr64.py ├── exception_handling.cc ├── exception_handling.py ├── fuz │ ├── 1 │ ├── 2 │ ├── 3 │ ├── 4 │ ├── 5 │ ├── 6 │ ├── 7 │ └── README.md ├── glibc_private.py ├── group_disable.py ├── hidden.py ├── hundreds.c ├── hundreds.h ├── insn_queue.c ├── insn_queue.py ├── libaccess.c ├── libaccess.h ├── libaccess_livepatch1.c ├── libaccess_livepatch1.in ├── libaccess_livepatch2.c ├── libaccess_livepatch2.in ├── libaddress.c ├── libaddress.h ├── libaddress_livepatch1.c ├── libaddress_livepatch1.in ├── libblocked.c ├── libblocked.h ├── libblocked_livepatch1.c ├── libblocked_livepatch1.in ├── libbuildid.c ├── libbuildid_livepatch1.c ├── libbuildid_livepatch1.in ├── libcomments_livepatch1.c ├── libcomments_livepatch1.in ├── libconstructor.c ├── libconstructor.h ├── libcontract.c ├── libcontract.h ├── libcontract_livepatch1.c ├── libcontract_livepatch1.in ├── libdozens_bsymbolic_livepatch1.in ├── libdozens_livepatch1.c ├── libdozens_livepatch1.in ├── libdozens_livepatch99.c ├── libdozens_livepatch99.in ├── libendbr64.c ├── libendbr64_livepatch1.in ├── libexception.cc ├── libexception.h ├── libhundreds_bsymbolic_livepatch1.in ├── libhundreds_livepatch1.c ├── libhundreds_livepatch1.in ├── libhundreds_livepatch2.c ├── libhundreds_livepatch2.in ├── libhundreds_livepatch3.c ├── libhundreds_livepatch3.in ├── libmanyprocesses.c ├── libmanyprocesses_livepatch1.c ├── libmanyprocesses_livepatch1.in ├── libnotes_livepatch1.c ├── libnotes_livepatch1.in ├── libpagecross.c ├── libpagecross_livepatch1.c ├── libpagecross_livepatch1.in ├── libpagecross_padding.S ├── libparameters.c ├── libparameters.h ├── libparameters_livepatch1.c ├── libparameters_livepatch1.in ├── libparameters_livepatch2.c ├── libparameters_livepatch2.in ├── libparameters_livepatch3.c ├── libparameters_livepatch3.in ├── libprefix.c ├── libprefix_livepatch1.in ├── libprocess_access_livepatch1.in ├── libprocess_livepatch1.c ├── libprocess_livepatch1.in ├── libpulp_messages.py ├── librecursion.c ├── librecursion.h ├── librecursion2.c ├── librecursion2.h ├── librecursion2_livepatch1.c ├── librecursion2_livepatch1.in ├── librecursion_livepatch1.c ├── librecursion_livepatch1.in ├── libsecdis_livepatch1.c ├── libsecdis_livepatch1.in ├── libstress.c ├── libstress_livepatch1.c ├── libstress_livepatch1.in ├── libtls.c ├── libtls_livepatch1.c ├── libtls_livepatch1.in ├── libvisibility.c ├── libvisibility_livepatch1.c ├── libvisibility_livepatch1.in ├── libvisibility_livepatch2.c ├── libvisibility_livepatch2.in ├── livepatchable.py ├── loop.c ├── manyprocesses.c ├── manyprocesses.py ├── memory_protection.c ├── memory_protection.py ├── missing_function.py ├── mprotect_patch.py ├── nolibpulp.py ├── notes.c ├── notes.ld ├── notes.py ├── numserv.c ├── numserv.py ├── numserv_bsymbolic.py ├── offsets.py ├── pagecross.c ├── pagecross.py ├── parameters.c ├── parameters.py ├── patches.py ├── path_disable.py ├── pcqueue.c ├── pcqueue.py ├── prefix.c ├── prefix.py ├── process.c ├── process.py ├── process_access.c ├── process_access.py ├── process_access_livepatch1.c ├── process_revert.py ├── recursion.c ├── recursion.py ├── recursion2.c ├── recursion2.py ├── redzone.c ├── redzone.py ├── relative_path.py ├── revert.py ├── revert_all.py ├── revert_all_target1.py ├── revert_all_target2.py ├── revert_and_patch.py ├── revert_with_invalid.py ├── run_libc.py ├── seccomp_disable.py ├── set_patchable.py ├── stress.c ├── stress.py ├── syscall_restart.c ├── syscall_restart.py ├── tempfiles.py ├── terminal.c ├── terminal.py ├── testsuite.py ├── textrel.py ├── tls.c ├── tls.py ├── user_disable.py ├── visibility.c └── visibility.py └── tools ├── Makefile.am ├── arch ├── powerpc64le │ └── post-arch.c └── x86_64 │ └── post-arch.c ├── arguments.h ├── check.c ├── check.h ├── dump.c ├── dump.h ├── elf-extra.c ├── elf-extra.h ├── extract.c ├── extract.h ├── insn_queue.c ├── insn_queue_tools.h ├── introspection.c ├── introspection.h ├── livepatchable.c ├── livepatchable.h ├── md4.c ├── md4.h ├── messages.c ├── messages.h ├── packer.c ├── packer.h ├── patches.c ├── patches.h ├── pcqueue.c ├── pcqueue.h ├── post.c ├── post.h ├── ptrace.c ├── ptrace.h ├── set_patchable.c ├── set_patchable.h ├── trigger.c ├── trigger.h └── ulp.c /.github/workflows/coding-style.yml: -------------------------------------------------------------------------------- 1 | name: Coding Style 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | clang-format: 11 | runs-on: ubuntu-latest 12 | 13 | container: 14 | image: opensuse/tumbleweed 15 | 16 | steps: 17 | - name: dependencies 18 | run: zypper -n install clang git findutils file 19 | - uses: actions/checkout@v2 20 | - name: format 21 | run: find -type f \( -name "*.[c|h]" -or -name "*.cc" \) -exec clang-format -style=file -i {} \; 22 | - name: verify 23 | run: /bin/bash -c "git status --short | file - | grep empty" 24 | id: verify 25 | - name: diagnostics 26 | if: failure() && steps.verify.outcome == 'failure' 27 | run: git diff 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.tar.* 2 | Makefile.in 3 | configure 4 | aclocal.m4 5 | autom4te.cache 6 | *~ 7 | *.swp 8 | dev/ 9 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # libpulp - User-space Livepatching Library 2 | # 3 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 4 | # 5 | # This file is part of libpulp. 6 | # 7 | # libpulp is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU Lesser General Public 9 | # License as published by the Free Software Foundation; either 10 | # version 2.1 of the License, or (at your option) any later version. 11 | # 12 | # libpulp is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # Lesser General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with libpulp. If not, see . 19 | 20 | ACLOCAL_AMFLAGS = -I config 21 | 22 | SUBDIRS = include common lib man tools tests docs scripts 23 | 24 | EXTRA_DIST = LICENSE README.md 25 | -------------------------------------------------------------------------------- /bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #Colors for colored print messages. 4 | RED='\033[0;31m' 5 | RESET='\033[0m' 6 | 7 | 8 | # Abort program with message. 9 | abort() 10 | { 11 | echo -e "${RED}ERROR: $@${RESET}" 12 | exit 1 13 | } 14 | 15 | 16 | # Check the folowing commands is available to this shell. 17 | check_existence() 18 | { 19 | local tool_available 20 | local tools='libtoolize aclocal autoheader automake autoconf' 21 | 22 | for tool in $tools; do 23 | $tool --version > /dev/null 24 | tool_available=$? 25 | 26 | if [ $tool_available -ne 0 ]; then 27 | abort "$tool not found, but is required by bootstrap" 28 | fi 29 | done 30 | } 31 | 32 | # Check existence of commands. On failure, user must install the missing 33 | # packages. 34 | check_existence 35 | 36 | # Run the bootstrap process 37 | libtoolize -c 38 | aclocal 39 | autoheader 40 | automake --add-missing -c 41 | autoconf 42 | -------------------------------------------------------------------------------- /common/Makefile.am: -------------------------------------------------------------------------------- 1 | # libpulp - User-space Livepatching Library 2 | # 3 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 4 | # 5 | # This file is part of libpulp. 6 | # 7 | # libpulp is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU Lesser General Public 9 | # License as published by the Free Software Foundation; either 10 | # version 2.1 of the License, or (at your option) any later version. 11 | # 12 | # libpulp is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # Lesser General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with libpulp. If not, see . 19 | 20 | # Static library shared among the tools. 21 | noinst_LTLIBRARIES = libcommon.la 22 | 23 | # Ensure access to the include directory 24 | AM_CFLAGS += -I$(abs_top_srcdir)/include 25 | 26 | # Add -fno-strict-alias to the insn_queue code. 27 | insn_queue.lo : CFLAGS += -fno-strict-aliasing 28 | 29 | libcommon_la_SOURCES = common.c insn_queue.c 30 | -------------------------------------------------------------------------------- /config/.gitignore: -------------------------------------------------------------------------------- 1 | compile 2 | config.guess 3 | config.sub 4 | depcomp 5 | install-sh 6 | libtool.m4 7 | ltmain.sh 8 | lt~obsolete.m4 9 | ltoptions.m4 10 | ltsugar.m4 11 | ltversion.m4 12 | missing 13 | test-driver 14 | -------------------------------------------------------------------------------- /docs/Makefile.am: -------------------------------------------------------------------------------- 1 | if HAVE_DOXYGEN 2 | directory = $(top_srcdir)/docs/man/man3 3 | 4 | man_MANS = $(directory) 5 | 6 | $(directory): doxyfile.stamp 7 | 8 | doxyfile.stamp: Doxyfile 9 | $(DOXYGEN) $^ 10 | if HAVE_PDFLATEX 11 | cd latex && $(MAKE) 12 | endif 13 | echo Timestamp > $@ 14 | 15 | CLEANFILES = doxyfile.stamp 16 | 17 | all-local: doxyfile.stamp 18 | clean-local: 19 | rm -rf $(top_builddir)/docs/man 20 | 21 | endif 22 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Userspace Livepatch Examples. 2 | 3 | This folder contain livepatching examples. Once you compile the example hitting 4 | `make`, it will generate two files: 5 | 6 | 1. `test` 7 | 2. `a_livepatch1.so` 8 | 9 | The first file is a binary and should be run with `libpulp.so` loaded. Assuming 10 | libpulp is installed in `/usr/local/lib64/libpulp.so.0`, that is: 11 | ``` 12 | $ LD_PRELOAD=/usr/local/lib64/libpulp.so.0 ./test 13 | ``` 14 | 15 | The second file is the livepatch and should be applied with the `ulp` tool by 16 | running: 17 | ``` 18 | $ ulp trigger a_livepatch.so 19 | ``` 20 | 21 | Have fun and happy livepatching! 22 | -------------------------------------------------------------------------------- /examples/cplusplus/1-class/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS=-O2 -fpatchable-function-entry=16,14 -fPIC -g3 3 | ULP=$(shell which ulp 2>/dev/null) 4 | LDFLAGS= 5 | 6 | ifeq ($(ULP),) 7 | $(error Not found ulp, please make install first) 8 | endif 9 | 10 | all: test a_livepatch1.so 11 | 12 | test: class.o 13 | $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) 14 | 15 | %.so: %.o %.dsc 16 | $(CXX) $(CXXFLAGS) -shared -o $@ $< 17 | $(ULP) packer $(word 2, $^) 18 | 19 | %.o: %.cpp 20 | $(CXX) $(CXXFLAGS) -c $^ -o $@ 21 | 22 | clean: 23 | rm -f test *.o *.so 24 | 25 | clena: clean 26 | -------------------------------------------------------------------------------- /examples/cplusplus/1-class/README.md: -------------------------------------------------------------------------------- 1 | # Example: Live Patching a C++ ordinary class 2 | ## About 3 | In this test we have two files: `class.cpp` and `a_livepatch1.cpp`. The first 4 | one contain code in C++ for a test program which print the contents of a 5 | `point` class, where the second one contains a livepatch that modifies the 6 | `Print` method so it prints content differently. 7 | 8 | ## Live Patching C++ methods 9 | C++ methods can be live patched the same way as C functions. However, for 10 | libpulp to find the symbols in the original target binary, you should write 11 | the mangled name instead of the C++ original name of the method. 12 | 13 | So instead of writing `Point3D::Print`, one should write `_ZN7Point3D5PrintEv`. 14 | The original declaration of the class should be copied as well (see 15 | `a_livepatch1.cpp` and `a_livepatch1.dsc`). 16 | -------------------------------------------------------------------------------- /examples/cplusplus/1-class/a_livepatch1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Point 4 | { 5 | protected: 6 | int x, y; 7 | 8 | public: 9 | Point(int x, int y); 10 | 11 | int Get_X(void) const; 12 | int Get_Y(void) const; 13 | 14 | void Print_LP(void); 15 | }; 16 | 17 | class Point3D : public Point 18 | { 19 | protected: 20 | int z; 21 | 22 | public: 23 | Point3D(int x, int y, int z); 24 | 25 | int Get_Z(void) const; 26 | 27 | void Print_LP(void); 28 | }; 29 | 30 | void Point::Print_LP(void) 31 | { 32 | std::cout << x + 1 << ' ' << y + 1 << '\n'; 33 | } 34 | 35 | void Point3D::Print_LP(void) 36 | { 37 | std::cout << x + 1 << ' ' << y + 1 << ' ' << z << '\n'; 38 | } 39 | -------------------------------------------------------------------------------- /examples/cplusplus/1-class/a_livepatch1.dsc: -------------------------------------------------------------------------------- 1 | a_livepatch1.so 2 | @./test 3 | _ZN7Point3D5PrintEv:_ZN7Point3D8Print_LPEv 4 | -------------------------------------------------------------------------------- /examples/cplusplus/1-class/class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Point 5 | { 6 | protected: 7 | int x, y; 8 | 9 | public: 10 | Point(int x, int y); 11 | 12 | int Get_X(void) const; 13 | int Get_Y(void) const; 14 | 15 | void Print(void); 16 | }; 17 | 18 | class Point3D : public Point 19 | { 20 | protected: 21 | int z; 22 | 23 | public: 24 | Point3D(int x, int y, int z); 25 | 26 | int Get_Z(void) const; 27 | 28 | void Print(void); 29 | }; 30 | 31 | int Point::Get_X(void) const 32 | { 33 | return x; 34 | } 35 | 36 | int Point::Get_Y(void) const 37 | { 38 | return y; 39 | } 40 | 41 | // Will be livepatched 42 | void Point::Print(void) 43 | { 44 | std::cout << Get_X() << ' ' << Get_Y() << '\n'; 45 | } 46 | 47 | Point::Point(int x, int y) 48 | { 49 | this->x = x; 50 | this->y = y; 51 | } 52 | 53 | Point3D::Point3D(int x, int y, int z) : Point(x, y) 54 | { 55 | this->z = z; 56 | } 57 | 58 | int Point3D::Get_Z(void) const 59 | { 60 | return z; 61 | } 62 | 63 | // Will be livepatched 64 | void Point3D::Print(void) 65 | { 66 | std::cout << Get_X() << ' ' << Get_Y() << ' ' << Get_Z() << '\n'; 67 | } 68 | 69 | int main(void) 70 | { 71 | Point3D p(3, 4, 5); 72 | while (1) { 73 | p.Print(); 74 | sleep(1); 75 | } 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /examples/cplusplus/2-private_class/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS=-O2 -fpatchable-function-entry=16,14 -fdump-ipa-clones -fPIC -g3 3 | ULP=$(shell which ulp 2>/dev/null) 4 | LDFLAGS= 5 | 6 | ifeq ($(ULP),) 7 | $(error Not found ulp, please make install first) 8 | endif 9 | 10 | all: test a_livepatch1.so 11 | 12 | test: class.o 13 | $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) 14 | 15 | %.so: %.o %.dsc 16 | $(CXX) $(CXXFLAGS) -shared -o $@ $< 17 | $(ULP) packer $(word 2, $^) 18 | 19 | %.o: %.cpp 20 | $(CXX) $(CXXFLAGS) -c $^ -o $@ 21 | 22 | clean: 23 | rm -f test *.o *.so *.ipa-clones 24 | 25 | clena: clean 26 | -------------------------------------------------------------------------------- /examples/cplusplus/2-private_class/a_livepatch1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef double vec3_t[3]; 4 | 5 | double norm3_lp(vec3_t v) 6 | { 7 | return cbrt(v[0]*v[0]*v[0] + v[1]*v[1]*v[1] + v[2]*v[2]*v[2]); 8 | } 9 | -------------------------------------------------------------------------------- /examples/cplusplus/2-private_class/a_livepatch1.dsc: -------------------------------------------------------------------------------- 1 | a_livepatch1.so 2 | @./test 3 | _ZL4normPd:_Z8norm3_lpPd:40122e 4 | -------------------------------------------------------------------------------- /examples/cplusplus/2-private_class/class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef double vec3_t[3]; 6 | #define noinline __attribute__((noinline)) 7 | 8 | static double dot(vec3_t u, vec3_t v) 9 | { 10 | return u[0]*v[0] + u[1]*v[1] + u[2]*v[2]; 11 | } 12 | 13 | // Will be livepatched. 14 | static noinline double norm(vec3_t v) 15 | { 16 | return sqrt(dot(v, v)); 17 | } 18 | 19 | class Point 20 | { 21 | protected: 22 | double x, y; 23 | 24 | public: 25 | Point(double x, double y); 26 | 27 | double Get_X(void) const; 28 | double Get_Y(void) const; 29 | }; 30 | 31 | class Point3D : public Point 32 | { 33 | protected: 34 | double z; 35 | 36 | public: 37 | Point3D(double x, double y, double z); 38 | double Norm(void); 39 | 40 | double Get_Z(void) const; 41 | 42 | }; 43 | 44 | double Point::Get_X(void) const 45 | { 46 | return x; 47 | } 48 | 49 | double Point::Get_Y(void) const 50 | { 51 | return y; 52 | } 53 | 54 | Point::Point(double x, double y) 55 | { 56 | this->x = x; 57 | this->y = y; 58 | } 59 | 60 | Point3D::Point3D(double x, double y, double z) : Point(x, y) 61 | { 62 | this->z = z; 63 | } 64 | 65 | double Point3D::Get_Z(void) const 66 | { 67 | return z; 68 | } 69 | 70 | double Point3D::Norm(void) 71 | { 72 | vec3_t v = {x, y, z}; 73 | return norm(v); 74 | } 75 | 76 | extern "C" double some_function(vec3_t v) 77 | { 78 | return norm(v) * norm(v); 79 | } 80 | 81 | int main(void) 82 | { 83 | Point3D p(3, 4, 5); 84 | while (1) { 85 | std::cout << p.Norm() << '\n'; 86 | sleep(1); 87 | } 88 | 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /examples/cplusplus/3-indirect_call/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS=-O2 -fpatchable-function-entry=16,14 -fdump-ipa-clones -fPIC -g3 3 | ULP=$(shell which ulp 2>/dev/null) 4 | LDFLAGS= 5 | 6 | ifeq ($(ULP),) 7 | $(error Not found ulp, please make install first) 8 | endif 9 | 10 | all: test a_livepatch1.so 11 | 12 | test: class.o 13 | $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) 14 | 15 | %.so: %.o %.dsc 16 | $(CXX) $(CXXFLAGS) -shared -o $@ $< 17 | $(ULP) packer $(word 2, $^) 18 | 19 | %.o: %.cpp 20 | $(CXX) $(CXXFLAGS) -c $^ -o $@ 21 | 22 | clean: 23 | rm -f test *.o *.so *.ipa-clones 24 | 25 | clena: clean 26 | -------------------------------------------------------------------------------- /examples/cplusplus/3-indirect_call/README.md: -------------------------------------------------------------------------------- 1 | # Example: Calling private non-inlined non-externalized function available in original binary 2 | ## About 3 | This example illustrates how we can use code that is already available in the 4 | original library. For this to work correctly, the function or method should not 5 | have been inlined, so it is callable. 6 | 7 | ## The example 8 | 9 | In this example we have two files: `class.cpp` and `a_livepatch1.cpp`. The 10 | first file contains code to calculate the norm of a 2D point and print its 11 | results. In the second file it contains a livepatch to replace the 2-norm 12 | with a 3-Norm. The print call goes untouched, and since it is not inlined, 13 | the original method can be called without problems. 14 | 15 | ## Live Patching 16 | 17 | This example is crafted so that the method `Print` is not inlined into `Norm`, 18 | as can be seen by the `noinline` declaration of it. 19 | 20 | ### Reference to non-externalized symbol 21 | 22 | Since the symbol is not externalized, we have to get the reference to the 23 | target function manually instead of relying on `ld` to find it to us. 24 | 25 | For us to be able to call this method, we must declare a pointer to a method 26 | and call it. This pointer will be filled by libpulp with the address of the 27 | desired method we want to call. 28 | 29 | In `a_livepatch.cpp`: 30 | ``` 31 | extern "C" { 32 | double (Point::*Print_LP)(double) = nullptr; 33 | } 34 | ``` 35 | 36 | Then on `a_livepatch.dsc`: 37 | ``` 38 | #_ZN5Point5PrintEd:Print_LP 39 | ``` 40 | 41 | The `#` token will describe that `Print_LP` should be initialized with the 42 | *address* of Point::Print. In case the debug symbols are not available in 43 | the binary, the offset of the symbol can be specified as: 44 | ``` 45 | #_ZN5Point5PrintEd:Print_LP:4011fe 46 | ``` 47 | -------------------------------------------------------------------------------- /examples/cplusplus/3-indirect_call/a_livepatch1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Point 4 | { 5 | private: 6 | void Print(double n); 7 | 8 | protected: 9 | double x, y; 10 | 11 | public: 12 | Point(double x, double y); 13 | double Norm_LP(void); 14 | }; 15 | 16 | /** This global variable will contain the address of Point::Print once the 17 | livepatch is installed. */ 18 | extern "C" { 19 | double (Point::*Print_LP)(double) = nullptr; 20 | } 21 | 22 | 23 | double Point::Norm_LP(void) 24 | { 25 | double n = cbrt(x*x*x + y*y*y); 26 | 27 | /** Since we declare it as a function, we must explicitely pass the 'this' 28 | pointer. */ 29 | (this->*Print_LP)(n); 30 | return n; 31 | } 32 | -------------------------------------------------------------------------------- /examples/cplusplus/3-indirect_call/a_livepatch1.dsc: -------------------------------------------------------------------------------- 1 | a_livepatch1.so 2 | @./test 3 | _ZN5Point4NormEv:_ZN5Point7Norm_LPEv 4 | #_ZN5Point5PrintEd:Print_LP 5 | -------------------------------------------------------------------------------- /examples/cplusplus/3-indirect_call/class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define noinline __attribute__((noinline)) 6 | 7 | class Point 8 | { 9 | private: 10 | void noinline Print(double n); 11 | 12 | protected: 13 | double x, y; 14 | 15 | public: 16 | Point(double x, double y); 17 | double Norm(void); 18 | }; 19 | 20 | Point::Point(double x, double y) 21 | { 22 | this->x = x; 23 | this->y = y; 24 | } 25 | 26 | // Will be livepatched; 27 | double Point::Norm(void) 28 | { 29 | double n = sqrt(x*x + y*y); 30 | Print(n); 31 | return n; 32 | } 33 | 34 | void noinline Point::Print(double n) 35 | { 36 | std::cout << "Point: " << x << ' ' << y << ' ' << "Have norm2 = " << n <<'\n'; 37 | } 38 | 39 | int main(void) 40 | { 41 | Point p(3, 4); 42 | while (1) { 43 | p.Norm(); 44 | sleep(1); 45 | } 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /examples/cplusplus/4-global_var/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS=-O2 -fpatchable-function-entry=16,14 -fdump-ipa-clones -fPIC -g3 3 | ULP=$(shell which ulp 2>/dev/null) 4 | LDFLAGS= 5 | 6 | ifeq ($(ULP),) 7 | $(error Not found ulp, please make install first) 8 | endif 9 | 10 | all: test a_livepatch1.so 11 | 12 | test: test.o 13 | $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) 14 | 15 | %.so: %.o %.dsc 16 | $(CXX) $(CXXFLAGS) -shared -o $@ $< 17 | $(ULP) packer $(word 2, $^) 18 | 19 | %.o: %.cpp 20 | $(CXX) $(CXXFLAGS) -c $^ -o $@ 21 | 22 | clean: 23 | rm -f test *.o *.so *.ipa-clones 24 | 25 | clena: clean 26 | -------------------------------------------------------------------------------- /examples/cplusplus/4-global_var/README.md: -------------------------------------------------------------------------------- 1 | # Example: Calling private non-inlined non-externalized function available in original binary 2 | ## About 3 | 4 | This example illustrates how we can access global variables -- private or 5 | public -- as it may be necessary to create a livepatch. One case where such cases 6 | may happen is to access global locks, as shown in this example. 7 | 8 | In `test.cpp`, there is an accumulator that is protected by a mutex lock. A 9 | livepatch that touches this critical section will have to lock it before doing 10 | any modifications to the `sum` variable. 11 | 12 | ## The example 13 | 14 | In this example we have two files: `test.cpp` and `a_livepatch1.cpp`. The 15 | first file contains code to accumulate into a variable using multiple 16 | threads. The second file contains a patch that set that variable to 0. 17 | 18 | ## Live Patching 19 | 20 | In order to create this livepatch, we have to setup references to the global 21 | variables that needs to be modified. On `a_livepatch.cpp`: 22 | ``` 23 | volatile long *sum_ptr = NULL; 24 | pthread_mutex_t *sum_lock_ptr = NULL; 25 | ``` 26 | Then on .dsc: 27 | ``` 28 | #sum:sum_ptr 29 | #sum_lock:sum_lock_ptr 30 | ``` 31 | 32 | with this, the pointers `sum_ptr` and `sum_lock_ptr` will be initialized with 33 | the address of `sum` and `sum_lock`. 34 | -------------------------------------------------------------------------------- /examples/cplusplus/4-global_var/a_livepatch1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* Pointer to the original sum variable. This will be initialized with the 8 | address of `sum` when the patch is loaded in the program, as described in 9 | the .dsc file. */ 10 | volatile long *sum_ptr = NULL; 11 | 12 | /* Pointer to the original lock. */ 13 | pthread_mutex_t *sum_lock_ptr = NULL; 14 | 15 | void accumulate_2(long x __attribute__((unused))) 16 | { 17 | assert(sum_ptr && sum_lock_ptr); 18 | 19 | if (pthread_mutex_lock(sum_lock_ptr) != 0) { 20 | abort(); 21 | } 22 | 23 | *sum_ptr = 0; 24 | 25 | if (pthread_mutex_unlock(sum_lock_ptr) != 0) { 26 | abort(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/cplusplus/4-global_var/a_livepatch1.dsc: -------------------------------------------------------------------------------- 1 | a_livepatch1.so 2 | @./test 3 | _Z10accumulatel:_Z12accumulate_2l 4 | #sum:sum_ptr 5 | #sum_lock:sum_lock_ptr 6 | -------------------------------------------------------------------------------- /examples/cplusplus/4-global_var/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define noinline __attribute__((noinline)) 6 | #define NUM_ACCUMULATORS 4 7 | 8 | volatile long sum; 9 | pthread_mutex_t sum_lock = PTHREAD_MUTEX_INITIALIZER; 10 | 11 | /* Accumulate into a global variable. */ 12 | // Will be livepatched; 13 | void noinline accumulate(long x) 14 | { 15 | if (pthread_mutex_lock(&sum_lock) != 0) { 16 | abort(); 17 | } 18 | 19 | sum += x; 20 | 21 | if (pthread_mutex_unlock(&sum_lock) != 0) { 22 | abort(); 23 | } 24 | } 25 | 26 | void *accumulator(void* x) 27 | { 28 | for (long i = 0; i < 100000000L; i++) { 29 | accumulate(i); 30 | } 31 | 32 | return NULL; 33 | } 34 | 35 | int main(void) 36 | { 37 | pthread_t threads[NUM_ACCUMULATORS]; 38 | 39 | for (int i = 0; i < NUM_ACCUMULATORS; i++) { 40 | if (pthread_create(&threads[i], NULL, accumulator, NULL) != 0) { 41 | abort(); 42 | } 43 | } 44 | 45 | for (int i = 0; i < NUM_ACCUMULATORS; i++) { 46 | if (pthread_join(threads[i], NULL) != 0) { 47 | abort(); 48 | } 49 | } 50 | 51 | printf("sum = %ld\n", sum); 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /examples/cplusplus/5-queue/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS=-fpatchable-function-entry=16,14 -fdump-ipa-clones -fPIC -g3 -Wno-terminate -O2 3 | ULP=$(shell which ulp 2>/dev/null) 4 | LDFLAGS= 5 | 6 | ifeq ($(ULP),) 7 | $(error Not found ulp, please make install first) 8 | endif 9 | 10 | all: test a_livepatch1.so 11 | 12 | test: class.o 13 | $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) 14 | 15 | %.so: %.o %.dsc 16 | $(CXX) $(CXXFLAGS) -shared -o $@ $< 17 | $(ULP) packer $(word 2, $^) 18 | 19 | %.o: %.cpp 20 | $(CXX) $(CXXFLAGS) -c $^ -o $@ 21 | 22 | clean: 23 | rm -f test *.o *.so *.ipa-clones 24 | 25 | clena: clean 26 | -------------------------------------------------------------------------------- /examples/cplusplus/5-queue/README.md: -------------------------------------------------------------------------------- 1 | # Example: Live patching template methods 2 | ## About 3 | 4 | This example illustrates how we can livepatch template methods in C++. 5 | 6 | ### C++ templates 7 | 8 | C++ has the ability to generate code according to given parameters by using 9 | `templates`. This is more powerful than C macros and it is very useful to 10 | generate classes or functions for multiple types or multiple predetermined 11 | bounds. 12 | 13 | ## The example 14 | 15 | In this example we have two files: `class.cpp` and `a_livepatch1.cpp`. The 16 | first file contains a template class `Queue` which generates code for each 17 | type and maximum bound. Here we only use the case where MAX = 32 and types 18 | as `long` and `double`. In the second file we have a livepatch which modifies 19 | the code of `Push` to print a message for each type it runs. 20 | 21 | Since the `Queue` is used with two types (`long` and `double`), we have to 22 | generate two functions in the livepatch library. This is shown by the 23 | declarations: 24 | ``` 25 | /* Output the modified functions for all types generated. */ 26 | template void Queue::Push_LP(long x); 27 | template void Queue::Push_LP(double x); 28 | ``` 29 | 30 | which will generate two functions `_ZN5QueueILi32ElE7Push_LPEl` and 31 | `_ZN5QueueILi32EdE7Push_LPEd`. 32 | 33 | ## Live Patching 34 | 35 | Unfortunately since C++ `template` functions are generating according to each 36 | one of the template parameters that are given, you must generate one function 37 | for each one parameter that are used in the program. On our example it is easy, 38 | as the project has one file, the template is expanded to only two types, and 39 | functions are not inlined. 40 | -------------------------------------------------------------------------------- /examples/cplusplus/5-queue/a_livepatch1.dsc: -------------------------------------------------------------------------------- 1 | a_livepatch1.so 2 | @./test 3 | _ZN5QueueILi32ElE4PushEl:_ZN5QueueILi32ElE7Push_LPEl 4 | _ZN5QueueILi32EdE4PushEd:_ZN5QueueILi32EdE7Push_LPEd 5 | -------------------------------------------------------------------------------- /include/.gitignore: -------------------------------------------------------------------------------- 1 | config.h.in 2 | -------------------------------------------------------------------------------- /include/Makefile.am: -------------------------------------------------------------------------------- 1 | # libpulp - User-space Livepatching Library 2 | # 3 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 4 | # 5 | # This file is part of libpulp. 6 | # 7 | # libpulp is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU Lesser General Public 9 | # License as published by the Free Software Foundation; either 10 | # version 2.1 of the License, or (at your option) any later version. 11 | # 12 | # libpulp is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # Lesser General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with libpulp. If not, see . 19 | 20 | noinst_HEADERS = \ 21 | ulp.h \ 22 | ulp_common.h \ 23 | interpose.h \ 24 | msg_queue.h \ 25 | error.h \ 26 | error_common.h \ 27 | terminal_colors.h \ 28 | ld_rtld.h \ 29 | insn_queue.h \ 30 | insn_queue_lib.h \ 31 | minielf.h 32 | 33 | # Workaround a bug in Autoconf 2.69 34 | if CPU_X86_64 35 | noinst_HEADERS += \ 36 | arch/x86_64/arch_common.h 37 | endif 38 | 39 | if CPU_PPC64LE 40 | noinst_HEADERS += \ 41 | arch/powerpc64le/arch_common.h 42 | endif 43 | -------------------------------------------------------------------------------- /include/arch/x86_64/arch_common.h: -------------------------------------------------------------------------------- 1 | #ifndef _ARCH_X86_64_H 2 | #define _ARCH_X86_64_H 3 | 4 | /** Intel endbr64 instruction optcode. */ 5 | #define INSN_ENDBR64 0xf3, 0x0f, 0x1e, 0xfa 6 | 7 | /** Offset of TLS pointer. */ 8 | #define TLS_DTV_OFFSET 0 9 | 10 | /** Struct used to store the registers in memory. */ 11 | typedef struct user_regs_struct registers_t; 12 | 13 | /** Register in which the function stores the return value. */ 14 | #define FUNCTION_RETURN_REG(reg) ((reg).rax) 15 | 16 | /** Register which acts as a program counter. */ 17 | #define PROGRAM_COUNTER_REG(reg) ((reg).rip) 18 | 19 | /** Register which acts as top of stack. */ 20 | #define STACK_TOP_REG(reg) ((reg).rsp) 21 | 22 | /** Set the GLOBAL ENTRYPOINT REGISTER, which in x86_64 doesn't exist. */ 23 | #define SET_GLOBAL_ENTRYPOINT_REG(reg, val) 24 | 25 | /** The red zone. */ 26 | #define RED_ZONE_LEN 128 27 | 28 | /** 29 | * Number of bytes that the kernel subtracts from the program counter, 30 | * when an ongoing syscall gets interrupted and must be restarted. 31 | */ 32 | #define RESTART_SYSCALL_SIZE 2 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/insn_queue_lib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2023 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #ifndef INSNQ_TOOL_H 23 | #define INSNQ_TOOL_H 24 | 25 | #include "insn_queue.h" 26 | 27 | void *insnq_get_writable_area(insn_queue_t *, size_t insn_size); 28 | 29 | ulp_error_t insnq_insert_print(const char *string); 30 | 31 | ulp_error_t insnq_insert_write(void *addr, int n, const void *bytes); 32 | 33 | int insnq_ensure_emptiness(void); 34 | 35 | /* Not necessary if compiling without gdb interface. */ 36 | #ifdef ENABLE_GDB_INTERFACE 37 | 38 | /** Interpret the global instruction queue from process side. */ 39 | int insnq_interpret_from_lib(void); 40 | 41 | #endif //ENABLE_GDB_INTERFACE 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /include/interpose.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | int __ulp_asunsafe_trylock(void); 23 | int __ulp_asunsafe_unlock(void); 24 | 25 | void *get_loaded_symbol_addr(const char *, const char *, void *); 26 | 27 | void *get_loaded_library_base_addr(const char *); 28 | 29 | int get_loaded_library_tls_index(const char *); 30 | -------------------------------------------------------------------------------- /include/terminal_colors.h: -------------------------------------------------------------------------------- 1 | #ifndef _TERMINAL_COLORS_H 2 | #define _TERMINAL_COLORS_H 3 | 4 | #define TERM_COLOR_RED "\x1b[31;1m" 5 | #define TERM_COLOR_GREEN "\x1b[32;1m" 6 | #define TERM_COLOR_YELLOW "\x1b[33;1m" 7 | #define TERM_COLOR_BLUE "\x1b[34;1m" 8 | #define TERM_COLOR_MAGENTA "\x1b[35;1m" 9 | #define TERM_COLOR_CYAN "\x1b[36;1m" 10 | #define TERM_COLOR_WHITE "\x1b[37;1m" 11 | #define TERM_COLOR_BOLD "\x1b[;1m" 12 | #define TERM_COLOR_RESET "\x1b[0m" 13 | 14 | void change_color(const char *ansi_escape); 15 | 16 | #endif //_TERMINAL_COLORS_H 17 | -------------------------------------------------------------------------------- /lib/libpulp.versions: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | /* Interposed from libc and libdl. */ 4 | free; 5 | malloc; 6 | calloc; 7 | realloc; 8 | reallocarray; 9 | valloc; 10 | pvalloc; 11 | memalign; 12 | aligned_alloc; 13 | posix_memalign; 14 | dlopen; 15 | dlmopen; 16 | dlclose; 17 | dladdr; 18 | dladdr1; 19 | dlinfo; 20 | __ulp_revert_all; 21 | __ulp_trigger; 22 | __ulp_check_patched; 23 | __ulp_state; 24 | __ulp_get_global_universe; 25 | __ulp_msg_queue; 26 | __ulp_metadata_buffer; 27 | __ulp_error_state; 28 | __ulp_enable_or_disable_patching; 29 | __ulp_insn_queue; 30 | __ulp_version; 31 | gdb_ulp_apply; 32 | gdb_ulp_revert; 33 | local: 34 | *; 35 | }; 36 | -------------------------------------------------------------------------------- /man/Makefile.am: -------------------------------------------------------------------------------- 1 | dist_man1_MANS = \ 2 | ulp.1 3 | 4 | dist_man7_MANS = \ 5 | libpulp.7 6 | -------------------------------------------------------------------------------- /patches/gcc/fix-pfe-section-flags.diff: -------------------------------------------------------------------------------- 1 | commit 33011f30120f958b14d8036a38ca27c7456b8244 2 | Author: Joao Moreira 3 | Date: Fri Apr 5 00:47:26 2019 -0300 4 | 5 | Fix gcc section _fpatchable_function_entry flags 6 | 7 | diff --git a/libpulp-0.1/gcc/gcc/targhooks.c b/libpulp-0.1/gcc/gcc/targhooks.c 8 | index 138f8d7..9fbaa25 100644 9 | --- a/libpulp-0.1/gcc/gcc/targhooks.c 10 | +++ b/libpulp-0.1/gcc/gcc/targhooks.c 11 | @@ -1814,7 +1814,7 @@ default_print_patchable_function_entry (FILE *file, 12 | ASM_GENERATE_INTERNAL_LABEL (buf, "LPFE", patch_area_number); 13 | 14 | switch_to_section (get_section ("__patchable_function_entries", 15 | - SECTION_RELRO , NULL)); 16 | + SECTION_WRITE | SECTION_RELRO , NULL)); 17 | fputs (asm_op, file); 18 | assemble_name_raw (file, buf); 19 | fputc ('\n', file); 20 | -------------------------------------------------------------------------------- /scripts/Makefile.am: -------------------------------------------------------------------------------- 1 | # libpulp - User-space Livepatching Library 2 | # 3 | # Copyright (C) 2020-2023 SUSE Software Solutions GmbH 4 | # 5 | # This file is part of libpulp. 6 | # 7 | # libpulp is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU Lesser General Public 9 | # License as published by the Free Software Foundation; either 10 | # version 2.1 of the License, or (at your option) any later version. 11 | # 12 | # libpulp is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # Lesser General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with libpulp. If not, see . 19 | 20 | dist_bin_SCRIPTS=setup_package.sh 21 | -------------------------------------------------------------------------------- /scripts/collect.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Look for the number of symbols and how many symbols will need to be read to 4 | # decide if a library is livepatchable or not in /usr/lib64 to collect 5 | # statistics. 6 | 7 | get_first_function_symbol() 8 | { 9 | local realfile=$(readlink -f $1) 10 | local symbol=$(readelf -D -sW $realfile | grep -E "FUNC[ ]*GLOBAL[ ]*DEFAULT[ ]*[0-9]+" | head -n 1 | awk '{ print substr($1, 1, length($1)-1) }') 11 | local num_symbols=$(readelf -D -sW $realfile | tail -n 1 | awk '{ print substr($1, 1, length($1)-1) }') 12 | 13 | echo "Analyzing $realfile" 14 | echo "$realfile, $symbol", $num_symbols >> output.csv 15 | } 16 | 17 | rm -f output.csv 18 | for so in $(find "/usr/lib64/" -name "*.so"); do 19 | get_first_function_symbol $so 20 | done 21 | 22 | sort -u output.csv -o output.csv 23 | -------------------------------------------------------------------------------- /tests/access.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | int 29 | main(void) 30 | { 31 | char buffer[128]; 32 | 33 | /* Original banner. */ 34 | printf("Banner addr: 0x%lX\n", (unsigned long)banner_get()); 35 | printf("%s\n", banner_get()); 36 | 37 | /* Use original banner setting function. */ 38 | banner_set(strdup("Banner changed from main")); 39 | printf("%s\n", banner_get()); 40 | 41 | /* Wait for input. */ 42 | if (fgets(buffer, sizeof(buffer), stdin) == NULL) { 43 | if (errno) { 44 | perror("access"); 45 | return 1; 46 | } 47 | } 48 | 49 | /* 50 | * Use banner setting function again, which is supposed to have been 51 | * changed by the test driver. The patched function ignores the 52 | * argument, so 'String from main' should not be in the output. 53 | */ 54 | banner_set("String from main"); 55 | printf("%s\n", banner_get()); 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /tests/access.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn(testsuite.testname) 25 | 26 | child.expect('Original banner') 27 | child.expect('Banner changed from main') 28 | 29 | child.livepatch('.libs/libaccess_livepatch1.so') 30 | 31 | child.sendline('') 32 | child.expect('String from live patch', 33 | reject=['String from main', 34 | 'Live patch data references not initialized']) 35 | 36 | child.close(force=True) 37 | exit(0) 38 | -------------------------------------------------------------------------------- /tests/access2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | int 29 | main(void) 30 | { 31 | char buffer[128]; 32 | 33 | /* Original banner. */ 34 | printf("Banner addr: 0x%lX\n", (unsigned long)banner_get()); 35 | printf("%s\n", banner_get()); 36 | 37 | /* Use original banner setting function. */ 38 | banner_set(strdup("Banner changed from main")); 39 | printf("%s\n", banner_get()); 40 | 41 | /* Wait for input. */ 42 | if (fgets(buffer, sizeof(buffer), stdin) == NULL) { 43 | if (errno) { 44 | perror("access"); 45 | return 1; 46 | } 47 | } 48 | 49 | /* 50 | * Use banner setting function again, which is supposed to have been 51 | * changed by the test driver. The patched function ignores the 52 | * argument, so 'String from main' should not be in the output. 53 | */ 54 | banner_set("String from main"); 55 | printf("%s\n", banner_get()); 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /tests/access2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('access') 25 | 26 | child.expect('Original banner') 27 | child.expect('Banner changed from main') 28 | 29 | child.livepatch('.libs/libaccess_livepatch2.so') 30 | 31 | child.sendline('') 32 | child.expect('String from live patch', 33 | reject=['String from main', 34 | 'Live patch data references not initialized']) 35 | 36 | child.close(force=True) 37 | exit(0) 38 | -------------------------------------------------------------------------------- /tests/blocked.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import signal 23 | 24 | import testsuite 25 | 26 | child = testsuite.spawn('blocked') 27 | 28 | # Wait for both threads to be ready (the order does not matter) 29 | child.expect('Waiting for signals.') 30 | child.expect('Waiting for signals.') 31 | 32 | # At program start, two threads are put into loops waiting for signals, 33 | # thread1 waits for SIGUSR1 and thread2 waits for SIGUSR2. 34 | child.kill(signal.SIGUSR1) 35 | child.expect('hello') 36 | child.kill(signal.SIGUSR2) 37 | child.expect('hello') 38 | 39 | # After the live patching, thread1, which is looping outside the 40 | # library, should produce a different output, whereas thread2, which 41 | # never leaves the library, should display the old behavior. 42 | child.livepatch('.libs/libblocked_livepatch1.so') 43 | 44 | child.kill(signal.SIGUSR1) 45 | child.expect('olleh', reject='hello') 46 | child.kill(signal.SIGUSR2) 47 | child.expect('hello', reject='olleh') 48 | 49 | child.close(force=True) 50 | exit(0) 51 | -------------------------------------------------------------------------------- /tests/buildid.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* From libbuildid.c. */ 4 | int retval(void); 5 | 6 | int 7 | main() 8 | { 9 | while (1) { 10 | int ret; 11 | 12 | printf("Waiting for input.\n"); 13 | getchar(); 14 | 15 | ret = retval(); 16 | printf("%d\n", ret); 17 | } 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /tests/buildid.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | # Check the comments of `libbuildid_livepatch1.ulp` Makefile rule in 23 | # Makefile.am on this folder. 24 | # 25 | # This test should fail because of buildid mismatch. 26 | 27 | import testsuite 28 | import subprocess 29 | 30 | errorcode = 1 31 | 32 | child = testsuite.spawn('buildid') 33 | child.expect('Waiting for input.') 34 | 35 | child.sendline('') 36 | child.expect('1338'); 37 | 38 | out = child.livepatch('.libs/libbuildid_livepatch1.so', capture_tool_output=True) 39 | if out.find("buildid mismatch") == -1: 40 | errorcode = 1 41 | else: 42 | errorcode = 0 43 | 44 | child.close(force=True) 45 | exit(errorcode) 46 | -------------------------------------------------------------------------------- /tests/cancel.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('cancel') 25 | 26 | child.expect('OK') 27 | 28 | child.close(force=True) 29 | exit(0) 30 | -------------------------------------------------------------------------------- /tests/chroot.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "libparameters.h" 6 | 7 | int 8 | main(void) 9 | { 10 | char buffer[128]; 11 | 12 | if (chroot("/proc")) { 13 | /* Permission error, skip the test. */ 14 | printf("chroot error\n"); 15 | return 77; 16 | } 17 | 18 | /* Loop waiting for any input. */ 19 | printf("Waiting for input.\n"); 20 | while (1) { 21 | if (fgets(buffer, sizeof(buffer), stdin) == NULL) { 22 | if (errno) { 23 | perror("chroot"); 24 | return 1; 25 | } 26 | printf("Reached the end of file; quitting.\n"); 27 | return 0; 28 | } 29 | int_params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 30 | float_params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 31 | } 32 | 33 | return 1; 34 | } 35 | -------------------------------------------------------------------------------- /tests/chroot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2023 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | import sys 24 | import os 25 | 26 | if os.geteuid() != 0: 27 | print("Test not running as root.", file=sys.stdout) 28 | exit(77) # Skip test 29 | 30 | child = testsuite.spawn('chroot') 31 | child.expect('Waiting for input.') 32 | 33 | child.sendline('') 34 | child.expect('1-2-3-4-5-6-7-8-9-10'); 35 | child.expect('1.0-2.0-3.0-4.0-5.0-6.0-7.0-8.0-9.0-10.0'); 36 | 37 | child.livepatch('.libs/libparameters_livepatch1.so') 38 | 39 | child.sendline('') 40 | child.expect('10-9-8-7-6-5-4-3-2-1', reject='1-2-3-4-5-6-7-8-9-10'); 41 | child.expect('10.0-9.0-8.0-7.0-6.0-5.0-4.0-3.0-2.0-1.0', 42 | reject='1.0-2.0-3.0-4.0-5.0-6.0-7.0-8.0-9.0-10.0'); 43 | 44 | child.close(force=True) 45 | exit(0) 46 | -------------------------------------------------------------------------------- /tests/comments.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define NOINLINE __attribute__((noinline)) 5 | 6 | int NOINLINE 7 | value() 8 | { 9 | /* Avoid interprocedural const-propagation on clang. */ 10 | volatile int x = 0; 11 | return x; 12 | } 13 | 14 | int 15 | main() 16 | { 17 | puts("Ready."); 18 | 19 | while (value() == 0) 20 | usleep(100); 21 | 22 | puts("Livepatched"); 23 | 24 | while (1) 25 | usleep(100); 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /tests/comments.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2022 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | error = 1 25 | 26 | child = testsuite.spawn('comments', script=False) 27 | 28 | child.expect('Ready.') 29 | child.livepatch('.libs/libcomments_livepatch1.so') 30 | child.expect('Livepatched'); 31 | 32 | try: 33 | msgs = child.get_patches() 34 | if msgs.find('bsc#1200316') != -1 and msgs.find('jsc#SLE-20049') != -1 and msgs.find('CVE-2021-3449') != -1: 35 | error = 0 36 | except: 37 | print("Bug labels not found.") 38 | error = 1 39 | 40 | child.close(force=True) 41 | exit(error) 42 | -------------------------------------------------------------------------------- /tests/constructor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | #include 25 | 26 | #include "constructor-template.c" 27 | 28 | int 29 | main(void) 30 | { 31 | void *data; 32 | 33 | data = malloc_wrapper(1); 34 | if (data == NULL) 35 | return 1; 36 | printf("OK\n"); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /tests/constructor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('constructor') 25 | 26 | # Simply check that the test program works correctly with malloc interposition. 27 | # See constructor.c for a lengthier explanation. 28 | child.expect('OK') 29 | 30 | child.close(force=True) 31 | exit(0) 32 | -------------------------------------------------------------------------------- /tests/contract.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | int 28 | main(void) 29 | { 30 | char buffer[128]; 31 | 32 | /* Signal readiness. */ 33 | printf("Waiting for input.\n"); 34 | 35 | /* Loop waiting for input and calling function(). */ 36 | while (1) { 37 | if (fgets(buffer, sizeof(buffer), stdin) == NULL) { 38 | if (errno) { 39 | perror("contract"); 40 | return 1; 41 | } 42 | printf("Reached the end of file; quitting.\n"); 43 | return 0; 44 | } 45 | fna(); 46 | fnb(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tests/contract.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('contract') 25 | 26 | child.expect('Waiting for input.') 27 | 28 | errors = 0 29 | child.sendline('') 30 | child.sendline('') 31 | child.expect('TYPE A data 128'); 32 | child.sendline('') 33 | child.expect('TYPE B data 256.000000'); 34 | 35 | # Send the test program into the library. 36 | child.sendline('') 37 | 38 | # Apply live patch while inside library 39 | child.livepatch('.libs/libcontract_livepatch1.so') 40 | 41 | # Let the process resume and check fna behavior 42 | child.sendline('') 43 | child.expect('TYPE A data 128', reject='Invalid type.') 44 | 45 | # Let the process resume and check fnb behavior 46 | child.sendline('') 47 | child.expect('TYPE B data 1024.000000', reject='Invalid type.') 48 | 49 | child.close(force=True) 50 | exit(errors) 51 | -------------------------------------------------------------------------------- /tests/dlsym_lock.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2022 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn("dlsym", timeout=10) 25 | 26 | child.expect('dl lock was acquired: 1', 27 | reject=["dl lock is nonsensical:", 28 | "symbol _rtld_global not found in ld-linux-x86_64.so"]) 29 | 30 | child.close(force=True) 31 | exit(0) 32 | -------------------------------------------------------------------------------- /tests/dozens.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | static int 23 | hidden_dozen(void) 24 | { 25 | /* Clang removes the symbol completely if it sees that it can inline the 26 | function, even with -fno-inline or __attribute__((noinline)). Even with 27 | the volatile, it generates a jump to symbol rather than a function, which 28 | means this function cannot be livepatched. However, the hidden.py test 29 | only check if this symbol is present in .symtab, so this is fine. */ 30 | volatile int x = 12; 31 | return x; 32 | } 33 | 34 | int 35 | dozen(void) 36 | { 37 | return hidden_dozen(); 38 | } 39 | -------------------------------------------------------------------------------- /tests/dozens.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | int dozen(void); 23 | -------------------------------------------------------------------------------- /tests/endbr64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | int 30 | main(void) 31 | { 32 | char input[64]; 33 | 34 | printf("Waiting for input.\n"); 35 | while (1) { 36 | if (scanf("%s", input) == EOF) { 37 | if (errno) { 38 | perror("numserv"); 39 | return 1; 40 | } 41 | printf("Reached the end of file; quitting.\n"); 42 | return 0; 43 | } 44 | if (strncmp(input, "dozen", strlen("dozen")) == 0) 45 | printf("%d\n", dozen()); 46 | if (strncmp(input, "hundred", strlen("hundred")) == 0) 47 | printf("%d\n", hundred()); 48 | if (strncmp(input, "quit", strlen("quit")) == 0) { 49 | printf("Quitting.\n"); 50 | return 0; 51 | } 52 | } 53 | 54 | return 1; 55 | } 56 | -------------------------------------------------------------------------------- /tests/endbr64.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | # 22 | # This test asserts that libpulp is capable of patching functions which 23 | # starts with endbr64 instruction on x86_64. 24 | 25 | import testsuite 26 | 27 | child = testsuite.spawn('endbr64') 28 | 29 | child.expect('Waiting for input.') 30 | 31 | child.sendline('hundred') 32 | child.expect('100') 33 | 34 | child.livepatch('.libs/libendbr64_livepatch1.so') 35 | 36 | child.sendline('hundred') 37 | child.expect('200', reject='100') 38 | 39 | child.livepatch('.libs/libendbr64_livepatch1.so', revert=True) 40 | 41 | child.sendline('hundred') 42 | child.expect('100', reject=['200', '300', '400']); 43 | 44 | child.close(force=True) 45 | exit(0) 46 | -------------------------------------------------------------------------------- /tests/exception_handling.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | int 28 | main(void) 29 | { 30 | try { 31 | outer(); 32 | } 33 | catch (std::runtime_error &e) { 34 | std::cout << "caught in main" << std::endl; 35 | } 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /tests/exception_handling.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('exception_handling') 25 | 26 | child.expect('caught in lib') 27 | child.expect('caught in main') 28 | 29 | child.close(force=True) 30 | exit(0) 31 | -------------------------------------------------------------------------------- /tests/fuz/1: -------------------------------------------------------------------------------- 1 | ulppacker-vlibdozens_livepatch1.dsc -------------------------------------------------------------------------------- /tests/fuz/2: -------------------------------------------------------------------------------- 1 | ulppacker -------------------------------------------------------------------------------- /tests/fuz/3: -------------------------------------------------------------------------------- 1 | ulptrigger-v-r2-pnumserv.libs/libhundreds_livepatch1.so -------------------------------------------------------------------------------- /tests/fuz/4: -------------------------------------------------------------------------------- 1 | ulptrigger-v-pnumserv.libs/*.so -------------------------------------------------------------------------------- /tests/fuz/5: -------------------------------------------------------------------------------- 1 | ulppost-v.libs/libdozens_livepatch1.so -------------------------------------------------------------------------------- /tests/fuz/6: -------------------------------------------------------------------------------- 1 | ulplivepatchable.libs/libdozens_livepatch1.so -------------------------------------------------------------------------------- /tests/fuz/7: -------------------------------------------------------------------------------- 1 | ulppatches -------------------------------------------------------------------------------- /tests/fuz/README.md: -------------------------------------------------------------------------------- 1 | This folder contains valid inputs for ulp tools, with PWD in test dir. 2 | Those files are used by AFL, a fuzzer which mutates the arguments input 3 | to the `ulp` program. 4 | 5 | Every parameter should be separated with NUL character in order to AFL 6 | correctly detects as being different arguments for argv. 7 | -------------------------------------------------------------------------------- /tests/glibc_private.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2025 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import re 23 | import testsuite 24 | import subprocess 25 | 26 | # Make sure libpulp is built without links to GLIBC_PRIVATE symbols. 27 | 28 | command = ['readelf', '-sW', testsuite.libpulp_path] 29 | try: 30 | output = subprocess.check_output(command, timeout=10, stderr=subprocess.STDOUT) 31 | priv = re.search('GLIBC_PRIVATE', output.decode()) 32 | if not priv: 33 | exit(0) 34 | 35 | except subprocess.TimeoutExpired: 36 | print('readelf timeout') 37 | exit(77) 38 | 39 | exit(1) 40 | -------------------------------------------------------------------------------- /tests/group_disable.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2023 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import re 23 | import testsuite 24 | import os 25 | 26 | env = { 'LD_PRELOAD': '../lib/.libs/libpulp.so', 27 | 'LIBPULP_DISABLE_ON_GROUPS': str(os.getgid()) } 28 | 29 | child = testsuite.spawn('numserv', env=env) 30 | 31 | child.expect('Waiting for input.') 32 | 33 | child.sendline('dozen') 34 | child.expect('12'); 35 | 36 | child.sendline('hundred') 37 | child.expect('100'); 38 | 39 | child.livepatch('.libs/libdozens_livepatch1.so', sanity=False) 40 | 41 | child.sendline('dozen') 42 | child.expect('12', reject='13'); 43 | 44 | child.close(force=True) 45 | exit(0) 46 | -------------------------------------------------------------------------------- /tests/hidden.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('numserv') 25 | 26 | child.expect('Waiting for input.') 27 | 28 | child.sendline('dozen') 29 | child.expect('12'); 30 | 31 | child.livepatch('.libs/libdozens_livepatch99.so') 32 | 33 | child.sendline('dozen') 34 | child.expect('13', reject='12'); 35 | 36 | child.close(force=True) 37 | exit(0) 38 | -------------------------------------------------------------------------------- /tests/hundreds.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | int 23 | hundred(void) 24 | { 25 | return 100; 26 | } 27 | -------------------------------------------------------------------------------- /tests/hundreds.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | int hundred(void); 23 | -------------------------------------------------------------------------------- /tests/insn_queue.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # This file is part of libpulp. 4 | # 5 | # libpulp is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU Lesser General Public 7 | # License as published by the Free Software Foundation; either 8 | # version 2.1 of the License, or (at your option) any later version. 9 | # 10 | # libpulp is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # Lesser General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with libpulp. If not, see . 17 | 18 | # This test checks the integrity of the instruction queue between libpulp and 19 | # the ULP tool. 20 | 21 | import sys 22 | import testsuite 23 | import subprocess 24 | 25 | child = testsuite.spawn('insn_queue', timeout = 20) 26 | child.expect("Success") 27 | child.close(force=False) 28 | -------------------------------------------------------------------------------- /tests/libaccess.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | #include 25 | 26 | static char *banner = "Original banner"; 27 | 28 | char * 29 | banner_get(void) 30 | { 31 | return banner; 32 | } 33 | 34 | void 35 | banner_set(char *new) 36 | { 37 | banner = new; 38 | } 39 | -------------------------------------------------------------------------------- /tests/libaccess.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | char *banner_get(void); 23 | void banner_set(char *); 24 | -------------------------------------------------------------------------------- /tests/libaccess_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | static char **ulpr_banner = NULL; 28 | static char *ulpr_string = "String from live patch"; 29 | 30 | void 31 | new_banner_set(__attribute__((unused)) char *new) 32 | { 33 | if (ulpr_banner == NULL) 34 | errx(EXIT_FAILURE, "Live patch data references not initialized"); 35 | 36 | *ulpr_banner = ulpr_string; 37 | } 38 | 39 | /* 40 | * Touch ulpr_banner so that it does not get optimized away or placed into 41 | * read-only sections. 42 | */ 43 | void 44 | banner_disturb(void) 45 | { 46 | ulpr_banner++; 47 | } 48 | -------------------------------------------------------------------------------- /tests/libaccess_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libaccess_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libaccess.so.0.json 3 | banner_set:new_banner_set 4 | #banner:ulpr_banner:__TARGET_OFFSET__:__PATCH_OFFSET__ 5 | -------------------------------------------------------------------------------- /tests/libaccess_livepatch2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | char **ulpr_banner = NULL; 28 | static char *ulpr_string = "String from live patch"; 29 | 30 | void 31 | new_banner_set(__attribute__((unused)) char *new) 32 | { 33 | if (ulpr_banner == NULL) 34 | errx(EXIT_FAILURE, "Live patch data references not initialized"); 35 | 36 | *ulpr_banner = ulpr_string; 37 | } 38 | 39 | /* 40 | * Touch ulpr_banner so that it does not get optimized away or placed into 41 | * read-only sections. 42 | */ 43 | void 44 | banner_disturb(void) 45 | { 46 | ulpr_banner++; 47 | } 48 | -------------------------------------------------------------------------------- /tests/libaccess_livepatch2.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libaccess_livepatch2.so 2 | @__ABS_BUILDDIR__/.libs/libaccess.so.0.json 3 | banner_set:new_banner_set 4 | #banner:ulpr_banner 5 | -------------------------------------------------------------------------------- /tests/libaddress.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | void * 23 | get_return_address(void) 24 | { 25 | void *result; 26 | 27 | result = __builtin_return_address(0); 28 | result = __builtin_extract_return_addr(result); 29 | 30 | return result; 31 | } 32 | 33 | void * 34 | get_address(void) 35 | { 36 | return get_return_address(); 37 | } 38 | -------------------------------------------------------------------------------- /tests/libaddress.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | void *get_address(void); 23 | -------------------------------------------------------------------------------- /tests/libaddress_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | void * 25 | new_get_address(void) 26 | { 27 | return NULL; 28 | } 29 | -------------------------------------------------------------------------------- /tests/libaddress_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libaddress_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libaddress.so.0.json 3 | get_address:new_get_address 4 | -------------------------------------------------------------------------------- /tests/libblocked.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | void 26 | hello(void) 27 | { 28 | printf("hello\n"); 29 | } 30 | 31 | /* Call hello to print on every interruption. */ 32 | void 33 | hello_loop(void) 34 | { 35 | while (1) { 36 | pause(); 37 | hello(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/libblocked.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | void hello(void); 23 | 24 | void hello_loop(void); 25 | -------------------------------------------------------------------------------- /tests/libblocked_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | void 24 | olleh(void) 25 | { 26 | printf("olleh\n"); 27 | } 28 | -------------------------------------------------------------------------------- /tests/libblocked_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libblocked_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libblocked.so.0.json 3 | hello:olleh 4 | -------------------------------------------------------------------------------- /tests/libbuildid.c: -------------------------------------------------------------------------------- 1 | #ifndef RETVAL 2 | #define RETVAL 1337 3 | #endif 4 | 5 | int 6 | retval(void) 7 | { 8 | return RETVAL; 9 | } 10 | -------------------------------------------------------------------------------- /tests/libbuildid_livepatch1.c: -------------------------------------------------------------------------------- 1 | int 2 | new_retval(void) 3 | { 4 | return 42; 5 | } 6 | -------------------------------------------------------------------------------- /tests/libbuildid_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libbuildid_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libbuildid.so.0 3 | retval:new_retval 4 | -------------------------------------------------------------------------------- /tests/libcomments_livepatch1.c: -------------------------------------------------------------------------------- 1 | int 2 | new_value(void) 3 | { 4 | return 1; 5 | } 6 | -------------------------------------------------------------------------------- /tests/libcomments_livepatch1.in: -------------------------------------------------------------------------------- 1 | ! This livepatch fixes bsc#1200316, jsc#SLE-20049, and CVE-2021-3449. 2 | __ABS_BUILDDIR__/.libs/libcomments_livepatch1.so 3 | @__ABS_BUILDDIR__/comments 4 | value:new_value 5 | -------------------------------------------------------------------------------- /tests/libconstructor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | #include "constructor-template.c" 25 | 26 | void * 27 | malloc_wrapper(size_t size) 28 | { 29 | return malloc(size); 30 | } 31 | -------------------------------------------------------------------------------- /tests/libconstructor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | void *malloc_wrapper(size_t size); 23 | -------------------------------------------------------------------------------- /tests/libcontract.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | void fna(void); 23 | 24 | void fnb(void); 25 | -------------------------------------------------------------------------------- /tests/libcontract_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libcontract_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libcontract.so.0.json 3 | print:new_print 4 | fna:new_fna 5 | fnb:new_fnb 6 | -------------------------------------------------------------------------------- /tests/libdozens_bsymbolic_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libdozens_bsymbolic_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libdozens_bsymbolic.so.0.json 3 | dozen:baker_dozen 4 | -------------------------------------------------------------------------------- /tests/libdozens_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | int 23 | baker_dozen(void) 24 | { 25 | return 13; 26 | } 27 | -------------------------------------------------------------------------------- /tests/libdozens_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libdozens_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libdozens.so.0.json 3 | dozen:baker_dozen 4 | -------------------------------------------------------------------------------- /tests/libdozens_livepatch99.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | int 23 | hidden_baker_dozen(void) 24 | { 25 | return 13; 26 | } 27 | -------------------------------------------------------------------------------- /tests/libdozens_livepatch99.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libdozens_livepatch99.so 2 | @__ABS_BUILDDIR__/.libs/libdozens.so.0.json 3 | hidden_dozen:hidden_baker_dozen 4 | -------------------------------------------------------------------------------- /tests/libendbr64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | int 23 | hundred(void) 24 | { 25 | return 100; 26 | } 27 | -------------------------------------------------------------------------------- /tests/libendbr64_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libendbr64_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libendbr64.so.0.json 3 | hundred:two_hundreds 4 | -------------------------------------------------------------------------------- /tests/libexception.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | void 26 | inner(void) 27 | { 28 | throw std::runtime_error(""); 29 | } 30 | 31 | void 32 | outer(void) 33 | { 34 | try { 35 | inner(); 36 | } 37 | catch (std::runtime_error &e) { 38 | std::cout << "caught in lib" << std::endl; 39 | throw; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/libexception.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | void inner(void); 23 | void outer(void); 24 | -------------------------------------------------------------------------------- /tests/libhundreds_bsymbolic_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libhundreds_bsymbolic_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libhundreds_bsymbolic.so.0 3 | hundred:two_hundreds 4 | -------------------------------------------------------------------------------- /tests/libhundreds_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | int 23 | two_hundreds(void) 24 | { 25 | return 200; 26 | } 27 | -------------------------------------------------------------------------------- /tests/libhundreds_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libhundreds_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libhundreds.so.0.json 3 | hundred:two_hundreds 4 | -------------------------------------------------------------------------------- /tests/libhundreds_livepatch2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | int 23 | three_hundreds(void) 24 | { 25 | return 300; 26 | } 27 | -------------------------------------------------------------------------------- /tests/libhundreds_livepatch2.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libhundreds_livepatch2.so 2 | @__ABS_BUILDDIR__/.libs/libhundreds.so.0.json 3 | hundred:three_hundreds 4 | -------------------------------------------------------------------------------- /tests/libhundreds_livepatch3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | int 23 | four_hundreds(void) 24 | { 25 | return 400; 26 | } 27 | -------------------------------------------------------------------------------- /tests/libhundreds_livepatch3.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libhundreds_livepatch3.so 2 | @__ABS_BUILDDIR__/.libs/libhundreds.so.0.json 3 | hundred:four_hundreds 4 | -------------------------------------------------------------------------------- /tests/libmanyprocesses_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | void 25 | new_int_params(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) 26 | { 27 | printf("%d-%d-%d-%d-%d-%d-%d-%d-%d-%d\n", j, i, h, g, f, e, d, c, b, a); 28 | } 29 | 30 | void 31 | new_float_params(float a, float b, float c, float d, float e, float f, float g, 32 | float h, float i, float j) 33 | { 34 | printf("%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f\n", j, i, h, g, f, 35 | e, d, c, b, a); 36 | } 37 | -------------------------------------------------------------------------------- /tests/libmanyprocesses_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libmanyprocesses_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libmanyprocesses.so.0 3 | int_params:new_int_params 4 | float_params:new_float_params 5 | -------------------------------------------------------------------------------- /tests/libnotes_livepatch1.c: -------------------------------------------------------------------------------- 1 | #include "stdbool.h" 2 | bool 3 | new_repeat(void) 4 | { 5 | return false; 6 | } 7 | -------------------------------------------------------------------------------- /tests/libnotes_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libnotes_livepatch1.so 2 | @__ABS_BUILDDIR__/notes 3 | repeat:new_repeat 4 | -------------------------------------------------------------------------------- /tests/libpagecross.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | void 25 | function(void) 26 | { 27 | printf("default\n"); 28 | } 29 | -------------------------------------------------------------------------------- /tests/libpagecross_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | void 25 | new_function(void) 26 | { 27 | printf("patched\n"); 28 | } 29 | -------------------------------------------------------------------------------- /tests/libpagecross_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libpagecross_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libpagecross.so.0 3 | function:new_function 4 | -------------------------------------------------------------------------------- /tests/libpagecross_padding.S: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | /* 23 | * From the start of a page (.align ), fill the memory with 24 | * garbage up to the end of the page less 16 bytes (.fill ), 25 | * so that the prologue of the to-be-patched function (in libpage.c) 26 | * crosses a page boundary. 27 | */ 28 | .set FILL_SIZE, PAGE_SIZE-16 29 | .section .text 30 | .fill FILL_SIZE, 1, 0xCC 31 | -------------------------------------------------------------------------------- /tests/libparameters.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | void int_params(int a, int b, int c, int d, int e, int f, int g, int h, 23 | int i, int j); 24 | 25 | void float_params(float a, float b, float c, float d, float e, float f, 26 | float g, float h, float i, float j); 27 | -------------------------------------------------------------------------------- /tests/libparameters_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | void 25 | new_int_params(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) 26 | { 27 | printf("%d-%d-%d-%d-%d-%d-%d-%d-%d-%d\n", j, i, h, g, f, e, d, c, b, a); 28 | } 29 | 30 | void 31 | new_float_params(float a, float b, float c, float d, float e, float f, float g, 32 | float h, float i, float j) 33 | { 34 | printf("%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f\n", j, i, h, g, f, 35 | e, d, c, b, a); 36 | } 37 | -------------------------------------------------------------------------------- /tests/libparameters_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libparameters_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libparameters.so.0 3 | int_params:new_int_params 4 | float_params:new_float_params 5 | -------------------------------------------------------------------------------- /tests/libparameters_livepatch2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | /* Empty file to create and empty live patch. */ 23 | -------------------------------------------------------------------------------- /tests/libparameters_livepatch2.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libparameters_livepatch2.so 2 | @__ABS_BUILDDIR__/.libs/libparameters.so.0 3 | -------------------------------------------------------------------------------- /tests/libparameters_livepatch3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | void 25 | new_int_params(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) 26 | { 27 | printf("%d-%d-%d-%d-%d-%d-%d-%d-%d-%d\n", j, i, h, g, f, e, d, c, b, a); 28 | } 29 | 30 | void 31 | new_float_params(float a, float b, float c, float d, float e, float f, float g, 32 | float h, float i, float j) 33 | { 34 | printf("%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f\n", j, i, h, g, f, 35 | e, d, c, b, a); 36 | } 37 | -------------------------------------------------------------------------------- /tests/libparameters_livepatch3.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libparameters_livepatch3.so 2 | @.libs/libparameters.so.0 3 | int_params:new_int_params 4 | float_params:new_float_params 5 | -------------------------------------------------------------------------------- /tests/libprefix.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | int 23 | hundred(void) 24 | { 25 | return 100; 26 | } 27 | -------------------------------------------------------------------------------- /tests/libprefix_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libprefix_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libprefix.so.0 3 | hundred:two_hundreds 4 | -------------------------------------------------------------------------------- /tests/libprocess_access_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libprocess_access_livepatch1.so 2 | @__ABS_BUILDDIR__/process_access 3 | banner_set:new_banner_set 4 | #banner:ulpr_banner 5 | -------------------------------------------------------------------------------- /tests/libprocess_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | void 25 | new_int_params(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) 26 | { 27 | printf("%d-%d-%d-%d-%d-%d-%d-%d-%d-%d\n", j, i, h, g, f, e, d, c, b, a); 28 | } 29 | 30 | void 31 | new_float_params(float a, float b, float c, float d, float e, float f, float g, 32 | float h, float i, float j) 33 | { 34 | printf("%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f-%.1f\n", j, i, h, g, f, 35 | e, d, c, b, a); 36 | } 37 | -------------------------------------------------------------------------------- /tests/libprocess_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libprocess_livepatch1.so 2 | @__ABS_BUILDDIR__/process 3 | int_params:new_int_params 4 | float_params:new_float_params 5 | -------------------------------------------------------------------------------- /tests/libpulp_messages.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('parameters') 25 | 26 | child.expect('Waiting for input.') 27 | 28 | child.sendline('') 29 | child.expect('1-2-3-4-5-6-7-8-9-10'); 30 | child.expect('1.0-2.0-3.0-4.0-5.0-6.0-7.0-8.0-9.0-10.0'); 31 | 32 | try: 33 | msgs = child.get_libpulp_messages() 34 | if msgs.find("libpulp loaded") != -1: 35 | error = 0 36 | except: 37 | error = 1 38 | 39 | child.close(force=True) 40 | exit(error) 41 | -------------------------------------------------------------------------------- /tests/librecursion.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | long long int 25 | fibonacci(long long int n) 26 | { 27 | if (n < 2) 28 | return n; 29 | 30 | return fibonacci(n - 1) + fibonacci(n - 2); 31 | } 32 | 33 | long long int 34 | lucas(long long int n) 35 | { 36 | if (n == 0) 37 | return 2; 38 | if (n == 1) 39 | return 1; 40 | 41 | return lucas(n - 1) + lucas(n - 2); 42 | } 43 | 44 | long long int 45 | recursion(long long int n) 46 | { 47 | return fibonacci(n); 48 | } 49 | -------------------------------------------------------------------------------- /tests/librecursion.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | long long int fibonacci(long long int n); 23 | long long int lucas(long long int n); 24 | 25 | long long int recursion(long long int n); 26 | -------------------------------------------------------------------------------- /tests/librecursion2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | long long int __attribute__((noinline)) 25 | func_1(long long int n) 26 | { 27 | if (n < 0) 28 | return 0; 29 | 30 | return n + func_2(n-1); 31 | } 32 | 33 | long long int __attribute__((noinline)) 34 | func_2(long long int n) 35 | { 36 | if (n < 0) 37 | return 0; 38 | 39 | return 2*n + func_1(n-1); 40 | } 41 | 42 | long long int __attribute__((noinline)) 43 | recursion(long long int n) 44 | { 45 | return func_1(n); 46 | } 47 | -------------------------------------------------------------------------------- /tests/librecursion2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | long long int func_1(long long int n); 23 | 24 | long long int func_2(long long int n); 25 | 26 | long long int recursion(long long int n); 27 | -------------------------------------------------------------------------------- /tests/librecursion2_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | long long int __attribute__((noinline)) 25 | new_func_1(long long int n) 26 | { 27 | if (n < 0) 28 | return 0; 29 | 30 | return -n + func_2(n-1); 31 | } 32 | 33 | long long int __attribute__((noinline)) 34 | new_func_2(long long int n) 35 | { 36 | if (n < 0) 37 | return 0; 38 | 39 | return -2*n + func_1(n-1); 40 | } 41 | -------------------------------------------------------------------------------- /tests/librecursion2_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/librecursion2_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/librecursion2.so.0 3 | func_1:new_func_1 4 | func_2:new_func_2 5 | -------------------------------------------------------------------------------- /tests/librecursion_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | int (*lucas_ptr)(int) = (void *)0L; 23 | 24 | long long int 25 | new_recursion(long long int n) 26 | { 27 | return lucas_ptr(n); 28 | } 29 | -------------------------------------------------------------------------------- /tests/librecursion_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/librecursion_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/librecursion.so.0 3 | recursion:new_recursion 4 | #lucas:lucas_ptr 5 | -------------------------------------------------------------------------------- /tests/libsecdis_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | /* This function is here for messing with seccomp. Seccomp disables 26 | mmap with EXEC | WRITE attributes, so if we call it we should get 27 | a memory allocation error with ENOPERM. */ 28 | 29 | __attribute__((constructor)) 30 | static void initialize(void) 31 | { 32 | void *page = mmap(NULL, 128, PROT_EXEC | PROT_READ | PROT_WRITE, 33 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 34 | 35 | /* Check if we got the page. */ 36 | if (page == (void *) -1L || page == NULL) { 37 | /* We did not get the page, abort. */ 38 | abort(); 39 | } 40 | 41 | /* Clean memory. */ 42 | munmap(page, 128); 43 | } 44 | 45 | int 46 | baker_dozen(void) 47 | { 48 | return 13; 49 | } 50 | -------------------------------------------------------------------------------- /tests/libsecdis_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libsecdis_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libdozens.so.0.json 3 | dozen:baker_dozen 4 | -------------------------------------------------------------------------------- /tests/libstress.c: -------------------------------------------------------------------------------- 1 | int 2 | value(void) 3 | { 4 | return 1; 5 | } 6 | -------------------------------------------------------------------------------- /tests/libstress_livepatch1.c: -------------------------------------------------------------------------------- 1 | int 2 | new_value(void) 3 | { 4 | return 0; 5 | } 6 | -------------------------------------------------------------------------------- /tests/libstress_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libstress_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libstress.so.0 3 | value:new_value 4 | -------------------------------------------------------------------------------- /tests/libtls.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | static __thread char *banner = "Original TLS banner"; 25 | 26 | char * 27 | banner_get(void) 28 | { 29 | return banner; 30 | } 31 | 32 | char ** 33 | banner_get_ref(void) 34 | { 35 | return &banner; 36 | } 37 | 38 | void 39 | banner_set(char *new) 40 | { 41 | banner = new; 42 | } 43 | -------------------------------------------------------------------------------- /tests/libtls_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "../include/ulp_common.h" 27 | 28 | // ti is overriden in the livepatching process. It must not be declared static 29 | // else the compiler may remove the variable because it is unreferenced. 30 | tls_index ti = { 0 }; 31 | static char *ulpr_string = "String from live patch"; 32 | 33 | void *__tls_get_addr(tls_index *); 34 | 35 | #define SWAP(a,b) { typeof(a) _t = (a); (a) = (b); (b) = _t; } 36 | 37 | void 38 | new_banner_set(__attribute__((unused)) char *new) 39 | { 40 | if (ti.ti_module == 0 && ti.ti_offset == 0) 41 | errx(EXIT_FAILURE, "Live patch data references not initialized"); 42 | 43 | char **ulpr_banner = __tls_get_addr(&ti); 44 | printf("module: %lx, offset: %lx\n", ti.ti_module, ti.ti_offset); 45 | printf("addr: 0x%lx\n", (unsigned long)ulpr_banner); 46 | *ulpr_banner = ulpr_string; 47 | } 48 | -------------------------------------------------------------------------------- /tests/libtls_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libtls_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libtls.so.0.json 3 | banner_set:new_banner_set 4 | #%banner:ti:__TARGET_OFFSET__:__PATCH_OFFSET__ 5 | -------------------------------------------------------------------------------- /tests/libvisibility.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2024 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | /* This function has hidden visibility. We should not be able to do an weak 23 | externalization here. */ 24 | 25 | static char string[] = "This is a hidden string"; 26 | 27 | __attribute__((visibility("hidden"))) 28 | void *get_hidden_address(void) 29 | { 30 | return string; 31 | } 32 | 33 | void *get_address(void) 34 | { 35 | return get_hidden_address(); 36 | } 37 | -------------------------------------------------------------------------------- /tests/libvisibility_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2024 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | static char string[128]; 25 | 26 | void *get_hidden_address(void); 27 | 28 | void *get_address_lp(void) 29 | { 30 | strcpy(string, "String from lp "); 31 | strcat(string, get_hidden_address()); 32 | return string; 33 | } 34 | -------------------------------------------------------------------------------- /tests/libvisibility_livepatch1.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libvisibility_livepatch1.so 2 | @__ABS_BUILDDIR__/.libs/libvisibility.so.0.json 3 | get_hidden_address:get_address_lp 4 | -------------------------------------------------------------------------------- /tests/libvisibility_livepatch2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2024 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | static char string[128]; 25 | 26 | // Strong externalization of get_hidden_address 27 | static __attribute__((used)) void *(*klpe_get_hidden_address)(void); 28 | 29 | void *get_address_lp(void) 30 | { 31 | strcpy(string, "String from lp "); 32 | strcat(string, (*klpe_get_hidden_address)()); 33 | return string; 34 | } 35 | -------------------------------------------------------------------------------- /tests/libvisibility_livepatch2.in: -------------------------------------------------------------------------------- 1 | __ABS_BUILDDIR__/.libs/libvisibility_livepatch2.so 2 | @__ABS_BUILDDIR__/.libs/libvisibility.so.0.json 3 | get_address:get_address_lp 4 | #get_hidden_address:klpe_get_hidden_address 5 | -------------------------------------------------------------------------------- /tests/livepatchable.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | if testsuite.is_library_livepatchable('.libs/libexception.so') == True: 25 | exit(0) 26 | 27 | exit(1) 28 | -------------------------------------------------------------------------------- /tests/loop.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | /* Link against a live patchable library. */ 27 | #include 28 | 29 | int 30 | main(void) 31 | { 32 | printf("Child ready\n"); 33 | printf("%d\n", getpid()); 34 | fflush(stdout); 35 | while (1) { 36 | pause(); 37 | } 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /tests/manyprocesses.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | void int_params(int a, int b, int c, int d, int e, int f, int g, int h, 26 | int i, int j); 27 | 28 | void float_params(float a, float b, float c, float d, float e, float f, 29 | float g, float h, float i, float j); 30 | 31 | int 32 | main(void) 33 | { 34 | char buffer[128]; 35 | 36 | /* Loop waiting for any input. */ 37 | printf("Waiting for input.\n"); 38 | while (1) { 39 | if (fgets(buffer, sizeof(buffer), stdin) == NULL) { 40 | if (errno) { 41 | perror("parameters"); 42 | return 1; 43 | } 44 | printf("Reached the end of file; quitting.\n"); 45 | return 0; 46 | } 47 | int_params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 48 | float_params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 49 | } 50 | 51 | return 1; 52 | } 53 | -------------------------------------------------------------------------------- /tests/memory_protection.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('memory_protection') 25 | 26 | child.expect('Waiting for input.') 27 | 28 | # Every time a newline is sent, the test program touchs code memory 29 | child.sendline('') 30 | child.expect('pristine'); 31 | 32 | child.livepatch('.libs/libaddress_livepatch1.so') 33 | 34 | # Try to touch code memory after live patching 35 | child.sendline('') 36 | try: 37 | child.expect('patched', reject='pristine'); 38 | except EOFError: 39 | # Diagnose the error 40 | print('Touching code after live patch failed.') 41 | if child.isalive() == False: 42 | print('The test program is dead') 43 | else: 44 | child.close(force=True) 45 | # Let the exception propagate, so that the stack trace gets printed 46 | raise 47 | 48 | child.close(force=True) 49 | exit(0) 50 | -------------------------------------------------------------------------------- /tests/missing_function.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import subprocess 23 | import testsuite 24 | 25 | livepatch_metadata = 'libparameters_livepatch2.ulp' 26 | livepatch_container = 'libparameters_livepatch2.so' 27 | 28 | child = testsuite.spawn('parameters') 29 | 30 | child.expect('Waiting for input.') 31 | 32 | errors = 1 33 | try: 34 | child.livepatch(livepatch_metadata) 35 | except subprocess.CalledProcessError: 36 | if not child.is_so_loaded(livepatch_container): 37 | errors = 0 38 | 39 | child.close(force=True) 40 | exit(errors) 41 | -------------------------------------------------------------------------------- /tests/nolibpulp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import os 23 | import subprocess 24 | import time 25 | 26 | import testsuite 27 | from testsuite import ulptool 28 | 29 | errorcode = 0 30 | child = testsuite.spawn('parameters', env=None) 31 | 32 | child.expect('Waiting for input.') 33 | 34 | # Check if libpulp got loaded in the process. This may be due to libpulp being 35 | # loaded as default by the system, hence there is nothing we can do other than 36 | # skip the test. 37 | if child.is_so_loaded("libpulp.so") is True: 38 | child.close(force=True) 39 | exit(77) # Skip test. 40 | 41 | child.sendline('') 42 | child.expect('1-2-3-4-5-6-7-8-9-10'); 43 | child.expect('1.0-2.0-3.0-4.0-5.0-6.0-7.0-8.0-9.0-10.0'); 44 | 45 | out = child.livepatch('.libs/libparameters_livepatch1.so', capture_tool_output=True) 46 | if out.find("Libpulp not found in target process") == -1: 47 | errorcode = 1 48 | 49 | child.sendline('') 50 | child.expect('1-2-3-4-5-6-7-8-9-10', reject='10-9-8-7-6-5-4-3-2-1'); 51 | 52 | child.close(force=True) 53 | exit(errorcode) 54 | -------------------------------------------------------------------------------- /tests/notes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | __attribute__((noinline)) 6 | bool 7 | repeat() 8 | { 9 | volatile bool ret = true; 10 | return ret; 11 | } 12 | 13 | int 14 | main() 15 | { 16 | puts("Ready."); 17 | 18 | while (repeat()) 19 | usleep(100); 20 | 21 | puts("Livepatched"); 22 | fflush(stdout); 23 | 24 | pause(); 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /tests/notes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2025 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | import platform 24 | 25 | child = testsuite.spawn('notes') 26 | 27 | child.expect('Ready.') 28 | child.livepatch('.libs/libnotes_livepatch1.so') 29 | child.expect('Livepatched'); 30 | 31 | child.close(force=True) 32 | exit(0) 33 | -------------------------------------------------------------------------------- /tests/numserv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | int 30 | main(void) 31 | { 32 | char input[64]; 33 | 34 | printf("Waiting for input.\n"); 35 | while (1) { 36 | if (scanf("%s", input) == EOF) { 37 | if (errno) { 38 | perror("numserv"); 39 | return 1; 40 | } 41 | printf("Reached the end of file; quitting.\n"); 42 | return 0; 43 | } 44 | if (strncmp(input, "dozen", strlen("dozen")) == 0) 45 | printf("%d\n", dozen()); 46 | if (strncmp(input, "hundred", strlen("hundred")) == 0) 47 | printf("%d\n", hundred()); 48 | if (strncmp(input, "quit", strlen("quit")) == 0) { 49 | printf("Quitting.\n"); 50 | return 0; 51 | } 52 | } 53 | 54 | return 1; 55 | } 56 | -------------------------------------------------------------------------------- /tests/numserv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import re 23 | 24 | import testsuite 25 | 26 | # Live patch selection variable 27 | bsymbolic = re.search('_bsymbolic', testsuite.testname) 28 | 29 | child = testsuite.spawn(testsuite.testname) 30 | 31 | child.expect('Waiting for input.') 32 | 33 | child.sendline('dozen') 34 | child.expect('12'); 35 | 36 | child.sendline('hundred') 37 | child.expect('100'); 38 | 39 | if not bsymbolic: 40 | child.livepatch('.libs/libdozens_livepatch1.so') 41 | else: 42 | child.livepatch('.libs/libdozens_bsymbolic_livepatch1.so') 43 | 44 | child.sendline('dozen') 45 | child.expect('13', reject='12'); 46 | 47 | child.sendline('hundred') 48 | child.expect('100'); 49 | 50 | if not bsymbolic: 51 | child.livepatch('.libs/libhundreds_livepatch1.so') 52 | else: 53 | child.livepatch('.libs/libhundreds_bsymbolic_livepatch1.so') 54 | 55 | child.sendline('dozen') 56 | child.expect('13', reject='12'); 57 | 58 | child.sendline('hundred') 59 | child.expect('200', reject='100'); 60 | 61 | child.close(force=True) 62 | exit(0) 63 | -------------------------------------------------------------------------------- /tests/pagecross.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | void function(void); 26 | 27 | int 28 | main(void) 29 | { 30 | char buffer[128]; 31 | 32 | /* Signal readiness. */ 33 | printf("Waiting for input.\n"); 34 | 35 | /* Loop waiting for input and calling function(). */ 36 | while (1) { 37 | if (fgets(buffer, sizeof(buffer), stdin) == NULL) { 38 | if (errno) { 39 | perror("pagecross"); 40 | return 1; 41 | } 42 | printf("Reached the end of file; quitting.\n"); 43 | return 0; 44 | } 45 | function(); 46 | } 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /tests/pagecross.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('pagecross') 25 | 26 | child.expect('Waiting for input.') 27 | 28 | child.sendline('') 29 | child.expect('default'); 30 | 31 | child.livepatch('.libs/libpagecross_livepatch1.so') 32 | 33 | child.sendline('') 34 | child.expect('patched', reject='default'); 35 | 36 | child.close(force=True) 37 | exit(0) 38 | -------------------------------------------------------------------------------- /tests/parameters.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | int 28 | main(void) 29 | { 30 | char buffer[128]; 31 | 32 | /* Loop waiting for any input. */ 33 | printf("Waiting for input.\n"); 34 | while (1) { 35 | if (fgets(buffer, sizeof(buffer), stdin) == NULL) { 36 | if (errno) { 37 | perror("parameters"); 38 | return 1; 39 | } 40 | printf("Reached the end of file; quitting.\n"); 41 | return 0; 42 | } 43 | int_params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 44 | float_params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 45 | } 46 | 47 | return 1; 48 | } 49 | -------------------------------------------------------------------------------- /tests/parameters.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('parameters') 25 | 26 | child.expect('Waiting for input.') 27 | 28 | child.sendline('') 29 | child.expect('1-2-3-4-5-6-7-8-9-10'); 30 | child.expect('1.0-2.0-3.0-4.0-5.0-6.0-7.0-8.0-9.0-10.0'); 31 | 32 | child.livepatch('.libs/libparameters_livepatch1.so') 33 | 34 | child.sendline('') 35 | child.expect('10-9-8-7-6-5-4-3-2-1', reject='1-2-3-4-5-6-7-8-9-10'); 36 | child.expect('10.0-9.0-8.0-7.0-6.0-5.0-4.0-3.0-2.0-1.0', 37 | reject='1.0-2.0-3.0-4.0-5.0-6.0-7.0-8.0-9.0-10.0'); 38 | 39 | child.close(force=True) 40 | exit(0) 41 | -------------------------------------------------------------------------------- /tests/patches.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2023 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | # Test `ulp patches` command. 23 | 24 | import testsuite 25 | import subprocess 26 | import sys 27 | import os 28 | 29 | # Check if the ULP tool crashes if -p is passed to unexisting process. 30 | command = [testsuite.ulptool, "patches", "-p", "99999"] 31 | try: 32 | tool = subprocess.run(command, timeout=10, stderr=subprocess.STDOUT) 33 | except: 34 | exit(1) 35 | 36 | # It should actually return an error because we explicitly trieed to retrieve 37 | # information of a non-running process. 38 | if tool.returncode == 0: 39 | exit(1) 40 | 41 | exit(0) 42 | -------------------------------------------------------------------------------- /tests/path_disable.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2023 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import re 23 | 24 | import testsuite 25 | 26 | env = { 'LD_PRELOAD': '../lib/.libs/libpulp.so', 27 | 'LIBPULP_DISABLE_ON_PATH': '*/numserv' } 28 | 29 | child = testsuite.spawn('numserv', env=env) 30 | 31 | child.expect('Waiting for input.') 32 | 33 | child.sendline('dozen') 34 | child.expect('12'); 35 | 36 | child.sendline('hundred') 37 | child.expect('100'); 38 | 39 | child.livepatch('.libs/libdozens_livepatch1.so', sanity=False) 40 | 41 | child.sendline('dozen') 42 | child.expect('12', reject='13'); 43 | 44 | child.close(force=True) 45 | exit(0) 46 | -------------------------------------------------------------------------------- /tests/pcqueue.c: -------------------------------------------------------------------------------- 1 | /* Include the C file so we have access to the implementation of the pcqueue 2 | without having to implement it into a library. */ 3 | 4 | #include "../tools/pcqueue.c" 5 | 6 | /* How many enqueues/dequeue. */ 7 | #define NUM_TEST 1000000 8 | 9 | static void * 10 | producer_thread(void *a) 11 | { 12 | long i; 13 | producer_consumer_t *pcqueue = a; 14 | 15 | for (i = 0; i < NUM_TEST; i++) { 16 | if (producer_consumer_enqueue(pcqueue, (void *)i) != 0) { 17 | abort(); 18 | } 19 | } 20 | 21 | return NULL; 22 | } 23 | 24 | int 25 | main() 26 | { 27 | pthread_t thread; 28 | long i; 29 | 30 | producer_consumer_t *pcqueue = producer_consumer_new(8); 31 | if (pcqueue == NULL) { 32 | printf("Error allocating queue\n"); 33 | return 1; 34 | } 35 | 36 | pthread_create(&thread, NULL, producer_thread, pcqueue); 37 | 38 | for (i = 0; i < NUM_TEST; i++) { 39 | void *elem = producer_consumer_dequeue(pcqueue); 40 | if ((long)elem != i) 41 | abort(); 42 | } 43 | 44 | pthread_join(thread, NULL); 45 | producer_consumer_delete(pcqueue); 46 | printf("Pass\n"); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /tests/pcqueue.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2022 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | 23 | import testsuite 24 | 25 | test = testsuite.spawn('./pcqueue', script=False, timeout=30) 26 | test.expect('Pass') 27 | test.close(force=True) 28 | -------------------------------------------------------------------------------- /tests/prefix.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2022 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | int 30 | main(void) 31 | { 32 | char input[64]; 33 | 34 | printf("Waiting for input.\n"); 35 | while (1) { 36 | if (scanf("%s", input) == EOF) { 37 | if (errno) { 38 | perror("numserv"); 39 | return 1; 40 | } 41 | printf("Reached the end of file; quitting.\n"); 42 | return 0; 43 | } 44 | if (strncmp(input, "dozen", strlen("dozen")) == 0) 45 | printf("%d\n", dozen()); 46 | if (strncmp(input, "hundred", strlen("hundred")) == 0) 47 | printf("%d\n", hundred()); 48 | if (strncmp(input, "quit", strlen("quit")) == 0) { 49 | printf("Quitting.\n"); 50 | return 0; 51 | } 52 | } 53 | 54 | return 1; 55 | } 56 | -------------------------------------------------------------------------------- /tests/prefix.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | # 22 | # This test checks if passing the -R option to trigger with a silly 23 | # prefix causes the patching to fail on libpulp.so side. This is 24 | # useful if ulp runs in a chroot. 25 | 26 | import testsuite 27 | import re 28 | 29 | child = testsuite.spawn('prefix') 30 | 31 | child.expect('Waiting for input.') 32 | 33 | child.sendline('hundred') 34 | child.expect('100') 35 | 36 | child.livepatch('.libs/libprefix_livepatch1.so', prefix="/silly-prefix/", sanity=False) 37 | 38 | msgs = child.get_libpulp_messages() 39 | if re.search(r'Unable to load shared object /silly-prefix/.*/.libs/libprefix_livepatch1.so', msgs): 40 | error = 0 41 | else: 42 | error = 1 43 | 44 | child.close(force=True) 45 | exit(error) 46 | -------------------------------------------------------------------------------- /tests/process.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('process', script=False) 25 | 26 | child.expect('Waiting for input.') 27 | 28 | child.sendline('') 29 | child.expect('1-2-3-4-5-6-7-8-9-10'); 30 | child.expect('1.0-2.0-3.0-4.0-5.0-6.0-7.0-8.0-9.0-10.0'); 31 | 32 | child.livepatch('.libs/libprocess_livepatch1.so') 33 | 34 | child.sendline('') 35 | child.expect('10-9-8-7-6-5-4-3-2-1', reject='1-2-3-4-5-6-7-8-9-10'); 36 | child.expect('10.0-9.0-8.0-7.0-6.0-5.0-4.0-3.0-2.0-1.0', 37 | reject='1.0-2.0-3.0-4.0-5.0-6.0-7.0-8.0-9.0-10.0'); 38 | 39 | child.close(force=True) 40 | exit(0) 41 | -------------------------------------------------------------------------------- /tests/process_access.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | # Tests if private variables in a process (not in a library) can be 25 | # correctly referenced. 26 | 27 | child = testsuite.spawn('process_access', script=False) 28 | 29 | child.expect('Original banner') 30 | child.expect('Banner changed from main') 31 | 32 | child.livepatch('.libs/libprocess_access_livepatch1.so') 33 | 34 | child.sendline('') 35 | child.expect('String from live patch', 36 | reject=['String from main', 37 | 'Live patch data references not initialized']) 38 | 39 | child.close(force=True) 40 | exit(0) 41 | -------------------------------------------------------------------------------- /tests/process_access_livepatch1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | char **ulpr_banner = NULL; 27 | static char *ulpr_string = "String from live patch"; 28 | 29 | void 30 | new_banner_set(__attribute__((unused)) char *new) 31 | { 32 | if (ulpr_banner == NULL) 33 | errx(EXIT_FAILURE, "Live patch data references not initialized"); 34 | 35 | *ulpr_banner = ulpr_string; 36 | } 37 | 38 | /* 39 | * Touch ulpr_banner so that it does not get optimized away or placed into 40 | * read-only sections. 41 | */ 42 | void 43 | banner_disturb(void) 44 | { 45 | ulpr_banner++; 46 | } 47 | -------------------------------------------------------------------------------- /tests/process_revert.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('process', script=False) 25 | 26 | child.expect('Waiting for input.') 27 | 28 | child.sendline('') 29 | child.expect('1-2-3-4-5-6-7-8-9-10'); 30 | child.expect('1.0-2.0-3.0-4.0-5.0-6.0-7.0-8.0-9.0-10.0'); 31 | 32 | child.livepatch('.libs/libprocess_livepatch1.so') 33 | 34 | child.sendline('') 35 | child.expect('10-9-8-7-6-5-4-3-2-1', reject='1-2-3-4-5-6-7-8-9-10'); 36 | child.expect('10.0-9.0-8.0-7.0-6.0-5.0-4.0-3.0-2.0-1.0', 37 | reject='1.0-2.0-3.0-4.0-5.0-6.0-7.0-8.0-9.0-10.0'); 38 | 39 | child.livepatch('.libs/libprocess_livepatch1.so', revert=True) 40 | 41 | child.sendline('') 42 | child.expect('1-2-3-4-5-6-7-8-9-10'); 43 | child.expect('1.0-2.0-3.0-4.0-5.0-6.0-7.0-8.0-9.0-10.0'); 44 | 45 | child.close(force=True) 46 | exit(0) 47 | -------------------------------------------------------------------------------- /tests/recursion.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | int 29 | main(void) 30 | { 31 | char buffer[128]; 32 | int input; 33 | 34 | /* Loop waiting for a numerical input. */ 35 | printf("Waiting for input.\n"); 36 | while (1) { 37 | if (fgets(buffer, sizeof(buffer), stdin) == NULL) { 38 | if (errno) { 39 | perror("recursive"); 40 | return 1; 41 | } 42 | printf("Reached the end of file; quitting.\n"); 43 | return 0; 44 | } 45 | input = atoi(buffer); 46 | if (input <= 0) { 47 | printf("Input must be greater than zero.\n"); 48 | continue; 49 | } 50 | printf("%lld\n", recursion(input)); 51 | } 52 | 53 | return 1; 54 | } 55 | -------------------------------------------------------------------------------- /tests/recursion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('recursion', timeout=60) 25 | 26 | child.expect('Waiting for input.') 27 | 28 | child.sendline('40') 29 | child.expect('102334155'); 30 | 31 | child.livepatch('.libs/librecursion_livepatch1.so') 32 | 33 | child.sendline('40') 34 | child.expect('228826127', reject='102334155'); 35 | 36 | child.close(force=True) 37 | exit(0) 38 | -------------------------------------------------------------------------------- /tests/recursion2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | int 29 | main(void) 30 | { 31 | char buffer[128]; 32 | int input; 33 | 34 | /* Loop waiting for a numerical input. */ 35 | printf("Waiting for input.\n"); 36 | while (1) { 37 | if (fgets(buffer, sizeof(buffer), stdin) == NULL) { 38 | if (errno) { 39 | perror("recursive"); 40 | return 1; 41 | } 42 | printf("Reached the end of file; quitting.\n"); 43 | return 0; 44 | } 45 | input = atoi(buffer); 46 | if (input <= 0) { 47 | printf("Input must be greater than zero.\n"); 48 | continue; 49 | } 50 | printf("%lld\n", recursion(input)); 51 | } 52 | 53 | return 1; 54 | } 55 | -------------------------------------------------------------------------------- /tests/recursion2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2025 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('recursion2', timeout=60) 25 | 26 | child.expect('Waiting for input.') 27 | 28 | child.sendline('2') 29 | child.expect('4'); 30 | 31 | child.sendline('40') 32 | child.expect('1220'); 33 | 34 | child.livepatch('.libs/librecursion2_livepatch1.so') 35 | 36 | child.sendline('2') 37 | child.expect('4'); 38 | 39 | child.sendline('40') 40 | child.expect('-1220', reject='1220'); 41 | 42 | child.close(force=True) 43 | exit(0) 44 | -------------------------------------------------------------------------------- /tests/redzone.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('redzone', timeout=50) 25 | 26 | child.expect('Waiting for input.') 27 | 28 | child.livepatch('.libs/libblocked_livepatch1.so') 29 | 30 | # Check live patch, which should not touch the redzone 31 | child.is_patch_applied('.libs/libblocked_livepatch1.so') 32 | 33 | # Read error output, if any 34 | child.readline() 35 | child.readline() 36 | 37 | ret = child.wait() 38 | if ret: 39 | exit(1) 40 | exit(0) 41 | -------------------------------------------------------------------------------- /tests/relative_path.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('parameters') 25 | 26 | child.expect('Waiting for input.') 27 | 28 | child.sendline('') 29 | child.expect('1-2-3-4-5-6-7-8-9-10'); 30 | child.expect('1.0-2.0-3.0-4.0-5.0-6.0-7.0-8.0-9.0-10.0'); 31 | 32 | child.livepatch('.libs/libparameters_livepatch3.so') 33 | 34 | child.sendline('') 35 | child.expect('10-9-8-7-6-5-4-3-2-1', reject='1-2-3-4-5-6-7-8-9-10'); 36 | child.expect('10.0-9.0-8.0-7.0-6.0-5.0-4.0-3.0-2.0-1.0', 37 | reject='1.0-2.0-3.0-4.0-5.0-6.0-7.0-8.0-9.0-10.0'); 38 | 39 | child.close(force=True) 40 | exit(0) 41 | -------------------------------------------------------------------------------- /tests/revert_all_target1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('numserv') 25 | 26 | child.expect('Waiting for input.') 27 | 28 | child.sendline('hundred') 29 | child.expect('100') 30 | 31 | child.livepatch('.libs/libhundreds_livepatch1.so') 32 | 33 | child.sendline('hundred') 34 | child.expect('200', reject='100') 35 | 36 | child.livepatch('.libs/libhundreds_livepatch2.so', revert_lib="target") 37 | 38 | child.sendline('hundred') 39 | child.expect('300', reject=['100', '200']) 40 | 41 | child.livepatch('.libs/libhundreds_livepatch1.so') 42 | 43 | child.sendline('hundred') 44 | child.expect('200', reject=['100', '300']) 45 | 46 | child.close(force=True) 47 | exit(0) 48 | -------------------------------------------------------------------------------- /tests/revert_all_target2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('numserv') 25 | 26 | child.expect('Waiting for input.') 27 | 28 | child.sendline('hundred') 29 | child.expect('100') 30 | 31 | child.livepatch('.libs/libhundreds_livepatch1.so') 32 | 33 | child.sendline('hundred') 34 | child.expect('200', reject='100') 35 | 36 | child.livepatch(revert_lib="target", sanity=False) 37 | 38 | child.sendline('hundred') 39 | child.expect('200', reject='100') 40 | 41 | child.close(force=True) 42 | exit(0) 43 | -------------------------------------------------------------------------------- /tests/revert_and_patch.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('numserv') 25 | 26 | child.expect('Waiting for input.') 27 | 28 | child.sendline('hundred') 29 | child.expect('100') 30 | 31 | child.livepatch('.libs/libhundreds_livepatch1.so') 32 | 33 | child.sendline('hundred') 34 | child.expect('200', reject='100') 35 | 36 | child.livepatch('.libs/libhundreds_livepatch2.so') 37 | 38 | child.sendline('hundred') 39 | child.expect('300', reject=['100', '200']) 40 | 41 | child.livepatch(revert_lib="libhundreds.so.0") 42 | 43 | child.sendline('hundred') 44 | child.expect('100', reject=['200', '300', '400']); 45 | 46 | child.livepatch('.libs/libhundreds_livepatch3.so') 47 | 48 | child.sendline('hundred') 49 | child.expect('400', reject=['100', '200', '300']) 50 | 51 | child.close(force=True) 52 | exit(0) 53 | -------------------------------------------------------------------------------- /tests/revert_with_invalid.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('numserv') 25 | 26 | child.expect('Waiting for input.') 27 | 28 | child.sendline('hundred') 29 | child.expect('100') 30 | 31 | child.livepatch('.libs/libhundreds_livepatch1.so') 32 | 33 | child.sendline('hundred') 34 | child.expect('200', reject='100') 35 | 36 | # Now try to patch a wrong file but revert all patches associated with 37 | # libhundred. If there is a fail on apply and revert-all is specified, 38 | # it shoudn't revert the livepatches. That could imply in unsecure 39 | # code being run. 40 | 41 | try: 42 | child.livepatch('.libs/libnonexistent_livepatch1.so', revert_lib="libhundreds.so.0", sanity=False) 43 | except: 44 | pass 45 | 46 | child.sendline('hundred') 47 | child.expect('200', reject='100') 48 | exit(0) 49 | -------------------------------------------------------------------------------- /tests/seccomp_disable.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | import sys 24 | import os 25 | 26 | if os.geteuid() == 0: 27 | child = testsuite.spawn('block_mprotect ./numserv') 28 | else: 29 | print("Test not running as root.", file=sys.stdout) 30 | exit(77) # Skip test 31 | 32 | child.expect('Waiting for input.') 33 | 34 | child.sendline('dozen') 35 | child.expect('12'); 36 | 37 | child.sendline('hundred') 38 | child.expect('100'); 39 | 40 | # Now lets try to load a livepatch that would make seccomp complain. 41 | child.livepatch('.libs/libsecdis_livepatch1.so', disable_seccomp=True) 42 | 43 | # See if the process survived. 44 | child.sendline('dozen') 45 | child.expect('13', reject='12'); 46 | 47 | child.close(force=True) 48 | exit(0) 49 | -------------------------------------------------------------------------------- /tests/stress.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define NUM_PROCESSES 4000 8 | 9 | int value(void); 10 | 11 | typedef enum 12 | { 13 | NONE = 0, 14 | READY, 15 | LIVEPATCHED, 16 | } state_t; 17 | 18 | int 19 | child_main(volatile state_t *state) 20 | { 21 | *state = READY; 22 | 23 | while (value()) { 24 | sleep(1); 25 | } 26 | 27 | *state = LIVEPATCHED; 28 | return 0; 29 | } 30 | 31 | int 32 | main(void) 33 | { 34 | pid_t pids[NUM_PROCESSES]; 35 | volatile state_t *states; 36 | states = mmap(NULL, NUM_PROCESSES * sizeof(state_t), PROT_READ | PROT_WRITE, 37 | MAP_SHARED | MAP_ANONYMOUS, -1, 0); 38 | 39 | for (int i = 0; i < NUM_PROCESSES; i++) { 40 | states[i] = NONE; 41 | pids[i] = fork(); 42 | 43 | if (pids[i] == 0) { 44 | /* Child. */ 45 | return child_main(&states[i]); 46 | } 47 | } 48 | 49 | for (int i = 0; i < NUM_PROCESSES; i++) { 50 | while (states[i] != READY) 51 | usleep(1000); 52 | } 53 | 54 | puts("Processes launched"); 55 | 56 | for (int i = 0; i < NUM_PROCESSES; i++) { 57 | while (states[i] != LIVEPATCHED) 58 | usleep(1000); 59 | } 60 | 61 | for (int i = 0; i < NUM_PROCESSES; i++) { 62 | int wstatus; 63 | waitpid(pids[i], &wstatus, 0); 64 | 65 | if (WIFEXITED(wstatus)) { 66 | int r = WEXITSTATUS(wstatus); 67 | if (r) { 68 | printf("Process %d returned non-zero: %d\n", pids[i], r); 69 | } 70 | } 71 | else { 72 | printf("Process %d ended without calling exit\n", pids[i]); 73 | } 74 | } 75 | 76 | munmap((void *)states, NUM_PROCESSES * sizeof(state_t)); 77 | puts("Processes finished"); 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /tests/stress.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # This file is part of libpulp. 4 | # 5 | # libpulp is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU Lesser General Public 7 | # License as published by the Free Software Foundation; either 8 | # version 2.1 of the License, or (at your option) any later version. 9 | # 10 | # libpulp is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # Lesser General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with libpulp. If not, see . 17 | 18 | # This test stress out the ulp tool when multiple processes are running. 19 | 20 | import sys 21 | import testsuite 22 | import subprocess 23 | 24 | child = testsuite.spawn('stress') 25 | child.expect("Processes launched") 26 | 27 | testsuite.childless_livepatch(wildcard='.libs/libstress_livepatch1.so', verbose=False, timeout=120) 28 | 29 | child.expect("Processes finished", reject=['returned non-zero']) 30 | child.close(force=True) 31 | -------------------------------------------------------------------------------- /tests/syscall_restart.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('syscall_restart') 25 | 26 | child.expect('Waiting for input.') 27 | 28 | # After printing the greeting message, the target process makes a call 29 | # to fgets, which calls the read syscall. Applying a live patch will 30 | # interrupt the syscall. 31 | child.livepatch('.libs/libparameters_livepatch1.so') 32 | 33 | # Send a newline, which should be received by the read syscall if it has 34 | # been successfully restarted by libpulp. If the syscall has not been 35 | # restarted, the child program will exit without printing anything. 36 | child.sendline('') 37 | child.expect('8-7-6-5-4-3-2-1'); 38 | child.expect('10.0-9.0-8.0-7.0-6.0-5.0-4.0-3.0-2.0-1.0'); 39 | 40 | child.close(force=True) 41 | exit(0) 42 | -------------------------------------------------------------------------------- /tests/tempfiles.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2022 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | import os 24 | 25 | # This test checks if ulp tool left temporary files behind. 26 | errno = 0 27 | tmp_list = os.listdir("/tmp/") 28 | 29 | for fname in tmp_list: 30 | if fname.startswith("ulp-") == True: 31 | # Flag error and remove any temp file we are left, so it does not 32 | # contaminate next test run. 33 | errno = 1 34 | os.remove("/tmp/" + fname) 35 | 36 | exit(errno) 37 | -------------------------------------------------------------------------------- /tests/terminal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | int 29 | main(int argc, char **argv, char **envp) 30 | { 31 | int pid; 32 | int status; 33 | 34 | if (argc < 2) { 35 | printf("Usage: %s .\n", argv[0]); 36 | return 1; 37 | } 38 | 39 | /* Signal readiness. */ 40 | printf("Parent ready\n"); 41 | fflush(stdout); 42 | 43 | /* Mimic a terminal by forking a new process and waiting for it. */ 44 | if ((pid = fork())) { 45 | if (waitpid(pid, &status, WUNTRACED | WCONTINUED) == -1) 46 | perror("terminal"); 47 | if (WIFSTOPPED(status)) 48 | printf("Child stopped with %d.\n", WSTOPSIG(status)); 49 | if (WIFCONTINUED(status)) 50 | printf("Child continued.\n"); 51 | return 7; 52 | } 53 | else 54 | execve(argv[1], argv, envp); 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /tests/textrel.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2025 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import re 23 | import testsuite 24 | import subprocess 25 | 26 | # Make sure libpulp is built without TEXTREL. 27 | 28 | command = ['readelf', '-d', testsuite.libpulp_path] 29 | try: 30 | output = subprocess.check_output(command, timeout=10, stderr=subprocess.STDOUT) 31 | textrel = re.search('TEXTREL', output.decode()) 32 | if not textrel: 33 | exit(0) 34 | 35 | except subprocess.TimeoutExpired: 36 | print('readelf timeout') 37 | exit(77) 38 | 39 | exit(1) 40 | -------------------------------------------------------------------------------- /tests/tls.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2021 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn(testsuite.testname) 25 | 26 | child.expect('Original TLS banner') 27 | child.expect('Banner changed from thread_func: 0') 28 | child.expect('Banner changed from thread_func: 1') 29 | 30 | child.livepatch('.libs/libtls_livepatch1.so') 31 | 32 | child.sendline('') 33 | child.expect('String from live patch', 34 | reject=['String from thread_func: 0', 35 | 'String from thread_func: 1', 36 | 'Live patch data references not initialized']) 37 | 38 | child.close(force=True) 39 | exit(0) 40 | -------------------------------------------------------------------------------- /tests/visibility.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2024 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | void *get_address(void); 26 | 27 | int main(void) 28 | { 29 | while (1) { 30 | puts("Press ENTER to continue"); 31 | getchar(); 32 | const char *string = get_address(); 33 | puts(string); 34 | } 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /tests/visibility.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # libpulp - User-space Livepatching Library 4 | # 5 | # Copyright (C) 2020-2024 SUSE Software Solutions GmbH 6 | # 7 | # This file is part of libpulp. 8 | # 9 | # libpulp is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | # 14 | # libpulp is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with libpulp. If not, see . 21 | 22 | import testsuite 23 | 24 | child = testsuite.spawn('visibility', script=False) 25 | 26 | child.expect('Press ENTER to continue') 27 | child.sendline('') 28 | child.expect('This is a hidden string') 29 | child.expect('Press ENTER to continue') 30 | out = child.livepatch('.libs/libvisibility_livepatch1.so', 31 | sanity=False, capture_tool_output=True) 32 | 33 | child.sendline('') 34 | child.expect('This is a hidden string') 35 | 36 | # Check if we can't apply the above patch. 37 | if out.find('Failure in dlopen') < 0: 38 | child.close(force=True) 39 | exit(1) 40 | 41 | # Now try to apply the patch with strong externalization 42 | child.expect('Press ENTER to continue') 43 | child.livepatch('.libs/libvisibility_livepatch2.so') 44 | 45 | child.sendline('') 46 | child.expect('String from lp This is a hidden string') 47 | 48 | child.close(force=True) 49 | exit(0) 50 | -------------------------------------------------------------------------------- /tools/check.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #ifndef CHECK_H 23 | #define CHECK_H 24 | 25 | struct arguments; 26 | 27 | int run_check(struct arguments *); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /tools/dump.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2017-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #ifndef DUMP_H 23 | #define DUMP_H 24 | 25 | struct arguments; 26 | 27 | int run_dump(struct arguments *); 28 | 29 | #endif /* DUMP_H */ 30 | -------------------------------------------------------------------------------- /tools/elf-extra.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2019-2022 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | /* Extra ELF functions. */ 27 | 28 | Elf_Scn *get_elfscn_by_name(Elf *elf, const char *name); 29 | 30 | Elf_Scn *get_elf_section(Elf *, ElfW(Word) sht_type); 31 | 32 | Elf *load_elf(const char *path, int *fd); 33 | 34 | void unload_elf(Elf **, int *fd); 35 | 36 | int embed_patch_metadata_into_elf(Elf *elfinput, const char *elf_path, 37 | const char *metadata, 38 | const char *section_name); 39 | -------------------------------------------------------------------------------- /tools/insn_queue_tools.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2023 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #ifndef INSNQ_TOOL_H 23 | #define INSNQ_TOOL_H 24 | 25 | struct ulp_process; 26 | 27 | #include "insn_queue.h" 28 | #include 29 | 30 | int insnq_get_version(struct ulp_process *process); 31 | 32 | bool insnq_check_compatibility(struct ulp_process *process); 33 | 34 | int insnq_interpret_from_process(struct ulp_process *); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /tools/livepatchable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2017-2022 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #ifndef LIVEPATCHABLE_H 23 | #define LIVEPATCHABLE_H 24 | 25 | struct arguments; 26 | 27 | int run_livepatchable(struct arguments *); 28 | 29 | #endif /* LIVEPATCHABLE.H */ 30 | -------------------------------------------------------------------------------- /tools/md4.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #define MD4_LENGTH 16 23 | uint8_t *MD4(char *input, uint64_t length); 24 | -------------------------------------------------------------------------------- /tools/messages.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2017-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #ifndef MESSAGES_H 23 | #define MESSAGES_H 24 | 25 | struct arguments; 26 | 27 | int run_messages(struct arguments *); 28 | 29 | #endif /* MESSAGES.H */ 30 | -------------------------------------------------------------------------------- /tools/pcqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef PCQUEUE_H 2 | #define PCQUEUE_H 3 | 4 | #include 5 | #include 6 | 7 | /* Uncoment this if the producer_consumer queue should support multiple 8 | producers and consumers. */ 9 | /* #define MORE_THAN_ONE_ONE */ 10 | 11 | /** A producer-consumer queue. This structure creates a channel in which 12 | two threads can communicate, one by enqueuing elements and another by 13 | dequeuing elements. */ 14 | struct producer_consumer 15 | { 16 | /** Maximum number of elements in this queue. */ 17 | int n; 18 | 19 | /** Position of the last inserted element.*/ 20 | int head; 21 | 22 | /** Position of the oldest element in the queue. */ 23 | int tail; 24 | 25 | /** Semaphore that will block any attempt of dequeuing an element if the 26 | queue is empty. */ 27 | sem_t empty; 28 | 29 | /** Semaphore that will block any attempt of enqueuing an element if the 30 | queue is full. */ 31 | sem_t full; 32 | #ifdef MORE_THAN_ONE_ONE 33 | /** Lock for head & tail. This is unnecessary if there is only one producer 34 | and one consumer. If you wish to support many producers and many 35 | consumers, define MORE_THAN_ONE_ONE. */ 36 | pthread_mutex_t lock; 37 | #endif 38 | 39 | /** The queue buffer. The 0 array element denotes where it starts, but it is 40 | allocated in `producer_consumer_new`. */ 41 | void *elem[0]; 42 | }; 43 | 44 | /** Typedef for a shorthand of struct producer_consumer. */ 45 | typedef struct producer_consumer producer_consumer_t; 46 | 47 | producer_consumer_t *producer_consumer_new(int n); 48 | 49 | int producer_consumer_delete(producer_consumer_t *queue); 50 | 51 | int producer_consumer_enqueue(producer_consumer_t *queue, void *elem); 52 | 53 | void *producer_consumer_dequeue(producer_consumer_t *queue); 54 | 55 | #endif // PCQUEUE_H 56 | -------------------------------------------------------------------------------- /tools/post.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #ifndef POST_H 23 | #define POST_H 24 | 25 | struct arguments; 26 | struct Elf_Scn; 27 | struct Elf; 28 | 29 | struct Elf_Scn *find_section_by_name(struct Elf *, const char *name); 30 | 31 | int run_post(struct arguments *); 32 | 33 | #endif /* POST_H */ 34 | -------------------------------------------------------------------------------- /tools/set_patchable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2020-2023 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #ifndef SET_PATCHABLE_H 23 | #define SET_PATCHABLE_H 24 | 25 | struct arguments; 26 | 27 | int run_set_patchable(struct arguments *); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /tools/trigger.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libpulp - User-space Livepatching Library 3 | * 4 | * Copyright (C) 2017-2021 SUSE Software Solutions GmbH 5 | * 6 | * This file is part of libpulp. 7 | * 8 | * libpulp is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * libpulp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with libpulp. If not, see . 20 | */ 21 | 22 | #ifndef TRIGGER_H 23 | #define TRIGGER_H 24 | 25 | struct arguments; 26 | 27 | int run_trigger(struct arguments *); 28 | 29 | #endif /* TRIGGER_H */ 30 | --------------------------------------------------------------------------------