LCOV - code coverage report
Current view: top level - fs/autofs4 - dev-ioctl.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 198 0.0 %
Date: 2014-02-18 Functions: 0 24 0.0 %
Branches: 0 118 0.0 %

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

Generated by: LCOV version 1.9