Ensuring data from netlink is within the bounds

While implementing the expression modules, a known bug raised and I was asked to fix it in the current modules I’m implementing and others modules like nft_exthdr.

http://marc.info/?l=netfilter-devel&m=147076838413500&w=2

The problem comes due to the netlink attributes are sent in U32 format, and sometimes, the private data in the kernel an U8 value will be enough. But it’s usual to assign directly the netlink value to the private attribute without checking if it’s bigger than U8.

For this reason, a piece of code like:

priv->offset = ntohl(nla_get_be32(tb[NFTA_EXTHDR_OFFSET]));
priv->len    = ntohl(nla_get_be32(tb[NFTA_EXTHDR_LEN]));

where

struct nft_exthdr {
    u8                      type;
    u8                      offset;
    u8                      len;
    enum nft_registers      dreg:8;
};

Produces an overflow. So we’ve to ensure the value loaded with something like:

u32 offset, len;


offset = ntohl(nla_get_be32(tb[NFTA_EXTHDR_OFFSET]));
len    = ntohl(nla_get_be32(tb[NFTA_EXTHDR_LEN]));

if (offset > U8_MAX || len > U8_MAX)
	return -EINVAL;

priv->offset = offset;
priv->len = len;

Fixes for other cases where found and patched.

http://marc.info/?l=netfilter-devel&m=147152076602019&w=2

Advertisements

Brand new hash expression

The new hash expression provides a way to generate a Jenkins Hash operation given a source register that could be a source IP address, destination IP address, or any other packet field.

meta mark set hash ip saddr mod 10

There was a module called nft_hash that implements a hash table, so I’ve to apply a patch to rename such module to another. This is the patch.

I had to learn the Jenkins Hash API in order to use it as described here:

http://lxr.free-electrons.com/source/include/linux/jhash.h

And make the changes in the libnftnl package to support this new expression in the form:

reg1 <- payload(base, offset, len)
reg1 <- hash(reg1, len, mod)
mark set reg1

But after the implementation in the kernel and libnftnl sides, I get the following error:

 root@nfkernel:~# /usr/src/libnftnl/examples/nft-rule-add ip filter
 input
 mnl_cb_run: No such file or directory

This error could be shown if the given table or chain doesn’t exist, or if the module is not loaded. But….

The nft structure was created

 root@nfkernel:~# nft list ruleset
 table ip filter {
         chain input {
                 type filter hook input priority 0; policy accept;
         }
 (...)
 }

And the module was loaded

 Module                  Size  Used by
 nft_hash                9946  0
 nf_tables_ipv6          2206  4
 nf_tables_ipv4          2206  4
 nf_tables              56474  3 nf_tables_ipv4,nf_tables_ipv6,nft_hash
 nfnetlink               5700  1 nf_tables

But then I realized that the nft_hash module size in memory is too big for such relatively “small” expression.

Then, I came into the idea that some kind of incompatibility or collision in the kernel between the “old” and the “new” nft_hash module must exist.

Finally, and thanks to my mentor Pablo Neira, I must include the following line in the source code.

 MODULE_ALIAS_NFT_EXPR("hash");

Then,

make clean
make
make modules_install

And it’s ready!

Here is the first patch for the kernel and libnftnl:

http://marc.info/?l=netfilter-devel&m=147075140407812&w=2

http://marc.info/?l=netfilter-devel&m=147075143907821&w=2