merge!:Test merge feature\rewrite-kernel-mod into copy dev2

This commit is contained in:
Tommaso Gagliardoni 2024-08-31 11:37:01 +02:00
commit b79805c361
151 changed files with 5633 additions and 2918 deletions

9
.gitignore vendored
View file

@ -55,9 +55,18 @@ dkms.conf
# Eclipse project files
.project
.cproject
.settings/
# Shufflecake binaries
shufflecake
shufflecake-lite
shufflecake-legacy
# Build directory
bin/
# Test images
disks/
# Temporary working directories
dm-vvz/

View file

@ -26,7 +26,12 @@
# Variables
SCRIPTNAME=$(basename "$0")
SCRIPT_DIR="$(dirname "$(realpath "$0")")"
<<<<<<< HEAD
CONTAINER_FILENAME=""
=======
LOOP_FILENAME="$SCRIPT_DIR/veracrypt-benchmark-loop-file.img"
LOOP_DEVICE=""
>>>>>>> feature/rewrite-kernel-mod
TIMEFORMAT='%3R'
# Colors
@ -38,7 +43,11 @@ NC='\033[0m' # No color
# Help
print_help() {
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 79 chars
<<<<<<< HEAD
echo -e "${BLUE}Usage: ${SCRIPTNAME} [OPTION]... [BLOCKDEVICE]${NC}"
=======
echo -e "${BLUE}Usage: ${SCRIPTNAME} [OPTION]... [BLOCKDEVICE]...${NC}"
>>>>>>> feature/rewrite-kernel-mod
echo " "
echo "This script is used to benchmark VeraCrypt on this machine."
echo "This script is part of the Shufflecake benchmark suite."
@ -47,6 +56,7 @@ print_help() {
echo " "
echo "This script requires root because it operates on block devices, please run it "
echo -e "with ${BLUE}sudo${NC}. It does the following:"
<<<<<<< HEAD
echo "1) Creates a standard and unformatted VeraCrypt volumes within a given device."
echo "2) Creates a hidden ext4 VeraCrypt volume within the standard one."
echo "3) Opens the hidden volume, and mounts it."
@ -61,6 +71,22 @@ print_help() {
echo " "
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 79 chars
echo -e "${BLUE}WARNING: ALL CONTENT OF THE PROVIDED BLOCK DEVICE WILL BE ERASED!${NC}"
=======
echo "1) Creates standard and hidden VeraCrypt volumes within a given device."
echo "2) Opens the hidden volume, formats it with ext4 and mounts it."
echo "3) Performs various fio r/w stress operations on it."
echo "4) Unmounts and closes the used volume."
echo " "
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 79 chars
echo "You can pass the path to a block device as an optional argument, otherwise the "
echo "script will ask for one. If no path is provided, the script will create a 1 GiB"
echo "local file and use it to back a loop device as a virtual block device to be "
echo "formatted with the appropriate tools. The file will be removed at the end."
echo " "
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 79 chars
echo "NOTICE: This script has been tested only with VeraCrypt v 1.25.9."
echo -e "${RED}WARNING: ALL CONTENT OF THE PROVIDED BLOCK DEVICE WILL BE ERASED!${NC}"
>>>>>>> feature/rewrite-kernel-mod
echo " "
exit 0
}
@ -84,7 +110,11 @@ usage() {
# Check that this is run as root
check_sudo() {
if [[ $EUID -ne 0 ]]; then
<<<<<<< HEAD
echo -e "${RED}Error: This script must be run as root.${NC}"
=======
echo -e "${RED}Error: This script must be run as root${NC}"
>>>>>>> feature/rewrite-kernel-mod
usage
exit 1
fi
@ -101,6 +131,7 @@ check_block_device() {
fi
}
<<<<<<< HEAD
check_not_loopdevice() {
DEVCHECK=$1
if [[ $DEVCHECK == /dev/loop* ]]; then
@ -121,12 +152,36 @@ create_container_file() {
#dd if=/dev/zero of="$CONTAINER_FILENAME" bs=1M count=1024 > /dev/null
#echo "Writing of empty file complete." >&2
echo "$CONTAINER_FILENAME"
=======
# Function to create loop device
create_loop_device() {
echo "I will now try to create a file $LOOP_FILENAME" >&2
if [ -e "$LOOP_FILENAME" ]; then
echo -e "${RED}Error: Impossible to generate file, $LOOP_FILENAME already exists${NC}"
exit 1
fi
sudo dd if=/dev/zero of="$LOOP_FILENAME" bs=1M count=1024 > /dev/null
echo "Writing of empty file complete. I will now try to attach it to a new loop device..." >&2
LOOP_DEVICE=$(sudo losetup -f --show "$LOOP_FILENAME")
echo "Successfully created loop device $LOOP_DEVICE" >&2
echo "$LOOP_DEVICE"
}
# Generate a suitable VeraCrypt volume name
find_veracryptvolname() {
volname="/dev/mapper/vc01" #placeholder
echo "$volname"
>>>>>>> feature/rewrite-kernel-mod
}
# Function for user confirmation
confirm() {
while true; do
<<<<<<< HEAD
echo -e "${BLUE}Are you sure you want to proceed? All data in $BLOCK_DEVICE will be erased. (y/n)${NC}"
=======
echo -e "${RED}Are you sure you want to proceed? All data on disk $BLOCK_DEVICE will be erased. (y/n)${NC}"
>>>>>>> feature/rewrite-kernel-mod
read -r response
case "$response" in
[yY]|[yY][eE][sS]) # Responded Yes
@ -136,7 +191,11 @@ confirm() {
return 1 # Return 1 for No (error, convention for bash scripting)
;;
*) # Responded something else
<<<<<<< HEAD
echo "Please press only (y)es or (n)o."
=======
echo "Please press only y or n."
>>>>>>> feature/rewrite-kernel-mod
;;
esac
done
@ -145,6 +204,7 @@ confirm() {
# Benchmarks
benchmark() {
<<<<<<< HEAD
MNTPOINT=""
TESTNAME="vc"
RUNTIME="20" # running time in seconds FOR EACH TEST
@ -194,15 +254,35 @@ benchmark() {
rmdir $MNTPOINT
echo "Volume detached and local mountpoint removed."
#end
=======
VOLUME="veracrypt-test"
MNTPOINT=""
PASSPHRASE="mypassword"
echo "Starting benchmark for VeraCrypt"
# TESTS HERE
bpx "THIS IS JUST A SKELETON, VERACRYPT SCRIPT NOT IMPLEMENTED YET, DOING NOTHING..."
# END TESTS
#end
>>>>>>> feature/rewrite-kernel-mod
}
# Clean up
cleanup() {
echo "Exiting and cleaning..."
<<<<<<< HEAD
if [[ -n $CONTAINER_FILENAME ]]; then
echo "Deleting $CONTAINER_FILENAME..."
rm -f "$CONTAINER_FILENAME"
echo "Container file deleted."
=======
# TODO clean other stuff if necessary
if [[ -n $LOOP_DEVICE ]]; then
echo "Detaching $LOOP_DEVICE"
sudo losetup -d "$LOOP_DEVICE"
echo "Deleting $LOOP_FILENAME"
sudo rm -f "$LOOP_FILENAME"
echo "Loop device detached and backing file deleted."
>>>>>>> feature/rewrite-kernel-mod
fi
}
@ -215,9 +295,15 @@ cleanup() {
# BANNER
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 79 chars
<<<<<<< HEAD
echo -e "${BLUE}===============================================================================${NC}"
echo -e "${BLUE} Benchmark Suite Script for VeraCrypt${NC}"
echo -e "${BLUE}===============================================================================${NC}"
=======
echo -e "${GREEN}===============================================================================${NC}"
echo -e "${GREEN} Benchmark Suite Script for VeraCrypt${NC}"
echo -e "${GREEN}===============================================================================${NC}"
>>>>>>> feature/rewrite-kernel-mod
# PRELIMINARY: PARSE HELP, SUDO, AND CHECK VERACRYPT EXISTS
@ -243,12 +329,17 @@ echo " "
# PARSER
case "$1" in
<<<<<<< HEAD
"") # no argument passed
=======
"")
>>>>>>> feature/rewrite-kernel-mod
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 79 chars
echo "Now you will be asked to enter the path for a block device to be used for the "
echo "benchmarks (all content will be erased). If no path is provided (default"
echo "choice), then the script will create a 1 GiB file in the current directory and "
<<<<<<< HEAD
echo "use it a VeraCrypt container instead, then the file will be removed at the end."
echo " "
echo -n "Please enter the path for a (non-loop) block device (default: none): "
@ -262,6 +353,16 @@ case "$1" in
BLOCK_DEVICE="$CONTAINER_FILENAME"
else
check_block_device "$BLOCK_DEVICE"
=======
echo "use it to back a loop device instead, then the file will be removed at the end."
echo " "
echo -n "Please enter the path for a block device (default: none): "
read BLOCK_DEVICE
if [ -z "$BLOCK_DEVICE" ]; then
echo "No path provided, creating a local file and loop device..."
LOOP_DEVICE=$(create_loop_device)
BLOCK_DEVICE=$LOOP_DEVICE
>>>>>>> feature/rewrite-kernel-mod
fi
;;
@ -269,16 +370,27 @@ case "$1" in
# argument passed
*)
BLOCK_DEVICE="$1"
<<<<<<< HEAD
check_block_device "$BLOCK_DEVICE"
;;
esac
check_not_loopdevice "$BLOCK_DEVICE"
=======
;;
esac
check_block_device "$BLOCK_DEVICE"
>>>>>>> feature/rewrite-kernel-mod
# MAIN PROGRAM
if confirm; then
<<<<<<< HEAD
benchmark
=======
benchmark # Call your disk formatting function here
>>>>>>> feature/rewrite-kernel-mod
else
echo "Aborting..."
fi
@ -286,3 +398,8 @@ fi
cleanup
<<<<<<< HEAD
=======
>>>>>>> feature/rewrite-kernel-mod

53
dm-sflc/.Kbuild Normal file
View file

@ -0,0 +1,53 @@
#
# Copyright The Shufflecake Project Authors (2022)
# Copyright The Shufflecake Project Contributors (2022)
# Copyright Contributors to the The Shufflecake Project.
#
# See the AUTHORS file at the top-level directory of this distribution and at
# <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
#
# This file is part of the program shufflecake-c, which is part of the
# Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
# layer for Linux. See <https://www.shufflecake.net>.
#
# 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, see <https://www.gnu.org/licenses/>.
#
MODULE_NAME := dm_sflc
obj-m := $(MODULE_NAME).o
OBJ_LIST := sflc.o dev_vol.o sysfs.o
OBJ_LIST += old/sflc_old.o old/target.o old/sysfs.o
OBJ_LIST += old/device/device.o old/device/volumes.o old/device/rawio.o old/device/rmap.o old/device/iv.o
OBJ_LIST += old/volume/volume.o old/volume/io.o old/volume/read.o old/volume/write.o old/volume/fmap.o
OBJ_LIST += old/utils/string.o old/utils/bio.o old/utils/pools.o old/utils/workqueues.o old/utils/vector.o
OBJ_LIST += old/crypto/rand/rand.o
OBJ_LIST += old/crypto/symkey/symkey.o old/crypto/symkey/skreq_pool.o
OBJ_LIST += lite/sflc_lite.o lite/sysfs.o
OBJ_LIST += lite/device.o lite/volume.o
OBJ_LIST += lite/posmap.o lite/read.o lite/write.o lite/crypto.o
$(MODULE_NAME)-y += $(OBJ_LIST)
# Normal CC flags
ccflags-y := -O2
ccflags-y += -I$(src)
ccflags-y += -Wall -Wno-declaration-after-statement
# Debug CC flags
ccflags-$(CONFIG_SFLC_DEBUG) += -DDEBUG
ccflags-$(CONFIG_SFLC_DEBUG) += -Og -g
ccflags-$(CONFIG_SFLC_DEBUG) += -fsanitize=kernel-address -fno-omit-frame-pointer

6
dm-sflc/.gitignore vendored
View file

@ -1,4 +1,8 @@
.project
.cproject
.settings/
bin/
!bin/
*.o
*.symvers
*.ko

View file

@ -22,25 +22,27 @@
#
KERNEL_DIR = /lib/modules/$(shell uname -r)/build
SRC_DIR = $(shell pwd)
BUILD_DIR = $(shell pwd)/bin
BUILD_DIR_MAKEFILE = $(BUILD_DIR)/Makefile
ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
default: $(BUILD_DIR_MAKEFILE)
make -C $(KERNEL_DIR) M=$(BUILD_DIR) src=$(SRC_DIR) CONFIG_SFLC_DEBUG=$(CONFIG_SFLC_DEBUG) modules
$(BUILD_DIR_MAKEFILE): $(BUILD_DIR)
echo "# This Makefile is here because of Kbuild" > $@
$(BUILD_DIR):
mkdir -p $@
default:
make -C $(KERNEL_DIR) M=$(ROOT_DIR)/bin CONFIG_SFLC_DEBUG=$(CONFIG_SFLC_DEBUG) modules
debug: CONFIG_SFLC_DEBUG=y
debug: default
install:
make -C $(KERNEL_DIR) M=$(BUILD_DIR) src=$(SRC_DIR) modules_install
make -C $(KERNEL_DIR) M=$(ROOT_DIR)/bin CONFIG_SFLC_DEBUG=$(CONFIG_SFLC_DEBUG) modules_install
clean:
rm -rf $(BUILD_DIR)
make -C $(KERNEL_DIR) M=$(ROOT_DIR)/bin CONFIG_SFLC_DEBUG=$(CONFIG_SFLC_DEBUG) clean
# Reserved
ORIGINALS = $(shell find src/ -type f)
SYMLINKS = $(patsubst src/%, bin/%, $(ORIGINALS))
symlinks: $(SYMLINKS)
bin/%: src/%
@mkdir -p "$(@D)"
ln -s $(shell realpath -m --relative-to=$(@D) $<) $@

View file

@ -25,14 +25,18 @@ MODULE_NAME := dm-sflc
obj-m := $(MODULE_NAME).o
OBJ_LIST := module.o
OBJ_LIST += sysfs/sysfs.o sysfs/devices.o sysfs/volumes.o
OBJ_LIST += target/target.o
OBJ_LIST += device/device.o device/volumes.o device/rawio.o device/rmap.o device/iv.o
OBJ_LIST += volume/volume.o volume/io.o volume/read.o volume/write.o volume/fmap.o
OBJ_LIST += utils/string.o utils/bio.o utils/pools.o utils/workqueues.o utils/vector.o
OBJ_LIST += crypto/rand/rand.o crypto/rand/selftest.o
OBJ_LIST += crypto/symkey/symkey.o crypto/symkey/skreq_pool.o crypto/symkey/selftest.o
OBJ_LIST := sflc.o dev_vol.o sysfs.o
OBJ_LIST += old/sflc_old.o old/target.o old/sysfs.o
OBJ_LIST += old/device/device.o old/device/volumes.o old/device/rawio.o old/device/rmap.o old/device/iv.o
OBJ_LIST += old/volume/volume.o old/volume/io.o old/volume/read.o old/volume/write.o old/volume/fmap.o
OBJ_LIST += old/utils/string.o old/utils/bio.o old/utils/pools.o old/utils/workqueues.o old/utils/vector.o
OBJ_LIST += old/crypto/rand/rand.o
OBJ_LIST += old/crypto/symkey/symkey.o old/crypto/symkey/skreq_pool.o
OBJ_LIST += lite/sflc_lite.o lite/sysfs.o
OBJ_LIST += lite/device.o lite/volume.o
OBJ_LIST += lite/posmap.o lite/read.o lite/write.o lite/crypto.o
$(MODULE_NAME)-y += $(OBJ_LIST)
@ -41,9 +45,9 @@ $(MODULE_NAME)-y += $(OBJ_LIST)
ccflags-y := -O2
ccflags-y += -I$(src)
ccflags-y += -Wall -Wno-declaration-after-statement
ccflags-y += -fmacro-prefix-map=$(src)/= # Strip the non-project directories from the filename used in the logs
# Debug CC flags
ccflags-$(CONFIG_SFLC_DEBUG) += -DDEBUG
ccflags-$(CONFIG_SFLC_DEBUG) += -Og -g
ccflags-$(CONFIG_SFLC_DEBUG) += -fsanitize=kernel-address -fno-omit-frame-pointer

1
dm-sflc/bin/dev_vol.c Symbolic link
View file

@ -0,0 +1 @@
../src/dev_vol.c

1
dm-sflc/bin/lite/crypto.c Symbolic link
View file

@ -0,0 +1 @@
../../src/lite/crypto.c

1
dm-sflc/bin/lite/device.c Symbolic link
View file

@ -0,0 +1 @@
../../src/lite/device.c

View file

@ -0,0 +1 @@
../../src/lite/dm_io_helper.h

1
dm-sflc/bin/lite/posmap.c Symbolic link
View file

@ -0,0 +1 @@
../../src/lite/posmap.c

1
dm-sflc/bin/lite/read.c Symbolic link
View file

@ -0,0 +1 @@
../../src/lite/read.c

View file

@ -0,0 +1 @@
../../src/lite/sflc_lite.c

View file

@ -0,0 +1 @@
../../src/lite/sflc_lite.h

View file

@ -0,0 +1 @@
../../src/lite/sflite_constants.h

1
dm-sflc/bin/lite/sysfs.c Symbolic link
View file

@ -0,0 +1 @@
../../src/lite/sysfs.c

1
dm-sflc/bin/lite/volume.c Symbolic link
View file

@ -0,0 +1 @@
../../src/lite/volume.c

1
dm-sflc/bin/lite/write.c Symbolic link
View file

@ -0,0 +1 @@
../../src/lite/write.c

View file

@ -0,0 +1 @@
../../../../src/old/crypto/rand/rand.c

View file

@ -0,0 +1 @@
../../../../src/old/crypto/rand/rand.h

View file

@ -0,0 +1 @@
../../../../src/old/crypto/symkey/skreq_pool.c

View file

@ -0,0 +1 @@
../../../../src/old/crypto/symkey/skreq_pool.h

View file

@ -0,0 +1 @@
../../../../src/old/crypto/symkey/symkey.c

View file

@ -0,0 +1 @@
../../../../src/old/crypto/symkey/symkey.h

View file

@ -0,0 +1 @@
../../../src/old/device/device.c

View file

@ -0,0 +1 @@
../../../src/old/device/device.h

1
dm-sflc/bin/old/device/iv.c Symbolic link
View file

@ -0,0 +1 @@
../../../src/old/device/iv.c

View file

@ -0,0 +1 @@
../../../src/old/device/rawio.c

View file

@ -0,0 +1 @@
../../../src/old/device/rmap.c

View file

@ -0,0 +1 @@
../../../src/old/device/volumes.c

1
dm-sflc/bin/old/log/log.h Symbolic link
View file

@ -0,0 +1 @@
../../../src/old/log/log.h

1
dm-sflc/bin/old/sflc_old.c Symbolic link
View file

@ -0,0 +1 @@
../../src/old/sflc_old.c

1
dm-sflc/bin/old/sflc_old.h Symbolic link
View file

@ -0,0 +1 @@
../../src/old/sflc_old.h

1
dm-sflc/bin/old/sysfs.c Symbolic link
View file

@ -0,0 +1 @@
../../src/old/sysfs.c

1
dm-sflc/bin/old/target.c Symbolic link
View file

@ -0,0 +1 @@
../../src/old/target.c

1
dm-sflc/bin/old/utils/bio.c Symbolic link
View file

@ -0,0 +1 @@
../../../src/old/utils/bio.c

1
dm-sflc/bin/old/utils/bio.h Symbolic link
View file

@ -0,0 +1 @@
../../../src/old/utils/bio.h

View file

@ -0,0 +1 @@
../../../src/old/utils/pools.c

View file

@ -0,0 +1 @@
../../../src/old/utils/pools.h

View file

@ -0,0 +1 @@
../../../src/old/utils/string.c

View file

@ -0,0 +1 @@
../../../src/old/utils/string.h

View file

@ -0,0 +1 @@
../../../src/old/utils/vector.c

View file

@ -0,0 +1 @@
../../../src/old/utils/vector.h

View file

@ -0,0 +1 @@
../../../src/old/utils/workqueues.c

View file

@ -0,0 +1 @@
../../../src/old/utils/workqueues.h

View file

@ -0,0 +1 @@
../../../src/old/volume/fmap.c

1
dm-sflc/bin/old/volume/io.c Symbolic link
View file

@ -0,0 +1 @@
../../../src/old/volume/io.c

View file

@ -0,0 +1 @@
../../../src/old/volume/read.c

View file

@ -0,0 +1 @@
../../../src/old/volume/volume.c

View file

@ -0,0 +1 @@
../../../src/old/volume/volume.h

View file

@ -0,0 +1 @@
../../../src/old/volume/write.c

1
dm-sflc/bin/sflc.c Symbolic link
View file

@ -0,0 +1 @@
../src/sflc.c

1
dm-sflc/bin/sflc.h Symbolic link
View file

@ -0,0 +1 @@
../src/sflc.h

View file

@ -0,0 +1 @@
../src/sflc_constants.h

1
dm-sflc/bin/sysfs.c Symbolic link
View file

@ -0,0 +1 @@
../src/sysfs.c

View file

@ -1,114 +0,0 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include <linux/slab.h>
#include "rand.h"
#include "log/log.h"
/*****************************************************
* CONSTANTS *
*****************************************************/
/*****************************************************
* PRIVATE VARIABLES *
*****************************************************/
/*****************************************************
* PRIVATE FUNCTIONS PROTOTYPES *
*****************************************************/
static void dumpHex(u8 * buf, unsigned count);
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
/* Selftest to see (by eye :D) if generated bytes are actually random */
int sflc_rand_selftest(void)
{
u8 * buf;
int err;
buf = kmalloc(32, GFP_KERNEL);
if (!buf) {
pr_err("Could not allocate random scratchpad\n");
return -ENOMEM;
}
/* Get random bytes the first time */
err = sflc_rand_getBytes(buf, 32);
if (err) {
pr_err("Got error when trying to read random bytes the first time: %d\n", err);
kfree(buf);
return err;
}
pr_debug("Here's 32 random bytes, fresh fresh!\n");
dumpHex(buf, 32);
/* Do it again */
err = sflc_rand_getBytes(buf, 32);
if (err) {
pr_err("Got error when trying to read random bytes the second time: %d\n", err);
kfree(buf);
return err;
}
pr_debug("Here's another 32 random bytes, fresh fresh pure questi!\n");
dumpHex(buf, 32);
pr_info("All well in the crypto rand self test? (Check random bytes)\n");
kfree(buf);
return 0;
}
/*****************************************************
* PRIVATE FUNCTIONS DEFINITIONS *
*****************************************************/
static void dumpHex(u8 * buf, unsigned count)
{
char * hex;
hex = kmalloc(6*count + 1, GFP_KERNEL);
if (!hex) {
pr_err("Could not allocate hex dump string\n");
return;
}
int i;
for (i = 0; i < count; i++) {
sprintf(hex+6*i, "0x%02X, ", buf[i]);
}
pr_notice("---- Hex dump ----\n");
pr_notice("%s", hex);
pr_notice("---- End of hex dump ----\n");
kfree(hex);
return;
}

View file

@ -1,261 +0,0 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include <linux/scatterlist.h>
#include <linux/random.h>
#include "symkey.h"
#include "log/log.h"
/*****************************************************
* CONSTANTS *
*****************************************************/
#define KEYS \
{ \
{0xF6, 0xD6, 0x6D, 0x6B, 0xD5, 0x2D, 0x59, 0xBB, 0x07, 0x96, 0x36, 0x58, 0x79, 0xEF, 0xF8, 0x86, \
0xC6, 0x6D, 0xD5, 0x1A, 0x5B, 0x6A, 0x99, 0x74, 0x4B, 0x50, 0x59, 0x0C, 0x87, 0xA2, 0x38, 0x84}, \
\
{0xFF, 0x7A, 0x61, 0x7C, 0xE6, 0x91, 0x48, 0xE4, 0xF1, 0x72, 0x6E, 0x2F, 0x43, 0x58, 0x1D, 0xE2, \
0xAA, 0x62, 0xD9, 0xF8, 0x05, 0x53, 0x2E, 0xDF, 0xF1, 0xEE, 0xD6, 0x87, 0xFB, 0x54, 0x15, 0x3D}, \
}
#define IVS \
{ \
{0x00, 0xFA, 0xAC, 0x24, 0xC1, 0x58, 0x5E, 0xF1, 0x5A, 0x43, 0xD8, 0x75, 0x00, 0x00, 0x00, 0x01}, \
\
{0x00, 0x1C, 0xC5, 0xB7, 0x51, 0xA5, 0x1D, 0x70, 0xA1, 0xC1, 0x11, 0x48, 0x00, 0x00, 0x00, 0x01}, \
}
#define PLAINTEXTS \
{ \
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, \
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}, \
\
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, \
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}, \
}
#define CIPHERTEXTS \
{ \
{0xF0, 0x5E, 0x23, 0x1B, 0x38, 0x94, 0x61, 0x2C, 0x49, 0xEE, 0x00, 0x0B, 0x80, 0x4E, 0xB2, 0xA9, \
0xB8, 0x30, 0x6B, 0x50, 0x8F, 0x83, 0x9D, 0x6A, 0x55, 0x30, 0x83, 0x1D, 0x93, 0x44, 0xAF, 0x1C}, \
\
{0xEB, 0x6C, 0x52, 0x82, 0x1D, 0x0B, 0xBB, 0xF7, 0xCE, 0x75, 0x94, 0x46, 0x2A, 0xCA, 0x4F, 0xAA, \
0xB4, 0x07, 0xDF, 0x86, 0x65, 0x69, 0xFD, 0x07, 0xF4, 0x8C, 0xC0, 0xB5, 0x83, 0xD6, 0x07, 0x1F}, \
}
/*****************************************************
* PRIVATE VARIABLES *
*****************************************************/
/*****************************************************
* PRIVATE FUNCTIONS PROTOTYPES *
*****************************************************/
/* Test encryption or decryption with known test vectors */
static int testEncdec(bool encrypt);
/* Test that encryption and decryption invert each other */
static int testRand(void);
static void dumpHex(u8 * buf, unsigned count);
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
/* Self test using known test vectors and random inputs */
int sflc_sk_selftest(void)
{
int err;
/* Test encryption */
err = testEncdec(true);
if (err) {
pr_err("Error in encryption test: %d\n", err);
return err;
}
/* Test decryption */
err = testEncdec(false);
if (err) {
pr_err("Error in decryption test: %d\n", err);
return err;
}
/* Test with random inputs */
err = testRand();
if (err) {
pr_err("Error in random test: %d\n", err);
return err;
}
pr_info("All good in crypto symkey selftest\n");
return 0;
}
/*****************************************************
* PRIVATE FUNCTIONS DEFINITIONS *
*****************************************************/
/* Test encryption or decryption with known test vectors */
static int testEncdec(bool encrypt)
{
sflc_sk_Context * ctx[2];
u8 scratchpad[32];
u8 key[2][32] = KEYS;
u8 iv[2][16] = IVS;
u8 pt[2][32] = PLAINTEXTS;
u8 ct[2][32] = CIPHERTEXTS;
int err;
int i;
for (i = 0; i < 2; i++) {
memset(scratchpad, 0xa7, 32);
ctx[i] = sflc_sk_createContext(key[i]);
if (IS_ERR(ctx)) {
err = PTR_ERR(ctx[i]);
pr_err("Could not create sk context; error %d\n", err);
return err;
}
if (encrypt) {
err = sflc_sk_encrypt(ctx[i], pt[i], scratchpad, 32, iv[i]);
if (err) {
pr_err("Failure during encryption %d; error %d\n", i, err);
sflc_sk_destroyContext(ctx[i]);
return err;
}
if(memcmp(scratchpad, ct[i], 32) != 0) {
pr_err("Mismatch for encryption %d\n", i);
dumpHex(scratchpad, 16);
sflc_sk_destroyContext(ctx[i]);
return -EINVAL;
}
}
else /* decrypt*/ {
err = sflc_sk_decrypt(ctx[i], ct[i], scratchpad, 32, iv[i]);
if (err) {
pr_err("Failure during decryption %d; error %d\n", i, err);
sflc_sk_destroyContext(ctx[i]);
return err;
}
if (memcmp(scratchpad, pt[i], 32) != 0) {
pr_err("Mismatch for decryption %d\n", i);
dumpHex(scratchpad, 32);
sflc_sk_destroyContext(ctx[i]);
return -EINVAL;
}
}
sflc_sk_destroyContext(ctx[i]);
}
return 0;
}
/* Test that encryption and decryption invert each other */
static int testRand(void)
{
u8 pt[48];
u8 scratchpad[48];
u8 key[32];
u8 iv[16];
sflc_sk_Context * ctx;
int err;
get_random_bytes(key, 32);
ctx = sflc_sk_createContext(key);
if (IS_ERR(ctx)) {
err = PTR_ERR(ctx);
pr_err("Could not create context; error %d\n", err);
return err;
}
memset(iv, 0, 16);
int i;
for (i = 0; i < 200; i++) {
get_random_bytes(pt, 48);
err = sflc_sk_encrypt(ctx, pt, scratchpad, 48, iv);
if (err) {
pr_err("Could not encrypt; error %d\n", err);
sflc_sk_destroyContext(ctx);
return err;
}
if (memcmp(pt, scratchpad, 48) == 0) {
pr_err("Random iteration %d; pt=scratchpad\n", i);
sflc_sk_destroyContext(ctx);
return -EINVAL;
}
/* Reset IV */
iv[15] = 0;
err = sflc_sk_decrypt(ctx, scratchpad, scratchpad, 48, iv);
if (err) {
pr_err("Could not decrypt; error %d\n", err);
sflc_sk_destroyContext(ctx);
return err;
}
if (memcmp(pt, scratchpad, 48) != 0) {
pr_err("Random iteration %d; mismatch. Dumping plaintext and scratchpad\n", i);
dumpHex(pt, 48);
dumpHex(scratchpad, 48);
sflc_sk_destroyContext(ctx);
return -EINVAL;
}
/* Reset IV */
iv[15] = 0;
}
sflc_sk_destroyContext(ctx);
return 0;
}
static void dumpHex(u8 * buf, unsigned count)
{
char * hex;
hex = kmalloc(6*count + 1, GFP_KERNEL);
if (!hex) {
pr_err("Could not allocate hex dump string\n");
return;
}
int i;
for (i = 0; i < count; i++) {
sprintf(hex+6*i, "0x%02X, ", buf[i]);
}
pr_notice("---- Hex dump ----\n");
pr_notice("%s", hex);
pr_notice("---- End of hex dump ----\n");
kfree(hex);
return;
}

View file

@ -1,376 +0,0 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
/*
* This file only implements the device-related device management functions.
*/
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include "device.h"
#include "sysfs/sysfs.h"
#include "utils/vector.h"
#include "log/log.h"
#include <linux/version.h>
#include <linux/vmalloc.h>
/*****************************************************
* CONSTANTS *
*****************************************************/
/*****************************************************
* PUBLIC VARIABLES DEFINITIONS *
*****************************************************/
/* The next available device ID */
size_t sflc_dev_nextId;
LIST_HEAD(sflc_dev_list);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
DEFINE_SEMAPHORE(sflc_dev_mutex, 1);
#else
DEFINE_SEMAPHORE(sflc_dev_mutex);
#endif
/*****************************************************
* PRIVATE VARIABLES *
*****************************************************/
/* Array tracking occupation of device IDs */
static bool *sflc_dev_occupiedIds;
/*****************************************************
* PRIVATE FUNCTIONS PROTOTYPES *
*****************************************************/
/* Acquire device ID, returns false if not possible */
static bool sflc_dev_acquireId(size_t id);
/* Release device ID */
static void sflc_dev_releaseId(size_t id);
/* Initialises and pre-shuffles the PSI array */
static int sflc_dev_initAndShufflePsiArray(u32 *psi_array, u32 len);
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
/* Inits global variables */
int sflc_dev_init(void)
{
/* Allocate occupation array */
sflc_dev_occupiedIds = kzalloc(SFLC_DEV_MAX_DEVICES_TOT, GFP_KERNEL);
if (!sflc_dev_occupiedIds) {
pr_err("Could not allocate array to track deviceID occupation");
return -ENOMEM;
}
/* First available ID is 0 */
sflc_dev_nextId = 0;
return 0;
}
/* Tears down global variables */
void sflc_dev_exit(void)
{
kfree(sflc_dev_occupiedIds);
}
/* Creates Device and adds it to the list. Returns an ERR_PTR() if unsuccessful. */
sflc_Device * sflc_dev_create(struct dm_target * ti, char * real_dev_path, u32 tot_slices)
{
sflc_Device * dev;
int err;
int i;
pr_debug("Called to create sflc_Device on %s\n", real_dev_path);
/* Allocate device */
dev = kzalloc(sizeof(sflc_Device), GFP_KERNEL);
if (!dev) {
pr_err("Could not allocate %lu bytes for sflc_Device\n", sizeof(sflc_Device));
err = -ENOMEM;
goto err_alloc_dev;
}
/* Init list node here, so it's always safe to list_del() */
INIT_LIST_HEAD(&dev->list_node);
/* Set device ID */
dev->dev_id = sflc_dev_nextId;
if (!sflc_dev_acquireId(sflc_dev_nextId)) {
pr_err("Could not create Device: max number of open devices reached");
err = -EINVAL;
goto err_dev_id;
}
/* Set backing real device */
err = dm_get_device(ti, real_dev_path, dm_table_get_mode(ti->table), &dev->bdev);
if (err) {
pr_err("Could not dm_get_device: error %d\n", err);
goto err_dm_get_dev;
}
/* And its path */
dev->bdev_path = kmalloc(strlen(real_dev_path) + 1, GFP_KERNEL);
if (!dev->bdev_path) {
pr_err("Could not allocate %lu bytes for dev->real_dev_path\n", strlen(real_dev_path) + 1);
err = -ENOMEM;
goto err_alloc_real_dev_path;
}
strcpy(dev->bdev_path, real_dev_path);
/* Init volumes */
for (i = 0; i < SFLC_DEV_MAX_VOLUMES; ++i) {
dev->vol[i] = NULL;
}
dev->vol_cnt = 0;
/* Set slices info */
dev->tot_slices = tot_slices;
dev->free_slices = tot_slices;
/* Compute header info (like in userland tool) */
u32 nr_pmbs_per_vol = DIV_ROUND_UP(tot_slices, SFLC_VOL_HEADER_MAPPINGS_PER_BLOCK);
dev->vol_header_nr_iv_blocks = DIV_ROUND_UP(nr_pmbs_per_vol, SFLC_VOL_LOG_SLICE_SIZE);
dev->vol_header_size = 1 + nr_pmbs_per_vol + dev->vol_header_nr_iv_blocks;
dev->dev_header_size = 1 + (SFLC_DEV_MAX_VOLUMES * dev->vol_header_size);
/* Init slices lock */
mutex_init(&dev->slices_lock);
/* Allocate reverse slice map */
dev->rmap = vmalloc(dev->tot_slices * sizeof(u8));
if (!dev->rmap) {
pr_err("Could not allocate reverse slice map\n");
err = -ENOMEM;
goto err_alloc_rmap;
}
/* Initialise it */
memset(dev->rmap, SFLC_DEV_RMAP_INVALID_VOL, dev->tot_slices * sizeof(u8));
/* Allocate PSI array */
dev->prmslices = vmalloc(dev->tot_slices * sizeof(u32));
if (!dev->prmslices) {
pr_err("Could not allocate PSI array\n");
err = -ENOMEM;
goto err_alloc_psi_array;
}
/* Initialise it and pre-shuffle it */
err = sflc_dev_initAndShufflePsiArray(dev->prmslices, dev->tot_slices);
if (err) {
pr_err("Could not init-and-shuffle PSI array: error %d", err);
goto err_initshuffle_psi_array;
}
/* Init related counter */
dev->prmslices_octr = 0;
/* Init IV cache lock */
mutex_init(&dev->iv_cache_lock);
/* Init IV cache waitqueue */
init_waitqueue_head(&dev->iv_cache_waitqueue);
/* Allocate IV cache */
dev->iv_cache = vzalloc(dev->tot_slices * sizeof(sflc_dev_IvCacheEntry *));
if (!dev->iv_cache) {
pr_err("Could not allocate IV cache\n");
err = -ENOMEM;
goto err_alloc_iv_cache;
}
/* Set it empty */
dev->iv_cache_nr_entries = 0;
/* Init list head */
INIT_LIST_HEAD(&dev->iv_lru_list);
/* Create kobject */
dev->kobj = sflc_sysfs_devCreateAndAdd(dev);
if (IS_ERR(dev->kobj)) {
err = PTR_ERR(dev->kobj);
pr_err("Could not create kobject; error %d\n", err);
goto err_sysfs;
}
/* Create dm_io_client */
dev->dmio_client = dm_io_client_create();
if (IS_ERR(dev->dmio_client)) {
err = PTR_ERR(dev->dmio_client);
pr_err("Could not create dm_io_client; error %d\n", err);
goto err_dmio;
}
/* Add to device list */
list_add_tail(&dev->list_node, &sflc_dev_list);
return dev;
err_dmio:
sflc_sysfs_putDev(dev->kobj);
err_sysfs:
vfree(dev->iv_cache);
err_alloc_iv_cache:
err_initshuffle_psi_array:
vfree(dev->prmslices);
err_alloc_psi_array:
vfree(dev->rmap);
err_alloc_rmap:
kfree(dev->bdev_path);
err_alloc_real_dev_path:
dm_put_device(ti, dev->bdev);
err_dm_get_dev:
sflc_dev_releaseId(dev->dev_id);
err_dev_id:
kfree(dev);
err_alloc_dev:
return ERR_PTR(err);
}
/* Returns NULL if not found */
sflc_Device * sflc_dev_lookupByPath(char * real_dev_path)
{
sflc_Device * dev;
/* Sweep the list of devices */
list_for_each_entry(dev, &sflc_dev_list, list_node) {
if (strcmp(real_dev_path, dev->bdev_path) == 0) {
return dev;
}
}
return NULL;
}
/* Returns false if still busy (not all volumes have been removed). Frees the Device. */
bool sflc_dev_destroy(struct dm_target * ti, sflc_Device * dev)
{
/* Check if we actually have to put this device */
if (!dev) {
return false;
}
if (dev->vol_cnt > 0) {
pr_warn("Called while still holding %d volumes\n", dev->vol_cnt);
return false;
}
/* Flush all IVs */
sflc_dev_flushIvs(dev);
/* List */
list_del(&dev->list_node);
/* dm_io */
dm_io_client_destroy(dev->dmio_client);
/* Sysfs */
sflc_sysfs_putDev(dev->kobj);
/* IV cache */
vfree(dev->iv_cache);
/* PSI array */
vfree(dev->prmslices);
/* Reverse slice map */
vfree(dev->rmap);
/* Backing device */
dm_put_device(ti, dev->bdev);
kfree(dev->bdev_path);
/* Release device ID */
sflc_dev_releaseId(dev->dev_id);
/* Free the device itself */
kfree(dev);
return true;
}
/*****************************************************
* PRIVATE FUNCTIONS DEFINITIONS *
*****************************************************/
/* Acquire device ID, returns false if not possible */
static bool sflc_dev_acquireId(size_t id)
{
/* Sanity check */
if (id >= SFLC_DEV_MAX_DEVICES_TOT) {
return false;
}
/* Check occupation */
if (sflc_dev_occupiedIds[id]) {
return false;
}
/* Mark as occupied */
sflc_dev_occupiedIds[id] = true;
/* Update the nextId if necessary */
if (id == sflc_dev_nextId) {
/* Jump to the next unoccupied ID */
for (; id < SFLC_DEV_MAX_DEVICES_TOT && sflc_dev_occupiedIds[id]; id++);
sflc_dev_nextId = id;
}
return true;
}
/* Release volume ID */
static void sflc_dev_releaseId(size_t id)
{
/* Sanity check */
if (id >= SFLC_DEV_MAX_DEVICES_TOT) {
return;
}
/* Mark as unoccupied */
sflc_dev_occupiedIds[id] = false;
/* Update the nextId if necessary */
if (id < sflc_dev_nextId) {
sflc_dev_nextId = id;
}
return;
}
/* Initialises and pre-shuffles the PSI array */
static int sflc_dev_initAndShufflePsiArray(u32 *psi_array, u32 len)
{
u32 i;
/* Init to the identity map */
for (i = 0; i < len; i++) {
psi_array[i] = i;
}
/* Permute */
return sflc_vec_u32shuffle(psi_array, len);
}

View file

@ -1,151 +0,0 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include <linux/module.h>
#include <linux/device-mapper.h>
#include "sysfs/sysfs.h"
#include "target/target.h"
#include "crypto/symkey/symkey.h"
#include "crypto/rand/rand.h"
#include "utils/pools.h"
#include "utils/workqueues.h"
#include "log/log.h"
/*****************************************************
* MODULE FUNCTION PROTOTYPES *
*****************************************************/
static int sflc_init(void);
static void sflc_exit(void);
/*****************************************************
* MODULE FUNCTIONS DEFINITIONS *
*****************************************************/
/* Module entry point, called just once, at module-load time */
static int sflc_init(void)
{
int ret;
ret = sflc_dev_init();
if (ret) {
pr_err("Could not init device module; error %d\n", ret);
goto err_dev_init;
}
ret = sflc_rand_init();
if (ret) {
pr_err("Could not init rand; error %d\n", ret);
goto err_rand_init;
}
/* Run crypto symkey self test */
ret = sflc_sk_selftest();
if (ret) {
pr_err("Error in crypto symkey self test: %d\n", ret);
goto err_sk;
}
/* Run crypto rand self test */
ret = sflc_rand_selftest();
if (ret) {
pr_err("Error in crypto rand self test: %d\n", ret);
goto err_rand_selftest;
}
/* Create the first sysfs entries */
ret = sflc_sysfs_init();
if (ret) {
pr_err("Could not init sysfs; error %d\n", ret);
goto err_sysfs;
}
/* Init the memory pools */
ret = sflc_pools_init();
if (ret) {
pr_err("Could not init memory pools; error %d\n", ret);
goto err_pools;
}
/* Init the workqueues */
ret = sflc_queues_init();
if (ret) {
pr_err("Could not init workqueues; error %d\n", ret);
goto err_queues;
}
/* Register the DM callbacks */
ret = dm_register_target(&sflc_target);
if (ret < 0) {
pr_err("dm_register failed: %d", ret);
goto err_dm;
}
pr_info("Shufflecake loaded");
return 0;
err_dm:
sflc_queues_exit();
err_queues:
sflc_pools_exit();
err_pools:
sflc_sysfs_exit();
err_sysfs:
err_rand_selftest:
err_sk:
sflc_rand_exit();
err_rand_init:
sflc_dev_exit();
err_dev_init:
return ret;
}
/* Module exit point, called just once, at module-unload time */
static void sflc_exit(void)
{
dm_unregister_target(&sflc_target);
sflc_queues_exit();
sflc_pools_exit();
sflc_sysfs_exit();
sflc_rand_exit();
sflc_dev_exit();
pr_info("Shufflecake unloaded");
return;
}
/* Declare them as such to the kernel */
module_init(sflc_init);
module_exit(sflc_exit);
/*****************************************************
* MODULE INFO *
*****************************************************/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Toninov");

209
dm-sflc/src/dev_vol.c Normal file
View file

@ -0,0 +1,209 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
#include <linux/delay.h>
#include "sflc.h"
#include "old/sflc_old.h"
/* Create a sflc_device containing the appropriate mode-specific struct */
struct sflc_device *sflc_dev_create(struct dm_target *ti, int argc, char **argv)
{
struct sflc_device *sdev;
u32 dev_id;
dev_t devt;
int mode;
int err;
sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
if (!sdev) {
DMERR("Could not allocate device");
return ERR_PTR(-ENOMEM);
}
/* Parse arguments */
if (sscanf(argv[0], "%d", &mode) != 1) {
err = -EINVAL;
goto bad_parse;
}
sscanf(argv[1], "%u", &dev_id);
err = lookup_bdev(argv[2], &devt);
if (err) {
DMERR("Could not look up block device");
goto bad_parse;
}
/* Assign fields */
sdev->dev_id = dev_id;
sdev->nr_volumes = 0;
sdev->mode = mode;
format_dev_t(sdev->name, devt);
/* Register with sysfs */
err = sflc_sysfs_register_device(sdev);
if (err)
goto bad_sysfs;
/* Instantiate inner device. Sysfs has to be inited by now */
switch (mode)
{
case SFLC_MODE_LEGACY:
sdev->sfold_dev = sfold_dev_create(ti, argc, argv, &sdev->kobj);
if (IS_ERR(sdev->sfold_dev)) {
err = PTR_ERR(sdev->sfold_dev);
goto bad_inner;
}
break;
case SFLC_MODE_LITE:
sdev->sflite_dev = sflite_dev_create(ti, argc, argv, &sdev->kobj);
if (IS_ERR(sdev->sflite_dev)) {
err = PTR_ERR(sdev->sflite_dev);
goto bad_inner;
}
break;
default:
DMERR("Invalid Shufflecake mode %d", mode);
err = -EINVAL;
goto bad_mode;
}
return sdev;
bad_mode:
bad_inner:
sflc_sysfs_unregister_device(sdev);
bad_sysfs:
bad_parse:
kfree(sdev);
return ERR_PTR(err);
}
void sflc_dev_destroy(struct sflc_device *sdev)
{
switch (sdev->mode)
{
case SFLC_MODE_LEGACY:
sfold_dev_destroy(sdev->sfold_dev);
break;
case SFLC_MODE_LITE:
sflite_dev_destroy(sdev->sflite_dev);
break;
default:
DMCRIT("Destroying device with invalid Shufflecake mode %d", sdev->mode);
return;
}
sflc_sysfs_unregister_device(sdev);
kfree(sdev);
}
/* Create a sflc_volume containing the appropriate mode-specific struct */
struct sflc_volume *sflc_vol_create(struct sflc_device *sdev, struct dm_target *ti,
int argc, char **argv)
{
struct sflc_volume *svol;
u32 vol_idx;
int mode;
int err;
svol = kzalloc(sizeof(*svol), GFP_KERNEL);
if (!svol) {
DMERR("Could not allocate volume");
return ERR_PTR(-ENOMEM);
}
/* Parse arguments */
if (sscanf(argv[0], "%d", &mode) != 1) {
err = -EINVAL;
goto bad_parse;
}
sscanf(argv[3], "%u", &vol_idx);
/* Assign fields */
svol->mode = mode;
sprintf(svol->name, "sflc_%u_%u", sdev->dev_id, vol_idx);
svol->sdev = sdev;
/* Register with sysfs */
err = sflc_sysfs_register_volume(svol);
if (err)
goto bad_sysfs;
/* Instantiate inner volume. Sysfs has to be inited by now */
switch (mode)
{
case SFLC_MODE_LEGACY:
svol->sfold_vol = sfold_vol_create(ti, sdev->sfold_dev, argc, argv, &svol->kobj);
if (IS_ERR(svol->sfold_vol)) {
err = PTR_ERR(svol->sfold_vol);
goto bad_inner;
}
svol->tt = &sfold_target_type;
break;
case SFLC_MODE_LITE:
svol->sflite_vol = sflite_vol_create(ti, sdev->sflite_dev, argc, argv, &svol->kobj);
if (IS_ERR(svol->sflite_vol)) {
err = PTR_ERR(svol->sflite_vol);
goto bad_inner;
}
svol->tt = &sflite_target_type;
break;
default:
DMERR("Invalid Shufflecake mode %d", mode);
err = -EINVAL;
goto bad_mode;
}
return svol;
bad_mode:
bad_inner:
sflc_sysfs_unregister_volume(svol);
bad_sysfs:
bad_parse:
kfree(svol);
return ERR_PTR(err);
}
void sflc_vol_destroy(struct sflc_volume *svol)
{
switch (svol->mode)
{
case SFLC_MODE_LEGACY:
sfold_vol_destroy(svol->sfold_vol);
break;
case SFLC_MODE_LITE:
sflite_vol_destroy(svol->sflite_vol);
break;
default:
DMCRIT("Destroying volume with invalid Shufflecake mode %d", svol->mode);
return;
}
sflc_sysfs_unregister_volume(svol);
kfree(svol);
}

125
dm-sflc/src/lite/crypto.c Normal file
View file

@ -0,0 +1,125 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
#include <linux/scatterlist.h>
#include <linux/crypto.h>
#include <crypto/skcipher.h>
#include "sflite_constants.h"
#include "sflc_lite.h"
/**
* Encrypt/decrypt exactly one block, already encoded in the scatterlist.
* All other crypto functions reduce to this one.
* The IV is constructed as the right-0-padded LE representation of the
* physical block number, which is exactly what dm-crypt does when using the
* IV mode "plain64".
*/
static int crypt_sg(struct crypto_skcipher *tfm, struct scatterlist *src,
struct scatterlist *dst, u64 pblk_num, int rw)
{
u8 iv[SFLITE_XTS_IVLEN];
struct skcipher_request *req = NULL;
DECLARE_CRYPTO_WAIT(wait);
int err;
// TODO not too sure about the gfp_mask here
// TODO move @req into struct sflite_io?
req = skcipher_request_alloc(tfm, GFP_NOIO);
if (!req)
return -ENOMEM;
skcipher_request_set_callback(req,
CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
crypto_req_done, &wait);
/* Construct IV */
memset(iv, 0, SFLITE_XTS_IVLEN);
*(__le64 *)iv = cpu_to_le64(pblk_num);
skcipher_request_set_crypt(req, src, dst, SFLITE_BLOCK_SIZE, iv);
if (rw == READ)
err = crypto_wait_req(crypto_skcipher_decrypt(req), &wait);
else
err = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
skcipher_request_free(req);
return err;
}
/* Encrypt-decrypt a single block (memory buffer is a page) */
int sflite_crypt_block_page(struct crypto_skcipher *tfm, struct page *src_page,
struct page *dst_page, u64 pblk_num, int rw)
{
struct scatterlist dst, src, *p_dst;
bool is_inplace;
/* Use same scatterlist if in-place */
is_inplace = (src_page == dst_page);
p_dst = is_inplace ? &src : &dst;
/* We assume PAGE_SIZE == SFLITE_BLOCK_SIZE */
/* And orig_bio to start at offset 0 within the page */
sg_init_table(&src, 1);
sg_set_page(&src, src_page, SFLITE_BLOCK_SIZE, 0);
if (!is_inplace) {
sg_init_table(&dst, 1);
sg_set_page(&dst, dst_page, SFLITE_BLOCK_SIZE, 0);
}
return crypt_sg(tfm, &src, p_dst, pblk_num, rw);
}
/* Encrypt-decrypt consecutive blocks (memory buffer is vmalloc'ed) */
int sflite_crypt_blocks_vm(struct crypto_skcipher *tfm, void *src_buf, void *dst_buf,
u64 num_blocks, u64 first_pblk_num, int rw)
{
struct scatterlist dst, src, *p_dst;
u64 pblk_num;
bool is_inplace;
int err;
/* Use same scatterlist if in-place */
is_inplace = (src_buf == dst_buf);
p_dst = is_inplace ? &src : &dst;
for (pblk_num = first_pblk_num;
pblk_num < first_pblk_num + num_blocks;
pblk_num++) {
sg_init_one(&src, src_buf, SFLITE_BLOCK_SIZE);
if (!is_inplace)
sg_init_one(&dst, dst_buf, SFLITE_BLOCK_SIZE);
err = crypt_sg(tfm, &src, p_dst, pblk_num, rw);
if (err)
return err;
src_buf += SFLITE_BLOCK_SIZE;
dst_buf += SFLITE_BLOCK_SIZE;
}
return 0;
}

204
dm-sflc/src/lite/device.c Normal file
View file

@ -0,0 +1,204 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
#include <linux/vmalloc.h>
#include <linux/math.h>
#include <linux/random.h>
#include <linux/minmax.h>
#include "sflc_lite.h"
/* Depth of the mempool backing the bio_set */
#define SFLITE_BIOSET_BIOS 64
/* Fisher-Yates shuffle */
static void fisheryates_u32(u32 *v, u32 len)
{
u32 i, j;
for (i = len-1; i >= 1; i--) {
j = get_random_u32_below(i+1);
swap(v[i], v[j]);
}
return;
}
/**
* Arguments:
* argv[0]: Shufflecake mode: legacy/lite
* argv[1]: Shufflecake-unique device ID
* argv[2]: path to underlying physical device
* argv[3]: volume index within the device
* argv[4]: number of 1 MB slices in the underlying device
* argv[5]: 64-byte encryption key (hex-encoded)
*/
struct sflite_device *sflite_dev_create(struct dm_target *ti, int argc, char **argv, struct kobject *kobj)
{
struct sflite_device *sdev;
dev_t devt;
u32 dev_id;
u32 tot_slices;
int i;
int err;
sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
if (!sdev) {
DMERR("Could not allocate device");
return ERR_PTR(-ENOMEM);
}
/* Parse args */
if (argc != 6) {
pr_err("Wrong argument count");
err = -EINVAL;
goto bad_parse;
}
sscanf(argv[1], "%u", &dev_id);
if (sscanf(argv[4], "%u", &tot_slices) != 1) {
pr_err("Could not decode tot_slices\n");
err = -EINVAL;
goto bad_parse;
}
sdev->dev_id = dev_id;
/* Look up block device and set name */
err = lookup_bdev(argv[2], &devt);
if (err) {
DMERR("Could not look up block device");
goto bad_lookup;
}
format_dev_t(sdev->name, devt);
/* Compute sizes */
sdev->tot_slices = tot_slices;
sdev->nr_free_slices = tot_slices;
/* Enough posmap blocks to fit all the entries */
sdev->posmap_size_sectors = SFLITE_BLOCK_SCALE *
DIV_ROUND_UP(tot_slices, SFLITE_PSIS_PER_BLOCK);
/* DMB + VMBs + PosMaps */
sdev->dev_header_size_sectors = SFLITE_BLOCK_SCALE +
(SFLITE_DEV_MAX_VOLUMES * SFLITE_BLOCK_SCALE) +
(SFLITE_DEV_MAX_VOLUMES * sdev->posmap_size_sectors);
/* Shuffled PSIs */
mutex_init(&sdev->slices_lock);
sdev->slices_ofld = vzalloc(tot_slices * sizeof(bool));
if (!sdev->slices_ofld) {
DMERR("Could not allocate PSI occupation bitfield");
err = -ENOMEM;
goto bad_ofld;
}
sdev->prmslices = vmalloc(tot_slices * sizeof(u32));
if (!sdev->prmslices) {
DMERR("Could not allocate shuffled PSI array");
err = -ENOMEM;
goto bad_prmslices;
}
/* Generate a permutation */
for (i = 0; i < tot_slices; i++)
sdev->prmslices[i] = i;
fisheryates_u32(sdev->prmslices, tot_slices);
sdev->prmslices_octr = 0;
/* Bioset */
err = bioset_init(&sdev->bioset, SFLITE_BIOSET_BIOS, 0, BIOSET_NEED_BVECS);
if (err) {
DMERR("Could not init bioset; error %d", err);
goto bad_bioset;
}
/* Client for dm-io */
sdev->io_client = dm_io_client_create();
if (IS_ERR(sdev->io_client)) {
err = PTR_ERR(sdev->io_client);
DMERR("Could not create dm-io client; error %d", err);
goto bad_dmio_client;
}
/* I/O workqueue */
sdev->io_queue = alloc_workqueue("sflite_%s_io",
WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE,
0, sdev->name);
if (!sdev->io_queue) {
err = -ENOMEM;
DMERR("Could not allocate I/O workqueue");
goto bad_io_wq;
}
/* Decryption workqueue */
sdev->crypt_queue = alloc_workqueue("sflite_%s_crypt",
WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE,
0, sdev->name);
if (!sdev->crypt_queue) {
err = -ENOMEM;
DMERR("Could not allocate decryption workqueue");
goto bad_crypt_wq;
}
/* Add to sysfs, once initialised */
sdev->kobj_parent = kobj;
err = sflite_sysfs_add_device(sdev);
if (err)
goto bad_sysfs;
return sdev;
bad_sysfs:
destroy_workqueue(sdev->crypt_queue);
bad_crypt_wq:
destroy_workqueue(sdev->io_queue);
bad_io_wq:
dm_io_client_destroy(sdev->io_client);
bad_dmio_client:
bioset_exit(&sdev->bioset);
bad_bioset:
vfree(sdev->prmslices);
bad_prmslices:
vfree(sdev->slices_ofld);
bad_ofld:
bad_lookup:
bad_parse:
kfree(sdev);
return ERR_PTR(err);
}
void sflite_dev_destroy(struct sflite_device *sdev)
{
sflite_sysfs_remove_device(sdev);
destroy_workqueue(sdev->crypt_queue);
destroy_workqueue(sdev->io_queue);
dm_io_client_destroy(sdev->io_client);
bioset_exit(&sdev->bioset);
vfree(sdev->prmslices);
vfree(sdev->slices_ofld);
kfree(sdev);
return;
}

View file

@ -0,0 +1,56 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
#ifndef _SFLITE_DMIOHELPER_H
#define _SFLITE_DMIOHELPER_H
#include <linux/dm-io.h>
#include <generated/uapi/linux/version.h>
/**
* The function dm_io() has changed signature in recent kernels.
* Here we provide a version-independent adapter, which uses a default value
* for the fifth parameter (the new one).
* The new signature is present for kernel 6.1.x with x>=83, 6.6.x with x>=23,
* 6.7.x with x>=11, 6.8.x with x>=2, 6.x with x>=9
*/
#if LINUX_VERSION_MAJOR <= 5 // Old
#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err)
#elif LINUX_VERSION_MAJOR >= 7 // New
#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err, IOPRIO_DEFAULT)
// Ok LINUX_VERSION_MAJOR is 6
#elif LINUX_VERSION_PATCHLEVEL >= 9 // New
#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err, IOPRIO_DEFAULT)
#elif LINUX_VERSION_PATCHLEVEL == 8 && LINUX_VERSION_SUBLEVEL >= 2 // New
#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err, IOPRIO_DEFAULT)
#elif LINUX_VERSION_PATCHLEVEL == 7 && LINUX_VERSION_SUBLEVEL >= 11 // New
#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err, IOPRIO_DEFAULT)
#elif LINUX_VERSION_PATCHLEVEL == 6 && LINUX_VERSION_SUBLEVEL >= 23 // New
#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err, IOPRIO_DEFAULT)
#elif LINUX_VERSION_PATCHLEVEL == 1 && LINUX_VERSION_SUBLEVEL >= 83 // New
#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err, IOPRIO_DEFAULT)
#else // Old
#define sflc_dm_io(ioreq, numreg, region, err) dm_io(ioreq, numreg, region, err)
#endif
#endif /* _SFLITE_DMIOHELPER_H */

377
dm-sflc/src/lite/posmap.c Normal file
View file

@ -0,0 +1,377 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
#include <linux/minmax.h>
#include <linux/delay.h>
#include "dm_io_helper.h"
#include "sflc_lite.h"
/* Helpers */
#define IS_PSI_TAKEN(sdev, psi) ( (sdev)->slices_ofld[(psi)] )
#define NEXT_RANDOM_PSI(sdev) ( (sdev)->prmslices[(sdev)->prmslices_octr] )
#define IS_LAST_LSI_IN_BLOCK(lsi, sdev) ( (((lsi)+1) % SFLITE_PSIS_PER_BLOCK == 0) || \
(((lsi)+1) == (sdev)->tot_slices) )
/*
*----------------------------
* Create slice mapping
*----------------------------
*/
/**
* Return the next free PSI in the device's shuffled array, without modifying
* the device state.
*
* MUTEX: @sdev->slices_lock must be held.
*/
static int peek_next_free_psi(struct sflite_device *sdev, u32 *psi)
{
if (unlikely(!sdev->nr_free_slices))
return -ENOSPC;
if (unlikely(sdev->prmslices_octr >= sdev->tot_slices)) {
DMCRIT("octr = %u, tot_slices = %u, free_slices = %u", sdev->prmslices_octr, sdev->tot_slices, sdev->nr_free_slices);
print_hex_dump(KERN_CRIT, "prmslices(REV) ", DUMP_PREFIX_OFFSET, 32, 4, sdev->prmslices, 4*sdev->tot_slices, false);
msleep(10000);
print_hex_dump(KERN_CRIT, "ofld(REV) ", DUMP_PREFIX_OFFSET, 32, 1, sdev->slices_ofld, sdev->tot_slices, false);
msleep(10000);
return -ENOTRECOVERABLE; // Grave inconsistency
}
/* Invariant: @prmslices_octr points to a free slice */
*psi = NEXT_RANDOM_PSI(sdev);
if (unlikely(IS_PSI_TAKEN(sdev, *psi))){
DMCRIT("octr = %u, tot_slices = %u, free_slices = %u", sdev->prmslices_octr, sdev->tot_slices, sdev->nr_free_slices);
DMCRIT("PSI %u is occupied", *psi);
print_hex_dump(KERN_CRIT, "prmslices ", DUMP_PREFIX_OFFSET, 32, 4, sdev->prmslices, 4*sdev->tot_slices, false);
msleep(10000);
print_hex_dump(KERN_CRIT, "ofld ", DUMP_PREFIX_OFFSET, 32, 1, sdev->slices_ofld, sdev->tot_slices, false);
msleep(10000);
return -ENOTRECOVERABLE; // Grave inconsistency
}
return 0;
}
/**
* Map LSI => PSI, only in memory.
* Sanity checks to be performed by the caller.
*
* MUTEX: @sdev->slices_lock must be held.
* MUTEX: @svol->posmap_lock must be held, except under volume ctor.
*/
static void _create_local_slice_mapping(struct sflite_volume *svol, u32 lsi, u32 psi)
{
struct sflite_device *sdev = svol->sdev;
/* Grab it from the device */
sdev->slices_ofld[psi] = true;
sdev->nr_free_slices--;
// Preserve the invariant: @prmslices_octr must point to a free slice
while(sdev->prmslices_octr < sdev->tot_slices &&
IS_PSI_TAKEN(sdev, NEXT_RANDOM_PSI(sdev))) {
sdev->prmslices_octr++;
}
/* Insert in the volume */
svol->posmap[lsi] = psi;
svol->nr_mapped_slices++;
return;
}
/**
* Delete mapping for the given LSI, only in memory.
* Sanity checks to be performed by the caller.
*
* MUTEX: @svol->posmap_lock must be held, except under volume ctor.
*/
static void _delete_local_slice_mapping(struct sflite_volume *svol, u32 lsi)
{
/* Delete mapping in the volume */
svol->posmap[lsi] = SFLITE_PSI_INVALID;
svol->nr_mapped_slices--;
/* Don't do anything in the device though, leave it there: we don't yet
* have an obvious way to release PSIs.
* This means a PSI will be incorrectly marked as occupied, but that's
* not too bad: the PSI shuffling and its occupation counter are
* ephemeral, so they reset if you close and reopen all the volumes. */
return;
}
/**
* Synchronously store (and flush) the given posmap block
*
* MUTEX: @svol->posmap_lock must be held, except under volume ctor.
*/
static int store_posmap_block(struct sflite_volume *svol, u32 posmap_block_num)
{
struct sflite_device *sdev = svol->sdev;
struct page *page;
struct bio *bio;
int err;
/* Sync + flush TODO GFP mask ok? */
bio = bio_alloc_bioset(svol->dm_dev->bdev, 1,
REQ_OP_WRITE | REQ_SYNC | REQ_FUA, GFP_NOIO,
&sdev->bioset);
if (!bio) {
DMERR("Could not allocate posmap block bio");
return -ENOMEM;
}
bio->bi_iter.bi_sector = SFLITE_POSMAP_START_SECTOR(svol) +
(posmap_block_num << SFLITE_BLOCK_SHIFT);
/* Alloc and add page TODO GFP mask */
page = alloc_page(GFP_NOIO);
if (!page) {
DMERR("Could not allocate posmap block page");
err = -ENOMEM;
goto bad_alloc_page;
}
// TODO remove this error check
if (unlikely(!bio_add_page(bio, page, SFLITE_BLOCK_SIZE, 0))) {
DMCRIT("Could not add posmap block page to bio!");
err = -ENOTRECOVERABLE;
goto bad_add_page;
}
/* Serialise posmap block onto the page */
void *page_ptr = kmap_local_page(page);
u32 first_lsi = posmap_block_num * SFLITE_PSIS_PER_BLOCK;
u32 last_lsi = min(first_lsi + SFLITE_PSIS_PER_BLOCK, sdev->tot_slices);
u32 lsi;
for (lsi = first_lsi; lsi < last_lsi; lsi++) {
u32 psi = svol->posmap[lsi];
__be32 *be_psi = (__be32*) (page_ptr + ((lsi-first_lsi) * sizeof(__be32)));
*be_psi = cpu_to_be32(psi);
}
// print_hex_dump(KERN_WARNING, "page_ptr(REV) ", DUMP_PREFIX_OFFSET, 32, 4, page_ptr, SFLITE_BLOCK_SIZE, false);
// msleep(100);
kunmap_local(page_ptr);
/* Encrypt the block in place */
err = sflite_crypt_block_page(svol->tfm, page, page,
bio->bi_iter.bi_sector >> SFLITE_BLOCK_SHIFT, WRITE);
if (err) {
DMERR("Could not encrypt posmap block; error %d", err);
goto bad_encrypt;
}
/* Submit */
err = submit_bio_wait(bio);
if (err)
DMERR("Could not complete posmap block bio; error %d", err);
bad_encrypt:
bad_add_page:
__free_page(page);
bad_alloc_page:
bio_put(bio);
return err;
}
/**
* Create a new mapping for the given LSI, and synchronise back to disk.
*
* MUTEX: @svol->posmap_lock must be held, except under volume ctor.
* MUTEX: takes @sdev->slices_lock.
*
* Syncing to disk means the posmap lock will be held (by the caller) for a long
* time thus blocking out all the other incoming bio's, even unrelated ones
* (falling in different slices). Several strategies are possible to avoid this
* problem, but for now we keep this simple implementation.
*/
int sflite_create_persistent_slice_mapping(struct sflite_volume *svol, u32 lsi, u32 *psi)
{
struct sflite_device *sdev = svol->sdev;
int err;
/* Bounds check TODO redundant? */
if(unlikely(lsi >= svol->sdev->tot_slices))
return -EINVAL;
/* Check mapping not existent TODO redundant? */
if (unlikely(svol->posmap[lsi] != SFLITE_PSI_INVALID))
return -EINVAL;
/* Create mapping */
if (mutex_lock_interruptible(&sdev->slices_lock))
return -ERESTARTSYS;
err = peek_next_free_psi(sdev, psi);
if (err) {
mutex_unlock(&sdev->slices_lock);
return err;
}
_create_local_slice_mapping(svol, lsi, *psi);
mutex_unlock(&sdev->slices_lock);
/* Write posmap block to disk */
err = store_posmap_block(svol, lsi/SFLITE_PSIS_PER_BLOCK);
if (err) {
DMERR("Could not store posmap block; error %d", err);
_delete_local_slice_mapping(svol, lsi);
return err;
}
return 0;
}
/*
*----------------------------
* Load position map
*----------------------------
*/
/**
* Synchronously read the entire on-disk encrypted position map
*
* MUTEX: no need for the caller to hold @svol->posmap_lock (we are in ctor).
*/
static int read_encrypted_posmap(struct sflite_volume *svol)
{
struct dm_io_request io_req = {
.bi_opf = REQ_OP_READ | REQ_SYNC,
.mem.type = DM_IO_VMA,
.mem.ptr.vma = svol->posmap,
.notify.fn = NULL,
.client = svol->sdev->io_client
};
struct dm_io_region io_region = {
.bdev = svol->dm_dev->bdev,
.sector = SFLITE_POSMAP_START_SECTOR(svol),
.count = svol->sdev->posmap_size_sectors
};
return sflc_dm_io(&io_req, 1, &io_region, NULL);
}
/**
* De-serialise the position map entries. On the fly, if a conflict is detected,
* resolve it by sampling a new PSI, and sync to disk (block by block).
*
* MUTEX: no need for the caller to hold @svol->posmap_lock (we are in ctor).
* MUTEX: @sdev->slices_lock must be held.
*/
static int _deserialise_and_sanitise_posmap(struct sflite_volume *svol)
{
struct sflite_device *sdev = svol->sdev;
void *posmap_ptr = svol->posmap;
u32 lsi;
bool posmap_block_dirty;
int err;
for (lsi = 0; lsi < sdev->tot_slices; lsi++) {
/* Reset dirty bit at the start of every posmap block */
if (lsi % SFLITE_PSIS_PER_BLOCK == 0)
posmap_block_dirty = false;
/* De-serialise posmap entry */
__be32 *be_psi = (__be32*) (posmap_ptr + (lsi * sizeof(__be32)));
u32 psi = be32_to_cpu(*be_psi);
/* If LSI unmapped, skip mapping creation */
if (psi == SFLITE_PSI_INVALID) {
svol->posmap[lsi] = psi;
goto skip_create_mapping;
}
/* If PSI out of bounds, something's seriously wrong */
if (psi >= sdev->tot_slices) {
DMERR("Decrypted PSI out of bounds: %u >= %u", psi, sdev->tot_slices);
return -EDOM;
}
/* If PSI already taken, sample a new one */
if (sdev->slices_ofld[psi]) {
DMWARN("Corruption of volume %u: LSI %u was evicted from PSI %u",
svol->vol_idx, lsi, psi);
err = peek_next_free_psi(sdev, &psi);
if (err)
return err;
posmap_block_dirty = true;
}
/* Whether sanitised or not, create the mapping locally */
_create_local_slice_mapping(svol, lsi, psi);
skip_create_mapping:
/* Only check dirty bit at the end of the posmap block */
if (posmap_block_dirty &&
IS_LAST_LSI_IN_BLOCK(lsi, sdev)) {
err = store_posmap_block(svol, lsi/SFLITE_PSIS_PER_BLOCK);
if (err)
return err;
}
}
return 0;
}
/**
* Load the volume's position map from the disk. If some conflicts are present
* (i.e. an LSI is mapped to a PSI that's already taken), then resolve them
* (i.e. re-sample a free PSI for the "unlucky" LSI) and sync back to disk.
*
* MUTEX: no need for the caller to hold @svol->posmap_lock (we are in ctor).
* MUTEX: takes @sdev->slices_lock.
*/
int sflite_load_and_sanitise_posmap(struct sflite_volume *svol)
{
int err;
struct sflite_device *sdev = svol->sdev;
/* Read raw posmap from disk */
err = read_encrypted_posmap(svol);
if (err)
return err;
/* Decrypt in place */
err = sflite_crypt_blocks_vm(svol->tfm, svol->posmap, svol->posmap,
svol->sdev->posmap_size_sectors >> SFLITE_BLOCK_SHIFT,
SFLITE_POSMAP_START_SECTOR(svol) >> SFLITE_BLOCK_SHIFT,
READ);
if (err)
return err;
/* Deserialise and sanitise as you go */
if (mutex_lock_interruptible(&sdev->slices_lock))
return -ERESTARTSYS;
err = _deserialise_and_sanitise_posmap(svol);
mutex_unlock(&sdev->slices_lock);
if (err)
return err;
// print_hex_dump(KERN_CRIT, "posmap(REV) ", DUMP_PREFIX_OFFSET, 32, 4, svol->posmap, 4*sdev->tot_slices, false);
// msleep(2000);
return 0;
}

168
dm-sflc/src/lite/read.c Normal file
View file

@ -0,0 +1,168 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
#include "sflc_lite.h"
#include <linux/delay.h>
static void sflite_read_endio(struct bio *phys_bio);
static void sflite_decrypt_work_fn(struct work_struct *work);
/* Landing here from ->map() through the io_queue */
void sflite_read_work_fn(struct work_struct *work)
{
struct sflite_io *sio = container_of(work, struct sflite_io, work);
struct sflite_volume *svol = sio->svol;
struct sflite_device *sdev = svol->sdev;
struct bio *orig_bio = sio->orig_bio;
struct bio *phys_bio;
u32 lsi = sio->lsi;
u32 block_offset = sio->block_offset;
u32 psi;
/* Read position map */
if (mutex_lock_interruptible(&svol->posmap_lock)) {
orig_bio->bi_status = BLK_STS_IOERR;
goto endio;
}
psi = svol->posmap[lsi];
mutex_unlock(&svol->posmap_lock);
/* If LSI is unmapped, short-circuit and return all zeros */
if (psi == SFLITE_PSI_INVALID) {
zero_fill_bio(orig_bio);
orig_bio->bi_status = BLK_STS_OK;
goto endio;
}
sio->psi = psi;
// DMWARN("READ: LSI=%u, PSI=%u, offset=%u", lsi, psi, sio->block_offset);
// msleep(100);
/* Shallow-copy the bio and submit it (different bi_endio).
We can shallow-copy because we don't need to own the pages,
we can decrypt in place. */
//DMWARN("READ: shallow copying");
//msleep(500);
/* Shallow copy */
phys_bio = bio_alloc_clone(svol->dm_dev->bdev, orig_bio, GFP_NOIO, &sdev->bioset);
if (!phys_bio) {
DMERR("Could not clone original bio");
orig_bio->bi_status = BLK_STS_IOERR;
goto endio;
}
/* Insert in the I/O struct */
sio->phys_bio = phys_bio;
// DMWARN("READ: submitting bio");
// msleep(500);
/* Remap sector */
phys_bio->bi_iter.bi_sector = SFLITE_PHYS_BIO_SECTOR(sdev, psi, block_offset);
/* Set fields for the endio */
phys_bio->bi_private = sio;
phys_bio->bi_end_io = sflite_read_endio;
/* Submit */
dm_submit_bio_remap(orig_bio, phys_bio);
return;
endio:
bio_endio(orig_bio);
return;
}
/* ISR for the phys_bio */
static void sflite_read_endio(struct bio *phys_bio)
{
struct sflite_io *sio = phys_bio->bi_private;
// DMWARN("READ ENDIO: queueing decryption");
// //msleep(500);
/* Can't decrypt here in ISR: submit to decryption workqueue.
* Can reuse the same work item, though, since it was popped out of the
* io_queue already */
INIT_WORK(&sio->work, sflite_decrypt_work_fn);
queue_work(sio->svol->sdev->crypt_queue, &sio->work);
}
/* Decrypt and endio */
static void sflite_decrypt_work_fn(struct work_struct *work)
{
struct sflite_io *sio = container_of(work, struct sflite_io, work);
struct sflite_volume *svol = sio->svol;
struct bio *orig_bio = sio->orig_bio;
struct bio *phys_bio = sio->phys_bio;
struct bio_vec bvl = bio_iovec(orig_bio);
int err;
/* If physical bio failed, then fail-fast */
if (phys_bio->bi_status != BLK_STS_OK) {
orig_bio->bi_status = phys_bio->bi_status;
goto endio;
}
// DMWARN("DECRYPT FN: decrypting page in place");
// msleep(2000);
/* Decrypt page in-place */
err = sflite_crypt_block_page(svol->tfm, bvl.bv_page, bvl.bv_page,
SFLITE_PHYS_BIO_SECTOR(svol->sdev, sio->psi, sio->block_offset) >> SFLITE_BLOCK_SHIFT,
READ);
if (err) {
DMERR("Could not decrypt bio; error %d", err);
orig_bio->bi_status = BLK_STS_IOERR;
goto endio;
}
// print_hex_dump(KERN_WARNING, "readpage ", DUMP_PREFIX_OFFSET, 32, 1, bvl.bv_page, SFLITE_BLOCK_SIZE, true);
// msleep(2000);
// DMWARN("DECRYPT FN: bio_advance");
// msleep(300);
/* Advance original bio by one block */
bio_advance(orig_bio, SFLITE_BLOCK_SIZE);
orig_bio->bi_status = BLK_STS_OK;
endio:
/* Free the physical bio */
// DMWARN("DECRYPT FN: bio_put");
// msleep(300);
bio_put(phys_bio);
/* End original bio */
// DMWARN("DECRYPT FN: bio_endio\n\n\n\n");
// msleep(300);
bio_endio(orig_bio);
return;
}

View file

@ -0,0 +1,161 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
#include <linux/module.h>
#include <linux/device-mapper.h>
#include <linux/vmalloc.h>
#include "sflite_constants.h"
#include "sflc_lite.h"
// Only to import the definition of struct sflc_volume
#include "sflc.h"
#include <linux/delay.h>
/*
*----------------------------
* Device mapper target
*----------------------------
*/
static int sflite_map(struct dm_target *ti, struct bio *bio)
{
struct sflite_io *sio = dm_per_bio_data(bio, sizeof(struct sflite_io));
struct sflc_volume *top_vol = ti->private;
struct sflite_volume *svol = top_vol->sflite_vol;
sector_t lblk_num = bio->bi_iter.bi_sector >> SFLITE_BLOCK_SHIFT;
if (unlikely(!bio_has_data(bio))) {
// DMWARN("No-data bio: bio_op() = %d, bi_opf = %u, bi_io_vec = %p, bi_idx = %u", bio_op(bio), bio->bi_opf, bio->bi_io_vec, bio->bi_iter.bi_idx);
// msleep(100);
}
/* Flush requests are just passed down, since our position map is
* currently write-through, so we have no volatile cache */
if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
/* Has to be empty though */
if (bio_sectors(bio)) {
DMWARN("Non-empty flush request!");
msleep(3000);
return DM_MAPIO_KILL;
}
// DMWARN("REQ_PREFLUSH empty (phew), sector: %llu", bio->bi_iter.bi_sector);
// msleep(100);
bio_set_dev(bio, svol->dm_dev->bdev);
return DM_MAPIO_REMAPPED;
}
/* Accept one block at a time TODO improve */
if (unlikely(bio->bi_iter.bi_size > SFLITE_BLOCK_SIZE)) {
DMWARN("Big bio: %u", bio->bi_iter.bi_size);
msleep(300);
dm_accept_partial_bio(bio, SFLITE_BLOCK_SCALE);
}
/* Only one segment, single page, starting at 0 TODO improve */
if (unlikely(bio_segments(bio) > 1 ||
bio_offset(bio) != 0)) {
DMWARN("Unaligned bio!");
msleep(3000);
return DM_MAPIO_KILL;
}
if (unlikely(bio->bi_iter.bi_size != SFLITE_BLOCK_SIZE)) {
DMWARN("Wrong bio size: %u", bio->bi_iter.bi_size);
msleep(3000);
return DM_MAPIO_KILL;
}
/* Init I/O struct */
sio->svol = svol;
sio->orig_bio = bio;
sio->lsi = lblk_num >> SFLITE_SLICE_SHIFT;
sio->block_offset = lblk_num & ((1U << SFLITE_SLICE_SHIFT) - 1);
/* Enqueue */
if (bio_data_dir(bio) == READ)
INIT_WORK(&sio->work, sflite_read_work_fn);
else
INIT_WORK(&sio->work, sflite_write_work_fn);
queue_work(svol->sdev->io_queue, &sio->work);
return DM_MAPIO_SUBMITTED;
}
static void sflite_io_hints(struct dm_target *ti, struct queue_limits *limits)
{
// Currently, we only handle one block at a time TODO improve
limits->logical_block_size = SFLITE_BLOCK_SIZE;
limits->physical_block_size = SFLITE_BLOCK_SIZE;
limits->io_min = SFLITE_BLOCK_SIZE;
limits->io_opt = SFLITE_BLOCK_SIZE;
return;
}
static int sflite_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data)
{
struct sflc_volume *top_vol = ti->private;
struct sflite_volume *svol = top_vol->sflite_vol;
struct sflite_device *sdev = svol->sdev;
if (!fn) {
dump_stack();
msleep(2000);
return -EINVAL;
}
return fn(ti, svol->dm_dev, 0, sdev->dev_header_size_sectors + ti->len, data);
}
struct target_type sflite_target_type = {
.map = sflite_map,
.io_hints = sflite_io_hints,
.iterate_devices = sflite_iterate_devices,
};
/*
*----------------------------
* Init and exit
*----------------------------
*/
int sflite_init(void)
{
/* For the moment, we assume PAGE_SIZE == SFLITE_BLOCK_SIZE TODO improve */
if (SFLITE_BLOCK_SIZE != PAGE_SIZE) {
DMERR("Error, PAGE_SIZE != %d bytes not yet supported", SFLITE_BLOCK_SIZE);
return -ENOTRECOVERABLE;
}
return 0;
}
void sflite_exit(void)
{
return;
}

View file

@ -0,0 +1,182 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
#ifndef _SFLITE_SFLITE_H
#define _SFLITE_SFLITE_H
#include <linux/device-mapper.h>
#include <linux/dm-io.h>
#include <linux/sysfs.h>
#include <crypto/skcipher.h>
#include "sflite_constants.h"
#include "sflc_constants.h"
/*
*----------------------------
* Structs
*----------------------------
*/
struct sflite_device
{
/* Shufflecake-unique device ID */
u32 dev_id;
/* <MAJOR>:<MINOR> */
char name[16];
/* Logical size of each volume */
u32 tot_slices;
/* Header sizes in 512-byte sectors */
sector_t posmap_size_sectors;
sector_t dev_header_size_sectors;
/* Shuffled array of PSIs */
struct mutex slices_lock;
u32 *prmslices;
u32 prmslices_octr;
bool *slices_ofld;
u32 nr_free_slices;
/* Parent sysfs directory */
struct kobject *kobj_parent;
/* Resource sharing */
struct bio_set bioset;
struct dm_io_client *io_client;
struct workqueue_struct *io_queue;
struct workqueue_struct *crypt_queue;
};
struct sflite_volume
{
/* Backing device */
struct sflite_device *sdev;
/* Underlying block device. This can't go in the sflite_device struct,
* because each ti grabs its own reference. */
struct dm_dev *dm_dev;
struct dm_target *ti;
/* Volume index within the device */
u32 vol_idx;
/* Volume name: sflite_<devID>_<volIdx> */
char name[32];
/* Position map */
struct mutex posmap_lock;
u32 *posmap;
u32 nr_mapped_slices;
/* Parent sysfs directory */
struct kobject *kobj_parent;
/* Crypto */
u8 enckey[SFLITE_XTS_KEYLEN];
struct crypto_skcipher *tfm;
};
struct sflite_io
{
struct sflite_volume *svol;
struct bio *orig_bio;
struct bio *phys_bio;
u32 lsi;
u32 block_offset;
u32 psi;
struct work_struct work;
};
/*
*----------------------------
* Macros
*----------------------------
*/
/* Starting sector of position map */
#define SFLITE_POSMAP_START_SECTOR(svol) \
(SFLITE_BLOCK_SCALE * (1 + SFLITE_DEV_MAX_VOLUMES) + \
(svol)->vol_idx * (svol)->sdev->posmap_size_sectors)
/* Physical sector of a remapped bio */
#define SFLITE_PHYS_BIO_SECTOR(sdev, psi, off) ( \
(sdev)->dev_header_size_sectors + ( \
((psi << SFLITE_SLICE_SHIFT) + off) << SFLITE_BLOCK_SHIFT \
) \
)
/*
*----------------------------
* Public variables
*----------------------------
*/
extern struct target_type sflite_target_type;
/*
*----------------------------
* Functions
*----------------------------
*/
/* Init and exit */
int sflite_init(void);
void sflite_exit(void);
/* Device */
struct sflite_device *sflite_dev_create(struct dm_target *ti, int argc, char **argv, struct kobject *kobj);
void sflite_dev_destroy(struct sflite_device *sdev);
/* Volume */
struct sflite_volume *sflite_vol_create(struct dm_target *ti, struct sflite_device *sdev,
int argc, char **argv, struct kobject *kobj);
void sflite_vol_destroy(struct sflite_volume *svol);
/* Sysfs */
int sflite_sysfs_add_device(struct sflite_device *sdev);
void sflite_sysfs_remove_device(struct sflite_device *sdev);
int sflite_sysfs_add_volume(struct sflite_volume *svol);
void sflite_sysfs_remove_volume(struct sflite_volume *svol);
/* Bio mapping */
void sflite_read_work_fn(struct work_struct *work);
void sflite_write_work_fn(struct work_struct *work);
/* Position map */
int sflite_load_and_sanitise_posmap(struct sflite_volume *svol);
int sflite_create_persistent_slice_mapping(struct sflite_volume *svol, u32 lsi, u32 *psi);
/* Crypto */
int sflite_crypt_blocks_vm(struct crypto_skcipher *tfm, void *src_buf, void *dst_buf,
u64 num_blocks, u64 first_pblk_num, int rw);
int sflite_crypt_block_page(struct crypto_skcipher *tfm, struct page *src_page,
struct page *dst_page, u64 pblk_num, int rw);
#endif /* _SFLITE_SFLITE_H */

View file

@ -0,0 +1,53 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
/* Constants specific to Shufflecake Lite */
#ifndef _SFLITE_SFLITE_CONSTANTS_H_
#define _SFLITE_SFLITE_CONSTANTS_H_
#define SFLITE_BLOCK_SIZE 4096 /* bytes */
#define SFLITE_BLOCK_SHIFT 3
#define SFLITE_BLOCK_SCALE (1 << SFLITE_BLOCK_SHIFT) /* 8 sectors in a block */
#define SFLITE_SLICE_SHIFT 8
#define SFLITE_SLICE_SCALE (1 << SFLITE_SLICE_SHIFT) /* 256 blocks in a slice */
/* XTS requires doubling the key size */
#define SFLITE_XTS_KEYLEN 64 /* bytes */
/* The IV is the right-0-padded LE physical block number */
#define SFLITE_XTS_IVLEN 16 /* bytes */
#define SFLITE_DEV_MAX_VOLUMES 15
#define SFLITE_MAX_DEVS 1024
#define SFLITE_PSI_INVALID 0xFFFFFFFF
/* PosMap entries are 4 bytes, therefore there are 1024 of them in a block */
#define SFLITE_PSIS_PER_BLOCK 1024
#endif /* _SFLITE_SFLITE_CONSTANTS_H_ */

116
dm-sflc/src/lite/sysfs.c Normal file
View file

@ -0,0 +1,116 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
#include "sflc_lite.h"
// Only to import the definitions of structs sflc_volume and sflc_device
#include "sflc.h"
/*
*----------------------------
* Device entries
*----------------------------
*/
static ssize_t tot_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf)
{
struct sflc_device *top_dev = container_of(kobj, struct sflc_device, kobj);
struct sflite_device *sdev = top_dev->sflite_dev;
return sysfs_emit(buf, "%u\n", sdev->tot_slices);
}
static ssize_t free_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf)
{
struct sflc_device *top_dev = container_of(kobj, struct sflc_device, kobj);
struct sflite_device *sdev = top_dev->sflite_dev;
int ret;
if (mutex_lock_interruptible(&sdev->slices_lock))
return -ERESTARTSYS;
ret = sysfs_emit(buf, "%u\n", sdev->nr_free_slices);
mutex_unlock(&sdev->slices_lock);
return ret;
}
static struct kobj_attribute tot_slices_kattr = __ATTR_RO(tot_slices);
static struct kobj_attribute free_slices_kattr = __ATTR_RO(free_slices);
static struct attribute *sflite_device_attrs[] = {
&tot_slices_kattr.attr,
&free_slices_kattr.attr,
NULL
};
static const struct attribute_group sflite_device_attr_group = {
.attrs = sflite_device_attrs,
};
int sflite_sysfs_add_device(struct sflite_device *sdev)
{
return sysfs_create_group(sdev->kobj_parent, &sflite_device_attr_group);
}
void sflite_sysfs_remove_device(struct sflite_device *sdev)
{
sysfs_remove_group(sdev->kobj_parent, &sflite_device_attr_group);
}
/*
*----------------------------
* Volume entries
*----------------------------
*/
static ssize_t mapped_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf)
{
struct sflc_volume *top_vol = container_of(kobj, struct sflc_volume, kobj);
struct sflite_volume *svol = top_vol->sflite_vol;
int ret;
if (mutex_lock_interruptible(&svol->posmap_lock))
return -ERESTARTSYS;
ret = sysfs_emit(buf, "%u\n", svol->nr_mapped_slices);
mutex_unlock(&svol->posmap_lock);
return ret;
}
static struct kobj_attribute mapped_slices_kattr = __ATTR_RO(mapped_slices);
static struct attribute *sflite_volume_attrs[] = {
&mapped_slices_kattr.attr,
NULL
};
static const struct attribute_group sflite_volume_attr_group = {
.attrs = sflite_volume_attrs,
};
int sflite_sysfs_add_volume(struct sflite_volume *svol)
{
return sysfs_create_group(svol->kobj_parent, &sflite_volume_attr_group);
}
void sflite_sysfs_remove_volume(struct sflite_volume *svol)
{
sysfs_remove_group(svol->kobj_parent, &sflite_volume_attr_group);
}

163
dm-sflc/src/lite/volume.c Normal file
View file

@ -0,0 +1,163 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
#include <linux/vmalloc.h>
#include "sflc_lite.h"
/**
* Arguments:
* argv[0]: Shufflecake mode: legacy/lite
* argv[1]: Shufflecake-unique device ID
* argv[2]: path to underlying physical device
* argv[3]: volume index within the device
* argv[4]: number of 1 MB slices in the underlying device
* argv[5]: 64-byte encryption key (hex-encoded)
*/
struct sflite_volume *sflite_vol_create(struct dm_target *ti, struct sflite_device* sdev,
int argc, char **argv, struct kobject *kobj)
{
struct sflite_volume *svol;
u32 vol_idx;
int err;
svol = kzalloc(sizeof(*svol), GFP_KERNEL);
if (!svol) {
DMERR("Could not allocate volume");
return ERR_PTR(-ENOMEM);
}
/* Parse arguments */
if (argc != 6) {
DMERR("Wrong argument count");
err = -EINVAL;
goto bad_parse;
}
if (sscanf(argv[3], "%u", &vol_idx) != 1) {
DMERR("Could not decode tot_slices\n");
err = -EINVAL;
goto bad_parse;
}
/* Decode the encryption key */
if (strlen(argv[5]) != 2 * SFLITE_XTS_KEYLEN) {
DMERR("Invalid key length");
err = -EINVAL;
goto bad_parse;
}
err = hex2bin(svol->enckey, argv[5], SFLITE_XTS_KEYLEN);
if (err) {
DMERR("Could not decode hexadecimal encryption key");
err = -EINVAL;
goto bad_parse;
}
svol->sdev = sdev;
svol->vol_idx = vol_idx;
sprintf(svol->name, "sflc_%u_%u", sdev->dev_id, vol_idx);
svol->ti = ti;
err = dm_get_device(ti, sdev->name,
dm_table_get_mode(ti->table), &svol->dm_dev);
if (err) {
ti->error = "Device lookup failed";
goto bad_dm_dev;
}
/* Crypto */
svol->tfm = crypto_alloc_skcipher("xts(aes)", 0, 0);
if (IS_ERR(svol->tfm)) {
err = PTR_ERR(svol->tfm);
DMERR("Could not allocate AES-XTS cipher handle; error %d", err);
goto bad_tfm_alloc;
}
err = crypto_skcipher_setkey(svol->tfm, svol->enckey, SFLITE_XTS_KEYLEN);
if (err) {
DMERR("Could not set key in crypto transform; error %d", err);
goto bad_tfm_setkey;
}
/* Position map */
mutex_init(&svol->posmap_lock);
/* Slight over-allocation, to fit a whole number of blocks */
svol->posmap = vmalloc(sdev->posmap_size_sectors * SECTOR_SIZE);
if (!svol->posmap) {
DMERR("Could not allocate position map");
err = -ENOMEM;
goto bad_posmap_alloc;
}
svol->nr_mapped_slices = 0;
/* Load from disk */
err = sflite_load_and_sanitise_posmap(svol);
if (err) {
DMERR("Could not load position map from disk; error %d", err);
goto bad_posmap_load;
}
/* Add to sysfs, once initialised */
svol->kobj_parent = kobj;
err = sflite_sysfs_add_volume(svol);
if (err) {
DMERR("Could not register volume with sysfs; error %d", err);
goto bad_sysfs;
}
/* Only accept one block per request for simplicity TODO: improve to one slice*/
ti->max_io_len = SFLITE_BLOCK_SCALE;
ti->flush_supported = true;
ti->num_flush_bios = 1;
ti->discards_supported = false;
ti->num_discard_bios = 0;
ti->num_secure_erase_bios = 0;
ti->num_write_zeroes_bios = 0;
ti->accounts_remapped_io = true;
ti->per_io_data_size = sizeof(struct sflite_io);
ti->private = svol;
return svol;
bad_sysfs:
bad_posmap_load:
vfree(svol->posmap);
bad_posmap_alloc:
bad_tfm_setkey:
crypto_free_skcipher(svol->tfm);
bad_tfm_alloc:
dm_put_device(ti, svol->dm_dev);
bad_dm_dev:
bad_parse:
kfree(svol);
return ERR_PTR(err);
}
void sflite_vol_destroy(struct sflite_volume *svol)
{
sflite_sysfs_remove_volume(svol);
vfree(svol->posmap);
crypto_free_skcipher(svol->tfm);
dm_put_device(svol->ti, svol->dm_dev);
kfree(svol);
return;
}

148
dm-sflc/src/lite/write.c Normal file
View file

@ -0,0 +1,148 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
#include "sflc_lite.h"
#include <linux/delay.h>
static void sflite_write_endio(struct bio *phys_bio);
void sflite_write_work_fn(struct work_struct *work)
{
struct sflite_io *sio = container_of(work, struct sflite_io, work);
struct sflite_volume *svol = sio->svol;
struct sflite_device *sdev = svol->sdev;
struct bio *orig_bio = sio->orig_bio;
struct bio_vec bvl = bio_iovec(orig_bio);
struct bio *phys_bio;
struct page *page;
u32 lsi = sio->lsi;
u32 block_offset = sio->block_offset;
u32 psi;
int err;
// DMWARN("WRITE: dequeued. Sector = %llu", orig_bio->bi_iter.bi_sector);
// msleep(100);
/* Read existing mapping, or create new one */
if (mutex_lock_interruptible(&svol->posmap_lock)) {
orig_bio->bi_status = BLK_STS_IOERR;
goto endio;
}
psi = svol->posmap[lsi];
/* If LSI unmapped, create new mapping, while holding the lock */
if (psi == SFLITE_PSI_INVALID) {
// DMWARN("WRITE: unmapped LSI %u, sampling PSI", lsi);
// msleep(100);
err = sflite_create_persistent_slice_mapping(svol, lsi, &psi);
if (err){
DMERR("Could not create slice mapping; error %d", err);
mutex_unlock(&svol->posmap_lock);
orig_bio->bi_status = BLK_STS_IOERR;
goto endio;
}
// DMWARN("WRITE: sampled PSI %u for LSI %u", psi, lsi);
// msleep(100);
}
mutex_unlock(&svol->posmap_lock);
sio->psi = psi;
/* Allocate physical bio */
phys_bio = bio_alloc_bioset(svol->dm_dev->bdev, 1, orig_bio->bi_opf,
GFP_NOIO, &sdev->bioset);
if (!phys_bio) {
DMERR("Could not allocate physical bio");
orig_bio->bi_status = BLK_STS_IOERR;
goto endio;
}
/* Insert in the I/O struct */
sio->phys_bio = phys_bio;
/* Physical bio needs its own page */
page = alloc_pages(GFP_NOIO, 0);
if (!page) {
DMERR("Could not allocate page for physical bio");
orig_bio->bi_status = BLK_STS_IOERR;
goto bad_alloc_page;
}
/* Remap sector */
phys_bio->bi_iter.bi_sector = SFLITE_PHYS_BIO_SECTOR(sdev, psi, block_offset);
/* Encrypt */
err = sflite_crypt_block_page(svol->tfm, bvl.bv_page, page,
phys_bio->bi_iter.bi_sector >> SFLITE_BLOCK_SHIFT, WRITE);
if (err) {
DMERR("Could not encrypt bio; error %d", err);
orig_bio->bi_status = BLK_STS_IOERR;
goto bad_encrypt;
}
/* Add page to bio */
__bio_add_page(phys_bio, page, SFLITE_BLOCK_SIZE, 0);
/* Set fields for the endio */
phys_bio->bi_private = sio;
phys_bio->bi_end_io = sflite_write_endio;
/* Submit */
dm_submit_bio_remap(orig_bio, phys_bio);
return;
bad_encrypt:
__free_page(page);
bad_alloc_page:
bio_put(phys_bio);
endio:
bio_endio(orig_bio);
return;
}
static void sflite_write_endio(struct bio *phys_bio)
{
struct sflite_io *sio = phys_bio->bi_private;
struct bio *orig_bio = sio->orig_bio;
/* If physical bio failed, then fail-fast */
if (phys_bio->bi_status != BLK_STS_OK) {
orig_bio->bi_status = phys_bio->bi_status;
DMWARN("WRITE ENDIO: phys_bio failed");
goto endio;
}
/* Advance original bio by one block */
bio_advance(orig_bio, SFLITE_BLOCK_SIZE);
orig_bio->bi_status = BLK_STS_OK;
endio:
/* Free the physical bio and its page */
bio_free_pages(phys_bio);
bio_put(phys_bio);
/* End original bio */
bio_endio(orig_bio);
return;
}

View file

@ -28,55 +28,55 @@
#include <crypto/rng.h>
#include <linux/random.h>
#include "rand.h"
#include "log/log.h"
#include "old/crypto/rand/rand.h"
#include "old/log/log.h"
/*****************************************************
* CONSTANTS *
*****************************************************/
#define SFLC_RAND_RNG_NAME "drbg_nopr_sha256"
#define SFOLD_RAND_RNG_NAME "drbg_nopr_sha256"
/*****************************************************
* PRIVATE VARIABLES *
*****************************************************/
static struct mutex sflc_rand_tfm_lock;
static struct crypto_rng * sflc_rand_tfm = NULL;
static struct mutex sfold_rand_tfm_lock;
static struct crypto_rng * sfold_rand_tfm = NULL;
/*****************************************************
* PRIVATE FUNCTIONS PROTOTYPES *
*****************************************************/
/* Flexible to accommodate for both required and non-required reseeding */
static int sflc_rand_reseed(void);
static int sfold_rand_reseed(void);
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
/* Init the submodule */
int sflc_rand_init(void)
int sfold_rand_init(void)
{
int err;
/* Init the lock governing the SFLC RNG */
mutex_init(&sflc_rand_tfm_lock);
mutex_init(&sfold_rand_tfm_lock);
/* Allocate module-wide RNG */
sflc_rand_tfm = crypto_alloc_rng(SFLC_RAND_RNG_NAME, CRYPTO_ALG_TYPE_RNG, 0);
if (IS_ERR(sflc_rand_tfm)) {
err = PTR_ERR(sflc_rand_tfm);
sflc_rand_tfm = NULL;
pr_err("Could not allocate RNG %s; error %d\n", SFLC_RAND_RNG_NAME, err);
sfold_rand_tfm = crypto_alloc_rng(SFOLD_RAND_RNG_NAME, CRYPTO_ALG_TYPE_RNG, 0);
if (IS_ERR(sfold_rand_tfm)) {
err = PTR_ERR(sfold_rand_tfm);
sfold_rand_tfm = NULL;
pr_err("Could not allocate RNG %s; error %d\n", SFOLD_RAND_RNG_NAME, err);
return err;
}
/* The new RNG comes not seeded, right? */
err = sflc_rand_reseed();
err = sfold_rand_reseed();
if (err) {
pr_err("Could not seed the RNG; error %d\n", err);
sflc_rand_exit();
sfold_rand_exit();
return err;
}
@ -84,26 +84,26 @@ int sflc_rand_init(void)
}
/* Get random bytes. Might sleep for re-seeding (not implemented yet), or for contention (mutex). */
int sflc_rand_getBytes(u8 * buf, unsigned count)
int sfold_rand_getBytes(u8 * buf, unsigned count)
{
int ret;
/* Acquire lock */
if (mutex_lock_interruptible(&sflc_rand_tfm_lock)) {
if (mutex_lock_interruptible(&sfold_rand_tfm_lock)) {
pr_err("Got error while waiting for SFLC RNG\n");
return -EINTR;
}
ret = crypto_rng_get_bytes(sflc_rand_tfm, buf, count);
ret = crypto_rng_get_bytes(sfold_rand_tfm, buf, count);
/* End of critical region */
mutex_unlock(&sflc_rand_tfm_lock);
mutex_unlock(&sfold_rand_tfm_lock);
return ret;
}
/* Get a random s32 from 0 (inclusive) to max (exclusive). Returns < 0 if error. */
s32 sflc_rand_uniform(s32 max)
s32 sfold_rand_uniform(s32 max)
{
s32 rand;
s32 thresh;
@ -120,7 +120,7 @@ s32 sflc_rand_uniform(s32 max)
thresh = S32_MAX - (S32_MAX % max);
do {
/* Sample a random signed integer, then make it positive */
int err = sflc_rand_getBytes((void *) &rand, sizeof(rand));
int err = sfold_rand_getBytes((void *) &rand, sizeof(rand));
/* Can't make it positive if it's all 1's */
if (rand == S32_MIN) {
continue;
@ -140,11 +140,11 @@ s32 sflc_rand_uniform(s32 max)
}
/* Tear down the submodule */
void sflc_rand_exit(void)
void sfold_rand_exit(void)
{
if (sflc_rand_tfm) {
crypto_free_rng(sflc_rand_tfm);
sflc_rand_tfm = NULL;
if (sfold_rand_tfm) {
crypto_free_rng(sfold_rand_tfm);
sfold_rand_tfm = NULL;
}
return;
@ -155,12 +155,12 @@ void sflc_rand_exit(void)
*****************************************************/
/* Flexible to accommodate for both required and non-required reseeding */
static int sflc_rand_reseed(void)
static int sfold_rand_reseed(void)
{
int err;
/* Reseed the RNG */
err = crypto_rng_reset(sflc_rand_tfm, NULL, crypto_rng_seedsize(sflc_rand_tfm));
err = crypto_rng_reset(sfold_rand_tfm, NULL, crypto_rng_seedsize(sfold_rand_tfm));
if (err) {
pr_err("Could not feed seed to the RNG; error %d\n", err);
return err;

View file

@ -27,8 +27,8 @@
* no need to make it more fine grained.
*/
#ifndef _SFLC_CRYPTO_RAND_RAND_H_
#define _SFLC_CRYPTO_RAND_RAND_H_
#ifndef _SFOLD_CRYPTO_RAND_RAND_H_
#define _SFOLD_CRYPTO_RAND_RAND_H_
/*****************************************************
* INCLUDE SECTION *
@ -40,20 +40,17 @@
* PUBLIC FUNCTIONS PROTOTYPES *
*****************************************************/
/* Selftest to see (by eye :D) if generated bytes are actually random */
int sflc_rand_selftest(void);
/* Init the submodule */
int sflc_rand_init(void);
int sfold_rand_init(void);
/* Get random bytes. Might sleep for re-seeding (not implemented yet), or for contention (mutex). */
int sflc_rand_getBytes(u8 * buf, unsigned count);
int sfold_rand_getBytes(u8 * buf, unsigned count);
/* Get a random s32 from 0 (inclusive) to max (exclusive). Returns < 0 if error. */
s32 sflc_rand_uniform(s32 max);
s32 sfold_rand_uniform(s32 max);
/* Tear down the submodule */
void sflc_rand_exit(void);
void sfold_rand_exit(void);
#endif /* _SFLC_CRYPTO_RAND_RAND_H_ */
#endif /* _SFOLD_CRYPTO_RAND_RAND_H_ */

View file

@ -25,8 +25,8 @@
* INCLUDE SECTION *
*****************************************************/
#include "skreq_pool.h"
#include "log/log.h"
#include "old/crypto/symkey/skreq_pool.h"
#include "old/log/log.h"
/*****************************************************
* CONSTANTS *
@ -37,17 +37,17 @@
*****************************************************/
/* A mempool_alloc_t using skcipher_request_alloc as backend */
static void * sflc_sk_allocRequest(gfp_t gfp_mask, void * pool_data);
static void * sfold_sk_allocRequest(gfp_t gfp_mask, void * pool_data);
/* A mempool_free_t using skcipher_request_free as backend */
static void sflc_sk_freeRequest(void * element, void * pool_data);
static void sfold_sk_freeRequest(void * element, void * pool_data);
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
mempool_t * sflc_sk_createReqPool(int min_nr, sflc_sk_Context * ctx)
mempool_t * sfold_sk_createReqPool(int min_nr, sfold_sk_Context * ctx)
{
return mempool_create(min_nr, sflc_sk_allocRequest, sflc_sk_freeRequest, (void *) ctx);
return mempool_create(min_nr, sfold_sk_allocRequest, sfold_sk_freeRequest, (void *) ctx);
}
/*****************************************************
@ -55,9 +55,9 @@ mempool_t * sflc_sk_createReqPool(int min_nr, sflc_sk_Context * ctx)
*****************************************************/
/* A mempool_alloc_t using skcipher_request_alloc as backend */
static void * sflc_sk_allocRequest(gfp_t gfp_mask, void * pool_data)
static void * sfold_sk_allocRequest(gfp_t gfp_mask, void * pool_data)
{
sflc_sk_Context * ctx = pool_data;
sfold_sk_Context * ctx = pool_data;
struct skcipher_request * skreq;
skreq = skcipher_request_alloc(ctx->tfm, gfp_mask);
@ -70,7 +70,7 @@ static void * sflc_sk_allocRequest(gfp_t gfp_mask, void * pool_data)
}
/* A mempool_free_t using skcipher_request_free as backend */
static void sflc_sk_freeRequest(void * element, void * pool_data)
static void sfold_sk_freeRequest(void * element, void * pool_data)
{
struct skcipher_request * skreq = element;

View file

@ -26,8 +26,8 @@
* functions to the mempool interface.
*/
#ifndef _SFLC_CRYPTO_SYMKEY_SKREQ_POOL_H_
#define _SFLC_CRYPTO_SYMKEY_SKREQ_POOL_H_
#ifndef _SFOLD_CRYPTO_SYMKEY_SKREQ_POOL_H_
#define _SFOLD_CRYPTO_SYMKEY_SKREQ_POOL_H_
/*****************************************************
* INCLUDE SECTION *
@ -35,7 +35,7 @@
#include <linux/mempool.h>
#include "symkey.h"
#include "old/crypto/symkey/symkey.h"
/*****************************************************
* CONSTANTS *
@ -49,7 +49,7 @@
* PUBLIC FUNCTIONS PROTOTYPES *
*****************************************************/
mempool_t * sflc_sk_createReqPool(int min_nr, sflc_sk_Context * ctx);
mempool_t * sfold_sk_createReqPool(int min_nr, sfold_sk_Context * ctx);
#endif /* _SFLC_CRYPTO_SYMKEY_SKREQ_POOL_H_ */
#endif /* _SFOLD_CRYPTO_SYMKEY_SKREQ_POOL_H_ */

View file

@ -27,66 +27,66 @@
#include <linux/scatterlist.h>
#include "symkey.h"
#include "skreq_pool.h"
#include "log/log.h"
#include "old/crypto/symkey/symkey.h"
#include "old/crypto/symkey/skreq_pool.h"
#include "old/log/log.h"
/*****************************************************
* CONSTANTS *
*****************************************************/
#define SFLC_SK_REQ_POOL_SIZE 1024
#define SFOLD_SK_REQ_POOL_SIZE 1024
#define SFLC_SK_ENCRYPT 0
#define SFLC_SK_DECRYPT 1
#define SFOLD_SK_ENCRYPT 0
#define SFOLD_SK_DECRYPT 1
/*****************************************************
* PRIVATE FUNCTIONS PROTOTYPES *
*****************************************************/
static int sflc_sk_encdec(sflc_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv, int op);
static int sfold_sk_encdec(sfold_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv, int op);
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
/* Create a new context with the given key. Returns an ERR_PTR() on failure. */
sflc_sk_Context * sflc_sk_createContext(u8 * key)
sfold_sk_Context * sfold_sk_createContext(u8 * key)
{
sflc_sk_Context * ctx;
sfold_sk_Context * ctx;
int err;
/* Allocate context */
ctx = kzalloc(sizeof(sflc_sk_Context), GFP_KERNEL);
ctx = kzalloc(sizeof(sfold_sk_Context), GFP_KERNEL);
if (!ctx) {
pr_err("Could not allocate %lu bytes for the sflc_sk_Context\n", sizeof(sflc_sk_Context));
pr_err("Could not allocate %lu bytes for the sfold_sk_Context\n", sizeof(sfold_sk_Context));
return ERR_PTR(-ENOMEM);
}
/* Allocate crypto transform */
ctx->tfm = crypto_alloc_skcipher(SFLC_SK_CIPHER_NAME, CRYPTO_ALG_ASYNC, 0);
ctx->tfm = crypto_alloc_skcipher(SFOLD_SK_CIPHER_NAME, CRYPTO_ALG_ASYNC, 0);
if (IS_ERR(ctx->tfm)) {
err = PTR_ERR(ctx->tfm);
ctx->tfm = NULL;
pr_err("Could not allocate skcipher handle: error %d\n", err);
sflc_sk_destroyContext(ctx);
sfold_sk_destroyContext(ctx);
return ERR_PTR(err);
}
/* Copy and set key */
memcpy(ctx->key, key, SFLC_SK_KEY_LEN);
err = crypto_skcipher_setkey(ctx->tfm, ctx->key, SFLC_SK_KEY_LEN);
memcpy(ctx->key, key, SFOLD_SK_KEY_LEN);
err = crypto_skcipher_setkey(ctx->tfm, ctx->key, SFOLD_SK_KEY_LEN);
if (err) {
pr_err("Could not set key in crypto transform: error %d\n", err);
sflc_sk_destroyContext(ctx);
sfold_sk_destroyContext(ctx);
return ERR_PTR(err);
}
/* Create request memory pool */
ctx->sk_req_pool = sflc_sk_createReqPool(SFLC_SK_REQ_POOL_SIZE, ctx);
ctx->sk_req_pool = sfold_sk_createReqPool(SFOLD_SK_REQ_POOL_SIZE, ctx);
if (!ctx->sk_req_pool) {
pr_err("Could not allocate skcipher_request memory pool\n");
sflc_sk_destroyContext(ctx);
sfold_sk_destroyContext(ctx);
return ERR_PTR(-ENOMEM);
}
@ -94,7 +94,7 @@ sflc_sk_Context * sflc_sk_createContext(u8 * key)
}
/* Destroy the given context */
void sflc_sk_destroyContext(sflc_sk_Context * ctx)
void sfold_sk_destroyContext(sfold_sk_Context * ctx)
{
if (!ctx) {
return;
@ -116,21 +116,21 @@ void sflc_sk_destroyContext(sflc_sk_Context * ctx)
}
/* Encrypt synchronously. Provide src = dst for in-place operation. */
int sflc_sk_encrypt(sflc_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv)
int sfold_sk_encrypt(sfold_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv)
{
return sflc_sk_encdec(ctx, src, dst, len, iv, SFLC_SK_ENCRYPT);
return sfold_sk_encdec(ctx, src, dst, len, iv, SFOLD_SK_ENCRYPT);
}
int sflc_sk_decrypt(sflc_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv)
int sfold_sk_decrypt(sfold_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv)
{
return sflc_sk_encdec(ctx, src, dst, len, iv, SFLC_SK_DECRYPT);
return sfold_sk_encdec(ctx, src, dst, len, iv, SFOLD_SK_DECRYPT);
}
/*****************************************************
* PRIVATE FUNCTIONS DEFINITIONS *
*****************************************************/
static int sflc_sk_encdec(sflc_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv, int op)
static int sfold_sk_encdec(sfold_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv, int op)
{
struct skcipher_request * skreq;
struct scatterlist srcsg;
@ -162,7 +162,7 @@ static int sflc_sk_encdec(sflc_sk_Context * ctx, u8 * src, u8 * dst, unsigned in
crypto_req_done, &skreq_wait);
/* Do it */
if (op == SFLC_SK_ENCRYPT) {
if (op == SFOLD_SK_ENCRYPT) {
ret = crypto_skcipher_encrypt(skreq);
} else {
ret = crypto_skcipher_decrypt(skreq);

View file

@ -25,8 +25,8 @@
* A thin wrapper around the kernel's synchronous block cipher API.
*/
#ifndef _SFLC_CRYPTO_SYMKEY_SYMKEY_H_
#define _SFLC_CRYPTO_SYMKEY_SYMKEY_H_
#ifndef _SFOLD_CRYPTO_SYMKEY_SYMKEY_H_
#define _SFOLD_CRYPTO_SYMKEY_SYMKEY_H_
/*****************************************************
* INCLUDE SECTION *
@ -39,9 +39,9 @@
* CONSTANTS *
*****************************************************/
#define SFLC_SK_CIPHER_NAME "ctr(aes)"
#define SFLC_SK_KEY_LEN 32
#define SFLC_SK_IV_LEN 16
#define SFOLD_SK_CIPHER_NAME "ctr(aes)"
#define SFOLD_SK_KEY_LEN 32
#define SFOLD_SK_IV_LEN 16
/*****************************************************
* TYPES *
@ -51,34 +51,31 @@
* There is one of these Context's for each volume.
* No need for locking, methods can be called in parallel.
*/
typedef struct sflc_sk_context_s
typedef struct sfold_sk_context_s
{
/* Only one transform for now */
struct crypto_skcipher * tfm;
/* 32-byte key */
u8 key[SFLC_SK_KEY_LEN];
u8 key[SFOLD_SK_KEY_LEN];
/* Memory pool for skcipher_request's */
mempool_t * sk_req_pool;
} sflc_sk_Context;
} sfold_sk_Context;
/*****************************************************
* PUBLIC FUNCTIONS PROTOTYPES *
*****************************************************/
/* Self test using known test vectors and random inputs */
int sflc_sk_selftest(void);
/* Create a new context with the given key. Returns an ERR_PTR() on failure. */
sflc_sk_Context * sflc_sk_createContext(u8 * key);
sfold_sk_Context * sfold_sk_createContext(u8 * key);
/* Destroy the given context */
void sflc_sk_destroyContext(sflc_sk_Context * ctx);
void sfold_sk_destroyContext(sfold_sk_Context * ctx);
/* Encrypt/decrypt synchronously. Provide src = dst for in-place operation. */
int sflc_sk_encrypt(sflc_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv);
int sflc_sk_decrypt(sflc_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv);
int sfold_sk_encrypt(sfold_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv);
int sfold_sk_decrypt(sfold_sk_Context * ctx, u8 * src, u8 * dst, unsigned int len, u8 * iv);
#endif /* _SFLC_CRYPTO_SYMKEY_SYMKEY_H_ */
#endif /* _SFOLD_CRYPTO_SYMKEY_SYMKEY_H_ */

View file

@ -0,0 +1,259 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
/*
* This file only implements the device-related device management functions.
*/
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include "old/sflc_old.h"
#include "old/device/device.h"
#include "old/utils/vector.h"
#include "old/log/log.h"
#include <linux/vmalloc.h>
/*****************************************************
* CONSTANTS *
*****************************************************/
/*****************************************************
* PUBLIC VARIABLES DEFINITIONS *
*****************************************************/
/* Initialises and pre-shuffles the PSI array */
static int sfold_dev_initAndShufflePsiArray(u32 *psi_array, u32 len);
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
/**
* Creates Device. Returns an ERR_PTR() if unsuccessful.
* Arguments:
* argv[0]: Shufflecake mode: legacy/lite
* argv[1]: Shufflecake-unique device ID
* argv[2]: path to underlying physical device
* argv[3]: volume index within the device
* argv[4]: number of 1 MB slices in the underlying device
* argv[5]: 32-byte encryption key (hex-encoded)
*/
sfold_Device *sfold_dev_create(struct dm_target *ti, int argc, char **argv, struct kobject *kobj)
{
sfold_Device * dev;
u32 tot_slices;
u32 dev_id;
int err;
int i;
/* Allocate device */
dev = kzalloc(sizeof(sfold_Device), GFP_KERNEL);
if (!dev) {
pr_err("Could not allocate %lu bytes for sfold_Device\n", sizeof(sfold_Device));
err = -ENOMEM;
goto err_alloc_dev;
}
/* Parse args */
if (argc != 6) {
pr_err("Wrong argument count");
err = -EINVAL;
goto err_parse;
}
sscanf(argv[1], "%u", &dev_id);
if (sscanf(argv[4], "%u", &tot_slices) != 1) {
pr_err("Could not decode tot_slices\n");
err = -EINVAL;
goto err_parse;
}
/* Init list node here, so it's always safe to list_del() */
INIT_LIST_HEAD(&dev->list_node);
/* Set device ID */
dev->dev_id = dev_id;
/* Set backing real device */
err = dm_get_device(ti, argv[2], dm_table_get_mode(ti->table), &dev->bdev);
if (err) {
pr_err("Could not dm_get_device: error %d\n", err);
goto err_dm_get_dev;
}
dev->ti = ti;
/* And its path */
dev->bdev_path = kmalloc(strlen(argv[2]) + 1, GFP_KERNEL);
if (!dev->bdev_path) {
pr_err("Could not allocate %lu bytes for dev->real_dev_path\n", strlen(argv[2]) + 1);
err = -ENOMEM;
goto err_alloc_real_dev_path;
}
strcpy(dev->bdev_path, argv[2]);
/* Init volumes */
for (i = 0; i < SFOLD_DEV_MAX_VOLUMES; ++i) {
dev->vol[i] = NULL;
}
dev->vol_cnt = 0;
/* Set slices info */
dev->tot_slices = tot_slices;
dev->free_slices = tot_slices;
/* Compute header info (like in userland tool) */
u32 nr_pmbs_per_vol = DIV_ROUND_UP(tot_slices, SFOLD_VOL_HEADER_MAPPINGS_PER_BLOCK);
dev->vol_header_nr_iv_blocks = DIV_ROUND_UP(nr_pmbs_per_vol, SFOLD_VOL_LOG_SLICE_SIZE);
dev->vol_header_size = 1 + nr_pmbs_per_vol + dev->vol_header_nr_iv_blocks;
dev->dev_header_size = 1 + (SFOLD_DEV_MAX_VOLUMES * dev->vol_header_size);
/* Init slices lock */
mutex_init(&dev->slices_lock);
/* Allocate reverse slice map */
dev->rmap = vmalloc(dev->tot_slices * sizeof(u8));
if (!dev->rmap) {
pr_err("Could not allocate reverse slice map\n");
err = -ENOMEM;
goto err_alloc_rmap;
}
/* Initialise it */
memset(dev->rmap, SFOLD_DEV_RMAP_INVALID_VOL, dev->tot_slices * sizeof(u8));
/* Allocate PSI array */
dev->shuffled_psi_array = vmalloc(dev->tot_slices * sizeof(u32));
if (!dev->shuffled_psi_array) {
pr_err("Could not allocate PSI array\n");
err = -ENOMEM;
goto err_alloc_psi_array;
}
/* Initialise it and pre-shuffle it */
err = sfold_dev_initAndShufflePsiArray(dev->shuffled_psi_array, dev->tot_slices);
if (err) {
pr_err("Could not init-and-shuffle PSI array: error %d", err);
goto err_initshuffle_psi_array;
}
/* Init related counter */
dev->shuffled_psi_ctr = 0;
/* Init IV cache lock */
mutex_init(&dev->iv_cache_lock);
/* Init IV cache waitqueue */
init_waitqueue_head(&dev->iv_cache_waitqueue);
/* Allocate IV cache */
dev->iv_cache = kzalloc(dev->tot_slices * sizeof(sfold_dev_IvCacheEntry *), GFP_KERNEL);
if (!dev->iv_cache) {
pr_err("Could not allocate IV cache\n");
err = -ENOMEM;
goto err_alloc_iv_cache;
}
/* Set it empty */
dev->iv_cache_nr_entries = 0;
/* Init list head */
INIT_LIST_HEAD(&dev->iv_lru_list);
/* Add to sysfs */
dev->kobj_parent = kobj;
err = sfold_sysfs_add_device(dev);
if (err) {
pr_err("Could not add device to sysfs; error %d\n", err);
goto err_sysfs;
}
return dev;
err_sysfs:
kfree(dev->iv_cache);
err_alloc_iv_cache:
err_initshuffle_psi_array:
vfree(dev->shuffled_psi_array);
err_alloc_psi_array:
vfree(dev->rmap);
err_alloc_rmap:
kfree(dev->bdev_path);
err_alloc_real_dev_path:
dm_put_device(ti, dev->bdev);
err_dm_get_dev:
err_parse:
kfree(dev);
err_alloc_dev:
return ERR_PTR(err);
}
/* Returns false if still busy (not all volumes have been removed). Frees the Device. */
bool sfold_dev_destroy(sfold_Device * dev)
{
/* Check if we actually have to put this device */
if (!dev) {
return false;
}
if (dev->vol_cnt > 0) {
pr_warn("Called while still holding %d volumes\n", dev->vol_cnt);
return false;
}
/* Flush all IVs */
sfold_dev_flushIvs(dev);
/* List */
list_del(&dev->list_node);
/* Sysfs */
sfold_sysfs_remove_device(dev);
/* IV cache */
kfree(dev->iv_cache);
/* PSI array */
vfree(dev->shuffled_psi_array);
/* Reverse slice map */
vfree(dev->rmap);
/* Backing device */
dm_put_device(dev->ti, dev->bdev);
kfree(dev->bdev_path);
/* Free the device itself */
kfree(dev);
return true;
}
/* Initialises and pre-shuffles the PSI array */
static int sfold_dev_initAndShufflePsiArray(u32 *psi_array, u32 len)
{
u32 i;
/* Init to the identity map */
for (i = 0; i < len; i++) {
psi_array[i] = i;
}
/* Permute */
return sfold_vec_u32shuffle(psi_array, len);
}

View file

@ -30,8 +30,8 @@
* are stored in increasing degree of "secrecy").
*/
#ifndef _SFLC_DEVICE_DEVICE_H_
#define _SFLC_DEVICE_DEVICE_H_
#ifndef _SFOLD_DEVICE_DEVICE_H_
#define _SFOLD_DEVICE_DEVICE_H_
/*****************************************************
@ -40,8 +40,8 @@
/* Necessary since device.h, volume.h, and sysfs.h all include each other */
typedef struct sflc_device_s sflc_Device;
typedef struct sflc_dev_iv_cache_entry_s sflc_dev_IvCacheEntry;
typedef struct sfold_device_s sfold_Device;
typedef struct sfold_dev_iv_cache_entry_s sfold_dev_IvCacheEntry;
/*****************************************************
@ -49,11 +49,10 @@ typedef struct sflc_dev_iv_cache_entry_s sflc_dev_IvCacheEntry;
*****************************************************/
#include <linux/device-mapper.h>
#include <linux/dm-io.h>
#include "volume/volume.h"
#include "crypto/symkey/symkey.h"
#include "sysfs/sysfs.h"
#include "old/sflc_old.h"
#include "old/volume/volume.h"
#include "old/crypto/symkey/symkey.h"
/*****************************************************
@ -61,30 +60,30 @@ typedef struct sflc_dev_iv_cache_entry_s sflc_dev_IvCacheEntry;
*****************************************************/
/* We need 4096-byte sectors to amortise the space overhead of the IVs */
#define SFLC_DEV_SECTOR_SIZE 4096
#define SFOLD_DEV_SECTOR_SIZE 4096
/* A SFLC sector encompasses 8 kernel sectors */
#define SFLC_DEV_SECTOR_SCALE (SFLC_DEV_SECTOR_SIZE / SECTOR_SIZE)
#define SFOLD_DEV_SECTOR_SCALE (SFOLD_DEV_SECTOR_SIZE / SECTOR_SIZE)
/* An IV block holds IVs for 256 data blocks */
#define SFLC_DEV_SECTOR_TO_IV_RATIO (SFLC_DEV_SECTOR_SIZE / SFLC_SK_IV_LEN)
#define SFOLD_DEV_SECTOR_TO_IV_RATIO (SFOLD_DEV_SECTOR_SIZE / SFOLD_SK_IV_LEN)
/* Max number of volumes linked to a single device */
#define SFLC_DEV_MAX_VOLUMES 15
#define SFOLD_DEV_MAX_VOLUMES 15
/* A physical slice contains the 256 encrypted data blocks and the IV block */
#define SFLC_DEV_PHYS_SLICE_SIZE (SFLC_VOL_LOG_SLICE_SIZE + (SFLC_VOL_LOG_SLICE_SIZE / SFLC_DEV_SECTOR_TO_IV_RATIO))
#define SFOLD_DEV_PHYS_SLICE_SIZE (SFOLD_VOL_LOG_SLICE_SIZE + (SFOLD_VOL_LOG_SLICE_SIZE / SFOLD_DEV_SECTOR_TO_IV_RATIO))
/* Value marking a PSI as unassigned */
#define SFLC_DEV_RMAP_INVALID_VOL 0xFFU
#define SFOLD_DEV_RMAP_INVALID_VOL 0xFFU
/* Maximum number of open devices in total across shufflecake */
#define SFLC_DEV_MAX_DEVICES_TOT 1024
#define SFOLD_DEV_MAX_DEVICES_TOT 1024
/*****************************************************
* TYPES *
*****************************************************/
struct sflc_dev_iv_cache_entry_s
struct sfold_dev_iv_cache_entry_s
{
/* The PSI it refers to */
u32 psi;
@ -100,23 +99,25 @@ struct sflc_dev_iv_cache_entry_s
struct list_head lru_node;
};
struct sflc_device_s
struct sfold_device_s
{
/* Underlying block device */
struct dm_dev * bdev;
char * bdev_path;
/* Target instance that owns the bdev reference */
struct dm_target *ti;
/* Shufflecake-unique numeric ID of this device */
size_t dev_id;
u32 dev_id;
/* All volumes linked to this device */
sflc_Volume * vol[SFLC_DEV_MAX_VOLUMES];
sfold_Volume * vol[SFOLD_DEV_MAX_VOLUMES];
int vol_cnt;
/* Reverse slice map, associating PSIs to volume indices */
u8 * rmap;
/* Shuffled array of PSIs, with advancement counter */
u32 *prmslices;
u32 prmslices_octr;
u32 *shuffled_psi_array;
u32 shuffled_psi_ctr;
/* Lock for all three of these objects */
struct mutex slices_lock;
@ -129,98 +130,57 @@ struct sflc_device_s
u32 vol_header_size;
u32 dev_header_size;
/* Parent sysfs directory */
struct kobject *kobj_parent;
/* LRU cache of IV blocks */
struct mutex iv_cache_lock;
wait_queue_head_t iv_cache_waitqueue;
sflc_dev_IvCacheEntry ** iv_cache;
sfold_dev_IvCacheEntry ** iv_cache;
u32 iv_cache_nr_entries;
struct list_head iv_lru_list;
/* Sysfs stuff */
sflc_sysfs_Device * kobj;
/* DM-io */
struct dm_io_client *dmio_client;
/* We keep all devices in a list */
struct list_head list_node;
};
/*****************************************************
* MACROS *
*****************************************************/
#define sflc_dev_psiToIvBlock(dev, psi) (dev->dev_header_size + (sector_t)(psi) * SFLC_DEV_PHYS_SLICE_SIZE)
/*****************************************************
* PUBLIC VARIABLES DECLARATIONS *
*****************************************************/
/* The next available device ID */
extern size_t sflc_dev_nextId;
/* List of all devices */
extern struct list_head sflc_dev_list;
/* Big, coarse-grained lock for all modifying operations on any device or the device list */
extern struct semaphore sflc_dev_mutex;
/*****************************************************
* PUBLIC FUNCTIONS PROTOTYPES *
*****************************************************/
/* Inits global variables */
int sflc_dev_init(void);
/* Tears down global variables */
void sflc_dev_exit(void);
/*
* None of these functions acquire the big device lock: it must be held
* by the caller.
*/
/* Creates Device and adds it to the list. Returns an ERR_PTR() if unsuccessful. */
sflc_Device * sflc_dev_create(struct dm_target * ti, char * real_dev_path, u32 tot_slices);
/* Returns NULL if not found */
sflc_Device * sflc_dev_lookupByPath(char * real_dev_path);
sfold_Device * sfold_dev_create(struct dm_target *ti, int argc, char **argv, struct kobject *kobj);
/* Returns false if still busy (not all volumes have been removed) Frees the Device. */
bool sflc_dev_destroy(struct dm_target * ti, sflc_Device * dev);
bool sfold_dev_destroy(sfold_Device * dev);
/* Returns false if volume index was already occupied. */
bool sflc_dev_addVolume(sflc_Device * dev, sflc_Volume * vol, int vol_idx);
/* Looks at all volumes in all devices. Returns NULL if not found */
sflc_Volume * sflc_dev_lookupVolumeByName(char * vol_name);
bool sfold_dev_addVolume(sfold_Device * dev, sfold_Volume * vol, int vol_idx);
/* Does not put the volume. Returns false if was already NULL. */
bool sflc_dev_removeVolume(sflc_Device * dev, int vol_idx);
bool sfold_dev_removeVolume(sfold_Device * dev, int vol_idx);
/* Synchronously reads/writes one 4096-byte sector from/to the underlying device
to/from the provided page */
int sflc_dev_rwSector(sflc_Device * dev, struct page * page, sector_t sector, int rw);
/* Synchronously read/write entire PSI (257 blocks) to/from VMA */
int sflc_dev_rwPsi(sflc_Device *dev, void *vma, u32 psi, int rw);
int sfold_dev_rwSector(sfold_Device * dev, struct page * page, sector_t sector, int rw);
/* The caller needs to hold slices_lock to call these functions */
/* Checks if PSI is free */
bool sflc_dev_isPsiFree(sflc_Device *dev, u32 psi);
/* Sets the PSI as owned by the given volume (also decreases free_slices).
* Returns < 0 if already taken. */
int sflc_dev_markPsiTaken(sflc_Device * dev, u32 psi, u8 vol_idx);
int sfold_dev_markPsiTaken(sfold_Device * dev, u32 psi, u8 vol_idx);
/* Returns a random free physical slice, or < 0 if error */
s32 sflc_dev_getNextRandomFreePsi(sflc_Device * dev);
s32 sfold_dev_getNextRandomFreePsi(sfold_Device * dev);
/* These functions provide concurrent-safe access to the entries of the IV cache.
@ -231,13 +191,13 @@ s32 sflc_dev_getNextRandomFreePsi(sflc_Device * dev);
When the refcount reaches 0, the IV block is flushed. */
/* Get a pointer to the specified IV block. Increases the refcount and possibly the dirtyness (if WRITE). */
u8 * sflc_dev_getIvBlockRef(sflc_Device * dev, u32 psi, int rw);
u8 * sfold_dev_getIvBlockRef(sfold_Device * dev, u32 psi, int rw);
/* Signal end of usage of an IV block. Decreases the refcount. */
int sflc_dev_putIvBlockRef(sflc_Device * dev, u32 psi);
int sfold_dev_putIvBlockRef(sfold_Device * dev, u32 psi);
/* Flush all dirty IV blocks */
void sflc_dev_flushIvs(sflc_Device * dev);
void sfold_dev_flushIvs(sfold_Device * dev);
#endif /* _SFLC_DEVICE_DEVICE_H_ */
#endif /* _SFOLD_DEVICE_DEVICE_H_ */

View file

@ -25,24 +25,30 @@
* INCLUDE SECTION *
*****************************************************/
#include "device.h"
#include "utils/pools.h"
#include "log/log.h"
#include "old/device/device.h"
#include "old/utils/pools.h"
#include "old/log/log.h"
/*****************************************************
* CONSTANTS *
*****************************************************/
/* Capacity of IV cache */
#define SFLC_DEV_IV_CACHE_CAPACITY 1024
#define SFOLD_DEV_IV_CACHE_CAPACITY 1024
/*****************************************************
* MACROS *
*****************************************************/
#define sfold_dev_psiToIvBlockSector(dev, psi) (dev->dev_header_size + (sector_t)(psi) * SFOLD_DEV_PHYS_SLICE_SIZE)
/*****************************************************
* PRIVATE FUNCTIONS PROTOTYPES *
*****************************************************/
static sflc_dev_IvCacheEntry * sflc_dev_newIvCacheEntry(sflc_Device * dev, u32 psi);
static int sflc_dev_destroyIvCacheEntry(sflc_Device * dev, sflc_dev_IvCacheEntry * entry);
static sfold_dev_IvCacheEntry * sfold_dev_newIvCacheEntry(sfold_Device * dev, u32 psi);
static int sfold_dev_destroyIvCacheEntry(sfold_Device * dev, sfold_dev_IvCacheEntry * entry);
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
@ -50,9 +56,9 @@ static int sflc_dev_destroyIvCacheEntry(sflc_Device * dev, sflc_dev_IvCacheEntry
/* Get a read/write pointer to the specified IV block. Increases the refcount.
Returns an ERR_PTR() if error. */
u8 * sflc_dev_getIvBlockRef(sflc_Device * dev, u32 psi, int rw)
u8 * sfold_dev_getIvBlockRef(sfold_Device * dev, u32 psi, int rw)
{
sflc_dev_IvCacheEntry * entry;
sfold_dev_IvCacheEntry * entry;
int err;
/* Lock + waitqueue pattern */
@ -65,13 +71,13 @@ u8 * sflc_dev_getIvBlockRef(sflc_Device * dev, u32 psi, int rw)
}
/* Check for either of two conditions in order to go through */
while (dev->iv_cache[psi] == NULL && dev->iv_cache_nr_entries >= SFLC_DEV_IV_CACHE_CAPACITY) {
while (dev->iv_cache[psi] == NULL && dev->iv_cache_nr_entries >= SFOLD_DEV_IV_CACHE_CAPACITY) {
/* We can't go through, yield the lock */
mutex_unlock(&dev->iv_cache_lock);
/* Sleep in the waitqueue (same conditions) */
if (wait_event_interruptible(dev->iv_cache_waitqueue, dev->iv_cache[psi] != NULL ||
dev->iv_cache_nr_entries < SFLC_DEV_IV_CACHE_CAPACITY)) {
dev->iv_cache_nr_entries < SFOLD_DEV_IV_CACHE_CAPACITY)) {
err = -EINTR;
pr_err("Interrupted while waiting in waitqueue\n");
goto err_wait_queue;
@ -93,7 +99,7 @@ u8 * sflc_dev_getIvBlockRef(sflc_Device * dev, u32 psi, int rw)
entry = dev->iv_cache[psi];
if (!entry) {
/* Create it */
entry = sflc_dev_newIvCacheEntry(dev, psi);
entry = sfold_dev_newIvCacheEntry(dev, psi);
if (IS_ERR(entry)) {
err = PTR_ERR(entry);
pr_err("Could not create new cache entry; error %d\n", err);
@ -133,9 +139,9 @@ err_lock_cache:
}
/* Signal end of usage of an IV block. Decreases the refcount. */
int sflc_dev_putIvBlockRef(sflc_Device * dev, u32 psi)
int sfold_dev_putIvBlockRef(sfold_Device * dev, u32 psi)
{
sflc_dev_IvCacheEntry * entry;
sfold_dev_IvCacheEntry * entry;
int err;
/* No condition needed besides mutual exclusion: just grab the lock (no waitqueue) */
@ -156,12 +162,12 @@ int sflc_dev_putIvBlockRef(sflc_Device * dev, u32 psi)
list_add(&entry->lru_node, &dev->iv_lru_list);
/* If cache is not full, we can return now */
if (dev->iv_cache_nr_entries < SFLC_DEV_IV_CACHE_CAPACITY) {
if (dev->iv_cache_nr_entries < SFOLD_DEV_IV_CACHE_CAPACITY) {
goto out;
}
/* Otherwise, let's look for the least recent unreffed entry, and evict it */
sflc_dev_IvCacheEntry * evicted;
sfold_dev_IvCacheEntry * evicted;
bool found = false;
list_for_each_entry_reverse(evicted, &dev->iv_lru_list, lru_node) {
if (evicted->refcnt == 0) {
@ -182,7 +188,7 @@ int sflc_dev_putIvBlockRef(sflc_Device * dev, u32 psi)
/* Pull it out of the LRU list */
__list_del_entry(&evicted->lru_node);
/* Destroy it (free and flush to disk) */
err = sflc_dev_destroyIvCacheEntry(dev, evicted);
err = sfold_dev_destroyIvCacheEntry(dev, evicted);
if (err) {
pr_err("Could not evict cache entry for PSI %u; error %d\n", evicted->psi, err);
goto err_destroy_entry;
@ -210,9 +216,9 @@ err_lock_cache:
}
/* Flush all dirty IV blocks */
void sflc_dev_flushIvs(sflc_Device * dev)
void sfold_dev_flushIvs(sfold_Device * dev)
{
sflc_dev_IvCacheEntry * entry, * _next;
sfold_dev_IvCacheEntry * entry, * _next;
int err;
/* Iterate over all entries */
@ -221,7 +227,7 @@ void sflc_dev_flushIvs(sflc_Device * dev)
__list_del_entry(&entry->lru_node);
/* Destroy it */
err = sflc_dev_destroyIvCacheEntry(dev, entry);
err = sfold_dev_destroyIvCacheEntry(dev, entry);
if (err) {
pr_err("Could not destroy IV cache entry for PSI %u; error %d\n", entry->psi, err);
}
@ -232,16 +238,16 @@ void sflc_dev_flushIvs(sflc_Device * dev)
* PRIVATE FUNCTIONS PROTOTYPES *
*****************************************************/
static sflc_dev_IvCacheEntry * sflc_dev_newIvCacheEntry(sflc_Device * dev, u32 psi)
static sfold_dev_IvCacheEntry * sfold_dev_newIvCacheEntry(sfold_Device * dev, u32 psi)
{
sflc_dev_IvCacheEntry * entry;
sfold_dev_IvCacheEntry * entry;
int err;
sector_t sector;
/* Allocate and init structure */
/* Allocate structure */
entry = kmem_cache_alloc(sflc_pools_ivSlab, GFP_NOIO);
entry = kmem_cache_alloc(sfold_pools_ivSlab, GFP_NOIO);
if (!entry) {
pr_err("Could not allocate IvCacheEntry structure\n");
err = -ENOMEM;
@ -251,7 +257,7 @@ static sflc_dev_IvCacheEntry * sflc_dev_newIvCacheEntry(sflc_Device * dev, u32 p
/* Set PSI */
entry->psi = psi;
/* Allocate page */
entry->iv_page = mempool_alloc(sflc_pools_pagePool, GFP_NOIO);
entry->iv_page = mempool_alloc(sfold_pools_pagePool, GFP_NOIO);
if (!entry->iv_page) {
pr_err("Could not allocate IV page\n");
err = -ENOMEM;
@ -271,10 +277,10 @@ static sflc_dev_IvCacheEntry * sflc_dev_newIvCacheEntry(sflc_Device * dev, u32 p
/* Read from disk */
/* Position on disk */
sector = sflc_dev_psiToIvBlock(dev, psi);
sector = sfold_dev_psiToIvBlockSector(dev, psi);
/* Read */
err = sflc_dev_rwSector(dev, entry->iv_page, sector, READ);
err = sfold_dev_rwSector(dev, entry->iv_page, sector, READ);
if (err) {
pr_err("Could not read IV block from disk; error %d\n", err);
goto err_read;
@ -285,14 +291,14 @@ static sflc_dev_IvCacheEntry * sflc_dev_newIvCacheEntry(sflc_Device * dev, u32 p
err_read:
kunmap(entry->iv_page);
mempool_free(entry->iv_page, sflc_pools_pagePool);
mempool_free(entry->iv_page, sfold_pools_pagePool);
err_alloc_page:
kmem_cache_free(sflc_pools_ivSlab, entry);
kmem_cache_free(sfold_pools_ivSlab, entry);
err_alloc_entry:
return ERR_PTR(err);
}
static int sflc_dev_destroyIvCacheEntry(sflc_Device * dev, sflc_dev_IvCacheEntry * entry)
static int sfold_dev_destroyIvCacheEntry(sfold_Device * dev, sfold_dev_IvCacheEntry * entry)
{
int err;
sector_t sector;
@ -300,11 +306,11 @@ static int sflc_dev_destroyIvCacheEntry(sflc_Device * dev, sflc_dev_IvCacheEntry
/* Write to disk */
/* Position on disk */
sector = sflc_dev_psiToIvBlock(dev, entry->psi);
sector = sfold_dev_psiToIvBlockSector(dev, entry->psi);
/* Write (if necessary) */
if (entry->dirtyness) {
err = sflc_dev_rwSector(dev, entry->iv_page, sector, WRITE);
err = sfold_dev_rwSector(dev, entry->iv_page, sector, WRITE);
if (err) {
pr_err("Could not write IV block to disk; error %d\n", err);
return err;
@ -317,10 +323,10 @@ static int sflc_dev_destroyIvCacheEntry(sflc_Device * dev, sflc_dev_IvCacheEntry
/* Kunmap page */
kunmap(entry->iv_page);
/* Free it */
mempool_free(entry->iv_page, sflc_pools_pagePool);
mempool_free(entry->iv_page, sfold_pools_pagePool);
/* Free structure */
kmem_cache_free(sflc_pools_ivSlab, entry);
kmem_cache_free(sfold_pools_ivSlab, entry);
return 0;
}

View file

@ -25,14 +25,12 @@
* INCLUDE SECTION *
*****************************************************/
#include "device.h"
#include "utils/pools.h"
#include "log/log.h"
#include "old/device/device.h"
#include "old/utils/pools.h"
#include "old/log/log.h"
#include <linux/bio.h>
#include <linux/dm-io.h>
#include <linux/errno.h>
//#include <linux/ioprio.h>
/*****************************************************
* CONSTANTS *
@ -48,7 +46,7 @@
/* Synchronously reads/writes one 4096-byte sector from/to the underlying device
to/from the provided page */
int sflc_dev_rwSector(sflc_Device * dev, struct page * page, sector_t sector, int rw)
int sfold_dev_rwSector(sfold_Device * dev, struct page * page, sector_t sector, int rw)
{
struct bio *bio;
blk_opf_t opf;
@ -59,16 +57,16 @@ int sflc_dev_rwSector(sflc_Device * dev, struct page * page, sector_t sector, in
opf |= REQ_SYNC;
/* Allocate bio */
bio = bio_alloc_bioset(dev->bdev->bdev, 1, opf, GFP_NOIO, &sflc_pools_bioset);
bio = bio_alloc_bioset(dev->bdev->bdev, 1, opf, GFP_NOIO, &sfold_pools_bioset);
if (!bio) {
pr_err("Could not allocate bio\n");
return -ENOMEM;
}
/* Set sector */
bio->bi_iter.bi_sector = sector * SFLC_DEV_SECTOR_SCALE;
bio->bi_iter.bi_sector = sector * SFOLD_DEV_SECTOR_SCALE;
/* Add page */
if (!bio_add_page(bio, page, SFLC_DEV_SECTOR_SIZE, 0)) {
if (!bio_add_page(bio, page, SFOLD_DEV_SECTOR_SIZE, 0)) {
pr_err("Catastrophe: could not add page to bio! WTF?\n");
err = EINVAL;
goto out;
@ -83,32 +81,6 @@ out:
return err;
}
/*
// Synchronously read/write entire PSI (257 blocks) to/from VMA
int sflc_dev_rwPsi(sflc_Device *dev, void *vma, u32 psi, int rw)
{
struct dm_io_request io_req = {
.bi_opf = ((rw == READ) ? REQ_OP_READ : REQ_OP_WRITE) | REQ_SYNC,
.mem.type = DM_IO_VMA,
.mem.offset = 0,
.mem.ptr.vma = vma,
.notify.fn = NULL,
.client = dev->dmio_client
};
struct dm_io_region io_reg = {
.bdev = dev->bdev->bdev,
.sector = sflc_dev_psiToIvBlock(dev, psi) * SFLC_DEV_SECTOR_SCALE,
.count = SFLC_DEV_PHYS_SLICE_SIZE * SFLC_DEV_SECTOR_SCALE
};
return dm_io(&io_req, 1, &io_reg, NULL);
}
*/
/*****************************************************
* PRIVATE FUNCTIONS DEFINITIONS *
*****************************************************/

View file

@ -29,9 +29,9 @@
* INCLUDE SECTION *
*****************************************************/
#include "device.h"
#include "crypto/rand/rand.h"
#include "log/log.h"
#include "old/device/device.h"
#include "old/crypto/rand/rand.h"
#include "old/log/log.h"
/*****************************************************
* CONSTANTS *
@ -41,18 +41,12 @@
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
/* Checks if PSI is free */
bool sflc_dev_isPsiFree(sflc_Device *dev, u32 psi)
{
return ((psi < dev->tot_slices) &&
(dev->rmap[psi] == SFLC_DEV_RMAP_INVALID_VOL));
}
/* Sets the PSI as owned by the given volume (also decreases free_slices).
* Returns < 0 if already taken. */
int sflc_dev_markPsiTaken(sflc_Device * dev, u32 psi, u8 vol_idx)
int sfold_dev_markPsiTaken(sfold_Device * dev, u32 psi, u8 vol_idx)
{
u8 prev_vol_idx;
/* Bounds check */
if (psi >= dev->tot_slices) {
pr_err("Requested to set ownership for invalid PSI\n");
@ -60,7 +54,8 @@ int sflc_dev_markPsiTaken(sflc_Device * dev, u32 psi, u8 vol_idx)
}
/* Check that it's free */
if (dev->rmap[psi] != SFLC_DEV_RMAP_INVALID_VOL) {
prev_vol_idx = dev->rmap[psi];
if (prev_vol_idx != SFOLD_DEV_RMAP_INVALID_VOL) {
pr_err("Requested to set ownership for already-owned PSI\n");
return -EINVAL;
}
@ -74,7 +69,7 @@ int sflc_dev_markPsiTaken(sflc_Device * dev, u32 psi, u8 vol_idx)
/* Returns a random free physical slice, or < 0 if error */
s32 sflc_dev_getNextRandomFreePsi(sflc_Device * dev)
s32 sfold_dev_getNextRandomFreePsi(sfold_Device * dev)
{
u32 psi;
@ -87,15 +82,14 @@ s32 sflc_dev_getNextRandomFreePsi(sflc_Device * dev)
/* Repeatedly advance the counter in the shuffled array
* until you find a free one */
do {
if (dev->prmslices_octr >= dev->tot_slices) {
pr_err("Double catastrophe! No free PSIs on the device, "
"and didn't catch it before!\n");
psi = dev->shuffled_psi_array[dev->shuffled_psi_ctr];
dev->shuffled_psi_ctr += 1;
if (dev->shuffled_psi_ctr >= dev->tot_slices) {
pr_err("Double catastrophe! No free PSIs on the device, and didn't catch it before!\n");
return -ENOSPC;
}
psi = dev->prmslices[dev->prmslices_octr];
dev->prmslices_octr += 1;
} while (dev->rmap[psi] != SFLC_DEV_RMAP_INVALID_VOL);
} while (dev->rmap[psi] != SFOLD_DEV_RMAP_INVALID_VOL);
return psi;
}

View file

@ -29,8 +29,8 @@
* INCLUDE SECTION *
*****************************************************/
#include "device.h"
#include "log/log.h"
#include "old/device/device.h"
#include "old/log/log.h"
/*****************************************************
* CONSTANTS *
@ -41,22 +41,13 @@
*****************************************************/
/* Returns false if volume index was already occupied. */
bool sflc_dev_addVolume(sflc_Device * dev, sflc_Volume * vol, int vol_idx)
bool sfold_dev_addVolume(sfold_Device * dev, sfold_Volume * vol, int vol_idx)
{
int err;
if (dev->vol[vol_idx]) {
pr_err("Something's wrong, asked to set volume number %d, already occupied\n", vol_idx);
return false;
}
/* Update sysfs */
err = sflc_sysfs_addVolumeToDevice(dev->kobj, vol->kvol);
if (err) {
pr_err("Could not add volume symlink in sysfs device subdir; error %d\n", err);
return false;
}
/* Update fields */
dev->vol[vol_idx] = vol;
dev->vol_cnt += 1;
@ -64,39 +55,15 @@ bool sflc_dev_addVolume(sflc_Device * dev, sflc_Volume * vol, int vol_idx)
return true;
}
/* Looks at all volumes in all devices. Returns NULL if not found */
sflc_Volume * sflc_dev_lookupVolumeByName(char * vol_name)
{
sflc_Device * dev;
sflc_Volume * vol;
/* Sweep all devices */
list_for_each_entry(dev, &sflc_dev_list, list_node) {
/* Sweep all volumes */
int i;
for (i = 0; i < SFLC_DEV_MAX_VOLUMES; ++i) {
vol = dev->vol[i];
if (vol && (strcmp(vol_name, vol->vol_name) == 0)) {
return vol;
}
}
}
return NULL;
}
/* Does not put the volume. Returns false if was already NULL. */
bool sflc_dev_removeVolume(sflc_Device * dev, int vol_idx)
bool sfold_dev_removeVolume(sfold_Device * dev, int vol_idx)
{
if (!dev->vol[vol_idx]) {
pr_err("Something's wrong, asked to unset volume number %d, already NULL\n", vol_idx);
return false;
}
/* Remove sysfs entry */
if (dev->vol[vol_idx]->kvol) {
sflc_sysfs_removeVolumeFromDevice(dev->kobj, dev->vol[vol_idx]->kvol);
}
/* Update fields */
dev->vol[vol_idx] = NULL;

View file

@ -25,8 +25,8 @@
* Logging format
*/
#ifndef _SFLC_LOG_LOG_H_
#define _SFLC_LOG_LOG_H_
#ifndef _SFOLD_LOG_LOG_H_
#define _SFOLD_LOG_LOG_H_
/*****************************************************
* INCLUDE SECTION *
@ -41,4 +41,4 @@
#undef pr_fmt
#define pr_fmt(fmt) "[%s] %s in %s:%d: " fmt, KBUILD_MODNAME, __func__, __FILE__, __LINE__
#endif /* _SFLC_LOG_LOG_H_ */
#endif /* _SFOLD_LOG_LOG_H_ */

View file

@ -0,0 +1,87 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include <linux/module.h>
#include <linux/device-mapper.h>
#include "old/sflc_old.h"
#include "old/crypto/symkey/symkey.h"
#include "old/crypto/rand/rand.h"
#include "old/utils/pools.h"
#include "old/utils/workqueues.h"
#include "old/log/log.h"
/*****************************************************
* MODULE FUNCTIONS DEFINITIONS *
*****************************************************/
/* Module entry point, called just once, at module-load time */
int sfold_init(void)
{
int ret;
ret = sfold_rand_init();
if (ret) {
pr_err("Could not init rand; error %d\n", ret);
goto err_rand_init;
}
/* Init the memory pools */
ret = sfold_pools_init();
if (ret) {
pr_err("Could not init memory pools; error %d\n", ret);
goto err_pools;
}
/* Init the workqueues */
ret = sfold_queues_init();
if (ret) {
pr_err("Could not init workqueues; error %d\n", ret);
goto err_queues;
}
return 0;
err_queues:
sfold_pools_exit();
err_pools:
sfold_rand_exit();
err_rand_init:
return ret;
}
/* Module exit point, called just once, at module-unload time */
void sfold_exit(void)
{
sfold_queues_exit();
sfold_pools_exit();
sfold_rand_exit();
return;
}

View file

@ -20,25 +20,27 @@
* GNU General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*/
/*
* Methods of our DM target
*/
#ifndef _SFLC_TARGET_TARGET_H_
#define _SFLC_TARGET_TARGET_H_
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include <linux/device-mapper.h>
/*****************************************************
* PUBLIC VARIABLES DECLARATIONS *
*****************************************************/
extern struct target_type sflc_target;
#ifndef _SFOLD_SFOLD_H
#define _SFOLD_SFOLD_H
#endif /* _SFLC_TARGET_TARGET_H_ */
// For the definition of sfold_Device and its functions
#include "old/device/device.h"
// For the definition of sfold_Volume and its functions
#include "old/volume/volume.h"
extern struct target_type sfold_target_type;
int sfold_init(void);
void sfold_exit(void);
int sfold_sysfs_add_device(sfold_Device *dev);
void sfold_sysfs_remove_device(sfold_Device *dev);
int sfold_sysfs_add_volume(sfold_Volume *vol);
void sfold_sysfs_remove_volume(sfold_Volume *vol);
#endif /* _SFOLD_SFOLD_H */

142
dm-sflc/src/old/sysfs.c Normal file
View file

@ -0,0 +1,142 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include <linux/module.h>
#include "old/sflc_old.h"
#include "old/log/log.h"
// Only to import the definitions of structs sflc_volume and sflc_device
#include "sflc.h"
/*
*----------------------------
* Devices
*----------------------------
*/
/* Show the total number of slices in a device */
static ssize_t tot_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf)
{
struct sflc_device *top_dev;
sfold_Device * dev;
ssize_t ret;
top_dev = container_of(kobj, struct sflc_device, kobj);
dev = top_dev->sfold_dev;
/* Write the tot_slices */
ret = sysfs_emit(buf, "%u\n", dev->tot_slices);
return ret;
}
/* Show the number of free slices in a device */
static ssize_t free_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf)
{
struct sflc_device *top_dev;
sfold_Device * dev;
ssize_t ret;
top_dev = container_of(kobj, struct sflc_device, kobj);
dev = top_dev->sfold_dev;
/* Write the free_slices */
if (mutex_lock_interruptible(&dev->slices_lock))
return -ERESTARTSYS;
ret = sysfs_emit(buf, "%u\n", dev->free_slices);
mutex_unlock(&dev->slices_lock);
return ret;
}
static struct kobj_attribute tot_slices_kattr = __ATTR_RO(tot_slices);
static struct kobj_attribute free_slices_kattr = __ATTR_RO(free_slices);
static struct attribute *sfold_device_attrs[] = {
&tot_slices_kattr.attr,
&free_slices_kattr.attr,
NULL
};
static const struct attribute_group sfold_device_attr_group = {
.attrs = sfold_device_attrs,
};
int sfold_sysfs_add_device(sfold_Device *dev)
{
return sysfs_create_group(dev->kobj_parent, &sfold_device_attr_group);
}
void sfold_sysfs_remove_device(sfold_Device *dev)
{
sysfs_remove_group(dev->kobj_parent, &sfold_device_attr_group);
}
/*
*----------------------------
* Volumes
*----------------------------
*/
/* Show the number of mapped slices in a volume */
static ssize_t mapped_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf)
{
struct sflc_volume *top_vol;
sfold_Volume * vol;
ssize_t ret;
top_vol = container_of(kobj, struct sflc_volume, kobj);
vol = top_vol->sfold_vol;
/* Write the free_slices */
if (mutex_lock_interruptible(&vol->fmap_lock))
return -ERESTARTSYS;
ret = sysfs_emit(buf, "%u\n", vol->mapped_slices);
mutex_unlock(&vol->fmap_lock);
return ret;
}
static struct kobj_attribute mapped_slices_kattr = __ATTR_RO(mapped_slices);
static struct attribute *sfold_volume_attrs[] = {
&mapped_slices_kattr.attr,
NULL
};
static const struct attribute_group sfold_volume_attr_group = {
.attrs = sfold_volume_attrs,
};
int sfold_sysfs_add_volume(sfold_Volume *vol)
{
return sysfs_create_group(vol->kobj_parent, &sfold_volume_attr_group);
}
void sfold_sysfs_remove_volume(sfold_Volume *vol)
{
sysfs_remove_group(vol->kobj_parent, &sfold_volume_attr_group);
}

150
dm-sflc/src/old/target.c Normal file
View file

@ -0,0 +1,150 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* 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, see <https://www.gnu.org/licenses/>.
*/
/*
* Methods of our DM target
*/
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include "old/device/device.h"
#include "old/volume/volume.h"
#include "old/utils/bio.h"
#include "old/utils/string.h"
#include "old/log/log.h"
// Only to import the definition of struct sflc_volume
#include "sflc.h"
/*****************************************************
* CONSTANTS *
*****************************************************/
/*****************************************************
* PRIVATE FUNCTIONS PROTOTYPES *
*****************************************************/
static int sfold_tgt_map(struct dm_target *ti, struct bio *bio);
static void sfold_tgt_ioHints(struct dm_target *ti, struct queue_limits *limits);
static int sfold_tgt_iterateDevices(struct dm_target *ti, iterate_devices_callout_fn fn,
void *data);
/*****************************************************
* PUBLIC VARIABLES DEFINITIONS *
*****************************************************/
struct target_type sfold_target_type = {
.map = sfold_tgt_map,
.io_hints = sfold_tgt_ioHints,
.iterate_devices = sfold_tgt_iterateDevices,
};
/*****************************************************
* PRIVATE FUNCTIONS DEFINITIONS *
*****************************************************/
/* Callback for every bio submitted to our virtual block device */
static int sfold_tgt_map(struct dm_target *ti, struct bio *bio)
{
int err;
struct sflc_volume *top_vol = ti->private;
sfold_Volume *vol = top_vol->sfold_vol;
/* If no data, just quickly remap the sector and the block device (no crypto) */
/* TODO: this is dangerous for deniability, will need more filtering */
if (unlikely(!bio_has_data(bio))) {
pr_debug("No-data bio: bio_op = %d", bio_op(bio));
err = sfold_vol_remapBioFast(vol, bio);
if (err) {
pr_err("Could not remap bio; error %d\n", err);
return DM_MAPIO_KILL;
}
return DM_MAPIO_REMAPPED;
}
/* At this point, the bio has data. Do a few sanity checks */
/* TODO: I think we can get rid of all of them */
/* Check that it is properly aligned and it doesn't cross vector boundaries */
if (unlikely(!sfold_bio_isAligned(bio))) {
pr_err("Unaligned bio!\n");
return DM_MAPIO_KILL;
}
/* If it contains more than one SFLC sector, complain with the DM layer and continue */
if (unlikely(bio->bi_iter.bi_size > SFOLD_DEV_SECTOR_SIZE)) {
pr_notice("Large bio of size %u\n", bio->bi_iter.bi_size);
dm_accept_partial_bio(bio, SFOLD_DEV_SECTOR_SCALE);
}
/* Check that it contains exactly one SFLC sector */
if (unlikely(bio->bi_iter.bi_size != SFOLD_DEV_SECTOR_SIZE)) {
pr_err("Wrong length (%u) of bio\n", bio->bi_iter.bi_size);
return DM_MAPIO_KILL;
}
/* Now it is safe, process it */
err = sfold_vol_processBio(vol, bio);
if (err) {
pr_err("Could not enqueue bio\n");
return DM_MAPIO_KILL;
}
return DM_MAPIO_SUBMITTED;
}
/* Callback executed to inform the DM about our 4096-byte sector size */
static void sfold_tgt_ioHints(struct dm_target *ti, struct queue_limits *limits)
{
struct sflc_volume *top_vol = ti->private;
sfold_Volume *vol = top_vol->sfold_vol;
pr_info("Called io_hints on volume \"%s\"\n", vol->vol_name);
limits->logical_block_size = SFOLD_DEV_SECTOR_SIZE;
limits->physical_block_size = SFOLD_DEV_SECTOR_SIZE;
limits->io_min = SFOLD_DEV_SECTOR_SIZE;
limits->io_opt = SFOLD_DEV_SECTOR_SIZE;
return;
}
/* Callback needed for God knows what, otherwise io_hints never gets called */
static int sfold_tgt_iterateDevices(struct dm_target *ti, iterate_devices_callout_fn fn,
void *data)
{
struct sflc_volume *top_vol = ti->private;
sfold_Volume *vol = top_vol->sfold_vol;
sfold_Device * dev = vol->dev;
pr_debug("Called iterate_devices on volume \"%s\"\n", vol->vol_name);
if (!fn) {
return -EINVAL;
}
return fn(ti, vol->dev->bdev, 0,
(dev->dev_header_size + dev->tot_slices * SFOLD_DEV_PHYS_SLICE_SIZE) * SFOLD_DEV_SECTOR_SCALE,
data);
}

View file

@ -29,8 +29,8 @@
* INCLUDE SECTION *
*****************************************************/
#include "bio.h"
#include "log/log.h"
#include "old/utils/bio.h"
#include "old/log/log.h"
/*****************************************************
@ -41,7 +41,7 @@
* Checks whether each of the bio's segments contains a whole
* number of 4096-byte sectors.
*/
bool sflc_bio_isAligned(struct bio * bio)
bool sfold_bio_isAligned(struct bio * bio)
{
bool ret = true;
@ -51,12 +51,12 @@ bool sflc_bio_isAligned(struct bio * bio)
return false;
}
/* Unlikely because we tell the DM layer about our sector size */
if (unlikely(bio->bi_iter.bi_size % SFLC_DEV_SECTOR_SIZE != 0)) {
if (unlikely(bio->bi_iter.bi_size % SFOLD_DEV_SECTOR_SIZE != 0)) {
pr_err("Abnormal bi_size = %u\n", bio->bi_iter.bi_size);
return false;
}
/* Unlikely because we tell the DM layer about our sector size */
if (unlikely(bio->bi_iter.bi_sector % SFLC_DEV_SECTOR_SCALE != 0)) {
if (unlikely(bio->bi_iter.bi_sector % SFOLD_DEV_SECTOR_SCALE != 0)) {
pr_err("Abnormal bi_sector = %llu\n", bio->bi_iter.bi_sector);
return false;
}
@ -64,7 +64,7 @@ bool sflc_bio_isAligned(struct bio * bio)
struct bio_vec bvl;
struct bvec_iter iter;
bio_for_each_segment(bvl, bio, iter) {
if ((bvl.bv_len == 0) || (bvl.bv_len % SFLC_DEV_SECTOR_SIZE != 0)) {
if ((bvl.bv_len == 0) || (bvl.bv_len % SFOLD_DEV_SECTOR_SIZE != 0)) {
pr_err("Abnormal vector: bv_len = %u\n", bvl.bv_len);
ret = false;
}

View file

@ -25,14 +25,14 @@
* A collection of utility bio functions
*/
#ifndef _SFLC_UTILS_BIO_H_
#define _SFLC_UTILS_BIO_H_
#ifndef _SFOLD_UTILS_BIO_H_
#define _SFOLD_UTILS_BIO_H_
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include "device/device.h"
#include "old/device/device.h"
/*****************************************************
* PUBLIC FUNCTIONS PROTOTYPES *
@ -42,7 +42,7 @@
* Checks whether each of the bio's segments contains a whole
* number of 4096-byte sectors.
*/
bool sflc_bio_isAligned(struct bio * bio);
bool sfold_bio_isAligned(struct bio * bio);
#endif /* _SFLC_UTILS_BIO_H_ */
#endif /* _SFOLD_UTILS_BIO_H_ */

View file

@ -29,100 +29,100 @@
* INCLUDE SECTION *
*****************************************************/
#include "pools.h"
#include "log/log.h"
#include "old/utils/pools.h"
#include "old/log/log.h"
/*****************************************************
* CONSTANTS *
*****************************************************/
/* Pool sizes */
#define SFLC_POOLS_BIOSET_POOL_SIZE 1024
#define SFLC_POOLS_PAGE_POOL_SIZE 1024
#define SFLC_POOLS_WRITE_WORK_POOL_SIZE 1024
#define SFLC_POOLS_DECRYPT_WORK_POOL_SIZE 1024
#define SFOLD_POOLS_BIOSET_POOL_SIZE 1024
#define SFOLD_POOLS_PAGE_POOL_SIZE 1024
#define SFOLD_POOLS_WRITE_WORK_POOL_SIZE 1024
#define SFOLD_POOLS_DECRYPT_WORK_POOL_SIZE 1024
/* Slab cache names */
#define SFLC_POOLS_WRITE_WORK_SLAB_NAME "sflc_write_work_slab"
#define SFLC_POOLS_DECRYPT_WORK_SLAB_NAME "sflc_decrypt_work_slab"
#define SFLC_POOLS_IV_SLAB_NAME "sflc_iv_slab"
#define SFOLD_POOLS_WRITE_WORK_SLAB_NAME "sfold_write_work_slab"
#define SFOLD_POOLS_DECRYPT_WORK_SLAB_NAME "sfold_decrypt_work_slab"
#define SFOLD_POOLS_IV_SLAB_NAME "sfold_iv_slab"
/*****************************************************
* PUBLIC VARIABLES DEFINITIONS *
*****************************************************/
struct bio_set sflc_pools_bioset;
mempool_t * sflc_pools_pagePool;
mempool_t * sflc_pools_writeWorkPool;
mempool_t * sflc_pools_decryptWorkPool;
struct kmem_cache * sflc_pools_ivSlab;
struct bio_set sfold_pools_bioset;
mempool_t * sfold_pools_pagePool;
mempool_t * sfold_pools_writeWorkPool;
mempool_t * sfold_pools_decryptWorkPool;
struct kmem_cache * sfold_pools_ivSlab;
/*****************************************************
* PRIVATE VARIABLES *
*****************************************************/
static struct kmem_cache * sflc_pools_writeWorkSlab;
static struct kmem_cache * sflc_pools_decryptWorkSlab;
static struct kmem_cache * sfold_pools_writeWorkSlab;
static struct kmem_cache * sfold_pools_decryptWorkSlab;
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
int sflc_pools_init(void)
int sfold_pools_init(void)
{
int err;
/* Memory pools: bioset */
err = bioset_init(&sflc_pools_bioset, SFLC_POOLS_BIOSET_POOL_SIZE, 0, BIOSET_NEED_BVECS);
err = bioset_init(&sfold_pools_bioset, SFOLD_POOLS_BIOSET_POOL_SIZE, 0, BIOSET_NEED_BVECS);
if (err) {
pr_err("Could not init bioset: error %d\n", err);
goto err_bioset;
}
/* Memory pools: page_pool */
sflc_pools_pagePool = mempool_create_page_pool(SFLC_POOLS_PAGE_POOL_SIZE, 0);
if (!sflc_pools_pagePool) {
sfold_pools_pagePool = mempool_create_page_pool(SFOLD_POOLS_PAGE_POOL_SIZE, 0);
if (!sfold_pools_pagePool) {
pr_err("Could not create page pool\n");
err = -ENOMEM;
goto err_pagepool;
}
/* Memory pools: writeWork slab cache */
sflc_pools_writeWorkSlab = kmem_cache_create(SFLC_POOLS_WRITE_WORK_SLAB_NAME, sizeof(sflc_vol_WriteWork), 0, SLAB_POISON | SLAB_RED_ZONE, NULL);
if (IS_ERR(sflc_pools_writeWorkSlab)) {
err = PTR_ERR(sflc_pools_writeWorkSlab);
sfold_pools_writeWorkSlab = kmem_cache_create(SFOLD_POOLS_WRITE_WORK_SLAB_NAME, sizeof(sfold_vol_WriteWork), 0, SLAB_POISON | SLAB_RED_ZONE, NULL);
if (IS_ERR(sfold_pools_writeWorkSlab)) {
err = PTR_ERR(sfold_pools_writeWorkSlab);
pr_err("Could not create writeWork slab cache; error %d\n", err);
goto err_create_write_work_slab;
}
/* Memory pools: writeWork pool */
sflc_pools_writeWorkPool = mempool_create_slab_pool(SFLC_POOLS_WRITE_WORK_POOL_SIZE, sflc_pools_writeWorkSlab);
if (!sflc_pools_writeWorkPool) {
sfold_pools_writeWorkPool = mempool_create_slab_pool(SFOLD_POOLS_WRITE_WORK_POOL_SIZE, sfold_pools_writeWorkSlab);
if (!sfold_pools_writeWorkPool) {
pr_err("Could not create writeWork pool\n");
err = -ENOMEM;
goto err_write_work_pool;
}
/* Memory pools: decryptWork slab cache */
sflc_pools_decryptWorkSlab = kmem_cache_create(SFLC_POOLS_DECRYPT_WORK_SLAB_NAME, sizeof(sflc_vol_DecryptWork), 0, SLAB_POISON | SLAB_RED_ZONE, NULL);
if (IS_ERR(sflc_pools_decryptWorkSlab)) {
err = PTR_ERR(sflc_pools_decryptWorkSlab);
sfold_pools_decryptWorkSlab = kmem_cache_create(SFOLD_POOLS_DECRYPT_WORK_SLAB_NAME, sizeof(sfold_vol_DecryptWork), 0, SLAB_POISON | SLAB_RED_ZONE, NULL);
if (IS_ERR(sfold_pools_decryptWorkSlab)) {
err = PTR_ERR(sfold_pools_decryptWorkSlab);
pr_err("Could not create decryptWork slab cache; error %d\n", err);
goto err_create_decrypt_work_slab;
}
/* Memory pools: decryptWork pool */
sflc_pools_decryptWorkPool = mempool_create_slab_pool(SFLC_POOLS_DECRYPT_WORK_POOL_SIZE, sflc_pools_decryptWorkSlab);
if (!sflc_pools_decryptWorkPool) {
sfold_pools_decryptWorkPool = mempool_create_slab_pool(SFOLD_POOLS_DECRYPT_WORK_POOL_SIZE, sfold_pools_decryptWorkSlab);
if (!sfold_pools_decryptWorkPool) {
pr_err("Could not create decryptWork pool\n");
err = -ENOMEM;
goto err_decrypt_work_pool;
}
/* Memory pools: IV slab cache */
sflc_pools_ivSlab = kmem_cache_create(SFLC_POOLS_IV_SLAB_NAME, sizeof(sflc_dev_IvCacheEntry), 0, SLAB_POISON | SLAB_RED_ZONE, NULL);
if (IS_ERR(sflc_pools_ivSlab)) {
err = PTR_ERR(sflc_pools_ivSlab);
sfold_pools_ivSlab = kmem_cache_create(SFOLD_POOLS_IV_SLAB_NAME, sizeof(sfold_dev_IvCacheEntry), 0, SLAB_POISON | SLAB_RED_ZONE, NULL);
if (IS_ERR(sfold_pools_ivSlab)) {
err = PTR_ERR(sfold_pools_ivSlab);
pr_err("Could not create IV slab cache; error %d\n", err);
goto err_create_iv_slab;
}
@ -131,28 +131,28 @@ int sflc_pools_init(void)
err_create_iv_slab:
mempool_destroy(sflc_pools_decryptWorkPool);
mempool_destroy(sfold_pools_decryptWorkPool);
err_decrypt_work_pool:
kmem_cache_destroy(sflc_pools_decryptWorkSlab);
kmem_cache_destroy(sfold_pools_decryptWorkSlab);
err_create_decrypt_work_slab:
mempool_destroy(sflc_pools_writeWorkPool);
mempool_destroy(sfold_pools_writeWorkPool);
err_write_work_pool:
kmem_cache_destroy(sflc_pools_writeWorkSlab);
kmem_cache_destroy(sfold_pools_writeWorkSlab);
err_create_write_work_slab:
mempool_destroy(sflc_pools_pagePool);
mempool_destroy(sfold_pools_pagePool);
err_pagepool:
bioset_exit(&sflc_pools_bioset);
bioset_exit(&sfold_pools_bioset);
err_bioset:
return err;
}
void sflc_pools_exit(void)
void sfold_pools_exit(void)
{
kmem_cache_destroy(sflc_pools_ivSlab);
mempool_destroy(sflc_pools_decryptWorkPool);
kmem_cache_destroy(sflc_pools_decryptWorkSlab);
mempool_destroy(sflc_pools_writeWorkPool);
kmem_cache_destroy(sflc_pools_writeWorkSlab);
mempool_destroy(sflc_pools_pagePool);
bioset_exit(&sflc_pools_bioset);
kmem_cache_destroy(sfold_pools_ivSlab);
mempool_destroy(sfold_pools_decryptWorkPool);
kmem_cache_destroy(sfold_pools_decryptWorkSlab);
mempool_destroy(sfold_pools_writeWorkPool);
kmem_cache_destroy(sfold_pools_writeWorkSlab);
mempool_destroy(sfold_pools_pagePool);
bioset_exit(&sfold_pools_bioset);
}

View file

@ -25,31 +25,31 @@
* A set of memory pools
*/
#ifndef _SFLC_UTILS_POOLS_H_
#define _SFLC_UTILS_POOLS_H_
#ifndef _SFOLD_UTILS_POOLS_H_
#define _SFOLD_UTILS_POOLS_H_
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include "device/device.h"
#include "old/device/device.h"
/*****************************************************
* PUBLIC VARIABLES DECLARATIONS *
*****************************************************/
extern struct bio_set sflc_pools_bioset;
extern mempool_t * sflc_pools_pagePool;
extern mempool_t * sflc_pools_writeWorkPool;
extern mempool_t * sflc_pools_decryptWorkPool;
extern struct kmem_cache * sflc_pools_ivSlab;
extern struct bio_set sfold_pools_bioset;
extern mempool_t * sfold_pools_pagePool;
extern mempool_t * sfold_pools_writeWorkPool;
extern mempool_t * sfold_pools_decryptWorkPool;
extern struct kmem_cache * sfold_pools_ivSlab;
/*****************************************************
* PUBLIC FUNCTIONS PROTOTYPES *
*****************************************************/
int sflc_pools_init(void);
void sflc_pools_exit(void);
int sfold_pools_init(void);
void sfold_pools_exit(void);
#endif /* _SFLC_UTILS_POOLS_H_ */
#endif /* _SFOLD_UTILS_POOLS_H_ */

View file

@ -31,15 +31,15 @@
#include <linux/string.h>
#include "string.h"
#include "log/log.h"
#include "old/utils/string.h"
#include "old/log/log.h"
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
int sflc_str_hexDecode(char * hex, u8 * bin)
int sfold_str_hexDecode(char * hex, u8 * bin)
{
char buf[3];
unsigned len;
@ -64,7 +64,7 @@ int sflc_str_hexDecode(char * hex, u8 * bin)
}
void sflc_str_replaceAll(char * str, char old, char new)
void sfold_str_replaceAll(char * str, char old, char new)
{
int i;

View file

@ -25,8 +25,8 @@
* A collection of utility string functions
*/
#ifndef _SFLC_UTILS_STRING_H_
#define _SFLC_UTILS_STRING_H_
#ifndef _SFOLD_UTILS_STRING_H_
#define _SFOLD_UTILS_STRING_H_
/*****************************************************
* INCLUDE SECTION *
@ -38,8 +38,8 @@
* PUBLIC FUNCTIONS PROTOTYPES *
*****************************************************/
int sflc_str_hexDecode(char * hex, u8 * bin);
void sflc_str_replaceAll(char * str, char old, char new);
int sfold_str_hexDecode(char * hex, u8 * bin);
void sfold_str_replaceAll(char * str, char old, char new);
#endif /* _SFLC_UTILS_STRING_H_ */
#endif /* _SFOLD_UTILS_STRING_H_ */

View file

@ -29,9 +29,9 @@
* INCLUDE SECTION *
*****************************************************/
#include "vector.h"
#include "crypto/rand/rand.h"
#include "log/log.h"
#include "old/utils/vector.h"
#include "old/crypto/rand/rand.h"
#include "old/log/log.h"
/*****************************************************
@ -39,22 +39,22 @@
*****************************************************/
/* Shuffle a vector of u32's with the Fisher-Yates algorithm */
int sflc_vec_u32shuffle(u32 *v, u32 len)
int sfold_vec_u32shuffle(u32 *v, u32 len)
{
u32 i;
for (i = len-1; i >= 1; i--) {
/* Sample a random index from 0 to i (inclusive) */
s32 j = sflc_rand_uniform(i+1);
s32 j = sfold_rand_uniform(i+1);
if (j < 0) {
pr_err("Could not sample j; error %d", j);
return j;
}
/* Swap v[i] and v[j] */
u32 tmp = v[i];
v[i] = v[j];
v[j] = tmp;
/* Swap v[i] and v[j] (without third variable 'cuz we're cool) */
v[i] ^= v[j]; // v[i] <- a XOR b
v[j] ^= v[i]; // v[j] <- b XOR (a XOR b) = a
v[i] ^= v[j]; // v[i] <- (a XOR b) XOR a = b
}
return 0;

View file

@ -25,8 +25,8 @@
* A collection of utility vector functions
*/
#ifndef _SFLC_UTILS_VECTOR_H_
#define _SFLC_UTILS_VECTOR_H_
#ifndef _SFOLD_UTILS_VECTOR_H_
#define _SFOLD_UTILS_VECTOR_H_
/*****************************************************
* INCLUDE SECTION *
@ -39,7 +39,7 @@
*****************************************************/
/* Shuffle a vector of u32's */
int sflc_vec_u32shuffle(u32 *v, u32 len);
int sfold_vec_u32shuffle(u32 *v, u32 len);
#endif /* _SFLC_UTILS_VECTOR_H_ */
#endif /* _SFOLD_UTILS_VECTOR_H_ */

View file

@ -28,42 +28,42 @@
* INCLUDE SECTION *
*****************************************************/
#include "workqueues.h"
#include "log/log.h"
#include "old/utils/workqueues.h"
#include "old/log/log.h"
/*****************************************************
* CONSTANTS *
*****************************************************/
#define SFLC_QUEUES_WRITE_WQ_NAME "sflc_write_workqueue"
#define SFLC_QUEUES_DECRYPT_WQ_NAME "sflc_decrypt_workqueue"
#define SFOLD_QUEUES_WRITE_WQ_NAME "sfold_write_workqueue"
#define SFOLD_QUEUES_DECRYPT_WQ_NAME "sfold_decrypt_workqueue"
/*****************************************************
* PUBLIC VARIABLES DEFINITIONS *
*****************************************************/
struct workqueue_struct * sflc_queues_writeQueue;
struct workqueue_struct * sflc_queues_decryptQueue;
struct workqueue_struct * sfold_queues_writeQueue;
struct workqueue_struct * sfold_queues_decryptQueue;
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
int sflc_queues_init(void)
int sfold_queues_init(void)
{
int err;
/* Write workqueue */
sflc_queues_writeQueue = create_workqueue(SFLC_QUEUES_WRITE_WQ_NAME);
if (!sflc_queues_writeQueue) {
sfold_queues_writeQueue = create_workqueue(SFOLD_QUEUES_WRITE_WQ_NAME);
if (!sfold_queues_writeQueue) {
pr_err("Could not create write workqueue\n");
err = -ENOMEM;
goto err_write_queue;
}
/* Decrypt workqueue */
sflc_queues_decryptQueue = create_workqueue(SFLC_QUEUES_DECRYPT_WQ_NAME);
if (!sflc_queues_decryptQueue) {
sfold_queues_decryptQueue = create_workqueue(SFOLD_QUEUES_DECRYPT_WQ_NAME);
if (!sfold_queues_decryptQueue) {
pr_err("Could not create decrypt workqueue\n");
err = -ENOMEM;
goto err_decrypt_queue;
@ -73,13 +73,13 @@ int sflc_queues_init(void)
err_decrypt_queue:
destroy_workqueue(sflc_queues_writeQueue);
destroy_workqueue(sfold_queues_writeQueue);
err_write_queue:
return err;
}
void sflc_queues_exit(void)
void sfold_queues_exit(void)
{
destroy_workqueue(sflc_queues_decryptQueue);
destroy_workqueue(sflc_queues_writeQueue);
destroy_workqueue(sfold_queues_decryptQueue);
destroy_workqueue(sfold_queues_writeQueue);
}

View file

@ -25,8 +25,8 @@
* A set of workqueues
*/
#ifndef _SFLC_UTILS_QUEUES_H_
#define _SFLC_UTILS_QUEUES_H_
#ifndef _SFOLD_UTILS_QUEUES_H_
#define _SFOLD_UTILS_QUEUES_H_
/*****************************************************
* INCLUDE SECTION *
@ -38,15 +38,15 @@
* PUBLIC VARIABLES DECLARATIONS *
*****************************************************/
extern struct workqueue_struct * sflc_queues_writeQueue;
extern struct workqueue_struct * sflc_queues_decryptQueue;
extern struct workqueue_struct * sfold_queues_writeQueue;
extern struct workqueue_struct * sfold_queues_decryptQueue;
/*****************************************************
* PUBLIC FUNCTIONS PROTOTYPES *
*****************************************************/
int sflc_queues_init(void);
void sflc_queues_exit(void);
int sfold_queues_init(void);
void sfold_queues_exit(void);
#endif /* _SFLC_UTILS_QUEUES_H_ */
#endif /* _SFOLD_UTILS_QUEUES_H_ */

View file

@ -29,12 +29,10 @@
* INCLUDE SECTION *
*****************************************************/
#include <linux/vmalloc.h>
#include "volume.h"
#include "crypto/rand/rand.h"
#include "utils/pools.h"
#include "log/log.h"
#include "old/volume/volume.h"
#include "old/crypto/rand/rand.h"
#include "old/utils/pools.h"
#include "old/log/log.h"
/*****************************************************
* CONSTANTS *
@ -44,8 +42,7 @@
* PRIVATE FUNCTIONS PROTOTYPES *
*****************************************************/
static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op);
static int sflc_vol_reassignLsi(sflc_Volume *vol, u32 lsi, u32 old_psi);
static s32 sfold_vol_mapSlice(sfold_Volume * vol, u32 lsi, int op);
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
@ -53,28 +50,28 @@ static int sflc_vol_reassignLsi(sflc_Volume *vol, u32 lsi, u32 old_psi);
/* Maps a logical 512-byte sector to a physical 512-byte sector. Returns < 0 if error.
* Specifically, if op == READ, and the logical slice is unmapped, -ENXIO is returned. */
s64 sflc_vol_remapSector(sflc_Volume * vol, sector_t log_sector, int op, u32 * psi_out, u32 * off_in_slice_out)
s64 sfold_vol_remapSector(sfold_Volume * vol, sector_t log_sector, int op, u32 * psi_out, u32 * off_in_slice_out)
{
u32 lsi;
u32 off_in_slice;
s32 psi;
sector_t phys_sector;
sflc_Device *dev = vol->dev;
sfold_Device *dev = vol->dev;
/* Start by scaling down to a Shufflecake sector */
log_sector /= SFLC_DEV_SECTOR_SCALE;
log_sector /= SFOLD_DEV_SECTOR_SCALE;
/* Get the logical slice index it belongs to */
lsi = log_sector / SFLC_VOL_LOG_SLICE_SIZE;
lsi = log_sector / SFOLD_VOL_LOG_SLICE_SIZE;
/* Get which block it is within the slice */
off_in_slice = log_sector % SFLC_VOL_LOG_SLICE_SIZE;
off_in_slice = log_sector % SFOLD_VOL_LOG_SLICE_SIZE;
/* Output the off_in_slice */
if (off_in_slice_out) {
*off_in_slice_out = off_in_slice;
}
/* Map it to a physical slice */
psi = sflc_vol_mapSlice(vol, lsi, op);
psi = sfold_vol_mapSlice(vol, lsi, op);
/* -ENXIO is a special case */
if (psi == -ENXIO) {
pr_debug("mapSlice returned -ENXIO: stupid READ\n");
@ -91,20 +88,20 @@ s64 sflc_vol_remapSector(sflc_Volume * vol, sector_t log_sector, int op, u32 * p
}
/* Get the physical sector (the first of every slice contains the IVs) */
phys_sector = ((sector_t)psi * SFLC_DEV_PHYS_SLICE_SIZE) + 1 + off_in_slice;
phys_sector = ((sector_t)psi * SFOLD_DEV_PHYS_SLICE_SIZE) + 1 + off_in_slice;
/* Add the device header */
phys_sector += dev->dev_header_size;
/* Scale it back up to a kernel sector */
phys_sector *= SFLC_DEV_SECTOR_SCALE;
phys_sector *= SFOLD_DEV_SECTOR_SCALE;
return phys_sector;
}
/* Loads (and decrypts) the position map from the volume's header */
int sflc_vol_loadFmap(sflc_Volume * vol)
int sfold_vol_loadFmap(sfold_Volume * vol)
{
sflc_Device * dev = vol->dev;
sfold_Device * dev = vol->dev;
sector_t sector;
struct page * iv_page;
u8 * iv_ptr;
@ -114,12 +111,12 @@ int sflc_vol_loadFmap(sflc_Volume * vol)
int err;
/* Allocate pages */
iv_page = mempool_alloc(sflc_pools_pagePool, GFP_NOIO);
iv_page = mempool_alloc(sfold_pools_pagePool, GFP_NOIO);
if (!iv_page) {
pr_err("Could not allocate IV page\n");
return -ENOMEM;
}
data_page = mempool_alloc(sflc_pools_pagePool, GFP_NOIO);
data_page = mempool_alloc(sfold_pools_pagePool, GFP_NOIO);
if (!data_page) {
pr_err("Could not allocate data page\n");
return -ENOMEM;
@ -148,7 +145,7 @@ int sflc_vol_loadFmap(sflc_Volume * vol)
int i;
for (i = 0; i < dev->vol_header_nr_iv_blocks && lsi < dev->tot_slices; i++) {
/* Load the IV block */
err = sflc_dev_rwSector(dev, iv_page, sector, READ);
err = sfold_dev_rwSector(dev, iv_page, sector, READ);
if (err) {
pr_err("Could not read IV block i=%d at sector %llu; error %d\n", i, sector, err);
goto out;
@ -157,9 +154,9 @@ int sflc_vol_loadFmap(sflc_Volume * vol)
/* Loop over the 256 data blocks */
int j;
for (j = 0; j < SFLC_DEV_SECTOR_TO_IV_RATIO && lsi < dev->tot_slices; j++) {
for (j = 0; j < SFOLD_DEV_SECTOR_TO_IV_RATIO && lsi < dev->tot_slices; j++) {
/* Load the data block */
err = sflc_dev_rwSector(dev, data_page, sector, READ);
err = sfold_dev_rwSector(dev, data_page, sector, READ);
if (err) {
pr_err("Could not read data block i=%d, j=%d at sector %llu; error %d\n", i, j, sector, err);
goto out;
@ -167,7 +164,7 @@ int sflc_vol_loadFmap(sflc_Volume * vol)
sector += 1;
/* Decrypt it in place */
err = sflc_sk_decrypt(vol->skctx, data_ptr, data_ptr, SFLC_DEV_SECTOR_SIZE, (iv_ptr + j*SFLC_SK_IV_LEN));
err = sfold_sk_decrypt(vol->skctx, data_ptr, data_ptr, SFOLD_DEV_SECTOR_SIZE, (iv_ptr + j*SFOLD_SK_IV_LEN));
if (err) {
pr_err("Could not decrypt data block i=%d, j=%d at sector %llu; error %d\n", i, j, sector, err);
goto out;
@ -175,42 +172,22 @@ int sflc_vol_loadFmap(sflc_Volume * vol)
/* Loop over the 1024 fmap entries in this data block */
int k;
for (k = 0; k < SFLC_VOL_HEADER_MAPPINGS_PER_BLOCK && lsi < dev->tot_slices; k++) {
for (k = 0; k < SFOLD_VOL_HEADER_MAPPINGS_PER_BLOCK && lsi < dev->tot_slices; k++) {
/* An entry is just a single big-endian PSI, the LSI
is implicitly the index of this entry */
__be32 * be_psi = (void *) (data_ptr + (k * sizeof(__be32)));
u32 psi = be32_to_cpu(*be_psi);
/* If unassigned, just move on */
if (psi == SFLC_VOL_FMAP_INVALID_PSI) {
vol->fmap[lsi] = psi;
/* Next iteration */
lsi += 1;
continue;
/* Add mapping to the volume's fmap */
vol->fmap[lsi] = psi;
/* Also add it to the device's rmap and to the count, if LSI is actually mapped */
if (psi != SFOLD_VOL_FMAP_INVALID_PSI) {
sfold_dev_markPsiTaken(dev, psi, vol->vol_idx);
vol->mapped_slices += 1;
}
/* If already assigned to lower-order volume, sample a new one */
if (!sflc_dev_isPsiFree(dev, psi)) {
pr_warn("Corruption of volume %d: LSI %u was evicted from PSI %u\n",
vol->vol_idx, lsi, psi);
err = sflc_vol_reassignLsi(vol, lsi, psi);
if (err) {
pr_err("Could not reassign evicted LSI; "
"error %d\n", err);
goto out;
}
/* Next iteration */
lsi += 1;
} else {
/* Just assign */
vol->fmap[lsi] = psi;
sflc_dev_markPsiTaken(dev, psi, vol->vol_idx);
vol->mapped_slices += 1;
/* Next iteration */
lsi += 1;
}
/* Next iteration */
lsi += 1;
}
}
}
@ -225,16 +202,16 @@ out:
kunmap(iv_page);
kunmap(data_page);
/* Free them */
mempool_free(iv_page, sflc_pools_pagePool);
mempool_free(data_page, sflc_pools_pagePool);
mempool_free(iv_page, sfold_pools_pagePool);
mempool_free(data_page, sfold_pools_pagePool);
return err;
}
/* Stores (and encrypts) the position map to the volume's header */
int sflc_vol_storeFmap(sflc_Volume * vol)
int sfold_vol_storeFmap(sfold_Volume * vol)
{
sflc_Device * dev = vol->dev;
sfold_Device * dev = vol->dev;
sector_t sector;
struct page * iv_page;
u8 * iv_ptr;
@ -244,12 +221,12 @@ int sflc_vol_storeFmap(sflc_Volume * vol)
int err;
/* Allocate pages */
iv_page = mempool_alloc(sflc_pools_pagePool, GFP_NOIO);
iv_page = mempool_alloc(sfold_pools_pagePool, GFP_NOIO);
if (!iv_page) {
pr_err("Could not allocate IV page\n");
return -ENOMEM;
}
data_page = mempool_alloc(sflc_pools_pagePool, GFP_NOIO);
data_page = mempool_alloc(sfold_pools_pagePool, GFP_NOIO);
if (!data_page) {
pr_err("Could not allocate data page\n");
return -ENOMEM;
@ -278,13 +255,13 @@ int sflc_vol_storeFmap(sflc_Volume * vol)
int i;
for (i = 0; i < dev->vol_header_nr_iv_blocks && lsi < dev->tot_slices; i++) {
/* Fill the IV block with random bytes */
err = sflc_rand_getBytes(iv_ptr, SFLC_DEV_SECTOR_SIZE);
err = sfold_rand_getBytes(iv_ptr, SFOLD_DEV_SECTOR_SIZE);
if (err) {
pr_err("Could not sample random IV for block i=%d at sector %llu; error %d\n", i, sector, err);
goto out;
}
/* Store it on the disk (before it gets changed by the encryption) */
err = sflc_dev_rwSector(dev, iv_page, sector, WRITE);
err = sfold_dev_rwSector(dev, iv_page, sector, WRITE);
if (err) {
pr_err("Could not read IV block i=%d at sector %llu; error %d\n", i, sector, err);
goto out;
@ -293,10 +270,10 @@ int sflc_vol_storeFmap(sflc_Volume * vol)
/* Loop over the 256 data blocks */
int j;
for (j = 0; j < SFLC_DEV_SECTOR_TO_IV_RATIO && lsi < dev->tot_slices; j++) {
for (j = 0; j < SFOLD_DEV_SECTOR_TO_IV_RATIO && lsi < dev->tot_slices; j++) {
/* Loop over the 1024 fmap entries that fit in this data block */
int k;
for (k = 0; k < SFLC_VOL_HEADER_MAPPINGS_PER_BLOCK && lsi < dev->tot_slices; k++) {
for (k = 0; k < SFOLD_VOL_HEADER_MAPPINGS_PER_BLOCK && lsi < dev->tot_slices; k++) {
/* Get the PSI for the current LSI */
u32 psi = vol->fmap[lsi];
/* Write it into the block as big-endian */
@ -308,14 +285,14 @@ int sflc_vol_storeFmap(sflc_Volume * vol)
}
/* Encrypt it in place */
err = sflc_sk_encrypt(vol->skctx, data_ptr, data_ptr, SFLC_DEV_SECTOR_SIZE, (iv_ptr + j*SFLC_SK_IV_LEN));
err = sfold_sk_encrypt(vol->skctx, data_ptr, data_ptr, SFOLD_DEV_SECTOR_SIZE, (iv_ptr + j*SFOLD_SK_IV_LEN));
if (err) {
pr_err("Could not encrypt data block i=%d, j=%d at sector %llu; error %d\n", i, j, sector, err);
goto out;
}
/* Store the data block */
err = sflc_dev_rwSector(dev, data_page, sector, WRITE);
err = sfold_dev_rwSector(dev, data_page, sector, WRITE);
if (err) {
pr_err("Could not write data block i=%d, j=%d at sector %llu; error %d\n", i, j, sector, err);
goto out;
@ -334,8 +311,8 @@ out:
kunmap(iv_page);
kunmap(data_page);
/* Free them */
mempool_free(iv_page, sflc_pools_pagePool);
mempool_free(data_page, sflc_pools_pagePool);
mempool_free(iv_page, sfold_pools_pagePool);
mempool_free(data_page, sfold_pools_pagePool);
return err;
}
@ -344,10 +321,10 @@ out:
* PRIVATE FUNCTIONS DEFINITIONS *
*****************************************************/
static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op)
static s32 sfold_vol_mapSlice(sfold_Volume * vol, u32 lsi, int op)
{
s32 psi;
sflc_Device * dev = vol->dev;
sfold_Device * dev = vol->dev;
/* Lock the volume's forward map */
if (mutex_lock_interruptible(&vol->fmap_lock)) {
@ -356,7 +333,7 @@ static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op)
}
/* If slice is already mapped, just return the mapping */
if (vol->fmap[lsi] != SFLC_VOL_FMAP_INVALID_PSI) {
if (vol->fmap[lsi] != SFOLD_VOL_FMAP_INVALID_PSI) {
mutex_unlock(&vol->fmap_lock);
return vol->fmap[lsi];
}
@ -377,7 +354,7 @@ static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op)
}
/* Get a free physical slice */
psi = sflc_dev_getNextRandomFreePsi(dev);
psi = sfold_dev_getNextRandomFreePsi(dev);
if (psi < 0) {
pr_err("Could not get a random free physical slice; error %d\n", psi);
mutex_unlock(&dev->slices_lock);
@ -389,7 +366,7 @@ static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op)
vol->fmap[lsi] = psi;
vol->mapped_slices += 1;
/* And in the device's rmap */
sflc_dev_markPsiTaken(dev, psi, vol->vol_idx);
sfold_dev_markPsiTaken(dev, psi, vol->vol_idx);
/* Unlock both maps */
mutex_unlock(&dev->slices_lock);
@ -397,58 +374,3 @@ static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op)
return psi;
}
static int sflc_vol_reassignLsi(sflc_Volume *vol, u32 lsi, u32 old_psi)
{
sflc_Device *dev = vol->dev;
s32 new_psi;
// void *vma;
int err;
// /* Allocate array holding the raw PSI */
// vma = vmalloc(SFLC_DEV_PHYS_SLICE_SIZE * SFLC_DEV_SECTOR_SIZE);
// if (!vma) {
// pr_err("Could not allocate VMA for raw PSI");
// return -ENOMEM;
// }
/* Sample new PSI */
new_psi = sflc_dev_getNextRandomFreePsi(dev);
if (new_psi < 0) {
err = new_psi;
pr_err("Could not sample new PSI for evicted LSI; "
"error %d\n", err);
goto out;
}
// /* Read PSI contents */
// err = sflc_dev_rwPsi(dev, vma, old_psi, READ);
// if (err) {
// pr_err("Could not read PSI; error %d", err);
// goto out;
// }
//
// /* Write them to new location */
// err = sflc_dev_rwPsi(dev, vma, new_psi, WRITE);
// if (err) {
// pr_err("Could not write PSI; error %d", err);
// goto out;
// }
/* Assign */
vol->fmap[lsi] = new_psi;
sflc_dev_markPsiTaken(dev, new_psi, vol->vol_idx);
vol->mapped_slices += 1;
pr_notice("Volume %d reassign LSI %u -> PSI %u",
vol->vol_idx, lsi, new_psi);
/* No prob */
err = 0;
out:
// vfree(vma);
return err;
}

View file

@ -29,10 +29,10 @@
* INCLUDE SECTION *
*****************************************************/
#include "volume.h"
#include "utils/pools.h"
#include "utils/workqueues.h"
#include "log/log.h"
#include "old/volume/volume.h"
#include "old/utils/pools.h"
#include "old/utils/workqueues.h"
#include "old/log/log.h"
/*****************************************************
* CONSTANTS *
@ -47,7 +47,7 @@
*****************************************************/
/* Remaps the underlying block device and the sector number */
int sflc_vol_remapBioFast(sflc_Volume * vol, struct bio * bio)
int sfold_vol_remapBioFast(sfold_Volume * vol, struct bio * bio)
{
s64 phys_sector;
int err;
@ -56,7 +56,7 @@ int sflc_vol_remapBioFast(sflc_Volume * vol, struct bio * bio)
bio_set_dev(bio, vol->dev->bdev->bdev);
/* Remap the starting sector (we don't care about PSI and off_in_slice). Also no slice allocation */
phys_sector = sflc_vol_remapSector(vol, bio->bi_iter.bi_sector, READ, NULL, NULL);
phys_sector = sfold_vol_remapSector(vol, bio->bi_iter.bi_sector, READ, NULL, NULL);
if (phys_sector < 0) {
err = (int) phys_sector;
pr_err("Could not remap sector; error %d\n", err);
@ -68,18 +68,18 @@ int sflc_vol_remapBioFast(sflc_Volume * vol, struct bio * bio)
}
/* Submits the bio to the device's workqueue */
int sflc_vol_processBio(sflc_Volume * vol, struct bio * bio)
int sfold_vol_processBio(sfold_Volume * vol, struct bio * bio)
{
sflc_vol_WriteWork * write_work;
sfold_vol_WriteWork * write_work;
/* If it is a READ, no need to pass it through a workqueue */
if (bio_data_dir(bio) == READ) {
sflc_vol_doRead(vol, bio);
sfold_vol_doRead(vol, bio);
return 0;
}
/* Allocate writeWork structure */
write_work = mempool_alloc(sflc_pools_writeWorkPool, GFP_NOIO);
write_work = mempool_alloc(sfold_pools_writeWorkPool, GFP_NOIO);
if (!write_work) {
pr_err("Failed allocation of work structure\n");
return -ENOMEM;
@ -88,10 +88,10 @@ int sflc_vol_processBio(sflc_Volume * vol, struct bio * bio)
/* Set fields */
write_work->vol = vol;
write_work->orig_bio = bio;
INIT_WORK(&write_work->work, sflc_vol_doWrite);
INIT_WORK(&write_work->work, sfold_vol_doWrite);
/* Enqueue */
queue_work(sflc_queues_writeQueue, &write_work->work);
queue_work(sfold_queues_writeQueue, &write_work->work);
return 0;
}

Some files were not shown because too many files have changed in this diff Show more