linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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;

  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).