Skip to content

Commit

Permalink
autofs/autofs4: Move compat_ioctl handling into fs
Browse files Browse the repository at this point in the history
Handling of autofs ioctl numbers does not need to be generic
and can easily be done directly in autofs itself.

This also pushes the BKL into autofs and autofs4 ioctl
methods.

Signed-off-by: Arnd Bergmann <[email protected]>
Acked-by: H. Peter Anvin <[email protected]>
Cc: Al Viro <[email protected]>
Cc: Ian Kent <[email protected]>
Cc: Autofs <[email protected]>
Cc: John Kacur <[email protected]>
Signed-off-by: Frederic Weisbecker <[email protected]>
  • Loading branch information
arndb authored and fweisbec committed Aug 8, 2010
1 parent 86a5ef7 commit c9243f5
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 39 deletions.
67 changes: 64 additions & 3 deletions fs/autofs/root.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/param.h>
#include <linux/time.h>
#include <linux/compat.h>
#include <linux/smp_lock.h>
#include "autofs_i.h"

Expand All @@ -25,13 +26,17 @@ static int autofs_root_symlink(struct inode *,struct dentry *,const char *);
static int autofs_root_unlink(struct inode *,struct dentry *);
static int autofs_root_rmdir(struct inode *,struct dentry *);
static int autofs_root_mkdir(struct inode *,struct dentry *,int);
static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
static long autofs_root_ioctl(struct file *,unsigned int,unsigned long);
static long autofs_root_compat_ioctl(struct file *,unsigned int,unsigned long);

const struct file_operations autofs_root_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = autofs_root_readdir,
.ioctl = autofs_root_ioctl,
.unlocked_ioctl = autofs_root_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = autofs_root_compat_ioctl,
#endif
};

const struct inode_operations autofs_root_inode_operations = {
Expand Down Expand Up @@ -492,6 +497,25 @@ static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode)
}

/* Get/set timeout ioctl() operation */
#ifdef CONFIG_COMPAT
static inline int autofs_compat_get_set_timeout(struct autofs_sb_info *sbi,
unsigned int __user *p)
{
unsigned long ntimeout;

if (get_user(ntimeout, p) ||
put_user(sbi->exp_timeout / HZ, p))
return -EFAULT;

if (ntimeout > UINT_MAX/HZ)
sbi->exp_timeout = 0;
else
sbi->exp_timeout = ntimeout * HZ;

return 0;
}
#endif

static inline int autofs_get_set_timeout(struct autofs_sb_info *sbi,
unsigned long __user *p)
{
Expand Down Expand Up @@ -546,7 +570,7 @@ static inline int autofs_expire_run(struct super_block *sb,
* ioctl()'s on the root directory is the chief method for the daemon to
* generate kernel reactions
*/
static int autofs_root_ioctl(struct inode *inode, struct file *filp,
static int autofs_do_root_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb);
Expand All @@ -571,6 +595,10 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp,
return 0;
case AUTOFS_IOC_PROTOVER: /* Get protocol version */
return autofs_get_protover(argp);
#ifdef CONFIG_COMPAT
case AUTOFS_IOC_SETTIMEOUT32:
return autofs_compat_get_set_timeout(sbi, argp);
#endif
case AUTOFS_IOC_SETTIMEOUT:
return autofs_get_set_timeout(sbi, argp);
case AUTOFS_IOC_EXPIRE:
Expand All @@ -579,4 +607,37 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp,
default:
return -ENOSYS;
}

}

static long autofs_root_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg)
{
int ret;

lock_kernel();
ret = autofs_do_root_ioctl(filp->f_path.dentry->d_inode,
filp, cmd, arg);
unlock_kernel();

return ret;
}

#ifdef CONFIG_COMPAT
static long autofs_root_compat_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg)
{
struct inode *inode = filp->f_path.dentry->d_inode;
int ret;

lock_kernel();
if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL)
ret = autofs_do_root_ioctl(inode, filp, cmd, arg);
else
ret = autofs_do_root_ioctl(inode, filp, cmd,
(unsigned long)compat_ptr(arg));
unlock_kernel();

return ret;
}
#endif
49 changes: 49 additions & 0 deletions fs/autofs4/root.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@
#include <linux/slab.h>
#include <linux/param.h>
#include <linux/time.h>
#include <linux/compat.h>
#include <linux/smp_lock.h>

#include "autofs_i.h"

static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
static int autofs4_dir_unlink(struct inode *,struct dentry *);
static int autofs4_dir_rmdir(struct inode *,struct dentry *);
static int autofs4_dir_mkdir(struct inode *,struct dentry *,int);
static long autofs4_root_ioctl(struct file *,unsigned int,unsigned long);
static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long);
static int autofs4_dir_open(struct inode *inode, struct file *file);
static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
static void *autofs4_follow_link(struct dentry *, struct nameidata *);
Expand All @@ -40,6 +43,9 @@ const struct file_operations autofs4_root_operations = {
.readdir = dcache_readdir,
.llseek = dcache_dir_lseek,
.unlocked_ioctl = autofs4_root_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = autofs4_root_compat_ioctl,
#endif
};

const struct file_operations autofs4_dir_operations = {
Expand Down Expand Up @@ -840,6 +846,26 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
}

/* Get/set timeout ioctl() operation */
#ifdef CONFIG_COMPAT
static inline int autofs4_compat_get_set_timeout(struct autofs_sb_info *sbi,
compat_ulong_t __user *p)
{
int rv;
unsigned long ntimeout;

if ((rv = get_user(ntimeout, p)) ||
(rv = put_user(sbi->exp_timeout/HZ, p)))
return rv;

if (ntimeout > UINT_MAX/HZ)
sbi->exp_timeout = 0;
else
sbi->exp_timeout = ntimeout * HZ;

return 0;
}
#endif

static inline int autofs4_get_set_timeout(struct autofs_sb_info *sbi,
unsigned long __user *p)
{
Expand Down Expand Up @@ -933,6 +959,10 @@ static int autofs4_root_ioctl_unlocked(struct inode *inode, struct file *filp,
return autofs4_get_protosubver(sbi, p);
case AUTOFS_IOC_SETTIMEOUT:
return autofs4_get_set_timeout(sbi, p);
#ifdef CONFIG_COMPAT
case AUTOFS_IOC_SETTIMEOUT32:
return autofs4_compat_get_set_timeout(sbi, p);
#endif

case AUTOFS_IOC_ASKUMOUNT:
return autofs4_ask_umount(filp->f_path.mnt, p);
Expand Down Expand Up @@ -961,3 +991,22 @@ static long autofs4_root_ioctl(struct file *filp,

return ret;
}

#ifdef CONFIG_COMPAT
static long autofs4_root_compat_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg)
{
struct inode *inode = filp->f_path.dentry->d_inode;
int ret;

lock_kernel();
if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL)
ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
else
ret = autofs4_root_ioctl_unlocked(inode, filp, cmd,
(unsigned long)compat_ptr(arg));
unlock_kernel();

return ret;
}
#endif
36 changes: 0 additions & 36 deletions fs/compat_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,23 +131,6 @@ static int w_long(unsigned int fd, unsigned int cmd,
return err;
}

static int rw_long(unsigned int fd, unsigned int cmd,
compat_ulong_t __user *argp)
{
mm_segment_t old_fs = get_fs();
int err;
unsigned long val;

if(get_user(val, argp))
return -EFAULT;
set_fs (KERNEL_DS);
err = sys_ioctl(fd, cmd, (unsigned long)&val);
set_fs (old_fs);
if (!err && put_user(val, argp))
return -EFAULT;
return err;
}

struct compat_video_event {
int32_t type;
compat_time_t timestamp;
Expand Down Expand Up @@ -594,12 +577,6 @@ static int do_smb_getmountuid(unsigned int fd, unsigned int cmd,
return err;
}

static int ioc_settimeout(unsigned int fd, unsigned int cmd,
compat_ulong_t __user *argp)
{
return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, argp);
}

/* Bluetooth ioctls */
#define HCIUARTSETPROTO _IOW('U', 200, int)
#define HCIUARTGETPROTO _IOR('U', 201, int)
Expand Down Expand Up @@ -1281,13 +1258,6 @@ COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE5)
COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS)
COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS)
COMPATIBLE_IOCTL(OSS_GETVERSION)
/* AUTOFS */
COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC)
COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER)
COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE)
COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI)
COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOSUBVER)
COMPATIBLE_IOCTL(AUTOFS_IOC_ASKUMOUNT)
/* Raw devices */
COMPATIBLE_IOCTL(RAW_SETBIND)
COMPATIBLE_IOCTL(RAW_GETBIND)
Expand Down Expand Up @@ -1552,9 +1522,6 @@ static long do_ioctl_trans(int fd, unsigned int cmd,
case RAW_GETBIND:
return raw_ioctl(fd, cmd, argp);
#endif
#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
case AUTOFS_IOC_SETTIMEOUT32:
return ioc_settimeout(fd, cmd, argp);
/* One SMB ioctl needs translations. */
#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t)
case SMB_IOC_GETMOUNTUID_32:
Expand Down Expand Up @@ -1609,9 +1576,6 @@ static long do_ioctl_trans(int fd, unsigned int cmd,
case KDSKBMETA:
case KDSKBLED:
case KDSETLED:
/* AUTOFS */
case AUTOFS_IOC_READY:
case AUTOFS_IOC_FAIL:
/* NBD */
case NBD_SET_SOCK:
case NBD_SET_BLKSIZE:
Expand Down
1 change: 1 addition & 0 deletions include/linux/auto_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ struct autofs_packet_expire {
#define AUTOFS_IOC_FAIL _IO(0x93,0x61)
#define AUTOFS_IOC_CATATONIC _IO(0x93,0x62)
#define AUTOFS_IOC_PROTOVER _IOR(0x93,0x63,int)
#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,compat_ulong_t)
#define AUTOFS_IOC_SETTIMEOUT _IOWR(0x93,0x64,unsigned long)
#define AUTOFS_IOC_EXPIRE _IOR(0x93,0x65,struct autofs_packet_expire)

Expand Down

0 comments on commit c9243f5

Please sign in to comment.