| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Directory notifications for Linux. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Copyright (C) 2009 Eric Paris <Red Hat Inc> |
|---|
| 7 | 8 | * dnotify was largly rewritten to use the new fsnotify infrastructure |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 10 | | - * under the terms of the GNU General Public License as published by the |
|---|
| 11 | | - * Free Software Foundation; either version 2, or (at your option) any |
|---|
| 12 | | - * later version. |
|---|
| 13 | | - * |
|---|
| 14 | | - * This program is distributed in the hope that it will be useful, but |
|---|
| 15 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 16 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|---|
| 17 | | - * General Public License for more details. |
|---|
| 18 | 9 | */ |
|---|
| 19 | 10 | #include <linux/fs.h> |
|---|
| 20 | 11 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 22 | 13 | #include <linux/sched/signal.h> |
|---|
| 23 | 14 | #include <linux/dnotify.h> |
|---|
| 24 | 15 | #include <linux/init.h> |
|---|
| 16 | +#include <linux/security.h> |
|---|
| 25 | 17 | #include <linux/spinlock.h> |
|---|
| 26 | 18 | #include <linux/slab.h> |
|---|
| 27 | 19 | #include <linux/fdtable.h> |
|---|
| .. | .. |
|---|
| 78 | 70 | * destroy the dnotify struct if it was not registered to receive multiple |
|---|
| 79 | 71 | * events. |
|---|
| 80 | 72 | */ |
|---|
| 81 | | -static int dnotify_handle_event(struct fsnotify_group *group, |
|---|
| 82 | | - struct inode *inode, |
|---|
| 83 | | - u32 mask, const void *data, int data_type, |
|---|
| 84 | | - const unsigned char *file_name, u32 cookie, |
|---|
| 85 | | - struct fsnotify_iter_info *iter_info) |
|---|
| 73 | +static int dnotify_handle_event(struct fsnotify_mark *inode_mark, u32 mask, |
|---|
| 74 | + struct inode *inode, struct inode *dir, |
|---|
| 75 | + const struct qstr *name, u32 cookie) |
|---|
| 86 | 76 | { |
|---|
| 87 | | - struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); |
|---|
| 88 | 77 | struct dnotify_mark *dn_mark; |
|---|
| 89 | 78 | struct dnotify_struct *dn; |
|---|
| 90 | 79 | struct dnotify_struct **prev; |
|---|
| .. | .. |
|---|
| 92 | 81 | __u32 test_mask = mask & ~FS_EVENT_ON_CHILD; |
|---|
| 93 | 82 | |
|---|
| 94 | 83 | /* not a dir, dnotify doesn't care */ |
|---|
| 95 | | - if (!S_ISDIR(inode->i_mode)) |
|---|
| 96 | | - return 0; |
|---|
| 97 | | - |
|---|
| 98 | | - if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info))) |
|---|
| 84 | + if (!dir && !(mask & FS_ISDIR)) |
|---|
| 99 | 85 | return 0; |
|---|
| 100 | 86 | |
|---|
| 101 | 87 | dn_mark = container_of(inode_mark, struct dnotify_mark, fsn_mark); |
|---|
| .. | .. |
|---|
| 135 | 121 | } |
|---|
| 136 | 122 | |
|---|
| 137 | 123 | static const struct fsnotify_ops dnotify_fsnotify_ops = { |
|---|
| 138 | | - .handle_event = dnotify_handle_event, |
|---|
| 124 | + .handle_inode_event = dnotify_handle_event, |
|---|
| 139 | 125 | .free_mark = dnotify_free_mark, |
|---|
| 140 | 126 | }; |
|---|
| 141 | 127 | |
|---|
| .. | .. |
|---|
| 288 | 274 | goto out_err; |
|---|
| 289 | 275 | } |
|---|
| 290 | 276 | |
|---|
| 277 | + /* |
|---|
| 278 | + * convert the userspace DN_* "arg" to the internal FS_* |
|---|
| 279 | + * defined in fsnotify |
|---|
| 280 | + */ |
|---|
| 281 | + mask = convert_arg(arg); |
|---|
| 282 | + |
|---|
| 283 | + error = security_path_notify(&filp->f_path, mask, |
|---|
| 284 | + FSNOTIFY_OBJ_TYPE_INODE); |
|---|
| 285 | + if (error) |
|---|
| 286 | + goto out_err; |
|---|
| 287 | + |
|---|
| 291 | 288 | /* expect most fcntl to add new rather than augment old */ |
|---|
| 292 | 289 | dn = kmem_cache_alloc(dnotify_struct_cache, GFP_KERNEL); |
|---|
| 293 | 290 | if (!dn) { |
|---|
| .. | .. |
|---|
| 301 | 298 | error = -ENOMEM; |
|---|
| 302 | 299 | goto out_err; |
|---|
| 303 | 300 | } |
|---|
| 304 | | - |
|---|
| 305 | | - /* convert the userspace DN_* "arg" to the internal FS_* defines in fsnotify */ |
|---|
| 306 | | - mask = convert_arg(arg); |
|---|
| 307 | 301 | |
|---|
| 308 | 302 | /* set up the new_fsn_mark and new_dn_mark */ |
|---|
| 309 | 303 | new_fsn_mark = &new_dn_mark->fsn_mark; |
|---|