24 Mar, 2011

1 commit


14 Aug, 2010

1 commit

  • Mark arguments to certain system calls as being const where they should be but
    aren't. The list includes:

    (*) The filename arguments of various stat syscalls, execve(), various utimes
    syscalls and some mount syscalls.

    (*) The filename arguments of some syscall helpers relating to the above.

    (*) The buffer argument of various write syscalls.

    Signed-off-by: David Howells
    Acked-by: David S. Miller
    Signed-off-by: Linus Torvalds

    David Howells
     

14 Jan, 2009

2 commits


27 Jul, 2008

5 commits

  • * do not pass nameidata; struct path is all the callers want.
    * switch to new helpers:
    user_path_at(dfd, pathname, flags, &path)
    user_path(pathname, &path)
    user_lpath(pathname, &path)
    user_path_dir(pathname, &path) (fail if not a directory)
    The last 3 are trivial macro wrappers for the first one.
    * remove nameidata in callers.

    Signed-off-by: Al Viro

    Al Viro
     
  • Incidentally, the name that gives hundreds of false positives on grep
    is not a good idea...

    Signed-off-by: Al Viro

    Al Viro
     
  • Move the immutable and append-only checks from chmod, chown and utimes
    into notify_change(). Checks for immutable and append-only files are
    always performed by the VFS and not by the filesystem (see
    permission() and may_...() in namei.c), so these belong in
    notify_change(), and not in inode_change_ok().

    This should be completely equivalent.

    CC: Ulrich Drepper
    CC: Michael Kerrisk
    Signed-off-by: Miklos Szeredi
    Signed-off-by: Al Viro

    Miklos Szeredi
     
  • Untange the mess that is do_utimes(). Add kerneldoc comment to
    do_utimes().

    CC: Ulrich Drepper
    CC: Michael Kerrisk
    Signed-off-by: Miklos Szeredi
    Signed-off-by: Al Viro

    Miklos Szeredi
     
  • Add a new ia_valid flag: ATTR_TIMES_SET, to handle the
    UTIMES_OMIT/UTIMES_NOW and UTIMES_NOW/UTIMES_OMIT cases. In these
    cases neither ATTR_MTIME_SET nor ATTR_ATIME_SET is in the flags, yet
    the POSIX draft specifies that permission checking is performed the
    same way as if one or both of the times was explicitly set to a
    timestamp.

    See the path "vfs: utimensat(): fix error checking for
    {UTIME_NOW,UTIME_OMIT} case" by Michael Kerrisk for the patch
    introducing this behavior.

    This is a cleanup, as well as allowing filesystems (NFS/fuse/...) to
    perform their own permission checking instead of the default.

    CC: Ulrich Drepper
    CC: Michael Kerrisk
    Signed-off-by: Miklos Szeredi
    Signed-off-by: Al Viro

    Miklos Szeredi
     

23 Jun, 2008

4 commits

  • The POSIX.1 draft spec for futimens()/utimensat() says:

    Only a process with the effective user ID equal to the
    user ID of the file, *or with write access to the file*,
    or with appropriate privileges may use futimens() or
    utimensat() with a null pointer as the times argument
    or with both tv_nsec fields set to the special value
    UTIME_NOW.

    The important piece here is "with write access to the file", and
    this matters for futimens(), which deals with an argument that
    is a file descriptor referring to the file whose timestamps are
    being updated, The standard is saying that the "writability"
    check is based on the file permissions, not the access mode with
    which the file is opened. (This behavior is consistent with the
    semantics of FreeBSD's futimes().) However, Linux is currently
    doing the latter -- futimens(fd, times) is a library
    function implemented as

    utimensat(fd, NULL, times, 0)

    and within the utimensat() implementation we have the code:

    f = fget(dfd); // dfd is 'fd'
    ...
    if (f) {
    if (!(f->f_mode & FMODE_WRITE))
    goto mnt_drop_write_and_out;

    The check should instead be based on the file permissions.

    Thanks to Miklos for pointing out how to do this check.
    Miklos also pointed out a simplification that could be
    made to my first version of this patch, since the checks
    for the pathname and file descriptor cases can now be
    conflated.

    Acked-by: Miklos Szeredi
    Cc: Al Viro
    Cc: Ulrich Drepper
    Signed-off-by: Michael Kerrisk
    Signed-off-by: Andrew Morton
    Signed-off-by: Al Viro

    Michael Kerrisk
     
  • The POSIX.1 draft spec for utimensat() says:

    Only a process with the effective user ID equal to the
    user ID of the file or with appropriate privileges may use
    futimens() or utimensat() with a non-null times argument
    that does not have both tv_nsec fields set to UTIME_NOW
    and does not have both tv_nsec fields set to UTIME_OMIT.

    If this condition is violated, then the error EPERM should result.
    However, the current implementation does not generate EPERM if
    one tv_nsec field is UTIME_NOW while the other is UTIME_OMIT.
    It should give this error for that case.

    This patch:

    a) Repairs that problem.
    b) Removes the now unneeded nsec_special() helper function.
    c) Adds some comments to explain the checks that are being
    performed.

    Thanks to Miklos, who provided comments on the previous iteration
    of this patch. As a result, this version is a little simpler and
    and its logic is better structured.

    Miklos suggested an alternative idea, migrating the
    is_owner_or_cap() checks into fs/attr.c:inode_change_ok() via
    the use of an ATTR_OWNER_CHECK flag. Maybe we could do that
    later, but for now I've gone with this version, which is
    IMO simpler, and can be more easily read as being correct.

    Acked-by: Miklos Szeredi
    Cc: Al Viro
    Cc: Ulrich Drepper
    Signed-off-by: Michael Kerrisk
    Signed-off-by: Andrew Morton
    Signed-off-by: Al Viro

    Michael Kerrisk
     
  • The POSIX.1 draft spec for utimensat() says that if a times[n].tv_nsec
    field is UTIME_OMIT or UTIME_NOW, then the value in the corresponding
    tv_sec field is ignored. See the last sentence of this para, from
    the spec:

    If the tv_nsec field of a timespec structure has
    the special value UTIME_NOW, the file's relevant
    timestamp shall be set to the greatest value
    supported by the file system that is not greater than
    the current time. If the tv_nsec field has the
    special value UTIME_OMIT, the file's relevant
    timestamp shall not be changed. In either case,
    the tv_sec field shall be ignored.

    However the current Linux implementation requires the tv_sec value to be
    zero (or the EINVAL error results). This requirement should be removed.

    Acked-by: Miklos Szeredi
    Cc: Al Viro
    Cc: Ulrich Drepper
    Signed-off-by: Michael Kerrisk
    Signed-off-by: Andrew Morton
    Signed-off-by: Al Viro

    Michael Kerrisk
     
  • …e and append-only files

    This patch fixes utimensat() to make its behavior consistent
    with that of utime()/utimes() when dealing with files marked
    immutable and append-only.

    The current utimensat() implementation also returns EPERM if
    'times' is non-NULL and the tv_nsec fields are both UTIME_NOW.
    For consistency, the

    (times != NULL && times[0].tv_nsec == UTIME_NOW &&
    times[1].tv_nsec == UTIME_NOW)

    case should be treated like the traditional utimes() case where
    'times' is NULL. That is, the call should succeed for a file
    marked append-only and should give the error EACCES if the file
    is marked as immutable.

    The simple way to do this is to set 'times' to NULL
    if (times[0].tv_nsec == UTIME_NOW && times[1].tv_nsec == UTIME_NOW).

    This is also the natural approach, since POSIX.1 semantics consider the
    times == {{x, UTIME_NOW}, {y, UTIME_NOW}}
    to be exactly equivalent to the case for
    times == NULL.

    (Thanks to Miklos for pointing this out.)

    Patch 3 in this series relies on the simplification provided
    by this patch.

    Acked-by: Miklos Szeredi <miklos@szeredi.hu>
    Cc: Al Viro <viro@zeniv.linux.org.uk>
    Cc: Ulrich Drepper <drepper@redhat.com>
    Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

    Michael Kerrisk
     

01 May, 2008

1 commit

  • If utimensat() is called with both times set to UTIME_NOW or one of them to
    UTIME_NOW and the other to UTIME_OMIT, then it will update the file time
    without any permission checking.

    I don't think this can be used for anything other than a local DoS, but could
    be quite bewildering at that (e.g. "Why was that large source tree rebuilt
    when I didn't modify anything???")

    This affects all kernels from 2.6.22, when the utimensat() syscall was
    introduced.

    Fix by doing the same permission checking as for the "times == NULL" case.

    Thanks to Michael Kerrisk, whose utimensat-non-conformances-and-fixes.patch in
    -mm also fixes this (and breaks other stuff), only he didn't realize the
    security implications of this bug.

    Signed-off-by: Miklos Szeredi
    Cc: Ulrich Drepper
    Cc: Michael Kerrisk
    Cc:
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Miklos Szeredi
     

19 Apr, 2008

1 commit


15 Feb, 2008

2 commits

  • * Add path_put() functions for releasing a reference to the dentry and
    vfsmount of a struct path in the right order

    * Switch from path_release(nd) to path_put(&nd->path)

    * Rename dput_path() to path_put_conditional()

    [akpm@linux-foundation.org: fix cifs]
    Signed-off-by: Jan Blunck
    Signed-off-by: Andreas Gruenbacher
    Acked-by: Christoph Hellwig
    Cc:
    Cc: Al Viro
    Cc: Steven French
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Jan Blunck
     
  • This is the central patch of a cleanup series. In most cases there is no good
    reason why someone would want to use a dentry for itself. This series reflects
    that fact and embeds a struct path into nameidata.

    Together with the other patches of this series
    - it enforced the correct order of getting/releasing the reference count on
    pairs
    - it prepares the VFS for stacking support since it is essential to have a
    struct path in every place where the stack can be traversed
    - it reduces the overall code size:

    without patch series:
    text data bss dec hex filename
    5321639 858418 715768 6895825 6938d1 vmlinux

    with patch series:
    text data bss dec hex filename
    5320026 858418 715768 6894212 693284 vmlinux

    This patch:

    Switch from nd->{dentry,mnt} to nd->path.{dentry,mnt} everywhere.

    [akpm@linux-foundation.org: coding-style fixes]
    [akpm@linux-foundation.org: fix cifs]
    [akpm@linux-foundation.org: fix smack]
    Signed-off-by: Jan Blunck
    Signed-off-by: Andreas Gruenbacher
    Acked-by: Christoph Hellwig
    Cc: Al Viro
    Cc: Casey Schaufler
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Jan Blunck
     

07 Feb, 2008

1 commit


17 Oct, 2007

1 commit


18 Jul, 2007

1 commit

  • Introduce is_owner_or_cap() macro in fs.h, and convert over relevant
    users to it. This is done because we want to avoid bugs in the future
    where we check for only effective fsuid of the current task against a
    file's owning uid, without simultaneously checking for CAP_FOWNER as
    well, thus violating its semantics.
    [ XFS uses special macros and structures, and in general looked ...
    untouchable, so we leave it alone -- but it has been looked over. ]

    The (current->fsuid != inode->i_uid) check in generic_permission() and
    exec_permission_lite() is left alone, because those operations are
    covered by CAP_DAC_OVERRIDE and CAP_DAC_READ_SEARCH. Similarly operations
    falling under the purview of CAP_CHOWN and CAP_LEASE are also left alone.

    Signed-off-by: Satyam Sharma
    Cc: Al Viro
    Acked-by: Serge E. Hallyn
    Signed-off-by: Linus Torvalds

    Satyam Sharma
     

17 Jul, 2007

1 commit


09 Jul, 2007

1 commit

  • Commit 1c710c896eb461895d3c399e15bb5f20b39c9073 added the utimensat()
    system call, but didn't handle the case of checking for the writability
    of the target right, when the target was a file descriptor, not a
    filename.

    We cannot use vfs_permission(MAY_WRITE) for that case, and need to
    simply check whether the file descriptor is writable. The oops from
    using the wrong function was noticed and narrowed down by Markus
    Trippelsdorf.

    Cc: Ulrich Drepper
    Cc: Markus Trippelsdorf
    Cc: Andrew Morton
    Acked-by: Al Viro
    Signed-off-by: Linus Torvalds

    Linus Torvalds
     

09 May, 2007

1 commit

  • Implement utimensat(2) which is an extension to futimesat(2) in that it

    a) supports nano-second resolution for the timestamps
    b) allows to selectively ignore the atime/mtime value
    c) allows to selectively use the current time for either atime or mtime
    d) supports changing the atime/mtime of a symlink itself along the lines
    of the BSD lutimes(3) functions

    For this change the internally used do_utimes() functions was changed to
    accept a timespec time value and an additional flags parameter.

    Additionally the sys_utime function was changed to match compat_sys_utime
    which already use do_utimes instead of duplicating the work.

    Also, the completely missing futimensat() functionality is added. We have
    such a function in glibc but we have to resort to using /proc/self/fd/* which
    not everybody likes (chroot etc).

    Test application (the syscall number will need per-arch editing):

    #include
    #include
    #include
    #include
    #include
    #include

    #define __NR_utimensat 280

    #define UTIME_NOW ((1l << 30) - 1l)
    #define UTIME_OMIT ((1l << 30) - 2l)

    int
    main(void)
    {
    int status = 0;

    int fd = open("ttt", O_RDWR|O_CREAT|O_EXCL, 0666);
    if (fd == -1)
    error (1, errno, "failed to create test file \"ttt\"");

    struct stat64 st1;
    if (fstat64 (fd, &st1) != 0)
    error (1, errno, "fstat failed");

    struct timespec t[2];
    t[0].tv_sec = 0;
    t[0].tv_nsec = 0;
    t[1].tv_sec = 0;
    t[1].tv_nsec = 0;
    if (syscall(__NR_utimensat, AT_FDCWD, "ttt", t, 0) != 0)
    error (1, errno, "utimensat failed");

    struct stat64 st2;
    if (fstat64 (fd, &st2) != 0)
    error (1, errno, "fstat failed");

    if (st2.st_atim.tv_sec != 0 || st2.st_atim.tv_nsec != 0)
    {
    puts ("atim not reset to zero");
    status = 1;
    }
    if (st2.st_mtim.tv_sec != 0 || st2.st_mtim.tv_nsec != 0)
    {
    puts ("mtim not reset to zero");
    status = 1;
    }
    if (status != 0)
    goto out;

    t[0] = st1.st_atim;
    t[1].tv_sec = 0;
    t[1].tv_nsec = UTIME_OMIT;
    if (syscall(__NR_utimensat, AT_FDCWD, "ttt", t, 0) != 0)
    error (1, errno, "utimensat failed");

    if (fstat64 (fd, &st2) != 0)
    error (1, errno, "fstat failed");

    if (st2.st_atim.tv_sec != st1.st_atim.tv_sec
    || st2.st_atim.tv_nsec != st1.st_atim.tv_nsec)
    {
    puts ("atim not set");
    status = 1;
    }
    if (st2.st_mtim.tv_sec != 0 || st2.st_mtim.tv_nsec != 0)
    {
    puts ("mtim changed from zero");
    status = 1;
    }
    if (status != 0)
    goto out;

    t[0].tv_sec = 0;
    t[0].tv_nsec = UTIME_OMIT;
    t[1] = st1.st_mtim;
    if (syscall(__NR_utimensat, AT_FDCWD, "ttt", t, 0) != 0)
    error (1, errno, "utimensat failed");

    if (fstat64 (fd, &st2) != 0)
    error (1, errno, "fstat failed");

    if (st2.st_atim.tv_sec != st1.st_atim.tv_sec
    || st2.st_atim.tv_nsec != st1.st_atim.tv_nsec)
    {
    puts ("mtim changed from original time");
    status = 1;
    }
    if (st2.st_mtim.tv_sec != st1.st_mtim.tv_sec
    || st2.st_mtim.tv_nsec != st1.st_mtim.tv_nsec)
    {
    puts ("mtim not set");
    status = 1;
    }
    if (status != 0)
    goto out;

    sleep (2);

    t[0].tv_sec = 0;
    t[0].tv_nsec = UTIME_NOW;
    t[1].tv_sec = 0;
    t[1].tv_nsec = UTIME_NOW;
    if (syscall(__NR_utimensat, AT_FDCWD, "ttt", t, 0) != 0)
    error (1, errno, "utimensat failed");

    if (fstat64 (fd, &st2) != 0)
    error (1, errno, "fstat failed");

    struct timeval tv;
    gettimeofday(&tv,NULL);

    if (st2.st_atim.tv_sec tv.tv_sec)
    {
    puts ("atim not set to NOW");
    status = 1;
    }
    if (st2.st_mtim.tv_sec tv.tv_sec)
    {
    puts ("mtim not set to NOW");
    status = 1;
    }

    if (symlink ("ttt", "tttsym") != 0)
    error (1, errno, "cannot create symlink");

    t[0].tv_sec = 0;
    t[0].tv_nsec = 0;
    t[1].tv_sec = 0;
    t[1].tv_nsec = 0;
    if (syscall(__NR_utimensat, AT_FDCWD, "tttsym", t, AT_SYMLINK_NOFOLLOW) != 0)
    error (1, errno, "utimensat failed");

    if (lstat64 ("tttsym", &st2) != 0)
    error (1, errno, "lstat failed");

    if (st2.st_atim.tv_sec != 0 || st2.st_atim.tv_nsec != 0)
    {
    puts ("symlink atim not reset to zero");
    status = 1;
    }
    if (st2.st_mtim.tv_sec != 0 || st2.st_mtim.tv_nsec != 0)
    {
    puts ("symlink mtim not reset to zero");
    status = 1;
    }
    if (status != 0)
    goto out;

    t[0].tv_sec = 1;
    t[0].tv_nsec = 0;
    t[1].tv_sec = 1;
    t[1].tv_nsec = 0;
    if (syscall(__NR_utimensat, fd, NULL, t, 0) != 0)
    error (1, errno, "utimensat failed");

    if (fstat64 (fd, &st2) != 0)
    error (1, errno, "fstat failed");

    if (st2.st_atim.tv_sec != 1 || st2.st_atim.tv_nsec != 0)
    {
    puts ("atim not reset to one");
    status = 1;
    }
    if (st2.st_mtim.tv_sec != 1 || st2.st_mtim.tv_nsec != 0)
    {
    puts ("mtim not reset to one");
    status = 1;
    }

    if (status == 0)
    puts ("all OK");

    out:
    close (fd);
    unlink ("ttt");
    unlink ("tttsym");

    return status;
    }

    [akpm@linux-foundation.org: add missing i386 syscall table entry]
    Signed-off-by: Ulrich Drepper
    Cc: Alexey Dobriyan
    Cc: Michael Kerrisk
    Cc:
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Ulrich Drepper
     

04 Dec, 2006

1 commit


01 Oct, 2006

1 commit