mirror of
https://git.yoctoproject.org/poky
synced 2026-04-22 15:32:14 +02:00
pseudo: Update to account for patches merged on branch
(From OE-Core rev: 9002c81b8996bfbdf3fa1b8b15a198408b749d1d) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> (cherry picked from commit ea22fb3aa1c5dd3edcd1d8b415a0843a9ee4677c) Signed-off-by: Steve Sakoman <steve@sakoman.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
@@ -1,64 +0,0 @@
|
||||
Rather than mapping mismatched inode entries to paths, thrown an abort()
|
||||
instead. Add a new result type to allow the server to pass back
|
||||
this instruction to the client.
|
||||
|
||||
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
|
||||
Upstream-Status: Pending
|
||||
|
||||
Index: git/pseudo.c
|
||||
===================================================================
|
||||
--- git.orig/pseudo.c
|
||||
+++ git/pseudo.c
|
||||
@@ -695,17 +695,15 @@ pseudo_op(pseudo_msg_t *msg, const char
|
||||
msg->path);
|
||||
pdb_did_unlink_file(path_by_ino, &by_ino, by_ino.deleting);
|
||||
} else {
|
||||
- int flags = 0;
|
||||
- if (msg->nlink > 1) {
|
||||
- flags = PDBGF_FILE | PDBGF_VERBOSE;
|
||||
- }
|
||||
- pseudo_debug(flags, "path mismatch [%d link%s]: ino %llu db '%s' req '%s'.\n",
|
||||
+ pseudo_diag("path mismatch [%d link%s]: ino %llu db '%s' req '%s'.\n",
|
||||
msg->nlink,
|
||||
msg->nlink == 1 ? "" : "s",
|
||||
(unsigned long long) msg_header.ino,
|
||||
path_by_ino ? path_by_ino : "no path",
|
||||
msg->path);
|
||||
found_ino = 0;
|
||||
+ msg->result = RESULT_ABORT;
|
||||
+ goto op_exit;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1025,6 +1023,7 @@ pseudo_op(pseudo_msg_t *msg, const char
|
||||
break;
|
||||
}
|
||||
|
||||
+op_exit:
|
||||
/* in the case of an exact match, we just used the pointer
|
||||
* rather than allocating space.
|
||||
*/
|
||||
Index: git/pseudo_client.c
|
||||
===================================================================
|
||||
--- git.orig/pseudo_client.c
|
||||
+++ git/pseudo_client.c
|
||||
@@ -1919,6 +1919,10 @@ pseudo_client_op(pseudo_op_t op, int acc
|
||||
#endif
|
||||
if (result) {
|
||||
pseudo_debug(PDBGF_OP, "(%d) %s", getpid(), pseudo_res_name(result->result));
|
||||
+ if (result->result == RESULT_ABORT) {
|
||||
+ pseudo_diag("abort()ing pseudi client by server request. See https://wiki.yoctoproject.org/wiki/Pseudo_Abort for more details on this.\n");
|
||||
+ abort();
|
||||
+ }
|
||||
if (op == OP_STAT || op == OP_FSTAT) {
|
||||
pseudo_debug(PDBGF_OP, " mode 0%o uid %d:%d",
|
||||
(int) result->mode,
|
||||
Index: git/enums/res.in
|
||||
===================================================================
|
||||
--- git.orig/enums/res.in
|
||||
+++ git/enums/res.in
|
||||
@@ -2,3 +2,4 @@ res: RESULT
|
||||
succeed
|
||||
fail
|
||||
error
|
||||
+abort
|
||||
@@ -1,298 +0,0 @@
|
||||
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) + ";"
|
||||
@@ -1,51 +0,0 @@
|
||||
When we see cases where the inode no longer matches the file path, pseudo
|
||||
notices but currently reuses the database entry. This can happen where for
|
||||
example, a file is deleted and a new file created outside of pseudo where
|
||||
the inode number is reused.
|
||||
|
||||
Change this to ignore the likely stale database entry instead. We're
|
||||
seeing bugs where inode reuse for deleted files causes permission corruption.
|
||||
(See bug #14057 for example). We don't want to delete the database entry
|
||||
as the permissions may need to be applied to that file (and testing shows
|
||||
we do need the path matching code which handles that).
|
||||
|
||||
I appreciate this should never happen under the original design of pseudo
|
||||
where all file accesses are monitored by pseudo. The reality is to do that,
|
||||
we'd have to run pseudo:
|
||||
|
||||
a) for all tasks
|
||||
b) as one pseudo database for all of TMPDIR
|
||||
|
||||
Neither of these is realistically possible for performance reasons.
|
||||
|
||||
I believe pseudo to be much better at catching all accesses than it
|
||||
might once have been. As such, these "fixups" are in the cases I've
|
||||
seen in the logs, always incorrect.
|
||||
|
||||
It therefore makes more sense to ignore the database data rather than
|
||||
corrupt the file permissions or worse. Looking at the pseudo logs
|
||||
in my heavily reused build directories, the number of these
|
||||
errors is staggering. This issue would explain many weird bugs we've
|
||||
seen over the years.
|
||||
|
||||
There is a risk that we could not map permissions in some case where
|
||||
we currently would. I have not seen evidence of this in any logs I've
|
||||
read though. This change, whilst going against the original design,
|
||||
is in my view the safer option for the project at this point given we
|
||||
don't use pseudo as originally designed and never will be able to.
|
||||
|
||||
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
|
||||
Upstream-Status: Pending
|
||||
|
||||
Index: git/pseudo.c
|
||||
===================================================================
|
||||
--- git.orig/pseudo.c
|
||||
+++ git/pseudo.c
|
||||
@@ -699,6 +701,7 @@ pseudo_op(pseudo_msg_t *msg, const char
|
||||
(unsigned long long) msg_header.ino,
|
||||
path_by_ino ? path_by_ino : "no path",
|
||||
msg->path);
|
||||
+ found_ino = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1,37 +0,0 @@
|
||||
Some operations may call unlink() on an open fd, then call fchown/fchmod/fstat
|
||||
on that fd. This would currently readd its entry to the database, which
|
||||
is necessary to preserve its permissions information however since that
|
||||
file will be lost when it is closed, we don't want the DB entry to persist.
|
||||
Marking it as may_unlink means the code will know its likely been deleted
|
||||
and ignore the entry later, giving improved behaviour that simple path
|
||||
mismatch warnings. We can use an nlink of zero to detect this.
|
||||
|
||||
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
|
||||
Upstream-Status: Pending
|
||||
|
||||
Index: git/pseudo.c
|
||||
===================================================================
|
||||
--- git.orig/pseudo.c
|
||||
+++ git/pseudo.c
|
||||
@@ -1100,6 +1100,21 @@ pseudo_op(pseudo_msg_t *msg, const char
|
||||
break;
|
||||
}
|
||||
|
||||
+ switch (msg->op) {
|
||||
+ case OP_FCHOWN: /* FALLTHROUGH */
|
||||
+ case OP_FCHMOD: /* FALLTHROUGH */
|
||||
+ case OP_FSTAT:
|
||||
+ if (!found_path && !found_ino && (msg->nlink == 0)) {
|
||||
+ /* If nlink is 0 for an fchown/fchmod/fstat, we probably have an fd which is
|
||||
+ * unlinked and we don't want to do inode/path matching against it. Marking it
|
||||
+ * as may unlink gives the right hints in the database to ensure we
|
||||
+ * handle correctly whilst maintaining the permissions whilst the
|
||||
+ * file exists for the fd. */
|
||||
+ pdb_may_unlink_file(msg, msg->client);
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
op_exit:
|
||||
/* in the case of an exact match, we just used the pointer
|
||||
* rather than allocating space.
|
||||
@@ -1,25 +0,0 @@
|
||||
We're seeing systems in the wild (e.g. ubuntu 20.04) which call
|
||||
with a dirfd set to the full filename and path set to "". Since
|
||||
this seems to be expected to work, handle it accordingly.
|
||||
|
||||
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
|
||||
@@ -1549,8 +1549,12 @@ base_path(int dirfd, const char *path, i
|
||||
|
||||
if (!path)
|
||||
return NULL;
|
||||
- if (!*path)
|
||||
+
|
||||
+ if (!*path) {
|
||||
+ if (dirfd != -1 && dirfd != AT_FDCWD)
|
||||
+ return fd_path(dirfd);
|
||||
return "";
|
||||
+ }
|
||||
|
||||
if (path[0] != '/') {
|
||||
if (dirfd != -1 && dirfd != AT_FDCWD) {
|
||||
@@ -1,56 +0,0 @@
|
||||
There is magic in the posts where specific variable names have specific
|
||||
magic. For that magic to work, "path" needs to be used not "pathname" as
|
||||
is currently there. Fix this, which fixes path issues on systems using
|
||||
statx (Ubuntu 20.04 in particular).
|
||||
|
||||
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
|
||||
Upstream-Status: Pending
|
||||
|
||||
Index: git/ports/linux/statx/guts/statx.c
|
||||
===================================================================
|
||||
--- git.orig/ports/linux/statx/guts/statx.c
|
||||
+++ git/ports/linux/statx/guts/statx.c
|
||||
@@ -5,14 +5,14 @@
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*
|
||||
* int
|
||||
- * statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf) {
|
||||
+ * statx(int dirfd, const char *path, int flags, unsigned int mask, struct statx *statxbuf) {
|
||||
* int rc = -1;
|
||||
*/
|
||||
pseudo_msg_t *msg;
|
||||
PSEUDO_STATBUF buf;
|
||||
int save_errno;
|
||||
|
||||
- rc = real_statx(dirfd, pathname, flags, mask, statxbuf);
|
||||
+ rc = real_statx(dirfd, path, flags, mask, statxbuf);
|
||||
save_errno = errno;
|
||||
if (rc == -1) {
|
||||
return rc;
|
||||
@@ -25,16 +25,16 @@
|
||||
buf.st_mode = statxbuf->stx_mode;
|
||||
buf.st_rdev = makedev(statxbuf->stx_rdev_major, statxbuf->stx_rdev_minor);
|
||||
buf.st_nlink = statxbuf->stx_nlink;
|
||||
- msg = pseudo_client_op(OP_STAT, 0, -1, dirfd, pathname, &buf);
|
||||
+ msg = pseudo_client_op(OP_STAT, 0, -1, dirfd, path, &buf);
|
||||
if (msg && msg->result == RESULT_SUCCEED) {
|
||||
- pseudo_debug(PDBGF_FILE, "statx(path %s), flags %o, stat rc %d, stat uid %o\n", pathname, flags, rc, statxbuf->stx_uid);
|
||||
+ pseudo_debug(PDBGF_FILE, "statx(path %s), flags %o, stat rc %d, stat uid %o\n", path, flags, rc, statxbuf->stx_uid);
|
||||
statxbuf->stx_uid = msg->uid;
|
||||
statxbuf->stx_gid = msg->gid;
|
||||
statxbuf->stx_mode = msg->mode;
|
||||
statxbuf->stx_rdev_major = major(msg->rdev);
|
||||
statxbuf->stx_rdev_minor = minor(msg->rdev);
|
||||
} else {
|
||||
- pseudo_debug(PDBGF_FILE, "statx(path %s) failed, flags %o, stat rc %d, stat uid %o\n", pathname, flags, rc, statxbuf->stx_uid);
|
||||
+ pseudo_debug(PDBGF_FILE, "statx(path %s) failed, flags %o, stat rc %d, stat uid %o\n", path, flags, rc, statxbuf->stx_uid);
|
||||
}
|
||||
errno = save_errno;
|
||||
/* return rc;
|
||||
Index: git/ports/linux/statx/wrapfuncs.in
|
||||
===================================================================
|
||||
--- git.orig/ports/linux/statx/wrapfuncs.in
|
||||
+++ git/ports/linux/statx/wrapfuncs.in
|
||||
@@ -1 +1 @@
|
||||
-int statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf);
|
||||
+int statx(int dirfd, const char *path, int flags, unsigned int mask, struct statx *statxbuf);
|
||||
@@ -1,155 +0,0 @@
|
||||
Consider what happens if a program does:
|
||||
|
||||
fd = fopen("A")
|
||||
link("A", "B")
|
||||
unlink("A")
|
||||
fchown(fd)
|
||||
|
||||
Assuming we can't use the database, in order to handle this correctly,
|
||||
we need to change the open fd to point at B when A us unlinked.
|
||||
|
||||
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
|
||||
Upstream-Status: Pending
|
||||
|
||||
Index: git/ports/unix/guts/linkat.c
|
||||
===================================================================
|
||||
--- git.orig/ports/unix/guts/linkat.c
|
||||
+++ git/ports/unix/guts/linkat.c
|
||||
@@ -116,6 +116,7 @@
|
||||
* if the thing linked is a symlink.
|
||||
*/
|
||||
pseudo_client_op(OP_LINK, 0, -1, -1, newpath, &buf);
|
||||
+ pseudo_client_linked_paths(oldpath, newpath);
|
||||
|
||||
errno = save_errno;
|
||||
|
||||
Index: git/pseudo_client.c
|
||||
===================================================================
|
||||
--- git.orig/pseudo_client.c
|
||||
+++ git/pseudo_client.c
|
||||
@@ -70,6 +70,8 @@ int pseudo_umask = 022;
|
||||
|
||||
static char **fd_paths = NULL;
|
||||
static int nfds = 0;
|
||||
+static char **linked_fd_paths = NULL;
|
||||
+static int linked_nfds = 0;
|
||||
static const char **passwd_paths = NULL;
|
||||
static int npasswd_paths = 0;
|
||||
#ifdef PSEUDO_PROFILING
|
||||
@@ -889,39 +891,70 @@ fd_path(int fd) {
|
||||
}
|
||||
|
||||
static void
|
||||
-pseudo_client_path(int fd, const char *path) {
|
||||
+pseudo_client_path_set(int fd, const char *path, char ***patharray, int *len) {
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
- if (fd >= nfds) {
|
||||
+ if (fd >= *len) {
|
||||
int i;
|
||||
pseudo_debug(PDBGF_CLIENT, "expanding fds from %d to %d\n",
|
||||
- nfds, fd + 1);
|
||||
- fd_paths = realloc(fd_paths, (fd + 1) * sizeof(char *));
|
||||
- for (i = nfds; i < fd + 1; ++i)
|
||||
- fd_paths[i] = 0;
|
||||
- nfds = fd + 1;
|
||||
+ *len, fd + 1);
|
||||
+ (*patharray) = realloc((*patharray), (fd + 1) * sizeof(char *));
|
||||
+ for (i = *len; i < fd + 1; ++i)
|
||||
+ (*patharray)[i] = 0;
|
||||
+ *len = fd + 1;
|
||||
} else {
|
||||
- if (fd_paths[fd]) {
|
||||
+ if ((*patharray)[fd]) {
|
||||
pseudo_debug(PDBGF_CLIENT, "reopening fd %d [%s] -- didn't see close\n",
|
||||
- fd, fd_paths[fd]);
|
||||
+ fd, (*patharray)[fd]);
|
||||
}
|
||||
/* yes, it is safe to free null pointers. yay for C89 */
|
||||
- free(fd_paths[fd]);
|
||||
- fd_paths[fd] = 0;
|
||||
+ free((*patharray)[fd]);
|
||||
+ (*patharray)[fd] = 0;
|
||||
}
|
||||
if (path) {
|
||||
- fd_paths[fd] = strdup(path);
|
||||
+ (*patharray)[fd] = strdup(path);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+pseudo_client_path(int fd, const char *path) {
|
||||
+ pseudo_client_path_set(fd, path, &fd_paths, &nfds);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+pseudo_client_linked_paths(const char *oldpath, const char *newpath) {
|
||||
+ int fd;
|
||||
+ for (fd = 3; fd < nfds; ++fd) {
|
||||
+ if (fd_paths[fd] && !strcmp(oldpath, fd_paths[fd])) {
|
||||
+ pseudo_client_path_set(fd, newpath, &linked_fd_paths, &linked_nfds);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
+pseudo_client_unlinked_path(const char *path) {
|
||||
+ int fd;
|
||||
+ for (fd = 0; fd < linked_nfds; ++fd) {
|
||||
+ if (linked_fd_paths[fd] && fd_paths[fd] && !strcmp(path, fd_paths[fd])) {
|
||||
+ pseudo_client_path(fd, linked_fd_paths[fd]);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void
|
||||
pseudo_client_close(int fd) {
|
||||
if (fd < 0 || fd >= nfds)
|
||||
return;
|
||||
|
||||
free(fd_paths[fd]);
|
||||
fd_paths[fd] = 0;
|
||||
+
|
||||
+ if (fd < linked_nfds) {
|
||||
+ free(linked_fd_paths[fd]);
|
||||
+ linked_fd_paths[fd] = 0;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* spawn server */
|
||||
@@ -1860,6 +1893,12 @@ pseudo_client_op(pseudo_op_t op, int acc
|
||||
dirfd);
|
||||
pseudo_client_path(dirfd, fd_path(fd));
|
||||
break;
|
||||
+ case OP_UNLINK:
|
||||
+ case OP_DID_UNLINK:
|
||||
+ if (path)
|
||||
+ pseudo_client_unlinked_path(path);
|
||||
+ do_request = 1;
|
||||
+ break;
|
||||
/* operations for which we should use the magic uid/gid */
|
||||
case OP_CHMOD:
|
||||
case OP_CREAT:
|
||||
@@ -1882,8 +1921,6 @@ pseudo_client_op(pseudo_op_t op, int acc
|
||||
case OP_LINK:
|
||||
case OP_RENAME:
|
||||
case OP_STAT:
|
||||
- case OP_UNLINK:
|
||||
- case OP_DID_UNLINK:
|
||||
case OP_CANCEL_UNLINK:
|
||||
case OP_MAY_UNLINK:
|
||||
case OP_GET_XATTR:
|
||||
Index: git/pseudo_client.h
|
||||
===================================================================
|
||||
--- git.orig/pseudo_client.h
|
||||
+++ git/pseudo_client.h
|
||||
@@ -9,6 +9,7 @@
|
||||
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);
|
||||
+extern void pseudo_client_linked_paths(const char *oldpath, const char *newpath);
|
||||
#if PSEUDO_STATBUF_64
|
||||
#define base_lstat real_lstat64
|
||||
#define base_fstat real_fstat64
|
||||
@@ -1,40 +0,0 @@
|
||||
|
||||
In the xattr handling functions, if result is NULL, which it can be
|
||||
with the path ignore code, there is a NULL pointer dereference and
|
||||
segfault. Everywhere else checks result first, this appears to just
|
||||
be an omission.
|
||||
|
||||
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
|
||||
Upstream-Status: Pending
|
||||
|
||||
Index: git/ports/linux/xattr/pseudo_wrappers.c
|
||||
===================================================================
|
||||
--- git.orig/ports/linux/xattr/pseudo_wrappers.c
|
||||
+++ git/ports/linux/xattr/pseudo_wrappers.c
|
||||
@@ -134,7 +134,7 @@ static ssize_t shared_getxattr(const cha
|
||||
pseudo_debug(PDBGF_XATTR, "getxattr(%s [fd %d], %s)\n",
|
||||
path ? path : "<no path>", fd, name);
|
||||
pseudo_msg_t *result = pseudo_client_op(OP_GET_XATTR, 0, fd, -1, path, &buf, name);
|
||||
- if (result->result != RESULT_SUCCEED) {
|
||||
+ if (!result || result->result != RESULT_SUCCEED) {
|
||||
errno = ENOATTR;
|
||||
return -1;
|
||||
}
|
||||
@@ -254,7 +254,7 @@ static int shared_setxattr(const char *p
|
||||
static ssize_t shared_listxattr(const char *path, int fd, char *list, size_t size) {
|
||||
RC_AND_BUF
|
||||
pseudo_msg_t *result = pseudo_client_op(OP_LIST_XATTR, 0, fd, -1, path, &buf);
|
||||
- if (result->result != RESULT_SUCCEED) {
|
||||
+ if (!result || result->result != RESULT_SUCCEED) {
|
||||
pseudo_debug(PDBGF_XATTR, "listxattr: no success.\n");
|
||||
errno = ENOATTR;
|
||||
return -1;
|
||||
@@ -276,7 +276,7 @@ static int shared_removexattr(const char
|
||||
RC_AND_BUF
|
||||
pseudo_msg_t *result = pseudo_client_op(OP_REMOVE_XATTR, 0, fd, -1, path, &buf, name);
|
||||
|
||||
- if (result->result != RESULT_SUCCEED) {
|
||||
+ if (!result || result->result != RESULT_SUCCEED) {
|
||||
/* docs say ENOATTR, but I don't have one */
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
@@ -2,19 +2,11 @@ require pseudo.inc
|
||||
|
||||
SRC_URI = "git://git.yoctoproject.org/pseudo;branch=oe-core \
|
||||
file://0001-configure-Prune-PIE-flags.patch \
|
||||
file://delete_mismatches.patch \
|
||||
file://add_ignore_paths.patch \
|
||||
file://abort_on_mismatch.patch \
|
||||
file://track_link_fds.patch \
|
||||
file://xattr_fix.patch \
|
||||
file://mayunlink.patch \
|
||||
file://pathfix.patch \
|
||||
file://statxfix.patch \
|
||||
file://fallback-passwd \
|
||||
file://fallback-group \
|
||||
"
|
||||
|
||||
SRCREV = "d6b1b13c268d7246f0288d32d6b5eccc658cff4e"
|
||||
SRCREV = "07141f919dc8582460f984ed1d2fb73e05f82ef3"
|
||||
S = "${WORKDIR}/git"
|
||||
PV = "1.9.0+git${SRCPV}"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user