@@ -248,6 +248,11 @@ class Function:
self.date = datetime.date.today().year
# Used to define pointers that should EFAULT if null
self.efault = None
+
+ # Used for functions which need to called with the original unconverted paths, e.g. openat2
+ # In those cases, use a suffix ('_int') for the path variable names instead of
+ # overwriting them. This means the wrapper needs to handle paths itself.
+ self.preserve_paths = False
function, comments = line.split(';')
comment = re.search(r'/\* *(.*) *\*/', comments)
@@ -383,6 +388,11 @@ class Function:
"""present argument list for a function call"""
return self.args.call()
+ def paths_decl(self):
+ if self.preserve_paths:
+ return "\n\t".join("char *" + path + "_int;" for path in self.paths_to_munge)
+ return ""
+
def fix_paths(self):
"""create/allocate canonical paths"""
fix_paths = []
@@ -390,6 +400,9 @@ class Function:
prefix = path[:-4]
if prefix not in self.specific_dirfds:
prefix = ''
+ pathvar = path
+ if self.preserve_paths:
+ pathvar = path + "_int"
if self.dirfd != "AT_FDCWD" and "flags" in self.flags \
and "AT_SYMLINK_NOFOLLOW" in self.flags:
fix_paths.append(
@@ -409,7 +422,7 @@ class Function:
"\t\t}\n" % (path, self.rc_assign()))
fix_paths.append(
"%s = pseudo_root_path(__func__, __LINE__, %s%s, %s, %s);" %
- (path, prefix, self.dirfd, path, self.flags))
+ (pathvar, prefix, self.dirfd, path, self.flags))
return "\n\t\t".join(fix_paths)
def ignore_paths(self):
@@ -424,6 +437,9 @@ class Function:
elif "path" in self.paths_to_munge:
mainpath = "path"
+ if mainpath and self.preserve_paths:
+ mainpath += "_int"
+
if mainpath:
return "pseudo_client_ignore_path(%s)" % mainpath
if self.fd_arg:
@@ -14,6 +14,7 @@
int save_errno;
sigset_t local_saved_sigmask;
struct open_how my_how;
+ char *pseudo_path;
/* Validate parameters */
if (!how || size < sizeof(struct open_how)) {
@@ -25,6 +26,19 @@
return -1;
}
+ /* This wrapper is not called with modified paths, therefore we have to handle this ourselves.
+ We can't use the standard mappings since the function needs relative paths to be preserved,
+ they can't be our usual absolute paths. An example difference:
+ openat2(AT_FDCWD, "/tmp/testdir/dir1/dir2/", {flags=O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH|O_DIRECTORY, resolve=RESOLVE_BENEATH}, 24) = -1 EXDEV (Invalid cross-device link)
+ vs.
+ openat2(AT_FDCWD, "dir1/dir2/", {flags=O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH|O_DIRECTORY, resolve=RESOLVE_BENEATH}, 24) = 4
+ FIXME - we don't handle chroot for relative paths
+ */
+ pseudo_path = pseudo_root_path(__func__, __LINE__, dirfd, path, 0);
+ if (path && path[0] == '/')
+ /* If the path is absolute, we should account for a potential chroot */
+ path = pseudo_path;
+
memcpy(&my_how, how, size);
/* mask out mode bits appropriately */
@@ -69,16 +83,16 @@
save_errno = errno;
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
if (my_how.flags & O_NOFOLLOW) {
- rc = real___lxstat64(_STAT_VER, path, &buf);
+ rc = real___lxstat64(_STAT_VER, pseudo_path, &buf);
} else {
- rc = real___xstat64(_STAT_VER, path, &buf);
+ rc = real___xstat64(_STAT_VER, pseudo_path, &buf);
}
#else
- rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, (my_how.flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
+ rc = real___fxstatat64(_STAT_VER, dirfd, pseudo_path, &buf, (my_how.flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
#endif
existed = (rc != -1);
if (!existed)
- pseudo_debug(PDBGF_FILE, "openat2_creat: %s -> 0%lld\n", path, my_how.mode);
+ pseudo_debug(PDBGF_FILE, "openat2_creat: %s -> 0%lld\n", pseudo_path, my_how.mode);
errno = save_errno;
}
@@ -90,12 +104,12 @@
save_errno = errno;
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
if (my_how.flags & O_NOFOLLOW) {
- rc = real___lxstat64(_STAT_VER, path, &buf);
+ rc = real___lxstat64(_STAT_VER, pseudo_path, &buf);
} else {
- rc = real___xstat64(_STAT_VER, path, &buf);
+ rc = real___xstat64(_STAT_VER, pseudo_path, &buf);
}
#else
- rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, (my_how.flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
+ rc = real___fxstatat64(_STAT_VER, dirfd, pseudo_path, &buf, (my_how.flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
#endif
if (rc != -1 && S_ISFIFO(buf.st_mode)) {
overly_magic_nonblocking = 1;
@@ -134,7 +148,7 @@
*/
if (pseudo_getlock()) {
pseudo_diag("PANIC: after opening a readonly/writeonly FIFO (path '%s', fd %d, errno %d, saved errno %d), could not regain lock. unrecoverable. sorry. bye.\n",
- path, rc, errno, save_errno);
+ pseudo_path, rc, errno, save_errno);
abort();
}
errno = save_errno;
@@ -156,28 +170,28 @@
#endif
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
if (my_how.flags & O_NOFOLLOW) {
- stat_rc = real___lxstat64(_STAT_VER, path, &buf);
+ stat_rc = real___lxstat64(_STAT_VER, pseudo_path, &buf);
} else {
- stat_rc = real___xstat64(_STAT_VER, path, &buf);
+ stat_rc = real___xstat64(_STAT_VER, pseudo_path, &buf);
}
#else
- stat_rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, (my_how.flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
+ stat_rc = real___fxstatat64(_STAT_VER, dirfd, pseudo_path, &buf, (my_how.flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
#endif
pseudo_debug(PDBGF_FILE, "openat2(path %s), flags %lld, stat rc %d, stat mode %o\n",
- path, my_how.flags, stat_rc, buf.st_mode);
+ pseudo_path, my_how.flags, stat_rc, buf.st_mode);
if (stat_rc != -1) {
buf.st_mode = PSEUDO_DB_MODE(buf.st_mode, my_how.mode);
if (!existed) {
real_fchmod(rc, PSEUDO_FS_MODE(my_how.mode, 0));
// file has no path, but has been created
- pseudo_client_op(OP_CREAT, 0, -1, dirfd, path, &buf);
+ pseudo_client_op(OP_CREAT, 0, -1, dirfd, pseudo_path, &buf);
}
- pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(my_how.flags), rc, dirfd, path, &buf);
+ pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(my_how.flags), rc, dirfd, pseudo_path, &buf);
} else {
pseudo_debug(PDBGF_FILE, "openat2 (fd %d, path %d/%s, flags %lld) succeeded, but stat failed (%s).\n",
- rc, dirfd, path, my_how.flags, strerror(errno));
- pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(my_how.flags), rc, dirfd, path, 0);
+ rc, dirfd, pseudo_path, my_how.flags, strerror(errno));
+ pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(my_how.flags), rc, dirfd, pseudo_path, 0);
}
errno = save_errno;
}
@@ -1 +1 @@
-int openat2(int dirfd, const char *path, const struct open_how *how, size_t size);
+int openat2(int dirfd, const char *path, const struct open_how *how, size_t size); /* preserve_paths=1 */
@@ -22,6 +22,7 @@ ${name}(${decl_args}) {
sigset_t saved;
${variadic_decl}
${rc_decl}
+ ${paths_decl}
PROFILE_START;
${maybe_async_skip}