aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ncpfs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ncpfs/ioctl.c')
-rw-r--r--fs/ncpfs/ioctl.c239
1 files changed, 210 insertions, 29 deletions
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