/* * Return the uid and gid of the last request for the mount * * When reconstructing an autofs mount tree with active mounts * we need to re-connect to mounts that may have used the original * process uid and gid (or string variations of them) for mount * lookups within the map entry. */ static int autofs_dev_ioctl_requester(struct file *fp, struct autofs_sb_info *sbi, struct autofs_dev_ioctl *param) { struct autofs_info *ino; struct nameidata nd; const char *path; dev_t devid; int err = -ENOENT; if (param->size <= sizeof(*param)) { err = -EINVAL; goto out; } path = param->path; devid = sbi->sb->s_dev; param->arg1 = param->arg2 = -1; /* Get nameidata of the parent directory */ err = path_lookup(path, LOOKUP_PARENT, &nd); if (err) goto out; err = autofs_dev_ioctl_find_super(&nd, devid); if (err) goto out_release; ino = autofs4_dentry_ino(nd.path.dentry); if (ino) { err = 0; autofs4_expire_wait(nd.path.dentry); spin_lock(&sbi->fs_lock); param->arg1 = ino->uid; param->arg2 = ino->gid; spin_unlock(&sbi->fs_lock); } out_release: path_put(&nd.path); out: return err; }
/* * Open a file descriptor on the autofs mount point corresponding * to the given path and device number (aka. new_encode_dev(sb->s_dev)). */ static int autofs_dev_ioctl_open_mountpoint(const char *path, dev_t devid) { struct file *filp; struct nameidata nd; int err, fd; fd = get_unused_fd(); if (likely(fd >= 0)) { /* Get nameidata of the parent directory */ err = path_lookup(path, LOOKUP_PARENT, &nd); if (err) goto out; /* * Search down, within the parent, looking for an * autofs super block that has the device number * corresponding to the autofs fs we want to open. */ err = autofs_dev_ioctl_find_super(&nd, devid); if (err) { path_put(&nd.path); goto out; } filp = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY, current_cred()); if (IS_ERR(filp)) { err = PTR_ERR(filp); goto out; } autofs_dev_ioctl_fd_install(fd, filp); } return fd; out: put_unused_fd(fd); return err; }
/* * Check if the given path is a mountpoint. * * If we are supplied with the file descriptor of an autofs * mount we're looking for a specific mount. In this case * the path is considered a mountpoint if it is itself a * mountpoint or contains a mount, such as a multi-mount * without a root mount. In this case we return 1 if the * path is a mount point and the super magic of the covering * mount if there is one or 0 if it isn't a mountpoint. * * If we aren't supplied with a file descriptor then we * lookup the nameidata of the path and check if it is the * root of a mount. If a type is given we are looking for * a particular autofs mount and if we don't find a match * we return fail. If the located nameidata path is the * root of a mount we return 1 along with the super magic * of the mount or 0 otherwise. * * In both cases the the device number (as returned by * new_encode_dev()) is also returned. */ static int autofs_dev_ioctl_ismountpoint(struct file *fp, struct autofs_sb_info *sbi, struct autofs_dev_ioctl *param) { struct nameidata nd; const char *path; unsigned int type; int err = -ENOENT; if (param->size <= sizeof(*param)) { err = -EINVAL; goto out; } path = param->path; type = param->arg1; param->arg1 = 0; param->arg2 = 0; if (!fp || param->ioctlfd == -1) { if (type == AUTOFS_TYPE_ANY) { struct super_block *sb; err = path_lookup(path, LOOKUP_FOLLOW, &nd); if (err) goto out; sb = nd.path.dentry->d_sb; param->arg1 = new_encode_dev(sb->s_dev); } else { struct autofs_info *ino; err = path_lookup(path, LOOKUP_PARENT, &nd); if (err) goto out; err = autofs_dev_ioctl_find_sbi_type(&nd, type); if (err) goto out_release; ino = autofs4_dentry_ino(nd.path.dentry); param->arg1 = autofs4_get_dev(ino->sbi); } err = 0; if (nd.path.dentry->d_inode && nd.path.mnt->mnt_root == nd.path.dentry) { err = 1; param->arg2 = nd.path.dentry->d_inode->i_sb->s_magic; } } else { dev_t devid = new_encode_dev(sbi->sb->s_dev); err = path_lookup(path, LOOKUP_PARENT, &nd); if (err) goto out; err = autofs_dev_ioctl_find_super(&nd, devid); if (err) goto out_release; param->arg1 = autofs4_get_dev(sbi); err = have_submounts(nd.path.dentry); if (nd.path.mnt->mnt_mountpoint != nd.path.mnt->mnt_root) { if (follow_down(&nd.path.mnt, &nd.path.dentry)) { struct inode *inode = nd.path.dentry->d_inode; param->arg2 = inode->i_sb->s_magic; } } } out_release: path_put(&nd.path); out: return err; }