Lines Matching +full:signal +full:- +full:group
1 // SPDX-License-Identifier: GPL-2.0
11 #include <linux/sched/signal.h>
23 return p1->mnt == p2->mnt && p1->dentry == p2->dentry; in fanotify_path_equal()
28 return hash_ptr(path->dentry, FANOTIFY_EVENT_HASH_BITS) ^ in fanotify_hash_path()
29 hash_ptr(path->mnt, FANOTIFY_EVENT_HASH_BITS); in fanotify_hash_path()
35 return fsid1->val[0] == fsid2->val[0] && fsid1->val[1] == fsid2->val[1]; in fanotify_fsid_equal()
40 return hash_32(fsid->val[0], FANOTIFY_EVENT_HASH_BITS) ^ in fanotify_hash_fsid()
41 hash_32(fsid->val[1], FANOTIFY_EVENT_HASH_BITS); in fanotify_hash_fsid()
47 if (fh1->type != fh2->type || fh1->len != fh2->len) in fanotify_fh_equal()
50 return !fh1->len || in fanotify_fh_equal()
51 !memcmp(fanotify_fh_buf(fh1), fanotify_fh_buf(fh2), fh1->len); in fanotify_fh_equal()
56 long salt = (long)fh->type | (long)fh->len << 8; in fanotify_hash_fh()
61 return full_name_hash((void *)salt, fanotify_fh_buf(fh), fh->len); in fanotify_hash_fh()
68 if (!ffe1->object_fh.len) in fanotify_fid_event_equal()
71 return fanotify_fsid_equal(&ffe1->fsid, &ffe2->fsid) && in fanotify_fid_event_equal()
72 fanotify_fh_equal(&ffe1->object_fh, &ffe2->object_fh); in fanotify_fid_event_equal()
78 if (info1->dir_fh_totlen != info2->dir_fh_totlen || in fanotify_info_equal()
79 info1->dir2_fh_totlen != info2->dir2_fh_totlen || in fanotify_info_equal()
80 info1->file_fh_totlen != info2->file_fh_totlen || in fanotify_info_equal()
81 info1->name_len != info2->name_len || in fanotify_info_equal()
82 info1->name2_len != info2->name2_len) in fanotify_info_equal()
85 if (info1->dir_fh_totlen && in fanotify_info_equal()
90 if (info1->dir2_fh_totlen && in fanotify_info_equal()
95 if (info1->file_fh_totlen && in fanotify_info_equal()
100 if (info1->name_len && in fanotify_info_equal()
102 info1->name_len)) in fanotify_info_equal()
105 return !info1->name2_len || in fanotify_info_equal()
107 info1->name2_len); in fanotify_info_equal()
113 struct fanotify_info *info1 = &fne1->info; in fanotify_name_event_equal()
114 struct fanotify_info *info2 = &fne2->info; in fanotify_name_event_equal()
117 if (!info1->dir_fh_totlen) in fanotify_name_event_equal()
120 if (!fanotify_fsid_equal(&fne1->fsid, &fne2->fsid)) in fanotify_name_event_equal()
130 if (!fanotify_fsid_equal(&fee1->fsid, &fee2->fsid)) in fanotify_error_event_equal()
141 if (old->hash != new->hash || in fanotify_should_merge()
142 old->type != new->type || old->pid != new->pid) in fanotify_should_merge()
153 if ((old->mask & FS_ISDIR) != (new->mask & FS_ISDIR)) in fanotify_should_merge()
160 if ((old->mask & FAN_RENAME) != (new->mask & FAN_RENAME)) in fanotify_should_merge()
163 switch (old->type) { in fanotify_should_merge()
187 static int fanotify_merge(struct fsnotify_group *group, in fanotify_merge() argument
191 unsigned int bucket = fanotify_event_hash_bucket(group, new); in fanotify_merge()
192 struct hlist_head *hlist = &group->fanotify_data.merge_hash[bucket]; in fanotify_merge()
195 pr_debug("%s: group=%p event=%p bucket=%u\n", __func__, in fanotify_merge()
196 group, event, bucket); in fanotify_merge()
203 if (fanotify_is_perm_event(new->mask)) in fanotify_merge()
210 old->mask |= new->mask; in fanotify_merge()
212 if (fanotify_is_error_event(old->mask)) in fanotify_merge()
213 FANOTIFY_EE(old)->err_count++; in fanotify_merge()
225 * by a signal). The function returns 0 in case access got allowed by userspace,
226 * -EPERM in case userspace disallowed the access, and -ERESTARTSYS in case
227 * the wait got interrupted by a signal.
229 static int fanotify_get_response(struct fsnotify_group *group, in fanotify_get_response() argument
235 pr_debug("%s: group=%p event=%p\n", __func__, group, event); in fanotify_get_response()
237 ret = wait_event_killable(group->fanotify_data.access_waitq, in fanotify_get_response()
238 event->state == FAN_EVENT_ANSWERED); in fanotify_get_response()
239 /* Signal pending? */ in fanotify_get_response()
241 spin_lock(&group->notification_lock); in fanotify_get_response()
243 if (event->state == FAN_EVENT_REPORTED) { in fanotify_get_response()
245 event->state = FAN_EVENT_CANCELED; in fanotify_get_response()
246 spin_unlock(&group->notification_lock); in fanotify_get_response()
250 if (event->state == FAN_EVENT_INIT) { in fanotify_get_response()
251 fsnotify_remove_queued_event(group, &event->fae.fse); in fanotify_get_response()
253 WARN_ON_ONCE(!hlist_unhashed(&event->fae.merge_list)); in fanotify_get_response()
256 * Event may be also answered in case signal delivery raced in fanotify_get_response()
260 spin_unlock(&group->notification_lock); in fanotify_get_response()
265 switch (event->response & ~FAN_AUDIT) { in fanotify_get_response()
271 ret = -EPERM; in fanotify_get_response()
275 if (event->response & FAN_AUDIT) in fanotify_get_response()
276 audit_fanotify(event->response & ~FAN_AUDIT); in fanotify_get_response()
278 pr_debug("%s: group=%p event=%p about to return ret=%d\n", __func__, in fanotify_get_response()
279 group, event, ret); in fanotify_get_response()
281 fsnotify_destroy_event(group, &event->fae.fse); in fanotify_get_response()
292 static u32 fanotify_group_event_mask(struct fsnotify_group *group, in fanotify_group_event_mask() argument
302 unsigned int fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS); in fanotify_group_event_mask()
308 __func__, iter_info->report_mask, event_mask, data, data_type); in fanotify_group_event_mask()
315 if (!d_is_reg(path->dentry) && !d_can_lookup(path->dentry)) in fanotify_group_event_mask()
333 if (!fsnotify_mask_applicable(mark->mask, ondir, type)) in fanotify_group_event_mask()
336 marks_mask |= mark->mask; in fanotify_group_event_mask()
338 /* Record the mark types of this group that matched the event */ in fanotify_group_event_mask()
354 * fanotify_alloc_event() when group is reporting fid as indication in fanotify_group_event_mask()
408 void *buf = fh->buf; in fanotify_encode_fh()
411 fh->type = FILEID_ROOT; in fanotify_encode_fh()
412 fh->len = 0; in fanotify_encode_fh()
413 fh->flags = 0; in fanotify_encode_fh()
427 err = -ENOENT; in fanotify_encode_fh()
434 err = -ENOMEM; in fanotify_encode_fh()
441 fh->flags |= FANOTIFY_FH_FLAG_EXT_BUF; in fanotify_encode_fh()
446 err = -EINVAL; in fanotify_encode_fh()
450 fh->type = type; in fanotify_encode_fh()
451 fh->len = fh_len; in fanotify_encode_fh()
469 fh->type = FILEID_INVALID; in fanotify_encode_fh()
470 fh->len = 0; in fanotify_encode_fh()
492 * and the group flags.
494 * With the group flag FAN_REPORT_TARGET_FID, always report the child fid.
496 * Without the group flag FAN_REPORT_TARGET_FID, report the modified directory
531 if (inode && S_ISDIR(inode->i_mode)) in fanotify_dfid_inode()
547 pevent->fae.type = FANOTIFY_EVENT_TYPE_PATH; in fanotify_alloc_path_event()
548 pevent->path = *path; in fanotify_alloc_path_event()
552 return &pevent->fae; in fanotify_alloc_path_event()
564 pevent->fae.type = FANOTIFY_EVENT_TYPE_PATH_PERM; in fanotify_alloc_perm_event()
565 pevent->response = 0; in fanotify_alloc_perm_event()
566 pevent->state = FAN_EVENT_INIT; in fanotify_alloc_perm_event()
567 pevent->path = *path; in fanotify_alloc_perm_event()
570 return &pevent->fae; in fanotify_alloc_perm_event()
584 ffe->fae.type = FANOTIFY_EVENT_TYPE_FID; in fanotify_alloc_fid_event()
585 ffe->fsid = *fsid; in fanotify_alloc_fid_event()
587 fanotify_encode_fh(&ffe->object_fh, id, fanotify_encode_fh_len(id), in fanotify_alloc_fid_event()
590 return &ffe->fae; in fanotify_alloc_fid_event()
604 struct inode *dir2 = moved ? d_inode(moved->d_parent) : NULL; in fanotify_alloc_name_event()
605 const struct qstr *name2 = moved ? &moved->d_name : NULL; in fanotify_alloc_name_event()
609 unsigned long name_len = name ? name->len : 0; in fanotify_alloc_name_event()
610 unsigned long name2_len = name2 ? name2->len : 0; in fanotify_alloc_name_event()
625 fne->fae.type = FANOTIFY_EVENT_TYPE_FID_NAME; in fanotify_alloc_name_event()
626 fne->fsid = *fsid; in fanotify_alloc_name_event()
628 info = &fne->info; in fanotify_alloc_name_event()
647 *hash ^= full_name_hash((void *)name_len, name->name, name_len); in fanotify_alloc_name_event()
651 *hash ^= full_name_hash((void *)name2_len, name2->name, in fanotify_alloc_name_event()
657 info->name_len, info->name_len, fanotify_info_name(info)); in fanotify_alloc_name_event()
661 __func__, dir2_fh_len, info->name2_len, in fanotify_alloc_name_event()
662 info->name2_len, fanotify_info_name2(info)); in fanotify_alloc_name_event()
665 return &fne->fae; in fanotify_alloc_name_event()
669 struct fsnotify_group *group, in fanotify_alloc_error_event() argument
683 fee = mempool_alloc(&group->fanotify_data.error_events_pool, GFP_NOFS); in fanotify_alloc_error_event()
687 fee->fae.type = FANOTIFY_EVENT_TYPE_FS_ERROR; in fanotify_alloc_error_event()
688 fee->error = report->error; in fanotify_alloc_error_event()
689 fee->err_count = 1; in fanotify_alloc_error_event()
690 fee->fsid = *fsid; in fanotify_alloc_error_event()
692 inode = report->inode; in fanotify_alloc_error_event()
699 fanotify_encode_fh(&fee->object_fh, inode, fh_len, NULL, 0); in fanotify_alloc_error_event()
703 return &fee->fae; in fanotify_alloc_error_event()
707 struct fsnotify_group *group, in fanotify_alloc_event() argument
714 unsigned int fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS); in fanotify_alloc_event()
729 * For certain events and group flags, report the child fid in fanotify_alloc_event()
738 * We record file name only in a group with FAN_REPORT_NAME in fanotify_alloc_event()
744 * For event on non-directory that is reported to parent, we in fanotify_alloc_event()
796 if (group->max_events == UINT_MAX) in fanotify_alloc_event()
802 old_memcg = set_active_memcg(group->memcg); in fanotify_alloc_event()
807 event = fanotify_alloc_error_event(group, fsid, data, in fanotify_alloc_event()
821 if (FAN_GROUP_FLAG(group, FAN_REPORT_TID)) in fanotify_alloc_event()
829 event->pid = pid; in fanotify_alloc_event()
850 conn = READ_ONCE(mark->connector); in fanotify_get_fsid()
854 if (!(conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID)) in fanotify_get_fsid()
858 fsid = conn->fsid; in fanotify_get_fsid()
870 static void fanotify_insert_event(struct fsnotify_group *group, in fanotify_insert_event() argument
874 unsigned int bucket = fanotify_event_hash_bucket(group, event); in fanotify_insert_event()
875 struct hlist_head *hlist = &group->fanotify_data.merge_hash[bucket]; in fanotify_insert_event()
877 assert_spin_locked(&group->notification_lock); in fanotify_insert_event()
879 if (!fanotify_is_hashed_event(event->mask)) in fanotify_insert_event()
882 pr_debug("%s: group=%p event=%p bucket=%u\n", __func__, in fanotify_insert_event()
883 group, event, bucket); in fanotify_insert_event()
885 hlist_add_head(&event->merge_list, hlist); in fanotify_insert_event()
888 static int fanotify_handle_event(struct fsnotify_group *group, u32 mask, in fanotify_handle_event() argument
924 mask = fanotify_group_event_mask(group, iter_info, &match_mask, in fanotify_handle_event()
929 pr_debug("%s: group=%p mask=%x report_mask=%x\n", __func__, in fanotify_handle_event()
930 group, mask, match_mask); in fanotify_handle_event()
941 if (FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS)) { in fanotify_handle_event()
948 event = fanotify_alloc_event(group, mask, data, data_type, dir, in fanotify_handle_event()
950 ret = -ENOMEM; in fanotify_handle_event()
957 fsnotify_queue_overflow(group); in fanotify_handle_event()
961 fsn_event = &event->fse; in fanotify_handle_event()
962 ret = fsnotify_insert_event(group, fsn_event, fanotify_merge, in fanotify_handle_event()
968 fsnotify_destroy_event(group, fsn_event); in fanotify_handle_event()
972 ret = fanotify_get_response(group, FANOTIFY_PERM(event), in fanotify_handle_event()
982 static void fanotify_free_group_priv(struct fsnotify_group *group) in fanotify_free_group_priv() argument
984 kfree(group->fanotify_data.merge_hash); in fanotify_free_group_priv()
985 if (group->fanotify_data.ucounts) in fanotify_free_group_priv()
986 dec_ucount(group->fanotify_data.ucounts, in fanotify_free_group_priv()
989 if (mempool_initialized(&group->fanotify_data.error_events_pool)) in fanotify_free_group_priv()
990 mempool_exit(&group->fanotify_data.error_events_pool); in fanotify_free_group_priv()
1009 if (fanotify_fh_has_ext_buf(&ffe->object_fh)) in fanotify_free_fid_event()
1010 kfree(fanotify_fh_ext_buf(&ffe->object_fh)); in fanotify_free_fid_event()
1019 static void fanotify_free_error_event(struct fsnotify_group *group, in fanotify_free_error_event() argument
1024 mempool_free(fee, &group->fanotify_data.error_events_pool); in fanotify_free_error_event()
1027 static void fanotify_free_event(struct fsnotify_group *group, in fanotify_free_event() argument
1033 put_pid(event->pid); in fanotify_free_event()
1034 switch (event->type) { in fanotify_free_event()
1051 fanotify_free_error_event(group, event); in fanotify_free_event()
1059 struct fsnotify_group *group) in fanotify_freeing_mark() argument
1061 if (!FAN_GROUP_FLAG(group, FAN_UNLIMITED_MARKS)) in fanotify_freeing_mark()
1062 dec_ucount(group->fanotify_data.ucounts, UCOUNT_FANOTIFY_MARKS); in fanotify_freeing_mark()