[Toybox] ls -laZ /dev takes a long time

enh enh at google.com
Fri Oct 16 12:56:01 PDT 2015


at the moment, ls.c has this:

  if (flags & FLAG_Z) {
    if (!CFG_TOYBOX_LSM_NONE) {
      int fd;

      // Why not just openat(O_PATH|(O_NOFOLLOW*!!(toys.optflags&FLAG_L))) and
      // lsm_fget_context() on that filehandle? Because the kernel is broken,
      // and won't let us read this "metadata" from the filehandle unless we
      // have permission to read the data. We _can_ read the same data in
      // by path, we just can't do it through an O_PATH filehandle, because
      // reasons. So as a bug workaround for the broken kernel, we do it
      // both ways.
      //
      // The O_NONBLOCK is there to avoid triggering automounting (there's
      // a rush of nostalgia for you) on directories we don't descend into,
      // which O_PATH would have done for us but see "the kernel is broken".
      if (S_ISSOCK(new->st.st_mode) ||
          (S_ISLNK(new->st.st_mode) && !(toys.optflags & FLAG_L)) ||
          -1 == (fd = openat(dirtree_parentfd(new), new->name,
                             O_RDONLY|O_NONBLOCK|O_NOATIME)))
      {
        char *path;

        // Wouldn't it be nice if the lsm functions worked like openat(),
        // fchmodat(), mknodat(), readlinkat() so we could do this without
        // even O_PATH? But no, this is 1990's tech.
        path = dirtree_path(new, 0);
        lsm_lget_context(path, (char **)&new->extra);
        free(path);
      } else {
        lsm_fget_context(fd, (char **)&new->extra);
        close(fd);
      }
    }
    if (CFG_TOYBOX_LSM_NONE || !new->extra) new->extra = (long)xstrdup("?");
  }

but that doesn't work well in /dev.

root at shamu:/ # time ls -laZ /dev > /dev/null
    0m10.33s real     0m0.05s user     0m0.62s system

some files, like /dev/smd_pkt_loopback, take a long time to fail to open:

     0.003022 openat(4, "smd_pkt_loopback",
O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_NOATIME) = -1 EPROBE_DEFER (Unknown
error 517)
     5.185825 lgetxattr("/dev/smd_pkt_loopback", "security.selinux",
"u:object_r:device:s0", 255) = 21

it seems dangerous to be opening every file when running "ls", as
opening a /dev file could have side effects or hang. if an open is
really required, bionic's lgetxattr supports O_PATH file descriptors
as of https://android-review.googlesource.com/152663 and the code for
that's trivial, so we could just have toybox do that directly rather
than whitelist bionic for O_PATH fgetxattr.

happy to provide a patch if you indicate a preferred direction...

-- 
Elliott Hughes - http://who/enh - http://jessies.org/~enh/
Android native code/tools questions? Mail me/drop by/add me as a reviewer.

 1445025361.0


More information about the Toybox mailing list