| 1 | |
| 2 | |
| 3 | * Copyright (C) 2008 Red Hat, Inc., Eric Paris <[email protected]>
|
| 4 |
|
| 5 |
|
| 6 | #include <linux/dcache.h>
|
| 7 | #include <linux/fs.h>
|
| 8 | #include <linux/gfp.h>
|
| 9 | #include <linux/init.h>
|
| 10 | #include <linux/module.h>
|
| 11 | #include <linux/mount.h>
|
| 12 | #include <linux/srcu.h>
|
| 13 |
|
| 14 | #include <linux/fsnotify_backend.h>
|
| 15 | #include "fsnotify.h"
|
| 16 |
|
| 17 | #define CREATE_TRACE_POINTS
|
| 18 | #include <trace/events/fsnotify.h>
|
| 19 |
|
| 20 | |
| 21 | * Clear all of the marks on an inode when it is being evicted from core
|
| 22 |
|
| 23 | void __fsnotify_inode_delete(struct inode *inode)
|
| 24 | {
|
| 25 | fsnotify_clear_marks_by_inode(inode);
|
| 26 | }
|
| 27 | EXPORT_SYMBOL_GPL(__fsnotify_inode_delete);
|
| 28 |
|
| 29 | void __fsnotify_vfsmount_delete(struct vfsmount *mnt)
|
| 30 | {
|
| 31 | fsnotify_clear_marks_by_mount(mnt);
|
| 32 | }
|
| 33 |
|
| 34 | void __fsnotify_mntns_delete(struct mnt_namespace *mntns)
|
| 35 | {
|
| 36 | fsnotify_clear_marks_by_mntns(mntns);
|
| 37 | }
|
| 38 |
|
| 39 | void fsnotify_sb_delete(struct super_block *sb)
|
| 40 | {
|
| 41 | struct fsnotify_sb_info *sbinfo = fsnotify_sb_info(sb);
|
| 42 |
|
| 43 |
|
| 44 | if (!sbinfo)
|
| 45 | return;
|
| 46 |
|
| 47 | fsnotify_unmount_inodes(sbinfo);
|
| 48 | fsnotify_clear_marks_by_sb(sb);
|
| 49 |
|
| 50 | wait_var_event(fsnotify_sb_watched_objects(sb),
|
| 51 | !atomic_long_read(fsnotify_sb_watched_objects(sb)));
|
| 52 | WARN_ON(fsnotify_sb_has_priority_watchers(sb, FSNOTIFY_PRIO_CONTENT));
|
| 53 | WARN_ON(fsnotify_sb_has_priority_watchers(sb,
|
| 54 | FSNOTIFY_PRIO_PRE_CONTENT));
|
| 55 | }
|
| 56 |
|
| 57 | void fsnotify_sb_free(struct super_block *sb)
|
| 58 | {
|
| 59 | if (sb->s_fsnotify_info) {
|
| 60 | WARN_ON_ONCE(!list_empty(&sb->s_fsnotify_info->inode_conn_list));
|
| 61 | kfree(sb->s_fsnotify_info);
|
| 62 | }
|
| 63 | }
|
| 64 |
|
| 65 | |
| 66 | * Given an inode, first check if we care what happens to our children. Inotify
|
| 67 | * and dnotify both tell their parents about events. If we care about any event
|
| 68 | * on a child we run all of our children and set a dentry flag saying that the
|
| 69 | * parent cares. Thus when an event happens on a child it can quickly tell
|
| 70 | * if there is a need to find a parent and send the event to the parent.
|
| 71 |
|
| 72 | void fsnotify_set_children_dentry_flags(struct inode *inode)
|
| 73 | {
|
| 74 | struct dentry *alias;
|
| 75 |
|
| 76 | if (!S_ISDIR(inode->i_mode))
|
| 77 | return;
|
| 78 |
|
| 79 | spin_lock(&inode->i_lock);
|
| 80 | |
| 81 | * directory, there damn well better only be one item on this list
|
| 82 | for_each_alias(alias, inode) {
|
| 83 | struct dentry *child;
|
| 84 |
|
| 85 | |
| 86 | * d_flags to indicate parental interest (their parent is the
|
| 87 | * original inode)
|
| 88 | spin_lock(&alias->d_lock);
|
| 89 | hlist_for_each_entry(child, &alias->d_children, d_sib) {
|
| 90 | if (!child->d_inode)
|
| 91 | continue;
|
| 92 |
|
| 93 | spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
|
| 94 | child->d_flags |= DCACHE_FSNOTIFY_PARENT_WATCHED;
|
| 95 | spin_unlock(&child->d_lock);
|
| 96 | }
|
| 97 | spin_unlock(&alias->d_lock);
|
| 98 | }
|
| 99 | spin_unlock(&inode->i_lock);
|
| 100 | }
|
| 101 |
|
| 102 | |
| 103 | * Lazily clear false positive PARENT_WATCHED flag for child whose parent had
|
| 104 | * stopped watching children.
|
| 105 |
|
| 106 | static void fsnotify_clear_child_dentry_flag(struct inode *pinode,
|
| 107 | struct dentry *dentry)
|
| 108 | {
|
| 109 | spin_lock(&dentry->d_lock);
|
| 110 | |
| 111 | * d_lock is a sufficient barrier to prevent observing a non-watched
|
| 112 | * parent state from before the fsnotify_set_children_dentry_flags()
|
| 113 | * or fsnotify_update_flags() call that had set PARENT_WATCHED.
|
| 114 |
|
| 115 | if (!fsnotify_inode_watches_children(pinode))
|
| 116 | dentry->d_flags &= ~DCACHE_FSNOTIFY_PARENT_WATCHED;
|
| 117 | spin_unlock(&dentry->d_lock);
|
| 118 | }
|
| 119 |
|
| 120 |
|
| 121 | static bool fsnotify_event_needs_parent(struct inode *inode, __u32 mnt_mask,
|
| 122 | __u32 mask)
|
| 123 | {
|
| 124 | __u32 marks_mask = 0;
|
| 125 |
|
| 126 |
|
| 127 | if (mask & FS_ISDIR)
|
| 128 | return false;
|
| 129 |
|
| 130 | |
| 131 | * All events that are possible on child can also may be reported with
|
| 132 | * parent/name info to inode/sb/mount. Otherwise, a watching parent
|
| 133 | * could result in events reported with unexpected name info to sb/mount.
|
| 134 |
|
| 135 | BUILD_BUG_ON(FS_EVENTS_POSS_ON_CHILD & ~FS_EVENTS_POSS_TO_PARENT);
|
| 136 |
|
| 137 |
|
| 138 | marks_mask |= fsnotify_parent_needed_mask(
|
| 139 | READ_ONCE(inode->i_fsnotify_mask));
|
| 140 | marks_mask |= fsnotify_parent_needed_mask(
|
| 141 | READ_ONCE(inode->i_sb->s_fsnotify_mask));
|
| 142 | marks_mask |= fsnotify_parent_needed_mask(mnt_mask);
|
| 143 |
|
| 144 |
|
| 145 | return mask & marks_mask;
|
| 146 | }
|
| 147 |
|
| 148 |
|
| 149 | static inline __u32 fsnotify_object_watched(struct inode *inode, __u32 mnt_mask,
|
| 150 | __u32 mask)
|
| 151 | {
|
| 152 | __u32 marks_mask = READ_ONCE(inode->i_fsnotify_mask) | mnt_mask |
|
| 153 | READ_ONCE(inode->i_sb->s_fsnotify_mask);
|
| 154 |
|
| 155 | return mask & marks_mask & ALL_FSNOTIFY_EVENTS;
|
| 156 | }
|
| 157 |
|
| 158 |
|
| 159 | int fsnotify_pre_content(const struct path *path, const loff_t *ppos,
|
| 160 | size_t count)
|
| 161 | {
|
| 162 | struct file_range range;
|
| 163 |
|
| 164 |
|
| 165 | if (!ppos)
|
| 166 | return fsnotify_path(path, FS_PRE_ACCESS);
|
| 167 |
|
| 168 | range.path = path;
|
| 169 | range.pos = PAGE_ALIGN_DOWN(*ppos);
|
| 170 | range.count = PAGE_ALIGN(*ppos + count) - range.pos;
|
| 171 |
|
| 172 | return fsnotify_parent(path->dentry, FS_PRE_ACCESS, &range,
|
| 173 | FSNOTIFY_EVENT_FILE_RANGE);
|
| 174 | }
|
| 175 |
|
| 176 | |
| 177 | * Notify this dentry's parent about a child's events with child name info
|
| 178 | * if parent is watching or if inode/sb/mount are interested in events with
|
| 179 | * parent and name info.
|
| 180 | *
|
| 181 | * Notify only the child without name info if parent is not watching and
|
| 182 | * inode/sb/mount are not interested in events with parent and name info.
|
| 183 |
|
| 184 | int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
|
| 185 | int data_type)
|
| 186 | {
|
| 187 | const struct path *path = fsnotify_data_path(data, data_type);
|
| 188 | __u32 mnt_mask = path ?
|
| 189 | READ_ONCE(real_mount(path->mnt)->mnt_fsnotify_mask) : 0;
|
| 190 | struct inode *inode = d_inode(dentry);
|
| 191 | struct dentry *parent;
|
| 192 | bool parent_watched = dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED;
|
| 193 | bool parent_needed, parent_interested;
|
| 194 | __u32 p_mask;
|
| 195 | struct inode *p_inode = NULL;
|
| 196 | struct name_snapshot name;
|
| 197 | struct qstr *file_name = NULL;
|
| 198 | int ret = 0;
|
| 199 |
|
| 200 |
|
| 201 | if (likely(!parent_watched &&
|
| 202 | !fsnotify_object_watched(inode, mnt_mask, mask)))
|
| 203 | return 0;
|
| 204 |
|
| 205 | parent = NULL;
|
| 206 | parent_needed = fsnotify_event_needs_parent(inode, mnt_mask, mask);
|
| 207 | if (!parent_watched && !parent_needed)
|
| 208 | goto notify;
|
| 209 |
|
| 210 |
|
| 211 | parent = dget_parent(dentry);
|
| 212 | p_inode = parent->d_inode;
|
| 213 | p_mask = fsnotify_inode_watches_children(p_inode);
|
| 214 | if (unlikely(parent_watched && !p_mask))
|
| 215 | fsnotify_clear_child_dentry_flag(p_inode, dentry);
|
| 216 |
|
| 217 | |
| 218 | * Include parent/name in notification either if some notification
|
| 219 | * groups require parent info or the parent is interested in this event.
|
| 220 | * The parent interest in ACCESS/MODIFY events does not apply to special
|
| 221 | * files, where read/write are not on the filesystem of the parent and
|
| 222 | * events can provide an undesirable side-channel for information
|
| 223 | * exfiltration.
|
| 224 |
|
| 225 | parent_interested = mask & p_mask & ALL_FSNOTIFY_EVENTS &&
|
| 226 | !(data_type == FSNOTIFY_EVENT_PATH &&
|
| 227 | d_is_special(dentry) &&
|
| 228 | (mask & (FS_ACCESS | FS_MODIFY)));
|
| 229 | if (parent_needed || parent_interested) {
|
| 230 |
|
| 231 | WARN_ON_ONCE(inode != fsnotify_data_inode(data, data_type));
|
| 232 |
|
| 233 |
|
| 234 | take_dentry_name_snapshot(&name, dentry);
|
| 235 | file_name = &name.name;
|
| 236 | if (parent_interested)
|
| 237 | mask |= FS_EVENT_ON_CHILD;
|
| 238 | }
|
| 239 |
|
| 240 | notify:
|
| 241 | ret = fsnotify(mask, data, data_type, p_inode, file_name, inode, 0);
|
| 242 |
|
| 243 | if (file_name)
|
| 244 | release_dentry_name_snapshot(&name);
|
| 245 | dput(parent);
|
| 246 |
|
| 247 | return ret;
|
| 248 | }
|
| 249 | EXPORT_SYMBOL_GPL(__fsnotify_parent);
|
| 250 |
|
| 251 | static int fsnotify_handle_inode_event(struct fsnotify_group *group,
|
| 252 | struct fsnotify_mark *inode_mark,
|
| 253 | u32 mask, const void *data, int data_type,
|
| 254 | struct inode *dir, const struct qstr *name,
|
| 255 | u32 cookie)
|
| 256 | {
|
| 257 | const struct path *path = fsnotify_data_path(data, data_type);
|
| 258 | struct inode *inode = fsnotify_data_inode(data, data_type);
|
| 259 | const struct fsnotify_ops *ops = group->ops;
|
| 260 |
|
| 261 | if (WARN_ON_ONCE(!ops->handle_inode_event))
|
| 262 | return 0;
|
| 263 |
|
| 264 | if (WARN_ON_ONCE(!inode && !dir))
|
| 265 | return 0;
|
| 266 |
|
| 267 | if ((inode_mark->flags & FSNOTIFY_MARK_FLAG_EXCL_UNLINK) &&
|
| 268 | path && d_unlinked(path->dentry))
|
| 269 | return 0;
|
| 270 |
|
| 271 |
|
| 272 | if (!(mask & inode_mark->mask & ALL_FSNOTIFY_EVENTS))
|
| 273 | return 0;
|
| 274 |
|
| 275 | return ops->handle_inode_event(inode_mark, mask, inode, dir, name, cookie);
|
| 276 | }
|
| 277 |
|
| 278 | static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask,
|
| 279 | const void *data, int data_type,
|
| 280 | struct inode *dir, const struct qstr *name,
|
| 281 | u32 cookie, struct fsnotify_iter_info *iter_info)
|
| 282 | {
|
| 283 | struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
|
| 284 | struct fsnotify_mark *parent_mark = fsnotify_iter_parent_mark(iter_info);
|
| 285 | int ret;
|
| 286 |
|
| 287 | if (WARN_ON_ONCE(fsnotify_iter_sb_mark(iter_info)) ||
|
| 288 | WARN_ON_ONCE(fsnotify_iter_vfsmount_mark(iter_info)))
|
| 289 | return 0;
|
| 290 |
|
| 291 | |
| 292 | * For FS_RENAME, 'dir' is old dir and 'data' is new dentry.
|
| 293 | * The only ->handle_inode_event() backend that supports FS_RENAME is
|
| 294 | * dnotify, where it means file was renamed within same parent.
|
| 295 |
|
| 296 | if (mask & FS_RENAME) {
|
| 297 | struct dentry *moved = fsnotify_data_dentry(data, data_type);
|
| 298 |
|
| 299 | if (dir != moved->d_parent->d_inode)
|
| 300 | return 0;
|
| 301 | }
|
| 302 |
|
| 303 | if (parent_mark) {
|
| 304 | ret = fsnotify_handle_inode_event(group, parent_mark, mask,
|
| 305 | data, data_type, dir, name, 0);
|
| 306 | if (ret)
|
| 307 | return ret;
|
| 308 | }
|
| 309 |
|
| 310 | if (!inode_mark)
|
| 311 | return 0;
|
| 312 |
|
| 313 | |
| 314 | * Some events can be sent on both parent dir and child marks (e.g.
|
| 315 | * FS_ATTRIB). If both parent dir and child are watching, report the
|
| 316 | * event once to parent dir with name (if interested) and once to child
|
| 317 | * without name (if interested).
|
| 318 | *
|
| 319 | * In any case regardless whether the parent is watching or not, the
|
| 320 | * child watcher is expecting an event without the FS_EVENT_ON_CHILD
|
| 321 | * flag. The file name is expected if and only if this is a directory
|
| 322 | * event.
|
| 323 |
|
| 324 | mask &= ~FS_EVENT_ON_CHILD;
|
| 325 | if (!(mask & ALL_FSNOTIFY_DIRENT_EVENTS)) {
|
| 326 | dir = NULL;
|
| 327 | name = NULL;
|
| 328 | }
|
| 329 |
|
| 330 | return fsnotify_handle_inode_event(group, inode_mark, mask, data, data_type,
|
| 331 | dir, name, cookie);
|
| 332 | }
|
| 333 |
|
| 334 | static int send_to_group(__u32 mask, const void *data, int data_type,
|
| 335 | struct inode *dir, const struct qstr *file_name,
|
| 336 | u32 cookie, struct fsnotify_iter_info *iter_info)
|
| 337 | {
|
| 338 | struct fsnotify_group *group = NULL;
|
| 339 | __u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS);
|
| 340 | __u32 marks_mask = 0;
|
| 341 | __u32 marks_ignore_mask = 0;
|
| 342 | bool is_dir = mask & FS_ISDIR;
|
| 343 | struct fsnotify_mark *mark;
|
| 344 | int type;
|
| 345 |
|
| 346 | if (!iter_info->report_mask)
|
| 347 | return 0;
|
| 348 |
|
| 349 |
|
| 350 | if (mask & FS_MODIFY) {
|
| 351 | fsnotify_foreach_iter_mark_type(iter_info, mark, type) {
|
| 352 | if (!(mark->flags &
|
| 353 | FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
|
| 354 | mark->ignore_mask = 0;
|
| 355 | }
|
| 356 | }
|
| 357 |
|
| 358 |
|
| 359 | fsnotify_foreach_iter_mark_type(iter_info, mark, type) {
|
| 360 | group = mark->group;
|
| 361 | marks_mask |= mark->mask;
|
| 362 | marks_ignore_mask |=
|
| 363 | fsnotify_effective_ignore_mask(mark, is_dir, type);
|
| 364 | }
|
| 365 |
|
| 366 | pr_debug("%s: group=%p mask=%x marks_mask=%x marks_ignore_mask=%x data=%p data_type=%d dir=%p cookie=%d\n",
|
| 367 | __func__, group, mask, marks_mask, marks_ignore_mask,
|
| 368 | data, data_type, dir, cookie);
|
| 369 |
|
| 370 | if (!(test_mask & marks_mask & ~marks_ignore_mask))
|
| 371 | return 0;
|
| 372 |
|
| 373 | if (group->ops->handle_event) {
|
| 374 | return group->ops->handle_event(group, mask, data, data_type, dir,
|
| 375 | file_name, cookie, iter_info);
|
| 376 | }
|
| 377 |
|
| 378 | return fsnotify_handle_event(group, mask, data, data_type, dir,
|
| 379 | file_name, cookie, iter_info);
|
| 380 | }
|
| 381 |
|
| 382 | static struct fsnotify_mark *fsnotify_first_mark(struct fsnotify_mark_connector *const *connp)
|
| 383 | {
|
| 384 | struct fsnotify_mark_connector *conn;
|
| 385 | struct hlist_node *node = NULL;
|
| 386 |
|
| 387 | conn = srcu_dereference(*connp, &fsnotify_mark_srcu);
|
| 388 | if (conn)
|
| 389 | node = srcu_dereference(conn->list.first, &fsnotify_mark_srcu);
|
| 390 |
|
| 391 | return hlist_entry_safe(node, struct fsnotify_mark, obj_list);
|
| 392 | }
|
| 393 |
|
| 394 | struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
|
| 395 | {
|
| 396 | struct hlist_node *node = NULL;
|
| 397 |
|
| 398 | if (mark)
|
| 399 | node = srcu_dereference(mark->obj_list.next,
|
| 400 | &fsnotify_mark_srcu);
|
| 401 |
|
| 402 | return hlist_entry_safe(node, struct fsnotify_mark, obj_list);
|
| 403 | }
|
| 404 |
|
| 405 | |
| 406 | * iter_info is a multi head priority queue of marks.
|
| 407 | * Pick a subset of marks from queue heads, all with the same group
|
| 408 | * and set the report_mask to a subset of the selected marks.
|
| 409 | * Returns false if there are no more groups to iterate.
|
| 410 |
|
| 411 | static bool fsnotify_iter_select_report_types(
|
| 412 | struct fsnotify_iter_info *iter_info)
|
| 413 | {
|
| 414 | struct fsnotify_group *max_prio_group = NULL;
|
| 415 | struct fsnotify_mark *mark;
|
| 416 | int type;
|
| 417 |
|
| 418 |
|
| 419 | fsnotify_foreach_iter_type(type) {
|
| 420 | mark = iter_info->marks[type];
|
| 421 | if (mark &&
|
| 422 | fsnotify_compare_groups(max_prio_group, mark->group) > 0)
|
| 423 | max_prio_group = mark->group;
|
| 424 | }
|
| 425 |
|
| 426 | if (!max_prio_group)
|
| 427 | return false;
|
| 428 |
|
| 429 |
|
| 430 | iter_info->current_group = max_prio_group;
|
| 431 | iter_info->report_mask = 0;
|
| 432 | fsnotify_foreach_iter_type(type) {
|
| 433 | mark = iter_info->marks[type];
|
| 434 | if (mark && mark->group == iter_info->current_group) {
|
| 435 | |
| 436 | * FSNOTIFY_ITER_TYPE_PARENT indicates that this inode
|
| 437 | * is watching children and interested in this event,
|
| 438 | * which is an event possible on child.
|
| 439 | * But is *this mark* watching children?
|
| 440 |
|
| 441 | if (type == FSNOTIFY_ITER_TYPE_PARENT &&
|
| 442 | !(mark->mask & FS_EVENT_ON_CHILD) &&
|
| 443 | !(fsnotify_ignore_mask(mark) & FS_EVENT_ON_CHILD))
|
| 444 | continue;
|
| 445 |
|
| 446 | fsnotify_iter_set_report_type(iter_info, type);
|
| 447 | }
|
| 448 | }
|
| 449 |
|
| 450 | return true;
|
| 451 | }
|
| 452 |
|
| 453 | |
| 454 | * Pop from iter_info multi head queue, the marks that belong to the group of
|
| 455 | * current iteration step.
|
| 456 |
|
| 457 | static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info)
|
| 458 | {
|
| 459 | struct fsnotify_mark *mark;
|
| 460 | int type;
|
| 461 |
|
| 462 | |
| 463 | * We cannot use fsnotify_foreach_iter_mark_type() here because we
|
| 464 | * may need to advance a mark of type X that belongs to current_group
|
| 465 | * but was not selected for reporting.
|
| 466 |
|
| 467 | fsnotify_foreach_iter_type(type) {
|
| 468 | mark = iter_info->marks[type];
|
| 469 | if (mark && mark->group == iter_info->current_group)
|
| 470 | iter_info->marks[type] =
|
| 471 | fsnotify_next_mark(iter_info->marks[type]);
|
| 472 | }
|
| 473 | }
|
| 474 |
|
| 475 | |
| 476 | * fsnotify - This is the main call to fsnotify.
|
| 477 | *
|
| 478 | * The VFS calls into hook specific functions in linux/fsnotify.h.
|
| 479 | * Those functions then in turn call here. Here will call out to all of the
|
| 480 | * registered fsnotify_group. Those groups can then use the notification event
|
| 481 | * in whatever means they feel necessary.
|
| 482 | *
|
| 483 | * @mask: event type and flags
|
| 484 | * @data: object that event happened on
|
| 485 | * @data_type: type of object for fanotify_data_XXX() accessors
|
| 486 | * @dir: optional directory associated with event -
|
| 487 | * if @file_name is not NULL, this is the directory that
|
| 488 | * @file_name is relative to
|
| 489 | * @file_name: optional file name associated with event
|
| 490 | * @inode: optional inode associated with event -
|
| 491 | * If @dir and @inode are both non-NULL, event may be
|
| 492 | * reported to both.
|
| 493 | * @cookie: inotify rename cookie
|
| 494 |
|
| 495 | int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,
|
| 496 | const struct qstr *file_name, struct inode *inode, u32 cookie)
|
| 497 | {
|
| 498 | const struct path *path = fsnotify_data_path(data, data_type);
|
| 499 | struct super_block *sb = fsnotify_data_sb(data, data_type);
|
| 500 | const struct fsnotify_mnt *mnt_data = fsnotify_data_mnt(data, data_type);
|
| 501 | struct fsnotify_sb_info *sbinfo = sb ? fsnotify_sb_info(sb) : NULL;
|
| 502 | struct fsnotify_iter_info iter_info = {};
|
| 503 | struct mount *mnt = NULL;
|
| 504 | struct inode *inode2 = NULL;
|
| 505 | struct dentry *moved;
|
| 506 | int inode2_type;
|
| 507 | int ret = 0;
|
| 508 | __u32 test_mask, marks_mask = 0;
|
| 509 |
|
| 510 | trace_fsnotify(mask, data, data_type, dir, file_name, inode, cookie);
|
| 511 |
|
| 512 | if (path)
|
| 513 | mnt = real_mount(path->mnt);
|
| 514 |
|
| 515 | if (!inode) {
|
| 516 |
|
| 517 | inode = dir;
|
| 518 |
|
| 519 | if (mask & FS_RENAME) {
|
| 520 | moved = fsnotify_data_dentry(data, data_type);
|
| 521 | inode2 = moved->d_parent->d_inode;
|
| 522 | inode2_type = FSNOTIFY_ITER_TYPE_INODE2;
|
| 523 | }
|
| 524 | } else if (mask & FS_EVENT_ON_CHILD) {
|
| 525 | |
| 526 | * Event on child - report on TYPE_PARENT to dir if it is
|
| 527 | * watching children and on TYPE_INODE to child.
|
| 528 |
|
| 529 | inode2 = dir;
|
| 530 | inode2_type = FSNOTIFY_ITER_TYPE_PARENT;
|
| 531 | }
|
| 532 |
|
| 533 | |
| 534 | * Optimization: srcu_read_lock() has a memory barrier which can
|
| 535 | * be expensive. It protects walking the *_fsnotify_marks lists.
|
| 536 | * However, if we do not walk the lists, we do not have to do
|
| 537 | * SRCU because we have no references to any objects and do not
|
| 538 | * need SRCU to keep them "alive".
|
| 539 |
|
| 540 | if ((!sbinfo || !sbinfo->sb_marks) &&
|
| 541 | (!mnt || !mnt->mnt_fsnotify_marks) &&
|
| 542 | (!inode || !inode->i_fsnotify_marks) &&
|
| 543 | (!inode2 || !inode2->i_fsnotify_marks) &&
|
| 544 | (!mnt_data || !mnt_data->ns->n_fsnotify_marks))
|
| 545 | return 0;
|
| 546 |
|
| 547 | if (sb)
|
| 548 | marks_mask |= READ_ONCE(sb->s_fsnotify_mask);
|
| 549 | if (mnt)
|
| 550 | marks_mask |= READ_ONCE(mnt->mnt_fsnotify_mask);
|
| 551 | if (inode)
|
| 552 | marks_mask |= READ_ONCE(inode->i_fsnotify_mask);
|
| 553 | if (inode2)
|
| 554 | marks_mask |= READ_ONCE(inode2->i_fsnotify_mask);
|
| 555 | if (mnt_data)
|
| 556 | marks_mask |= READ_ONCE(mnt_data->ns->n_fsnotify_mask);
|
| 557 |
|
| 558 | |
| 559 | * If this is a modify event we may need to clear some ignore masks.
|
| 560 | * In that case, the object with ignore masks will have the FS_MODIFY
|
| 561 | * event in its mask.
|
| 562 | * Otherwise, return if none of the marks care about this type of event.
|
| 563 |
|
| 564 | test_mask = (mask & ALL_FSNOTIFY_EVENTS);
|
| 565 | if (!(test_mask & marks_mask))
|
| 566 | return 0;
|
| 567 |
|
| 568 | iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
|
| 569 |
|
| 570 | if (sbinfo) {
|
| 571 | iter_info.marks[FSNOTIFY_ITER_TYPE_SB] =
|
| 572 | fsnotify_first_mark(&sbinfo->sb_marks);
|
| 573 | }
|
| 574 | if (mnt) {
|
| 575 | iter_info.marks[FSNOTIFY_ITER_TYPE_VFSMOUNT] =
|
| 576 | fsnotify_first_mark(&mnt->mnt_fsnotify_marks);
|
| 577 | }
|
| 578 | if (inode) {
|
| 579 | iter_info.marks[FSNOTIFY_ITER_TYPE_INODE] =
|
| 580 | fsnotify_first_mark(&inode->i_fsnotify_marks);
|
| 581 | }
|
| 582 | if (inode2) {
|
| 583 | iter_info.marks[inode2_type] =
|
| 584 | fsnotify_first_mark(&inode2->i_fsnotify_marks);
|
| 585 | }
|
| 586 | if (mnt_data) {
|
| 587 | iter_info.marks[FSNOTIFY_ITER_TYPE_MNTNS] =
|
| 588 | fsnotify_first_mark(&mnt_data->ns->n_fsnotify_marks);
|
| 589 | }
|
| 590 |
|
| 591 | |
| 592 | * We need to merge inode/vfsmount/sb mark lists so that e.g. inode mark
|
| 593 | * ignore masks are properly reflected for mount/sb mark notifications.
|
| 594 | * That's why this traversal is so complicated...
|
| 595 |
|
| 596 | while (fsnotify_iter_select_report_types(&iter_info)) {
|
| 597 | ret = send_to_group(mask, data, data_type, dir, file_name,
|
| 598 | cookie, &iter_info);
|
| 599 |
|
| 600 | if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
|
| 601 | goto out;
|
| 602 |
|
| 603 | fsnotify_iter_next(&iter_info);
|
| 604 | }
|
| 605 | ret = 0;
|
| 606 | out:
|
| 607 | srcu_read_unlock(&fsnotify_mark_srcu, iter_info.srcu_idx);
|
| 608 |
|
| 609 | return ret;
|
| 610 | }
|
| 611 | EXPORT_SYMBOL_GPL(fsnotify);
|
| 612 |
|
| 613 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
|
| 614 | |
| 615 | * At open time we check fsnotify_sb_has_priority_watchers(), call the open perm
|
| 616 | * hook and set the FMODE_NONOTIFY_ mode bits accordignly.
|
| 617 | * Later, fsnotify permission hooks do not check if there are permission event
|
| 618 | * watches, but that there were permission event watches at open time.
|
| 619 |
|
| 620 | int fsnotify_open_perm_and_set_mode(struct file *file)
|
| 621 | {
|
| 622 | struct dentry *dentry = file->f_path.dentry, *parent;
|
| 623 | struct super_block *sb = dentry->d_sb;
|
| 624 | __u32 mnt_mask, p_mask = 0;
|
| 625 |
|
| 626 |
|
| 627 | if (FMODE_FSNOTIFY_NONE(file->f_mode))
|
| 628 | return 0;
|
| 629 |
|
| 630 | |
| 631 | * Permission events is a super set of pre-content events, so if there
|
| 632 | * are no permission event watchers, there are also no pre-content event
|
| 633 | * watchers and this is implied from the single FMODE_NONOTIFY_PERM bit.
|
| 634 |
|
| 635 | if (likely(!fsnotify_sb_has_priority_watchers(sb,
|
| 636 | FSNOTIFY_PRIO_CONTENT))) {
|
| 637 | file_set_fsnotify_mode(file, FMODE_NONOTIFY_PERM);
|
| 638 | return 0;
|
| 639 | }
|
| 640 |
|
| 641 | |
| 642 | * OK, there are some permission event watchers. Check if anybody is
|
| 643 | * watching for permission events on *this* file.
|
| 644 |
|
| 645 | mnt_mask = READ_ONCE(real_mount(file->f_path.mnt)->mnt_fsnotify_mask);
|
| 646 | p_mask = fsnotify_object_watched(d_inode(dentry), mnt_mask,
|
| 647 | ALL_FSNOTIFY_PERM_EVENTS);
|
| 648 | if (dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED) {
|
| 649 | parent = dget_parent(dentry);
|
| 650 | p_mask |= fsnotify_inode_watches_children(d_inode(parent));
|
| 651 | dput(parent);
|
| 652 | }
|
| 653 |
|
| 654 | |
| 655 | * Legacy FAN_ACCESS_PERM events have very high performance overhead,
|
| 656 | * so unlikely to be used in the wild. If they are used there will be
|
| 657 | * no optimizations at all.
|
| 658 |
|
| 659 | if (unlikely(p_mask & FS_ACCESS_PERM)) {
|
| 660 |
|
| 661 | file_set_fsnotify_mode(file, 0);
|
| 662 | goto open_perm;
|
| 663 | }
|
| 664 |
|
| 665 | |
| 666 | * Pre-content events are only supported on regular files.
|
| 667 | * If there are pre-content event watchers and no permission access
|
| 668 | * watchers, set FMODE_NONOTIFY | FMODE_NONOTIFY_PERM to indicate that.
|
| 669 | * That is the common case with HSM service.
|
| 670 |
|
| 671 | if (d_is_reg(dentry) && (p_mask & FSNOTIFY_PRE_CONTENT_EVENTS)) {
|
| 672 | file_set_fsnotify_mode(file, FMODE_NONOTIFY |
|
| 673 | FMODE_NONOTIFY_PERM);
|
| 674 | goto open_perm;
|
| 675 | }
|
| 676 |
|
| 677 |
|
| 678 | file_set_fsnotify_mode(file, FMODE_NONOTIFY_PERM);
|
| 679 |
|
| 680 | open_perm:
|
| 681 | |
| 682 | * Send open perm events depending on object masks and regardless of
|
| 683 | * FMODE_NONOTIFY_PERM.
|
| 684 |
|
| 685 | if (file->f_flags & __FMODE_EXEC && p_mask & FS_OPEN_EXEC_PERM) {
|
| 686 | int ret = fsnotify_path(&file->f_path, FS_OPEN_EXEC_PERM);
|
| 687 |
|
| 688 | if (ret)
|
| 689 | return ret;
|
| 690 | }
|
| 691 |
|
| 692 | if (p_mask & FS_OPEN_PERM)
|
| 693 | return fsnotify_path(&file->f_path, FS_OPEN_PERM);
|
| 694 |
|
| 695 | return 0;
|
| 696 | }
|
| 697 | #endif
|
| 698 |
|
| 699 | void fsnotify_mnt(__u32 mask, struct mnt_namespace *ns, struct vfsmount *mnt)
|
| 700 | {
|
| 701 | struct fsnotify_mnt data = {
|
| 702 | .ns = ns,
|
| 703 | .mnt_id = real_mount(mnt)->mnt_id_unique,
|
| 704 | };
|
| 705 |
|
| 706 | if (WARN_ON_ONCE(!ns))
|
| 707 | return;
|
| 708 |
|
| 709 | |
| 710 | * This is an optimization as well as making sure fsnotify_init() has
|
| 711 | * been called.
|
| 712 |
|
| 713 | if (!ns->n_fsnotify_marks)
|
| 714 | return;
|
| 715 |
|
| 716 | fsnotify(mask, &data, FSNOTIFY_EVENT_MNT, NULL, NULL, NULL, 0);
|
| 717 | }
|
| 718 |
|
| 719 | static __init int fsnotify_init(void)
|
| 720 | {
|
| 721 | int ret;
|
| 722 |
|
| 723 | BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 26);
|
| 724 |
|
| 725 | ret = init_srcu_struct(&fsnotify_mark_srcu);
|
| 726 | if (ret)
|
| 727 | panic("initializing fsnotify_mark_srcu");
|
| 728 |
|
| 729 | fsnotify_init_connector_caches();
|
| 730 |
|
| 731 | return 0;
|
| 732 | }
|
| 733 | core_initcall(fsnotify_init);
|