2019-05-22 10:51:29 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2018-06-08 03:11:13 +03:00
/*
* Copyright 1997 - 1998 Transmeta Corporation - - All Rights Reserved
* Copyright 1999 - 2000 Jeremy Fitzhardinge < jeremy @ goop . org >
* Copyright 2001 - 2006 Ian Kent < raven @ themaw . net >
*/
# include <linux/capability.h>
# include <linux/compat.h>
# include "autofs_i.h"
2021-01-21 16:19:43 +03:00
static int autofs_dir_symlink ( struct user_namespace * , struct inode * ,
struct dentry * , const char * ) ;
2018-06-08 03:11:13 +03:00
static int autofs_dir_unlink ( struct inode * , struct dentry * ) ;
static int autofs_dir_rmdir ( struct inode * , struct dentry * ) ;
2021-01-21 16:19:43 +03:00
static int autofs_dir_mkdir ( struct user_namespace * , struct inode * ,
struct dentry * , umode_t ) ;
2018-06-08 03:11:13 +03:00
static long autofs_root_ioctl ( struct file * , unsigned int , unsigned long ) ;
# ifdef CONFIG_COMPAT
static long autofs_root_compat_ioctl ( struct file * ,
unsigned int , unsigned long ) ;
# endif
static int autofs_dir_open ( struct inode * inode , struct file * file ) ;
static struct dentry * autofs_lookup ( struct inode * ,
struct dentry * , unsigned int ) ;
static struct vfsmount * autofs_d_automount ( struct path * ) ;
static int autofs_d_manage ( const struct path * , bool ) ;
static void autofs_dentry_release ( struct dentry * ) ;
const struct file_operations autofs_root_operations = {
. open = dcache_dir_open ,
. release = dcache_dir_close ,
. read = generic_read_dir ,
. iterate_shared = dcache_readdir ,
. llseek = dcache_dir_lseek ,
. unlocked_ioctl = autofs_root_ioctl ,
# ifdef CONFIG_COMPAT
. compat_ioctl = autofs_root_compat_ioctl ,
# endif
} ;
const struct file_operations autofs_dir_operations = {
. open = autofs_dir_open ,
. release = dcache_dir_close ,
. read = generic_read_dir ,
. iterate_shared = dcache_readdir ,
. llseek = dcache_dir_lseek ,
} ;
const struct inode_operations autofs_dir_inode_operations = {
. lookup = autofs_lookup ,
. unlink = autofs_dir_unlink ,
. symlink = autofs_dir_symlink ,
. mkdir = autofs_dir_mkdir ,
. rmdir = autofs_dir_rmdir ,
} ;
const struct dentry_operations autofs_dentry_operations = {
. d_automount = autofs_d_automount ,
. d_manage = autofs_d_manage ,
. d_release = autofs_dentry_release ,
} ;
static void autofs_del_active ( struct dentry * dentry )
{
struct autofs_sb_info * sbi = autofs_sbi ( dentry - > d_sb ) ;
struct autofs_info * ino ;
ino = autofs_dentry_ino ( dentry ) ;
2019-07-27 17:00:33 +03:00
spin_lock ( & sbi - > lookup_lock ) ;
list_del_init ( & ino - > active ) ;
spin_unlock ( & sbi - > lookup_lock ) ;
2018-06-08 03:11:13 +03:00
}
static int autofs_dir_open ( struct inode * inode , struct file * file )
{
struct dentry * dentry = file - > f_path . dentry ;
struct autofs_sb_info * sbi = autofs_sbi ( dentry - > d_sb ) ;
pr_debug ( " file=%p dentry=%p %pd \n " , file , dentry , dentry ) ;
if ( autofs_oz_mode ( sbi ) )
goto out ;
/*
* An empty directory in an autofs file system is always a
* mount point . The daemon must have failed to mount this
* during lookup so it doesn ' t exist . This can happen , for
* example , if user space returns an incorrect status for a
* mount request . Otherwise we ' re doing a readdir on the
* autofs file system so just let the libfs routines handle
* it .
*/
spin_lock ( & sbi - > lookup_lock ) ;
if ( ! path_is_mountpoint ( & file - > f_path ) & & simple_empty ( dentry ) ) {
spin_unlock ( & sbi - > lookup_lock ) ;
return - ENOENT ;
}
spin_unlock ( & sbi - > lookup_lock ) ;
out :
return dcache_dir_open ( inode , file ) ;
}
static void autofs_dentry_release ( struct dentry * de )
{
struct autofs_info * ino = autofs_dentry_ino ( de ) ;
struct autofs_sb_info * sbi = autofs_sbi ( de - > d_sb ) ;
pr_debug ( " releasing %p \n " , de ) ;
if ( ! ino )
return ;
if ( sbi ) {
spin_lock ( & sbi - > lookup_lock ) ;
if ( ! list_empty ( & ino - > active ) )
list_del ( & ino - > active ) ;
if ( ! list_empty ( & ino - > expiring ) )
list_del ( & ino - > expiring ) ;
spin_unlock ( & sbi - > lookup_lock ) ;
}
autofs_free_ino ( ino ) ;
}
static struct dentry * autofs_lookup_active ( struct dentry * dentry )
{
struct autofs_sb_info * sbi = autofs_sbi ( dentry - > d_sb ) ;
struct dentry * parent = dentry - > d_parent ;
const struct qstr * name = & dentry - > d_name ;
unsigned int len = name - > len ;
unsigned int hash = name - > hash ;
const unsigned char * str = name - > name ;
struct list_head * p , * head ;
head = & sbi - > active_list ;
if ( list_empty ( head ) )
return NULL ;
spin_lock ( & sbi - > lookup_lock ) ;
list_for_each ( p , head ) {
struct autofs_info * ino ;
struct dentry * active ;
const struct qstr * qstr ;
ino = list_entry ( p , struct autofs_info , active ) ;
active = ino - > dentry ;
spin_lock ( & active - > d_lock ) ;
/* Already gone? */
if ( ( int ) d_count ( active ) < = 0 )
goto next ;
qstr = & active - > d_name ;
if ( active - > d_name . hash ! = hash )
goto next ;
if ( active - > d_parent ! = parent )
goto next ;
if ( qstr - > len ! = len )
goto next ;
if ( memcmp ( qstr - > name , str , len ) )
goto next ;
if ( d_unhashed ( active ) ) {
dget_dlock ( active ) ;
spin_unlock ( & active - > d_lock ) ;
spin_unlock ( & sbi - > lookup_lock ) ;
return active ;
}
next :
spin_unlock ( & active - > d_lock ) ;
}
spin_unlock ( & sbi - > lookup_lock ) ;
return NULL ;
}
static struct dentry * autofs_lookup_expiring ( struct dentry * dentry ,
bool rcu_walk )
{
struct autofs_sb_info * sbi = autofs_sbi ( dentry - > d_sb ) ;
struct dentry * parent = dentry - > d_parent ;
const struct qstr * name = & dentry - > d_name ;
unsigned int len = name - > len ;
unsigned int hash = name - > hash ;
const unsigned char * str = name - > name ;
struct list_head * p , * head ;
head = & sbi - > expiring_list ;
if ( list_empty ( head ) )
return NULL ;
spin_lock ( & sbi - > lookup_lock ) ;
list_for_each ( p , head ) {
struct autofs_info * ino ;
struct dentry * expiring ;
const struct qstr * qstr ;
if ( rcu_walk ) {
spin_unlock ( & sbi - > lookup_lock ) ;
return ERR_PTR ( - ECHILD ) ;
}
ino = list_entry ( p , struct autofs_info , expiring ) ;
expiring = ino - > dentry ;
spin_lock ( & expiring - > d_lock ) ;
/* We've already been dentry_iput or unlinked */
if ( d_really_is_negative ( expiring ) )
goto next ;
qstr = & expiring - > d_name ;
if ( expiring - > d_name . hash ! = hash )
goto next ;
if ( expiring - > d_parent ! = parent )
goto next ;
if ( qstr - > len ! = len )
goto next ;
if ( memcmp ( qstr - > name , str , len ) )
goto next ;
if ( d_unhashed ( expiring ) ) {
dget_dlock ( expiring ) ;
spin_unlock ( & expiring - > d_lock ) ;
spin_unlock ( & sbi - > lookup_lock ) ;
return expiring ;
}
next :
spin_unlock ( & expiring - > d_lock ) ;
}
spin_unlock ( & sbi - > lookup_lock ) ;
return NULL ;
}
static int autofs_mount_wait ( const struct path * path , bool rcu_walk )
{
struct autofs_sb_info * sbi = autofs_sbi ( path - > dentry - > d_sb ) ;
struct autofs_info * ino = autofs_dentry_ino ( path - > dentry ) ;
int status = 0 ;
if ( ino - > flags & AUTOFS_INF_PENDING ) {
if ( rcu_walk )
return - ECHILD ;
pr_debug ( " waiting for mount name=%pd \n " , path - > dentry ) ;
status = autofs_wait ( sbi , path , NFY_MOUNT ) ;
pr_debug ( " mount wait done status=%d \n " , status ) ;
2019-01-04 02:27:43 +03:00
ino - > last_used = jiffies ;
return status ;
2018-06-08 03:11:13 +03:00
}
2019-01-04 02:27:43 +03:00
if ( ! ( sbi - > flags & AUTOFS_SBI_STRICTEXPIRE ) )
ino - > last_used = jiffies ;
2018-06-08 03:11:13 +03:00
return status ;
}
static int do_expire_wait ( const struct path * path , bool rcu_walk )
{
struct dentry * dentry = path - > dentry ;
struct dentry * expiring ;
expiring = autofs_lookup_expiring ( dentry , rcu_walk ) ;
if ( IS_ERR ( expiring ) )
return PTR_ERR ( expiring ) ;
if ( ! expiring )
return autofs_expire_wait ( path , rcu_walk ) ;
else {
const struct path this = { . mnt = path - > mnt , . dentry = expiring } ;
/*
* If we are racing with expire the request might not
* be quite complete , but the directory has been removed
* so it must have been successful , just wait for it .
*/
autofs_expire_wait ( & this , 0 ) ;
autofs_del_expiring ( expiring ) ;
dput ( expiring ) ;
}
return 0 ;
}
static struct dentry * autofs_mountpoint_changed ( struct path * path )
{
struct dentry * dentry = path - > dentry ;
struct autofs_sb_info * sbi = autofs_sbi ( dentry - > d_sb ) ;
/*
* If this is an indirect mount the dentry could have gone away
* as a result of an expire and a new one created .
*/
if ( autofs_type_indirect ( sbi - > type ) & & d_unhashed ( dentry ) ) {
struct dentry * parent = dentry - > d_parent ;
struct autofs_info * ino ;
struct dentry * new ;
new = d_lookup ( parent , & dentry - > d_name ) ;
if ( ! new )
return NULL ;
ino = autofs_dentry_ino ( new ) ;
ino - > last_used = jiffies ;
dput ( path - > dentry ) ;
path - > dentry = new ;
}
return path - > dentry ;
}
static struct vfsmount * autofs_d_automount ( struct path * path )
{
struct dentry * dentry = path - > dentry ;
struct autofs_sb_info * sbi = autofs_sbi ( dentry - > d_sb ) ;
struct autofs_info * ino = autofs_dentry_ino ( dentry ) ;
int status ;
pr_debug ( " dentry=%p %pd \n " , dentry , dentry ) ;
/* The daemon never triggers a mount. */
if ( autofs_oz_mode ( sbi ) )
return NULL ;
/*
* If an expire request is pending everyone must wait .
* If the expire fails we ' re still mounted so continue
* the follow and return . A return of - EAGAIN ( which only
* happens with indirect mounts ) means the expire completed
* and the directory was removed , so just go ahead and try
* the mount .
*/
status = do_expire_wait ( path , 0 ) ;
if ( status & & status ! = - EAGAIN )
return NULL ;
/* Callback to the daemon to perform the mount or wait */
spin_lock ( & sbi - > fs_lock ) ;
if ( ino - > flags & AUTOFS_INF_PENDING ) {
spin_unlock ( & sbi - > fs_lock ) ;
status = autofs_mount_wait ( path , 0 ) ;
if ( status )
return ERR_PTR ( status ) ;
goto done ;
}
/*
* If the dentry is a symlink it ' s equivalent to a directory
* having path_is_mountpoint ( ) true , so there ' s no need to call
* back to the daemon .
*/
if ( d_really_is_positive ( dentry ) & & d_is_symlink ( dentry ) ) {
spin_unlock ( & sbi - > fs_lock ) ;
goto done ;
}
if ( ! path_is_mountpoint ( path ) ) {
/*
* It ' s possible that user space hasn ' t removed directories
* after umounting a rootless multi - mount , although it
* should . For v5 path_has_submounts ( ) is sufficient to
* handle this because the leaves of the directory tree under
* the mount never trigger mounts themselves ( they have an
* autofs trigger mount mounted on them ) . But v4 pseudo direct
* mounts do need the leaves to trigger mounts . In this case
* we have no choice but to use the list_empty ( ) check and
* require user space behave .
*/
if ( sbi - > version > 4 ) {
if ( path_has_submounts ( path ) ) {
spin_unlock ( & sbi - > fs_lock ) ;
goto done ;
}
} else {
if ( ! simple_empty ( dentry ) ) {
spin_unlock ( & sbi - > fs_lock ) ;
goto done ;
}
}
ino - > flags | = AUTOFS_INF_PENDING ;
spin_unlock ( & sbi - > fs_lock ) ;
status = autofs_mount_wait ( path , 0 ) ;
spin_lock ( & sbi - > fs_lock ) ;
ino - > flags & = ~ AUTOFS_INF_PENDING ;
if ( status ) {
spin_unlock ( & sbi - > fs_lock ) ;
return ERR_PTR ( status ) ;
}
}
spin_unlock ( & sbi - > fs_lock ) ;
done :
/* Mount succeeded, check if we ended up with a new dentry */
dentry = autofs_mountpoint_changed ( path ) ;
if ( ! dentry )
return ERR_PTR ( - ENOENT ) ;
return NULL ;
}
static int autofs_d_manage ( const struct path * path , bool rcu_walk )
{
struct dentry * dentry = path - > dentry ;
struct autofs_sb_info * sbi = autofs_sbi ( dentry - > d_sb ) ;
struct autofs_info * ino = autofs_dentry_ino ( dentry ) ;
int status ;
pr_debug ( " dentry=%p %pd \n " , dentry , dentry ) ;
/* The daemon never waits. */
if ( autofs_oz_mode ( sbi ) ) {
if ( ! path_is_mountpoint ( path ) )
return - EISDIR ;
return 0 ;
}
/* Wait for pending expires */
if ( do_expire_wait ( path , rcu_walk ) = = - ECHILD )
return - ECHILD ;
/*
* This dentry may be under construction so wait on mount
* completion .
*/
status = autofs_mount_wait ( path , rcu_walk ) ;
if ( status )
return status ;
if ( rcu_walk ) {
/* We don't need fs_lock in rcu_walk mode,
* just testing ' AUTOFS_INFO_NO_RCU ' is enough .
* simple_empty ( ) takes a spinlock , so leave it
* to last .
* We only return - EISDIR when certain this isn ' t
* a mount - trap .
*/
struct inode * inode ;
if ( ino - > flags & AUTOFS_INF_WANT_EXPIRE )
return 0 ;
if ( path_is_mountpoint ( path ) )
return 0 ;
inode = d_inode_rcu ( dentry ) ;
if ( inode & & S_ISLNK ( inode - > i_mode ) )
return - EISDIR ;
if ( list_empty ( & dentry - > d_subdirs ) )
return 0 ;
if ( ! simple_empty ( dentry ) )
return - EISDIR ;
return 0 ;
}
spin_lock ( & sbi - > fs_lock ) ;
/*
* If the dentry has been selected for expire while we slept
* on the lock then it might go away . We ' ll deal with that in
* - > d_automount ( ) and wait on a new mount if the expire
* succeeds or return here if it doesn ' t ( since there ' s no
* mount to follow with a rootless multi - mount ) .
*/
if ( ! ( ino - > flags & AUTOFS_INF_EXPIRING ) ) {
/*
* Any needed mounting has been completed and the path
* updated so check if this is a rootless multi - mount so
* we can avoid needless calls - > d_automount ( ) and avoid
* an incorrect ELOOP error return .
*/
if ( ( ! path_is_mountpoint ( path ) & & ! simple_empty ( dentry ) ) | |
( d_really_is_positive ( dentry ) & & d_is_symlink ( dentry ) ) )
status = - EISDIR ;
}
spin_unlock ( & sbi - > fs_lock ) ;
return status ;
}
/* Lookups in the root directory */
static struct dentry * autofs_lookup ( struct inode * dir ,
struct dentry * dentry , unsigned int flags )
{
struct autofs_sb_info * sbi ;
struct autofs_info * ino ;
struct dentry * active ;
pr_debug ( " name = %pd \n " , dentry ) ;
/* File name too long to exist */
if ( dentry - > d_name . len > NAME_MAX )
return ERR_PTR ( - ENAMETOOLONG ) ;
sbi = autofs_sbi ( dir - > i_sb ) ;
pr_debug ( " pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d \n " ,
2019-01-04 02:27:39 +03:00
current - > pid , task_pgrp_nr ( current ) ,
sbi - > flags & AUTOFS_SBI_CATATONIC ,
2018-06-08 03:11:13 +03:00
autofs_oz_mode ( sbi ) ) ;
active = autofs_lookup_active ( dentry ) ;
if ( active )
return active ;
else {
/*
* A dentry that is not within the root can never trigger a
* mount operation , unless the directory already exists , so we
* can return fail immediately . The daemon however does need
* to create directories within the file system .
*/
if ( ! autofs_oz_mode ( sbi ) & & ! IS_ROOT ( dentry - > d_parent ) )
return ERR_PTR ( - ENOENT ) ;
ino = autofs_new_ino ( sbi ) ;
if ( ! ino )
return ERR_PTR ( - ENOMEM ) ;
2019-07-27 17:03:14 +03:00
spin_lock ( & sbi - > lookup_lock ) ;
spin_lock ( & dentry - > d_lock ) ;
/* Mark entries in the root as mount triggers */
if ( IS_ROOT ( dentry - > d_parent ) & &
autofs_type_indirect ( sbi - > type ) )
__managed_dentry_set_managed ( dentry ) ;
2018-06-08 03:11:13 +03:00
dentry - > d_fsdata = ino ;
ino - > dentry = dentry ;
2019-07-27 17:00:33 +03:00
list_add ( & ino - > active , & sbi - > active_list ) ;
spin_unlock ( & sbi - > lookup_lock ) ;
2019-07-27 17:03:14 +03:00
spin_unlock ( & dentry - > d_lock ) ;
2018-06-08 03:11:13 +03:00
}
return NULL ;
}
2021-01-21 16:19:43 +03:00
static int autofs_dir_symlink ( struct user_namespace * mnt_userns ,
struct inode * dir , struct dentry * dentry ,
const char * symname )
2018-06-08 03:11:13 +03:00
{
struct autofs_sb_info * sbi = autofs_sbi ( dir - > i_sb ) ;
struct autofs_info * ino = autofs_dentry_ino ( dentry ) ;
struct autofs_info * p_ino ;
struct inode * inode ;
size_t size = strlen ( symname ) ;
char * cp ;
pr_debug ( " %s <- %pd \n " , symname , dentry ) ;
if ( ! autofs_oz_mode ( sbi ) )
return - EACCES ;
2018-08-22 07:58:41 +03:00
/* autofs_oz_mode() needs to allow path walks when the
* autofs mount is catatonic but the state of an autofs
* file system needs to be preserved over restarts .
*/
2019-01-04 02:27:39 +03:00
if ( sbi - > flags & AUTOFS_SBI_CATATONIC )
2018-08-22 07:58:41 +03:00
return - EACCES ;
2018-06-08 03:11:13 +03:00
BUG_ON ( ! ino ) ;
autofs_clean_ino ( ino ) ;
autofs_del_active ( dentry ) ;
cp = kmalloc ( size + 1 , GFP_KERNEL ) ;
if ( ! cp )
return - ENOMEM ;
strcpy ( cp , symname ) ;
inode = autofs_get_inode ( dir - > i_sb , S_IFLNK | 0555 ) ;
if ( ! inode ) {
kfree ( cp ) ;
return - ENOMEM ;
}
inode - > i_private = cp ;
inode - > i_size = size ;
d_add ( dentry , inode ) ;
dget ( dentry ) ;
2019-09-18 06:31:27 +03:00
ino - > count + + ;
2018-06-08 03:11:13 +03:00
p_ino = autofs_dentry_ino ( dentry - > d_parent ) ;
2019-09-18 06:31:27 +03:00
p_ino - > count + + ;
2018-06-08 03:11:13 +03:00
dir - > i_mtime = current_time ( dir ) ;
return 0 ;
}
/*
* NOTE !
*
* Normal filesystems would do a " d_delete() " to tell the VFS dcache
* that the file no longer exists . However , doing that means that the
* VFS layer can turn the dentry into a negative dentry . We don ' t want
* this , because the unlink is probably the result of an expire .
* We simply d_drop it and add it to a expiring list in the super block ,
* which allows the dentry lookup to check for an incomplete expire .
*
* If a process is blocked on the dentry waiting for the expire to finish ,
* it will invalidate the dentry and try to mount with a new one .
*
* Also see autofs_dir_rmdir ( ) . .
*/
static int autofs_dir_unlink ( struct inode * dir , struct dentry * dentry )
{
struct autofs_sb_info * sbi = autofs_sbi ( dir - > i_sb ) ;
struct autofs_info * ino = autofs_dentry_ino ( dentry ) ;
struct autofs_info * p_ino ;
2018-08-22 07:58:41 +03:00
if ( ! autofs_oz_mode ( sbi ) )
return - EACCES ;
/* autofs_oz_mode() needs to allow path walks when the
* autofs mount is catatonic but the state of an autofs
* file system needs to be preserved over restarts .
*/
2019-01-04 02:27:39 +03:00
if ( sbi - > flags & AUTOFS_SBI_CATATONIC )
2018-08-22 07:58:41 +03:00
return - EACCES ;
2018-06-08 03:11:13 +03:00
2019-09-18 06:31:27 +03:00
ino - > count - - ;
2019-09-18 06:23:08 +03:00
p_ino = autofs_dentry_ino ( dentry - > d_parent ) ;
2019-09-18 06:31:27 +03:00
p_ino - > count - - ;
2018-06-08 03:11:13 +03:00
dput ( ino - > dentry ) ;
d_inode ( dentry ) - > i_size = 0 ;
clear_nlink ( d_inode ( dentry ) ) ;
dir - > i_mtime = current_time ( dir ) ;
spin_lock ( & sbi - > lookup_lock ) ;
__autofs_add_expiring ( dentry ) ;
d_drop ( dentry ) ;
spin_unlock ( & sbi - > lookup_lock ) ;
return 0 ;
}
/*
* Version 4 of autofs provides a pseudo direct mount implementation
* that relies on directories at the leaves of a directory tree under
* an indirect mount to trigger mounts . To allow for this we need to
* set the DMANAGED_AUTOMOUNT and DMANAGED_TRANSIT flags on the leaves
* of the directory tree . There is no need to clear the automount flag
* following a mount or restore it after an expire because these mounts
* are always covered . However , it is necessary to ensure that these
* flags are clear on non - empty directories to avoid unnecessary calls
* during path walks .
*/
static void autofs_set_leaf_automount_flags ( struct dentry * dentry )
{
struct dentry * parent ;
/* root and dentrys in the root are already handled */
if ( IS_ROOT ( dentry - > d_parent ) )
return ;
managed_dentry_set_managed ( dentry ) ;
parent = dentry - > d_parent ;
/* only consider parents below dentrys in the root */
if ( IS_ROOT ( parent - > d_parent ) )
return ;
managed_dentry_clear_managed ( parent ) ;
}
static void autofs_clear_leaf_automount_flags ( struct dentry * dentry )
{
struct dentry * parent ;
/* flags for dentrys in the root are handled elsewhere */
if ( IS_ROOT ( dentry - > d_parent ) )
return ;
managed_dentry_clear_managed ( dentry ) ;
parent = dentry - > d_parent ;
/* only consider parents below dentrys in the root */
if ( IS_ROOT ( parent - > d_parent ) )
return ;
2019-09-18 06:31:27 +03:00
if ( autofs_dentry_ino ( parent ) - > count = = 2 )
2018-06-08 03:11:13 +03:00
managed_dentry_set_managed ( parent ) ;
}
static int autofs_dir_rmdir ( struct inode * dir , struct dentry * dentry )
{
struct autofs_sb_info * sbi = autofs_sbi ( dir - > i_sb ) ;
struct autofs_info * ino = autofs_dentry_ino ( dentry ) ;
struct autofs_info * p_ino ;
pr_debug ( " dentry %p, removing %pd \n " , dentry , dentry ) ;
if ( ! autofs_oz_mode ( sbi ) )
return - EACCES ;
2018-08-22 07:58:41 +03:00
/* autofs_oz_mode() needs to allow path walks when the
* autofs mount is catatonic but the state of an autofs
* file system needs to be preserved over restarts .
*/
2019-01-04 02:27:39 +03:00
if ( sbi - > flags & AUTOFS_SBI_CATATONIC )
2018-08-22 07:58:41 +03:00
return - EACCES ;
2019-09-18 06:31:27 +03:00
if ( ino - > count ! = 1 )
2018-06-08 03:11:13 +03:00
return - ENOTEMPTY ;
2019-09-18 06:28:08 +03:00
spin_lock ( & sbi - > lookup_lock ) ;
2018-06-08 03:11:13 +03:00
__autofs_add_expiring ( dentry ) ;
d_drop ( dentry ) ;
spin_unlock ( & sbi - > lookup_lock ) ;
if ( sbi - > version < 5 )
autofs_clear_leaf_automount_flags ( dentry ) ;
2019-09-18 06:31:27 +03:00
ino - > count - - ;
2019-09-18 06:23:08 +03:00
p_ino = autofs_dentry_ino ( dentry - > d_parent ) ;
2019-09-18 06:31:27 +03:00
p_ino - > count - - ;
2018-06-08 03:11:13 +03:00
dput ( ino - > dentry ) ;
d_inode ( dentry ) - > i_size = 0 ;
clear_nlink ( d_inode ( dentry ) ) ;
if ( dir - > i_nlink )
drop_nlink ( dir ) ;
return 0 ;
}
2021-01-21 16:19:43 +03:00
static int autofs_dir_mkdir ( struct user_namespace * mnt_userns ,
struct inode * dir , struct dentry * dentry ,
umode_t mode )
2018-06-08 03:11:13 +03:00
{
struct autofs_sb_info * sbi = autofs_sbi ( dir - > i_sb ) ;
struct autofs_info * ino = autofs_dentry_ino ( dentry ) ;
struct autofs_info * p_ino ;
struct inode * inode ;
if ( ! autofs_oz_mode ( sbi ) )
return - EACCES ;
2018-08-22 07:58:41 +03:00
/* autofs_oz_mode() needs to allow path walks when the
* autofs mount is catatonic but the state of an autofs
* file system needs to be preserved over restarts .
*/
2019-01-04 02:27:39 +03:00
if ( sbi - > flags & AUTOFS_SBI_CATATONIC )
2018-08-22 07:58:41 +03:00
return - EACCES ;
2018-06-08 03:11:13 +03:00
pr_debug ( " dentry %p, creating %pd \n " , dentry , dentry ) ;
BUG_ON ( ! ino ) ;
autofs_clean_ino ( ino ) ;
autofs_del_active ( dentry ) ;
inode = autofs_get_inode ( dir - > i_sb , S_IFDIR | mode ) ;
if ( ! inode )
return - ENOMEM ;
d_add ( dentry , inode ) ;
if ( sbi - > version < 5 )
autofs_set_leaf_automount_flags ( dentry ) ;
dget ( dentry ) ;
2019-09-18 06:31:27 +03:00
ino - > count + + ;
2018-06-08 03:11:13 +03:00
p_ino = autofs_dentry_ino ( dentry - > d_parent ) ;
2019-09-18 06:31:27 +03:00
p_ino - > count + + ;
2018-06-08 03:11:13 +03:00
inc_nlink ( dir ) ;
dir - > i_mtime = current_time ( dir ) ;
return 0 ;
}
/* Get/set timeout ioctl() operation */
# ifdef CONFIG_COMPAT
static inline int autofs_compat_get_set_timeout ( struct autofs_sb_info * sbi ,
compat_ulong_t __user * p )
{
unsigned long ntimeout ;
int rv ;
rv = get_user ( ntimeout , p ) ;
if ( rv )
goto error ;
rv = put_user ( sbi - > exp_timeout / HZ , p ) ;
if ( rv )
goto error ;
if ( ntimeout > UINT_MAX / HZ )
sbi - > exp_timeout = 0 ;
else
sbi - > exp_timeout = ntimeout * HZ ;
return 0 ;
error :
return rv ;
}
# endif
static inline int autofs_get_set_timeout ( struct autofs_sb_info * sbi ,
unsigned long __user * p )
{
unsigned long ntimeout ;
int rv ;
rv = get_user ( ntimeout , p ) ;
if ( rv )
goto error ;
rv = put_user ( sbi - > exp_timeout / HZ , p ) ;
if ( rv )
goto error ;
if ( ntimeout > ULONG_MAX / HZ )
sbi - > exp_timeout = 0 ;
else
sbi - > exp_timeout = ntimeout * HZ ;
return 0 ;
error :
return rv ;
}
/* Return protocol version */
static inline int autofs_get_protover ( struct autofs_sb_info * sbi ,
int __user * p )
{
return put_user ( sbi - > version , p ) ;
}
/* Return protocol sub version */
static inline int autofs_get_protosubver ( struct autofs_sb_info * sbi ,
int __user * p )
{
return put_user ( sbi - > sub_version , p ) ;
}
/*
* Tells the daemon whether it can umount the autofs mount .
*/
static inline int autofs_ask_umount ( struct vfsmount * mnt , int __user * p )
{
int status = 0 ;
if ( may_umount ( mnt ) )
status = 1 ;
pr_debug ( " may umount %d \n " , status ) ;
status = put_user ( status , p ) ;
return status ;
}
/* Identify autofs_dentries - this is so we can tell if there's
* an extra dentry refcount or not . We only hold a refcount on the
* dentry if its non - negative ( ie , d_inode ! = NULL )
*/
int is_autofs_dentry ( struct dentry * dentry )
{
return dentry & & d_really_is_positive ( dentry ) & &
dentry - > d_op = = & autofs_dentry_operations & &
dentry - > d_fsdata ! = NULL ;
}
/*
* ioctl ( ) ' s on the root directory is the chief method for the daemon to
* generate kernel reactions
*/
static int autofs_root_ioctl_unlocked ( struct inode * inode , struct file * filp ,
unsigned int cmd , unsigned long arg )
{
struct autofs_sb_info * sbi = autofs_sbi ( inode - > i_sb ) ;
void __user * p = ( void __user * ) arg ;
pr_debug ( " cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u \n " ,
cmd , arg , sbi , task_pgrp_nr ( current ) ) ;
if ( _IOC_TYPE ( cmd ) ! = _IOC_TYPE ( AUTOFS_IOC_FIRST ) | |
_IOC_NR ( cmd ) - _IOC_NR ( AUTOFS_IOC_FIRST ) > = AUTOFS_IOC_COUNT )
return - ENOTTY ;
if ( ! autofs_oz_mode ( sbi ) & & ! capable ( CAP_SYS_ADMIN ) )
return - EPERM ;
switch ( cmd ) {
case AUTOFS_IOC_READY : /* Wait queue: go ahead and retry */
return autofs_wait_release ( sbi , ( autofs_wqt_t ) arg , 0 ) ;
case AUTOFS_IOC_FAIL : /* Wait queue: fail with ENOENT */
return autofs_wait_release ( sbi , ( autofs_wqt_t ) arg , - ENOENT ) ;
case AUTOFS_IOC_CATATONIC : /* Enter catatonic mode (daemon shutdown) */
autofs_catatonic_mode ( sbi ) ;
return 0 ;
case AUTOFS_IOC_PROTOVER : /* Get protocol version */
return autofs_get_protover ( sbi , p ) ;
case AUTOFS_IOC_PROTOSUBVER : /* Get protocol sub version */
return autofs_get_protosubver ( sbi , p ) ;
case AUTOFS_IOC_SETTIMEOUT :
return autofs_get_set_timeout ( sbi , p ) ;
# ifdef CONFIG_COMPAT
case AUTOFS_IOC_SETTIMEOUT32 :
return autofs_compat_get_set_timeout ( sbi , p ) ;
# endif
case AUTOFS_IOC_ASKUMOUNT :
return autofs_ask_umount ( filp - > f_path . mnt , p ) ;
/* return a single thing to expire */
case AUTOFS_IOC_EXPIRE :
return autofs_expire_run ( inode - > i_sb , filp - > f_path . mnt , sbi , p ) ;
/* same as above, but can send multiple expires through pipe */
case AUTOFS_IOC_EXPIRE_MULTI :
return autofs_expire_multi ( inode - > i_sb ,
filp - > f_path . mnt , sbi , p ) ;
default :
return - EINVAL ;
}
}
static long autofs_root_ioctl ( struct file * filp ,
unsigned int cmd , unsigned long arg )
{
struct inode * inode = file_inode ( filp ) ;
return autofs_root_ioctl_unlocked ( inode , filp , cmd , arg ) ;
}
# ifdef CONFIG_COMPAT
static long autofs_root_compat_ioctl ( struct file * filp ,
unsigned int cmd , unsigned long arg )
{
struct inode * inode = file_inode ( filp ) ;
int ret ;
if ( cmd = = AUTOFS_IOC_READY | | cmd = = AUTOFS_IOC_FAIL )
ret = autofs_root_ioctl_unlocked ( inode , filp , cmd , arg ) ;
else
ret = autofs_root_ioctl_unlocked ( inode , filp , cmd ,
( unsigned long ) compat_ptr ( arg ) ) ;
return ret ;
}
# endif