All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Blake <eblake@redhat.com>
To: Greg Kurz <groug@kaod.org>, Stefan Hajnoczi <stefanha@gmail.com>
Cc: qemu-devel@nongnu.org, Jann Horn <jannh@google.com>,
	Prasad J Pandit <prasad@redhat.com>,
	"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>,
	Stefan Hajnoczi <stefanha@redhat.com>
Subject: Re: [Qemu-devel] [PATCH 23/29] 9pfs: local: chmod: don't follow symlinks
Date: Fri, 24 Feb 2017 09:23:25 -0600	[thread overview]
Message-ID: <b3f08f09-9678-2142-c4d7-5a66f49b173d@redhat.com> (raw)
In-Reply-To: <20170224113402.07a0fb44@bahia.lan>

[-- Attachment #1: Type: text/plain, Size: 3506 bytes --]

On 02/24/2017 04:34 AM, Greg Kurz wrote:
> On Thu, 23 Feb 2017 15:10:42 +0000
> Stefan Hajnoczi <stefanha@gmail.com> wrote:
> 
>> On Mon, Feb 20, 2017 at 03:42:19PM +0100, Greg Kurz wrote:
>>> The local_chmod() callback is vulnerable to symlink attacks because it
>>> calls:
>>>
>>> (1) chmod() which follows symbolic links for all path elements
>>> (2) local_set_xattr()->setxattr() which follows symbolic links for all
>>>     path elements
>>> (3) local_set_mapped_file_attr() which calls in turn local_fopen() and
>>>     mkdir(), both functions following symbolic links for all path
>>>     elements but the rightmost one
>>>

>>> +        fd = local_open_nofollow(fs_ctx, fs_path->data, O_RDONLY, 0);
>>> +        if (fd == -1) {
>>> +            return -1;
>>> +        }
>>> +        ret = fchmod(fd, credp->fc_mode);
>>> +        close_preserve_errno(fd);  
>>
>> As mentioned on IRC, not sure this is workable since chmod(2) must not
>> require read permission on the file.  This patch introduces failures
>> when the file isn't readable.
>>
> 
> Yeah :-\ This one is the more painful issue to address. I need a
> chmod() variant that would fail on symlinks instead of following
> them... and I'm kinda suffering to implement this in a race-free
> manner.

BSD has lchmod(), but Linux does not.  And Linux does not yet properly
implement AT_SYMLINK_NOFOLLOW.  (The BSD semantics are pretty cool:
restricting mode bits on a symlink can create scenarios where some users
can dereference the symlink but others get ENOENT failures - but I don't
know of any effort to add those semantics to the Linux kernel)

POSIX says support for AT_SYMLINK_NOFOLLOW is optional, precisely
because POSIX does not require permissions on symlinks to matter, but
the way it requires it is that AT_SYMLINK_NOFOLLOW is supposed to be a
no-op for regular files, and cause an EOPNOTSUPP failure for symlinks.

Unfortunately, the Linux man page says that Linux fails with ENOTSUP
(which is identical to EOPNOTSUPP) any time AT_SYMLINK_NOFOLLOW is set,
and not just if it is attempted on a symlink.  And I just verified that
poor behavior as follows:

$ cat foo.c
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char **argv)
{
    int ret = 1;
    if (symlink("a", "l") < 0)
        goto cleanup;
    if (fchmodat(AT_FDCWD, "l", 0600, AT_SYMLINK_NOFOLLOW) == 0)
        printf("kernel supports mode bits on symlinks\n");
    else if (errno != EOPNOTSUPP) {
        printf("Oops, kernel failed with %m on symlink\n");
        goto cleanup;
    }
    if (creat("f", 0600) < 0)
        goto cleanup;
    if (fchmodat(AT_FDCWD, "f", 0600, AT_SYMLINK_NOFOLLOW) < 0) {
        printf("Oops, kernel failed with %m on regular file\n");
        goto cleanup;
    }
    ret = 0;
 cleanup:
    remove("l");
    remove("f");
    return ret;
}
$ ./foo
Oops, kernel failed with Operation not supported on regular file

If you were to get that kernel bug fixed, then you could use fchmodat()
to do a safe chmod() which does not chase through a final symlink, and
relative to a safe directory fd that you obtain for the rest of the path
(as done elsewhere in the series).  Use the CVE nature of the problem as
leverage on the kernel developers, if that's what it takes.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

  reply	other threads:[~2017-02-24 15:23 UTC|newest]

Thread overview: 75+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-20 14:39 [Qemu-devel] [PATCH 00/29] 9pfs: local: fix vulnerability to symlink attacks Greg Kurz
2017-02-20 14:39 ` [Qemu-devel] [PATCH 01/29] 9pfs: local: move xattr security ops to 9p-xattr.c Greg Kurz
2017-02-23 10:57   ` Stefan Hajnoczi
2017-02-20 14:39 ` [Qemu-devel] [PATCH 02/29] 9pfs: remove side-effects in local_init() Greg Kurz
2017-02-23 11:00   ` Stefan Hajnoczi
2017-02-20 14:39 ` [Qemu-devel] [PATCH 03/29] 9pfs: remove side-effects in local_open() and local_opendir() Greg Kurz
2017-02-23 11:01   ` Stefan Hajnoczi
2017-02-20 14:39 ` [Qemu-devel] [PATCH 04/29] 9pfs: introduce openat_nofollow() helper Greg Kurz
2017-02-23 11:16   ` Stefan Hajnoczi
2017-02-23 11:56     ` Greg Kurz
2017-02-24 17:17       ` Stefan Hajnoczi
2017-02-24 22:17         ` Greg Kurz
2017-02-27 10:20           ` Stefan Hajnoczi
2017-02-27 10:37             ` Greg Kurz
2017-02-20 14:39 ` [Qemu-devel] [PATCH 05/29] 9pfs: local: keep a file descriptor on the shared folder Greg Kurz
2017-02-23 11:23   ` Stefan Hajnoczi
2017-02-20 14:40 ` [Qemu-devel] [PATCH 06/29] 9pfs: local: open/opendir: don't follow symlinks Greg Kurz
2017-02-23 13:18   ` Stefan Hajnoczi
2017-02-20 14:40 ` [Qemu-devel] [PATCH 07/29] 9pfs: local: introduce symlink-attack safe xattr helpers Greg Kurz
2017-02-23 13:44   ` Stefan Hajnoczi
2017-02-23 20:54     ` Greg Kurz
2017-02-23 15:02   ` Eric Blake
2017-02-23 15:05     ` Jann Horn
2017-02-23 20:31       ` Greg Kurz
2017-02-23 21:01     ` Greg Kurz
2017-02-20 14:40 ` [Qemu-devel] [PATCH 08/29] 9pfs: local: lgetxattr: don't follow symlinks Greg Kurz
2017-02-23 13:45   ` Stefan Hajnoczi
2017-02-20 14:40 ` [Qemu-devel] [PATCH 09/29] 9pfs: local: llistxattr: " Greg Kurz
2017-02-23 14:07   ` Stefan Hajnoczi
2017-02-20 14:40 ` [Qemu-devel] [PATCH 10/29] 9pfs: local: lsetxattr: " Greg Kurz
2017-02-23 14:08   ` Stefan Hajnoczi
2017-02-20 14:40 ` [Qemu-devel] [PATCH 11/29] 9pfs: local: lremovexattr: " Greg Kurz
2017-02-23 14:09   ` Stefan Hajnoczi
2017-02-24 21:58   ` Greg Kurz
2017-02-20 14:40 ` [Qemu-devel] [PATCH 12/29] 9pfs: local: unlinkat: " Greg Kurz
2017-02-23 14:17   ` Stefan Hajnoczi
2017-02-20 14:41 ` [Qemu-devel] [PATCH 13/29] 9pfs: local: remove: " Greg Kurz
2017-02-23 14:23   ` Stefan Hajnoczi
2017-02-24  0:21     ` Greg Kurz
2017-02-20 14:41 ` [Qemu-devel] [PATCH 14/29] 9pfs: local: utimensat: " Greg Kurz
2017-02-23 14:48   ` Stefan Hajnoczi
2017-02-20 14:41 ` [Qemu-devel] [PATCH 15/29] 9pfs: local: statfs: " Greg Kurz
2017-02-23 14:48   ` Stefan Hajnoczi
2017-02-20 14:41 ` [Qemu-devel] [PATCH 16/29] 9pfs: local: truncate: " Greg Kurz
2017-02-23 14:50   ` Stefan Hajnoczi
2017-02-20 14:41 ` [Qemu-devel] [PATCH 17/29] 9pfs: local: readlink: " Greg Kurz
2017-02-23 14:52   ` Stefan Hajnoczi
2017-02-20 14:41 ` [Qemu-devel] [PATCH 18/29] 9pfs: local: lstat: " Greg Kurz
2017-02-23 14:55   ` Stefan Hajnoczi
2017-02-20 14:41 ` [Qemu-devel] [PATCH 19/29] 9pfs: local: renameat: " Greg Kurz
2017-02-23 14:57   ` Stefan Hajnoczi
2017-02-20 14:41 ` [Qemu-devel] [PATCH 20/29] 9pfs: local: rename: use renameat Greg Kurz
2017-02-23 14:57   ` Stefan Hajnoczi
2017-02-20 14:42 ` [Qemu-devel] [PATCH 21/29] 9pfs: local: improve error handling in link op Greg Kurz
2017-02-23 15:00   ` Stefan Hajnoczi
2017-02-20 14:42 ` [Qemu-devel] [PATCH 22/29] 9pfs: local: link: don't follow symlinks Greg Kurz
2017-02-23 15:01   ` Stefan Hajnoczi
2017-02-20 14:42 ` [Qemu-devel] [PATCH 23/29] 9pfs: local: chmod: " Greg Kurz
2017-02-23 15:10   ` Stefan Hajnoczi
2017-02-24 10:34     ` Greg Kurz
2017-02-24 15:23       ` Eric Blake [this message]
2017-02-24 16:22         ` Jann Horn
2017-02-24 19:25           ` Greg Kurz
2017-02-20 14:42 ` [Qemu-devel] [PATCH 24/29] 9pfs: local: chown: " Greg Kurz
2017-02-23 15:10   ` Stefan Hajnoczi
2017-02-20 14:42 ` [Qemu-devel] [PATCH 25/29] 9pfs: local: symlink: " Greg Kurz
2017-02-23 15:15   ` Stefan Hajnoczi
2017-02-20 14:42 ` [Qemu-devel] [PATCH 26/29] 9pfs: local: mknod: " Greg Kurz
2017-02-23 15:16   ` Stefan Hajnoczi
2017-02-20 14:42 ` [Qemu-devel] [PATCH 27/29] 9pfs: local: mkdir: " Greg Kurz
2017-02-23 15:16   ` Stefan Hajnoczi
2017-02-20 14:42 ` [Qemu-devel] [PATCH 28/29] 9pfs: local: open2: " Greg Kurz
2017-02-23 15:22   ` Stefan Hajnoczi
2017-02-20 14:43 ` [Qemu-devel] [PATCH 29/29] 9pfs: local: drop unused code Greg Kurz
2017-02-23 15:22   ` Stefan Hajnoczi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b3f08f09-9678-2142-c4d7-5a66f49b173d@redhat.com \
    --to=eblake@redhat.com \
    --cc=aneesh.kumar@linux.vnet.ibm.com \
    --cc=groug@kaod.org \
    --cc=jannh@google.com \
    --cc=prasad@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@gmail.com \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.