.. | .. |
---|
| 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; |
---|