X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fncpfs%2Fioctl.c;h=8843a83d4ef03dc4242dd11646c78480736375cb;hb=7d8b6f8e7158f0f307fb8315de1fb962f0c717d9;hp=88df79356a1f333b75f079f6940dc9492709312d;hpb=ec9397bab20a628530ce3051167d3d0fcc2c1af7;p=linux-2.6.git diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index 88df79356..8843a83d4 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c @@ -7,19 +7,21 @@ * */ -#include - -#include +#include +#include #include #include #include #include #include #include +#include #include #include +#include + #include "ncplib_kernel.h" /* maximum limit for ncp_objectname_ioctl */ @@ -30,11 +32,13 @@ #define NCP_PACKET_SIZE_INTERNAL 65536 static int -ncp_get_fs_info(struct ncp_server* server, struct inode* inode, struct ncp_fs_info __user *arg) +ncp_get_fs_info(struct ncp_server * server, struct file *file, + struct ncp_fs_info __user *arg) { + struct inode *inode = file->f_path.dentry->d_inode; struct ncp_fs_info info; - if ((permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(file, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; } @@ -58,11 +62,84 @@ ncp_get_fs_info(struct ncp_server* server, struct inode* inode, struct ncp_fs_in } static int -ncp_get_fs_info_v2(struct ncp_server* server, struct inode* inode, struct ncp_fs_info_v2 __user * arg) +ncp_get_fs_info_v2(struct ncp_server * server, struct file *file, + struct ncp_fs_info_v2 __user * arg) { + struct inode *inode = file->f_path.dentry->d_inode; struct ncp_fs_info_v2 info2; - if ((permission(inode, MAY_WRITE, NULL) != 0) + 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; +} + +#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_path.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; } @@ -84,6 +161,11 @@ ncp_get_fs_info_v2(struct ncp_server* server, struct inode* inode, struct ncp_fs 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. @@ -188,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 ((permission(inode, MAY_WRITE, NULL) != 0) + 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; @@ -245,30 +339,46 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return ncp_conn_logged_in(inode->i_sb); case NCP_IOC_GET_FS_INFO: - return ncp_get_fs_info(server, inode, argp); + return ncp_get_fs_info(server, filp, argp); case NCP_IOC_GET_FS_INFO_V2: - return ncp_get_fs_info_v2(server, inode, argp); - - case NCP_IOC_GETMOUNTUID2: - { - unsigned long tmp = server->m.mounted_uid; - - if ( (permission(inode, MAY_READ, NULL) != 0) - && (current->uid != server->m.mounted_uid)) - { - return -EACCES; - } - if (put_user(tmp, (unsigned long __user *)argp)) + return ncp_get_fs_info_v2(server, filp, 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: { struct ncp_setroot_ioctl sr; - if ( (permission(inode, MAY_READ, NULL) != 0) + if ((file_permission(filp, MAY_READ) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -343,7 +453,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, #ifdef CONFIG_NCPFS_PACKET_SIGNING case NCP_IOC_SIGN_INIT: - if ((permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -366,7 +476,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return 0; case NCP_IOC_SIGN_WANTED: - if ( (permission(inode, MAY_READ, NULL) != 0) + if ((file_permission(filp, MAY_READ) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -379,7 +489,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, { int newstate; - if ( (permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -400,7 +510,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, #ifdef CONFIG_NCPFS_IOCTL_LOCKING case NCP_IOC_LOCKUNLOCK: - if ( (permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -472,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; @@ -496,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; @@ -508,15 +647,27 @@ 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) { - newname = ncp_kmalloc(user.object_name_len, GFP_USER); - if (!newname) return -ENOMEM; + newname = kmalloc(user.object_name_len, GFP_USER); + if (!newname) + return -ENOMEM; if (copy_from_user(newname, user.object_name, user.object_name_len)) { - ncp_kfree_s(newname, user.object_name_len); + kfree(newname); return -EFAULT; } } else { @@ -535,10 +686,13 @@ outrel: server->priv.len = 0; server->priv.data = NULL; /* leave critical section */ - if (oldprivate) ncp_kfree_s(oldprivate, oldprivatelen); - if (oldname) ncp_kfree_s(oldname, oldnamelen); + kfree(oldprivate); + 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; @@ -547,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; @@ -557,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(argp, &user32, 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; @@ -571,15 +748,26 @@ 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) { - new = ncp_kmalloc(user.len, GFP_USER); - if (!new) return -ENOMEM; + new = kmalloc(user.len, GFP_USER); + if (!new) + return -ENOMEM; if (copy_from_user(new, user.data, user.len)) { - ncp_kfree_s(new, user.len); + kfree(new); return -EFAULT; } } else { @@ -591,7 +779,7 @@ outrel: server->priv.len = user.len; server->priv.data = new; /* leave critical section */ - if (old) ncp_kfree_s(old, oldlen); + kfree(old); return 0; } @@ -605,7 +793,7 @@ outrel: #endif /* CONFIG_NCPFS_NLS */ case NCP_IOC_SETDENTRYTTL: - if ((permission(inode, MAY_WRITE, NULL) != 0) && + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) return -EACCES; { @@ -630,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 ((permission(inode, MAY_READ, NULL) != 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_path.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