LCOV - code coverage report
Current view: top level - include/linux - fsnotify.h (source / functions) Hit Total Coverage
Test: landlock.info Lines: 126 128 98.4 %
Date: 2021-04-22 12:43:58 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0 */
       2             : #ifndef _LINUX_FS_NOTIFY_H
       3             : #define _LINUX_FS_NOTIFY_H
       4             : 
       5             : /*
       6             :  * include/linux/fsnotify.h - generic hooks for filesystem notification, to
       7             :  * reduce in-source duplication from both dnotify and inotify.
       8             :  *
       9             :  * We don't compile any of this away in some complicated menagerie of ifdefs.
      10             :  * Instead, we rely on the code inside to optimize away as needed.
      11             :  *
      12             :  * (C) Copyright 2005 Robert Love
      13             :  */
      14             : 
      15             : #include <linux/fsnotify_backend.h>
      16             : #include <linux/audit.h>
      17             : #include <linux/slab.h>
      18             : #include <linux/bug.h>
      19             : 
      20             : /*
      21             :  * Notify this @dir inode about a change in a child directory entry.
      22             :  * The directory entry may have turned positive or negative or its inode may
      23             :  * have changed (i.e. renamed over).
      24             :  *
      25             :  * Unlike fsnotify_parent(), the event will be reported regardless of the
      26             :  * FS_EVENT_ON_CHILD mask on the parent inode and will not be reported if only
      27             :  * the child is interested and not the parent.
      28             :  */
      29        8828 : static inline void fsnotify_name(struct inode *dir, __u32 mask,
      30             :                                  struct inode *child,
      31             :                                  const struct qstr *name, u32 cookie)
      32             : {
      33        8017 :         fsnotify(mask, child, FSNOTIFY_EVENT_INODE, dir, name, NULL, cookie);
      34             : }
      35             : 
      36        8017 : static inline void fsnotify_dirent(struct inode *dir, struct dentry *dentry,
      37             :                                    __u32 mask)
      38             : {
      39        8017 :         fsnotify_name(dir, mask, d_inode(dentry), &dentry->d_name, 0);
      40        8017 : }
      41             : 
      42        2486 : static inline void fsnotify_inode(struct inode *inode, __u32 mask)
      43             : {
      44        2486 :         if (S_ISDIR(inode->i_mode))
      45         581 :                 mask |= FS_ISDIR;
      46             : 
      47        2486 :         fsnotify(mask, inode, FSNOTIFY_EVENT_INODE, NULL, NULL, inode, 0);
      48        2486 : }
      49             : 
      50             : /* Notify this dentry's parent about a child's events. */
      51      187112 : static inline int fsnotify_parent(struct dentry *dentry, __u32 mask,
      52             :                                   const void *data, int data_type)
      53             : {
      54      187112 :         struct inode *inode = d_inode(dentry);
      55             : 
      56      187112 :         if (S_ISDIR(inode->i_mode)) {
      57       67910 :                 mask |= FS_ISDIR;
      58             : 
      59             :                 /* sb/mount marks are not interested in name of directory */
      60       67910 :                 if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
      61       67913 :                         goto notify_child;
      62             :         }
      63             : 
      64             :         /* disconnected dentry cannot notify parent */
      65      119199 :         if (IS_ROOT(dentry))
      66       30173 :                 goto notify_child;
      67             : 
      68       89026 :         return __fsnotify_parent(dentry, mask, data, data_type);
      69             : 
      70       98086 : notify_child:
      71       98086 :         return fsnotify(mask, data, data_type, NULL, NULL, inode, 0);
      72             : }
      73             : 
      74             : /*
      75             :  * Simple wrappers to consolidate calls to fsnotify_parent() when an event
      76             :  * is on a file/dentry.
      77             :  */
      78        1161 : static inline void fsnotify_dentry(struct dentry *dentry, __u32 mask)
      79             : {
      80        1161 :         fsnotify_parent(dentry, mask, d_inode(dentry), FSNOTIFY_EVENT_INODE);
      81        1100 : }
      82             : 
      83      186019 : static inline int fsnotify_file(struct file *file, __u32 mask)
      84             : {
      85      186019 :         const struct path *path = &file->f_path;
      86             : 
      87      186019 :         if (file->f_mode & FMODE_NONOTIFY)
      88             :                 return 0;
      89             : 
      90      185952 :         return fsnotify_parent(path->dentry, mask, path, FSNOTIFY_EVENT_PATH);
      91             : }
      92             : 
      93             : /* Simple call site for access decisions */
      94       64404 : static inline int fsnotify_perm(struct file *file, int mask)
      95             : {
      96       64404 :         int ret;
      97       64404 :         __u32 fsnotify_mask = 0;
      98             : 
      99       64404 :         if (!(mask & (MAY_READ | MAY_OPEN)))
     100             :                 return 0;
     101             : 
     102       52488 :         if (mask & MAY_OPEN) {
     103       17591 :                 fsnotify_mask = FS_OPEN_PERM;
     104             : 
     105       17591 :                 if (file->f_flags & __FMODE_EXEC) {
     106        2782 :                         ret = fsnotify_file(file, FS_OPEN_EXEC_PERM);
     107             : 
     108        2782 :                         if (ret)
     109             :                                 return ret;
     110             :                 }
     111       34897 :         } else if (mask & MAY_READ) {
     112       34898 :                 fsnotify_mask = FS_ACCESS_PERM;
     113             :         }
     114             : 
     115       52488 :         return fsnotify_file(file, fsnotify_mask);
     116             : }
     117             : 
     118             : /*
     119             :  * fsnotify_link_count - inode's link count changed
     120             :  */
     121         764 : static inline void fsnotify_link_count(struct inode *inode)
     122             : {
     123         654 :         fsnotify_inode(inode, FS_ATTRIB);
     124          91 : }
     125             : 
     126             : /*
     127             :  * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
     128             :  */
     129         396 : static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
     130             :                                  const struct qstr *old_name,
     131             :                                  int isdir, struct inode *target,
     132             :                                  struct dentry *moved)
     133             : {
     134         396 :         struct inode *source = moved->d_inode;
     135         396 :         u32 fs_cookie = fsnotify_get_cookie();
     136         396 :         __u32 old_dir_mask = FS_MOVED_FROM;
     137         396 :         __u32 new_dir_mask = FS_MOVED_TO;
     138         396 :         const struct qstr *new_name = &moved->d_name;
     139             : 
     140         396 :         if (old_dir == new_dir)
     141         395 :                 old_dir_mask |= FS_DN_RENAME;
     142             : 
     143         396 :         if (isdir) {
     144           5 :                 old_dir_mask |= FS_ISDIR;
     145           5 :                 new_dir_mask |= FS_ISDIR;
     146             :         }
     147             : 
     148         396 :         fsnotify_name(old_dir, old_dir_mask, source, old_name, fs_cookie);
     149         396 :         fsnotify_name(new_dir, new_dir_mask, source, new_name, fs_cookie);
     150             : 
     151         396 :         if (target)
     152          91 :                 fsnotify_link_count(target);
     153         396 :         fsnotify_inode(source, FS_MOVE_SELF);
     154         396 :         audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE);
     155         396 : }
     156             : 
     157             : /*
     158             :  * fsnotify_inode_delete - and inode is being evicted from cache, clean up is needed
     159             :  */
     160        5383 : static inline void fsnotify_inode_delete(struct inode *inode)
     161             : {
     162        5383 :         __fsnotify_inode_delete(inode);
     163             : }
     164             : 
     165             : /*
     166             :  * fsnotify_vfsmount_delete - a vfsmount is being destroyed, clean up is needed
     167             :  */
     168        1069 : static inline void fsnotify_vfsmount_delete(struct vfsmount *mnt)
     169             : {
     170        1069 :         __fsnotify_vfsmount_delete(mnt);
     171             : }
     172             : 
     173             : /*
     174             :  * fsnotify_inoderemove - an inode is going away
     175             :  */
     176        1231 : static inline void fsnotify_inoderemove(struct inode *inode)
     177             : {
     178        1231 :         fsnotify_inode(inode, FS_DELETE_SELF);
     179        1231 :         __fsnotify_inode_delete(inode);
     180        1231 : }
     181             : 
     182             : /*
     183             :  * fsnotify_create - 'name' was linked in
     184             :  */
     185        5291 : static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
     186             : {
     187        5291 :         audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
     188             : 
     189        5291 :         fsnotify_dirent(inode, dentry, FS_CREATE);
     190        1467 : }
     191             : 
     192             : /*
     193             :  * fsnotify_link - new hardlink in 'inode' directory
     194             :  * Note: We have to pass also the linked inode ptr as some filesystems leave
     195             :  *   new_dentry->d_inode NULL and instantiate inode pointer later
     196             :  */
     197          19 : static inline void fsnotify_link(struct inode *dir, struct inode *inode,
     198             :                                  struct dentry *new_dentry)
     199             : {
     200          19 :         fsnotify_link_count(inode);
     201          19 :         audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE);
     202             : 
     203          19 :         fsnotify_name(dir, FS_CREATE, inode, &new_dentry->d_name, 0);
     204          19 : }
     205             : 
     206             : /*
     207             :  * fsnotify_unlink - 'name' was unlinked
     208             :  *
     209             :  * Caller must make sure that dentry->d_name is stable.
     210             :  */
     211         654 : static inline void fsnotify_unlink(struct inode *dir, struct dentry *dentry)
     212             : {
     213             :         /* Expected to be called before d_delete() */
     214         654 :         WARN_ON_ONCE(d_is_negative(dentry));
     215             : 
     216         654 :         fsnotify_dirent(dir, dentry, FS_DELETE);
     217         654 : }
     218             : 
     219             : /*
     220             :  * fsnotify_mkdir - directory 'name' was created
     221             :  */
     222        1524 : static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
     223             : {
     224        1524 :         audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
     225             : 
     226        1524 :         fsnotify_dirent(inode, dentry, FS_CREATE | FS_ISDIR);
     227         785 : }
     228             : 
     229             : /*
     230             :  * fsnotify_rmdir - directory 'name' was removed
     231             :  *
     232             :  * Caller must make sure that dentry->d_name is stable.
     233             :  */
     234         548 : static inline void fsnotify_rmdir(struct inode *dir, struct dentry *dentry)
     235             : {
     236             :         /* Expected to be called before d_delete() */
     237         548 :         WARN_ON_ONCE(d_is_negative(dentry));
     238             : 
     239         548 :         fsnotify_dirent(dir, dentry, FS_DELETE | FS_ISDIR);
     240         548 : }
     241             : 
     242             : /*
     243             :  * fsnotify_access - file was read
     244             :  */
     245       27235 : static inline void fsnotify_access(struct file *file)
     246             : {
     247       27235 :         fsnotify_file(file, FS_ACCESS);
     248           0 : }
     249             : 
     250             : /*
     251             :  * fsnotify_modify - file was modified
     252             :  */
     253       11489 : static inline void fsnotify_modify(struct file *file)
     254             : {
     255       11489 :         fsnotify_file(file, FS_MODIFY);
     256         222 : }
     257             : 
     258             : /*
     259             :  * fsnotify_open - file was opened
     260             :  */
     261       45542 : static inline void fsnotify_open(struct file *file)
     262             : {
     263       45542 :         __u32 mask = FS_OPEN;
     264             : 
     265       45542 :         if (file->f_flags & __FMODE_EXEC)
     266        2082 :                 mask |= FS_OPEN_EXEC;
     267             : 
     268       45542 :         fsnotify_file(file, mask);
     269       45548 : }
     270             : 
     271             : /*
     272             :  * fsnotify_close - file was closed
     273             :  */
     274       46480 : static inline void fsnotify_close(struct file *file)
     275             : {
     276       46480 :         __u32 mask = (file->f_mode & FMODE_WRITE) ? FS_CLOSE_WRITE :
     277             :                                                     FS_CLOSE_NOWRITE;
     278             : 
     279       46480 :         fsnotify_file(file, mask);
     280       46488 : }
     281             : 
     282             : /*
     283             :  * fsnotify_xattr - extended attributes were changed
     284             :  */
     285          61 : static inline void fsnotify_xattr(struct dentry *dentry)
     286             : {
     287          61 :         fsnotify_dentry(dentry, FS_ATTRIB);
     288          61 : }
     289             : 
     290             : /*
     291             :  * fsnotify_change - notify_change event.  file was modified and/or metadata
     292             :  * was changed.
     293             :  */
     294        1100 : static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
     295             : {
     296        1100 :         __u32 mask = 0;
     297             : 
     298        1100 :         if (ia_valid & ATTR_UID)
     299         308 :                 mask |= FS_ATTRIB;
     300        1100 :         if (ia_valid & ATTR_GID)
     301         308 :                 mask |= FS_ATTRIB;
     302        1100 :         if (ia_valid & ATTR_SIZE)
     303          64 :                 mask |= FS_MODIFY;
     304             : 
     305             :         /* both times implies a utime(s) call */
     306        1100 :         if ((ia_valid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME))
     307         262 :                 mask |= FS_ATTRIB;
     308         838 :         else if (ia_valid & ATTR_ATIME)
     309           0 :                 mask |= FS_ACCESS;
     310         838 :         else if (ia_valid & ATTR_MTIME)
     311          73 :                 mask |= FS_MODIFY;
     312             : 
     313        1100 :         if (ia_valid & ATTR_MODE)
     314         564 :                 mask |= FS_ATTRIB;
     315             : 
     316        1100 :         if (mask)
     317        1100 :                 fsnotify_dentry(dentry, mask);
     318        1100 : }
     319             : 
     320             : #endif  /* _LINUX_FS_NOTIFY_H */

Generated by: LCOV version 1.14