summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/pseudo/files/add_ignore_paths.patch
blob: eddfdb8674b0914ac44634d1cc2d7716438e0f74 (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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
Currently, pseudo considers any path accessed whist its running to be
a valid entry to track in its database. The way OpenEmbedded uses pseudo,
there are paths we care about accesses to from a pseudo perspective and paths
which we simply don't care about.

This patch adds a PSEUDO_IGNORE_PATHS environment variable which is a comma
separated list of path prefixes to ignore accesses to.

To do this, we add some functions which can check a path argument or a file
descriptor argument and use these in the pseudo wrappers where path or fd
arguments are present. Where paths are being ignored, we skip straight to
the underlying real function.

Psuedo needs to keep track of the open fd mappings to files so we still need
to allow those cases into the pseudo_op function. Specficially this means
OP_CLOSE, OP_OPEN, OP_DUP and OP_CHDIR.

Apart from OP_OPEN which could call the server, the other operations are client
side only so passed through. We 'tag' the functions using these operations so
that the path ignore code isn't triggered. For OP_OPEN we exit early and skip
the server op. We also have a catch all in client_op to ensure any operatings
we didn't manage to skip early still get skipped correctly.

OP_CHROOT is a special case. Where ignored path prefixes are used as a chroot,
for the lifetime of the chroot, the path is effectively dropped from the
PSEUDO_IGNORE_PATHS list. Whilst slightly counter intuaitive, this turned out
to be the most effective way to do things due to commands like useradd and
their use of chroots.

For sqlite3 and appropriate path filtering in OE, this took the database from
45,000 entries to about 180. For dbus this was 88,000 down to 760. Given the
number of client to server trips these numbers of paths involves, the win
is seemingly worthwhile.

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Upstream-Status: Pending

Index: git/pseudo_client.c
===================================================================
--- git.orig/pseudo_client.c
+++ git/pseudo_client.c
@@ -1482,6 +1482,43 @@ base_path(int dirfd, const char *path, i
 	return newpath;
 }
 
+int pseudo_client_ignore_fd(int fd) {
+	if (fd >= 0 && fd <= nfds)
+		return pseudo_client_ignore_path(fd_path(fd));
+	return 0;
+}
+
+int pseudo_client_ignore_path_chroot(const char *path, int ignore_chroot) {
+	char *env;
+	if (path) {
+		if (ignore_chroot && pseudo_chroot && strncmp(path, pseudo_chroot, pseudo_chroot_len) == 0)
+			return 0;
+		env = pseudo_get_value("PSEUDO_IGNORE_PATHS");
+		if (env) {
+			char *p = env;
+        	        while (*p) {
+				char *next = strchr(p, ',');
+				if (!next)
+				    next = strchr(p, '\0');
+				if ((next - p) && !strncmp(path, p, next - p)) {
+		 			pseudo_debug(PDBGF_PATH | PDBGF_VERBOSE, "ignoring path: '%s'\n", path);
+					return 1;
+				}
+				if (next && *next != '\0')
+					p = next+1;
+				else
+					break;
+			}
+			free(env);
+		}
+	}
+	return 0;
+}
+
+int pseudo_client_ignore_path(const char *path) {
+	return pseudo_client_ignore_path_chroot(path, 1);
+}
+
 pseudo_msg_t *
 pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path, const PSEUDO_STATBUF *buf, ...) {
 	pseudo_msg_t *result = 0;
@@ -1522,6 +1559,16 @@ pseudo_client_op(pseudo_op_t op, int acc
 		}
 	}
 
+	if (op != OP_CHROOT && op != OP_CHDIR && op != OP_CLOSE && op != OP_DUP
+			&& pseudo_client_ignore_path_chroot(path, 0)) {
+		if (op == OP_OPEN) {
+			pseudo_client_path(fd, path);
+		}
+		/* reenable wrappers */
+		pseudo_magic();
+		return result;
+	}
+
 #ifdef PSEUDO_XATTRDB
 	if (buf) {
 		struct stat64 bufcopy = *buf;
Index: git/pseudo_util.c
===================================================================
--- git.orig/pseudo_util.c
+++ git/pseudo_util.c
@@ -43,6 +43,7 @@ static struct pseudo_variables pseudo_en
 	{ "PSEUDO_BINDIR", 13, NULL },
 	{ "PSEUDO_LIBDIR", 13, NULL },
 	{ "PSEUDO_LOCALSTATEDIR", 20, NULL },
+	{ "PSEUDO_IGNORE_PATHS", 19, NULL },
 	{ "PSEUDO_PASSWD", 13, NULL },
 	{ "PSEUDO_CHROOT", 13, NULL },
 	{ "PSEUDO_UIDS", 11, NULL },
Index: git/pseudo_client.h
===================================================================
--- git.orig/pseudo_client.h
+++ git/pseudo_client.h
@@ -7,6 +7,8 @@
  *
  */
 extern pseudo_msg_t *pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path, const PSEUDO_STATBUF *buf, ...);
+extern int pseudo_client_ignore_path(const char *path);
+extern int pseudo_client_ignore_fd(int fd);
 #if PSEUDO_STATBUF_64
 #define base_lstat real_lstat64
 #define base_fstat real_fstat64
Index: git/ports/linux/wrapfuncs.in
===================================================================
--- git.orig/ports/linux/wrapfuncs.in
+++ git/ports/linux/wrapfuncs.in
@@ -1,23 +1,23 @@
-int open(const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW */
+int open(const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW, noignore_path=1 */
 char *get_current_dir_name(void);
 int __xstat(int ver, const char *path, struct stat *buf);
 int __lxstat(int ver, const char *path, struct stat *buf); /* flags=AT_SYMLINK_NOFOLLOW */
 int __fxstat(int ver, int fd, struct stat *buf);
 int lchown(const char *path, uid_t owner, gid_t group); /* flags=AT_SYMLINK_NOFOLLOW */
 int __fxstatat(int ver, int dirfd, const char *path, struct stat *buf, int flags);
-int openat(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW */
-int __openat_2(int dirfd, const char *path, int flags); /* flags=flags&O_NOFOLLOW */
+int openat(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW, noignore_path=1 */
+int __openat_2(int dirfd, const char *path, int flags); /* flags=flags&O_NOFOLLOW, noignore_path=1 */
 int mknod(const char *path, mode_t mode, dev_t dev); /* real_func=pseudo_mknod */
 int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev); /* real_func=pseudo_mknodat */
 int __xmknod(int ver, const char *path, mode_t mode, dev_t *dev); /* flags=AT_SYMLINK_NOFOLLOW */
 int __xmknodat(int ver, int dirfd, const char *path, mode_t mode, dev_t *dev); /* flags=AT_SYMLINK_NOFOLLOW */
-int fcntl(int fd, int cmd, ...{struct flock *lock});
+int fcntl(int fd, int cmd, ...{struct flock *lock});  /* noignore_path=1 */
 # just so we know the inums of symlinks
 char *canonicalize_file_name(const char *filename);
 int eaccess(const char *path, int mode);
-int open64(const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW */
-int openat64(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW */
-int __openat64_2(int dirfd, const char *path, int flags); /* flags=flags&O_NOFOLLOW */
+int open64(const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW, noignore_path=1 */
+int openat64(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW, noignore_path=1 */
+int __openat64_2(int dirfd, const char *path, int flags); /* flags=flags&O_NOFOLLOW, noignore_path=1 */
 int creat64(const char *path, mode_t mode);
 int stat(const char *path, struct stat *buf); /* real_func=pseudo_stat */
 int lstat(const char *path, struct stat *buf); /* real_func=pseudo_lstat, flags=AT_SYMLINK_NOFOLLOW */
@@ -29,9 +29,9 @@ int __xstat64(int ver, const char *path,
 int __lxstat64(int ver, const char *path, struct stat64 *buf); /* flags=AT_SYMLINK_NOFOLLOW */
 int __fxstat64(int ver, int fd, struct stat64 *buf);
 int __fxstatat64(int ver, int dirfd, const char *path, struct stat64 *buf, int flags);
-FILE *fopen64(const char *path, const char *mode);
-int nftw64(const char *path, int (*fn)(const char *, const struct stat64 *, int, struct FTW *), int nopenfd, int flag);
-FILE *freopen64(const char *path, const char *mode, FILE *stream);
+FILE *fopen64(const char *path, const char *mode); /* noignore_path=1 */
+int nftw64(const char *path, int (*fn)(const char *, const struct stat64 *, int, struct FTW *), int nopenfd, int flag); /* noignore_path=1 */
+FILE *freopen64(const char *path, const char *mode, FILE *stream);  /* noignore_path=1 */
 int ftw64(const char *path, int (*fn)(const char *, const struct stat64 *, int), int nopenfd);
 int glob64(const char *pattern, int flags, int (*errfunc)(const char *, int), glob64_t *pglob);
 int scandir64(const char *path, struct dirent64 ***namelist, int (*filter)(const struct dirent64 *), int (*compar)());
Index: git/templates/wrapfuncs.c
===================================================================
--- git.orig/templates/wrapfuncs.c
+++ git/templates/wrapfuncs.c
@@ -60,9 +60,15 @@ ${maybe_async_skip}
 		${rc_assign} (*real_${name})(${call_args});
 	} else {
 		${fix_paths}
-		/* exec*() use this to restore the sig mask */
-		pseudo_saved_sigmask = saved;
-		${rc_assign} wrap_$name(${call_args});
+		if (${ignore_paths}) {
+			/* call the real syscall */
+			pseudo_debug(PDBGF_SYSCALL, "${name} ignored path, calling real syscall.\n");
+			${rc_assign} (*real_${name})(${call_args});
+		} else {
+			/* exec*() use this to restore the sig mask */
+			pseudo_saved_sigmask = saved;
+			${rc_assign} wrap_$name(${call_args});
+		}
 	}
 	${variadic_end}
 	save_errno = errno;
Index: git/ports/unix/wrapfuncs.in
===================================================================
--- git.orig/ports/unix/wrapfuncs.in
+++ git/ports/unix/wrapfuncs.in
@@ -1,14 +1,14 @@
 int creat(const char *path, mode_t mode);
 char *getcwd(char *buf, size_t size);
 char *getwd(char *buf);
-int close(int fd);
+int close(int fd);  /* noignore_path=1 */
 int fchmod(int fd, mode_t mode);
 int fchown(int fd, uid_t owner, gid_t group);
 int lchown(const char *path, uid_t owner, gid_t group); /* flags=AT_SYMLINK_NOFOLLOW */
-int dup2(int oldfd, int newfd);
-int dup(int fd);
-int chdir(const char *path);
-int fchdir(int dirfd);
+int dup2(int oldfd, int newfd); /* noignore_path=1 */
+int dup(int fd); /* noignore_path=1 */
+int chdir(const char *path); /* noignore_path=1 */
+int fchdir(int dirfd); /* noignore_path=1 */
 int access(const char *path, int mode);
 FTS *fts_open(char * const *path_argv, int options, int (*compar)(const FTSENT **, const FTSENT **)); /* inode64=1 */
 int ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int nopenfd);
@@ -20,18 +20,18 @@ char *mktemp(char *template);
 long pathconf(const char *path, int name);
 char *realpath(const char *name, char *resolved_name); /* version="GLIBC_2.3" */
 int remove(const char *path); /* flags=AT_SYMLINK_NOFOLLOW */
-DIR *opendir(const char *path);
-int closedir(DIR *dirp);
+DIR *opendir(const char *path); /* noignore_path=1 */
+int closedir(DIR *dirp); /* noignore_path=1 */
 char *tempnam(const char *template, const char *pfx);
 char *tmpnam(char *s);
 int truncate(const char *path, off_t length);
 int utime(const char *path, const struct utimbuf *buf);
 int utimes(const char *path, const struct timeval *times);
 # needed because libc stdio does horrible things with inline asm syscalls
-FILE *fopen(const char *path, const char *mode);
-int fclose(FILE *fp);
-FILE *freopen(const char *path, const char *mode, FILE *stream);
-int chroot(const char *path);
+FILE *fopen(const char *path, const char *mode); /* noignore_path=1 */
+int fclose(FILE *fp);  /* noignore_path=1 */
+FILE *freopen(const char *path, const char *mode, FILE *stream); /* noignore_path=1 */
+int chroot(const char *path); /* noignore_path=1 */
 int acct(const char *path);
 int chmod(const char *path, mode_t mode);
 int chown(const char *path, uid_t owner, gid_t group);
Index: git/makewrappers
===================================================================
--- git.orig/makewrappers
+++ git/makewrappers
@@ -228,6 +228,8 @@ class Function:
         self.real_func = None
         self.paths_to_munge = []
         self.specific_dirfds = {}
+        self.fd_arg = False
+        self.noignore_path = False
         self.hand_wrapped = None
         self.async_skip = None
         # used for the copyright date when creating stub functions
@@ -267,6 +269,11 @@ class Function:
                 self.flags = '(flags & AT_SYMLINK_NOFOLLOW)'
             elif arg.name.endswith('path'):
                 self.paths_to_munge.append(arg.name)
+            elif arg.name == 'fd':
+                self.fd_arg = "fd"
+            elif arg.name == 'filedes':
+                self.fd_arg = "filedes"
+
     
         # pick default values
         if self.type == 'void':
@@ -361,6 +368,25 @@ class Function:
                 (path, prefix, self.dirfd, path, self.flags))
         return "\n\t\t".join(fix_paths)
 
+    def ignore_paths(self):
+        if self.noignore_path:
+            return "0"
+
+        mainpath = None
+        if "oldpath" in self.paths_to_munge:
+            mainpath = "oldpath"
+        elif "newpath" in self.paths_to_munge:
+            mainpath = "newpath"
+        elif "path" in self.paths_to_munge:
+            mainpath = "path"
+
+        if mainpath:
+            return "pseudo_client_ignore_path(%s)" % mainpath
+        if self.fd_arg:
+            return "pseudo_client_ignore_fd(%s)" % self.fd_arg
+
+        return "0"
+
     def real_predecl(self):
         if self.real_func:
             return self.decl().replace(self.name, self.real_func, 1) + ";"