• TehPers ( TehPers@beehaw.org ) 
          link
          fedilink
          English
          arrow-up
          3
          ·
          7 months ago

          Many of their TOCTOU issues are something a type system can help with. Require operations to execute on a fd handle directly rather than using convenience functions.

          let fd = FileDescriptor::new(path);
          fd.delete()?;
          fd.create(mode)?;
          
          let is_root = fd == FileDescriptor::new("/"); // does (dev, inode) comparison internally
          // etc
          

          The uutils devs would need to create that themselves, but OpenOptions seems to get them part of the way there at least.

            • TehPers ( TehPers@beehaw.org ) 
              link
              fedilink
              English
              arrow-up
              1
              ·
              7 months ago

              That’s a question of API, not type system.

              It’s only enforced because of Rust’s strict type system. Python, on the other hand, lets you do whatever you want by comparison, and complains only at runtime. I’ve seen far too many **kwargs for my liking.

              And FD types (e.g. OwnedFd, BorrowedFd) are already in std.

              My example would be a thin wrapper around these, most likely. It’s only an example of what I’m trying to convey, though.

  • MoSal ( MoSal@programming.dev ) 
    link
    fedilink
    arrow-up
    5
    ·
    7 months ago
    // Don't bail on the first error, but remember the worst one.
    let mut worst = 0;
    for file in files {
        if let Err(e) = chmod_one(file) {
            worst = worst.max(e.exit_code());
        }
    }
    process::exit(worst);
    

    This is not rustic, I feel.

    files.iter()
      .map(chmod_one)
      .filter_map(Result::err)
    

    is more like it.

    From there, you can next() for first error, last() for last error, or fold() for max error, or collect() if you need to save all errors.


    And no, static compilation doesn’t help here, because get_user_by_name goes through NSS, which dlopens libnss_* modules at runtime regardless of whether your binary is statically linked.

    This is not true in musl systems. I just quickly checked in a Chimera rootfs (which has a system dynamic musl libc btw).

    I believe the described dlopening is one of the well known reasons why GNU libc is not suitable for static linking, unlike musl!

    In Arch, this indeed loads /usr/lib/libnss_systemd.so.2.

    Everyone can test this with strace id 2>&1 | egrep 'open.*\.so'.