From: Eric Blake <eblake@redhat.com>
To: Greg Kurz <groug@kaod.org>, qemu-devel@nongnu.org
Cc: zhiyong.wu@ucloud.cn, "Michael Tokarev" <mjt@tls.msk.ru>,
"Philippe Mathieu-Daudé" <f4bug@amsat.org>
Subject: Re: [Qemu-devel] [for-2.10 PATCH v3] 9pfs: local: fix fchmodat_nofollow() limitations
Date: Wed, 9 Aug 2017 11:19:42 -0500 [thread overview]
Message-ID: <1732154b-1ed6-41e5-7dd2-c9062898ee4b@redhat.com> (raw)
In-Reply-To: <150229440762.12920.17394043752149329973.stgit@bahia.lan>
[-- Attachment #1: Type: text/plain, Size: 3303 bytes --]
On 08/09/2017 11:00 AM, Greg Kurz wrote:
> This function has to ensure it doesn't follow a symlink that could be used
> to escape the virtfs directory. This could be easily achieved if fchmodat()
> on linux honored the AT_SYMLINK_NOFOLLOW flag as described in POSIX, but
> it doesn't. There was a tentative to implement a new fchmodat2() syscall
> with the correct semantics:
>
> https://patchwork.kernel.org/patch/9596301/
>
> but it didn't gain much momentum. Also it was suggested to look at a O_PATH
s/a O_PATH/an O_PATH/
> based solution in the first place.
>
> The current implementation covers most use-cases, but it notably fails if:
> - the target path has access rights equal to 0000 (openat() returns EPERM),
> => once you've done chmod(0000) on a file, you can never chmod() again
> - the target path is UNIX domain socket (openat() returns ENXIO)
> => bind() of UNIX domain sockets fails if the file is on 9pfs
>
> The solution is to use O_PATH: openat() now succeeds in both cases, and we
> can ensure the path isn't a symlink with fstat(). The associated entry in
> "/proc/self/fd" can hence be safely passed to the regular chmod() syscall.
My late-breaking question from v2 remains: fstat() on O_PATH only works
in kernel 3.6 and newer; are we worried about kernels in the window of
2.6.39 (when O_PATH was introduced) and 3.5? Or at this point, are we
reasonably sure that platforms are either too old for O_PATH at all
(Hello RHEL 6, with 2.6.32), or else new enough that we aren't going to
have spurious failures due to fstat() not doing what we want?
I don't actually know the failure mode of fstat() on kernel 3.5, so if
someone cares about that working (presumably because they are on a
platform with such a kernel), please speak up. (Or even run my test
program included on the v1 thread, to show us what happens)
> + fd = openat_file(dirfd, name, O_RDONLY | O_PATH_9P_UTIL, 0);
> +#ifndef O_PATH
Please make this '#if O_PATH' or even '#if O_PATH_9P_UTIL'; as it might
be feasible for someone to
#ifndef O_PATH
#define O_PATH 0
#endif
where the macro is defined but the feature is not present, messing up
our code if we only check for a definition.
> +#else
> + /* Now we handle racing symlinks. */
> + ret = fstat(fd, &stbuf);
> + if (ret) {
> + goto out;
This may leave errno at an unusual value for fchmodat(), if we are on
kernel 3.5. But until someone speaks up that it matters, I'm okay
saving any cleanup work in that area for a followup patch.
> + }
> + if (S_ISLNK(stbuf.st_mode)) {
> + errno = ELOOP;
> + ret = -1;
> + goto out;
> + }
> +
> + {
> + char *proc_path = g_strdup_printf("/proc/self/fd/%d", fd);
> + ret = chmod(proc_path, mode);
> + g_free(proc_path);
> + }
> +#endif
> +out:
Swap these two lines - your only use of 'goto out' are under the O_PATH
branch, and therefore you get a compilation failure about unused label
on older glibc.
With the #if condition fixed and the scope of the #endif fixed,
Reviewed-by: Eric Blake <eblake@redhat.com>
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]
next prev parent reply other threads:[~2017-08-09 16:19 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-09 16:00 [Qemu-devel] [for-2.10 PATCH v3] 9pfs: local: fix fchmodat_nofollow() limitations Greg Kurz
2017-08-09 16:19 ` Eric Blake [this message]
2017-08-09 16:31 ` Greg Kurz
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=1732154b-1ed6-41e5-7dd2-c9062898ee4b@redhat.com \
--to=eblake@redhat.com \
--cc=f4bug@amsat.org \
--cc=groug@kaod.org \
--cc=mjt@tls.msk.ru \
--cc=qemu-devel@nongnu.org \
--cc=zhiyong.wu@ucloud.cn \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).