@@ -3735,6 +3735,15 @@ static int do_open(struct nameidata *nd,
}
if (do_truncate)
mnt_drop_write(nd->path.mnt);
+
+ /*
+ * This permission hook is different than fsnotify_open_perm() hook.
+ * This is a pre-content hook that is called without sb_writers held
+ * and after the file was truncated.
+ */
+ if (!error)
+ error = fsnotify_file_perm(file, MAY_OPEN);
+
return error;
}
@@ -168,6 +168,10 @@ static inline int fsnotify_file_area_perm(struct file *file, int perm_mask,
fsnotify_mask = FS_PRE_MODIFY;
else if (perm_mask & MAY_READ)
fsnotify_mask = FS_PRE_ACCESS;
+ else if (perm_mask & MAY_OPEN && file->f_mode & FMODE_WRITER)
+ fsnotify_mask = FS_PRE_MODIFY;
+ else if (perm_mask & MAY_OPEN)
+ fsnotify_mask = FS_PRE_ACCESS;
else
return 0;
@@ -176,10 +180,14 @@ static inline int fsnotify_file_area_perm(struct file *file, int perm_mask,
/*
* fsnotify_file_perm - permission hook before file access
+ *
+ * Called from read()/write() with perm_mask MAY_READ/MAY_WRITE.
+ * Called from open() with MAY_OPEN without sb_writers held and after the file
+ * was truncated. Note that this is a different event from fsnotify_open_perm().
*/
static inline int fsnotify_file_perm(struct file *file, int perm_mask)
{
- return fsnotify_file_area_perm(file, perm_mask, NULL, 0);
+ return fsnotify_file_area_perm(file, perm_mask, &file->f_pos, 0);
}
/*