# HG changeset patch # User Paul Boddie # Date 1644442229 -3600 # Node ID 184132df62ec2966a286ac093f5212c3c1c86e7d # Parent a0b44b2cd98850693c9d424f3aa8ca7735362823 Introduced file permissions testing when accessing files. diff -r a0b44b2cd988 -r 184132df62ec conf/dstest_file_access.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/dstest_file_access.cfg Wed Feb 09 22:30:29 2022 +0100 @@ -0,0 +1,51 @@ +-- vim:set ft=lua: + +local L4 = require("L4"); + +local l = L4.default_loader; + +local pipe_server = l:new_channel(); + +l:startv({ + caps = { + server = pipe_server:svr(), + }, + log = { "pipes", "r" }, + }, + "rom/dstest_pipe_server", "10"); + +local blocksvr = l:new_channel(); + +l:startv({ + caps = { + server = blocksvr:svr(), + }, + log = { "blocksvr", "r" }, + }, + "rom/dstest_block_server", "10"); + +local ext2svr = l:new_channel(); + +l:startv({ + caps = { + blocksvr = blocksvr, + pipes = pipe_server, + ext2svr = ext2svr:svr(), + }, + log = { "ext2svr", "y" }, + }, + "rom/dstest_ext2_server", "blocksvr", "rom/e2test.fs", "10", "ext2svr"); + +-- Obtain user filesystems with umask 0022 (18). + +local open_for_user = 6; +local ext2svr_davidb = L4.cast(L4.Proto.Factory, ext2svr):create(open_for_user, 1001, 1001, 18); + +l:startv({ + caps = { + server = ext2svr_davidb, + }, + log = { "client", "g" }, + }, + -- program, directory + "rom/dstest_file_access", "home/paulb/private", "home/paulb/public", "home/paulb/shared"); diff -r a0b44b2cd988 -r 184132df62ec conf/dstest_file_access.list --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/dstest_file_access.list Wed Feb 09 22:30:29 2022 +0100 @@ -0,0 +1,28 @@ +entry dstest_file_access +roottask moe rom/dstest_file_access.cfg +module dstest_file_access.cfg +module e2test.fs +module l4re +module ned +module dstest_file_access +module dstest_ext2_server +module dstest_block_server +module dstest_pipe_server +module lib4re-c.so +module lib4re-c-util.so +module lib4re.so +module lib4re-util.so +module libc_be_l4refile.so +module libc_be_l4re.so +module libc_be_socket_noop.so +module libc_support_misc.so +module libdl.so +module libipc.so +module libl4sys-direct.so +module libl4sys.so +module libl4util.so +module libld-l4.so +module libpthread.so +module libstdc++.so +module libsupc++.so +module libuc_c.so diff -r a0b44b2cd988 -r 184132df62ec libfsserver/include/fsserver/ext2_file_operations.h --- a/libfsserver/include/fsserver/ext2_file_operations.h Tue Feb 08 00:03:32 2022 +0100 +++ b/libfsserver/include/fsserver/ext2_file_operations.h Wed Feb 09 22:30:29 2022 +0100 @@ -57,10 +57,16 @@ { } + /* Access and object type tests. */ + + bool can_access(user_t user, flags_t flags, ext2_ino_t ino); + bool is_directory(ext2_ino_t ino_file); bool is_file(ext2_ino_t ino_file); + /* File manipulation. */ + void close_file(ext2_file_t file); long create_file(ext2_ino_t ino_parent, const char *filename, user_t user, diff -r a0b44b2cd988 -r 184132df62ec libfsserver/lib/files/ext2_file_opener.cc --- a/libfsserver/lib/files/ext2_file_opener.cc Tue Feb 08 00:03:32 2022 +0100 +++ b/libfsserver/lib/files/ext2_file_opener.cc Wed Feb 09 22:30:29 2022 +0100 @@ -1,7 +1,7 @@ /* * An opener for a file provided by an Ext2-compatible filesystem. * - * Copyright (C) 2021 Paul Boddie + * Copyright (C) 2021, 2022 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -64,6 +64,9 @@ if (!err) { + if (!_ops->can_access(_user, flags, ino)) + return -L4_EPERM; + *fileid = (fileid_t) ino; return L4_EOK; } diff -r a0b44b2cd988 -r 184132df62ec libfsserver/lib/files/ext2_file_operations.cc --- a/libfsserver/lib/files/ext2_file_operations.cc Tue Feb 08 00:03:32 2022 +0100 +++ b/libfsserver/lib/files/ext2_file_operations.cc Wed Feb 09 22:30:29 2022 +0100 @@ -22,10 +22,27 @@ #include #include #include +#include #include "ext2_file_operations.h" -/* Object type tests. */ + + +/* Access and object type tests. */ + +bool Ext2FileOperations::can_access(user_t user, flags_t flags, ext2_ino_t ino) +{ + struct ext2_inode inode; + errcode_t retval = ext2fs_read_inode(_fs, ino, &inode); + + if (retval) + return false; + + if ((flags & O_RDWR) || (flags & O_WRONLY)) + return access_can_write(user, &inode); + else + return access_can_read(user, &inode); +} bool Ext2FileOperations::is_directory(ext2_ino_t ino_file) { @@ -41,6 +58,8 @@ return _image_isfile(_fs, ino_file); } + + /* Perform closing operations on a file. */ void Ext2FileOperations::close_file(ext2_file_t file) diff -r a0b44b2cd988 -r 184132df62ec libfsserver/lib/generic/resource_registry.cc --- a/libfsserver/lib/generic/resource_registry.cc Tue Feb 08 00:03:32 2022 +0100 +++ b/libfsserver/lib/generic/resource_registry.cc Wed Feb 09 22:30:29 2022 +0100 @@ -1,7 +1,7 @@ /* * Filesystem resource registry incorporating opening functionality. * - * Copyright (C) 2021 Paul Boddie + * Copyright (C) 2021, 2022 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -143,7 +143,8 @@ std::lock_guard guard(_lock); /* Obtain an identifier for the object, even for new files (subject to use - of the appropriate flag). */ + of the appropriate flag). This also checks the access rights for any + configured user. */ fileid_t fileid; long err = opening->get_fileid(path, flags, &fileid); @@ -176,7 +177,8 @@ { std::lock_guard guard(_lock); - /* Obtain an identifier for any recognised object. */ + /* Obtain an identifier for any recognised object. This also checks the + access rights for any configured user. */ fileid_t fileid; long err = opening->get_fileid(path, 0, &fileid); @@ -226,7 +228,8 @@ long err; fileid_t source_fileid, target_fileid; - /* Obtain an identifier for any recognised object. */ + /* Obtain an identifier for any recognised object. This also checks the + access rights for any configured user. */ err = opening->get_fileid(source, 0, &source_fileid); diff -r a0b44b2cd988 -r 184132df62ec test_files/mk_e2test.sh --- a/test_files/mk_e2test.sh Tue Feb 08 00:03:32 2022 +0100 +++ b/test_files/mk_e2test.sh Wed Feb 09 22:30:29 2022 +0100 @@ -1,6 +1,9 @@ #!/bin/sh -THIS_DIR=$(realpath $(dirname "$0")) +# NOTE: There should be a stable user identifier defined, not that of the user +# NOTE: running this script. + +PROGNAME=$(basename "$0") if [ "$1" = '-q' ] ; then QUIET=$1 @@ -9,19 +12,21 @@ QUIET= fi -PKGDIR=$1 -E2ACCESS_DIR=$2 -TARGET=$3 +PKGDIR=$(realpath "$1") +E2ACCESS_DIR=$(realpath "$2") +TARGET=$(realpath "$3") if [ ! -e "$PKGDIR" ] || [ ! -e "$E2ACCESS_DIR" ] || [ ! "$TARGET" ] ; then - echo "Usage: $0 [ -q ] " 1>&2 + cat 1>&2 < + +Package directory: $PKGDIR +e2access directory: $E2ACCESS_DIR +Target filesystem: $TARGET +EOF exit 1 fi -PKGDIR=`realpath "$PKGDIR"` -E2ACCESS_DIR=`realpath "$E2ACCESS_DIR"` -TARGET=`realpath "$TARGET"` - # Initialise the program details and environment. E2ACCESS="$E2ACCESS_DIR"/e2access @@ -31,6 +36,34 @@ mkdir tmp_e2test cd tmp_e2test + +# Set a sensible umask. + +umask 0022 + +mkdir -p home/paulb/public +echo "Public!" > home/paulb/public/message + +# Set a restrictive umask. + +umask 0077 + +echo "Not public!" > home/paulb/public/message2 + +mkdir -p home/paulb/private +echo "Private!" > home/paulb/private/message + +# Set a permissive umask. + +umask 0000 + +mkdir -p home/paulb/shared +echo "Editable!" > home/paulb/shared/message + +# Restore the umask for the remaining files. + +umask 0022 + mkdir -p home/paulb/many cd home/paulb/many @@ -62,12 +95,12 @@ exit 1 fi -# Add the directory and files to the image. +# Add the directories and files to the image. -"$E2ACCESS" "$TARGET" --make-dirs home/paulb/many - -"$E2ACCESS" "$TARGET" --copy-in $(find home/paulb/many -maxdepth 1 -type f | sort) home/paulb/many -"$E2ACCESS" "$TARGET" --copy-in $(find home/paulb -maxdepth 1 -type f | sort) home/paulb +for DIR in home/paulb/private home/paulb/public home/paulb/shared home/paulb/many home/paulb ; do + "$E2ACCESS" "$TARGET" --make-dirs "$DIR" + "$E2ACCESS" "$TARGET" --copy-in $(find "$DIR" -maxdepth 1 -type f | sort) "$DIR" +done # Leave the root of the filesystem. @@ -78,6 +111,11 @@ "$E2ACCESS" "$TARGET" --list-dirs 'home' "$E2ACCESS" "$TARGET" --list-dirs 'home/paulb' "$E2ACCESS" "$TARGET" --list-dirs 'home/paulb/many' + "$E2ACCESS" "$TARGET" --list-dirs 'home/paulb/private' + "$E2ACCESS" "$TARGET" --list-dirs 'home/paulb/public' + "$E2ACCESS" "$TARGET" --list-dirs 'home/paulb/shared' fi rm -r tmp_e2test + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r a0b44b2cd988 -r 184132df62ec tests/Makefile --- a/tests/Makefile Tue Feb 08 00:03:32 2022 +0100 +++ b/tests/Makefile Wed Feb 09 22:30:29 2022 +0100 @@ -4,6 +4,7 @@ TARGET = \ dstest_block_client dstest_block_client_simple \ dstest_ext2fs_client \ + dstest_file_access \ dstest_file_client \ dstest_file_monitor \ dstest_file_readdir \ @@ -21,6 +22,8 @@ SRC_CC_dstest_ext2fs_client = dstest_ext2fs_client.cc +SRC_CC_dstest_file_access = dstest_file_access.cc + SRC_CC_dstest_file_client = dstest_file_client.cc SRC_CC_dstest_file_monitor = dstest_file_monitor.cc diff -r a0b44b2cd988 -r 184132df62ec tests/dstest_file_access.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/dstest_file_access.cc Wed Feb 09 22:30:29 2022 +0100 @@ -0,0 +1,98 @@ +/* + * Test file access. + * + * Copyright (C) 2020, 2021, 2022 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include + +#include +#include +#include + +#include +#include + + + +int main(int argc, char *argv[]) +{ + if (argc < 2) + { + printf("Need directory names.\n"); + return 1; + } + + for (int i = 1; i < argc; i++) + { + char *dirname = argv[i]; + + printf("Opening %s...\n", dirname); + + file_t *reader = client_opendir(dirname); + + if (reader == NULL) + { + printf("Could not read from directory: %s\n", dirname); + continue; + } + + printf("Reading...\n"); + + struct dirent *dirent; + + while ((dirent = client_readdir(reader)) != NULL) + { + char *filename = dirent->d_name; + if (!strlen(filename) || (filename[0] == '.')) + continue; + + char path[strlen(filename) + strlen(dirname) + 2]; + + sprintf(path, "%s/%s", dirname, filename); + + printf("Attempt to read %s...\n", filename); + + file_t *file = client_open(path, O_RDONLY); + + if (file == NULL) + printf("Could not open file: %s\n", filename); + else + { + char buffer[32]; + offset_t nread = client_read(file, buffer, 32); + + fputs("Start of file: ", stdout); + fwrite(buffer, sizeof(char), nread, stdout); + fputs("\n", stdout); + + client_close(file); + } + + free(dirent); + } + + printf("Directory shown.\n"); + + } + + return 0; +} + +// vim: tabstop=2 expandtab shiftwidth=2