From 3e617040425cd87f7af90804151ee8cb1f0ab8e9 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 17 Feb 2008 13:42:27 +0000 Subject: [PATCH] axeld + bonefish: Added parameters --start-offset and --end-offset to restrict the access of the file system to only that part of the given file. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23970 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/tools/fs_shell/Jamfile | 1 + src/tools/fs_shell/fcntl.cpp | 15 +- src/tools/fs_shell/fssh.cpp | 23 ++- src/tools/fs_shell/partition_support.cpp | 215 +++++++++++++++++++++++ src/tools/fs_shell/partition_support.h | 29 +++ src/tools/fs_shell/stat.cpp | 59 +++++-- src/tools/fs_shell/stat_priv.h | 20 +++ src/tools/fs_shell/uio.cpp | 22 ++- src/tools/fs_shell/unistd.cpp | 47 ++++- 9 files changed, 404 insertions(+), 27 deletions(-) create mode 100644 src/tools/fs_shell/partition_support.cpp create mode 100644 src/tools/fs_shell/partition_support.h create mode 100644 src/tools/fs_shell/stat_priv.h diff --git a/src/tools/fs_shell/Jamfile b/src/tools/fs_shell/Jamfile index ada90660de..1f4ee179d2 100644 --- a/src/tools/fs_shell/Jamfile +++ b/src/tools/fs_shell/Jamfile @@ -47,6 +47,7 @@ BuildPlatformStaticLibrary fs_shell.a : lock.cpp module.cpp node_monitor.cpp + partition_support.cpp path_util.cpp rootfs.cpp sem.cpp diff --git a/src/tools/fs_shell/fcntl.cpp b/src/tools/fs_shell/fcntl.cpp index 1c2cd0a591..515fb69e36 100644 --- a/src/tools/fs_shell/fcntl.cpp +++ b/src/tools/fs_shell/fcntl.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2007, Ingo Weinhold, bonefish@cs.tu-berlin.de. + * Copyright 2007-2008, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -9,6 +9,7 @@ #include #include "fssh_errno.h" +#include "partition_support.h" #include "stat_util.h" @@ -37,19 +38,23 @@ fssh_open(const char *pathname, int oflags, ...) // Use the _kern_open() defined in libroot on BeOS incompatible systems. // Required for proper attribute emulation support. + int fd; #if __BEOS__ - return open(pathname, to_platform_open_mode(oflags), + fd = open(pathname, to_platform_open_mode(oflags), to_platform_mode(mode)); #else - int fd = _kern_open(-1, pathname, to_platform_open_mode(oflags), + fd = _kern_open(-1, pathname, to_platform_open_mode(oflags), to_platform_mode(mode)); if (fd < 0) { fssh_set_errno(fd); - return -1; + fd = -1; } - return fd; #endif + + restricted_file_opened(fd); + + return fd; } diff --git a/src/tools/fs_shell/fssh.cpp b/src/tools/fs_shell/fssh.cpp index 21db3ccf43..9e74a5c092 100644 --- a/src/tools/fs_shell/fssh.cpp +++ b/src/tools/fs_shell/fssh.cpp @@ -27,6 +27,7 @@ #include "fssh_string.h" #include "fssh_type_constants.h" #include "module.h" +#include "partition_support.h" #include "path_util.h" #include "syscalls.h" #include "vfs.h" @@ -1159,8 +1160,11 @@ static void print_usage(bool error) { fprintf((error ? stderr : stdout), - "Usage: %s [-n] \n" - " %s --initialize [-n] " + "Usage: %s [ --start-offset ]\n" + " [ --end-offset ] [-n] \n" + " %s [ --start-offset ]\n" + " [ --end-offset ]\n" + " --initialize [-n] " "[ ]\n", sArgv[0], sArgv[0] ); @@ -1193,6 +1197,8 @@ main(int argc, const char* const* argv) const char* device = NULL; const char* volumeName = NULL; const char* initParameters = NULL; + fssh_off_t startOffset = 0; + fssh_off_t endOffset = -1; // eat options int argi = 1; @@ -1204,6 +1210,14 @@ main(int argc, const char* const* argv) initialize = true; } else if (strcmp(arg, "-n") == 0) { interactive = false; + } else if (strcmp(arg, "--start-offset") == 0) { + if (argi >= argc) + print_usage_and_exit(true); + startOffset = atoll(argv[argi++]); + } else if (strcmp(arg, "--end-offset") == 0) { + if (argi >= argc) + print_usage_and_exit(true); + endOffset = atoll(argv[argi++]); } else { print_usage_and_exit(true); } @@ -1247,6 +1261,11 @@ main(int argc, const char* const* argv) return error; } + // restrict access if requested + if (startOffset != 0 || endOffset != -1) + add_file_restriction(device, startOffset, endOffset); + + // start the action int result; if (initialize) { diff --git a/src/tools/fs_shell/partition_support.cpp b/src/tools/fs_shell/partition_support.cpp new file mode 100644 index 0000000000..d0426417a6 --- /dev/null +++ b/src/tools/fs_shell/partition_support.cpp @@ -0,0 +1,215 @@ +/* + * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "compatibility.h" + +#include "partition_support.h" + +#include +#include + +#include + +#include "fssh_errno.h" +#include "fssh_stat.h" +#include "fssh_unistd.h" +#include "stat_priv.h" + + +namespace FSShell { + + +struct FileRestriction { + FileRestriction(fssh_dev_t device, fssh_ino_t node, fssh_off_t startOffset, + fssh_off_t endOffset) + : device(device), + node(node), + startOffset(startOffset), + endOffset(endOffset) + { + } + + fssh_dev_t device; + fssh_ino_t node; + fssh_off_t startOffset; + fssh_off_t endOffset; +}; + + +typedef std::list FileRestrictionList; + +static FileRestrictionList sFileRestrictions; + + +static FileRestriction* +find_file_restriction(fssh_dev_t device, fssh_ino_t node) +{ + for (FileRestrictionList::iterator it = sFileRestrictions.begin(); + it != sFileRestrictions.end(); + ++it) { + FileRestriction* restriction = *it; + if (restriction->device == device && restriction->node == node) + return restriction; + } + + return NULL; +} + + +static FileRestriction* +find_file_restriction(int fd) +{ + struct fssh_stat st; + if (unrestricted_fstat(fd, &st) < 0) + return NULL; + + return find_file_restriction(st.fssh_st_dev, st.fssh_st_ino); +} + + +void +add_file_restriction(const char* fileName, fssh_off_t startOffset, + fssh_off_t endOffset) +{ + struct fssh_stat st; + if (unrestricted_stat(fileName, &st) < 0) + return; + + fssh_dev_t device = st.fssh_st_dev; + fssh_ino_t node = st.fssh_st_ino; + + FileRestriction* restriction = find_file_restriction(device, node); + if (restriction) + return; + + if (endOffset < 0) + endOffset = st.fssh_st_size; + + restriction = new FileRestriction(device, node, startOffset, endOffset); + sFileRestrictions.push_back(restriction); +} + + +void +restricted_file_opened(int fd) +{ + FileRestriction* restriction = find_file_restriction(fd); + if (!restriction) + return; + + lseek(fd, restriction->startOffset, SEEK_SET); +} + + +void +restricted_file_duped(int oldFD, int newFD) +{ +} + + +void +restricted_file_closed(int fd) +{ +} + + +int +restricted_file_restrict_io(int fd, fssh_off_t& pos, fssh_off_t size) +{ + FileRestriction* restriction = find_file_restriction(fd); + if (!restriction) + return 0; + + if (pos < 0) { + pos = lseek(fd, 0, SEEK_CUR); + if (pos < 0) + return -1; + } else + pos += restriction->startOffset; + + if (pos < restriction->startOffset || pos > restriction->endOffset) { + fssh_set_errno(B_BAD_VALUE); + return -1; + } + + fssh_off_t maxSize = restriction->endOffset - pos; + if (size > maxSize) + size = maxSize; + + return 0; +} + + +#include +void +restricted_file_restrict_stat(struct fssh_stat* st) +{ + FileRestriction* restriction = find_file_restriction(st->fssh_st_dev, + st->fssh_st_ino); + if (!restriction) + return; + +printf("restricted_file_restrict_stat(): startOffset: %lld, endOffset: %lld\n", +restriction->startOffset, restriction->endOffset); + st->fssh_st_size = restriction->endOffset - restriction->startOffset; +} + + +static int +to_platform_seek_mode(int fsshWhence) +{ + switch (fsshWhence) { + case FSSH_SEEK_CUR: + return SEEK_CUR; + case FSSH_SEEK_END: + return SEEK_END; + case FSSH_SEEK_SET: + default: + return SEEK_SET; + } +} + + +fssh_off_t +fssh_lseek(int fd, fssh_off_t offset, int whence) +{ + FileRestriction* restriction = find_file_restriction(fd); + if (!restriction) + return lseek(fd, offset, to_platform_seek_mode(whence)); + + fssh_off_t pos; + + switch (whence) { + case FSSH_SEEK_CUR: + { + pos = lseek(fd, 0, SEEK_CUR); + if (pos < 0) + return pos; + pos += offset; + break; + } + case FSSH_SEEK_END: + pos = restriction->endOffset + offset; + break; + case FSSH_SEEK_SET: + default: + pos = restriction->startOffset + offset; + break; + } + + if (pos < restriction->startOffset) { + fssh_set_errno(B_BAD_VALUE); + return -1; + } + + pos = lseek(fd, pos, SEEK_SET); + if (pos >= 0) + pos -= restriction->startOffset; + + return pos; +} + + +} // namespace FSShell diff --git a/src/tools/fs_shell/partition_support.h b/src/tools/fs_shell/partition_support.h new file mode 100644 index 0000000000..c4dd5c7196 --- /dev/null +++ b/src/tools/fs_shell/partition_support.h @@ -0,0 +1,29 @@ +/* + * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _FSSH_PARTITION_SUPPORT_H +#define _FSSH_PARTITION_SUPPORT_H + +#include "fssh_defs.h" +#include "fssh_stat.h" + + +namespace FSShell { + + +void add_file_restriction(const char* fileName, fssh_off_t startOffset, + fssh_off_t endOffset); + +void restricted_file_opened(int fd); +void restricted_file_duped(int oldFD, int newFD); +void restricted_file_closed(int fd); + +int restricted_file_restrict_io(int fd, fssh_off_t& pos, fssh_off_t size); +void restricted_file_restrict_stat(struct fssh_stat* st); + + +} // namespace FSShell + + +#endif // _FSSH_PARTITION_SUPPORT_H diff --git a/src/tools/fs_shell/stat.cpp b/src/tools/fs_shell/stat.cpp index dc5a59e9e6..a7c3202484 100644 --- a/src/tools/fs_shell/stat.cpp +++ b/src/tools/fs_shell/stat.cpp @@ -12,6 +12,8 @@ #include #include "fssh_errno.h" +#include "partition_support.h" +#include "stat_priv.h" #include "stat_util.h" @@ -27,14 +29,7 @@ using FSShell::to_platform_mode; int -fssh_mkdir(const char *path, fssh_mode_t mode) -{ - return mkdir(path, to_platform_mode(mode)); -} - - -int -fssh_stat(const char *path, struct fssh_stat *fsshStat) +FSShell::unrestricted_stat(const char *path, struct fssh_stat *fsshStat) { struct stat st; @@ -58,7 +53,7 @@ fssh_stat(const char *path, struct fssh_stat *fsshStat) int -fssh_fstat(int fd, struct fssh_stat *fsshStat) +FSShell::unrestricted_fstat(int fd, struct fssh_stat *fsshStat) { struct stat st; @@ -82,7 +77,7 @@ fssh_fstat(int fd, struct fssh_stat *fsshStat) int -fssh_lstat(const char *path, struct fssh_stat *fsshStat) +FSShell::unrestricted_lstat(const char *path, struct fssh_stat *fsshStat) { struct stat st; @@ -103,3 +98,47 @@ fssh_lstat(const char *path, struct fssh_stat *fsshStat) return 0; } + +// #pragma mark - + +int +fssh_mkdir(const char *path, fssh_mode_t mode) +{ + return mkdir(path, to_platform_mode(mode)); +} + + +int +fssh_stat(const char *path, struct fssh_stat *fsshStat) +{ + if (FSShell::unrestricted_stat(path, fsshStat) < 0) + return -1; + + FSShell::restricted_file_restrict_stat(fsshStat); + + return 0; +} + + +int +fssh_fstat(int fd, struct fssh_stat *fsshStat) +{ + if (FSShell::unrestricted_fstat(fd, fsshStat) < 0) + return -1; + + FSShell::restricted_file_restrict_stat(fsshStat); + + return 0; +} + + +int +fssh_lstat(const char *path, struct fssh_stat *fsshStat) +{ + if (FSShell::unrestricted_lstat(path, fsshStat) < 0) + return -1; + + FSShell::restricted_file_restrict_stat(fsshStat); + + return 0; +} diff --git a/src/tools/fs_shell/stat_priv.h b/src/tools/fs_shell/stat_priv.h new file mode 100644 index 0000000000..413c0d45ba --- /dev/null +++ b/src/tools/fs_shell/stat_priv.h @@ -0,0 +1,20 @@ +/* + * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _FSSH_STAT_PRIV_H +#define _FSSH_STAT_PRIV_H + +#include "fssh_defs.h" + + +namespace FSShell { + +int unrestricted_stat(const char *path, struct fssh_stat *fsshStat); +int unrestricted_fstat(int fd, struct fssh_stat *fsshStat); +int unrestricted_lstat(const char *path, struct fssh_stat *fsshStat); + +} // namespace FSShell + + +#endif // _FSSH_STAT_PRIV_H diff --git a/src/tools/fs_shell/uio.cpp b/src/tools/fs_shell/uio.cpp index 5f25d1908f..0551ef11a6 100644 --- a/src/tools/fs_shell/uio.cpp +++ b/src/tools/fs_shell/uio.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2007, Ingo Weinhold, bonefish@cs.tu-berlin.de. + * Copyright 2007-2008, Ingo Weinhold, bonefish@cs.tu-berlin.de. * Distributed under the terms of the MIT License. */ @@ -12,6 +12,8 @@ #include #include +#include "partition_support.h" + static const fssh_size_t kMaxIOVecs = 1024; @@ -41,6 +43,11 @@ fssh_readv(int fd, const struct fssh_iovec *vector, fssh_size_t count) if (!prepare_iovecs(vector, count, systemVecs)) return -1; + fssh_off_t pos = -1; + fssh_size_t length = 0; + if (FSShell::restricted_file_restrict_io(fd, pos, length) < 0) + return -1; + #if !defined(HAIKU_HOST_PLATFORM_FREEBSD) return readv(fd, systemVecs, count); #else @@ -57,6 +64,10 @@ fssh_readv_pos(int fd, fssh_off_t pos, const struct fssh_iovec *vec, if (!prepare_iovecs(vec, count, systemVecs)) return -1; + fssh_size_t length = 0; + if (FSShell::restricted_file_restrict_io(fd, pos, length) < 0) + return -1; + return readv_pos(fd, pos, systemVecs, count); } @@ -68,6 +79,11 @@ fssh_writev(int fd, const struct fssh_iovec *vector, fssh_size_t count) if (!prepare_iovecs(vector, count, systemVecs)) return -1; + fssh_off_t pos = -1; + fssh_size_t length = 0; + if (FSShell::restricted_file_restrict_io(fd, pos, length) < 0) + return -1; + #if !defined(HAIKU_HOST_PLATFORM_FREEBSD) return writev(fd, systemVecs, count); #else @@ -84,5 +100,9 @@ fssh_writev_pos(int fd, fssh_off_t pos, const struct fssh_iovec *vec, if (!prepare_iovecs(vec, count, systemVecs)) return -1; + fssh_size_t length = 0; + if (FSShell::restricted_file_restrict_io(fd, pos, length) < 0) + return -1; + return writev_pos(fd, pos, systemVecs, count); } diff --git a/src/tools/fs_shell/unistd.cpp b/src/tools/fs_shell/unistd.cpp index 49f059611a..afdc955b97 100644 --- a/src/tools/fs_shell/unistd.cpp +++ b/src/tools/fs_shell/unistd.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2007, Ingo Weinhold, bonefish@cs.tu-berlin.de. + * Copyright 2007-2008, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -15,6 +15,7 @@ #include "fssh_drivers.h" #include "fssh_errno.h" +#include "partition_support.h" #ifdef __BEOS__ # include @@ -86,22 +87,28 @@ fssh_dup(int fd) { // Use the _kern_dup() defined in libroot on BeOS incompatible systems. // Required for proper attribute emulation support. + int newFD; #if __BEOS__ - return dup(fd); + newFD = dup(fd); #else - int result = _kern_dup(fd); - if (result < 0) { - fssh_set_errno(result); - return -1; + newFD = _kern_dup(fd); + if (newFD < 0) { + fssh_set_errno(newFD); + newFD = -1; } - return result; #endif + + FSShell::restricted_file_duped(fd, newFD); + + return newFD; } int fssh_close(int fd) { + FSShell::restricted_file_closed(fd); + // Use the _kern_close() defined in libroot on BeOS incompatible systems. // Required for proper attribute emulation support. #if __BEOS__ @@ -296,9 +303,16 @@ fssh_ssize_t fssh_read(int fd, void *buffer, fssh_size_t count) { #if !defined(HAIKU_HOST_PLATFORM_FREEBSD) + fssh_off_t pos = -1; + if (FSShell::restricted_file_restrict_io(fd, pos, count) < 0) + return -1; return read(fd, buffer, count); #else - return read_pos(fd, lseek(fd, 0, SEEK_CUR), buffer, count); + fssh_ssize_t bytesRead = read_pos(fd, fssh_lseek(fd, 0, FSSH_SEEK_CUR), + buffer, count); + if (bytesRead > 0) + fssh_lseek(fd, bytesRead, FSSH_SEEK_CUR); + return bytesRead; #endif } @@ -306,6 +320,8 @@ fssh_read(int fd, void *buffer, fssh_size_t count) fssh_ssize_t fssh_read_pos(int fd, fssh_off_t pos, void *buffer, fssh_size_t count) { + if (FSShell::restricted_file_restrict_io(fd, pos, count) < 0) + return -1; return read_pos(fd, pos, buffer, count); } @@ -314,20 +330,33 @@ fssh_ssize_t fssh_write(int fd, const void *buffer, fssh_size_t count) { #if !defined(HAIKU_HOST_PLATFORM_FREEBSD) + fssh_off_t pos = -1; + if (FSShell::restricted_file_restrict_io(fd, pos, count) < 0) + return -1; return write(fd, buffer, count); #else - return write_pos(fd, lseek(fd, 0, SEEK_CUR), buffer, count); + fssh_ssize_t written = write_pos(fd, fssh_lseek(fd, 0, FSSH_SEEK_CUR), + buffer, count); + if (written > 0) + fssh_lseek(fd, written, FSSH_SEEK_CUR); + return written; #endif } +#include fssh_ssize_t fssh_write_pos(int fd, fssh_off_t pos, const void *buffer, fssh_size_t count) { + if (FSShell::restricted_file_restrict_io(fd, pos, count) < 0) + return -1; return write_pos(fd, pos, buffer, count); } +// fssh_lseek() -- implemented in partition_support.cpp + + fssh_gid_t fssh_getegid(void) {