From: David Howells <dhowells@redhat.com>
To: Arnd Bergmann <arnd@arndb.de>
Cc: David Howells <dhowells@redhat.com>,
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 10/17] BLOCK: Move the loop device ioctl compat stuff to the loop driver [try #2]
Date: Fri, 25 Aug 2006 10:27:33 +0100 [thread overview]
Message-ID: <15287.1156498053@warthog.cambridge.redhat.com> (raw)
In-Reply-To: <200608250023.13204.arnd@arndb.de>
Arnd Bergmann <arnd@arndb.de> wrote:
> The structure should be called compat_loop_info by convention, when it
> is moved to the file itself.
Seems reasonable.
> I guess this should be implemented like loop_set_status_old(), by calling a
> new loop_info64_from_compat() function an then the regular
> loop_set_status().
Whilst that does seem reasonable, it seems like a lot of extra code for
something that I wouldn't have thought would be that performance critical.
Surely these two ioctls aren't called that often...
On the other hand, it does reduce stack space usage somewhat - which is a good
thing - and that can be reduced still further by moving the on-stack struct
compat_loop_info variable and the copy_to/from_user into loop_set_status_compat
and loop_get_status_compat.
Anyway, how about the attached patch (to go on top of the one you've already
got)?
David
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 48ad173..82bc5bd 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1176,7 +1176,7 @@ static int lo_ioctl(struct inode * inode
}
#ifdef CONFIG_COMPAT
-struct loop_info32 {
+struct compat_loop_info {
compat_int_t lo_number; /* ioctl r/o */
compat_dev_t lo_device; /* ioctl r/o */
compat_ulong_t lo_inode; /* ioctl r/o */
@@ -1191,47 +1191,120 @@ struct loop_info32 {
char reserved[4];
};
+static noinline int
+loop_info64_from_compat(const struct compat_loop_info *arg,
+ struct loop_info64 *info64)
+{
+ struct compat_loop_info info;
+
+ if (copy_from_user(&info, arg, sizeof(info)))
+ return -EFAULT;
+
+ memset(info64, 0, sizeof(*info64));
+ info64->lo_number = info.lo_number;
+ info64->lo_device = info.lo_device;
+ info64->lo_inode = info.lo_inode;
+ info64->lo_rdevice = info.lo_rdevice;
+ info64->lo_offset = info.lo_offset;
+ info64->lo_sizelimit = 0;
+ info64->lo_encrypt_type = info.lo_encrypt_type;
+ info64->lo_encrypt_key_size = info.lo_encrypt_key_size;
+ info64->lo_flags = info.lo_flags;
+ info64->lo_init[0] = info.lo_init[0];
+ info64->lo_init[1] = info.lo_init[1];
+ if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
+ memcpy(info64->lo_crypt_name, info.lo_name, LO_NAME_SIZE);
+ else
+ memcpy(info64->lo_file_name, info.lo_name, LO_NAME_SIZE);
+ memcpy(info64->lo_encrypt_key, info.lo_encrypt_key, LO_KEY_SIZE);
+ return 0;
+}
+
+static noinline int
+loop_info64_to_compat(const struct loop_info64 *info64,
+ struct compat_loop_info __user *arg)
+{
+ struct compat_loop_info info;
+
+ memset(&info, 0, sizeof(info));
+ info.lo_number = info64->lo_number;
+ info.lo_device = info64->lo_device;
+ info.lo_inode = info64->lo_inode;
+ info.lo_rdevice = info64->lo_rdevice;
+ info.lo_offset = info64->lo_offset;
+ info.lo_encrypt_type = info64->lo_encrypt_type;
+ info.lo_encrypt_key_size = info64->lo_encrypt_key_size;
+ info.lo_flags = info64->lo_flags;
+ info.lo_init[0] = info64->lo_init[0];
+ info.lo_init[1] = info64->lo_init[1];
+ if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
+ memcpy(info.lo_name, info64->lo_crypt_name, LO_NAME_SIZE);
+ else
+ memcpy(info.lo_name, info64->lo_file_name, LO_NAME_SIZE);
+ memcpy(info.lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE);
+
+ /* error in case values were truncated */
+ if (info.lo_device != info64->lo_device ||
+ info.lo_rdevice != info64->lo_rdevice ||
+ info.lo_inode != info64->lo_inode ||
+ info.lo_offset != info64->lo_offset ||
+ info.lo_init[0] != info64->lo_init[0] ||
+ info.lo_init[1] != info64->lo_init[1])
+ return -EOVERFLOW;
+
+ if (copy_to_user(arg, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+}
+
+static int
+loop_set_status_compat(struct loop_device *lo,
+ const struct compat_loop_info __user *arg)
+{
+ struct loop_info64 info64;
+ int ret;
+
+ ret = loop_info64_from_compat(arg, &info64);
+ if (ret < 0)
+ return ret;
+ return loop_set_status(lo, &info64);
+}
+
+static int
+loop_get_status_compat(struct loop_device *lo,
+ struct compat_loop_info __user *arg)
+{
+ struct loop_info64 info64;
+ int err = 0;
+
+ if (!arg)
+ err = -EINVAL;
+ if (!err)
+ err = loop_get_status(lo, &info64);
+ if (!err)
+ err = loop_info64_to_compat(&info64, arg);
+ return err;
+}
+
static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct inode *inode = file->f_dentry->d_inode;
- mm_segment_t old_fs = get_fs();
- struct loop_info l;
- struct loop_info32 __user *ul;
- int err = -ENOIOCTLCMD;
-
- ul = compat_ptr(arg);
+ struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+ int err;
lock_kernel();
switch(cmd) {
case LOOP_SET_STATUS:
- err = get_user(l.lo_number, &ul->lo_number);
- err |= __get_user(l.lo_device, &ul->lo_device);
- err |= __get_user(l.lo_inode, &ul->lo_inode);
- err |= __get_user(l.lo_rdevice, &ul->lo_rdevice);
- err |= __copy_from_user(&l.lo_offset, &ul->lo_offset,
- 8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
- if (err) {
- err = -EFAULT;
- } else {
- set_fs (KERNEL_DS);
- err = lo_ioctl(inode, file, cmd, (unsigned long)&l);
- set_fs (old_fs);
- }
+ mutex_lock(&lo->lo_ctl_mutex);
+ err = loop_set_status_compat(
+ lo, (const struct compat_loop_info __user *) arg);
+ mutex_unlock(&lo->lo_ctl_mutex);
break;
case LOOP_GET_STATUS:
- set_fs (KERNEL_DS);
- err = lo_ioctl(inode, file, cmd, (unsigned long)&l);
- set_fs (old_fs);
- if (!err) {
- err = put_user(l.lo_number, &ul->lo_number);
- err |= __put_user(l.lo_device, &ul->lo_device);
- err |= __put_user(l.lo_inode, &ul->lo_inode);
- err |= __put_user(l.lo_rdevice, &ul->lo_rdevice);
- err |= __copy_to_user(&ul->lo_offset, &l.lo_offset,
- (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
- if (err)
- err = -EFAULT;
- }
+ mutex_lock(&lo->lo_ctl_mutex);
+ err = loop_get_status_compat(
+ lo, (struct compat_loop_info __user *) arg);
+ mutex_unlock(&lo->lo_ctl_mutex);
break;
case LOOP_CLR_FD:
case LOOP_GET_STATUS64:
@@ -1241,6 +1314,9 @@ static long lo_compat_ioctl(struct file
case LOOP_CHANGE_FD:
err = lo_ioctl(inode, file, cmd, arg);
break;
+ default:
+ err = -ENOIOCTLCMD;
+ break;
}
unlock_kernel();
return err;
next prev parent reply other threads:[~2006-08-25 9:27 UTC|newest]
Thread overview: 74+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <200608250023.20903.arnd@arndb.de>
2006-08-24 21:32 ` [PATCH 01/17] BLOCK: Move functions out of buffer code [try #2] David Howells
2006-08-24 21:32 ` [PATCH 02/17] BLOCK: Remove duplicate declaration of exit_io_context() " David Howells
2006-08-25 14:08 ` Christoph Hellwig
2006-08-24 21:32 ` [PATCH 03/17] BLOCK: Stop fallback_migrate_page() from using page_has_buffers() " David Howells
2006-08-25 14:10 ` Christoph Hellwig
2006-08-25 16:11 ` David Howells
2006-08-24 21:33 ` [PATCH 04/17] BLOCK: Separate the bounce buffering code from the highmem code " David Howells
2006-08-25 14:12 ` Christoph Hellwig
2006-08-24 21:33 ` [PATCH 05/17] BLOCK: Don't call block_sync_page() from AFS " David Howells
2006-08-25 14:13 ` Christoph Hellwig
2006-08-25 16:12 ` David Howells
2006-08-24 21:33 ` [PATCH 06/17] BLOCK: Move bdev_cache_init() declaration to headerfile " David Howells
2006-08-25 14:13 ` Christoph Hellwig
2006-08-24 21:33 ` [PATCH 07/17] BLOCK: Remove dependence on existence of blockdev_superblock " David Howells
2006-08-25 14:14 ` Christoph Hellwig
2006-08-24 21:33 ` [PATCH 08/17] BLOCK: Dissociate generic_writepages() from mpage stuff " David Howells
2006-08-25 14:16 ` Christoph Hellwig
2006-08-24 21:33 ` [PATCH 09/17] BLOCK: Move __invalidate_device() to block_dev.c " David Howells
2006-08-25 14:16 ` Christoph Hellwig
2006-08-24 21:33 ` [PATCH 10/17] BLOCK: Move the loop device ioctl compat stuff to the loop driver " David Howells
2006-08-25 9:27 ` David Howells [this message]
2006-08-25 11:01 ` David Howells
2006-08-24 21:33 ` [PATCH 11/17] BLOCK: Move common FS-specific ioctls to linux/fs.h " David Howells
2006-08-25 8:38 ` David Howells
2006-08-25 8:44 ` Arnd Bergmann
2006-08-24 21:33 ` [PATCH 12/17] BLOCK: Move the ReiserFS device ioctl compat stuff to the ReiserFS driver " David Howells
2006-08-24 21:33 ` [PATCH 13/17] BLOCK: Move the Ext2 device ioctl compat stuff to the Ext2 " David Howells
2006-08-24 21:33 ` [PATCH 14/17] BLOCK: Move the Ext3 device ioctl compat stuff to the Ext3 " David Howells
2006-08-24 21:33 ` [PATCH 15/17] BLOCK: Stop CIFS from using EXT2 ioctl numbers directly " David Howells
2006-08-24 21:41 ` Trond Myklebust
2006-08-25 8:12 ` David Howells
2006-08-24 21:33 ` [PATCH 16/17] BLOCK: Move the msdos device ioctl compat stuff to the msdos driver " David Howells
2006-08-24 21:33 ` [PATCH 17/17] BLOCK: Make it possible to disable the block layer " David Howells
2006-08-25 14:27 ` Christoph Hellwig
2006-08-25 14:52 ` Alexey Dobriyan
2006-08-25 16:23 ` David Howells
2006-08-29 11:51 ` Christoph Hellwig
2006-08-29 12:21 ` Stefan Richter
2006-08-29 12:23 ` David Howells
2006-08-29 12:25 ` Christoph Hellwig
2006-08-29 13:50 ` Stefan Richter
2006-08-29 14:13 ` Stefan Richter
2006-08-30 1:12 ` Roman Zippel
2006-08-30 18:33 ` Stefan Richter
2006-08-30 21:43 ` Adrian Bunk
2006-08-30 22:41 ` Roman Zippel
2006-08-30 23:38 ` Adrian Bunk
2006-08-30 23:58 ` Roman Zippel
2006-08-31 8:01 ` Stefan Richter
2006-09-01 0:15 ` David Woodhouse
2006-09-01 0:48 ` Randy.Dunlap
2006-09-01 1:27 ` David Woodhouse
2006-09-01 1:47 ` Adrian Bunk
2006-09-01 13:44 ` Jörn Engel
2006-09-01 15:31 ` Stefan Richter
2006-09-01 16:19 ` Jörn Engel
2006-09-01 16:34 ` Adrian Bunk
2006-09-01 17:51 ` Stefan Richter
2006-09-01 18:14 ` Sam Ravnborg
2006-08-30 22:50 ` Stefan Richter
2006-08-30 23:12 ` Adrian Bunk
2006-08-30 1:11 ` Roman Zippel
2006-08-30 11:29 ` Stefan Richter
2006-08-29 19:58 ` Greg KH
2006-08-29 21:08 ` John Stoffel
2006-08-31 3:01 ` Matthew Wilcox
2006-08-31 3:04 ` Shaya Potter
2006-08-31 8:53 ` Stefan Richter
2006-08-31 12:32 ` Shaya Potter
2006-08-31 13:16 ` Stefan Richter
2006-08-31 13:27 ` Shaya Potter
2006-08-31 10:13 ` David Howells
2006-08-25 18:46 ` David Howells
2006-08-25 14:08 ` [PATCH 01/17] BLOCK: Move functions out of buffer code " Christoph Hellwig
[not found] <200608251217.24543.arnd@arndb.de>
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=15287.1156498053@warthog.cambridge.redhat.com \
--to=dhowells@redhat.com \
--cc=arnd@arndb.de \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).