LCOV - code coverage report
Current view: top level - fs/autofs - dev-ioctl.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 121 276 43.8 %
Date: 2022-04-01 14:17:54 Functions: 12 24 50.0 %
Branches: 37 120 30.8 %

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

Generated by: LCOV version 1.14