• Jamal Hadi Salim's avatar
    net: sched: cls_u32: Fix match key mis-addressing · e68409db
    Jamal Hadi Salim authored
    A match entry is uniquely identified with an "address" or "path" in the
    form of: hashtable ID(12b):bucketid(8b):nodeid(12b).
    
    When creating table match entries all of hash table id, bucket id and
    node (match entry id) are needed to be either specified by the user or
    reasonable in-kernel defaults are used. The in-kernel default for a table id is
    0x800(omnipresent root table); for bucketid it is 0x0. Prior to this fix there
    was none for a nodeid i.e. the code assumed that the user passed the correct
    nodeid and if the user passes a nodeid of 0 (as Mingi Cho did) then that is what
    was used. But nodeid of 0 is reserved for identifying the table. This is not
    a problem until we dump. The dump code notices that the nodeid is zero and
    assumes it is referencing a table and therefore references table struct
    tc_u_hnode instead of what was created i.e match entry struct tc_u_knode.
    
    Ming does an equivalent of:
    tc filter add dev dummy0 parent 10: prio 1 handle 0x1000 \
    protocol ip u32 match ip src 10.0.0.1/32 classid 10:1 action ok
    
    Essentially specifying a table id 0, bucketid 1 and nodeid of zero
    Tableid 0 is remapped to the default of 0x800.
    Bucketid 1 is ignored and defaults to 0x00.
    Nodeid was assumed to be what Ming passed - 0x000
    
    dumping before fix shows:
    ~$ tc filter ls dev dummy0 parent 10:
    filter protocol ip pref 1 u32 chain 0
    filter protocol ip pref 1 u32 chain 0 fh 800: ht divisor 1
    filter protocol ip pref 1 u32 chain 0 fh 800: ht divisor -30591
    
    Note that the last line reports a table instead of a match entry
    (you can tell this because it says "ht divisor...").
    As a result of reporting the wrong data type (misinterpretting of struct
    tc_u_knode as being struct tc_u_hnode) the divisor is reported with value
    of -30591. Ming identified this as part of the heap address
    (physmap_base is 0xffff8880 (-30591 - 1)).
    
    The fix is to ensure that when table entry matches are added and no
    nodeid is specified (i.e nodeid == 0) then we get the next available
    nodeid from the table's pool.
    
    After the fix, this is what the dump shows:
    $ tc filter ls dev dummy0 parent 10:
    filter protocol ip pref 1 u32 chain 0
    filter protocol ip pref 1 u32 chain 0 fh 800: ht divisor 1
    filter protocol ip pref 1 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 10:1 not_in_hw
      match 0a000001/ffffffff at 12
    	action order 1: gact action pass
    	 random type none pass val 0
    	 index 1 ref 1 bind 1
    Reported-by: default avatarMingi Cho <mgcho.minic@gmail.com>
    Fixes: 1da177e4 ("Linux-2.6.12-rc2")
    Signed-off-by: default avatarJamal Hadi Salim <jhs@mojatatu.com>
    Link: https://lore.kernel.org/r/20230726135151.416917-1-jhs@mojatatu.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
    e68409db
cls_u32.c 36 KB