Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-linus' of git://git.infradead.org/users/eparis/notify

* 'for-linus' of git://git.infradead.org/users/eparis/notify:
fsnotify: drop two useless bools in the fnsotify main loop
fsnotify: fix list walk order
fanotify: Return EPERM when a process is not privileged
fanotify: resize pid and reorder structure
fanotify: drop duplicate pr_debug statement
fanotify: flush outstanding perm requests on group destroy
fsnotify: fix ignored mask handling between inode and vfsmount marks
fanotify: add MAINTAINERS entry
fsnotify: reset used_inode and used_vfsmount on each pass
fanotify: do not dereference inode_mark when it is unset

+74 -46
+6
MAINTAINERS
··· 2296 2296 F: Documentation/hwmon/f71805f 2297 2297 F: drivers/hwmon/f71805f.c 2298 2298 2299 + FANOTIFY 2300 + M: Eric Paris <eparis@redhat.com> 2301 + S: Maintained 2302 + F: fs/notify/fanotify/ 2303 + F: include/linux/fanotify.h 2304 + 2299 2305 FARSYNC SYNCHRONOUS DRIVER 2300 2306 M: Kevin Curtis <kevin.curtis@farsite.co.uk> 2301 2307 W: http://www.farsite.co.uk/
-3
fs/notify/fanotify/fanotify.c
··· 165 165 "mask=%x data=%p data_type=%d\n", __func__, group, to_tell, 166 166 inode_mark, vfsmnt_mark, event_mask, data, data_type); 167 167 168 - pr_debug("%s: group=%p vfsmount_mark=%p inode_mark=%p mask=%x\n", 169 - __func__, group, vfsmnt_mark, inode_mark, event_mask); 170 - 171 168 /* sorry, fanotify only gives a damn about files and dirs */ 172 169 if (!S_ISREG(to_tell->i_mode) && 173 170 !S_ISDIR(to_tell->i_mode))
+28 -1
fs/notify/fanotify/fanotify_user.c
··· 195 195 re->fd = fd; 196 196 197 197 mutex_lock(&group->fanotify_data.access_mutex); 198 + 199 + if (group->fanotify_data.bypass_perm) { 200 + mutex_unlock(&group->fanotify_data.access_mutex); 201 + kmem_cache_free(fanotify_response_event_cache, re); 202 + event->response = FAN_ALLOW; 203 + return 0; 204 + } 205 + 198 206 list_add_tail(&re->list, &group->fanotify_data.access_list); 199 207 mutex_unlock(&group->fanotify_data.access_mutex); 200 208 ··· 372 364 static int fanotify_release(struct inode *ignored, struct file *file) 373 365 { 374 366 struct fsnotify_group *group = file->private_data; 367 + struct fanotify_response_event *re, *lre; 375 368 376 369 pr_debug("%s: file=%p group=%p\n", __func__, file, group); 377 370 371 + #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS 372 + mutex_lock(&group->fanotify_data.access_mutex); 373 + 374 + group->fanotify_data.bypass_perm = true; 375 + 376 + list_for_each_entry_safe(re, lre, &group->fanotify_data.access_list, list) { 377 + pr_debug("%s: found group=%p re=%p event=%p\n", __func__, group, 378 + re, re->event); 379 + 380 + list_del_init(&re->list); 381 + re->event->response = FAN_ALLOW; 382 + 383 + kmem_cache_free(fanotify_response_event_cache, re); 384 + } 385 + mutex_unlock(&group->fanotify_data.access_mutex); 386 + 387 + wake_up(&group->fanotify_data.access_waitq); 388 + #endif 378 389 /* matches the fanotify_init->fsnotify_alloc_group */ 379 390 fsnotify_put_group(group); 380 391 ··· 641 614 __func__, flags, event_f_flags); 642 615 643 616 if (!capable(CAP_SYS_ADMIN)) 644 - return -EACCES; 617 + return -EPERM; 645 618 646 619 if (flags & ~FAN_ALL_INIT_FLAGS) 647 620 return -EINVAL;
+36 -32
fs/notify/fsnotify.c
··· 148 148 const unsigned char *file_name, 149 149 struct fsnotify_event **event) 150 150 { 151 - struct fsnotify_group *group = inode_mark->group; 152 - __u32 inode_test_mask = (mask & ~FS_EVENT_ON_CHILD); 153 - __u32 vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD); 151 + struct fsnotify_group *group = NULL; 152 + __u32 inode_test_mask = 0; 153 + __u32 vfsmount_test_mask = 0; 154 154 155 - pr_debug("%s: group=%p to_tell=%p mnt=%p mark=%p mask=%x data=%p" 156 - " data_is=%d cookie=%d event=%p\n", __func__, group, to_tell, 157 - mnt, inode_mark, mask, data, data_is, cookie, *event); 155 + if (unlikely(!inode_mark && !vfsmount_mark)) { 156 + BUG(); 157 + return 0; 158 + } 158 159 159 160 /* clear ignored on inode modification */ 160 161 if (mask & FS_MODIFY) { ··· 169 168 170 169 /* does the inode mark tell us to do something? */ 171 170 if (inode_mark) { 171 + group = inode_mark->group; 172 + inode_test_mask = (mask & ~FS_EVENT_ON_CHILD); 172 173 inode_test_mask &= inode_mark->mask; 173 174 inode_test_mask &= ~inode_mark->ignored_mask; 174 175 } 175 176 176 177 /* does the vfsmount_mark tell us to do something? */ 177 178 if (vfsmount_mark) { 179 + vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD); 180 + group = vfsmount_mark->group; 178 181 vfsmount_test_mask &= vfsmount_mark->mask; 179 182 vfsmount_test_mask &= ~vfsmount_mark->ignored_mask; 180 183 if (inode_mark) 181 184 vfsmount_test_mask &= ~inode_mark->ignored_mask; 182 185 } 186 + 187 + pr_debug("%s: group=%p to_tell=%p mnt=%p mask=%x inode_mark=%p" 188 + " inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x" 189 + " data=%p data_is=%d cookie=%d event=%p\n", 190 + __func__, group, to_tell, mnt, mask, inode_mark, 191 + inode_test_mask, vfsmount_mark, vfsmount_test_mask, data, 192 + data_is, cookie, *event); 183 193 184 194 if (!inode_test_mask && !vfsmount_test_mask) 185 195 return 0; ··· 219 207 int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, 220 208 const unsigned char *file_name, u32 cookie) 221 209 { 222 - struct hlist_node *inode_node, *vfsmount_node; 210 + struct hlist_node *inode_node = NULL, *vfsmount_node = NULL; 223 211 struct fsnotify_mark *inode_mark = NULL, *vfsmount_mark = NULL; 224 212 struct fsnotify_group *inode_group, *vfsmount_group; 225 213 struct fsnotify_event *event = NULL; 226 214 struct vfsmount *mnt; 227 215 int idx, ret = 0; 228 - bool used_inode = false, used_vfsmount = false; 229 216 /* global tests shouldn't care about events on child only the specific event */ 230 217 __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); 231 218 ··· 249 238 (test_mask & to_tell->i_fsnotify_mask)) 250 239 inode_node = srcu_dereference(to_tell->i_fsnotify_marks.first, 251 240 &fsnotify_mark_srcu); 252 - else 253 - inode_node = NULL; 254 241 255 - if (mnt) { 256 - if ((mask & FS_MODIFY) || 257 - (test_mask & mnt->mnt_fsnotify_mask)) 258 - vfsmount_node = srcu_dereference(mnt->mnt_fsnotify_marks.first, 259 - &fsnotify_mark_srcu); 260 - else 261 - vfsmount_node = NULL; 262 - } else { 263 - mnt = NULL; 264 - vfsmount_node = NULL; 242 + if (mnt && ((mask & FS_MODIFY) || 243 + (test_mask & mnt->mnt_fsnotify_mask))) { 244 + vfsmount_node = srcu_dereference(mnt->mnt_fsnotify_marks.first, 245 + &fsnotify_mark_srcu); 246 + inode_node = srcu_dereference(to_tell->i_fsnotify_marks.first, 247 + &fsnotify_mark_srcu); 265 248 } 266 249 267 250 while (inode_node || vfsmount_node) { 251 + inode_group = vfsmount_group = NULL; 252 + 268 253 if (inode_node) { 269 254 inode_mark = hlist_entry(srcu_dereference(inode_node, &fsnotify_mark_srcu), 270 255 struct fsnotify_mark, i.i_list); 271 256 inode_group = inode_mark->group; 272 - } else 273 - inode_group = (void *)-1; 257 + } 274 258 275 259 if (vfsmount_node) { 276 260 vfsmount_mark = hlist_entry(srcu_dereference(vfsmount_node, &fsnotify_mark_srcu), 277 261 struct fsnotify_mark, m.m_list); 278 262 vfsmount_group = vfsmount_mark->group; 279 - } else 280 - vfsmount_group = (void *)-1; 263 + } 281 264 282 - if (inode_group < vfsmount_group) { 265 + if (inode_group > vfsmount_group) { 283 266 /* handle inode */ 284 267 send_to_group(to_tell, NULL, inode_mark, NULL, mask, data, 285 268 data_is, cookie, file_name, &event); 286 - used_inode = true; 287 - } else if (vfsmount_group < inode_group) { 269 + /* we didn't use the vfsmount_mark */ 270 + vfsmount_group = NULL; 271 + } else if (vfsmount_group > inode_group) { 288 272 send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data, 289 273 data_is, cookie, file_name, &event); 290 - used_vfsmount = true; 274 + inode_group = NULL; 291 275 } else { 292 276 send_to_group(to_tell, mnt, inode_mark, vfsmount_mark, 293 277 mask, data, data_is, cookie, file_name, 294 278 &event); 295 - used_vfsmount = true; 296 - used_inode = true; 297 279 } 298 280 299 - if (used_inode) 281 + if (inode_group) 300 282 inode_node = srcu_dereference(inode_node->next, 301 283 &fsnotify_mark_srcu); 302 - if (used_vfsmount) 284 + if (vfsmount_group) 303 285 vfsmount_node = srcu_dereference(vfsmount_node->next, 304 286 &fsnotify_mark_srcu); 305 287 }
+3 -10
include/linux/fanotify.h
··· 65 65 FAN_ALL_PERM_EVENTS |\ 66 66 FAN_Q_OVERFLOW) 67 67 68 - #define FANOTIFY_METADATA_VERSION 1 68 + #define FANOTIFY_METADATA_VERSION 2 69 69 70 70 struct fanotify_event_metadata { 71 71 __u32 event_len; 72 72 __u32 vers; 73 - __s32 fd; 74 73 __u64 mask; 75 - __s64 pid; 74 + __s32 fd; 75 + __s32 pid; 76 76 } __attribute__ ((packed)); 77 77 78 78 struct fanotify_response { ··· 95 95 (long)(meta)->event_len >= (long)FAN_EVENT_METADATA_LEN && \ 96 96 (long)(meta)->event_len <= (long)(len)) 97 97 98 - #ifdef __KERNEL__ 99 - 100 - struct fanotify_wait { 101 - struct fsnotify_event *event; 102 - __s32 fd; 103 - }; 104 - #endif /* __KERNEL__ */ 105 98 #endif /* _LINUX_FANOTIFY_H */
+1
include/linux/fsnotify_backend.h
··· 156 156 struct mutex access_mutex; 157 157 struct list_head access_list; 158 158 wait_queue_head_t access_waitq; 159 + bool bypass_perm; /* protected by access_mutex */ 159 160 #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */ 160 161 int f_flags; 161 162 } fanotify_data;