LCOV - code coverage report
Current view: top level - lkbce/fs/autofs4 - dev-ioctl.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 134 320 41.9 %
Date: 2017-01-25 Functions: 13 31 41.9 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2008 Red Hat, Inc. All rights reserved.
       3             :  * Copyright 2008 Ian Kent <raven@themaw.net>
       4             :  *
       5             :  * This file is part of the Linux kernel and is made available under
       6             :  * the terms of the GNU General Public License, version 2, or at your
       7             :  * option, any later version, incorporated herein by reference.
       8             :  */
       9             : 
      10             : #include <linux/module.h>
      11             : #include <linux/vmalloc.h>
      12             : #include <linux/miscdevice.h>
      13             : #include <linux/init.h>
      14             : #include <linux/wait.h>
      15             : #include <linux/namei.h>
      16             : #include <linux/fcntl.h>
      17             : #include <linux/file.h>
      18             : #include <linux/fdtable.h>
      19             : #include <linux/sched.h>
      20             : #include <linux/compat.h>
      21             : #include <linux/syscalls.h>
      22             : #include <linux/magic.h>
      23             : #include <linux/dcache.h>
      24             : #include <linux/uaccess.h>
      25             : 
      26             : #include "autofs_i.h"
      27             : 
      28             : /*
      29             :  * This module implements an interface for routing autofs ioctl control
      30             :  * commands via a miscellaneous device file.
      31             :  *
      32             :  * The alternate interface is needed because we need to be able open
      33             :  * an ioctl file descriptor on an autofs mount that may be covered by
      34             :  * another mount. This situation arises when starting automount(8)
      35             :  * or other user space daemon which uses direct mounts or offset
      36             :  * mounts (used for autofs lazy mount/umount of nested mount trees),
      37             :  * which have been left busy at at service shutdown.
      38             :  */
      39             : 
      40             : #define AUTOFS_DEV_IOCTL_SIZE   sizeof(struct autofs_dev_ioctl)
      41             : 
      42           1 : typedef int (*ioctl_fn)(struct file *, struct autofs_sb_info *,
      43             :                         struct autofs_dev_ioctl *);
      44             : 
      45             : static int check_name(const char *name)
      46             : {
      47           8 :         if (!strchr(name, '/'))
      48           2 :                 return -EINVAL;
      49           2 :         return 0;
      50             : }
      51             : 
      52             : /*
      53             :  * Check a string doesn't overrun the chunk of
      54             :  * memory we copied from user land.
      55             :  */
      56             : static int invalid_str(char *str, size_t size)
      57             : {
      58           8 :         if (memchr(str, 0, size))
      59           2 :                 return 0;
      60           2 :         return -EINVAL;
      61             : }
      62             : 
      63             : /*
      64             :  * Check that the user compiled against correct version of autofs
      65             :  * misc device code.
      66             :  *
      67             :  * As well as checking the version compatibility this always copies
      68             :  * the kernel interface version out.
      69             :  */
      70             : static int check_dev_ioctl_version(int cmd, struct autofs_dev_ioctl *param)
      71             : {
      72           4 :         int err = 0;
      73           2 : 
      74           4 :         if ((AUTOFS_DEV_IOCTL_VERSION_MAJOR != param->ver_major) ||
      75             :             (AUTOFS_DEV_IOCTL_VERSION_MINOR < param->ver_minor)) {
      76           6 :                 AUTOFS_WARN("ioctl control interface version mismatch: "
      77             :                      "kernel(%u.%u), user(%u.%u), cmd(%d)",
      78             :                      AUTOFS_DEV_IOCTL_VERSION_MAJOR,
      79             :                      AUTOFS_DEV_IOCTL_VERSION_MINOR,
      80             :                      param->ver_major, param->ver_minor, cmd);
      81           2 :                 err = -EINVAL;
      82             :         }
      83             : 
      84             :         /* Fill in the kernel version. */
      85           4 :         param->ver_major = AUTOFS_DEV_IOCTL_VERSION_MAJOR;
      86           4 :         param->ver_minor = AUTOFS_DEV_IOCTL_VERSION_MINOR;
      87             : 
      88           4 :         return err;
      89             : }
      90             : 
      91             : /*
      92             :  * Copy parameter control struct, including a possible path allocated
      93             :  * at the end of the struct.
      94             :  */
      95             : static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *in)
      96             : {
      97           2 :         struct autofs_dev_ioctl tmp, *ads;
      98           2 : 
      99          12 :         if (copy_from_user(&tmp, in, sizeof(tmp)))
     100           8 :                 return ERR_PTR(-EFAULT);
     101           2 : 
     102           6 :         if (tmp.size < sizeof(tmp))
     103           8 :                 return ERR_PTR(-EINVAL);
     104           2 : 
     105           8 :         ads = kmalloc(tmp.size, GFP_KERNEL);
     106           4 :         if (!ads)
     107           6 :                 return ERR_PTR(-ENOMEM);
     108             : 
     109          10 :         if (copy_from_user(ads, in, tmp.size)) {
     110           2 :                 kfree(ads);
     111           6 :                 return ERR_PTR(-EFAULT);
     112             :         }
     113             : 
     114           2 :         return ads;
     115             : }
     116             : 
     117             : static inline void free_dev_ioctl(struct autofs_dev_ioctl *param)
     118             : {
     119          10 :         kfree(param);
     120          10 :         return;
     121             : }
     122             : 
     123             : /*
     124             :  * Check sanity of parameter control fields and if a path is present
     125             :  * check that it is terminated and contains at least one "/".
     126             :  */
     127             : static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param)
     128             : {
     129           2 :         int err;
     130           2 : 
     131           8 :         err = check_dev_ioctl_version(cmd, param);
     132           6 :         if (err) {
     133           6 :                 AUTOFS_WARN("invalid device control module version "
     134             :                      "supplied for cmd(0x%08x)", cmd);
     135           2 :                 goto out;
     136             :         }
     137             : 
     138           4 :         if (param->size > sizeof(*param)) {
     139           6 :                 err = invalid_str(param->path, param->size - sizeof(*param));
     140           4 :                 if (err) {
     141           6 :                         AUTOFS_WARN(
     142             :                           "path string terminator missing for cmd(0x%08x)",
     143             :                           cmd);
     144           2 :                         goto out;
     145             :                 }
     146             : 
     147           4 :                 err = check_name(param->path);
     148           4 :                 if (err) {
     149           6 :                         AUTOFS_WARN("invalid path supplied for cmd(0x%08x)",
     150             :                                     cmd);
     151           2 :                         goto out;
     152             :                 }
     153             :         }
     154             : 
     155           4 :         err = 0;
     156           4 : out:
     157          10 :         return err;
     158             : }
     159             : 
     160             : /*
     161             :  * Get the autofs super block info struct from the file opened on
     162             :  * the autofs mount point.
     163             :  */
     164             : static struct autofs_sb_info *autofs_dev_ioctl_sbi(struct file *f)
     165             : {
     166           4 :         struct autofs_sb_info *sbi = NULL;
     167           2 :         struct inode *inode;
     168             : 
     169           4 :         if (f) {
     170           2 :                 inode = f->f_path.dentry->d_inode;
     171           4 :                 sbi = autofs4_sbi(inode->i_sb);
     172             :         }
     173           4 :         return sbi;
     174             : }
     175             : 
     176             : /* Return autofs module protocol version */
     177             : static int autofs_dev_ioctl_protover(struct file *fp,
     178             :                                      struct autofs_sb_info *sbi,
     179             :                                      struct autofs_dev_ioctl *param)
     180             : {
     181           0 :         param->protover.version = sbi->version;
     182           0 :         return 0;
     183             : }
     184             : 
     185             : /* Return autofs module protocol sub version */
     186             : static int autofs_dev_ioctl_protosubver(struct file *fp,
     187             :                                         struct autofs_sb_info *sbi,
     188             :                                         struct autofs_dev_ioctl *param)
     189             : {
     190           0 :         param->protosubver.sub_version = sbi->sub_version;
     191           0 :         return 0;
     192             : }
     193             : 
     194             : static int find_autofs_mount(const char *pathname,
     195             :                              struct path *res,
     196             :                              int test(struct path *path, void *data),
     197             :                              void *data)
     198           0 : {
     199           0 :         struct path path;
     200           0 :         int err = kern_path(pathname, 0, &path);
     201           0 :         if (err)
     202           0 :                 return err;
     203           0 :         err = -ENOENT;
     204           0 :         while (path.dentry == path.mnt->mnt_root) {
     205           0 :                 if (path.mnt->mnt_sb->s_magic == AUTOFS_SUPER_MAGIC) {
     206           0 :                         if (test(&path, data)) {
     207           0 :                                 path_get(&path);
     208           0 :                                 if (!err) /* already found some */
     209           0 :                                         path_put(res);
     210           0 :                                 *res = path;
     211           0 :                                 err = 0;
     212             :                         }
     213             :                 }
     214           0 :                 if (!follow_up(&path))
     215           0 :                         break;
     216             :         }
     217           0 :         path_put(&path);
     218           0 :         return err;
     219           0 : }
     220             : 
     221             : static int test_by_dev(struct path *path, void *p)
     222             : {
     223           0 :         return path->mnt->mnt_sb->s_dev == *(dev_t *)p;
     224             : }
     225             : 
     226             : static int test_by_type(struct path *path, void *p)
     227             : {
     228           0 :         struct autofs_info *ino = autofs4_dentry_ino(path->dentry);
     229           0 :         return ino && ino->sbi->type & *(unsigned *)p;
     230             : }
     231             : 
     232             : static void autofs_dev_ioctl_fd_install(unsigned int fd, struct file *file)
     233             : {
     234           0 :         struct files_struct *files = current->files;
     235           0 :         struct fdtable *fdt;
     236           0 : 
     237           0 :         spin_lock(&files->file_lock);
     238           0 :         fdt = files_fdtable(files);
     239           0 :         BUG_ON(fdt->fd[fd] != NULL);
     240           0 :         rcu_assign_pointer(fdt->fd[fd], file);
     241           0 :         FD_SET(fd, fdt->close_on_exec);
     242           0 :         spin_unlock(&files->file_lock);
     243           0 : }
     244             : 
     245             : 
     246             : /*
     247             :  * Open a file descriptor on the autofs mount point corresponding
     248             :  * to the given path and device number (aka. new_encode_dev(sb->s_dev)).
     249             :  */
     250             : static int autofs_dev_ioctl_open_mountpoint(const char *name, dev_t devid)
     251             : {
     252           0 :         int err, fd;
     253           0 : 
     254           0 :         fd = get_unused_fd();
     255           0 :         if (likely(fd >= 0)) {
     256           0 :                 struct file *filp;
     257           0 :                 struct path path;
     258           0 : 
     259           0 :                 err = find_autofs_mount(name, &path, test_by_dev, &devid);
     260           0 :                 if (err)
     261           0 :                         goto out;
     262             : 
     263             :                 /*
     264             :                  * Find autofs super block that has the device number
     265             :                  * corresponding to the autofs fs we want to open.
     266             :                  */
     267             : 
     268           0 :                 filp = dentry_open(path.dentry, path.mnt, O_RDONLY,
     269             :                                    current_cred());
     270           0 :                 if (IS_ERR(filp)) {
     271           0 :                         err = PTR_ERR(filp);
     272           0 :                         goto out;
     273             :                 }
     274             : 
     275           0 :                 autofs_dev_ioctl_fd_install(fd, filp);
     276             :         }
     277             : 
     278           0 :         return fd;
     279           0 : 
     280             : out:
     281           0 :         put_unused_fd(fd);
     282           0 :         return err;
     283             : }
     284             : 
     285             : /* Open a file descriptor on an autofs mount point */
     286             : static int autofs_dev_ioctl_openmount(struct file *fp,
     287             :                                       struct autofs_sb_info *sbi,
     288             :                                       struct autofs_dev_ioctl *param)
     289           0 : {
     290           0 :         const char *path;
     291           0 :         dev_t devid;
     292           0 :         int err, fd;
     293           0 : 
     294             :         /* param->path has already been checked */
     295           0 :         if (!param->openmount.devid)
     296           0 :                 return -EINVAL;
     297             : 
     298           0 :         param->ioctlfd = -1;
     299             : 
     300           0 :         path = param->path;
     301           0 :         devid = new_decode_dev(param->openmount.devid);
     302             : 
     303           0 :         err = 0;
     304           0 :         fd = autofs_dev_ioctl_open_mountpoint(path, devid);
     305           0 :         if (unlikely(fd < 0)) {
     306           0 :                 err = fd;
     307           0 :                 goto out;
     308             :         }
     309             : 
     310           0 :         param->ioctlfd = fd;
     311           0 : out:
     312           0 :         return err;
     313             : }
     314             : 
     315             : /* Close file descriptor allocated above (user can also use close(2)). */
     316             : static int autofs_dev_ioctl_closemount(struct file *fp,
     317             :                                        struct autofs_sb_info *sbi,
     318             :                                        struct autofs_dev_ioctl *param)
     319           0 : {
     320           0 :         return sys_close(param->ioctlfd);
     321             : }
     322             : 
     323             : /*
     324             :  * Send "ready" status for an existing wait (either a mount or an expire
     325             :  * request).
     326             :  */
     327             : static int autofs_dev_ioctl_ready(struct file *fp,
     328             :                                   struct autofs_sb_info *sbi,
     329           0 :                                   struct autofs_dev_ioctl *param)
     330           0 : {
     331             :         autofs_wqt_t token;
     332             : 
     333           0 :         token = (autofs_wqt_t) param->ready.token;
     334           0 :         return autofs4_wait_release(sbi, token, 0);
     335             : }
     336             : 
     337             : /*
     338             :  * Send "fail" status for an existing wait (either a mount or an expire
     339             :  * request).
     340             :  */
     341             : static int autofs_dev_ioctl_fail(struct file *fp,
     342             :                                  struct autofs_sb_info *sbi,
     343           0 :                                  struct autofs_dev_ioctl *param)
     344           0 : {
     345           0 :         autofs_wqt_t token;
     346             :         int status;
     347             : 
     348           0 :         token = (autofs_wqt_t) param->fail.token;
     349           0 :         status = param->fail.status ? param->fail.status : -ENOENT;
     350           0 :         return autofs4_wait_release(sbi, token, status);
     351             : }
     352             : 
     353             : /*
     354             :  * Set the pipe fd for kernel communication to the daemon.
     355             :  *
     356             :  * Normally this is set at mount using an option but if we
     357             :  * are reconnecting to a busy mount then we need to use this
     358             :  * to tell the autofs mount about the new kernel pipe fd. In
     359             :  * order to protect mounts against incorrectly setting the
     360             :  * pipefd we also require that the autofs mount be catatonic.
     361             :  *
     362             :  * This also sets the process group id used to identify the
     363             :  * controlling process (eg. the owning automount(8) daemon).
     364             :  */
     365             : static int autofs_dev_ioctl_setpipefd(struct file *fp,
     366             :                                       struct autofs_sb_info *sbi,
     367             :                                       struct autofs_dev_ioctl *param)
     368           0 : {
     369           0 :         int pipefd;
     370           0 :         int err = 0;
     371           0 : 
     372           0 :         if (param->setpipefd.pipefd == -1)
     373           0 :                 return -EINVAL;
     374             : 
     375           0 :         pipefd = param->setpipefd.pipefd;
     376             : 
     377           0 :         mutex_lock(&sbi->wq_mutex);
     378           0 :         if (!sbi->catatonic) {
     379           0 :                 mutex_unlock(&sbi->wq_mutex);
     380           0 :                 return -EBUSY;
     381             :         } else {
     382           0 :                 struct file *pipe = fget(pipefd);
     383           0 :                 if (!pipe->f_op || !pipe->f_op->write) {
     384           0 :                         err = -EPIPE;
     385           0 :                         fput(pipe);
     386           0 :                         goto out;
     387             :                 }
     388           0 :                 sbi->oz_pgrp = task_pgrp_nr(current);
     389           0 :                 sbi->pipefd = pipefd;
     390           0 :                 sbi->pipe = pipe;
     391           0 :                 sbi->catatonic = 0;
     392             :         }
     393             : out:
     394           0 :         mutex_unlock(&sbi->wq_mutex);
     395           0 :         return err;
     396             : }
     397             : 
     398             : /*
     399             :  * Make the autofs mount point catatonic, no longer responsive to
     400             :  * mount requests. Also closes the kernel pipe file descriptor.
     401             :  */
     402             : static int autofs_dev_ioctl_catatonic(struct file *fp,
     403             :                                       struct autofs_sb_info *sbi,
     404             :                                       struct autofs_dev_ioctl *param)
     405             : {
     406           0 :         autofs4_catatonic_mode(sbi);
     407           0 :         return 0;
     408             : }
     409             : 
     410             : /* Set the autofs mount timeout */
     411             : static int autofs_dev_ioctl_timeout(struct file *fp,
     412             :                                     struct autofs_sb_info *sbi,
     413             :                                     struct autofs_dev_ioctl *param)
     414           0 : {
     415             :         unsigned long timeout;
     416             : 
     417           0 :         timeout = param->timeout.timeout;
     418           0 :         param->timeout.timeout = sbi->exp_timeout / HZ;
     419           0 :         sbi->exp_timeout = timeout * HZ;
     420           0 :         return 0;
     421             : }
     422             : 
     423             : /*
     424             :  * Return the uid and gid of the last request for the mount
     425             :  *
     426             :  * When reconstructing an autofs mount tree with active mounts
     427             :  * we need to re-connect to mounts that may have used the original
     428             :  * process uid and gid (or string variations of them) for mount
     429             :  * lookups within the map entry.
     430             :  */
     431             : static int autofs_dev_ioctl_requester(struct file *fp,
     432             :                                       struct autofs_sb_info *sbi,
     433             :                                       struct autofs_dev_ioctl *param)
     434           0 : {
     435           0 :         struct autofs_info *ino;
     436           0 :         struct path path;
     437           0 :         dev_t devid;
     438           0 :         int err = -ENOENT;
     439             : 
     440           0 :         if (param->size <= sizeof(*param)) {
     441           0 :                 err = -EINVAL;
     442           0 :                 goto out;
     443             :         }
     444             : 
     445           0 :         devid = sbi->sb->s_dev;
     446             : 
     447           0 :         param->requester.uid = param->requester.gid = -1;
     448             : 
     449           0 :         err = find_autofs_mount(param->path, &path, test_by_dev, &devid);
     450           0 :         if (err)
     451           0 :                 goto out;
     452             : 
     453           0 :         ino = autofs4_dentry_ino(path.dentry);
     454           0 :         if (ino) {
     455           0 :                 err = 0;
     456           0 :                 autofs4_expire_wait(path.dentry);
     457           0 :                 spin_lock(&sbi->fs_lock);
     458           0 :                 param->requester.uid = ino->uid;
     459           0 :                 param->requester.gid = ino->gid;
     460           0 :                 spin_unlock(&sbi->fs_lock);
     461             :         }
     462           0 :         path_put(&path);
     463             : out:
     464           0 :         return err;
     465             : }
     466             : 
     467             : /*
     468             :  * Call repeatedly until it returns -EAGAIN, meaning there's nothing
     469             :  * more that can be done.
     470             :  */
     471             : static int autofs_dev_ioctl_expire(struct file *fp,
     472             :                                    struct autofs_sb_info *sbi,
     473             :                                    struct autofs_dev_ioctl *param)
     474           0 : {
     475           0 :         struct vfsmount *mnt;
     476           0 :         int how;
     477             : 
     478           0 :         how = param->expire.how;
     479           0 :         mnt = fp->f_path.mnt;
     480             : 
     481           0 :         return autofs4_do_expire_multi(sbi->sb, mnt, sbi, how);
     482             : }
     483             : 
     484             : /* Check if autofs mount point is in use */
     485             : static int autofs_dev_ioctl_askumount(struct file *fp,
     486             :                                       struct autofs_sb_info *sbi,
     487             :                                       struct autofs_dev_ioctl *param)
     488           0 : {
     489           0 :         param->askumount.may_umount = 0;
     490           0 :         if (may_umount(fp->f_path.mnt))
     491           0 :                 param->askumount.may_umount = 1;
     492           0 :         return 0;
     493             : }
     494             : 
     495             : /*
     496             :  * Check if the given path is a mountpoint.
     497             :  *
     498             :  * If we are supplied with the file descriptor of an autofs
     499             :  * mount we're looking for a specific mount. In this case
     500             :  * the path is considered a mountpoint if it is itself a
     501             :  * mountpoint or contains a mount, such as a multi-mount
     502             :  * without a root mount. In this case we return 1 if the
     503             :  * path is a mount point and the super magic of the covering
     504             :  * mount if there is one or 0 if it isn't a mountpoint.
     505             :  *
     506             :  * If we aren't supplied with a file descriptor then we
     507             :  * lookup the nameidata of the path and check if it is the
     508             :  * root of a mount. If a type is given we are looking for
     509             :  * a particular autofs mount and if we don't find a match
     510             :  * we return fail. If the located nameidata path is the
     511             :  * root of a mount we return 1 along with the super magic
     512             :  * of the mount or 0 otherwise.
     513             :  *
     514             :  * In both cases the the device number (as returned by
     515             :  * new_encode_dev()) is also returned.
     516             :  */
     517             : static int autofs_dev_ioctl_ismountpoint(struct file *fp,
     518             :                                          struct autofs_sb_info *sbi,
     519             :                                          struct autofs_dev_ioctl *param)
     520           0 : {
     521           0 :         struct path path;
     522           0 :         const char *name;
     523           0 :         unsigned int type;
     524           0 :         unsigned int devid, magic;
     525           0 :         int err = -ENOENT;
     526           0 : 
     527           0 :         if (param->size <= sizeof(*param)) {
     528           0 :                 err = -EINVAL;
     529           0 :                 goto out;
     530             :         }
     531             : 
     532           0 :         name = param->path;
     533           0 :         type = param->ismountpoint.in.type;
     534             : 
     535           0 :         param->ismountpoint.out.devid = devid = 0;
     536           0 :         param->ismountpoint.out.magic = magic = 0;
     537             : 
     538           0 :         if (!fp || param->ioctlfd == -1) {
     539           0 :                 if (autofs_type_any(type))
     540           0 :                         err = kern_path(name, LOOKUP_FOLLOW, &path);
     541             :                 else
     542           0 :                         err = find_autofs_mount(name, &path, test_by_type, &type);
     543           0 :                 if (err)
     544           0 :                         goto out;
     545           0 :                 devid = new_encode_dev(path.mnt->mnt_sb->s_dev);
     546           0 :                 err = 0;
     547           0 :                 if (path.dentry->d_inode &&
     548             :                     path.mnt->mnt_root == path.dentry) {
     549           0 :                         err = 1;
     550           0 :                         magic = path.dentry->d_inode->i_sb->s_magic;
     551             :                 }
     552             :         } else {
     553           0 :                 dev_t dev = sbi->sb->s_dev;
     554             : 
     555           0 :                 err = find_autofs_mount(name, &path, test_by_dev, &dev);
     556           0 :                 if (err)
     557           0 :                         goto out;
     558             : 
     559           0 :                 devid = new_encode_dev(dev);
     560             : 
     561           0 :                 err = have_submounts(path.dentry);
     562             : 
     563           0 :                 if (path.mnt->mnt_mountpoint != path.mnt->mnt_root) {
     564           0 :                         if (follow_down(&path))
     565           0 :                                 magic = path.mnt->mnt_sb->s_magic;
     566             :                 }
     567             :         }
     568             : 
     569           0 :         param->ismountpoint.out.devid = devid;
     570           0 :         param->ismountpoint.out.magic = magic;
     571           0 :         path_put(&path);
     572             : out:
     573           0 :         return err;
     574             : }
     575             : 
     576             : /*
     577             :  * Our range of ioctl numbers isn't 0 based so we need to shift
     578             :  * the array index by _IOC_NR(AUTOFS_CTL_IOC_FIRST) for the table
     579             :  * lookup.
     580             :  */
     581             : #define cmd_idx(cmd)    (cmd - _IOC_NR(AUTOFS_DEV_IOCTL_IOC_FIRST))
     582             : 
     583             : static ioctl_fn lookup_dev_ioctl(unsigned int cmd)
     584             : {
     585           2 :         static struct {
     586           2 :                 int cmd;
     587             :                 ioctl_fn fn;
     588          57 :         } _ioctls[] = {
     589             :                 {cmd_idx(AUTOFS_DEV_IOCTL_VERSION_CMD), NULL},
     590             :                 {cmd_idx(AUTOFS_DEV_IOCTL_PROTOVER_CMD),
     591             :                          autofs_dev_ioctl_protover},
     592             :                 {cmd_idx(AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD),
     593             :                          autofs_dev_ioctl_protosubver},
     594             :                 {cmd_idx(AUTOFS_DEV_IOCTL_OPENMOUNT_CMD),
     595             :                          autofs_dev_ioctl_openmount},
     596             :                 {cmd_idx(AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD),
     597             :                          autofs_dev_ioctl_closemount},
     598             :                 {cmd_idx(AUTOFS_DEV_IOCTL_READY_CMD),
     599             :                          autofs_dev_ioctl_ready},
     600             :                 {cmd_idx(AUTOFS_DEV_IOCTL_FAIL_CMD),
     601             :                          autofs_dev_ioctl_fail},
     602             :                 {cmd_idx(AUTOFS_DEV_IOCTL_SETPIPEFD_CMD),
     603             :                          autofs_dev_ioctl_setpipefd},
     604             :                 {cmd_idx(AUTOFS_DEV_IOCTL_CATATONIC_CMD),
     605             :                          autofs_dev_ioctl_catatonic},
     606             :                 {cmd_idx(AUTOFS_DEV_IOCTL_TIMEOUT_CMD),
     607             :                          autofs_dev_ioctl_timeout},
     608             :                 {cmd_idx(AUTOFS_DEV_IOCTL_REQUESTER_CMD),
     609             :                          autofs_dev_ioctl_requester},
     610             :                 {cmd_idx(AUTOFS_DEV_IOCTL_EXPIRE_CMD),
     611             :                          autofs_dev_ioctl_expire},
     612             :                 {cmd_idx(AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD),
     613             :                          autofs_dev_ioctl_askumount},
     614             :                 {cmd_idx(AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD),
     615             :                          autofs_dev_ioctl_ismountpoint}
     616             :         };
     617           2 :         unsigned int idx = cmd_idx(cmd);
     618             : 
     619          12 :         return (idx >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[idx].fn;
     620             : }
     621             : 
     622             : /* ioctl dispatcher */
     623             : static int _autofs_dev_ioctl(unsigned int command, struct autofs_dev_ioctl __user *user)
     624             : {
     625           2 :         struct autofs_dev_ioctl *param;
     626           2 :         struct file *fp;
     627           2 :         struct autofs_sb_info *sbi;
     628           2 :         unsigned int cmd_first, cmd;
     629           4 :         ioctl_fn fn = NULL;
     630           4 :         int err = 0;
     631           2 : 
     632           2 :         /* only root can play with this */
     633           8 :         if (!capable(CAP_SYS_ADMIN))
     634           4 :                 return -EPERM;
     635           2 : 
     636           4 :         cmd_first = _IOC_NR(AUTOFS_DEV_IOCTL_IOC_FIRST);
     637           4 :         cmd = _IOC_NR(command);
     638             : 
     639           8 :         if (_IOC_TYPE(command) != _IOC_TYPE(AUTOFS_DEV_IOCTL_IOC_FIRST) ||
     640             :             cmd - cmd_first >= AUTOFS_DEV_IOCTL_IOC_COUNT) {
     641           2 :                 return -ENOTTY;
     642             :         }
     643             : 
     644             :         /* Copy the parameters into kernel space. */
     645          12 :         param = copy_dev_ioctl(user);
     646           8 :         if (IS_ERR(param))
     647           6 :                 return PTR_ERR(param);
     648             : 
     649          12 :         err = validate_dev_ioctl(command, param);
     650           4 :         if (err)
     651           2 :                 goto out;
     652             : 
     653             :         /* The validate routine above always sets the version */
     654           4 :         if (cmd == AUTOFS_DEV_IOCTL_VERSION_CMD)
     655           2 :                 goto done;
     656             : 
     657           4 :         fn = lookup_dev_ioctl(cmd);
     658           4 :         if (!fn) {
     659           6 :                 AUTOFS_WARN("unknown command 0x%08x", command);
     660           2 :                 return -ENOTTY;
     661             :         }
     662             : 
     663           2 :         fp = NULL;
     664           2 :         sbi = NULL;
     665             : 
     666             :         /*
     667             :          * For obvious reasons the openmount can't have a file
     668             :          * descriptor yet. We don't take a reference to the
     669             :          * file during close to allow for immediate release.
     670             :          */
     671           4 :         if (cmd != AUTOFS_DEV_IOCTL_OPENMOUNT_CMD &&
     672             :             cmd != AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD) {
     673           4 :                 fp = fget(param->ioctlfd);
     674           4 :                 if (!fp) {
     675           4 :                         if (cmd == AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD)
     676           2 :                                 goto cont;
     677           2 :                         err = -EBADF;
     678           2 :                         goto out;
     679             :                 }
     680             : 
     681           6 :                 if (!fp->f_op) {
     682           2 :                         err = -ENOTTY;
     683           2 :                         fput(fp);
     684           2 :                         goto out;
     685             :                 }
     686             : 
     687           6 :                 sbi = autofs_dev_ioctl_sbi(fp);
     688           8 :                 if (!sbi || sbi->magic != AUTOFS_SBI_MAGIC) {
     689           2 :                         err = -EINVAL;
     690           2 :                         fput(fp);
     691           2 :                         goto out;
     692             :                 }
     693             : 
     694             :                 /*
     695             :                  * Admin needs to be able to set the mount catatonic in
     696             :                  * order to be able to perform the re-open.
     697             :                  */
     698          14 :                 if (!autofs4_oz_mode(sbi) &&
     699             :                     cmd != AUTOFS_DEV_IOCTL_CATATONIC_CMD) {
     700           2 :                         err = -EACCES;
     701           2 :                         fput(fp);
     702           2 :                         goto out;
     703             :                 }
     704             :         }
     705             : cont:
     706          56 :         err = fn(fp, sbi, param);
     707             : 
     708           8 :         if (fp)
     709           8 :                 fput(fp);
     710             : done:
     711          28 :         if (err >= 0 && copy_to_user(user, param, AUTOFS_DEV_IOCTL_SIZE))
     712           2 :                 err = -EFAULT;
     713             : out:
     714          24 :         free_dev_ioctl(param);
     715           2 :         return err;
     716             : }
     717             : 
     718             : static long autofs_dev_ioctl(struct file *file, uint command, ulong u)
     719           8 : {
     720           2 :         int err;
     721          10 :         err = _autofs_dev_ioctl(command, (struct autofs_dev_ioctl __user *) u);
     722           2 :         return (long) err;
     723             : }
     724             : 
     725             : #ifdef CONFIG_COMPAT
     726             : static long autofs_dev_ioctl_compat(struct file *file, uint command, ulong u)
     727             : {
     728           6 :         return (long) autofs_dev_ioctl(file, command, (ulong) compat_ptr(u));
     729           1 : }
     730             : #else
     731             : #define autofs_dev_ioctl_compat NULL
     732             : #endif
     733             : 
     734           1 : static const struct file_operations _dev_ioctl_fops = {
     735             :         .unlocked_ioctl  = autofs_dev_ioctl,
     736             :         .compat_ioctl = autofs_dev_ioctl_compat,
     737             :         .owner   = THIS_MODULE,
     738             : };
     739             : 
     740           1 : static struct miscdevice _autofs_dev_ioctl_misc = {
     741             :         .minor          = MISC_DYNAMIC_MINOR,
     742             :         .name           = AUTOFS_DEVICE_NAME,
     743             :         .fops           = &_dev_ioctl_fops
     744             : };
     745             : 
     746             : /* Register/deregister misc character device */
     747             : int autofs_dev_ioctl_init(void)
     748             : {
     749           1 :         int r;
     750           1 : 
     751           2 :         r = misc_register(&_autofs_dev_ioctl_misc);
     752           2 :         if (r) {
     753           3 :                 AUTOFS_ERROR("misc_register failed for control device");
     754           1 :                 return r;
     755             :         }
     756             : 
     757           1 :         return 0;
     758             : }
     759             : 
     760             : void autofs_dev_ioctl_exit(void)
     761             : {
     762           4 :         misc_deregister(&_autofs_dev_ioctl_misc);
     763           2 :         return;
     764             : }
     765             : 

Generated by: LCOV version 1.10