summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/systemd/systemd/0007-don-t-pass-AT_SYMLINK_NOFOLLOW-flag-to-faccessat.patch
blob: 1d4ce3371220050ca55f38b707945f7a35f9a841 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
From 5bf8235bc5c802908aa5d95740350927d87e953a Mon Sep 17 00:00:00 2001
From: Andre McCurdy <armccurdy@gmail.com>
Date: Tue, 10 Oct 2017 14:33:30 -0700
Subject: [PATCH] don't pass AT_SYMLINK_NOFOLLOW flag to faccessat()

Avoid using AT_SYMLINK_NOFOLLOW flag. It doesn't seem like the right
thing to do and it's not portable (not supported by musl). See:

  http://lists.landley.net/pipermail/toybox-landley.net/2014-September/003610.html
  http://www.openwall.com/lists/musl/2015/02/05/2

Note that laccess() is never passing AT_EACCESS so a lot of the
discussion in the links above doesn't apply. Note also that
(currently) all systemd callers of laccess() pass mode as F_OK, so
only check for existence of a file, not access permissions.
Therefore, in this case, the only distiction between faccessat()
with (flag == 0) and (flag == AT_SYMLINK_NOFOLLOW) is the behaviour
for broken symlinks; laccess() on a broken symlink will succeed with
(flag == AT_SYMLINK_NOFOLLOW) and fail (flag == 0).

The laccess() macros was added to systemd some time ago and it's not
clear if or why it needs to return success for broken symlinks. Maybe
just historical and not actually necessary or desired behaviour?

Upstream-Status: Inappropriate [musl specific]

Signed-off-by: Andre McCurdy <armccurdy@gmail.com>
---
 src/basic/fs-util.h          | 21 ++++++++++++++++++++-
 src/shared/base-filesystem.c |  6 +++---
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h
index 6a1e2e76d1..c3f7235e09 100644
--- a/src/basic/fs-util.h
+++ b/src/basic/fs-util.h
@@ -49,8 +49,27 @@ int futimens_opath(int fd, const struct timespec ts[2]);
 int fd_warn_permissions(const char *path, int fd);
 int stat_warn_permissions(const char *path, const struct stat *st);
 
+/*
+   Avoid using AT_SYMLINK_NOFOLLOW flag. It doesn't seem like the right thing to
+   do and it's not portable (not supported by musl). See:
+
+     http://lists.landley.net/pipermail/toybox-landley.net/2014-September/003610.html
+     http://www.openwall.com/lists/musl/2015/02/05/2
+
+   Note that laccess() is never passing AT_EACCESS so a lot of the discussion in
+   the links above doesn't apply. Note also that (currently) all systemd callers
+   of laccess() pass mode as F_OK, so only check for existence of a file, not
+   access permissions. Therefore, in this case, the only distiction between
+   faccessat() with (flag == 0) and (flag == AT_SYMLINK_NOFOLLOW) is the
+   behaviour for broken symlinks; laccess() on a broken symlink will succeed
+   with (flag == AT_SYMLINK_NOFOLLOW) and fail (flag == 0).
+
+   The laccess() macros was added to systemd some time ago and it's not clear if
+   or why it needs to return success for broken symlinks. Maybe just historical
+   and not actually necessary or desired behaviour?
+*/
 #define laccess(path, mode)                                             \
-        RET_NERRNO(faccessat(AT_FDCWD, (path), (mode), AT_SYMLINK_NOFOLLOW))
+        RET_NERRNO(faccessat(AT_FDCWD, (path), (mode), 0))
 
 int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode);
 
diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c
index a4e2dae245..67aa8ea1f2 100644
--- a/src/shared/base-filesystem.c
+++ b/src/shared/base-filesystem.c
@@ -145,7 +145,7 @@ int base_filesystem_create_fd(int fd, const char *root, uid_t uid, gid_t gid) {
         /* The "root" parameter is decoration only – it's only used as part of log messages */
 
         for (size_t i = 0; i < ELEMENTSOF(table); i++) {
-                if (faccessat(fd, table[i].dir, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+                if (faccessat(fd, table[i].dir, F_OK, 0) >= 0)
                         continue;
 
                 if (table[i].target) { /* Create as symlink? */
@@ -153,7 +153,7 @@ int base_filesystem_create_fd(int fd, const char *root, uid_t uid, gid_t gid) {
 
                         /* check if one of the targets exists */
                         NULSTR_FOREACH(s, table[i].target) {
-                                if (faccessat(fd, s, F_OK, AT_SYMLINK_NOFOLLOW) < 0)
+                                if (faccessat(fd, s, F_OK, 0) < 0)
                                         continue;
 
                                 /* check if a specific file exists at the target path */
@@ -164,7 +164,7 @@ int base_filesystem_create_fd(int fd, const char *root, uid_t uid, gid_t gid) {
                                         if (!p)
                                                 return log_oom();
 
-                                        if (faccessat(fd, p, F_OK, AT_SYMLINK_NOFOLLOW) < 0)
+                                        if (faccessat(fd, p, F_OK, 0) < 0)
                                                 continue;
                                 }