* Naming O_TMPFILE files
@ 2016-09-21 11:50 Florian Weimer
2016-09-23 8:41 ` Florian Weimer
0 siblings, 1 reply; 5+ messages in thread
From: Florian Weimer @ 2016-09-21 11:50 UTC (permalink / raw)
To: linux-man, Linux API, Linux FS Devel, aneesh.kumar, Alexander Viro
[-- Attachment #1: Type: text/plain, Size: 2423 bytes --]
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.
Is this really the intended behavior? Has it always been this way?
Thanks,
Florian
[-- Attachment #2: linkat.c --]
[-- Type: text/x-csrc, Size: 1997 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)
int
main (void)
{
const char *const out_name = "linkat.out";
unlink (out_name);
int fd = open (".", O_RDWR | O_TMPFILE, 0);
if (fd < 0)
err (1, "open");
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)");
CHECK (linkat (fd, "", AT_FDCWD, out_name, AT_EMPTY_PATH));
unlink (out_name);
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);
CHECK (linkat (AT_FDCWD, proc_name, AT_FDCWD, out_name,
AT_SYMLINK_FOLLOW));
unlink (out_name);
CHECK (linkat (AT_FDCWD, proc_name, current_fd, out_name,
AT_SYMLINK_FOLLOW));
unlink (out_name);
snprintf (proc_name, sizeof (proc_name), "%d", fd);
CHECK (linkat (proc_fd, proc_name, AT_FDCWD, out_name,
AT_SYMLINK_FOLLOW));
unlink (out_name);
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;
}
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Naming O_TMPFILE files
2016-09-21 11:50 Naming O_TMPFILE files Florian Weimer
@ 2016-09-23 8:41 ` Florian Weimer
2016-09-26 8:11 ` Michael Kerrisk (man-pages)
0 siblings, 1 reply; 5+ messages in thread
From: Florian Weimer @ 2016-09-23 8:41 UTC (permalink / raw)
To: linux-man, Linux API, Linux FS Devel, aneesh.kumar, Alexander Viro
[-- 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;
}
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Naming O_TMPFILE files
2016-09-23 8:41 ` Florian Weimer
@ 2016-09-26 8:11 ` Michael Kerrisk (man-pages)
2016-09-26 15:11 ` Florian Weimer
0 siblings, 1 reply; 5+ messages in thread
From: Michael Kerrisk (man-pages) @ 2016-09-26 8:11 UTC (permalink / raw)
To: Florian Weimer, linux-man, Linux API, Linux FS Devel,
aneesh.kumar, Alexander Viro
Cc: mtk.manpages
On 09/23/2016 10:41 AM, Florian Weimer wrote:
> 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, could you elaborate on the "can only be linked once in
this way"? In my experiments, it's possible to link multiple times
to the O_TMPFILE file.
Cheers,
Michael
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Naming O_TMPFILE files
2016-09-26 8:11 ` Michael Kerrisk (man-pages)
@ 2016-09-26 15:11 ` Florian Weimer
0 siblings, 0 replies; 5+ messages in thread
From: Florian Weimer @ 2016-09-26 15:11 UTC (permalink / raw)
To: Michael Kerrisk (man-pages)
Cc: Florian Weimer, linux-man, Linux API, Linux FS Devel,
aneesh.kumar, Alexander Viro
* Michael Kerrisk:
> On 09/23/2016 10:41 AM, Florian Weimer wrote:
>>> 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, could you elaborate on the "can only be linked once in
> this way"? In my experiments, it's possible to link multiple times
> to the O_TMPFILE file.
It's in the quoted bits above. After the first success, subsequent
attempts at linking the same file descriptor (with AT_EMPTY_PATH or
the /proc/self/fd kludge) fail. This is what confused me so much, and
makes the behavior seem extremely erratic.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Naming O_TMPFILE files
@ 2016-09-26 15:11 ` Florian Weimer
0 siblings, 0 replies; 5+ messages in thread
From: Florian Weimer @ 2016-09-26 15:11 UTC (permalink / raw)
To: Michael Kerrisk (man-pages)
Cc: Florian Weimer, linux-man, Linux API, Linux FS Devel,
aneesh.kumar, Alexander Viro
* Michael Kerrisk:
> On 09/23/2016 10:41 AM, Florian Weimer wrote:
>>> 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, could you elaborate on the "can only be linked once in
> this way"? In my experiments, it's possible to link multiple times
> to the O_TMPFILE file.
It's in the quoted bits above. After the first success, subsequent
attempts at linking the same file descriptor (with AT_EMPTY_PATH or
the /proc/self/fd kludge) fail. This is what confused me so much, and
makes the behavior seem extremely erratic.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2016-09-26 15:11 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-21 11:50 Naming O_TMPFILE files Florian Weimer
2016-09-23 8:41 ` Florian Weimer
2016-09-26 8:11 ` Michael Kerrisk (man-pages)
2016-09-26 15:11 ` Florian Weimer
2016-09-26 15:11 ` Florian Weimer
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.