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

bash and ksh behave differently when redirecting output to a file owned by a different user than root

    • Icon: Bug Bug
    • Resolution: Won't Do
    • Icon: Undefined Undefined
    • None
    • rhel-9.4
    • bash
    • None
    • None
    • Low
    • Upstream
    • rhel-sst-cs-plumbers
    • ssg_core_services
    • None
    • False
    • Hide

      None

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

      What were you trying to do that didn't work?

      A customer found out that bash and ksh were behaving differently when redirecting output to a file not owned by root user:

      # touch /tmp/foo
      # chown renaud:renaud /tmp/foo
      # bash -c "echo hello > /tmp/foo"
      --> no error
      
      # ksh -c "echo hello > /tmp/foo"
      ksh: /tmp/foo: cannot create [Permission denied]
      

      When stracing bash, we can see bash initially gets a EACCES (as for ksh), but then retries with O_CREAT flag, which then is a success:

      [...] openat(AT_FDCWD</root>, "/tmp/foo", O_WRONLY|O_CREAT|O_TRUNC, 0666) = -1 EACCES (Permission denied) <0.000046>
      [...] openat(AT_FDCWD</root>, "/tmp/foo", O_WRONLY|O_TRUNC) = 3</tmp/foo> <0.000073>
      [...] +++ exited with 0 +++
      

      IMHO ksh has proper behaviour, while bash hasn't, below is my explanation.

      Reproducing this on my RHEL9 system, I went with breakpointing the code when the initial attempt to create the file fails with EACCES.
      I could see with bash that upon failure, the following code block on line 749-755 was executed, which is the retry without O_CREAT flag:

       714 static int
       715 redir_open (filename, flags, mode, ri)
       716      char *filename;
       717      int flags, mode;
       718      enum r_instruction ri;
       719 {
       :
       749 #if defined (AFS)
       750       if ((fd < 0) && (errno == EACCES))
       751         {
       752           fd = open (filename, flags & ~O_CREAT, mode);
       753           errno = EACCES;       /* restore errno */
       754         }
       755 #endif /* AFS */
       756     }
       757 
       758   return fd;
       759 }
      

      The code above is compiled because bash on RHEL9 is compiled with AFS support (--with-afs).
      AFS stands apparently for Andrew File System, this file system is not supported on RHEL, as seen by checking the kernel modules:

      # grep AFS /boot/config-5.14.0-427.20.1.el9_4.x86_64 
      CONFIG_AFS_FS=m
      CONFIG_AFS_DEBUG=y
      CONFIG_AFS_FSCACHE=y
      # CONFIG_AFS_DEBUG_CURSOR is not set
      
      # ls /lib/modules/5.14.0-427.20.1.el9_4.x86_64/kernel/fs/afs
      --> empty
      

      It's however shipped on Fedora 40 (my laptop OS).

      So I went with rebuilding bash without AFS support, and in such case, it behaves "correctly", the redirection just fails and there is no retry:

      [root@vm-rhel9 ~]# ll /tmp/foo
      -rw-r--r--. 1 renaud renaud 6 Jul 19 09:49 /tmp/foo
      
      [root@vm-rhel9 ~]# bash -c "echo hello > /tmp/foo"
      bash: line 1: /tmp/foo: Permission denied
      

      So, IMHO, there is a bug in bash. Even with AFS support, bash should check that the underlying file system is AFS, and retry in such case, whereas for other file systems, it should just fail, as when compiled without AFS support.

      Please provide the package NVR for which bug is seen:

      bash-5.1.8-9.el9_4 and all previous releases
      Upstream bash (including Fedora 40 bash-5.2.26-3.fc40.x86_64)

      How reproducible:

      Always, see above

      Expected results

      EACCES

      Actual results

      No error

              rhn-support-svashish Siteshwar Vashisht
              rhn-support-rmetrich Renaud Métrich
              Siteshwar Vashisht Siteshwar Vashisht
              Karel Volný Karel Volný
              Votes:
              1 Vote for this issue
              Watchers:
              5 Start watching this issue

                Created:
                Updated:
                Resolved: