diff options
Diffstat (limited to 'fs/ncpfs/ioctl.c')
-rw-r--r-- | fs/ncpfs/ioctl.c | 71 |
1 files changed, 61 insertions, 10 deletions
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index c67b4bdcf71..3a97c95e1ca 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c @@ -14,6 +14,7 @@ #include <linux/ioctl.h> #include <linux/time.h> #include <linux/mm.h> +#include <linux/mount.h> #include <linux/highuid.h> #include <linux/smp_lock.h> #include <linux/vmalloc.h> @@ -261,7 +262,7 @@ ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) } #endif /* CONFIG_NCPFS_NLS */ -int ncp_ioctl(struct inode *inode, struct file *filp, +static int __ncp_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { struct ncp_server *server = NCP_SERVER(inode); @@ -388,11 +389,11 @@ int ncp_ioctl(struct inode *inode, struct file *filp, struct dentry* dentry = inode->i_sb->s_root; if (dentry) { - struct inode* inode = dentry->d_inode; + struct inode* s_inode = dentry->d_inode; - if (inode) { - sr.volNumber = NCP_FINFO(inode)->volNumber; - sr.dirEntNum = NCP_FINFO(inode)->dirEntNum; + if (s_inode) { + sr.volNumber = NCP_FINFO(s_inode)->volNumber; + sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum; sr.namespace = server->name_space[sr.volNumber]; } else DPRINTK("ncpfs: s_root->d_inode==NULL\n"); @@ -438,12 +439,12 @@ int ncp_ioctl(struct inode *inode, struct file *filp, dentry = inode->i_sb->s_root; server->root_setuped = 1; if (dentry) { - struct inode* inode = dentry->d_inode; + struct inode* s_inode = dentry->d_inode; if (inode) { - NCP_FINFO(inode)->volNumber = vnum; - NCP_FINFO(inode)->dirEntNum = de; - NCP_FINFO(inode)->DosDirNum = dosde; + NCP_FINFO(s_inode)->volNumber = vnum; + NCP_FINFO(s_inode)->dirEntNum = de; + NCP_FINFO(s_inode)->DosDirNum = dosde; } else DPRINTK("ncpfs: s_root->d_inode==NULL\n"); } else @@ -518,7 +519,6 @@ int ncp_ioctl(struct inode *inode, struct file *filp, } { struct ncp_lock_ioctl rqdata; - int result; if (copy_from_user(&rqdata, argp, sizeof(rqdata))) return -EFAULT; @@ -822,6 +822,57 @@ outrel: return -EINVAL; } +static int ncp_ioctl_need_write(unsigned int cmd) +{ + switch (cmd) { + case NCP_IOC_GET_FS_INFO: + case NCP_IOC_GET_FS_INFO_V2: + case NCP_IOC_NCPREQUEST: + case NCP_IOC_SETDENTRYTTL: + case NCP_IOC_SIGN_INIT: + case NCP_IOC_LOCKUNLOCK: + case NCP_IOC_SET_SIGN_WANTED: + return 1; + case NCP_IOC_GETOBJECTNAME: + case NCP_IOC_SETOBJECTNAME: + case NCP_IOC_GETPRIVATEDATA: + case NCP_IOC_SETPRIVATEDATA: + case NCP_IOC_SETCHARSETS: + case NCP_IOC_GETCHARSETS: + case NCP_IOC_CONN_LOGGED_IN: + case NCP_IOC_GETDENTRYTTL: + case NCP_IOC_GETMOUNTUID2: + case NCP_IOC_SIGN_WANTED: + case NCP_IOC_GETROOT: + case NCP_IOC_SETROOT: + return 0; + default: + /* unkown IOCTL command, assume write */ + return 1; + } +} + +int ncp_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + int ret; + + if (ncp_ioctl_need_write(cmd)) { + /* + * inside the ioctl(), any failures which + * are because of file_permission() are + * -EACCESS, so it seems consistent to keep + * that here. + */ + if (mnt_want_write(filp->f_path.mnt)) + return -EACCES; + } + ret = __ncp_ioctl(inode, filp, cmd, arg); + if (ncp_ioctl_need_write(cmd)) + mnt_drop_write(filp->f_path.mnt); + return ret; +} + #ifdef CONFIG_COMPAT long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { |