Add option to disable the concurrent write protection

This allows writing to the filesystem from the host computer and
CircuitPython by increasing the risk of filesystem corruption.
crypto-aes
Scott Shawcroft 4 years ago
parent b1e8c43679
commit 1a0596a2fb
No known key found for this signature in database
GPG Key ID: FD0EDC4B6C53CA59
  1. 2
      extmod/vfs_fat.h
  2. 3
      extmod/vfs_fat_file.c
  3. 2
      lib/tinyusb
  4. 7
      main.c
  5. 23
      shared-bindings/storage/__init__.c
  6. 2
      shared-bindings/storage/__init__.h
  7. 5
      shared-module/storage/__init__.c
  8. 9
      supervisor/filesystem.h
  9. 1
      supervisor/flash.h
  10. 32
      supervisor/shared/filesystem.c
  11. 20
      supervisor/shared/flash.c
  12. 4
      supervisor/shared/usb/usb_msc_flash.c

@ -38,6 +38,8 @@
#define FSUSER_NO_FILESYSTEM (0x0008) // the block device has no filesystem on it
// Device is writable over USB and read-only to MicroPython.
#define FSUSER_USB_WRITABLE (0x0010)
// Bit set when the above flag is checked before opening a file for write.
#define FSUSER_CONCURRENT_WRITE_PROTECTED (0x0020)
typedef struct _fs_user_mount_t {
mp_obj_base_t base;

@ -34,6 +34,7 @@
#include "py/mperrno.h"
#include "lib/oofatfs/ff.h"
#include "extmod/vfs_fat.h"
#include "supervisor/filesystem.h"
// this table converts from FRESULT to POSIX errno
const byte fresult_to_errno_table[20] = {
@ -187,7 +188,7 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar
}
}
assert(vfs != NULL);
if ((vfs->flags & FSUSER_USB_WRITABLE) != 0 && (mode & FA_WRITE) != 0) {
if ((mode & FA_WRITE) != 0 && !filesystem_is_writable_by_python(vfs)) {
mp_raise_OSError(MP_EROFS);
}

@ -1 +1 @@
Subproject commit 29b49199beb8e9b5fead83e5cd36105f8746f1d7
Subproject commit 55874813f82157b7509729b1a0c66e68f86e2d07

@ -323,12 +323,12 @@ void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
mp_hal_delay_ms(1500);
// USB isn't up, so we can write the file.
filesystem_writable_by_python(true);
filesystem_set_internal_writable_by_usb(false);
f_open(fs, boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS);
// Switch the filesystem back to non-writable by Python now instead of later,
// since boot.py might change it back to writable.
filesystem_writable_by_python(false);
filesystem_set_internal_writable_by_usb(true);
// Write version info to boot_out.txt.
mp_hal_stdout_tx_str(MICROPY_FULL_VERSION_INFO);
@ -416,7 +416,8 @@ int __attribute__((used)) main(void) {
// By default our internal flash is readonly to local python code and
// writable over USB. Set it here so that boot.py can change it.
filesystem_writable_by_python(false);
filesystem_set_internal_concurrent_write_protection(true);
filesystem_set_internal_writable_by_usb(true);
run_boot_py(safe_mode);

@ -48,16 +48,18 @@
//| directly.
//|
//| .. function:: mount(filesystem, mount_path, \*, readonly=False)
//| .. function:: mount(filesystem, mount_path, \*, readonly=False, disable_concurrent_write_protection=False)
//|
//| Mounts the given filesystem object at the given path.
//|
//| This is the CircuitPython analog to the UNIX ``mount`` command.
//|
//| :param bool readonly: True when the filesystem should be readonly to CircuitPython.
//|
mp_obj_t storage_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_readonly };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_readonly, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_false} },
{ MP_QSTR_readonly, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
// parse args
@ -77,7 +79,7 @@ mp_obj_t storage_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_arg
mp_raise_ValueError(translate("filesystem must provide mount method"));
}
common_hal_storage_mount(vfs_obj, mnt_str, mp_obj_is_true(args[ARG_readonly].u_obj));
common_hal_storage_mount(vfs_obj, mnt_str, args[ARG_readonly].u_bool);
return mp_const_none;
}
@ -101,14 +103,21 @@ mp_obj_t storage_umount(mp_obj_t mnt_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(storage_umount_obj, storage_umount);
//| .. function:: remount(mount_path, readonly=False)
//| .. function:: remount(mount_path, readonly=False, *, disable_concurrent_write_protection=False)
//|
//| Remounts the given path with new parameters.
//|
//| :param bool readonly: True when the filesystem should be readonly to CircuitPython.
//| :param bool disable_concurrent_write_protection: When True, the check that makes sure the
//| underlying filesystem data is written by one computer is disabled. Disabling the protection
//| allows CircuitPython and a host to write to the same filesystem with the risk that the
//| filesystem will be corrupted.
//|
mp_obj_t storage_remount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_readonly };
enum { ARG_readonly, ARG_disable_concurrent_write_protection };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_readonly, MP_ARG_BOOL | MP_ARG_REQUIRED, {.u_bool = false} },
{ MP_QSTR_readonly, MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_disable_concurrent_write_protection, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
// get the mount point
@ -118,7 +127,7 @@ mp_obj_t storage_remount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
common_hal_storage_remount(mnt_str, args[ARG_readonly].u_bool);
common_hal_storage_remount(mnt_str, args[ARG_readonly].u_bool, args[ARG_disable_concurrent_write_protection].u_bool);
return mp_const_none;
}

@ -33,7 +33,7 @@
void common_hal_storage_mount(mp_obj_t vfs_obj, const char* path, bool readonly);
void common_hal_storage_umount_path(const char* path);
void common_hal_storage_umount_object(mp_obj_t vfs_obj);
void common_hal_storage_remount(const char* path, bool readonly);
void common_hal_storage_remount(const char* path, bool readonly, bool disable_concurrent_write_protection);
mp_obj_t common_hal_storage_getmount(const char* path);
void common_hal_storage_erase_filesystem(void);

@ -143,7 +143,7 @@ mp_obj_t common_hal_storage_getmount(const char *mount_path) {
return storage_object_from_path(mount_path);
}
void common_hal_storage_remount(const char *mount_path, bool readonly) {
void common_hal_storage_remount(const char *mount_path, bool readonly, bool disable_concurrent_write_protection) {
if (strcmp(mount_path, "/") != 0) {
mp_raise_OSError(MP_EINVAL);
}
@ -156,7 +156,8 @@ void common_hal_storage_remount(const char *mount_path, bool readonly) {
}
#endif
supervisor_flash_set_usb_writable(readonly);
filesystem_set_internal_writable_by_usb(readonly);
filesystem_set_internal_concurrent_write_protection(!disable_concurrent_write_protection);
}
void common_hal_storage_erase_filesystem(void) {

@ -29,9 +29,16 @@
#include <stdbool.h>
#include "extmod/vfs_fat.h"
void filesystem_init(bool create_allowed, bool force_create);
void filesystem_flush(void);
void filesystem_writable_by_python(bool writable);
bool filesystem_present(void);
void filesystem_set_internal_writable_by_usb(bool usb_writable);
void filesystem_set_internal_concurrent_write_protection(bool concurrent_write_protection);
void filesystem_set_writable_by_usb(fs_user_mount_t *vfs, bool usb_writable);
void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concurrent_write_protection);
bool filesystem_is_writable_by_python(fs_user_mount_t *vfs);
bool filesystem_is_writable_by_usb(fs_user_mount_t *vfs);
#endif // MICROPY_INCLUDED_SUPERVISOR_FILESYSTEM_H

@ -37,7 +37,6 @@
#include "supervisor/internal_flash.h"
#endif
void supervisor_flash_set_usb_writable(bool usb_writable);
void supervisor_flash_init(void);
uint32_t supervisor_flash_get_block_size(void);
uint32_t supervisor_flash_get_block_count(void);

@ -24,6 +24,8 @@
* THE SOFTWARE.
*/
#include "supervisor/filesystem.h"
#include "extmod/vfs_fat.h"
#include "lib/oofatfs/ff.h"
#include "lib/oofatfs/diskio.h"
@ -92,16 +94,42 @@ void filesystem_flush(void) {
supervisor_flash_flush();
}
void filesystem_writable_by_python(bool writable) {
void filesystem_set_internal_writable_by_usb(bool writable) {
fs_user_mount_t *vfs = &_internal_vfs;
if (!writable) {
filesystem_set_writable_by_usb(vfs, writable);
}
void filesystem_set_writable_by_usb(fs_user_mount_t *vfs, bool usb_writable) {
if (usb_writable) {
vfs->flags |= FSUSER_USB_WRITABLE;
} else {
vfs->flags &= ~FSUSER_USB_WRITABLE;
}
}
bool filesystem_is_writable_by_python(fs_user_mount_t *vfs) {
return (vfs->flags & FSUSER_CONCURRENT_WRITE_PROTECTED) == 0 ||
(vfs->flags & FSUSER_USB_WRITABLE) == 0;
}
bool filesystem_is_writable_by_usb(fs_user_mount_t *vfs) {
return (vfs->flags & FSUSER_CONCURRENT_WRITE_PROTECTED) == 0 ||
(vfs->flags & FSUSER_USB_WRITABLE) != 0;
}
void filesystem_set_internal_concurrent_write_protection(bool concurrent_write_protection) {
filesystem_set_concurrent_write_protection(&_internal_vfs, concurrent_write_protection);
}
void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concurrent_write_protection) {
if (concurrent_write_protection) {
vfs->flags |= FSUSER_CONCURRENT_WRITE_PROTECTED;
} else {
vfs->flags &= ~FSUSER_CONCURRENT_WRITE_PROTECTED;
}
}
bool filesystem_present(void) {
return true;
}

@ -33,26 +33,6 @@
#define PART1_START_BLOCK (0x1)
void supervisor_flash_set_usb_writable(bool usb_writable) {
mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table);
for (uint8_t i = 0; current_mount != NULL; i++) {
if (i == VFS_INDEX) {
break;
}
current_mount = current_mount->next;
}
if (current_mount == NULL) {
return;
}
fs_user_mount_t *vfs = (fs_user_mount_t *) current_mount->obj;
if (usb_writable) {
vfs->flags |= FSUSER_USB_WRITABLE;
} else {
vfs->flags &= ~FSUSER_USB_WRITABLE;
}
}
// there is a singleton Flash object
const mp_obj_type_t supervisor_flash_type;
STATIC const mp_obj_base_t supervisor_flash_obj = {&supervisor_flash_type};

@ -34,6 +34,7 @@
#include "lib/oofatfs/ff.h"
#include "py/mpstate.h"
#include "supervisor/filesystem.h"
#include "supervisor/shared/autoreload.h"
#define MSC_FLASH_BLOCK_SIZE 512
@ -148,8 +149,7 @@ bool tud_msc_is_writable_cb(uint8_t lun) {
if (vfs == NULL) {
return false;
}
if (vfs->writeblocks[0] == MP_OBJ_NULL ||
(vfs->flags & FSUSER_USB_WRITABLE) == 0) {
if (vfs->writeblocks[0] == MP_OBJ_NULL || !filesystem_is_writable_by_usb(vfs)) {
return false;
}
return true;

Loading…
Cancel
Save