diff mbox series

[pseudo] linkat: Avoid a segmentation fault

Message ID 20260424150431.101072-1-pkj@axis.com
State New
Headers show
Series [pseudo] linkat: Avoid a segmentation fault | expand

Commit Message

Peter Kjellerstedt April 24, 2026, 3:04 p.m. UTC
This avoids the following segmentation fault (in useradd):

  Program terminated with signal SIGSEGV, Segmentation fault.
  #0  0x0000795b22562f49 in wrap_linkat (olddirfd=olddirfd@entry=-100,
      oldname=oldname@entry=0x6016835f1fb0 "/etc/group.3167327",
      newdirfd=newdirfd@entry=-100,
      newname=newname@entry=0x6016835f1fd0 "/etc/group.lock",
      flags=flags@entry=0) at ports/unix/guts/linkat.c:37
  37              oldpath = oldname;
  (gdb) bt
  #0  0x0000795b22562f49 in wrap_linkat (olddirfd=olddirfd@entry=-100,
      oldname=oldname@entry=0x6016835f1fb0 "/etc/group.3167327",
      newdirfd=newdirfd@entry=-100,
      newname=newname@entry=0x6016835f1fd0 "/etc/group.lock",
      flags=flags@entry=0) at ports/unix/guts/linkat.c:37
  #1  0x0000795b2257b95c in wrap_link (newname=0x6016835f1fd0 "/etc/group.lock",
      oldname=0x6016835f1fb0 "/etc/group.3167327") at ports/unix/guts/link.c:17
  #2  link (oldname=0x6016835f1fb0 "/etc/group.3167327",
      newname=0x6016835f1fd0 "/etc/group.lock") at pseudo_wrapfuncs.c:8968
  #3  0x00006016814d45dd in do_lock_file (file=file@entry=0x6016835f1fb0 "/etc/group.3167327",
      lock=lock@entry=0x6016835f1fd0 "/etc/group.lock", log=log@entry=true)
      at ../../sources/shadow-4.19.4/lib/commonio.c:167
  #4  0x00006016814d4e88 in commonio_lock_nowait (db=db@entry=0x6016814df9e0 <group_db>,
      log=log@entry=true) at ../../sources/shadow-4.19.4/lib/commonio.c:373
  #5  0x00006016814d4f09 in commonio_lock (db=db@entry=0x6016814df9e0 <group_db>)
      at ../../sources/shadow-4.19.4/lib/commonio.c:413
  #6  0x00006016814cfc9a in gr_lock () at ../../sources/shadow-4.19.4/lib/groupio.c:141
  #7  0x00006016814c981f in open_group_files (process_selinux=process_selinux@entry=false)
      at ../../sources/shadow-4.19.4/src/useradd.c:1797
  #8  0x00006016814cacdc in open_files (process_selinux=process_selinux@entry=false)
      at ../../sources/shadow-4.19.4/src/useradd.c:1759
  #9  0x00006016814cc388 in main (argc=<optimized out>, argv=<optimized out>)
      at ../../sources/shadow-4.19.4/src/useradd.c:2585
  (gdb) l
  32              if (olddirfd != AT_FDCWD || newdirfd != AT_FDCWD) {
  33                      errno = ENOSYS;
  34                      return -1;
  35              }
  36      #endif
  37              oldpath = oldname;
  38              if (pseudo_chroot_len && strncmp(oldpath, pseudo_chroot, pseudo_chroot_len) &&
  39                      oldpath[pseudo_chroot_len] == '/') {
  40                      oldpath += pseudo_chroot_len;
  41              }
  (gdb) p oldname
  $1 = 0x6016835f1fb0 "/etc/group.3167327"
  (gdb) p oldpath
  $2 = 0x6016835f1fb0 "/etc/group.3167327"
  (gdb) p pseudo_chroot_len
  $3 = 91

The above code (on line 38) is supposed to check if oldpath is prefixed
by pseudo_chroot, but instead it checks the opposite, and then the check
for the slash on the next line is made outside oldpath if it is shorter
than pseudo_chroot.

Signed-off-by: Peter Kjellerstedt <peter.kjellerstedt@axis.com>
---
 ports/unix/guts/linkat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/ports/unix/guts/linkat.c b/ports/unix/guts/linkat.c
index e1712a9..60fbf63 100644
--- a/ports/unix/guts/linkat.c
+++ b/ports/unix/guts/linkat.c
@@ -35,7 +35,7 @@ 
 	}
 #endif
 	oldpath = oldname;
-	if (pseudo_chroot_len && strncmp(oldpath, pseudo_chroot, pseudo_chroot_len) &&
+	if (pseudo_chroot_len && !strncmp(oldpath, pseudo_chroot, pseudo_chroot_len) &&
 		oldpath[pseudo_chroot_len] == '/') {
 		oldpath += pseudo_chroot_len;
 	}