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.
This commit is contained in:
parent
b1e8c43679
commit
1a0596a2fb
@ -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
|
7
main.c
7
main.c
@ -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…
Reference in New Issue
Block a user