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

Gilbert E. Detillieux gedetil at cs.umanitoba.ca
Fri Nov 29 10:31:43 CST 2019


The strace on bash is more revealing than the one on tcsh, because of 
the retry on openat() calls...

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

The first call (ignoring the use of openat vs open or creat) is 
essentially equivalent to what would happen with the creat call in tcsh. 
  The key difference between that and the second call is the use of 
O_CREAT (and the following mode argument).  However, that should have no 
effect on an existing file, and only come into play when a new file is 
actually created.

The fact that there's different behaviour between the two openat calls, 
and the fact that you're getting EACCES when uid==0 (which should almost 
never happen, especially on file access), and the fact that this is a 
new error, suggests a kernel bug to me.

It's possible that it's a "feature", but this would seem misguided to 
me.  (Without seeing the actual code diffs, it's hard to say for sure.) 
But I can't think of any logical reason why you'd get an EACCES error on 
this as root.  (Unless it's the convoluted logic of SELinux that's 
coming into play?... I'd expect the second call to fail the same way in 
that case, but no guarantees if the kernel code paths are different.)

The bash vs tcsh differences (the retried openat vs using creat) could 
be due to a number of reasons, and may make sense in other instances 
where the O_CREAT could lead to errors (perhaps more likely for non-root 
users).  I wouldn't assume it's a specific workaround for the new kernel 
behaviour, without seeing comments (or online discussion by the 
maintainers) to that effect.

Gilbert

On 2019-11-29 5:07 a.m., Trevor Cordes wrote:
> 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.

-- 
Manitoba UNIX User Group	E-mail: <gedetil at muug.ca>
c/o Gilbert E. Detillieux	Web:	http://muug.ca/
University of Manitoba		Phone:  (204)474-8161
Winnipeg MB CANADA  R3T 2N2	Fax:    (204)474-7609


More information about the Roundtable mailing list