@@ -2382,15 +2382,38 @@ static HYMO_NOCFI int hymo_krp_vfs_getxattr_entry(struct kretprobe_instance *ri,
23822382 if (!entry || !entry -> src )
23832383 return 0 ;
23842384
2385- /* Resolve source path (bypass redirect) and get its actual SELinux context */
2385+ /* Resolve source path (bypass redirect) and get its actual SELinux context.
2386+ * When source file doesn't exist (e.g. overlay dir is empty), try parent
2387+ * directories until we find one with a valid context (e.g. /system/product/overlay). */
23862388 atomic_long_set (& hymo_xattr_source_tgid , (long )task_tgid_vnr (current ));
2387- if (hymo_kern_path && hymo_kern_path (entry -> src , LOOKUP_FOLLOW , & src_path ) == 0 ) {
2388- ret = hymo_get_selinux_ctx_from_path (& src_path , d -> src_ctx , HYMO_SELINUX_CTX_MAX );
2389- path_put (& src_path );
2390- if (ret > 0 && (size_t )ret < HYMO_SELINUX_CTX_MAX ) {
2391- d -> src_ctx_len = (size_t )ret ;
2392- d -> src_ctx [d -> src_ctx_len ] = '\0' ;
2393- d -> spoof_selinux = true;
2389+ if (hymo_kern_path ) {
2390+ char parent [256 ];
2391+ const char * try_path = entry -> src ;
2392+ size_t len = strlen (entry -> src );
2393+
2394+ while (try_path && len > 1 ) {
2395+ if (hymo_kern_path (try_path , LOOKUP_FOLLOW , & src_path ) == 0 ) {
2396+ ret = hymo_get_selinux_ctx_from_path (& src_path , d -> src_ctx , HYMO_SELINUX_CTX_MAX );
2397+ path_put (& src_path );
2398+ if (ret > 0 && (size_t )ret < HYMO_SELINUX_CTX_MAX ) {
2399+ d -> src_ctx_len = (size_t )ret ;
2400+ d -> src_ctx [d -> src_ctx_len ] = '\0' ;
2401+ d -> spoof_selinux = true;
2402+ break ;
2403+ }
2404+ }
2405+ /* Try parent directory: strip last component */
2406+ if (len >= sizeof (parent ))
2407+ break ;
2408+ memcpy (parent , try_path , len + 1 );
2409+ {
2410+ char * slash = strrchr (parent , '/' );
2411+ if (!slash || slash == parent )
2412+ break ;
2413+ * slash = '\0' ;
2414+ try_path = parent ;
2415+ len = slash - parent ;
2416+ }
23942417 }
23952418 }
23962419 atomic_long_set (& hymo_xattr_source_tgid , 0 );
0 commit comments