Commit fbde105f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull bpf fixes from Alexei Starovoitov:

 - Finish constification of 1st parameter of bpf_d_path() (Rong Tao)

 - Harden userspace-supplied xdp_desc validation (Alexander Lobakin)

 - Fix metadata_dst leak in __bpf_redirect_neigh_v{4,6}() (Daniel
   Borkmann)

 - Fix undefined behavior in {get,put}_unaligned_be32() (Eric Biggers)

 - Use correct context to unpin bpf hash map with special types (KaFai
   Wan)

* tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
  selftests/bpf: Add test for unpinning htab with internal timer struct
  bpf: Avoid RCU context warning when unpinning htab with internal structs
  xsk: Harden userspace-supplied xdp_desc validation
  bpf: Fix metadata_dst leak __bpf_redirect_neigh_v{4,6}
  libbpf: Fix undefined behavior in {get,put}_unaligned_be32()
  bpf: Finish constification of 1st parameter of bpf_d_path()
parents ae13bd23 ffce84bc
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4891,7 +4891,7 @@ union bpf_attr {
 *
 *		**-ENOENT** if the bpf_local_storage cannot be found.
 *
 * long bpf_d_path(struct path *path, char *buf, u32 sz)
 * long bpf_d_path(const struct path *path, char *buf, u32 sz)
 *	Description
 *		Return full path for given **struct path** object, which
 *		needs to be the kernel BTF *path* object. The path is
+2 −2
Original line number Diff line number Diff line
@@ -775,7 +775,7 @@ static int bpf_show_options(struct seq_file *m, struct dentry *root)
	return 0;
}

static void bpf_free_inode(struct inode *inode)
static void bpf_destroy_inode(struct inode *inode)
{
	enum bpf_type type;

@@ -790,7 +790,7 @@ const struct super_operations bpf_super_ops = {
	.statfs		= simple_statfs,
	.drop_inode	= inode_just_drop,
	.show_options	= bpf_show_options,
	.free_inode	= bpf_free_inode,
	.destroy_inode	= bpf_destroy_inode,
};

enum {
+2 −0
Original line number Diff line number Diff line
@@ -2281,6 +2281,7 @@ static int __bpf_redirect_neigh_v6(struct sk_buff *skb, struct net_device *dev,
		if (IS_ERR(dst))
			goto out_drop;

		skb_dst_drop(skb);
		skb_dst_set(skb, dst);
	} else if (nh->nh_family != AF_INET6) {
		goto out_drop;
@@ -2389,6 +2390,7 @@ static int __bpf_redirect_neigh_v4(struct sk_buff *skb, struct net_device *dev,
			goto out_drop;
		}

		skb_dst_drop(skb);
		skb_dst_set(skb, &rt->dst);
	}

+35 −10
Original line number Diff line number Diff line
@@ -143,14 +143,24 @@ static inline bool xp_unused_options_set(u32 options)
static inline bool xp_aligned_validate_desc(struct xsk_buff_pool *pool,
					    struct xdp_desc *desc)
{
	u64 addr = desc->addr - pool->tx_metadata_len;
	u64 len = desc->len + pool->tx_metadata_len;
	u64 offset = addr & (pool->chunk_size - 1);
	u64 len = desc->len;
	u64 addr, offset;

	if (!desc->len)
	if (!len)
		return false;

	if (offset + len > pool->chunk_size)
	/* Can overflow if desc->addr < pool->tx_metadata_len */
	if (check_sub_overflow(desc->addr, pool->tx_metadata_len, &addr))
		return false;

	offset = addr & (pool->chunk_size - 1);

	/*
	 * Can't overflow: @offset is guaranteed to be < ``U32_MAX``
	 * (pool->chunk_size is ``u32``), @len is guaranteed
	 * to be <= ``U32_MAX``.
	 */
	if (offset + len + pool->tx_metadata_len > pool->chunk_size)
		return false;

	if (addr >= pool->addrs_cnt)
@@ -158,27 +168,42 @@ static inline bool xp_aligned_validate_desc(struct xsk_buff_pool *pool,

	if (xp_unused_options_set(desc->options))
		return false;

	return true;
}

static inline bool xp_unaligned_validate_desc(struct xsk_buff_pool *pool,
					      struct xdp_desc *desc)
{
	u64 addr = xp_unaligned_add_offset_to_addr(desc->addr) - pool->tx_metadata_len;
	u64 len = desc->len + pool->tx_metadata_len;
	u64 len = desc->len;
	u64 addr, end;

	if (!desc->len)
	if (!len)
		return false;

	/* Can't overflow: @len is guaranteed to be <= ``U32_MAX`` */
	len += pool->tx_metadata_len;
	if (len > pool->chunk_size)
		return false;

	if (addr >= pool->addrs_cnt || addr + len > pool->addrs_cnt ||
	    xp_desc_crosses_non_contig_pg(pool, addr, len))
	/* Can overflow if desc->addr is close to 0 */
	if (check_sub_overflow(xp_unaligned_add_offset_to_addr(desc->addr),
			       pool->tx_metadata_len, &addr))
		return false;

	if (addr >= pool->addrs_cnt)
		return false;

	/* Can overflow if pool->addrs_cnt is high enough */
	if (check_add_overflow(addr, len, &end) || end > pool->addrs_cnt)
		return false;

	if (xp_desc_crosses_non_contig_pg(pool, addr, len))
		return false;

	if (xp_unused_options_set(desc->options))
		return false;

	return true;
}

+1 −0
Original line number Diff line number Diff line
@@ -788,6 +788,7 @@ class PrinterHelpersHeader(Printer):
            'struct task_struct',
            'struct cgroup',
            'struct path',
            'const struct path',
            'struct btf_ptr',
            'struct inode',
            'struct socket',
Loading