tmpfiles: if we get ENOENT when opening /proc/self/fd/, check if /proc is mounted

let's return ENOSYS in that case, to make things a bit less confusng.

Previously we'd just propagate ENOENT, which people might mistake as
applying to the object being modified rather than /proc/ just not being
there.

Let's return ENOSYS instead, i.e. an error clearly indicating that some
kernel API is not available. This hopefully should put people on a
better track.

Note that we only do the procfs check in the error path, which hopefully
means it's the less likely path.

We probably can add similar bits to more suitable codepaths dealing with
/proc/self/fd, but for now, let's pick to the ones noticed in #14745.

Fixes: #14745
This commit is contained in:
Lennart Poettering 2020-04-23 14:52:10 +02:00
parent 883fff25f4
commit f8606626ed
3 changed files with 25 additions and 5 deletions

View File

@ -21,9 +21,10 @@
#include "path-util.h"
#include "process-util.h"
#include "socket-util.h"
#include "stat-util.h"
#include "stdio-util.h"
#include "util.h"
#include "tmpfile-util.h"
#include "util.h"
/* The maximum number of iterations in the loop to close descriptors in the fallback case
* when /proc/self/fd/ is inaccessible. */
@ -939,8 +940,15 @@ int fd_reopen(int fd, int flags) {
xsprintf(procfs_path, "/proc/self/fd/%i", fd);
new_fd = open(procfs_path, flags);
if (new_fd < 0)
return -errno;
if (new_fd < 0) {
if (errno != ENOENT)
return -errno;
if (proc_mounted() == 0)
return -ENOSYS; /* if we have no /proc/, the concept is not implementable */
return -ENOENT;
}
return new_fd;
}

View File

@ -337,8 +337,15 @@ int fchmod_opath(int fd, mode_t m) {
* fchownat() does. */
xsprintf(procfs_path, "/proc/self/fd/%i", fd);
if (chmod(procfs_path, m) < 0)
return -errno;
if (chmod(procfs_path, m) < 0) {
if (errno != ENOENT)
return -errno;
if (proc_mounted() == 0)
return -ENOSYS; /* if we have no /proc/, the concept is not implementable */
return -ENOENT;
}
return 0;
}

View File

@ -1078,6 +1078,11 @@ static int fd_set_acls(Item *item, int fd, const char *path, const struct stat *
if (r > 0)
return -r; /* already warned */
/* The above procfs paths don't work if /proc is not mounted. */
if (r == -ENOENT && proc_mounted() == 0)
r = -ENOSYS;
if (r == -EOPNOTSUPP) {
log_debug_errno(r, "ACLs not supported by file system at %s", path);
return 0;