]> git.hungrycats.org Git - linux/commitdiff
[PATCH] sparse (compat_ioctl): raw_ioctl() fixes
authorAlexander Viro <viro@parcelfarce.linux.theplanet.co.uk>
Sat, 29 May 2004 11:42:59 +0000 (04:42 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Sat, 29 May 2004 11:42:59 +0000 (04:42 -0700)
Whoever had done the translation apparently never heard of
big-endian boxen.  Replaced the kludge with get_user()/put_user() on
64bit values.  Note that
struct raw_config_request
{
        int     raw_minor;
        __u64   block_major;
        __u64   block_minor;
};
has __u64 on _all_ platforms and it is used as an integer in raw.c code.
The only reason why translation is needed at all is alignment for 64bit
values; block_major and block_minor themselves should be passed as-is.

Breakage fixed, entire area annotated.

fs/compat_ioctl.c

index 3400bf05f248da2e3ce3a0ee5172e799fe9261c9..a87c4d3199af36c83b3e582c817dfc86a7e3d58f 100644 (file)
@@ -2428,28 +2428,22 @@ struct raw32_config_request
         __u64   block_minor;
 } __attribute__((packed));
 
-static int get_raw32_request(struct raw_config_request *req, struct raw32_config_request *user_req)
+static int get_raw32_request(struct raw_config_request *req, struct raw32_config_request __user *user_req)
 {
-        __u32   lo_maj, hi_maj, lo_min, hi_min;
         int ret;
 
         if ((ret = verify_area(VERIFY_READ, user_req,
                                sizeof(struct raw32_config_request))))
                 return ret;
 
-        __get_user(req->raw_minor, &user_req->raw_minor);
-        __get_user(lo_maj, (__u32*)&user_req->block_major);
-        __get_user(hi_maj, ((__u32*)(&user_req->block_major) + 1));
-        __get_user(lo_min, (__u32*)&user_req->block_minor);
-        __get_user(hi_min, ((__u32*)(&user_req->block_minor) + 1));
+        ret = __get_user(req->raw_minor, &user_req->raw_minor);
+        ret |= __get_user(req->block_major, &user_req->block_major);
+        ret |= __get_user(req->block_minor, &user_req->block_minor);
 
-        req->block_major = lo_maj | (((__u64)hi_maj) << 32);
-        req->block_minor = lo_min | (((__u64)hi_min) << 32);
-
-        return ret;
+        return ret ? -EFAULT : 0;
 }
 
-static int set_raw32_request(struct raw_config_request *req, struct raw32_config_request *user_req)
+static int set_raw32_request(struct raw_config_request *req, struct raw32_config_request __user *user_req)
 {
        int ret;
 
@@ -2457,13 +2451,11 @@ static int set_raw32_request(struct raw_config_request *req, struct raw32_config
                                sizeof(struct raw32_config_request))))
                 return ret;
 
-        __put_user(req->raw_minor, &user_req->raw_minor);
-        __put_user((__u32)(req->block_major), (__u32*)&user_req->block_major);
-        __put_user((__u32)(req->block_major >> 32), ((__u32*)(&user_req->block_major) + 1));
-        __put_user((__u32)(req->block_minor), (__u32*)&user_req->block_minor);
-        __put_user((__u32)(req->block_minor >> 32), ((__u32*)(&user_req->block_minor) + 1));
+        ret = __put_user(req->raw_minor, &user_req->raw_minor);
+        ret |= __put_user(req->block_major, &user_req->block_major);
+        ret |= __put_user(req->block_minor, &user_req->block_minor);
 
-        return ret;
+        return ret ? -EFAULT : 0;
 }
 
 static int raw_ioctl(unsigned fd, unsigned cmd, unsigned long arg)
@@ -2474,7 +2466,7 @@ static int raw_ioctl(unsigned fd, unsigned cmd, unsigned long arg)
         case RAW_SETBIND:
         case RAW_GETBIND: {
                 struct raw_config_request req;
-                struct raw32_config_request *user_req = compat_ptr(arg);
+                struct raw32_config_request __user *user_req = compat_ptr(arg);
                 mm_segment_t oldfs = get_fs();
 
                 if ((ret = get_raw32_request(&req, user_req)))