diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2020-09-30 14:36:20 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2020-10-07 11:18:38 +0100 |
commit | 842de9dbba53d04644e1c491fc0d4681d66680fd (patch) | |
tree | f3da48774e19f5a5887c99a66d872c5b9367461f | |
parent | 84e0642ed6aba422583871fc153bbd94380074de (diff) | |
download | poky-842de9dbba53d04644e1c491fc0d4681d66680fd.tar.gz |
psuedo: Add tracking of linked files for fds
Where files are link()'d and one is unlink()'d, pseudo's fd mappings
can become confused. Add a patch to try and improve this for the common
usecases we see.
(From OE-Core rev: 9ce621fa2099608ca0ccbb8420b31d71cdd7b00e)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | meta/recipes-devtools/pseudo/files/track_link_fds.patch | 155 | ||||
-rw-r--r-- | meta/recipes-devtools/pseudo/pseudo_git.bb | 1 |
2 files changed, 156 insertions, 0 deletions
diff --git a/meta/recipes-devtools/pseudo/files/track_link_fds.patch b/meta/recipes-devtools/pseudo/files/track_link_fds.patch new file mode 100644 index 0000000000..a3a9eb3f23 --- /dev/null +++ b/meta/recipes-devtools/pseudo/files/track_link_fds.patch | |||
@@ -0,0 +1,155 @@ | |||
1 | Consider what happens if a program does: | ||
2 | |||
3 | fd = fopen("A") | ||
4 | link("A", "B") | ||
5 | unlink("A") | ||
6 | fchown(fd) | ||
7 | |||
8 | Assuming we can't use the database, in order to handle this correctly, | ||
9 | we need to change the open fd to point at B when A us unlinked. | ||
10 | |||
11 | Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> | ||
12 | Upstream-Status: Pending | ||
13 | |||
14 | Index: git/ports/unix/guts/linkat.c | ||
15 | =================================================================== | ||
16 | --- git.orig/ports/unix/guts/linkat.c | ||
17 | +++ git/ports/unix/guts/linkat.c | ||
18 | @@ -116,6 +116,7 @@ | ||
19 | * if the thing linked is a symlink. | ||
20 | */ | ||
21 | pseudo_client_op(OP_LINK, 0, -1, -1, newpath, &buf); | ||
22 | + pseudo_client_linked_paths(oldpath, newpath); | ||
23 | |||
24 | errno = save_errno; | ||
25 | |||
26 | Index: git/pseudo_client.c | ||
27 | =================================================================== | ||
28 | --- git.orig/pseudo_client.c | ||
29 | +++ git/pseudo_client.c | ||
30 | @@ -70,6 +70,8 @@ int pseudo_umask = 022; | ||
31 | |||
32 | static char **fd_paths = NULL; | ||
33 | static int nfds = 0; | ||
34 | +static char **linked_fd_paths = NULL; | ||
35 | +static int linked_nfds = 0; | ||
36 | static const char **passwd_paths = NULL; | ||
37 | static int npasswd_paths = 0; | ||
38 | #ifdef PSEUDO_PROFILING | ||
39 | @@ -889,39 +891,70 @@ fd_path(int fd) { | ||
40 | } | ||
41 | |||
42 | static void | ||
43 | -pseudo_client_path(int fd, const char *path) { | ||
44 | +pseudo_client_path_set(int fd, const char *path, char ***patharray, int *len) { | ||
45 | if (fd < 0) | ||
46 | return; | ||
47 | |||
48 | - if (fd >= nfds) { | ||
49 | + if (fd >= *len) { | ||
50 | int i; | ||
51 | pseudo_debug(PDBGF_CLIENT, "expanding fds from %d to %d\n", | ||
52 | - nfds, fd + 1); | ||
53 | - fd_paths = realloc(fd_paths, (fd + 1) * sizeof(char *)); | ||
54 | - for (i = nfds; i < fd + 1; ++i) | ||
55 | - fd_paths[i] = 0; | ||
56 | - nfds = fd + 1; | ||
57 | + *len, fd + 1); | ||
58 | + (*patharray) = realloc((*patharray), (fd + 1) * sizeof(char *)); | ||
59 | + for (i = *len; i < fd + 1; ++i) | ||
60 | + (*patharray)[i] = 0; | ||
61 | + *len = fd + 1; | ||
62 | } else { | ||
63 | - if (fd_paths[fd]) { | ||
64 | + if ((*patharray)[fd]) { | ||
65 | pseudo_debug(PDBGF_CLIENT, "reopening fd %d [%s] -- didn't see close\n", | ||
66 | - fd, fd_paths[fd]); | ||
67 | + fd, (*patharray)[fd]); | ||
68 | } | ||
69 | /* yes, it is safe to free null pointers. yay for C89 */ | ||
70 | - free(fd_paths[fd]); | ||
71 | - fd_paths[fd] = 0; | ||
72 | + free((*patharray)[fd]); | ||
73 | + (*patharray)[fd] = 0; | ||
74 | } | ||
75 | if (path) { | ||
76 | - fd_paths[fd] = strdup(path); | ||
77 | + (*patharray)[fd] = strdup(path); | ||
78 | + } | ||
79 | +} | ||
80 | + | ||
81 | +static void | ||
82 | +pseudo_client_path(int fd, const char *path) { | ||
83 | + pseudo_client_path_set(fd, path, &fd_paths, &nfds); | ||
84 | +} | ||
85 | + | ||
86 | +void | ||
87 | +pseudo_client_linked_paths(const char *oldpath, const char *newpath) { | ||
88 | + int fd; | ||
89 | + for (fd = 3; fd < nfds; ++fd) { | ||
90 | + if (fd_paths[fd] && !strcmp(oldpath, fd_paths[fd])) { | ||
91 | + pseudo_client_path_set(fd, newpath, &linked_fd_paths, &linked_nfds); | ||
92 | + } | ||
93 | } | ||
94 | } | ||
95 | |||
96 | static void | ||
97 | +pseudo_client_unlinked_path(const char *path) { | ||
98 | + int fd; | ||
99 | + for (fd = 0; fd < linked_nfds; ++fd) { | ||
100 | + if (linked_fd_paths[fd] && fd_paths[fd] && !strcmp(path, fd_paths[fd])) { | ||
101 | + pseudo_client_path(fd, linked_fd_paths[fd]); | ||
102 | + } | ||
103 | + } | ||
104 | +} | ||
105 | + | ||
106 | + | ||
107 | +static void | ||
108 | pseudo_client_close(int fd) { | ||
109 | if (fd < 0 || fd >= nfds) | ||
110 | return; | ||
111 | |||
112 | free(fd_paths[fd]); | ||
113 | fd_paths[fd] = 0; | ||
114 | + | ||
115 | + if (fd < linked_nfds) { | ||
116 | + free(linked_fd_paths[fd]); | ||
117 | + linked_fd_paths[fd] = 0; | ||
118 | + } | ||
119 | } | ||
120 | |||
121 | /* spawn server */ | ||
122 | @@ -1860,6 +1893,12 @@ pseudo_client_op(pseudo_op_t op, int acc | ||
123 | dirfd); | ||
124 | pseudo_client_path(dirfd, fd_path(fd)); | ||
125 | break; | ||
126 | + case OP_UNLINK: | ||
127 | + case OP_DID_UNLINK: | ||
128 | + if (path) | ||
129 | + pseudo_client_unlinked_path(path); | ||
130 | + do_request = 1; | ||
131 | + break; | ||
132 | /* operations for which we should use the magic uid/gid */ | ||
133 | case OP_CHMOD: | ||
134 | case OP_CREAT: | ||
135 | @@ -1882,8 +1921,6 @@ pseudo_client_op(pseudo_op_t op, int acc | ||
136 | case OP_LINK: | ||
137 | case OP_RENAME: | ||
138 | case OP_STAT: | ||
139 | - case OP_UNLINK: | ||
140 | - case OP_DID_UNLINK: | ||
141 | case OP_CANCEL_UNLINK: | ||
142 | case OP_MAY_UNLINK: | ||
143 | case OP_GET_XATTR: | ||
144 | Index: git/pseudo_client.h | ||
145 | =================================================================== | ||
146 | --- git.orig/pseudo_client.h | ||
147 | +++ git/pseudo_client.h | ||
148 | @@ -9,6 +9,7 @@ | ||
149 | extern pseudo_msg_t *pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path, const PSEUDO_STATBUF *buf, ...); | ||
150 | extern int pseudo_client_ignore_path(const char *path); | ||
151 | extern int pseudo_client_ignore_fd(int fd); | ||
152 | +extern void pseudo_client_linked_paths(const char *oldpath, const char *newpath); | ||
153 | #if PSEUDO_STATBUF_64 | ||
154 | #define base_lstat real_lstat64 | ||
155 | #define base_fstat real_fstat64 | ||
diff --git a/meta/recipes-devtools/pseudo/pseudo_git.bb b/meta/recipes-devtools/pseudo/pseudo_git.bb index 56c9b4e232..a5e79ec9a5 100644 --- a/meta/recipes-devtools/pseudo/pseudo_git.bb +++ b/meta/recipes-devtools/pseudo/pseudo_git.bb | |||
@@ -5,6 +5,7 @@ SRC_URI = "git://git.yoctoproject.org/pseudo;branch=oe-core \ | |||
5 | file://delete_mismatches.patch \ | 5 | file://delete_mismatches.patch \ |
6 | file://add_ignore_paths.patch \ | 6 | file://add_ignore_paths.patch \ |
7 | file://abort_on_mismatch.patch \ | 7 | file://abort_on_mismatch.patch \ |
8 | file://track_link_fds.patch \ | ||
8 | file://fallback-passwd \ | 9 | file://fallback-passwd \ |
9 | file://fallback-group \ | 10 | file://fallback-group \ |
10 | " | 11 | " |