From: Florian Weimer <fweimer@redhat.com>
To: "linux-man@vger.kernel.org" <linux-man@vger.kernel.org>,
Linux API <linux-api@vger.kernel.org>,
Linux FS Devel <linux-fsdevel@vger.kernel.org>,
aneesh.kumar@linux.vnet.ibm.com,
Alexander Viro <viro@zeniv.linux.org.uk>
Subject: Re: Naming O_TMPFILE files
Date: Fri, 23 Sep 2016 10:41:24 +0200 [thread overview]
Message-ID: <2be4ffbb-abab-42c8-88a3-910230bf0d13@redhat.com> (raw)
In-Reply-To: <0831c636-4513-7c6c-255d-737a4415c8af@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 2685 bytes --]
On 09/21/2016 01:50 PM, Florian Weimer wrote:
> AT_EMPTY_PATH is supposed to be able to give names to files created with
> O_TMPFILE unless O_EXCL was specified at creation time.
>
> However, since this commit
>
> commit 11a7b371b64ef39fc5fb1b6f2218eef7c4d035e3
> Author: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> Date: Sat Jan 29 18:43:42 2011 +0530
>
> fs: allow AT_EMPTY_PATH in linkat(), limit that to CAP_DAC_READ_SEARCH
>
> linkat bails out early with AT_EMPTY_PATH and !CAP_DAC_READ_SEARCH,
> never looking at O_EXCL.
>
> The /proc/self/fd kludge works for unprivileged users, but only if
> *both* paths use AT_FDCWD. It fails if the first path uses a real
> descriptor for /proc/self/fd, or if the second path uses a real
> descriptor for the current directory, or both. For privileged users,
> only AT_EMPTY_PATH case with an AT_FDCWD target works.
>
> The attached test program prints under a non-privileged user:
>
> error: linkat (fd, "", AT_FDCWD, out_name, AT_EMPTY_PATH):
> No such file or directory
> error: linkat (fd, "", current_fd, out_name, AT_EMPTY_PATH):
> No such file or directory
> success: linkat (AT_FDCWD, proc_name, AT_FDCWD, out_name,
> AT_SYMLINK_FOLLOW)
> error: linkat (AT_FDCWD, proc_name, current_fd, out_name,
> AT_SYMLINK_FOLLOW):
> No such file or directory
> error: linkat (proc_fd, proc_name, AT_FDCWD, out_name, AT_SYMLINK_FOLLOW):
> No such file or directory
> error: linkat (proc_fd, proc_name, current_fd, out_name,
> AT_SYMLINK_FOLLOW):
> No such file or directory
> successes: 1, failures: 5
>
> And under a privileged user:
>
> success: linkat (fd, "", AT_FDCWD, out_name, AT_EMPTY_PATH)
> error: linkat (fd, "", current_fd, out_name, AT_EMPTY_PATH):
> No such file or directory
> error: linkat (AT_FDCWD, proc_name, AT_FDCWD, out_name, AT_SYMLINK_FOLLOW):
> No such file or directory
> error: linkat (AT_FDCWD, proc_name, current_fd, out_name,
> AT_SYMLINK_FOLLOW):
> No such file or directory
> error: linkat (proc_fd, proc_name, AT_FDCWD, out_name, AT_SYMLINK_FOLLOW):
> No such file or directory
> error: linkat (proc_fd, proc_name, current_fd, out_name,
> AT_SYMLINK_FOLLOW):
> No such file or directory
> successes: 1, failures: 5
>
> (Seen on tmpfs and XFS, 4.7.x kernels.)
>
> I double-checked with strace, and the test case does not appear to be
> broken. But the exhibited behavior is truly bizarre, and it means that
> it is very difficult to give a name to an O_TMPFILE file.
The test case is broken because it does not account for the fact that an
O_TMPFILE file can only be linked once in this way. This is still a bit
counter-intuitive, but it means that O_TMPFILE works.
Florian
[-- Attachment #2: linkat.c --]
[-- Type: text/x-csrc, Size: 2192 bytes --]
#include <unistd.h>
#include <fcntl.h>
#include <err.h>
#include <stdio.h>
static int failures;
static int successes;
#define CHECK(ret) \
do \
if ((ret) < 0) \
{ \
printf ("error: %s:\n %m\n", #ret); \
++failures; \
} \
else \
{ \
printf ("success: %s\n", #ret); \
++successes; \
} \
while (0)
static const char *const out_name = "linkat.out";
void
setup_fd (int *pfd)
{
if (*pfd >= 0)
close (*pfd);
*pfd = open (".", O_RDWR | O_TMPFILE, 0);
if (*pfd < 0)
err (1, "open");
}
int
main (void)
{
unlink (out_name);
int current_fd = open (".", O_RDONLY | O_DIRECTORY);
if (current_fd < 0)
err (1, "open (O_DIRECTORY)");
int proc_fd = open ("/proc/self/fd", O_RDONLY | O_DIRECTORY);
if (proc_fd < 0)
err (1, "open (O_DIRECTORY)");
int fd = -1;
setup_fd (&fd);
CHECK (linkat (fd, "", AT_FDCWD, out_name, AT_EMPTY_PATH));
unlink (out_name);
setup_fd (&fd);
CHECK (linkat (fd, "", current_fd, out_name, AT_EMPTY_PATH));
unlink (out_name);
char proc_name[100];
snprintf (proc_name, sizeof (proc_name), "/proc/self/fd/%d", fd);
setup_fd (&fd);
CHECK (linkat (AT_FDCWD, proc_name, AT_FDCWD, out_name,
AT_SYMLINK_FOLLOW));
unlink (out_name);
setup_fd (&fd);
CHECK (linkat (AT_FDCWD, proc_name, current_fd, out_name,
AT_SYMLINK_FOLLOW));
unlink (out_name);
snprintf (proc_name, sizeof (proc_name), "%d", fd);
setup_fd (&fd);
CHECK (linkat (proc_fd, proc_name, AT_FDCWD, out_name,
AT_SYMLINK_FOLLOW));
unlink (out_name);
setup_fd (&fd);
CHECK (linkat (proc_fd, proc_name, current_fd, out_name,
AT_SYMLINK_FOLLOW));
unlink (out_name);
printf ("successes: %d, failures: %d\n", successes, failures);
return 0;
}
next prev parent reply other threads:[~2016-09-23 8:41 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-21 11:50 Naming O_TMPFILE files Florian Weimer
2016-09-23 8:41 ` Florian Weimer [this message]
2016-09-26 8:11 ` Michael Kerrisk (man-pages)
2016-09-26 15:11 ` Florian Weimer
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=2be4ffbb-abab-42c8-88a3-910230bf0d13@redhat.com \
--to=fweimer@redhat.com \
--cc=aneesh.kumar@linux.vnet.ibm.com \
--cc=linux-api@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-man@vger.kernel.org \
--cc=viro@zeniv.linux.org.uk \
/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).