diff options
-rwxr-xr-x | makewrappers | 26 | ||||
-rw-r--r-- | ports/linux/wrapfuncs.in | 20 | ||||
-rw-r--r-- | ports/unix/wrapfuncs.in | 22 | ||||
-rw-r--r-- | pseudo_client.c | 47 | ||||
-rw-r--r-- | pseudo_client.h | 2 | ||||
-rw-r--r-- | pseudo_util.c | 1 | ||||
-rw-r--r-- | templates/wrapfuncs.c | 12 |
7 files changed, 106 insertions, 24 deletions
diff --git a/makewrappers b/makewrappers index b34f7eb..232c08d 100755 --- a/makewrappers +++ b/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) + ";" diff --git a/ports/linux/wrapfuncs.in b/ports/linux/wrapfuncs.in index aae0f0d..5cc6791 100644 --- a/ports/linux/wrapfuncs.in +++ b/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, struct stat64 *buf); 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)()); diff --git a/ports/unix/wrapfuncs.in b/ports/unix/wrapfuncs.in index 3910fae..bd2706f 100644 --- a/ports/unix/wrapfuncs.in +++ b/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); diff --git a/pseudo_client.c b/pseudo_client.c index 9ba2eab..401f141 100644 --- a/pseudo_client.c +++ b/pseudo_client.c @@ -1482,6 +1482,43 @@ base_path(int dirfd, const char *path, int leave_last) { 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 access, int fd, int dirfd, const char *path } } + 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; diff --git a/pseudo_client.h b/pseudo_client.h index 457b095..4c10fc6 100644 --- a/pseudo_client.h +++ b/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 diff --git a/pseudo_util.c b/pseudo_util.c index c867ed6..1d06009 100644 --- a/pseudo_util.c +++ b/pseudo_util.c @@ -43,6 +43,7 @@ static struct pseudo_variables pseudo_env[] = { { "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 }, diff --git a/templates/wrapfuncs.c b/templates/wrapfuncs.c index 3859183..93bb671 100644 --- a/templates/wrapfuncs.c +++ b/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; |