Uploaded image for project: 'Facter'
  1. Facter
  2. FACT-2054

Facter::Core::Execution.execute incorrectly expands shell builtins

    XMLWordPrintable

    Details

    • Template:
    • Team:
      Night's Watch
    • Story Points:
      5
    • Sprint:
      NW - 2019-10-30, NW - 2019-11-13, 2019-11-27, 2019-12-11
    • Method Found:
      Needs Assessment
    • Release Notes:
      Enhancement
    • Release Notes Summary:
      Hide
      Facter::Core::Execution.execute by default searches command passed as argument in a list of directories and expands it to absolute path. Now accepts a new boolean parameter -expand. When true, behaves like before, searches the command and expands it to absolute path. When set to false e.g
      ```Facter::Core::Execution.execute(command, {:expand => false}) ```
      verifies if it is a shel builtin command, and in that case command is passed as it is (not expanded to absolute path).
      Show
      Facter::Core::Execution.execute by default searches command passed as argument in a list of directories and expands it to absolute path. Now accepts a new boolean parameter -expand. When true, behaves like before, searches the command and expands it to absolute path. When set to false e.g ```Facter::Core::Execution.execute(command, {:expand => false}) ``` verifies if it is a shel builtin command, and in that case command is passed as it is (not expanded to absolute path).
    • QA Risk Assessment:
      Needs Assessment

      Description

      When executing commands, Facter will expand the first word in the command string to be a fully qualified path. I.e. ls -l will become /usr/bin/ls -l. If the command string is a compound command that contains a pipeline or conditional construct, then Facter will wrap the string in /usr/bin/sh -c.

      However, the first word of the compound is still expanded to an absolute path. This breaks shell builtins like cd as they are expanded to external commands like /usr/bin/cd or fail to be found on the PATH.

      Reproduction Case

      • Install the latest version of puppet-agent on CentOS 7, along with strace:

      yum install -y http://yum.puppetlabs.com/puppet-release-el-7.noarch.rpm
      yum install -y puppet-agent strace
      

      • Create a test script that loads Facter, and uses it to execute a compound command that begins with cd:

      cat <<EOF > test.rb
      #!/opt/puppetlabs/puppet/bin/ruby
      require 'facter'
       
      puts Facter::Core::Execution.execute('cd /opt/puppetlabs && ls')
      EOF
      chmod +x test.rb
      

      • Execute the test script.

      Outcome

      The script prints the contents of the current working directory instead of /opt/puppetlabs:

      # ./test.rb
      1
      anaconda-ks.cfg
      linux.iso
      test.rb
      

      Running the script under strrace reveals that cd is being expanded to /usr/bin/cd before being passed to sh -c:

      # strace -f -e trace=execve ./test.rb
      execve("./test.rb", ["./test.rb"], [/* 23 vars */]) = 0
      strace: Process 20373 attached
      strace: Process 20374 attached
      [pid 20374] execve("/usr/bin/sh", ["sh", "-c", "/usr/bin/cd /opt/puppetlabs && l"...], [/* 24 vars */]) = 0
      strace: Process 20375 attached
      [pid 20375] execve("/usr/bin/cd", ["/usr/bin/cd", "/opt/puppetlabs"], [/* 24 vars */]) = 0
      [pid 20375] +++ exited with 0 +++
      [pid 20374] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=20375, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
      strace: Process 20376 attached
      [pid 20376] execve("/usr/bin/ls", ["ls"], [/* 24 vars */]) = 0
      [pid 20376] +++ exited with 0 +++
      [pid 20374] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=20376, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
      [pid 20374] +++ exited with 0 +++
      [pid 20372] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=20374, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
      1
      anaconda-ks.cfg
      linux.iso
      test.rb
      [pid 20373] +++ exited with 0 +++
      +++ exited with 0 +++
      

      Expected Outcome

      The script prints the content of /opt/puppetlabs:

      # ./test.rb
      bin
      facter
      puppet
      pxp-agent
      

      Suggested Workaround

      The expansion only affects the first word in the command line, so adding an extra true && to the compound command acts as a sacrificial noop that takes the hit instead.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              george.mrejea George Mrejea
              Reporter:
              chuck Charlie Sharpsteen
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:

                  Zendesk Support