@@ -1252,13 +1252,10 @@ static void xfrm_hash_rebuild(struct work_struct *work)
12521252{
12531253 struct net * net = container_of (work , struct net ,
12541254 xfrm .policy_hthresh .work );
1255- unsigned int hmask ;
12561255 struct xfrm_policy * pol ;
12571256 struct xfrm_policy * policy ;
12581257 struct hlist_head * chain ;
1259- struct hlist_head * odst ;
12601258 struct hlist_node * newpos ;
1261- int i ;
12621259 int dir ;
12631260 unsigned seq ;
12641261 u8 lbits4 , rbits4 , lbits6 , rbits6 ;
@@ -1322,23 +1319,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
13221319 goto out_unlock ;
13231320 }
13241321
1325- /* reset the bydst and inexact table in all directions */
13261322 for (dir = 0 ; dir < XFRM_POLICY_MAX ; dir ++ ) {
1327- struct hlist_node * n ;
1328-
1329- hlist_for_each_entry_safe (policy , n ,
1330- & net -> xfrm .policy_inexact [dir ],
1331- bydst_inexact_list ) {
1332- hlist_del_rcu (& policy -> bydst );
1333- hlist_del_init (& policy -> bydst_inexact_list );
1334- }
1335-
1336- hmask = net -> xfrm .policy_bydst [dir ].hmask ;
1337- odst = net -> xfrm .policy_bydst [dir ].table ;
1338- for (i = hmask ; i >= 0 ; i -- ) {
1339- hlist_for_each_entry_safe (policy , n , odst + i , bydst )
1340- hlist_del_rcu (& policy -> bydst );
1341- }
13421323 if ((dir & XFRM_POLICY_MASK ) == XFRM_POLICY_OUT ) {
13431324 /* dir out => dst = remote, src = local */
13441325 net -> xfrm .policy_bydst [dir ].dbits4 = rbits4 ;
@@ -1363,6 +1344,10 @@ static void xfrm_hash_rebuild(struct work_struct *work)
13631344 /* skip socket policies */
13641345 continue ;
13651346 }
1347+
1348+ hlist_del_rcu (& policy -> bydst );
1349+ hlist_del_init (& policy -> bydst_inexact_list );
1350+
13661351 newpos = NULL ;
13671352 chain = policy_hash_bysel (net , & policy -> selector ,
13681353 policy -> family , dir );
@@ -4484,63 +4469,50 @@ EXPORT_SYMBOL_GPL(xfrm_audit_policy_delete);
44844469#endif
44854470
44864471#ifdef CONFIG_XFRM_MIGRATE
4487- static bool xfrm_migrate_selector_match (const struct xfrm_selector * sel_cmp ,
4488- const struct xfrm_selector * sel_tgt )
4489- {
4490- if (sel_cmp -> proto == IPSEC_ULPROTO_ANY ) {
4491- if (sel_tgt -> family == sel_cmp -> family &&
4492- xfrm_addr_equal (& sel_tgt -> daddr , & sel_cmp -> daddr ,
4493- sel_cmp -> family ) &&
4494- xfrm_addr_equal (& sel_tgt -> saddr , & sel_cmp -> saddr ,
4495- sel_cmp -> family ) &&
4496- sel_tgt -> prefixlen_d == sel_cmp -> prefixlen_d &&
4497- sel_tgt -> prefixlen_s == sel_cmp -> prefixlen_s ) {
4498- return true;
4499- }
4500- } else {
4501- if (memcmp (sel_tgt , sel_cmp , sizeof (* sel_tgt )) == 0 ) {
4502- return true;
4503- }
4504- }
4505- return false;
4506- }
4507-
45084472static struct xfrm_policy * xfrm_migrate_policy_find (const struct xfrm_selector * sel ,
45094473 u8 dir , u8 type , struct net * net , u32 if_id )
45104474{
45114475 struct xfrm_policy * pol , * ret = NULL ;
4512- struct hlist_head * chain ;
4513- u32 priority = ~0U ;
4476+ struct flowi fl ;
45144477
4515- spin_lock_bh (& net -> xfrm .xfrm_policy_lock );
4516- chain = policy_hash_direct (net , & sel -> daddr , & sel -> saddr , sel -> family , dir );
4517- hlist_for_each_entry (pol , chain , bydst ) {
4518- if ((if_id == 0 || pol -> if_id == if_id ) &&
4519- xfrm_migrate_selector_match (sel , & pol -> selector ) &&
4520- pol -> type == type ) {
4521- ret = pol ;
4522- priority = ret -> priority ;
4523- break ;
4524- }
4525- }
4526- chain = & net -> xfrm .policy_inexact [dir ];
4527- hlist_for_each_entry (pol , chain , bydst_inexact_list ) {
4528- if ((pol -> priority >= priority ) && ret )
4529- break ;
4478+ memset (& fl , 0 , sizeof (fl ));
45304479
4531- if ((if_id == 0 || pol -> if_id == if_id ) &&
4532- xfrm_migrate_selector_match (sel , & pol -> selector ) &&
4533- pol -> type == type ) {
4534- ret = pol ;
4480+ fl .flowi_proto = sel -> proto ;
4481+
4482+ switch (sel -> family ) {
4483+ case AF_INET :
4484+ fl .u .ip4 .saddr = sel -> saddr .a4 ;
4485+ fl .u .ip4 .daddr = sel -> daddr .a4 ;
4486+ if (sel -> proto == IPSEC_ULPROTO_ANY )
45354487 break ;
4536- }
4488+ fl .u .flowi4_oif = sel -> ifindex ;
4489+ fl .u .ip4 .fl4_sport = sel -> sport ;
4490+ fl .u .ip4 .fl4_dport = sel -> dport ;
4491+ break ;
4492+ case AF_INET6 :
4493+ fl .u .ip6 .saddr = sel -> saddr .in6 ;
4494+ fl .u .ip6 .daddr = sel -> daddr .in6 ;
4495+ if (sel -> proto == IPSEC_ULPROTO_ANY )
4496+ break ;
4497+ fl .u .flowi6_oif = sel -> ifindex ;
4498+ fl .u .ip6 .fl4_sport = sel -> sport ;
4499+ fl .u .ip6 .fl4_dport = sel -> dport ;
4500+ break ;
4501+ default :
4502+ return ERR_PTR (- EAFNOSUPPORT );
45374503 }
45384504
4539- xfrm_pol_hold ( ret );
4505+ rcu_read_lock ( );
45404506
4541- spin_unlock_bh (& net -> xfrm .xfrm_policy_lock );
4507+ pol = xfrm_policy_lookup_bytype (net , type , & fl , sel -> family , dir , if_id );
4508+ if (IS_ERR_OR_NULL (pol ))
4509+ goto out_unlock ;
45424510
4543- return ret ;
4511+ if (!xfrm_pol_hold_rcu (ret ))
4512+ pol = NULL ;
4513+ out_unlock :
4514+ rcu_read_unlock ();
4515+ return pol ;
45444516}
45454517
45464518static int migrate_tmpl_match (const struct xfrm_migrate * m , const struct xfrm_tmpl * t )
@@ -4677,9 +4649,9 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
46774649
46784650 /* Stage 1 - find policy */
46794651 pol = xfrm_migrate_policy_find (sel , dir , type , net , if_id );
4680- if (! pol ) {
4652+ if (IS_ERR_OR_NULL ( pol ) ) {
46814653 NL_SET_ERR_MSG (extack , "Target policy not found" );
4682- err = - ENOENT ;
4654+ err = IS_ERR ( pol ) ? PTR_ERR ( pol ) : - ENOENT ;
46834655 goto out ;
46844656 }
46854657
0 commit comments