From 1bdbdfdf12ae35f08f5dcbec06a35c8d0f11ef55 Mon Sep 17 00:00:00 2001 From: Jonathan Bauer Date: Fri, 29 May 2020 14:37:49 +0200 Subject: Initial working state * Moved old Makefile to Kbuild.in * New Makefile to compile against running kernel (or KDIR) * Moved file format defines from loop/include/uapi/linux/loop.h to loop_file_fmt.h * Moved definitions of loop_info{,64} to loop_file_fmt.h * Renamed loop_info{,64} to xloop_info{,64} * Removed checks for file format support which was now unneeded --- Kbuild.in | 11 ++++++ Makefile | 15 +++---- README.md | 15 +++++++ loop_file_fmt.h | 6 +++ loop_main.c | 120 +++++++++++++++----------------------------------------- loop_main.h | 35 ++++++++++++++++- 6 files changed, 106 insertions(+), 96 deletions(-) create mode 100644 Kbuild.in create mode 100644 README.md diff --git a/Kbuild.in b/Kbuild.in new file mode 100644 index 0000000..c50333a --- /dev/null +++ b/Kbuild.in @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 + +loop-y += loop_main.o loop_file_fmt.o +obj-$(CONFIG_BLK_DEV_LOOP) += loop.o + +obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o + +obj-$(CONFIG_BLK_DEV_LOOP_FILE_FMT_RAW) += loop_file_fmt_raw.o + +loop_file_fmt_qcow-y += loop_file_fmt_qcow_main.o loop_file_fmt_qcow_cluster.o loop_file_fmt_qcow_cache.o +obj-$(CONFIG_BLK_DEV_LOOP_FILE_FMT_QCOW) += loop_file_fmt_qcow.o diff --git a/Makefile b/Makefile index a82cd7a..b7f2191 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,12 @@ # SPDX-License-Identifier: GPL-2.0 +include $(PWD)/Kbuild.in -loop-y += loop_main.o loop_file_fmt.o -obj-$(CONFIG_BLK_DEV_LOOP) += loop.o +ifndef KDIR + KDIR = /lib/modules/$(shell uname -r)/build +endif -obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o +all: + make -C "$(KDIR)" "M=$(PWD)" modules -obj-$(CONFIG_BLK_DEV_LOOP_FILE_FMT_RAW) += loop_file_fmt_raw.o - -loop_file_fmt_qcow-y += loop_file_fmt_qcow_main.o loop_file_fmt_qcow_cluster.o loop_file_fmt_qcow_cache.o -obj-$(CONFIG_BLK_DEV_LOOP_FILE_FMT_QCOW) += loop_file_fmt_qcow.o +clean: + make -C "$(KDIR)" "M=$(PWD)" clean diff --git a/README.md b/README.md new file mode 100644 index 0000000..e32b858 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +Building the modules: + +```shell +$ make CONFIG_BLK_DEV_LOOP_FILE_FMT_QCOW=m CONFIG_BLK_DEV_LOOP_FILE_FMT_RAW=m +``` + +Results in: +* xloop.ko +* loop_file_fmt_raw.ko +* loop_file_fmt_qcow.ko + +Clean: +```shell +$ make clean +``` diff --git a/loop_file_fmt.h b/loop_file_fmt.h index 5c0e493..8a16c86 100644 --- a/loop_file_fmt.h +++ b/loop_file_fmt.h @@ -14,6 +14,12 @@ struct loop_file_fmt; +#define LO_FILE_FMT_RAW 0 +#define LO_FILE_FMT_QCOW 1 +#define LO_FILE_FMT_VDI 2 +#define LO_FILE_FMT_VMDK 3 +#define MAX_LO_FILE_FMT (LO_FILE_FMT_VMDK + 1) + /** * struct loop_file_fmt_ops - File format subsystem operations * diff --git a/loop_main.c b/loop_main.c index 7c1bb19..3bf4f1f 100644 --- a/loop_main.c +++ b/loop_main.c @@ -121,7 +121,7 @@ static int transfer_xor(struct loop_device *lo, int cmd, return 0; } -static int xor_init(struct loop_device *lo, const struct loop_info64 *info) +static int xor_init(struct loop_device *lo, const struct xloop_info64 *info) { if (unlikely(info->lo_encrypt_key_size <= 0)) return -EINVAL; @@ -741,7 +741,7 @@ loop_release_xfer(struct loop_device *lo) static int loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer, - const struct loop_info64 *i) + const struct xloop_info64 *i) { int err = 0; @@ -906,7 +906,7 @@ static int loop_clr_fd(struct loop_device *lo) } static int -loop_set_status(struct loop_device *lo, const struct loop_info64 *info) +loop_set_status(struct loop_device *lo, const struct xloop_info64 *info) { int err; struct loop_func_table *xfer; @@ -1043,7 +1043,7 @@ out_unlock: } static int -loop_get_status(struct loop_device *lo, struct loop_info64 *info) +loop_get_status(struct loop_device *lo, struct xloop_info64 *info) { struct path path; struct kstat stat; @@ -1088,7 +1088,7 @@ loop_get_status(struct loop_device *lo, struct loop_info64 *info) } static void -loop_info64_from_old(const struct loop_info *info, struct loop_info64 *info64) +loop_info64_from_old(const struct xloop_info *info, struct xloop_info64 *info64) { memset(info64, 0, sizeof(*info64)); info64->lo_number = info->lo_number; @@ -1111,7 +1111,7 @@ loop_info64_from_old(const struct loop_info *info, struct loop_info64 *info64) } static int -loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info) +loop_info64_to_old(const struct xloop_info64 *info64, struct xloop_info *info) { memset(info, 0, sizeof(*info)); info->lo_number = info64->lo_number; @@ -1142,61 +1142,39 @@ loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info) } static int -loop_set_status_old(struct loop_device *lo, const struct loop_info __user *arg) +loop_set_status_old(struct loop_device *lo, const struct xloop_info __user *arg) { - struct loop_info info; - struct loop_info64 info64; + struct xloop_info info; + struct xloop_info64 info64; int err; - /* backward compatibility: copy everything except the file format type - * field */ - err = copy_from_user(&info, arg, - sizeof(info) - sizeof(info.lo_file_fmt_type)); + /* copy everything from the user space */ + err = copy_from_user(&info, arg, sizeof(info)); if (err) return -EFAULT; - if (info.lo_flags & LO_FLAGS_FILE_FMT) { - /* copy everything from the user space */ - err = copy_from_user(&info, arg, sizeof(info)); - if (err) - return -EFAULT; - } else { - info64.lo_file_fmt_type = LO_FILE_FMT_RAW; - } - loop_info64_from_old(&info, &info64); return loop_set_status(lo, &info64); } static int -loop_set_status64(struct loop_device *lo, const struct loop_info64 __user *arg) +loop_set_status64(struct loop_device *lo, const struct xloop_info64 __user *arg) { - struct loop_info64 info64; + struct xloop_info64 info64; int err; - /* backward compatibility: copy everything except the file format type - * field */ - err = copy_from_user(&info64, arg, - sizeof(info64) - sizeof(info64.lo_file_fmt_type)); + /* copy everything from the user space */ + err = copy_from_user(&info64, arg, sizeof(info64)); if (err) return -EFAULT; - if (info64.lo_flags & LO_FLAGS_FILE_FMT) { - /* copy everything from the user space */ - err = copy_from_user(&info64, arg, sizeof(info64)); - if (err) - return -EFAULT; - } else { - info64.lo_file_fmt_type = LO_FILE_FMT_RAW; - } - return loop_set_status(lo, &info64); } static int -loop_get_status_old(struct loop_device *lo, struct loop_info __user *arg) { - struct loop_info info; - struct loop_info64 info64; +loop_get_status_old(struct loop_device *lo, struct xloop_info __user *arg) { + struct xloop_info info; + struct xloop_info64 info64; int lo_flags; int err; @@ -1216,15 +1194,7 @@ loop_get_status_old(struct loop_device *lo, struct loop_info __user *arg) { if (!err) err = loop_info64_to_old(&info64, &info); - if (lo_flags & LO_FLAGS_FILE_FMT) { - /* copy entire structure to user space because file format - * support is available */ - err = copy_to_user(arg, &info, sizeof(info)); - } else { - /* copy normal structure to user space */ - err = copy_to_user(arg, &info, - sizeof(info) - sizeof(info.lo_file_fmt_type)); - } + err = copy_to_user(arg, &info, sizeof(info)); if (err) return -EFAULT; @@ -1233,8 +1203,8 @@ loop_get_status_old(struct loop_device *lo, struct loop_info __user *arg) { } static int -loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg) { - struct loop_info64 info64; +loop_get_status64(struct loop_device *lo, struct xloop_info64 __user *arg) { + struct xloop_info64 info64; u32 lo_flags; int err; @@ -1254,15 +1224,7 @@ loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg) { if (err) return -EFAULT; - if (lo_flags & LO_FLAGS_FILE_FMT) { - /* copy entire structure to user space because file format - * support is available */ - err = copy_to_user(arg, &info64, sizeof(info64)); - } else { - /* copy normal structure to user space */ - err = copy_to_user(arg, &info64, - sizeof(info64) - sizeof(info64.lo_file_fmt_type)); - } + err = copy_to_user(arg, &info64, sizeof(info64)); if (err) return -EFAULT; @@ -1371,20 +1333,20 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, err = -EPERM; if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) { err = loop_set_status_old(lo, - (struct loop_info __user *)arg); + (struct xloop_info __user *)arg); } break; case LOOP_GET_STATUS: - return loop_get_status_old(lo, (struct loop_info __user *) arg); + return loop_get_status_old(lo, (struct xloop_info __user *) arg); case LOOP_SET_STATUS64: err = -EPERM; if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) { err = loop_set_status64(lo, - (struct loop_info64 __user *) arg); + (struct xloop_info64 __user *) arg); } break; case LOOP_GET_STATUS64: - return loop_get_status64(lo, (struct loop_info64 __user *) arg); + return loop_get_status64(lo, (struct xloop_info64 __user *) arg); case LOOP_SET_CAPACITY: case LOOP_SET_DIRECT_IO: case LOOP_SET_BLOCK_SIZE: @@ -1422,27 +1384,17 @@ struct compat_loop_info { */ static noinline int loop_info64_from_compat(const struct compat_loop_info __user *arg, - struct loop_info64 *info64) + struct xloop_info64 *info64) { struct compat_loop_info info; int err; /* backward compatibility: copy everything except the file format type * field */ - err = copy_from_user(&info, arg, - sizeof(info) - sizeof(info.lo_file_fmt_type)); + err = copy_from_user(&info, arg, sizeof(info)); if (err) return -EFAULT; - if (info.lo_flags & LO_FLAGS_FILE_FMT) { - /* copy everything from the user space */ - err = copy_from_user(&info, arg, sizeof(info)); - if (err) - return -EFAULT; - } else { - info.lo_file_fmt_type = LO_FILE_FMT_RAW; - } - memset(info64, 0, sizeof(*info64)); info64->lo_number = info.lo_number; info64->lo_device = info.lo_device; @@ -1469,7 +1421,7 @@ loop_info64_from_compat(const struct compat_loop_info __user *arg, * - noinlined to reduce stack space usage in main part of driver */ static noinline int -loop_info64_to_compat(const struct loop_info64 *info64, +loop_info64_to_compat(const struct xloop_info64 *info64, struct compat_loop_info __user *arg) { struct compat_loop_info info; @@ -1513,15 +1465,7 @@ loop_info64_to_compat(const struct loop_info64 *info64, info.lo_file_fmt_type != info64->lo_file_fmt_type) return -EOVERFLOW; - if (lo_flags & LO_FLAGS_FILE_FMT) { - /* copy entire structure to user space because file format - * support is available */ - err = copy_to_user(arg, &info, sizeof(info)); - } else { - /* copy normal structure to user space */ - err = copy_to_user(arg, &info, - sizeof(info) - sizeof(info.lo_file_fmt_type)); - } + err = copy_to_user(arg, &info, sizeof(info)); if (err) return -EFAULT; @@ -1533,7 +1477,7 @@ static int loop_set_status_compat(struct loop_device *lo, const struct compat_loop_info __user *arg) { - struct loop_info64 info64; + struct xloop_info64 info64; int ret; ret = loop_info64_from_compat(arg, &info64); @@ -1546,7 +1490,7 @@ static int loop_get_status_compat(struct loop_device *lo, struct compat_loop_info __user *arg) { - struct loop_info64 info64; + struct xloop_info64 info64; int err; if (!arg) diff --git a/loop_main.h b/loop_main.h index 33f6578..324ec2e 100644 --- a/loop_main.h +++ b/loop_main.h @@ -32,6 +32,39 @@ enum { struct loop_func_table; +struct xloop_info { + int lo_number; /* ioctl r/o */ + __kernel_old_dev_t lo_device; /* ioctl r/o */ + unsigned long lo_inode; /* ioctl r/o */ + __kernel_old_dev_t lo_rdevice; /* ioctl r/o */ + int lo_offset; + int lo_encrypt_type; + int lo_encrypt_key_size; /* ioctl w/o */ + int lo_flags; /* ioctl r/o */ + char lo_name[LO_NAME_SIZE]; + unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ + unsigned long lo_init[2]; + char reserved[4]; + int lo_file_fmt_type; +}; + +struct xloop_info64 { + __u64 lo_device; /* ioctl r/o */ + __u64 lo_inode; /* ioctl r/o */ + __u64 lo_rdevice; /* ioctl r/o */ + __u64 lo_offset; + __u64 lo_sizelimit;/* bytes, 0 == max available */ + __u32 lo_number; /* ioctl r/o */ + __u32 lo_encrypt_type; + __u32 lo_encrypt_key_size; /* ioctl w/o */ + __u32 lo_flags; /* ioctl r/o */ + __u8 lo_file_name[LO_NAME_SIZE]; + __u8 lo_crypt_name[LO_NAME_SIZE]; + __u8 lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ + __u64 lo_init[2]; + __u32 lo_file_fmt_type; +} __attribute__((packed)); + struct loop_device { int lo_number; atomic_t lo_refcnt; @@ -93,7 +126,7 @@ struct loop_func_table { struct page *raw_page, unsigned raw_off, struct page *loop_page, unsigned loop_off, int size, sector_t real_block); - int (*init)(struct loop_device *, const struct loop_info64 *); + int (*init)(struct loop_device *, const struct xloop_info64 *); /* release is called from loop_unregister_transfer or clr_fd */ int (*release)(struct loop_device *); int (*ioctl)(struct loop_device *, int cmd, unsigned long arg); -- cgit v1.2.3-55-g7522