summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/compat_ioctl.c198
-rw-r--r--fs/ncpfs/dir.c3
-rw-r--r--fs/ncpfs/file.c3
-rw-r--r--fs/ncpfs/ioctl.c239
4 files changed, 216 insertions, 227 deletions
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 64b34533edea..27ca1aa30562 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -60,7 +60,6 @@
#include <linux/ctype.h>
#include <linux/ioctl32.h>
#include <linux/syscalls.h>
-#include <linux/ncp_fs.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/wireless.h>
@@ -2348,193 +2347,6 @@ static int rtc_ioctl(unsigned fd, unsigned cmd, unsigned long arg)
}
}
-#if defined(CONFIG_NCP_FS) || defined(CONFIG_NCP_FS_MODULE)
-struct ncp_ioctl_request_32 {
- u32 function;
- u32 size;
- compat_caddr_t data;
-};
-
-struct ncp_fs_info_v2_32 {
- s32 version;
- u32 mounted_uid;
- u32 connection;
- u32 buffer_size;
-
- u32 volume_number;
- u32 directory_id;
-
- u32 dummy1;
- u32 dummy2;
- u32 dummy3;
-};
-
-struct ncp_objectname_ioctl_32
-{
- s32 auth_type;
- u32 object_name_len;
- compat_caddr_t object_name; /* an userspace data, in most cases user name */
-};
-
-struct ncp_privatedata_ioctl_32
-{
- u32 len;
- compat_caddr_t data; /* ~1000 for NDS */
-};
-
-#define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct ncp_ioctl_request_32)
-#define NCP_IOC_GETMOUNTUID2_32 _IOW('n', 2, u32)
-#define NCP_IOC_GET_FS_INFO_V2_32 _IOWR('n', 4, struct ncp_fs_info_v2_32)
-#define NCP_IOC_GETOBJECTNAME_32 _IOWR('n', 9, struct ncp_objectname_ioctl_32)
-#define NCP_IOC_SETOBJECTNAME_32 _IOR('n', 9, struct ncp_objectname_ioctl_32)
-#define NCP_IOC_GETPRIVATEDATA_32 _IOWR('n', 10, struct ncp_privatedata_ioctl_32)
-#define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct ncp_privatedata_ioctl_32)
-
-static int do_ncp_ncprequest(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
- struct ncp_ioctl_request_32 n32;
- struct ncp_ioctl_request __user *p = compat_alloc_user_space(sizeof(*p));
-
- if (copy_from_user(&n32, compat_ptr(arg), sizeof(n32)) ||
- put_user(n32.function, &p->function) ||
- put_user(n32.size, &p->size) ||
- put_user(compat_ptr(n32.data), &p->data))
- return -EFAULT;
-
- return sys_ioctl(fd, NCP_IOC_NCPREQUEST, (unsigned long)p);
-}
-
-static int do_ncp_getmountuid2(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
- mm_segment_t old_fs = get_fs();
- __kernel_uid_t kuid;
- int err;
-
- cmd = NCP_IOC_GETMOUNTUID2;
-
- set_fs(KERNEL_DS);
- err = sys_ioctl(fd, cmd, (unsigned long)&kuid);
- set_fs(old_fs);
-
- if (!err)
- err = put_user(kuid,
- (unsigned int __user *) compat_ptr(arg));
-
- return err;
-}
-
-static int do_ncp_getfsinfo2(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
- mm_segment_t old_fs = get_fs();
- struct ncp_fs_info_v2_32 n32;
- struct ncp_fs_info_v2 n;
- int err;
-
- if (copy_from_user(&n32, compat_ptr(arg), sizeof(n32)))
- return -EFAULT;
- if (n32.version != NCP_GET_FS_INFO_VERSION_V2)
- return -EINVAL;
- n.version = NCP_GET_FS_INFO_VERSION_V2;
-
- set_fs(KERNEL_DS);
- err = sys_ioctl(fd, NCP_IOC_GET_FS_INFO_V2, (unsigned long)&n);
- set_fs(old_fs);
-
- if (!err) {
- n32.version = n.version;
- n32.mounted_uid = n.mounted_uid;
- n32.connection = n.connection;
- n32.buffer_size = n.buffer_size;
- n32.volume_number = n.volume_number;
- n32.directory_id = n.directory_id;
- n32.dummy1 = n.dummy1;
- n32.dummy2 = n.dummy2;
- n32.dummy3 = n.dummy3;
- err = copy_to_user(compat_ptr(arg), &n32, sizeof(n32)) ? -EFAULT : 0;
- }
- return err;
-}
-
-static int do_ncp_getobjectname(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
- struct ncp_objectname_ioctl_32 n32, __user *p32 = compat_ptr(arg);
- struct ncp_objectname_ioctl __user *p = compat_alloc_user_space(sizeof(*p));
- s32 auth_type;
- u32 name_len;
- int err;
-
- if (copy_from_user(&n32, p32, sizeof(n32)) ||
- put_user(n32.object_name_len, &p->object_name_len) ||
- put_user(compat_ptr(n32.object_name), &p->object_name))
- return -EFAULT;
-
- err = sys_ioctl(fd, NCP_IOC_GETOBJECTNAME, (unsigned long)p);
- if (err)
- return err;
-
- if (get_user(auth_type, &p->auth_type) ||
- put_user(auth_type, &p32->auth_type) ||
- get_user(name_len, &p->object_name_len) ||
- put_user(name_len, &p32->object_name_len))
- return -EFAULT;
-
- return 0;
-}
-
-static int do_ncp_setobjectname(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
- struct ncp_objectname_ioctl_32 n32, __user *p32 = compat_ptr(arg);
- struct ncp_objectname_ioctl __user *p = compat_alloc_user_space(sizeof(*p));
-
- if (copy_from_user(&n32, p32, sizeof(n32)) ||
- put_user(n32.auth_type, &p->auth_type) ||
- put_user(n32.object_name_len, &p->object_name_len) ||
- put_user(compat_ptr(n32.object_name), &p->object_name))
- return -EFAULT;
-
- return sys_ioctl(fd, NCP_IOC_SETOBJECTNAME, (unsigned long)p);
-}
-
-static int do_ncp_getprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
- struct ncp_privatedata_ioctl_32 n32, __user *p32 = compat_ptr(arg);
- struct ncp_privatedata_ioctl __user *p =
- compat_alloc_user_space(sizeof(*p));
- u32 len;
- int err;
-
- if (copy_from_user(&n32, p32, sizeof(n32)) ||
- put_user(n32.len, &p->len) ||
- put_user(compat_ptr(n32.data), &p->data))
- return -EFAULT;
-
- err = sys_ioctl(fd, NCP_IOC_GETPRIVATEDATA, (unsigned long)p);
- if (err)
- return err;
-
- if (get_user(len, &p->len) ||
- put_user(len, &p32->len))
- return -EFAULT;
-
- return 0;
-}
-
-static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
- struct ncp_privatedata_ioctl_32 n32;
- struct ncp_privatedata_ioctl_32 __user *p32 = compat_ptr(arg);
- struct ncp_privatedata_ioctl __user *p =
- compat_alloc_user_space(sizeof(*p));
-
- if (copy_from_user(&n32, p32, sizeof(n32)) ||
- put_user(n32.len, &p->len) ||
- put_user(compat_ptr(n32.data), &p->data))
- return -EFAULT;
-
- return sys_ioctl(fd, NCP_IOC_SETPRIVATEDATA, (unsigned long)p);
-}
-#endif
-
static int
lp_timeout_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
{
@@ -2748,16 +2560,6 @@ HANDLE_IOCTL(RTC_IRQP_SET32, rtc_ioctl)
HANDLE_IOCTL(RTC_EPOCH_READ32, rtc_ioctl)
HANDLE_IOCTL(RTC_EPOCH_SET32, rtc_ioctl)
-#if defined(CONFIG_NCP_FS) || defined(CONFIG_NCP_FS_MODULE)
-HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest)
-HANDLE_IOCTL(NCP_IOC_GETMOUNTUID2_32, do_ncp_getmountuid2)
-HANDLE_IOCTL(NCP_IOC_GET_FS_INFO_V2_32, do_ncp_getfsinfo2)
-HANDLE_IOCTL(NCP_IOC_GETOBJECTNAME_32, do_ncp_getobjectname)
-HANDLE_IOCTL(NCP_IOC_SETOBJECTNAME_32, do_ncp_setobjectname)
-HANDLE_IOCTL(NCP_IOC_GETPRIVATEDATA_32, do_ncp_getprivatedata)
-HANDLE_IOCTL(NCP_IOC_SETPRIVATEDATA_32, do_ncp_setprivatedata)
-#endif
-
/* dvb */
HANDLE_IOCTL(VIDEO_GET_EVENT, do_video_get_event)
HANDLE_IOCTL(VIDEO_STILLPICTURE, do_video_stillpicture)
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 =
.read = generic_read_dir,
.readdir = ncp_readdir,
.ioctl = ncp_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = ncp_compat_ioctl,
+#endif
};
struct 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 =
.read = ncp_file_read,
.write = ncp_file_write,
.ioctl = ncp_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = ncp_compat_ioctl,
+#endif
.mmap = ncp_mmap,
.release = ncp_release,
.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 @@
*
*/
-
-#include <asm/uaccess.h>
#include <linux/capability.h>
+#include <linux/compat.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/time.h>
#include <linux/mm.h>
#include <linux/highuid.h>
+#include <linux/smp_lock.h>
#include <linux/vmalloc.h>
#include <linux/ncp_fs.h>
+#include <asm/uaccess.h>
+
#include "ncplib_kernel.h"
/* maximum limit for ncp_objectname_ioctl */
@@ -89,6 +91,82 @@ ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,
return 0;
}
+#ifdef CONFIG_COMPAT
+struct compat_ncp_objectname_ioctl
+{
+ s32 auth_type;
+ u32 object_name_len;
+ compat_caddr_t object_name; /* an userspace data, in most cases user name */
+};
+
+struct compat_ncp_fs_info_v2 {
+ s32 version;
+ u32 mounted_uid;
+ u32 connection;
+ u32 buffer_size;
+
+ u32 volume_number;
+ u32 directory_id;
+
+ u32 dummy1;
+ u32 dummy2;
+ u32 dummy3;
+};
+
+struct compat_ncp_ioctl_request {
+ u32 function;
+ u32 size;
+ compat_caddr_t data;
+};
+
+struct compat_ncp_privatedata_ioctl
+{
+ u32 len;
+ compat_caddr_t data; /* ~1000 for NDS */
+};
+
+#define NCP_IOC_GET_FS_INFO_V2_32 _IOWR('n', 4, struct compat_ncp_fs_info_v2)
+#define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct compat_ncp_ioctl_request)
+#define NCP_IOC_GETOBJECTNAME_32 _IOWR('n', 9, struct compat_ncp_objectname_ioctl)
+#define NCP_IOC_SETOBJECTNAME_32 _IOR('n', 9, struct compat_ncp_objectname_ioctl)
+#define NCP_IOC_GETPRIVATEDATA_32 _IOWR('n', 10, struct compat_ncp_privatedata_ioctl)
+#define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct compat_ncp_privatedata_ioctl)
+
+static int
+ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,
+ struct compat_ncp_fs_info_v2 __user * arg)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ struct compat_ncp_fs_info_v2 info2;
+
+ if ((file_permission(file, MAY_WRITE) != 0)
+ && (current->uid != server->m.mounted_uid)) {
+ return -EACCES;
+ }
+ if (copy_from_user(&info2, arg, sizeof(info2)))
+ return -EFAULT;
+
+ if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
+ DPRINTK("info.version invalid: %d\n", info2.version);
+ return -EINVAL;
+ }
+ info2.mounted_uid = server->m.mounted_uid;
+ info2.connection = server->connection;
+ info2.buffer_size = server->buffer_size;
+ info2.volume_number = NCP_FINFO(inode)->volNumber;
+ info2.directory_id = NCP_FINFO(inode)->DosDirNum;
+ info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
+
+ if (copy_to_user(arg, &info2, sizeof(info2)))
+ return -EFAULT;
+ return 0;
+}
+#endif
+
+#define NCP_IOC_GETMOUNTUID16 _IOW('n', 2, u16)
+#define NCP_IOC_GETMOUNTUID32 _IOW('n', 2, u32)
+#define NCP_IOC_GETMOUNTUID64 _IOW('n', 2, u64)
+
#ifdef CONFIG_NCPFS_NLS
/* Here we are select the iocharset and the codepage for NLS.
* Thanks Petr Vandrovec for idea and many hints.
@@ -192,12 +270,24 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
void __user *argp = (void __user *)arg;
switch (cmd) {
+#ifdef CONFIG_COMPAT
+ case NCP_IOC_NCPREQUEST_32:
+#endif
case NCP_IOC_NCPREQUEST:
-
if ((file_permission(filp, MAY_WRITE) != 0)
&& (current->uid != server->m.mounted_uid)) {
return -EACCES;
}
+#ifdef CONFIG_COMPAT
+ if (cmd == NCP_IOC_NCPREQUEST_32) {
+ struct compat_ncp_ioctl_request request32;
+ if (copy_from_user(&request32, argp, sizeof(request32)))
+ return -EFAULT;
+ request.function = request32.function;
+ request.size = request32.size;
+ request.data = compat_ptr(request32.data);
+ } else
+#endif
if (copy_from_user(&request, argp, sizeof(request)))
return -EFAULT;
@@ -254,19 +344,35 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
case NCP_IOC_GET_FS_INFO_V2:
return ncp_get_fs_info_v2(server, filp, argp);
- case NCP_IOC_GETMOUNTUID2:
- {
- unsigned long tmp = server->m.mounted_uid;
-
- if ((file_permission(filp, MAY_READ) != 0)
- && (current->uid != server->m.mounted_uid))
- {
- return -EACCES;
- }
- if (put_user(tmp, (unsigned long __user *)argp))
+#ifdef CONFIG_COMPAT
+ case NCP_IOC_GET_FS_INFO_V2_32:
+ return ncp_get_compat_fs_info_v2(server, filp, argp);
+#endif
+ /* we have too many combinations of CONFIG_COMPAT,
+ * CONFIG_64BIT and CONFIG_UID16, so just handle
+ * any of the possible ioctls */
+ case NCP_IOC_GETMOUNTUID16:
+ case NCP_IOC_GETMOUNTUID32:
+ case NCP_IOC_GETMOUNTUID64:
+ if ((file_permission(filp, MAY_READ) != 0)
+ && (current->uid != server->m.mounted_uid)) {
+ return -EACCES;
+ }
+ if (cmd == NCP_IOC_GETMOUNTUID16) {
+ u16 uid;
+ SET_UID(uid, server->m.mounted_uid);
+ if (put_user(uid, (u16 __user *)argp))
+ return -EFAULT;
+ } else if (cmd == NCP_IOC_GETMOUNTUID32) {
+ if (put_user(server->m.mounted_uid,
+ (u32 __user *)argp))
+ return -EFAULT;
+ } else {
+ if (put_user(server->m.mounted_uid,
+ (u64 __user *)argp))
return -EFAULT;
- return 0;
}
+ return 0;
case NCP_IOC_GETROOT:
{
@@ -476,6 +582,32 @@ outrel:
}
#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
+#ifdef CONFIG_COMPAT
+ case NCP_IOC_GETOBJECTNAME_32:
+ if (current->uid != server->m.mounted_uid) {
+ return -EACCES;
+ }
+ {
+ struct compat_ncp_objectname_ioctl user;
+ size_t outl;
+
+ if (copy_from_user(&user, argp, sizeof(user)))
+ return -EFAULT;
+ user.auth_type = server->auth.auth_type;
+ outl = user.object_name_len;
+ user.object_name_len = server->auth.object_name_len;
+ if (outl > user.object_name_len)
+ outl = user.object_name_len;
+ if (outl) {
+ if (copy_to_user(compat_ptr(user.object_name),
+ server->auth.object_name,
+ outl)) return -EFAULT;
+ }
+ if (copy_to_user(argp, &user, sizeof(user)))
+ return -EFAULT;
+ return 0;
+ }
+#endif
case NCP_IOC_GETOBJECTNAME:
if (current->uid != server->m.mounted_uid) {
return -EACCES;
@@ -500,6 +632,9 @@ outrel:
return -EFAULT;
return 0;
}
+#ifdef CONFIG_COMPAT
+ case NCP_IOC_SETOBJECTNAME_32:
+#endif
case NCP_IOC_SETOBJECTNAME:
if (current->uid != server->m.mounted_uid) {
return -EACCES;
@@ -512,8 +647,19 @@ outrel:
void* oldprivate;
size_t oldprivatelen;
+#ifdef CONFIG_COMPAT
+ if (cmd == NCP_IOC_SETOBJECTNAME_32) {
+ struct compat_ncp_objectname_ioctl user32;
+ if (copy_from_user(&user32, argp, sizeof(user32)))
+ return -EFAULT;
+ user.auth_type = user32.auth_type;
+ user.object_name_len = user32.object_name_len;
+ user.object_name = compat_ptr(user32.object_name);
+ } else
+#endif
if (copy_from_user(&user, argp, sizeof(user)))
return -EFAULT;
+
if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN)
return -ENOMEM;
if (user.object_name_len) {
@@ -544,6 +690,9 @@ outrel:
kfree(oldname);
return 0;
}
+#ifdef CONFIG_COMPAT
+ case NCP_IOC_GETPRIVATEDATA_32:
+#endif
case NCP_IOC_GETPRIVATEDATA:
if (current->uid != server->m.mounted_uid) {
return -EACCES;
@@ -552,8 +701,18 @@ outrel:
struct ncp_privatedata_ioctl user;
size_t outl;
+#ifdef CONFIG_COMPAT
+ if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
+ struct compat_ncp_privatedata_ioctl user32;
+ if (copy_from_user(&user32, argp, sizeof(user32)))
+ return -EFAULT;
+ user.len = user32.len;
+ user.data = compat_ptr(user32.data);
+ } else
+#endif
if (copy_from_user(&user, argp, sizeof(user)))
return -EFAULT;
+
outl = user.len;
user.len = server->priv.len;
if (outl > user.len) outl = user.len;
@@ -562,10 +721,23 @@ outrel:
server->priv.data,
outl)) return -EFAULT;
}
+#ifdef CONFIG_COMPAT
+ if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
+ struct compat_ncp_privatedata_ioctl user32;
+ user32.len = user.len;
+ user32.data = (unsigned long) user.data;
+ if (copy_to_user(&user32, argp, sizeof(user32)))
+ return -EFAULT;
+ } else
+#endif
if (copy_to_user(argp, &user, sizeof(user)))
return -EFAULT;
+
return 0;
}
+#ifdef CONFIG_COMPAT
+ case NCP_IOC_SETPRIVATEDATA_32:
+#endif
case NCP_IOC_SETPRIVATEDATA:
if (current->uid != server->m.mounted_uid) {
return -EACCES;
@@ -576,8 +748,18 @@ outrel:
void* old;
size_t oldlen;
+#ifdef CONFIG_COMPAT
+ if (cmd == NCP_IOC_SETPRIVATEDATA_32) {
+ struct compat_ncp_privatedata_ioctl user32;
+ if (copy_from_user(&user32, argp, sizeof(user32)))
+ return -EFAULT;
+ user.len = user32.len;
+ user.data = compat_ptr(user32.data);
+ } else
+#endif
if (copy_from_user(&user, argp, sizeof(user)))
return -EFAULT;
+
if (user.len > NCP_PRIVATE_DATA_MAX_LEN)
return -ENOMEM;
if (user.len) {
@@ -636,20 +818,19 @@ outrel:
}
}
-/* #ifdef CONFIG_UID16 */
- /* NCP_IOC_GETMOUNTUID may be same as NCP_IOC_GETMOUNTUID2,
- so we have this out of switch */
- if (cmd == NCP_IOC_GETMOUNTUID) {
- __kernel_uid_t uid = 0;
- if ((file_permission(filp, MAY_READ) != 0)
- && (current->uid != server->m.mounted_uid)) {
- return -EACCES;
- }
- SET_UID(uid, server->m.mounted_uid);
- if (put_user(uid, (__kernel_uid_t __user *)argp))
- return -EFAULT;
- return 0;
- }
-/* #endif */
return -EINVAL;
}
+
+#ifdef CONFIG_COMPAT
+long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ int ret;
+
+ lock_kernel();
+ arg = (unsigned long) compat_ptr(arg);
+ ret = ncp_ioctl(inode, file, cmd, arg);
+ unlock_kernel();
+ return ret;
+}
+#endif