Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libpulp for openSUSE:Factory checked 
in at 2025-02-25 16:47:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libpulp (Old)
 and      /work/SRC/openSUSE:Factory/.libpulp.new.1873 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libpulp"

Tue Feb 25 16:47:59 2025 rev:8 rq:1248355 version:0.3.11

Changes:
--------
--- /work/SRC/openSUSE:Factory/libpulp/libpulp.changes  2025-02-11 
21:25:37.404729212 +0100
+++ /work/SRC/openSUSE:Factory/.libpulp.new.1873/libpulp.changes        
2025-02-25 16:48:07.984278715 +0100
@@ -1,0 +2,8 @@
+Tue Feb 25 12:20:15 UTC 2025 - Giuliano Belinassi <[email protected]>
+
+- Update package with libpulp-0.3.11:
+  - Detect whenever the process was loaded in a custom starting address.
+  - ulp_stack now allocates multiples of page size.
+  - Fix livepatching of `malloc` in ppc64le (jsc#PED-11850).
+
+-------------------------------------------------------------------

Old:
----
  libpulp-0.3.10.tar.gz

New:
----
  libpulp-0.3.11.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libpulp.spec ++++++
--- /var/tmp/diff_new_pack.Sr9Mci/_old  2025-02-25 16:48:08.592304127 +0100
+++ /var/tmp/diff_new_pack.Sr9Mci/_new  2025-02-25 16:48:08.592304127 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           libpulp
-Version:        0.3.10
+Version:        0.3.11
 Release:        0
 Summary:        Userspace live patching library and tools
 License:        LGPL-2.1-or-later

++++++ libpulp-0.3.10.tar.gz -> libpulp-0.3.11.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libpulp-0.3.10/configure new/libpulp-0.3.11/configure
--- old/libpulp-0.3.10/configure        2025-02-10 21:30:36.000000000 +0100
+++ new/libpulp-0.3.11/configure        2025-02-25 13:12:18.000000000 +0100
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.72 for libpulp 0.3.10.
+# Generated by GNU Autoconf 2.72 for libpulp 0.3.11.
 #
 # Report bugs to <[email protected]>.
 #
@@ -614,8 +614,8 @@
 # Identity of this package.
 PACKAGE_NAME='libpulp'
 PACKAGE_TARNAME='libpulp'
-PACKAGE_VERSION='0.3.10'
-PACKAGE_STRING='libpulp 0.3.10'
+PACKAGE_VERSION='0.3.11'
+PACKAGE_STRING='libpulp 0.3.11'
 PACKAGE_BUGREPORT='[email protected]'
 PACKAGE_URL=''
 
@@ -1420,7 +1420,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-'configure' configures libpulp 0.3.10 to adapt to many kinds of systems.
+'configure' configures libpulp 0.3.11 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1492,7 +1492,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of libpulp 0.3.10:";;
+     short | recursive ) echo "Configuration of libpulp 0.3.11:";;
    esac
   cat <<\_ACEOF
 
@@ -1628,7 +1628,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-libpulp configure 0.3.10
+libpulp configure 0.3.11
 generated by GNU Autoconf 2.72
 
 Copyright (C) 2023 Free Software Foundation, Inc.
@@ -1979,7 +1979,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by libpulp $as_me 0.3.10, which was
+It was created by libpulp $as_me 0.3.11, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -3823,7 +3823,7 @@
 
 # Define the identity of the package.
  PACKAGE='libpulp'
- VERSION='0.3.10'
+ VERSION='0.3.11'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -20219,7 +20219,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by libpulp $as_me 0.3.10, which was
+This file was extended by libpulp $as_me 0.3.11, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -20287,7 +20287,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-libpulp config.status 0.3.10
+libpulp config.status 0.3.11
 configured by $0, generated by GNU Autoconf 2.72,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libpulp-0.3.10/configure.ac 
new/libpulp-0.3.11/configure.ac
--- old/libpulp-0.3.10/configure.ac     2025-02-10 21:24:43.000000000 +0100
+++ new/libpulp-0.3.11/configure.ac     2025-02-25 01:45:32.000000000 +0100
@@ -1,6 +1,6 @@
 #   libpulp - User-space Livepatching Library
 #
-#   Copyright (C) 2020-2024 SUSE Software Solutions GmbH
+#   Copyright (C) 2020-2025 SUSE Software Solutions GmbH
 #
 #   This file is part of libpulp.
 #
@@ -17,7 +17,7 @@
 #   You should have received a copy of the GNU General Public License
 #   along with libpulp.  If not, see <http://www.gnu.org/licenses/>.
 
-AC_INIT([libpulp],[0.3.10],[[email protected]])
+AC_INIT([libpulp],[0.3.11],[[email protected]])
 
 # Keep most generated files under the config directory.
 AC_CONFIG_AUX_DIR([config])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libpulp-0.3.10/include/arch/powerpc64le/arch_common.h 
new/libpulp-0.3.11/include/arch/powerpc64le/arch_common.h
--- old/libpulp-0.3.10/include/arch/powerpc64le/arch_common.h   2025-01-30 
21:56:54.000000000 +0100
+++ new/libpulp-0.3.11/include/arch/powerpc64le/arch_common.h   2025-02-25 
01:45:18.000000000 +0100
@@ -4,9 +4,6 @@
 /** Offset of TLS pointer.  */
 #define TLS_DTV_OFFSET 0x8000
 
-/* Program load bias, which can be recovered by running `ld --verbose`.  */
-#define EXECUTABLE_START         0x10000000UL
-
 /* The Red zone.  */
 #define RED_ZONE_LEN             512
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libpulp-0.3.10/include/arch/x86_64/arch_common.h 
new/libpulp-0.3.11/include/arch/x86_64/arch_common.h
--- old/libpulp-0.3.10/include/arch/x86_64/arch_common.h        2024-10-17 
21:20:16.000000000 +0200
+++ new/libpulp-0.3.11/include/arch/x86_64/arch_common.h        2025-02-25 
01:45:18.000000000 +0100
@@ -22,9 +22,6 @@
 /** Set the GLOBAL ENTRYPOINT REGISTER, which in x86_64 doesn't exist.  */
 #define SET_GLOBAL_ENTRYPOINT_REG(reg, val)
 
-/** Program load bias, which can be recovered by running `ld --verbose`.  */
-#define EXECUTABLE_START      0x400000UL
-
 /** The red zone.  */
 #define RED_ZONE_LEN          128
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libpulp-0.3.10/lib/arch/powerpc64le/patch.c 
new/libpulp-0.3.11/lib/arch/powerpc64le/patch.c
--- old/libpulp-0.3.10/lib/arch/powerpc64le/patch.c     2025-01-30 
21:56:54.000000000 +0100
+++ new/libpulp-0.3.11/lib/arch/powerpc64le/patch.c     2025-02-25 
01:45:18.000000000 +0100
@@ -256,17 +256,18 @@
      caller), so just assert it here.  */
   libpulp_assert(ulp_stack[ULP_STACK_REAL_SIZE] <= 
ulp_stack[ULP_STACK_USED_SIZE]);
 
+  /* NOTE: be careful with the functions we call here.  If we call a certain
+     function here, then we may have problems livepatching it.  */
+
   /* Storage depleted, allocate a new stack.  */
   unsigned long old_size = ulp_stack[ULP_STACK_REAL_SIZE];
 
-  /* Setup new size.  */
-  ulp_stack[ULP_STACK_REAL_SIZE] += 32;
+  /* Setup new stack size. Increase by PAGESIZE to be optimal */
+  ulp_stack[ULP_STACK_REAL_SIZE] += sysconf(_SC_PAGESIZE);
   ulp_stack[ULP_STACK_REAL_SIZE] *= 2;
 
   void *old = (void *)ulp_stack[ULP_STACK_PTR];
 
-  DEBUG("thread %lu: expanding stack to %lu bytes", pthread_self(), 
ulp_stack[ULP_STACK_REAL_SIZE]);
-
   /* Allocate buffer for our stack.  */
   void *new = mmap(NULL, ulp_stack[ULP_STACK_REAL_SIZE],
                    PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -280,7 +281,17 @@
 
   /* In case we have a previous allocated buffer, then copy this.  */
   if (old != NULL) {
-    memcpy(new, old, old_size);
+
+    /* We can't use memcpy here, hence do our thing.  */
+    unsigned char *restrict oldp = old;
+    unsigned char *restrict newp = new;
+    unsigned long s = old_size;
+
+    while (s > 0) {
+      *newp++ = *oldp++;
+      s--;
+    }
+
     munmap(old, old_size);
     old = NULL;
   }
@@ -288,6 +299,8 @@
   ulp_stack[ULP_STACK_PTR] = (unsigned long) new;
   libpulp_assert(ulp_stack[ULP_STACK_PTR] != 0L);
 
+  DEBUG("thread %lu: expanded stack to %lu bytes", pthread_self(), 
ulp_stack[ULP_STACK_REAL_SIZE]);
+
   /* Setup destructor for mmap memory, so we don't leak memory when a thread
      is destroyed.  */
   pthread_once(&ulp_once_control, ulp_pthread_key_init);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libpulp-0.3.10/tests/notes.py 
new/libpulp-0.3.11/tests/notes.py
--- old/libpulp-0.3.10/tests/notes.py   2025-02-10 22:51:59.000000000 +0100
+++ new/libpulp-0.3.11/tests/notes.py   2025-02-25 01:45:18.000000000 +0100
@@ -22,11 +22,6 @@
 import testsuite
 import platform
 
-if platform.processor() == 'ppc64le':
-  # Skip this test on ppc64le, as for some reason the build id of the
-  # main process is not found by libpulp.
-  exit(77)
-
 child = testsuite.spawn('notes')
 
 child.expect('Ready.')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libpulp-0.3.10/tools/introspection.c 
new/libpulp-0.3.11/tools/introspection.c
--- old/libpulp-0.3.10/tools/introspection.c    2025-02-05 21:01:07.000000000 
+0100
+++ new/libpulp-0.3.11/tools/introspection.c    2025-02-25 01:45:18.000000000 
+0100
@@ -517,6 +517,74 @@
 }
 #endif // ENABLE_DLINFO_CACHE
 
+
+/** @brief Parsers /proc/pid/maps to figure the EHDR mapping of dynamic object.
+ *
+ * This function reads the /proc/pid/maps to find the EHDR mapping of the
+ * dynamic object.  Usually this can be found by looking at the link_map.l_addr
+ * field, however for the main process this information is not available there.
+ *
+ * @param p   process to analyze.
+ * @param obj Object representing a library, or the main program itself, from 
p.
+ *
+ * @return 0 on success, anything else on failure.
+ */
+ElfW(Addr)
+get_ehdr_addr(struct ulp_process *p, struct ulp_dynobj *obj)
+{
+  if (obj->link_map.l_addr) {
+    return obj->link_map.l_addr;
+  }
+
+  const char *format_str = "/proc/%d/maps";
+  char filename[strlen(format_str) + 10];
+  sprintf(filename, format_str, p->pid);
+
+  FILE *maps = fopen(filename, "r");
+  if (maps == NULL) {
+    DEBUG("error: unable to open maps.");
+    return 0;
+  }
+
+  char *line = NULL;
+  size_t len = 0;
+  ssize_t n;
+
+  while ((n = getline(&line, &len, maps)) != -1) {
+    const char *str_addr1  =    strtok(line, "-");
+    /* clang-format off */
+
+ /* const char *str_addr2  = */ strtok(NULL, " ");
+ /* const char *str_perm   = */ strtok(NULL, " ");
+ /* const char *str_offset = */ strtok(NULL, " ");
+ /* const char *str_dev    = */ strtok(NULL, " ");
+ /* const char *str_inode  = */ strtok(NULL, " ");
+    const char *str_path   =    strtok(NULL, " ");
+
+    /* clang-format on */
+
+    /* Get the basename (last string after all /) and remove the newline there
+       if it exists.  */
+    char *bin_name = (char *) get_basename(str_path);
+    unsigned bin_len = strlen(bin_name);
+    if (bin_name[bin_len-1] == '\n') {
+      bin_name[bin_len-1] = '\0';
+    }
+
+    if (strcmp(bin_name, p->dynobj_main->filename) == 0) {
+      ElfW(Addr) addr1 = strtoul(str_addr1, NULL, 16);
+      fclose(maps);
+      FREE_AND_NULLIFY(line);
+      return addr1;
+    }
+  }
+
+  fclose(maps);
+  FREE_AND_NULLIFY(line);
+
+  return 0UL;
+}
+
 /** @brief Parses ELF headers of dynobj `obj` from process with pid `pid`.
  *
  * This function read the remote process memory to locate the following
@@ -533,8 +601,12 @@
  * @return 0 on success, anything else on failure.
  */
 int
-parse_dynobj_elf_headers(int pid, struct ulp_dynobj *obj)
+parse_dynobj_elf_headers(struct ulp_process *p, struct ulp_dynobj *obj)
 {
+  pid_t pid = p->pid;
+
+  ElfW(Addr) l_addr = 0;
+
   ElfW(Addr) ehdr_addr = 0;
   ElfW(Ehdr) ehdr;
   ElfW(Addr) phdr_addr = 0;
@@ -559,18 +631,10 @@
     return ENOLINKMAP;
   }
 
-  /* l_addr holds the pointer to the ELF header.  */
-  ehdr_addr = obj->link_map.l_addr;
+  l_addr = obj->link_map.l_addr;
+  ehdr_addr = get_ehdr_addr(p, obj);
 
-  /* Read ELF header from remote process.  */
-  if (ehdr_addr == 0) {
-    /* If l_addr is zero, it means that there is no load bias.  In that case,
-     * the elf address is on address 0x400000 on x86_64.  */
-    ret = read_memory((char *)&ehdr, sizeof(ehdr), pid, EXECUTABLE_START);
-  }
-  else {
-    ret = read_memory((char *)&ehdr, sizeof(ehdr), pid, ehdr_addr);
-  }
+  ret = read_memory((char *)&ehdr, sizeof(ehdr), pid, ehdr_addr);
   if (ret != 0) {
     DEBUG("Unable to read ELF header from process %d\n", pid);
     return ETARGETHOOK;
@@ -584,8 +648,6 @@
 
   /* Get first process header address.  */
   phdr_addr = ehdr_addr + ehdr.e_phoff;
-  if (ehdr_addr == 0)
-    phdr_addr += EXECUTABLE_START;
 
   /* Iterate over each process header.  */
   for (i = 0; i < ehdr.e_phnum; i++) {
@@ -602,7 +664,7 @@
     /* Look for the dynamic section.  */
     if (phdr.p_type == PT_DYNAMIC && !pt_dynamic_ran) {
       ElfW(Dyn) dyn;
-      ElfW(Addr) dyn_addr = ehdr_addr + phdr.p_paddr;
+      ElfW(Addr) dyn_addr = l_addr + phdr.p_vaddr;
 
       /* Iterate over each tag in this section.  */
       do {
@@ -647,8 +709,7 @@
     }
     else if (phdr.p_type == PT_NOTE) {
       /* We are after the build id.  */
-
-      ElfW(Addr) note_addr = ehdr_addr + phdr.p_paddr;
+      ElfW(Addr) note_addr = l_addr + phdr.p_vaddr;
       unsigned sec_size = phdr.p_memsz;
       ElfW(Addr) note_addr_end = note_addr + sec_size;
 
@@ -1115,7 +1176,7 @@
     return ret;
   }
 
-  parse_dynobj_elf_headers(process->pid, obj);
+  parse_dynobj_elf_headers(process, obj);
 
   return 0;
 }
@@ -1158,7 +1219,7 @@
   /* Pointers to linux-vdso.so are invalid, so skip this library.  */
   if (strcmp(obj->filename, "linux-vdso.so.1") &&
       strcmp(obj->filename, "linux-vdso64.so.1"))
-    parse_dynobj_elf_headers(pid, obj);
+    parse_dynobj_elf_headers(process, obj);
 
   /* Only libpulp.so should have those symbols exported.  */
   if (strstr(libname, "libpulp.so")) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libpulp-0.3.10/tools/introspection.h 
new/libpulp-0.3.11/tools/introspection.h
--- old/libpulp-0.3.10/tools/introspection.h    2024-10-17 21:20:16.000000000 
+0200
+++ new/libpulp-0.3.11/tools/introspection.h    2025-02-25 01:45:18.000000000 
+0100
@@ -205,6 +205,8 @@
   return get_basename(process->dynobj_main->filename);
 }
 
+ElfW(Addr) get_ehdr_addr(struct ulp_process *, struct ulp_dynobj *);
+
 ulp_error_t get_libpulp_error_state_remote(struct ulp_process *);
 
 const char *adjust_prefix_for_chroot(struct ulp_process *,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libpulp-0.3.10/tools/patches.c 
new/libpulp-0.3.11/tools/patches.c
--- old/libpulp-0.3.10/tools/patches.c  2024-10-17 21:20:16.000000000 +0200
+++ new/libpulp-0.3.11/tools/patches.c  2025-02-25 01:45:18.000000000 +0100
@@ -451,14 +451,15 @@
  *
  * @param patch  The list of patches loaded in the target process.
  * @param obj    The libary object.
- * @param pid    Pid of target process.
+ * @param p      The process to analyze.
  *
  * @return       True if livepatchable, False if not.
  */
 static bool
 is_library_livepatchable(struct ulp_applied_patch *patch,
-                         struct ulp_dynobj *obj, pid_t pid)
+                         struct ulp_dynobj *obj, struct ulp_process *p)
 {
+  pid_t pid = p->pid;
   int i, ret;
   if (has_livepatch_loaded(patch, obj->filename))
     return true;
@@ -469,15 +470,9 @@
     goto detach_process;
   }
 
-  ElfW(Addr) ehdr_addr = obj->link_map.l_addr;
+  ElfW(Addr) ehdr_addr = get_ehdr_addr(p, obj);
   ElfW(Addr) dynsym_addr = obj->dynsym_addr;
 
-  if (ehdr_addr == 0) {
-    /* If l_addr is zero, it means that there is no load bias.  In that case,
-     * the elf address is on address 0x400000 on x86_64.  */
-    ehdr_addr = EXECUTABLE_START;
-  }
-
   /* FIXME: Some applications take a very long time to decide if library is
      livepatchable because the library has a lot of symbols.  In this case we
      limit the number of symbols to read to a constant value.  Statistics shows
@@ -561,7 +556,7 @@
   if (!object_item)
     printf("    (none)\n");
   while (object_item) {
-    if (is_library_livepatchable(patch, object_item, pid)) {
+    if (is_library_livepatchable(patch, object_item, process)) {
       printf("    in %s", object_item->filename);
       if (print_buildid)
         printf(" (%s)", buildid_to_string(object_item->build_id));

Reply via email to