forked from mirrors/linux
		
	netlink: introduce NLA_POLICY_MAX_BE
netlink allows to specify allowed ranges for integer types. Unfortunately, nfnetlink passes integers in big endian, so the existing NLA_POLICY_MAX() cannot be used. At the moment, nfnetlink users, such as nf_tables, need to resort to programmatic checking via helpers such as nft_parse_u32_check(). This is both cumbersome and error prone. This adds NLA_POLICY_MAX_BE which adds range check support for BE16, BE32 and BE64 integers. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									98ba81081b
								
							
						
					
					
						commit
						08724ef699
					
				
					 2 changed files with 36 additions and 4 deletions
				
			
		|  | @ -325,6 +325,7 @@ struct nla_policy { | ||||||
| 		struct netlink_range_validation_signed *range_signed; | 		struct netlink_range_validation_signed *range_signed; | ||||||
| 		struct { | 		struct { | ||||||
| 			s16 min, max; | 			s16 min, max; | ||||||
|  | 			u8 network_byte_order:1; | ||||||
| 		}; | 		}; | ||||||
| 		int (*validate)(const struct nlattr *attr, | 		int (*validate)(const struct nlattr *attr, | ||||||
| 				struct netlink_ext_ack *extack); | 				struct netlink_ext_ack *extack); | ||||||
|  | @ -418,6 +419,14 @@ struct nla_policy { | ||||||
| 	.type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp),	\ | 	.type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp),	\ | ||||||
| 	.validation_type = NLA_VALIDATE_MAX,		\ | 	.validation_type = NLA_VALIDATE_MAX,		\ | ||||||
| 	.max = _max,					\ | 	.max = _max,					\ | ||||||
|  | 	.network_byte_order = 0,			\ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define NLA_POLICY_MAX_BE(tp, _max) {			\ | ||||||
|  | 	.type = NLA_ENSURE_UINT_TYPE(tp),		\ | ||||||
|  | 	.validation_type = NLA_VALIDATE_MAX,		\ | ||||||
|  | 	.max = _max,					\ | ||||||
|  | 	.network_byte_order = 1,			\ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define NLA_POLICY_MASK(tp, _mask) {			\ | #define NLA_POLICY_MASK(tp, _mask) {			\ | ||||||
|  |  | ||||||
							
								
								
									
										31
									
								
								lib/nlattr.c
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								lib/nlattr.c
									
									
									
									
									
								
							|  | @ -159,6 +159,31 @@ void nla_get_range_unsigned(const struct nla_policy *pt, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static u64 nla_get_attr_bo(const struct nla_policy *pt, | ||||||
|  | 			   const struct nlattr *nla) | ||||||
|  | { | ||||||
|  | 	switch (pt->type) { | ||||||
|  | 	case NLA_U16: | ||||||
|  | 		if (pt->network_byte_order) | ||||||
|  | 			return ntohs(nla_get_be16(nla)); | ||||||
|  | 
 | ||||||
|  | 		return nla_get_u16(nla); | ||||||
|  | 	case NLA_U32: | ||||||
|  | 		if (pt->network_byte_order) | ||||||
|  | 			return ntohl(nla_get_be32(nla)); | ||||||
|  | 
 | ||||||
|  | 		return nla_get_u32(nla); | ||||||
|  | 	case NLA_U64: | ||||||
|  | 		if (pt->network_byte_order) | ||||||
|  | 			return be64_to_cpu(nla_get_be64(nla)); | ||||||
|  | 
 | ||||||
|  | 		return nla_get_u64(nla); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	WARN_ON_ONCE(1); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int nla_validate_range_unsigned(const struct nla_policy *pt, | static int nla_validate_range_unsigned(const struct nla_policy *pt, | ||||||
| 				       const struct nlattr *nla, | 				       const struct nlattr *nla, | ||||||
| 				       struct netlink_ext_ack *extack, | 				       struct netlink_ext_ack *extack, | ||||||
|  | @ -172,12 +197,10 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt, | ||||||
| 		value = nla_get_u8(nla); | 		value = nla_get_u8(nla); | ||||||
| 		break; | 		break; | ||||||
| 	case NLA_U16: | 	case NLA_U16: | ||||||
| 		value = nla_get_u16(nla); |  | ||||||
| 		break; |  | ||||||
| 	case NLA_U32: | 	case NLA_U32: | ||||||
| 		value = nla_get_u32(nla); |  | ||||||
| 		break; |  | ||||||
| 	case NLA_U64: | 	case NLA_U64: | ||||||
|  | 		value = nla_get_attr_bo(pt, nla); | ||||||
|  | 		break; | ||||||
| 	case NLA_MSECS: | 	case NLA_MSECS: | ||||||
| 		value = nla_get_u64(nla); | 		value = nla_get_u64(nla); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Florian Westphal
						Florian Westphal