nfs-utils: rpc.svcgssd segmentation fault in nss_gss_princ_to_ids()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello!

I hope I have found the right place to report this.

I have recently upgraded from nfs-utils-1.3.4 to nfs-utils-2.3.1 on a Gentoo
Linux (hardened) system. After this upgrade the rpc.svcgssd crashes on my
kerberized NFS server each time a client tries to mount an NFS export.

The crash is a segmentation fault:

  kernel: rpc.svcgssd[19772]: segfault at 8 ip 00007f6b6aafa98c sp 00007fff2ca8ce30 error 4 in nsswitch.so[7f6b6aaf9000+7000]

The call stack leading up to this looks as follows:

  (gdb) 
  Program received signal SIGSEGV, Segmentation fault.
  nss_gss_princ_to_ids (secname=<optimized out>, princ=0x55cabc7d9940 "nfs/host.example.domain@xxxxxxxxxxxx", 
      uid=0x7ffca550e0d8, gid=0x7ffca550e0dc, UNUSED_ex=<optimized out>) at nss.c:415
  415	nss.c: No such file or directory.

  (gdb) bt
  #0  nss_gss_princ_to_ids (secname=<optimized out>, princ=0x55cabc7d9940 "nfs/host.example.domain@xxxxxxxxxxxx", 
      uid=0x7ffca550e0d8, gid=0x7ffca550e0dc, UNUSED_ex=<optimized out>) at nss.c:415
  #1  0x00007f6c97cc2886 in nfs4_gss_princ_to_ids (secname=secname@entry=0x55caba8e2030 <m2f+16> "krb5", 
      princ=princ@entry=0x55cabc7d9940 "nfs/host.example.domain@xxxxxxxxxxxx", uid=0x7ffca550e0d8, uid@entry=0x1, 
      gid=0x7ffca550e0dc, gid@entry=0x7f6c95cf3a76 <conf_get_section+86>) at libnfsidmap.c:682
  #2  0x000055caba6da138 in get_ids (cred=0x7ffca550e038, mech=<optimized out>, client_name=<optimized out>)
      at svcgssd_proc.c:251
  #3  handle_nullreq (f=f@entry=3) at svcgssd_proc.c:407
  #4  0x000055caba6d996a in gssd_run () at svcgssd_main_loop.c:91
  #5  0x000055caba6d83b1 in main (argc=1, argv=<optimized out>) at svcgssd.c:211

  (gdb) p realms
  $1 = (struct conf_list *) 0x0

I debugged this a bit and strange things came about. There seem to be
duplicate instances of the local_realms variable in the
support/nfsidmap/nfsidmap_common.c compilation unit:

  gdb --args /usr/sbin/rpc.svcgssd  -f
  (gdb) start
  Temporary breakpoint 1 at 0x2170: file svcgssd.c, line 94.
  Starting program: /usr/sbin/rpc.svcgssd -f
  Temporary breakpoint 1, main (argc=2, argv=0x7fffffffddc8) at svcgssd.c:94
  94	svcgssd.c: No such file or directory.

  (gdb) b get_local_realms 
  Breakpoint 2 at 0x7ffff7bd1fc0: file nfsidmap_common.c, line 30.
  (gdb) c
  Continuing.

  Breakpoint 2, get_local_realms () at nfsidmap_common.c:30
  30	nfsidmap_common.c: No such file or directory.
  (gdb) disassemble 
  Dump of assembler code for function get_local_realms:
  => 0x00007ffff5e0b4a0 <+0>:	sub    $0x1038,%rsp
     0x00007ffff5e0b4a7 <+7>:	orq    $0x0,(%rsp)
     0x00007ffff5e0b4ac <+12>:	add    $0x1020,%rsp
     0x00007ffff5e0b4b3 <+19>:	mov    %fs:0x28,%rax
     0x00007ffff5e0b4bc <+28>:	mov    %rax,0x8(%rsp)
     0x00007ffff5e0b4c1 <+33>:	xor    %eax,%eax
     0x00007ffff5e0b4c3 <+35>:	mov    0x204f7e(%rip),%rax        # 0x7ffff6010448 <local_realms>
     0x00007ffff5e0b4ca <+42>:	mov    0x8(%rsp),%rdx
     0x00007ffff5e0b4cf <+47>:	xor    %fs:0x28,%rdx
     0x00007ffff5e0b4d8 <+56>:	jne    0x7ffff5e0b4df <get_local_realms+63>
     0x00007ffff5e0b4da <+58>:	add    $0x18,%rsp
     0x00007ffff5e0b4de <+62>:	retq   
     0x00007ffff5e0b4df <+63>:	callq  0x7ffff5e0a250 <__stack_chk_fail@plt>

  End of assembler dump.

  (gdb) p local_realms
  $1 = (struct conf_list *) 0x555555764300
  (gdb) p &local_realms
  $2 = (struct conf_list **) 0x7ffff7dd7208 <local_realms>

  (gdb) x /1g 0x7ffff6010448
  0x7ffff6010448 <local_realms>:	0x0000000000000000

So there's one instance of the variable that was actually assigned the
expected data. And there's another one that is at NULL and returned from
get_local_realms().

This is related to the "#pragma GCC visibility push(hidden)" in the
compilation unit. Moving it after the local_realms variable declaration fixes
the issue. I've attached a patch that does just this.

I am not quite sure whether this is a compiler issue or an invalid use of the
visibility hidden pragma. The compiler used is:

  gcc (Gentoo Hardened 6.4.0-r1 p1.3) 6.4.0

Please advise.

Regards

Matthias
commit b1935a982aa68890ffe888381f7905f57c6b055d
Author: Matthias Gerstner <Matthias.Gerstner@xxxxxxxxxx>
Date:   Tue Feb 20 23:33:18 2018 +0100

    get_local_realms: work around strange duplication of local_realms
    
    The hidden visibility seems to cause the get_local_realms() function to
    return a NULL pointer, although the local_realms global variable is
    actually assigned. Assembler code shows there are two instances of this
    variable around, one set to NULL, the other to the expected value.
    
    This happened on Gentoo Hardened with gcc 4.6.0-r1.

diff --git a/support/nfsidmap/nfsidmap_common.c b/support/nfsidmap/nfsidmap_common.c
index 891c855..e5c33a8 100644
--- a/support/nfsidmap/nfsidmap_common.c
+++ b/support/nfsidmap/nfsidmap_common.c
@@ -19,13 +19,13 @@
 #include "nfsidmap_plugin.h"
 #include "conffile.h"
 
-#pragma GCC visibility push(hidden)
-
 int reformat_group = 0;
 int no_strip = 0;
 
 struct conf_list *local_realms;
 
+#pragma GCC visibility push(hidden)
+
 struct conf_list *get_local_realms(void)
 {
 	return local_realms;

Attachment: signature.asc
Description: Digital signature


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux