aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ncpfs
diff options
context:
space:
mode:
authorPetr Vandrovec <petr@vandrovec.name>2006-10-01 02:27:55 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-01 03:39:23 -0400
commit54f67f631dfc25ca7a8b19200e34013abc974337 (patch)
tree96c481c2723e1f5f626110c9a7f1c4a07b9ee056 /fs/ncpfs
parent89bbc03c01f68e627a2b120963f136e2815f0d84 (diff)
[PATCH] Move ncpfs 32bit compat ioctl to ncpfs
The ncp specific compat ioctls are clearly local to one file system, so the code can better live there. This version of the patch moves everything into the generic ioctl handler and uses it for both 32 and 64 bit calls. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Petr Vandrovec <petr@vandrovec.name> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/ncpfs')
-rw-r--r--fs/ncpfs/dir.c3
-rw-r--r--fs/ncpfs/file.c3
-rw-r--r--fs/ncpfs/ioctl.c239
3 files changed, 216 insertions, 29 deletions
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index b4ee89250e95..458b3b785194 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -53,6 +53,9 @@ const struct file_operations ncp_dir_operations =
53 .read = generic_read_dir, 53 .read = generic_read_dir,
54 .readdir = ncp_readdir, 54 .readdir = ncp_readdir,
55 .ioctl = ncp_ioctl, 55 .ioctl = ncp_ioctl,
56#ifdef CONFIG_COMPAT
57 .compat_ioctl = ncp_compat_ioctl,
58#endif
56}; 59};
57 60
58struct inode_operations ncp_dir_inode_operations = 61struct inode_operations ncp_dir_inode_operations =
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index e6b7c67cf057..df37524b85db 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -289,6 +289,9 @@ const struct file_operations ncp_file_operations =
289 .read = ncp_file_read, 289 .read = ncp_file_read,
290 .write = ncp_file_write, 290 .write = ncp_file_write,
291 .ioctl = ncp_ioctl, 291 .ioctl = ncp_ioctl,
292#ifdef CONFIG_COMPAT
293 .compat_ioctl = ncp_compat_ioctl,
294#endif
292 .mmap = ncp_mmap, 295 .mmap = ncp_mmap,
293 .release = ncp_release, 296 .release = ncp_release,
294 .fsync = ncp_fsync, 297 .fsync = ncp_fsync,
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index 42039fe0653c..a89ac84a8241 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -7,19 +7,21 @@
7 * 7 *
8 */ 8 */
9 9
10
11#include <asm/uaccess.h>
12#include <linux/capability.h> 10#include <linux/capability.h>
11#include <linux/compat.h>
13#include <linux/errno.h> 12#include <linux/errno.h>
14#include <linux/fs.h> 13#include <linux/fs.h>
15#include <linux/ioctl.h> 14#include <linux/ioctl.h>
16#include <linux/time.h> 15#include <linux/time.h>
17#include <linux/mm.h> 16#include <linux/mm.h>
18#include <linux/highuid.h> 17#include <linux/highuid.h>
18#include <linux/smp_lock.h>
19#include <linux/vmalloc.h> 19#include <linux/vmalloc.h>
20 20
21#include <linux/ncp_fs.h> 21#include <linux/ncp_fs.h>
22 22
23#include <asm/uaccess.h>
24
23#include "ncplib_kernel.h" 25#include "ncplib_kernel.h"
24 26
25/* maximum limit for ncp_objectname_ioctl */ 27/* maximum limit for ncp_objectname_ioctl */
@@ -89,6 +91,82 @@ ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,
89 return 0; 91 return 0;
90} 92}
91 93
94#ifdef CONFIG_COMPAT
95struct compat_ncp_objectname_ioctl
96{
97 s32 auth_type;
98 u32 object_name_len;
99 compat_caddr_t object_name; /* an userspace data, in most cases user name */
100};
101
102struct compat_ncp_fs_info_v2 {
103 s32 version;
104 u32 mounted_uid;
105 u32 connection;
106 u32 buffer_size;
107
108 u32 volume_number;
109 u32 directory_id;
110
111 u32 dummy1;
112 u32 dummy2;
113 u32 dummy3;
114};
115
116struct compat_ncp_ioctl_request {
117 u32 function;
118 u32 size;
119 compat_caddr_t data;
120};
121
122struct compat_ncp_privatedata_ioctl
123{
124 u32 len;
125 compat_caddr_t data; /* ~1000 for NDS */
126};
127
128#define NCP_IOC_GET_FS_INFO_V2_32 _IOWR('n', 4, struct compat_ncp_fs_info_v2)
129#define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct compat_ncp_ioctl_request)
130#define NCP_IOC_GETOBJECTNAME_32 _IOWR('n', 9, struct compat_ncp_objectname_ioctl)
131#define NCP_IOC_SETOBJECTNAME_32 _IOR('n', 9, struct compat_ncp_objectname_ioctl)
132#define NCP_IOC_GETPRIVATEDATA_32 _IOWR('n', 10, struct compat_ncp_privatedata_ioctl)
133#define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct compat_ncp_privatedata_ioctl)
134
135static int
136ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,
137 struct compat_ncp_fs_info_v2 __user * arg)
138{
139 struct inode *inode = file->f_dentry->d_inode;
140 struct compat_ncp_fs_info_v2 info2;
141
142 if ((file_permission(file, MAY_WRITE) != 0)
143 && (current->uid != server->m.mounted_uid)) {
144 return -EACCES;
145 }
146 if (copy_from_user(&info2, arg, sizeof(info2)))
147 return -EFAULT;
148
149 if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
150 DPRINTK("info.version invalid: %d\n", info2.version);
151 return -EINVAL;
152 }
153 info2.mounted_uid = server->m.mounted_uid;
154 info2.connection = server->connection;
155 info2.buffer_size = server->buffer_size;
156 info2.volume_number = NCP_FINFO(inode)->volNumber;
157 info2.directory_id = NCP_FINFO(inode)->DosDirNum;
158 info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
159
160 if (copy_to_user(arg, &info2, sizeof(info2)))
161 return -EFAULT;
162 return 0;
163}
164#endif
165
166#define NCP_IOC_GETMOUNTUID16 _IOW('n', 2, u16)
167#define NCP_IOC_GETMOUNTUID32 _IOW('n', 2, u32)
168#define NCP_IOC_GETMOUNTUID64 _IOW('n', 2, u64)
169
92#ifdef CONFIG_NCPFS_NLS 170#ifdef CONFIG_NCPFS_NLS
93/* Here we are select the iocharset and the codepage for NLS. 171/* Here we are select the iocharset and the codepage for NLS.
94 * Thanks Petr Vandrovec for idea and many hints. 172 * Thanks Petr Vandrovec for idea and many hints.
@@ -192,12 +270,24 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
192 void __user *argp = (void __user *)arg; 270 void __user *argp = (void __user *)arg;
193 271
194 switch (cmd) { 272 switch (cmd) {
273#ifdef CONFIG_COMPAT
274 case NCP_IOC_NCPREQUEST_32:
275#endif
195 case NCP_IOC_NCPREQUEST: 276 case NCP_IOC_NCPREQUEST:
196
197 if ((file_permission(filp, MAY_WRITE) != 0) 277 if ((file_permission(filp, MAY_WRITE) != 0)
198 && (current->uid != server->m.mounted_uid)) { 278 && (current->uid != server->m.mounted_uid)) {
199 return -EACCES; 279 return -EACCES;
200 } 280 }
281#ifdef CONFIG_COMPAT
282 if (cmd == NCP_IOC_NCPREQUEST_32) {
283 struct compat_ncp_ioctl_request request32;
284 if (copy_from_user(&request32, argp, sizeof(request32)))
285 return -EFAULT;
286 request.function = request32.function;
287 request.size = request32.size;
288 request.data = compat_ptr(request32.data);
289 } else
290#endif
201 if (copy_from_user(&request, argp, sizeof(request))) 291 if (copy_from_user(&request, argp, sizeof(request)))
202 return -EFAULT; 292 return -EFAULT;
203 293
@@ -254,19 +344,35 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
254 case NCP_IOC_GET_FS_INFO_V2: 344 case NCP_IOC_GET_FS_INFO_V2:
255 return ncp_get_fs_info_v2(server, filp, argp); 345 return ncp_get_fs_info_v2(server, filp, argp);
256 346
257 case NCP_IOC_GETMOUNTUID2: 347#ifdef CONFIG_COMPAT
258 { 348 case NCP_IOC_GET_FS_INFO_V2_32:
259 unsigned long tmp = server->m.mounted_uid; 349 return ncp_get_compat_fs_info_v2(server, filp, argp);
260 350#endif
261 if ((file_permission(filp, MAY_READ) != 0) 351 /* we have too many combinations of CONFIG_COMPAT,
262 && (current->uid != server->m.mounted_uid)) 352 * CONFIG_64BIT and CONFIG_UID16, so just handle
263 { 353 * any of the possible ioctls */
264 return -EACCES; 354 case NCP_IOC_GETMOUNTUID16:
265 } 355 case NCP_IOC_GETMOUNTUID32:
266 if (put_user(tmp, (unsigned long __user *)argp)) 356 case NCP_IOC_GETMOUNTUID64:
357 if ((file_permission(filp, MAY_READ) != 0)
358 && (current->uid != server->m.mounted_uid)) {
359 return -EACCES;
360 }
361 if (cmd == NCP_IOC_GETMOUNTUID16) {
362 u16 uid;
363 SET_UID(uid, server->m.mounted_uid);
364 if (put_user(uid, (u16 __user *)argp))
365 return -EFAULT;
366 } else if (cmd == NCP_IOC_GETMOUNTUID32) {
367 if (put_user(server->m.mounted_uid,
368 (u32 __user *)argp))
369 return -EFAULT;
370 } else {
371 if (put_user(server->m.mounted_uid,
372 (u64 __user *)argp))
267 return -EFAULT; 373 return -EFAULT;
268 return 0;
269 } 374 }
375 return 0;
270 376
271 case NCP_IOC_GETROOT: 377 case NCP_IOC_GETROOT:
272 { 378 {
@@ -476,6 +582,32 @@ outrel:
476 } 582 }
477#endif /* CONFIG_NCPFS_IOCTL_LOCKING */ 583#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
478 584
585#ifdef CONFIG_COMPAT
586 case NCP_IOC_GETOBJECTNAME_32:
587 if (current->uid != server->m.mounted_uid) {
588 return -EACCES;
589 }
590 {
591 struct compat_ncp_objectname_ioctl user;
592 size_t outl;
593
594 if (copy_from_user(&user, argp, sizeof(user)))
595 return -EFAULT;
596 user.auth_type = server->auth.auth_type;
597 outl = user.object_name_len;
598 user.object_name_len = server->auth.object_name_len;
599 if (outl > user.object_name_len)
600 outl = user.object_name_len;
601 if (outl) {
602 if (copy_to_user(compat_ptr(user.object_name),
603 server->auth.object_name,
604 outl)) return -EFAULT;
605 }
606 if (copy_to_user(argp, &user, sizeof(user)))
607 return -EFAULT;
608 return 0;
609 }
610#endif
479 case NCP_IOC_GETOBJECTNAME: 611 case NCP_IOC_GETOBJECTNAME:
480 if (current->uid != server->m.mounted_uid) { 612 if (current->uid != server->m.mounted_uid) {
481 return -EACCES; 613 return -EACCES;
@@ -500,6 +632,9 @@ outrel:
500 return -EFAULT; 632 return -EFAULT;
501 return 0; 633 return 0;
502 } 634 }
635#ifdef CONFIG_COMPAT
636 case NCP_IOC_SETOBJECTNAME_32:
637#endif
503 case NCP_IOC_SETOBJECTNAME: 638 case NCP_IOC_SETOBJECTNAME:
504 if (current->uid != server->m.mounted_uid) { 639 if (current->uid != server->m.mounted_uid) {
505 return -EACCES; 640 return -EACCES;
@@ -512,8 +647,19 @@ outrel:
512 void* oldprivate; 647 void* oldprivate;
513 size_t oldprivatelen; 648 size_t oldprivatelen;
514 649
650#ifdef CONFIG_COMPAT
651 if (cmd == NCP_IOC_SETOBJECTNAME_32) {
652 struct compat_ncp_objectname_ioctl user32;
653 if (copy_from_user(&user32, argp, sizeof(user32)))
654 return -EFAULT;
655 user.auth_type = user32.auth_type;
656 user.object_name_len = user32.object_name_len;
657 user.object_name = compat_ptr(user32.object_name);
658 } else
659#endif
515 if (copy_from_user(&user, argp, sizeof(user))) 660 if (copy_from_user(&user, argp, sizeof(user)))
516 return -EFAULT; 661 return -EFAULT;
662
517 if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN) 663 if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN)
518 return -ENOMEM; 664 return -ENOMEM;
519 if (user.object_name_len) { 665 if (user.object_name_len) {
@@ -544,6 +690,9 @@ outrel:
544 kfree(oldname); 690 kfree(oldname);
545 return 0; 691 return 0;
546 } 692 }
693#ifdef CONFIG_COMPAT
694 case NCP_IOC_GETPRIVATEDATA_32:
695#endif
547 case NCP_IOC_GETPRIVATEDATA: 696 case NCP_IOC_GETPRIVATEDATA:
548 if (current->uid != server->m.mounted_uid) { 697 if (current->uid != server->m.mounted_uid) {
549 return -EACCES; 698 return -EACCES;
@@ -552,8 +701,18 @@ outrel:
552 struct ncp_privatedata_ioctl user; 701 struct ncp_privatedata_ioctl user;
553 size_t outl; 702 size_t outl;
554 703
704#ifdef CONFIG_COMPAT
705 if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
706 struct compat_ncp_privatedata_ioctl user32;
707 if (copy_from_user(&user32, argp, sizeof(user32)))
708 return -EFAULT;
709 user.len = user32.len;
710 user.data = compat_ptr(user32.data);
711 } else
712#endif
555 if (copy_from_user(&user, argp, sizeof(user))) 713 if (copy_from_user(&user, argp, sizeof(user)))
556 return -EFAULT; 714 return -EFAULT;
715
557 outl = user.len; 716 outl = user.len;
558 user.len = server->priv.len; 717 user.len = server->priv.len;
559 if (outl > user.len) outl = user.len; 718 if (outl > user.len) outl = user.len;
@@ -562,10 +721,23 @@ outrel:
562 server->priv.data, 721 server->priv.data,
563 outl)) return -EFAULT; 722 outl)) return -EFAULT;
564 } 723 }
724#ifdef CONFIG_COMPAT
725 if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
726 struct compat_ncp_privatedata_ioctl user32;
727 user32.len = user.len;
728 user32.data = (unsigned long) user.data;
729 if (copy_to_user(&user32, argp, sizeof(user32)))
730 return -EFAULT;
731 } else
732#endif
565 if (copy_to_user(argp, &user, sizeof(user))) 733 if (copy_to_user(argp, &user, sizeof(user)))
566 return -EFAULT; 734 return -EFAULT;
735
567 return 0; 736 return 0;
568 } 737 }
738#ifdef CONFIG_COMPAT
739 case NCP_IOC_SETPRIVATEDATA_32:
740#endif
569 case NCP_IOC_SETPRIVATEDATA: 741 case NCP_IOC_SETPRIVATEDATA:
570 if (current->uid != server->m.mounted_uid) { 742 if (current->uid != server->m.mounted_uid) {
571 return -EACCES; 743 return -EACCES;
@@ -576,8 +748,18 @@ outrel:
576 void* old; 748 void* old;
577 size_t oldlen; 749 size_t oldlen;
578 750
751#ifdef CONFIG_COMPAT
752 if (cmd == NCP_IOC_SETPRIVATEDATA_32) {
753 struct compat_ncp_privatedata_ioctl user32;
754 if (copy_from_user(&user32, argp, sizeof(user32)))
755 return -EFAULT;
756 user.len = user32.len;
757 user.data = compat_ptr(user32.data);
758 } else
759#endif
579 if (copy_from_user(&user, argp, sizeof(user))) 760 if (copy_from_user(&user, argp, sizeof(user)))
580 return -EFAULT; 761 return -EFAULT;
762
581 if (user.len > NCP_PRIVATE_DATA_MAX_LEN) 763 if (user.len > NCP_PRIVATE_DATA_MAX_LEN)
582 return -ENOMEM; 764 return -ENOMEM;
583 if (user.len) { 765 if (user.len) {
@@ -636,20 +818,19 @@ outrel:
636 } 818 }
637 819
638 } 820 }
639/* #ifdef CONFIG_UID16 */
640 /* NCP_IOC_GETMOUNTUID may be same as NCP_IOC_GETMOUNTUID2,
641 so we have this out of switch */
642 if (cmd == NCP_IOC_GETMOUNTUID) {
643 __kernel_uid_t uid = 0;
644 if ((file_permission(filp, MAY_READ) != 0)
645 && (current->uid != server->m.mounted_uid)) {
646 return -EACCES;
647 }
648 SET_UID(uid, server->m.mounted_uid);
649 if (put_user(uid, (__kernel_uid_t __user *)argp))
650 return -EFAULT;
651 return 0;
652 }
653/* #endif */
654 return -EINVAL; 821 return -EINVAL;
655} 822}
823
824#ifdef CONFIG_COMPAT
825long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
826{
827 struct inode *inode = file->f_dentry->d_inode;
828 int ret;
829
830 lock_kernel();
831 arg = (unsigned long) compat_ptr(arg);
832 ret = ncp_ioctl(inode, file, cmd, arg);
833 unlock_kernel();
834 return ret;
835}
836#endif