bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#22185: Operation not permitted for `touch -d` on 777 file


From: Assaf Gordon
Subject: bug#22185: Operation not permitted for `touch -d` on 777 file
Date: Wed, 16 Dec 2015 13:19:59 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.4.0

Hello,

On 12/16/2015 09:39 AM, Silvio Ricardo Cordeiro wrote:
The following code fails whenever the specified date is different from `now`:

$ mkdir testdir; chmod 777 testdir; cd testdir
$ touch file; chmod 777 file
$ su another_user
$ touch -d 'now' file  # works
$ touch -d 'yesterday' file  # fails
touch: setting times of ‘file’: Operation not permitted

I see no description of that in the documentation, and it just seems wrong. If 
other users have full control over the file (and surrounding directory), 
shouldn't they be able to change its date?


Trying first to reproduce and understand the issue, I'm seeing this:

1.
When running with 'now', the utimensat(2) syscall is passed NULL as the 
timespec parameter:

    $ strace -e utimensat touch -d 'now' file
    utimensat(0, NULL, NULL, 0)             = 0
    +++ exited with 0 +++

2.
When running with 'yesterday', the syscall is passed a timespec containing a 
specific time:

    $ strace -e utimensat touch -d 'yesterday' file
    utimensat(0, NULL, {{1450202605, 538896888}, {1450202605, 538896888}}, 0) = 
-1 EPERM (Operation not permitted)
    touch: setting times of ‘file’: Operation not permitted
    +++ exited with 1 +++

3.
This coincides with the touch.c code ( 
http://lingrok.org/xref/coreutils/src/touch.c#157 ),
with the following comment:

    157  if (amtime_now)
    158    {
    159      /* Pass NULL to futimens so it will not fail if we have
    160         write access to the file, but don't own it.  */
    161      t = NULL;
    162    }

4.
The linux kernel syscall (if I traced the flow correctly) ends up in 
'utimes_common' ( http://lingrok.org/xref/linux-linus/fs/utimes.c#51 ).
The code block that is executed with timespec=NULL is this ( 
http://lingrok.org/xref/linux-linus/fs/utimes.c#89 ):

    90          /*
    91           * If times is NULL (or both times are UTIME_NOW),
    92           * then we need to check permissions, because
    93           * inode_change_ok() won't do it.
    94           */
    95          error = -EACCES;
    96                if (IS_IMMUTABLE(inode))
    97                  goto mnt_drop_write_and_out;
    98
    99          if (!inode_owner_or_capable(inode)) {
    100                 error = inode_permission(inode, MAY_WRITE);
    101                 if (error)
    102                         goto mnt_drop_write_and_out;
    103         }

Which seems to indicate that if the request is to change the time to 'now' 
using NULL (as opposed to the spelled-out timespec value that is equivalent to 
the current time), then the permission check go through a slightly different 
code path (using 'inode_permissions(..., MAY_WRITE)'),
and perhaps checking for write-permissions (which you have) as opposed to 
ownership (which you don't).

If the above is correct, then this is not a bug in coreutils' touch per-se, but 
a linux kernel behavior.

Comments very welcomed,
regards,
 - assaf








reply via email to

[Prev in Thread] Current Thread [Next in Thread]