[RndTbl] creat() fails on non-root owned file when stickybit set on dir (tcsh) (new kernel bug?)

Trevor Cordes trevor at tecnopolis.ca
Fri Nov 29 05:07:34 CST 2019


Just upgraded to F30 with kernel 5.3.12 (not going to F31 quite yet).  Hit 
a weird error that didn't happen in the previous kernel/OS:

If my dir has stickybit set, in this case /tmp, then root can't use tcsh's 
">!" redirection on a file owned by another user (permission denied).  F29 
">!" allowed it just fine (kernel 5.3.11).  I checked and tcsh versions 
didn't change, except just the bump to F30.

">!" in tcsh is the same as > in bash.  tcsh lets you set an option to >! 
require explicit instruction to clobber existing files so you don't 
accidentally > an existing file without realizing it.  That's the extra ! 
after the >.

It's funny, because root can still append to the file (>>), rm it, chmod, 
etc., just not this explicit clobber.

Funnier still is it works in bash (using >) but the OS is still giving it 
the permission denied.  (See below.)

It looks like tcsh is using creat() and that is the syscall returning the 
error.

as root:

tcsh
sudo -u trevor touch /tmp/t
echo foo >> /tmp/t	# ok
echo foo >! /tmp/t	# Permission denied.

strace on 5.3.12 F30 (error):

dup(19)                                 = 0
fcntl(0, F_SETFD, 0)                    = 0
dup2(17, 1)                             = 1
dup2(18, 2)                             = 2
creat("t", 0666)                        = -1 EACCES (Permission denied)
write(18, "t: Permission denied.\n", 22l: Permission denied.
) = 22

strace on 5.3.11 F29 (ok):

dup(19)                                 = 0
fcntl(0, F_SETFD, 0)                    = 0
dup2(17, 1)                             = 1
dup2(18, 2)                             = 2
creat("t", 0666)                        = 3
fcntl(3, F_GETFL)                       = 0x8001 (flags O_WRONLY|O_LARGEFILE)
fcntl(3, F_SETFL, O_WRONLY|O_LARGEFILE) = 0
...

strace with bash on 5.3.12 F30 (no error! note the double try!)
(command for bash is just:  echo foo > /tmp/t)

openat(AT_FDCWD, "/tmp/t", O_WRONLY|O_CREAT|O_TRUNC, 0666) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/tmp/t", O_WRONLY|O_TRUNC) = 3
fcntl(1, F_GETFD)                       = 0
fcntl(1, F_DUPFD, 10)                   = 10
...

So bash uses openat instead of creat, but still gets EACCESS, but then 
retries with slightly different options... almost like bash hit this same 
bug but has already worked around it.

So is this a kernel bug / change in API?  Should I report this to kernel 
bugs or to tcsh bugs?  This is a "bug" in the sense that something changed 
because I've been doing this type of command for, oh, 20 years, and it's 
always worked before.  And I know Linus doesn't like to change the 
existing user interface into the kernel.


More information about the Roundtable mailing list