mirror of
https://codeberg.org/shufflecake/shufflecake-c.git
synced 2025-12-28 14:44:56 -05:00
Merge pull request 'release: v0.5.5' (#153) from dev into main
Reviewed-on: https://codeberg.org/shufflecake/shufflecake-c/pulls/153
This commit is contained in:
commit
635fcbd228
17 changed files with 313 additions and 62 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
|
@ -7,6 +7,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
|
||||
## [0.5.5] - 2025-09-24
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed issue of bad memory allocation on some archs due to the improper use of vmalloc. The fix is experimental, as we could not reproduce the bug on RISCV architecture, so feedback is welcome.
|
||||
|
||||
### Added
|
||||
|
||||
- Added explanation on how to deal with unsigned kernel modules with Secure Boot in README.md.
|
||||
|
||||
|
||||
## [0.5.4] - 2025-09-06
|
||||
|
||||
### Fixed
|
||||
|
|
|
|||
27
README.md
27
README.md
|
|
@ -1,5 +1,5 @@
|
|||
[](https://codeberg.org/shufflecake/shufflecake-c)
|
||||
[](https://codeberg.org/shufflecake/shufflecake-c/releases/tag/v0.5.4)
|
||||
[](https://codeberg.org/shufflecake/shufflecake-c/releases/tag/v0.5.5)
|
||||
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||
[](https://eprint.iacr.org/2023/1529)
|
||||
[](https://shufflecake.net/)
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
|
||||
|
||||
# Shufflecake - Full C Implementation - v0.5.4
|
||||
# Shufflecake - Full C Implementation - v0.5.5
|
||||
|
||||
_Shufflecake_ is a plausible deniability (hidden storage) layer for Linux. You can consider Shufflecake a spiritual successor of tools like TrueCrypt and VeraCrypt, but vastly improved, both in terms of security and functionality. Official website: <https://www.shufflecake.net>.
|
||||
|
||||
|
|
@ -40,6 +40,7 @@ __WARNING__: Shufflecake is a strong encryption and plausible deniability soluti
|
|||
- [Enabling R/W Workqueues](#workqueues)
|
||||
- [Volume Corruption Mitigation](#mitigcorr)
|
||||
- [Providing Passwords Non-Interactively](#passwordnonint)
|
||||
- [Using with Secure Boot](#secureboot)
|
||||
- [Changelog](#changelog)
|
||||
- [Bugs](#bugs)
|
||||
- [Maintainers](#maintainers)
|
||||
|
|
@ -114,6 +115,8 @@ sudo modprobe dm_mod
|
|||
sudo insmod dm-sflc.ko
|
||||
```
|
||||
|
||||
(Note: if you have Secure Boot enabled, this step might fail. See [this section](#secureboot) for workarounds.)
|
||||
|
||||
At this point you can run the `shufflecake` command as `sudo shufflecake <action> <block_device>`.
|
||||
|
||||
When finished, you can unload the module with
|
||||
|
|
@ -229,7 +232,7 @@ This section documents advanced use cases and features of Shufflecake.
|
|||
|
||||
Once a new slice is assigned to a Shufflecake volume, that assignment is static: that slice stays in the position map of that volume even if all its content (i.e. the files in the filesystem area mapped onto the slice) is deleted. On the long run, this can lead to a situation where there are no free available slices left for Shufflecake volume allocation, even if the filesystems of the volumes show plenty of available virtual space. In order to avoid this, Shufflecake implements slice garbage collection on `close`: all slices that only contain sectors unused by the filesystem on top are marked as free and removed from the slice mapping.
|
||||
|
||||
Usually, filesystems do not mark unused sectors automatically. To force this, call `fstrim` inside the filesystems of the open volumes, and then `close` the underlying device. Once the device is `open`ed again, those slices will be newly available for allocation. This should be done once in a while, especially after deleting large amount of data from the volumes.
|
||||
Usually, filesystems do not mark unused sectors automatically. To force this, call `fstrim` inside the filesystems of the open volumes, and then `close` the underlying device. Once the device is `open`ed again, those slices will be newly available for allocation. This should be done every once in a while, especially after deleting large amount of data from the volumes.
|
||||
|
||||
|
||||
#### Enabling R/W Workqueues <a id="user-content-workqueues"></a>
|
||||
|
|
@ -280,12 +283,27 @@ sudo ./shufflecake -n 3 init <block_device> < passwords.txt
|
|||
Both methods works with the `init` and `open` action, and we do not have current plans to change this behavior for the near future.
|
||||
|
||||
|
||||
#### Using with Secure Boot <a id="user-content-secureboot"></a>
|
||||
|
||||
If you have Secure Boot enabled, then your kernel will most likely refuse to load an unsigned kernel module, such as `dm-sflc.ko`. You can confirm that that is the case if `insmod dm-sflc.ko` returns an error like "Key was rejected by service" (the kernel logs in `dmesg` might have more information). The only two solutions are:
|
||||
|
||||
1. You (temporarily) disable Secure Boot.
|
||||
|
||||
2. You enroll your own MOK (machine-owner key) and sign the kernel module `dm-sflc.ko` with it; you may need to recompile before signing.
|
||||
|
||||
Both these options have security implications, of course, which you should be aware of. We cannot provide a step-by-step guide for option 2, because the procedure is distro-specific. However, enrolling a MOK is a relatively standard operation, that is well supported by many distributions, so online guides should be easy to find.
|
||||
|
||||
|
||||
|
||||
|
||||
## Changelog <a id="user-content-changelog"></a>
|
||||
|
||||
Please see the file `CHANGELOG.md` for a detailed history of changes.
|
||||
See the file `CHANGELOG.md` for a detailed history of changes.
|
||||
|
||||
## [0.5.5] - 2025-09-24
|
||||
|
||||
- Experimental fix for the issue of bad memory allocation on some archs due to the improper use of vmalloc.
|
||||
- Added instructions on how to deal with unsigned kernel modules with Secure Boot on.
|
||||
|
||||
## [0.5.4] - 2025-09-06
|
||||
|
||||
|
|
@ -323,7 +341,6 @@ Bugs and other issues are tracked at <https://codeberg.org/shufflecake/shuffleca
|
|||
|
||||
Outstanding known bugs and/or limitations:
|
||||
|
||||
- Opening volumes does not work on certain architectures (see issue <https://codeberg.org/shufflecake/shufflecake-c/issues/143>).
|
||||
- Crash consistency is currently not guaranteed (see issue <https://codeberg.org/shufflecake/shufflecake-c/issues/136>).
|
||||
- Only a maximum of 15 volumes per device is supported.
|
||||
- There is (currently) no protection against multi-snapshot attacks.
|
||||
|
|
|
|||
|
|
@ -92,34 +92,125 @@ int sflite_crypt_block_page(struct crypto_skcipher *tfm, struct page *src_page,
|
|||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
/*
|
||||
*----------------------------
|
||||
* Memory buffer enc/dec
|
||||
*----------------------------
|
||||
*/
|
||||
|
||||
/* Setup sg list: allocate, if more than one entry, otherwise assign to prealloc_sg */
|
||||
static int sgtable_setup(struct sg_table *sgt, struct scatterlist *prealloc_sg,
|
||||
unsigned nents, gfp_t gfp_flags)
|
||||
{
|
||||
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 (nents > 1) {
|
||||
err = sg_alloc_table(sgt, nents, gfp_flags);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
src_buf += SFLITE_BLOCK_SIZE;
|
||||
dst_buf += SFLITE_BLOCK_SIZE;
|
||||
} else {
|
||||
sg_init_table(prealloc_sg, 1);
|
||||
sgt->sgl = prealloc_sg;
|
||||
sgt->nents = sgt->orig_nents = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Populate the sg list: every sg entry will map to a page */
|
||||
static void sgtable_populate(struct sg_table *sgt, void *buf, unsigned buf_len)
|
||||
{
|
||||
struct scatterlist *sg;
|
||||
unsigned i, off = offset_in_page(buf);
|
||||
bool is_vmalloc = is_vmalloc_addr(buf);
|
||||
|
||||
for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) {
|
||||
struct page *page;
|
||||
unsigned int len = min(PAGE_SIZE - off, buf_len);
|
||||
|
||||
if (is_vmalloc)
|
||||
page = vmalloc_to_page(buf);
|
||||
else
|
||||
page = virt_to_page(buf);
|
||||
|
||||
sg_set_page(sg, page, len, off);
|
||||
|
||||
off = 0;
|
||||
buf += len;
|
||||
buf_len -= len;
|
||||
}
|
||||
WARN_ON(buf_len != 0);
|
||||
}
|
||||
|
||||
/* Teardown sg list: free if necessary */
|
||||
static void sgtable_teardown(struct sg_table *sgt)
|
||||
{
|
||||
if (sgt->orig_nents > 1)
|
||||
sg_free_table(sgt);
|
||||
}
|
||||
|
||||
|
||||
/* Encrypt-decrypt consecutive blocks in a memory buffer (can be vmalloc'ed) */
|
||||
int sflite_crypt_blocks_buf(struct crypto_skcipher *tfm, void *src_buf, void *dst_buf,
|
||||
u64 num_blocks, u64 first_pblk_num, int rw, gfp_t gfp_flags)
|
||||
{
|
||||
struct sg_table sgt_dst, sgt_src, *p_sgt_dst;
|
||||
struct scatterlist prealloc_sg_dst, prealloc_sg_src;
|
||||
unsigned nents;
|
||||
u64 pblk_num;
|
||||
bool is_inplace;
|
||||
int err = 0;
|
||||
|
||||
/* Use same sg_table if in-place */
|
||||
is_inplace = (src_buf == dst_buf);
|
||||
p_sgt_dst = is_inplace ? &sgt_src : &sgt_dst;
|
||||
|
||||
/* Setup sg_table.
|
||||
* Since both SFLITE_BLOCK_SIZE and PAGE_SIZE are powers of 2, one
|
||||
* has to be multiple of the other; also, we enforce that blocks start
|
||||
* to be written from the start of the page (true for the PosMap);
|
||||
* therefore, a single block will span exactly
|
||||
* ceil(SFLITE_BLOCK_SIZE / PAGE_SIZE) pages.
|
||||
* If this is > 1, we make no effort to detect contiguous pages,
|
||||
* for simplicity. */
|
||||
BUG_ON((offset_in_page(src_buf) % SFLITE_BLOCK_SIZE) ||
|
||||
(offset_in_page(dst_buf) % SFLITE_BLOCK_SIZE));
|
||||
nents = DIV_ROUND_UP(SFLITE_BLOCK_SIZE, PAGE_SIZE);
|
||||
err = sgtable_setup(&sgt_src, &prealloc_sg_src, nents, gfp_flags);
|
||||
if (err) {
|
||||
DMERR("Could not setup sg_table src");
|
||||
sgtable_teardown(&sgt_src);
|
||||
return err;
|
||||
}
|
||||
if (!is_inplace) {
|
||||
err = sgtable_setup(&sgt_dst, &prealloc_sg_dst, nents, gfp_flags);
|
||||
if (err) {
|
||||
DMERR("Could not setup sg_table dst");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Encrypt every block separately, with its own IV */
|
||||
for (pblk_num = first_pblk_num;
|
||||
pblk_num < first_pblk_num + num_blocks;
|
||||
pblk_num++) {
|
||||
sgtable_populate(&sgt_src, src_buf, SFLITE_BLOCK_SIZE);
|
||||
if (!is_inplace)
|
||||
sgtable_populate(&sgt_dst, dst_buf, SFLITE_BLOCK_SIZE);
|
||||
|
||||
err = crypt_sg(tfm, sgt_src.sgl, p_sgt_dst->sgl, pblk_num, rw);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
src_buf += SFLITE_BLOCK_SIZE;
|
||||
dst_buf += SFLITE_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
out:
|
||||
if (!is_inplace)
|
||||
sgtable_teardown(&sgt_dst);
|
||||
sgtable_teardown(&sgt_src);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ void sflite_flush_work_fn(struct work_struct *work)
|
|||
goto endio;
|
||||
}
|
||||
// Just flush the position map: this function sleeps.
|
||||
err = sflite_flush_posmap(svol);
|
||||
err = sflite_flush_posmap(svol, GFP_NOIO);
|
||||
if (err) {
|
||||
DMERR("Could not flush position map; error %d", err);
|
||||
bi_status = BLK_STS_IOERR;
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ static int __send_empty_flush(struct sflite_volume *svol)
|
|||
return sflc_dm_io(&req, 1, ®ion, NULL);
|
||||
}
|
||||
|
||||
static int __serialise_and_encrypt_posmap_blocks(struct sflite_volume *svol, u32 i, u32 j)
|
||||
static int __serialise_and_encrypt_posmap_blocks(struct sflite_volume *svol, u32 i, u32 j, gfp_t gfp_flags)
|
||||
{
|
||||
u32 first_lsi = i * SFLITE_PSIS_PER_BLOCK;
|
||||
u32 last_lsi = min(j * SFLITE_PSIS_PER_BLOCK, svol->sdev->tot_slices);
|
||||
|
|
@ -195,17 +195,17 @@ static int __serialise_and_encrypt_posmap_blocks(struct sflite_volume *svol, u32
|
|||
}
|
||||
|
||||
// Encrypt `crypt_entries` in-place
|
||||
return sflite_crypt_blocks_vm(svol->tfm,
|
||||
return sflite_crypt_blocks_buf(svol->tfm,
|
||||
start_ptr, start_ptr,
|
||||
j - i,
|
||||
(SFLITE_POSMAP_START_SECTOR(svol) >> SFLITE_BLOCK_SHIFT) + i,
|
||||
WRITE);
|
||||
WRITE, gfp_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously store (and flush) all the dirty posmap blocks.
|
||||
*/
|
||||
int sflite_flush_posmap(struct sflite_volume *svol)
|
||||
int sflite_flush_posmap(struct sflite_volume *svol, gfp_t gfp_flags)
|
||||
{
|
||||
struct sflite_device *sdev = svol->sdev;
|
||||
struct dm_io_region region;
|
||||
|
|
@ -228,8 +228,8 @@ int sflite_flush_posmap(struct sflite_volume *svol)
|
|||
break;
|
||||
j = find_next_zero_bit(svol->posmap.dirty_bitmap, bitmap_bits, i);
|
||||
|
||||
// Encrypt from block i to j (exclusive)
|
||||
err = __serialise_and_encrypt_posmap_blocks(svol, i, j);
|
||||
// Encrypt from block i (inclusive) to j (exclusive)
|
||||
err = __serialise_and_encrypt_posmap_blocks(svol, i, j, gfp_flags);
|
||||
if (unlikely(err))
|
||||
break;
|
||||
|
||||
|
|
@ -304,15 +304,16 @@ static int __read_encrypted_posmap(struct sflite_volume *svol)
|
|||
|
||||
/**
|
||||
* 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 (only once, at the end).
|
||||
* resolve it locally by sampling a new PSI.
|
||||
* Returns a boolean (by ref) signalling whether the posmap had corruption.
|
||||
*/
|
||||
static int __deserialise_and_sanitise_posmap(struct sflite_volume *svol)
|
||||
static int __deserialise_and_sanitise_posmap_local(struct sflite_volume *svol, bool *had_corruption)
|
||||
{
|
||||
struct sflite_device *sdev = svol->sdev;
|
||||
bool had_corruption = false;
|
||||
int err;
|
||||
|
||||
u32 lsi;
|
||||
*had_corruption = false;
|
||||
for (lsi = 0; lsi < sdev->tot_slices; lsi++) {
|
||||
/* De-serialise posmap entry */
|
||||
__be32 *be_psi = (__be32*) (svol->posmap.entries + lsi);
|
||||
|
|
@ -338,16 +339,12 @@ static int __deserialise_and_sanitise_posmap(struct sflite_volume *svol)
|
|||
err = __peek_next_free_psi(sdev, &psi);
|
||||
if (err)
|
||||
return err;
|
||||
had_corruption = sanitised = true;
|
||||
*had_corruption = sanitised = true;
|
||||
}
|
||||
/* Whether sanitised or not, create the mapping locally */
|
||||
__create_local_slice_mapping(svol, lsi, psi, sanitised); // Set dirty bitmap only if PSI has just been sampled
|
||||
}
|
||||
|
||||
// Only write back at the end, if at least one sanitisation happened
|
||||
if (had_corruption)
|
||||
err = sflite_flush_posmap(svol);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -357,8 +354,9 @@ static int __deserialise_and_sanitise_posmap(struct sflite_volume *svol)
|
|||
* (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.
|
||||
*/
|
||||
int sflite_load_and_sanitise_posmap(struct sflite_volume *svol)
|
||||
int sflite_load_and_sanitise_posmap(struct sflite_volume *svol, gfp_t gfp_flags)
|
||||
{
|
||||
bool had_corruption;
|
||||
int err;
|
||||
|
||||
/* Read raw posmap from disk onto `crypt_entries` */
|
||||
|
|
@ -367,18 +365,25 @@ int sflite_load_and_sanitise_posmap(struct sflite_volume *svol)
|
|||
return err;
|
||||
|
||||
/* Decrypt from `crypt_entries` onto cleartext `entries` */
|
||||
err = sflite_crypt_blocks_vm(svol->tfm, svol->posmap.crypt_entries, svol->posmap.entries,
|
||||
err = sflite_crypt_blocks_buf(svol->tfm, svol->posmap.crypt_entries, svol->posmap.entries,
|
||||
svol->sdev->posmap_size_blocks,
|
||||
SFLITE_POSMAP_START_SECTOR(svol) >> SFLITE_BLOCK_SHIFT,
|
||||
READ);
|
||||
READ, gfp_flags);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Deserialise and sanitise as you go */
|
||||
err = __deserialise_and_sanitise_posmap(svol);
|
||||
err = __deserialise_and_sanitise_posmap_local(svol, &had_corruption);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
// Write back if at least one sanitisation happened
|
||||
if (had_corruption) {
|
||||
err = sflite_flush_posmap(svol, gfp_flags);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
// print_hex_dump(KERN_CRIT, "posmap(REV) ", DUMP_PREFIX_OFFSET, 32, 4, svol->posmap.entries, 4*sdev->tot_slices, false);
|
||||
// msleep(2000);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
// Only to import the definition of struct sflc_volume and the args struct
|
||||
#include "sflc.h"
|
||||
|
||||
#include <generated/uapi/linux/version.h>
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------
|
||||
|
|
@ -135,9 +137,13 @@ static int sflite_map(struct dm_target *ti, struct bio *bio)
|
|||
if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) {
|
||||
/* Ensure the discard request falls within a single slice */
|
||||
if (unlikely(bio->bi_iter.bi_size != SFLITE_BLOCK_SIZE * SFLITE_SLICE_SCALE)) {
|
||||
DMINFO("Wrong discard bio size: %u", bio->bi_iter.bi_size);
|
||||
// TODO investigate where these are coming from
|
||||
//bio->bi_status = BLK_STS_INVAL; // BUG: this only seems to work on recent (>6.8) kernels
|
||||
DMINFO("Wrong discard bio size: %u", bio->bi_iter.bi_size); // TODO investigate where these are coming from
|
||||
#if LINUX_VERSION_MAJOR >= 6 && LINUX_VERSION_PATCHLEVEL >= 11
|
||||
bio->bi_status = BLK_STS_INVAL;
|
||||
#else
|
||||
bio->bi_status = BLK_STS_NOTSUPP;
|
||||
#endif
|
||||
|
||||
bio_endio(bio);
|
||||
return DM_MAPIO_SUBMITTED;
|
||||
}
|
||||
|
|
@ -145,7 +151,11 @@ static int sflite_map(struct dm_target *ti, struct bio *bio)
|
|||
/* Ensure the logical block number is aligned with the beginning of a slice */
|
||||
if (unlikely(lblk_num % SFLITE_SLICE_SCALE != 0)) {
|
||||
DMWARN("Unaligned discard bio!");
|
||||
//bio->bi_status = BLK_STS_INVAL; // BUG: this only seems to work on recent (>6.8) kernels
|
||||
#if LINUX_VERSION_MAJOR >= 6 && LINUX_VERSION_PATCHLEVEL >= 11
|
||||
bio->bi_status = BLK_STS_INVAL;
|
||||
#else
|
||||
bio->bi_status = BLK_STS_NOTSUPP;
|
||||
#endif
|
||||
bio_endio(bio);
|
||||
return DM_MAPIO_SUBMITTED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,14 +67,14 @@ void sflite_flush_work_fn(struct work_struct *work);
|
|||
void sflite_discard_work_fn(struct work_struct *work);
|
||||
|
||||
/* Position map */
|
||||
int sflite_load_and_sanitise_posmap(struct sflite_volume *svol);
|
||||
int sflite_load_and_sanitise_posmap(struct sflite_volume *svol, gfp_t gfp_flags);
|
||||
int sflite_create_local_slice_mapping(struct sflite_volume *svol, u32 lsi, u32 *psi);
|
||||
int sflite_destroy_local_slice_mapping(struct sflite_volume *svol, u32 lsi);
|
||||
int sflite_flush_posmap(struct sflite_volume *svol);
|
||||
int sflite_flush_posmap(struct sflite_volume *svol, gfp_t gfp_flags);
|
||||
|
||||
/* 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_blocks_buf(struct crypto_skcipher *tfm, void *src_buf, void *dst_buf,
|
||||
u64 num_blocks, u64 first_pblk_num, int rw, gfp_t gfp_flags);
|
||||
int sflite_crypt_block_page(struct crypto_skcipher *tfm, struct page *src_page,
|
||||
struct page *dst_page, u64 pblk_num, int rw);
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/version.h>
|
||||
#include "sflc_lite.h"
|
||||
#include "sflc.h"
|
||||
|
||||
|
|
@ -98,7 +99,7 @@ struct sflc_volume_base *sflite_vol_ctr(struct sflc_device_base *sd_base,
|
|||
goto bad_posmap_dirty_bitmap_alloc;
|
||||
}
|
||||
/* Load from disk */
|
||||
err = sflite_load_and_sanitise_posmap(svol);
|
||||
err = sflite_load_and_sanitise_posmap(svol, GFP_KERNEL);
|
||||
if (err) {
|
||||
DMERR("Could not load position map from disk; error %d", err);
|
||||
goto bad_posmap_load;
|
||||
|
|
@ -115,7 +116,9 @@ struct sflc_volume_base *sflite_vol_ctr(struct sflc_device_base *sd_base,
|
|||
ti->max_io_len = SFLITE_BLOCK_SCALE;
|
||||
ti->flush_supported = true;
|
||||
ti->num_flush_bios = 1;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) // temporary workaround for older kernels - TODO
|
||||
ti->max_discard_granularity = SFLITE_BLOCK_SIZE * SFLITE_SLICE_SCALE;
|
||||
#endif
|
||||
ti->discards_supported = true;
|
||||
ti->num_discard_bios = 1;
|
||||
ti->num_secure_erase_bios = 0;
|
||||
|
|
@ -153,7 +156,7 @@ void sflite_vol_dtr(struct sflc_volume_base *sv_base)
|
|||
|
||||
/* Flush on close */
|
||||
if (!down_write_killable(&svol->posmap.flush_lock)) {
|
||||
sflite_flush_posmap(svol);
|
||||
sflite_flush_posmap(svol, GFP_KERNEL);
|
||||
up_write(&svol->posmap.flush_lock);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
#define SFLC_VER_MAJOR 0
|
||||
#define SFLC_VER_MINOR 5
|
||||
#define SFLC_VER_REVISION 4
|
||||
#define SFLC_VER_REVISION 5
|
||||
#define SFLC_VER_SPECIAL ""
|
||||
|
||||
#define STRINGIFY0(s) # s
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 2.3 KiB |
BIN
resources/images/badges/badge_version_0.5.5.png
Normal file
BIN
resources/images/badges/badge_version_0.5.5.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
|
|
@ -29,8 +29,8 @@
|
|||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.7438272"
|
||||
inkscape:cx="235.98425"
|
||||
inkscape:cy="228.69516"
|
||||
inkscape:cx="236.3487"
|
||||
inkscape:cy="229.05961"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1377"
|
||||
inkscape:window-x="0"
|
||||
|
|
@ -333,7 +333,7 @@
|
|||
height="5.2916675"
|
||||
x="61.548569"
|
||||
y="79.569435"
|
||||
inkscape:export-filename="badge_version_0.5.4.png"
|
||||
inkscape:export-filename="badge_version_0.5.5.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96" />
|
||||
<text
|
||||
|
|
@ -364,7 +364,7 @@
|
|||
id="tspan462"
|
||||
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.183262"
|
||||
x="79.882088"
|
||||
y="83.4077">0.5.4</tspan></text>
|
||||
y="83.4077">0.5.5</tspan></text>
|
||||
<rect
|
||||
style="fill:#951b89;fill-opacity:1;stroke:none;stroke-width:0.245683;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect358"
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
|
@ -27,7 +27,7 @@
|
|||
#### Main files
|
||||
####
|
||||
|
||||
PROJ_SRCS := $(addprefix utils/,crypto.c disk.c dm.c file.c string.c input.c)
|
||||
PROJ_SRCS := $(addprefix utils/,crypto.c disk.c dm.c file.c string.c input.c kernmod.c)
|
||||
PROJ_SRCS += $(addprefix header/,position_map_legacy.c position_map_lite.c volume_master_block_legacy.c volume_master_block_lite.c device_master_block.c)
|
||||
PROJ_SRCS += $(addprefix operations/,volume_header_legacy.c volume_header_lite.c devmapper_legacy.c devmapper_lite.c dmb.c)
|
||||
PROJ_SRCS += $(addprefix commands/,init_legacy.c init_lite.c open_legacy.c open_lite.c close.c test_pwd.c change_pwd.c)
|
||||
|
|
|
|||
42
shufflecake-userland/include/utils/kernmod.h
Normal file
42
shufflecake-userland/include/utils/kernmod.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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 _UTILS_KERNMOD_H_
|
||||
#define _UTILS_KERNMOD_H_
|
||||
|
||||
|
||||
/*****************************************************
|
||||
* INCLUDE SECTION *
|
||||
*****************************************************/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
/*****************************************************
|
||||
* PUBLIC FUNCTIONS PROTOTYPES *
|
||||
*****************************************************/
|
||||
|
||||
bool sflc_isKernelModuleLoaded(char *module_name);
|
||||
|
||||
|
||||
#endif /* _UTILS_KERNOMD_H_ */
|
||||
|
|
@ -40,6 +40,8 @@
|
|||
|
||||
/* Name of the DM target in the kernel */
|
||||
#define SFLC_DM_TARGET_NAME "shufflecake"
|
||||
/* Name of the kernel module once inserted */
|
||||
#define SFLC_KERNMOD_NAME "dm_sflc"
|
||||
|
||||
/* Modes */
|
||||
#define SFLC_MODE_LEGACY 0
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "cli.h"
|
||||
#include "utils/sflc.h"
|
||||
#include "utils/disk.h"
|
||||
#include "utils/kernmod.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
|
||||
|
|
@ -185,7 +186,11 @@ int sflc_cli_dispatch(int argc, char **argv) {
|
|||
return EINVAL;
|
||||
}
|
||||
|
||||
// TODO check that dm_sflc is loaded
|
||||
/* Check that the kernel module is loaded */
|
||||
if (!sflc_isKernelModuleLoaded(SFLC_KERNMOD_NAME)) {
|
||||
printf("Error: kernel module dm-sflc is not inserted.\n");
|
||||
return EINVAL;
|
||||
}
|
||||
/* Check that input is actually a block device */
|
||||
if (strncmp(args.block_device, "/dev/", 5) != 0 || !sflc_disk_isBlockDevice(args.block_device)) {
|
||||
printf("Error: '%s' is not a valid block device.\n", args.block_device);
|
||||
|
|
|
|||
65
shufflecake-userland/src/utils/kernmod.c
Normal file
65
shufflecake-userland/src/utils/kernmod.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "utils/kernmod.h"
|
||||
#include "utils/sflc.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
|
||||
/*****************************************************
|
||||
* PUBLIC FUNCTIONS DEFINITIONS *
|
||||
*****************************************************/
|
||||
|
||||
bool sflc_isKernelModuleLoaded(char *module_name) {
|
||||
FILE *fp;
|
||||
char line[SFLC_BIGBUFSIZE];
|
||||
|
||||
// Open /proc/modules to check loaded modules
|
||||
fp = fopen("/proc/modules", "r");
|
||||
if (fp == NULL) {
|
||||
perror("Failed to open /proc/modules: ");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read each line in /proc/modules
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
// Compare the module name in the current line with the input module name
|
||||
char *current_module = strtok(line, " "); // First token in the line is the module name
|
||||
if (current_module != NULL && strcmp(current_module, module_name) == 0) {
|
||||
fclose(fp);
|
||||
return true; // Module is loaded
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return false; // Module not found
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue