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 tag 'fsnotify_for_v5.1-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull fsnotify fix from Jan Kara:
"A fix of user trigerable NULL pointer dereference syzbot has recently
spotted.

The problem was introduced in this merge window so no CC stable is
needed"

* tag 'fsnotify_for_v5.1-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
fsnotify: Fix NULL ptr deref in fanotify_get_fsid()

+18 -8
+12 -2
fs/notify/fanotify/fanotify.c
··· 346 346 __kernel_fsid_t fsid = {}; 347 347 348 348 fsnotify_foreach_obj_type(type) { 349 + struct fsnotify_mark_connector *conn; 350 + 349 351 if (!fsnotify_iter_should_report_type(iter_info, type)) 350 352 continue; 351 353 352 - fsid = iter_info->marks[type]->connector->fsid; 354 + conn = READ_ONCE(iter_info->marks[type]->connector); 355 + /* Mark is just getting destroyed or created? */ 356 + if (!conn) 357 + continue; 358 + fsid = conn->fsid; 353 359 if (WARN_ON_ONCE(!fsid.val[0] && !fsid.val[1])) 354 360 continue; 355 361 return fsid; ··· 414 408 return 0; 415 409 } 416 410 417 - if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) 411 + if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { 418 412 fsid = fanotify_get_fsid(iter_info); 413 + /* Racing with mark destruction or creation? */ 414 + if (!fsid.val[0] && !fsid.val[1]) 415 + return 0; 416 + } 419 417 420 418 event = fanotify_alloc_event(group, inode, mask, data, data_type, 421 419 &fsid);
+6 -6
fs/notify/mark.c
··· 239 239 240 240 void fsnotify_put_mark(struct fsnotify_mark *mark) 241 241 { 242 - struct fsnotify_mark_connector *conn; 242 + struct fsnotify_mark_connector *conn = READ_ONCE(mark->connector); 243 243 void *objp = NULL; 244 244 unsigned int type = FSNOTIFY_OBJ_TYPE_DETACHED; 245 245 bool free_conn = false; 246 246 247 247 /* Catch marks that were actually never attached to object */ 248 - if (!mark->connector) { 248 + if (!conn) { 249 249 if (refcount_dec_and_test(&mark->refcnt)) 250 250 fsnotify_final_mark_destroy(mark); 251 251 return; ··· 255 255 * We have to be careful so that traversals of obj_list under lock can 256 256 * safely grab mark reference. 257 257 */ 258 - if (!refcount_dec_and_lock(&mark->refcnt, &mark->connector->lock)) 258 + if (!refcount_dec_and_lock(&mark->refcnt, &conn->lock)) 259 259 return; 260 260 261 - conn = mark->connector; 262 261 hlist_del_init_rcu(&mark->obj_list); 263 262 if (hlist_empty(&conn->list)) { 264 263 objp = fsnotify_detach_connector_from_object(conn, &type); ··· 265 266 } else { 266 267 __fsnotify_recalc_mask(conn); 267 268 } 268 - mark->connector = NULL; 269 + WRITE_ONCE(mark->connector, NULL); 269 270 spin_unlock(&conn->lock); 270 271 271 272 fsnotify_drop_object(type, objp); ··· 619 620 /* mark should be the last entry. last is the current last entry */ 620 621 hlist_add_behind_rcu(&mark->obj_list, &last->obj_list); 621 622 added: 622 - mark->connector = conn; 623 + WRITE_ONCE(mark->connector, conn); 623 624 out_err: 624 625 spin_unlock(&conn->lock); 625 626 spin_unlock(&mark->lock); ··· 807 808 refcount_set(&mark->refcnt, 1); 808 809 fsnotify_get_group(group); 809 810 mark->group = group; 811 + WRITE_ONCE(mark->connector, NULL); 810 812 } 811 813 812 814 /*