Uploaded image for project: 'RHEL'
  1. RHEL
  2. RHEL-19731

SIGSEGV using hierarchical map entries on reload with autofs-5.1.4-109

    • Icon: Bug Bug
    • Resolution: Done-Errata
    • Icon: Undefined Undefined
    • rhel-9.4
    • rhel-9.3.0
    • autofs
    • None
    • autofs-5.1.7-58.el9
    • None
    • Important
    • rhel-sst-filesystems
    • ssg_filesystems_storage_and_HA
    • 18
    • 20
    • 2
    • QE ack, Dev ack
    • False
    • Hide

      None

      Show
      None
    • None
    • Red Hat Enterprise Linux
    • None
    • None

      Hierarchical mount entries on autofs-5.1.4-109.el8.x86_64 causes crashes on reload (systemctl reload).

        1. Reproducer :

      [root@rhel8 ~]# rpm -q autofs
      autofs-5.1.4-109.el8.x86_64

      // Using bind mounts :

      [root@rhel8 ~]# grep -v ^# /etc/auto.direct
      /required \
      / localhost:/playground2 \
      /sub1 localhost:/playground3 \
      /sub2 localhost:/playground4

      // trigger the mount :

      [root@rhel8 ~]# grep requi /proc/mounts
      /etc/auto.direct /required autofs rw,relatime,fd=13,pgrp=33021,timeout=300,minproto=5,maxproto=5,direct,pipe_ino=10600557 0 0
      [root@rhel8 ~]# find /required &> /dev/null
      [root@rhel8 ~]# grep requi /proc/mounts
      /etc/auto.direct /required autofs rw,relatime,fd=13,pgrp=33021,timeout=300,minproto=5,maxproto=5,direct,pipe_ino=10600557 0 0
      /dev/mapper/rhel-root /required xfs rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota 0 0
      /etc/auto.direct /required/sub1 autofs rw,relatime,fd=13,pgrp=33021,timeout=300,minproto=5,maxproto=5,offset,pipe_ino=10600557 0 0
      /etc/auto.direct /required/sub2 autofs rw,relatime,fd=13,pgrp=33021,timeout=300,minproto=5,maxproto=5,offset,pipe_ino=10600557 0 0
      /dev/mapper/rhel-root /required/sub1 xfs rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota 0 0
      /dev/mapper/rhel-root /required/sub2 xfs rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota 0 0

      // now, i edit /etc/auto.direct to remove one of the entries and reload the map :

      [root@rhel8 ~]# vi /etc/auto.direct
      [root@rhel8 ~]# grep -v ^# /etc/auto.direct
      /required \
      / localhost:/playground2 \
      /sub2 localhost:/playground4

      // reload :

      [root@rhel8 ~]# systemctl reload autofs
      [root@rhel8 ~]# systemctl status autofs
      ● autofs.service - Automounts filesystems on demand
      Loaded: loaded (/usr/lib/systemd/system/autofs.service; disabled; vendor preset: disabled)
      Active: failed (Result: signal) since Fri 2023-12-01 14:10:20 CET; 4s ago
      Process: 33082 ExecReload=/usr/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
      Process: 33021 ExecStart=/usr/sbin/automount $OPTIONS --systemd-service --dont-check-daemon (code=killed, signal=SEGV)
      Main PID: 33021 (code=killed, signal=SEGV)

      Dec 01 14:07:52 rhel8 automount[33021]: mount(bind): mounted /playground4 type bind on /required/sub2
      Dec 01 14:07:52 rhel8 automount[33021]: dev_ioctl_send_ready: token = 101
      Dec 01 14:07:52 rhel8 automount[33021]: mounted /required/sub2
      Dec 01 14:09:07 rhel8 automount[33021]: st_expire: state 1 path /-
      Dec 01 14:09:07 rhel8 automount[33021]: expire_proc: exp_proc = 139817037059840 path /-
      Dec 01 14:09:07 rhel8 automount[33021]: expire_proc_direct: send expire to trigger /required
      Dec 01 14:09:07 rhel8 automount[33021]: expire_proc_direct: 3 remaining in /-
      Dec 01 14:09:07 rhel8 automount[33021]: expire_cleanup: got thid 139817037059840 path /- stat 3
      Dec 01 14:09:07 rhel8 automount[33021]: expire_cleanup: sigchld: exp 139817037059840 finished, switching from 2 to 1
      Dec 01 14:09:07 rhel8 automount[33021]: st_ready: st_ready(): state = 2 path /-

        1. Analisys (gdb) :

      Program terminated with signal SIGSEGV, Segmentation fault.
      #0 try_remount (ap=ap@entry=0x561c4fa10cd0, me=me@entry=0x7f29a40022e0, type=type@entry=2) at mounts.c:2883
      2883 if (mapent->key[0] == '/')
      [Current thread is 1 (Thread 0x7f29b0467700 (LWP 33088))]
      Missing separate debuginfos, use: yum debuginfo-install libtirpc-1.1.4-8.el8_6.x86_64

      (gdb) p (int) mapent
      $2 = 56 <<----------- hence crash

      (gdb) bt
      #0 try_remount (ap=ap@entry=0x561c4fa10cd0, me=me@entry=0x7f29a40022e0, type=type@entry=2) at mounts.c:2883
      #1 0x0000561c4d8a792c in do_mount_autofs_direct (ap=ap@entry=0x561c4fa10cd0, me=me@entry=0x7f29a40022e0, timeout=300) at direct.c:301
      #2 0x0000561c4d8b5829 in do_readmap_mount (now=708176, me=0x7f29a40022e0, map=0x561c4fa10db0, ap=0x561c4fa10cd0) at state.c:407
      #3 do_readmap (arg=0x7f2998001400) at state.c:479
      #4 0x00007f29bd7111ca in start_thread (arg=<optimized out>) at pthread_create.c:479
      #5 0x00007f29bbcb3e73 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

      // code :

      2880 me->flags &= ~MOUNT_FLAG_DIR_CREATED;
      2881 mapent = IS_MM(me) ? MM_PARENT(me) : me;
      2882 /* Direct or offset mount, key is full path */
      2883 if (mapent->key[0] == '/')

      // we crash since its a multi-mount, but parent is NULL, hence on MM_PARENT we return addr relative to node field :

      191 #define MM_PARENT(me) (MAPENT(me->mm_parent))
      73 #define MAPENT (container_of(n, struct mapent, node))

      (gdb) p me->mm_root
      $4 = (struct tree_node *) 0x7f29a4002318
      (gdb) p me->mm_parent
      $5 = (struct tree_node *) 0x0

      gdb) p (int)&((struct mapent*)0)->node
      $6 = 56

      // looks like hierarchical mounts should be taken into consideration as well

        1. Solution ?

      // with the following patch i cannot reproduce it :

      diff --git a/lib/mounts.c b/lib/mounts.c
      index bc35258..153474e 100644
      — a/lib/mounts.c
      +++ b/lib/mounts.c
      @@ -2878,7 +2878,7 @@ int try_remount(struct autofs_point *ap, struct mapent *me, unsigned int type)
      }

      me->flags &= ~MOUNT_FLAG_DIR_CREATED;

      • mapent = IS_MM(me) ? MM_PARENT(me) : me;
        + mapent = (IS_MM(me) && !IS_MM_ROOT(me)) ? MM_PARENT(me) : me;
        /* Direct or offset mount, key is full path */
        if (mapent->key[0] == '/') {
        if (!is_mounted(mapent->key, MNTS_REAL))

      // however stale entry removed keeps mounted after try_remount, not sure if this is expected or not

              ikent@redhat.com Ian Kent
              rhn-support-rbergant Roberto Bergantinos Corpas
              Ian Kent Ian Kent
              Kun Wang Kun Wang
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Created:
                Updated:
                Resolved: