Merge 5.15.87 into android14-5.15
Changes in 5.15.87
usb: dwc3: qcom: Fix memory leak in dwc3_qcom_interconnect_init
cifs: fix oops during encryption
Revert "selftests/bpf: Add test for unstable CT lookup API"
nvme-pci: fix doorbell buffer value endianness
nvme-pci: fix mempool alloc size
nvme-pci: fix page size checks
ACPI: resource: Skip IRQ override on Asus Vivobook K3402ZA/K3502ZA
ACPI: resource: do IRQ override on LENOVO IdeaPad
ACPI: resource: do IRQ override on XMG Core 15
ACPI: resource: do IRQ override on Lenovo 14ALC7
block, bfq: fix uaf for bfqq in bfq_exit_icq_bfqq
ata: ahci: Fix PCS quirk application for suspend
nvme: fix the NVME_CMD_EFFECTS_CSE_MASK definition
nvmet: don't defer passthrough commands with trivial effects to the workqueue
fs/ntfs3: Validate BOOT record_size
fs/ntfs3: Add overflow check for attribute size
fs/ntfs3: Validate data run offset
fs/ntfs3: Add null pointer check to attr_load_runs_vcn
fs/ntfs3: Fix memory leak on ntfs_fill_super() error path
fs/ntfs3: Add null pointer check for inode operations
fs/ntfs3: Validate attribute name offset
fs/ntfs3: Validate buffer length while parsing index
fs/ntfs3: Validate resident attribute name
fs/ntfs3: Fix slab-out-of-bounds read in run_unpack
soundwire: dmi-quirks: add quirk variant for LAPBC710 NUC15
fs/ntfs3: Validate index root when initialize NTFS security
fs/ntfs3: Use __GFP_NOWARN allocation at wnd_init()
fs/ntfs3: Use __GFP_NOWARN allocation at ntfs_fill_super()
fs/ntfs3: Delete duplicate condition in ntfs_read_mft()
fs/ntfs3: Fix slab-out-of-bounds in r_page
objtool: Fix SEGFAULT
powerpc/rtas: avoid device tree lookups in rtas_os_term()
powerpc/rtas: avoid scheduling in rtas_os_term()
HID: multitouch: fix Asus ExpertBook P2 P2451FA trackpoint
HID: plantronics: Additional PIDs for double volume key presses quirk
pstore: Properly assign mem_type property
pstore/zone: Use GFP_ATOMIC to allocate zone buffer
hfsplus: fix bug causing custom uid and gid being unable to be assigned with mount
binfmt: Fix error return code in load_elf_fdpic_binary()
ovl: Use ovl mounter's fsuid and fsgid in ovl_link()
ALSA: line6: correct midi status byte when receiving data from podxt
ALSA: line6: fix stack overflow in line6_midi_transmit
pnode: terminate at peers of source
mfd: mt6360: Add bounds checking in Regmap read/write call-backs
md: fix a crash in mempool_free
mm, compaction: fix fast_isolate_around() to stay within boundaries
f2fs: should put a page when checking the summary info
f2fs: allow to read node block after shutdown
mmc: vub300: fix warning - do not call blocking ops when !TASK_RUNNING
tpm: acpi: Call acpi_put_table() to fix memory leak
tpm: tpm_crb: Add the missed acpi_put_table() to fix memory leak
tpm: tpm_tis: Add the missed acpi_put_table() to fix memory leak
SUNRPC: Don't leak netobj memory when gss_read_proxy_verf() fails
kcsan: Instrument memcpy/memset/memmove with newer Clang
ASoC: Intel/SOF: use set_stream() instead of set_tdm_slots() for HDAudio
ASoC/SoundWire: dai: expand 'stream' concept beyond SoundWire
rcu-tasks: Simplify trc_read_check_handler() atomic operations
net/af_packet: add VLAN support for AF_PACKET SOCK_RAW GSO
net/af_packet: make sure to pull mac header
media: stv0288: use explicitly signed char
soc: qcom: Select REMAP_MMIO for LLCC driver
kest.pl: Fix grub2 menu handling for rebooting
ktest.pl minconfig: Unset configs instead of just removing them
jbd2: use the correct print format
perf/x86/intel/uncore: Disable I/O stacks to PMU mapping on ICX-D
perf/x86/intel/uncore: Clear attr_update properly
arm64: dts: qcom: sdm845-db845c: correct SPI2 pins drive strength
mmc: sdhci-sprd: Disable CLK_AUTO when the clock is less than 400K
btrfs: fix resolving backrefs for inline extent followed by prealloc
ARM: ux500: do not directly dereference __iomem
arm64: dts: qcom: sdm850-lenovo-yoga-c630: correct I2C12 pins drive strength
selftests: Use optional USERCFLAGS and USERLDFLAGS
PM/devfreq: governor: Add a private governor_data for governor
cpufreq: Init completion before kobject_init_and_add()
ALSA: patch_realtek: Fix Dell Inspiron Plus 16
ALSA: hda/realtek: Apply dual codec fixup for Dell Latitude laptops
fs: dlm: fix sock release if listen fails
fs: dlm: retry accept() until -EAGAIN or error returns
mptcp: mark ops structures as ro_after_init
mptcp: remove MPTCP 'ifdef' in TCP SYN cookies
dm cache: Fix ABBA deadlock between shrink_slab and dm_cache_metadata_abort
dm thin: Fix ABBA deadlock between shrink_slab and dm_pool_abort_metadata
dm thin: Use last transaction's pmd->root when commit failed
dm thin: resume even if in FAIL mode
dm thin: Fix UAF in run_timer_softirq()
dm integrity: Fix UAF in dm_integrity_dtr()
dm clone: Fix UAF in clone_dtr()
dm cache: Fix UAF in destroy()
dm cache: set needs_check flag after aborting metadata
tracing/hist: Fix out-of-bound write on 'action_data.var_ref_idx'
perf/core: Call LSM hook after copying perf_event_attr
of/kexec: Fix reading 32-bit "linux,initrd-{start,end}" values
KVM: VMX: Resume guest immediately when injecting #GP on ECREATE
KVM: nVMX: Inject #GP, not #UD, if "generic" VMXON CR0/CR4 check fails
KVM: nVMX: Properly expose ENABLE_USR_WAIT_PAUSE control to L1
x86/microcode/intel: Do not retry microcode reloading on the APs
ftrace/x86: Add back ftrace_expected for ftrace bug reports
x86/kprobes: Fix kprobes instruction boudary check with CONFIG_RETHUNK
x86/kprobes: Fix optprobe optimization check with CONFIG_RETHUNK
tracing: Fix race where eprobes can be called before the event
tracing: Fix complicated dependency of CONFIG_TRACER_MAX_TRACE
tracing/hist: Fix wrong return value in parse_action_params()
tracing/probes: Handle system names with hyphens
tracing: Fix infinite loop in tracing_read_pipe on overflowed print_trace_line
staging: media: tegra-video: fix chan->mipi value on error
staging: media: tegra-video: fix device_node use after free
ARM: 9256/1: NWFPE: avoid compiler-generated __aeabi_uldivmod
media: dvb-core: Fix double free in dvb_register_device()
media: dvb-core: Fix UAF due to refcount races at releasing
cifs: fix confusing debug message
cifs: fix missing display of three mount options
rtc: ds1347: fix value written to century register
block: mq-deadline: Do not break sequential write streams to zoned HDDs
md/bitmap: Fix bitmap chunk size overflow issues
efi: Add iMac Pro 2017 to uefi skip cert quirk
wifi: wilc1000: sdio: fix module autoloading
ASoC: jz4740-i2s: Handle independent FIFO flush bits
ipu3-imgu: Fix NULL pointer dereference in imgu_subdev_set_selection()
ipmi: fix long wait in unload when IPMI disconnect
mtd: spi-nor: Check for zero erase size in spi_nor_find_best_erase_type()
ima: Fix a potential NULL pointer access in ima_restore_measurement_list
ipmi: fix use after free in _ipmi_destroy_user()
PCI: Fix pci_device_is_present() for VFs by checking PF
PCI/sysfs: Fix double free in error path
riscv: stacktrace: Fixup ftrace_graph_ret_addr retp argument
riscv: mm: notify remote harts about mmu cache updates
crypto: n2 - add missing hash statesize
crypto: ccp - Add support for TEE for PCI ID 0x14CA
driver core: Fix bus_type.match() error handling in __driver_attach()
phy: qcom-qmp-combo: fix sc8180x reset
iommu/amd: Fix ivrs_acpihid cmdline parsing code
remoteproc: core: Do pm_relax when in RPROC_OFFLINE state
parisc: led: Fix potential null-ptr-deref in start_task()
device_cgroup: Roll back to original exceptions after copy failure
drm/connector: send hotplug uevent on connector cleanup
drm/vmwgfx: Validate the box size for the snooped cursor
drm/i915/dsi: fix VBT send packet port selection for dual link DSI
drm/ingenic: Fix missing platform_driver_unregister() call in ingenic_drm_init()
ext4: silence the warning when evicting inode with dioread_nolock
ext4: add inode table check in __ext4_get_inode_loc to aovid possible infinite loop
ext4: remove trailing newline from ext4_msg() message
fs: ext4: initialize fsdata in pagecache_write()
ext4: fix use-after-free in ext4_orphan_cleanup
ext4: fix undefined behavior in bit shift for ext4_check_flag_values
ext4: add EXT4_IGET_BAD flag to prevent unexpected bad inode
ext4: add helper to check quota inums
ext4: fix bug_on in __es_tree_search caused by bad quota inode
ext4: fix reserved cluster accounting in __es_remove_extent()
ext4: check and assert if marking an no_delete evicting inode dirty
ext4: fix bug_on in __es_tree_search caused by bad boot loader inode
ext4: fix leaking uninitialized memory in fast-commit journal
ext4: fix uninititialized value in 'ext4_evict_inode'
ext4: init quota for 'old.inode' in 'ext4_rename'
ext4: fix delayed allocation bug in ext4_clu_mapped for bigalloc + inline
ext4: fix corruption when online resizing a 1K bigalloc fs
ext4: fix error code return to user-space in ext4_get_branch()
ext4: avoid BUG_ON when creating xattrs
ext4: fix kernel BUG in 'ext4_write_inline_data_end()'
ext4: fix inode leak in ext4_xattr_inode_create() on an error path
ext4: initialize quota before expanding inode in setproject ioctl
ext4: avoid unaccounted block allocation when expanding inode
ext4: allocate extended attribute value in vmalloc area
drm/amdgpu: handle polaris10/11 overlap asics (v2)
drm/amdgpu: make display pinning more flexible (v2)
block: mq-deadline: Fix dd_finish_request() for zoned devices
tracing: Fix issue of missing one synthetic field
ext4: remove unused enum EXT4_FC_COMMIT_FAILED
ext4: use ext4_debug() instead of jbd_debug()
ext4: introduce EXT4_FC_TAG_BASE_LEN helper
ext4: factor out ext4_fc_get_tl()
ext4: fix potential out of bound read in ext4_fc_replay_scan()
ext4: disable fast-commit of encrypted dir operations
ext4: don't set up encryption key during jbd2 transaction
ext4: add missing validation of fast-commit record lengths
ext4: fix unaligned memory access in ext4_fc_reserve_space()
ext4: fix off-by-one errors in fast-commit block filling
ARM: renumber bits related to _TIF_WORK_MASK
phy: qcom-qmp-combo: fix out-of-bounds clock access
btrfs: replace strncpy() with strscpy()
btrfs: move missing device handling in a dedicate function
btrfs: fix extent map use-after-free when handling missing device in read_one_chunk
x86/mce: Get rid of msr_ops
x86/MCE/AMD: Clear DFR errors found in THR handler
media: s5p-mfc: Fix to handle reference queue during finishing
media: s5p-mfc: Clear workbit to handle error condition
media: s5p-mfc: Fix in register read and write for H264
perf probe: Use dwarf_attr_integrate as generic DWARF attr accessor
perf probe: Fix to get the DW_AT_decl_file and DW_AT_call_file as unsinged data
ravb: Fix "failed to switch device to config mode" message during unbind
ext4: goto right label 'failed_mount3a'
ext4: correct inconsistent error msg in nojournal mode
mbcache: automatically delete entries from cache on freeing
ext4: fix deadlock due to mbcache entry corruption
drm/i915/migrate: don't check the scratch page
drm/i915/migrate: fix offset calculation
drm/i915/migrate: fix length calculation
SUNRPC: ensure the matching upcall is in-flight upon downcall
btrfs: fix an error handling path in btrfs_defrag_leaves()
bpf: pull before calling skb_postpull_rcsum()
drm/panfrost: Fix GEM handle creation ref-counting
netfilter: nf_tables: consolidate set description
netfilter: nf_tables: add function to create set stateful expressions
netfilter: nf_tables: perform type checking for existing sets
vmxnet3: correctly report csum_level for encapsulated packet
netfilter: nf_tables: honor set timeout and garbage collection updates
veth: Fix race with AF_XDP exposing old or uninitialized descriptors
nfsd: shut down the NFSv4 state objects before the filecache
net: hns3: add interrupts re-initialization while doing VF FLR
net: hns3: refactor hns3_nic_reuse_page()
net: hns3: extract macro to simplify ring stats update code
net: hns3: fix miss L3E checking for rx packet
net: hns3: fix VF promisc mode not update when mac table full
net: sched: fix memory leak in tcindex_set_parms
qlcnic: prevent ->dcb use-after-free on qlcnic_dcb_enable() failure
net: dsa: mv88e6xxx: depend on PTP conditionally
nfc: Fix potential resource leaks
vdpa_sim: fix possible memory leak in vdpasim_net_init() and vdpasim_blk_init()
vhost/vsock: Fix error handling in vhost_vsock_init()
vringh: fix range used in iotlb_translate()
vhost: fix range used in translate_desc()
vdpa_sim: fix vringh initialization in vdpasim_queue_ready()
net/mlx5: E-Switch, properly handle ingress tagged packets on VST
net/mlx5: Add forgotten cleanup calls into mlx5_init_once() error path
net/mlx5: Avoid recovery in probe flows
net/mlx5e: IPoIB, Don't allow CQE compression to be turned on by default
net/mlx5e: TC, Refactor mlx5e_tc_add_flow_mod_hdr() to get flow attr
net/mlx5e: Always clear dest encap in neigh-update-del
net/mlx5e: Fix hw mtu initializing at XDP SQ allocation
net: amd-xgbe: add missed tasklet_kill
net: ena: Fix toeplitz initial hash value
net: ena: Don't register memory info on XDP exchange
net: ena: Account for the number of processed bytes in XDP
net: ena: Use bitmask to indicate packet redirection
net: ena: Fix rx_copybreak value update
net: ena: Set default value for RX interrupt moderation
net: ena: Update NUMA TPH hint register upon NUMA node update
net: phy: xgmiitorgmii: Fix refcount leak in xgmiitorgmii_probe
RDMA/mlx5: Fix mlx5_ib_get_hw_stats when used for device
RDMA/mlx5: Fix validation of max_rd_atomic caps for DC
drm/meson: Reduce the FIFO lines held when AFBC is not used
filelock: new helper: vfs_inode_has_locks
ceph: switch to vfs_inode_has_locks() to fix file lock bug
gpio: sifive: Fix refcount leak in sifive_gpio_probe
net: sched: atm: dont intepret cls results when asked to drop
net: sched: cbq: dont intepret cls results when asked to drop
net: sparx5: Fix reading of the MAC address
netfilter: ipset: fix hash:net,port,net hang with /0 subnet
netfilter: ipset: Rework long task execution when adding/deleting entries
perf tools: Fix resources leak in perf_data__open_dir()
drm/imx: ipuv3-plane: Fix overlay plane width
fs/ntfs3: don't hold ni_lock when calling truncate_setsize()
drivers/net/bonding/bond_3ad: return when there's no aggregator
octeontx2-pf: Fix lmtst ID used in aura free
usb: rndis_host: Secure rndis_query check against int overflow
perf stat: Fix handling of --for-each-cgroup with --bpf-counters to match non BPF mode
drm/i915: unpin on error in intel_vgpu_shadow_mm_pin()
caif: fix memory leak in cfctrl_linkup_request()
udf: Fix extension of the last extent in the file
ASoC: Intel: bytcr_rt5640: Add quirk for the Advantech MICA-071 tablet
nvme: fix multipath crash caused by flush request when blktrace is enabled
io_uring: check for valid register opcode earlier
nvmet: use NVME_CMD_EFFECTS_CSUPP instead of open coding it
nvme: also return I/O command effects from nvme_command_effects
btrfs: check superblock to ensure the fs was not modified at thaw time
x86/kexec: Fix double-free of elf header buffer
x86/bugs: Flush IBP in ib_prctl_set()
nfsd: fix handling of readdir in v4root vs. mount upcall timeout
fbdev: matroxfb: G200eW: Increase max memory from 1 MB to 16 MB
block: don't allow splitting of a REQ_NOWAIT bio
io_uring: fix CQ waiting timeout handling
thermal: int340x: Add missing attribute for data rate base
riscv: uaccess: fix type of 0 variable on error in get_user()
riscv, kprobes: Stricter c.jr/c.jalr decoding
drm/i915/gvt: fix gvt debugfs destroy
drm/i915/gvt: fix vgpu debugfs clean in remove
hfs/hfsplus: use WARN_ON for sanity check
hfs/hfsplus: avoid WARN_ON() for sanity check, use proper error handling
ksmbd: fix infinite loop in ksmbd_conn_handler_loop()
ksmbd: check nt_len to be at least CIFS_ENCPWD_SIZE in ksmbd_decode_ntlmssp_auth_blob
Revert "ACPI: PM: Add support for upcoming AMD uPEP HID AMDI007"
mptcp: dedicated request sock for subflow in v6
mptcp: use proper req destructor for IPv6
ext4: don't allow journal inode to have encrypt flag
selftests: set the BUILD variable to absolute path
btrfs: make thaw time super block check to also verify checksum
net: hns3: fix return value check bug of rx copybreak
mbcache: Avoid nesting of cache->c_list_lock under bit locks
efi: random: combine bootloader provided RNG seed with RNG protocol output
io_uring: Fix unsigned 'res' comparison with zero in io_fixup_rw_res()
drm/mgag200: Fix PLL setup for G200_SE_A rev >=4
Linux 5.15.87
Change-Id: I06fb376627506652ed60c04d56074956e6e075a0
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -1698,9 +1698,10 @@ call_ad(struct net *net, struct sock *ctnl, struct sk_buff *skb,
|
||||
ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried);
|
||||
ip_set_unlock(set);
|
||||
retried = true;
|
||||
} while (ret == -EAGAIN &&
|
||||
set->variant->resize &&
|
||||
(ret = set->variant->resize(set, retried)) == 0);
|
||||
} while (ret == -ERANGE ||
|
||||
(ret == -EAGAIN &&
|
||||
set->variant->resize &&
|
||||
(ret = set->variant->resize(set, retried)) == 0));
|
||||
|
||||
if (!ret || (ret == -IPSET_ERR_EXIST && eexist))
|
||||
return 0;
|
||||
|
||||
@@ -98,11 +98,11 @@ static int
|
||||
hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct hash_ip4 *h = set->data;
|
||||
struct hash_ip4 *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ip4_elem e = { 0 };
|
||||
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
|
||||
u32 ip = 0, ip_to = 0, hosts;
|
||||
u32 ip = 0, ip_to = 0, hosts, i = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
@@ -147,14 +147,14 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
|
||||
|
||||
/* 64bit division is not allowed on 32bit */
|
||||
if (((u64)ip_to - ip + 1) >> (32 - h->netmask) > IPSET_MAX_RANGE)
|
||||
return -ERANGE;
|
||||
|
||||
if (retried)
|
||||
ip = ntohl(h->next.ip);
|
||||
for (; ip <= ip_to;) {
|
||||
for (; ip <= ip_to; i++) {
|
||||
e.ip = htonl(ip);
|
||||
if (i > IPSET_MAX_RANGE) {
|
||||
hash_ip4_data_next(&h->next, &e);
|
||||
return -ERANGE;
|
||||
}
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
|
||||
@@ -97,11 +97,11 @@ static int
|
||||
hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct hash_ipmark4 *h = set->data;
|
||||
struct hash_ipmark4 *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipmark4_elem e = { };
|
||||
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
|
||||
u32 ip, ip_to = 0;
|
||||
u32 ip, ip_to = 0, i = 0;
|
||||
int ret;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
@@ -148,13 +148,14 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
ip_set_mask_from_to(ip, ip_to, cidr);
|
||||
}
|
||||
|
||||
if (((u64)ip_to - ip + 1) > IPSET_MAX_RANGE)
|
||||
return -ERANGE;
|
||||
|
||||
if (retried)
|
||||
ip = ntohl(h->next.ip);
|
||||
for (; ip <= ip_to; ip++) {
|
||||
for (; ip <= ip_to; ip++, i++) {
|
||||
e.ip = htonl(ip);
|
||||
if (i > IPSET_MAX_RANGE) {
|
||||
hash_ipmark4_data_next(&h->next, &e);
|
||||
return -ERANGE;
|
||||
}
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
|
||||
@@ -105,11 +105,11 @@ static int
|
||||
hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct hash_ipport4 *h = set->data;
|
||||
struct hash_ipport4 *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipport4_elem e = { .ip = 0 };
|
||||
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
|
||||
u32 ip, ip_to = 0, p = 0, port, port_to;
|
||||
u32 ip, ip_to = 0, p = 0, port, port_to, i = 0;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
@@ -173,17 +173,18 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
swap(port, port_to);
|
||||
}
|
||||
|
||||
if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
|
||||
return -ERANGE;
|
||||
|
||||
if (retried)
|
||||
ip = ntohl(h->next.ip);
|
||||
for (; ip <= ip_to; ip++) {
|
||||
p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
|
||||
: port;
|
||||
for (; p <= port_to; p++) {
|
||||
for (; p <= port_to; p++, i++) {
|
||||
e.ip = htonl(ip);
|
||||
e.port = htons(p);
|
||||
if (i > IPSET_MAX_RANGE) {
|
||||
hash_ipport4_data_next(&h->next, &e);
|
||||
return -ERANGE;
|
||||
}
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
|
||||
@@ -108,11 +108,11 @@ static int
|
||||
hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct hash_ipportip4 *h = set->data;
|
||||
struct hash_ipportip4 *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportip4_elem e = { .ip = 0 };
|
||||
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
|
||||
u32 ip, ip_to = 0, p = 0, port, port_to;
|
||||
u32 ip, ip_to = 0, p = 0, port, port_to, i = 0;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
@@ -180,17 +180,18 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
swap(port, port_to);
|
||||
}
|
||||
|
||||
if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
|
||||
return -ERANGE;
|
||||
|
||||
if (retried)
|
||||
ip = ntohl(h->next.ip);
|
||||
for (; ip <= ip_to; ip++) {
|
||||
p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
|
||||
: port;
|
||||
for (; p <= port_to; p++) {
|
||||
for (; p <= port_to; p++, i++) {
|
||||
e.ip = htonl(ip);
|
||||
e.port = htons(p);
|
||||
if (i > IPSET_MAX_RANGE) {
|
||||
hash_ipportip4_data_next(&h->next, &e);
|
||||
return -ERANGE;
|
||||
}
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
|
||||
@@ -160,12 +160,12 @@ static int
|
||||
hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct hash_ipportnet4 *h = set->data;
|
||||
struct hash_ipportnet4 *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 };
|
||||
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
|
||||
u32 ip = 0, ip_to = 0, p = 0, port, port_to;
|
||||
u32 ip2_from = 0, ip2_to = 0, ip2;
|
||||
u32 ip2_from = 0, ip2_to = 0, ip2, i = 0;
|
||||
bool with_ports = false;
|
||||
u8 cidr;
|
||||
int ret;
|
||||
@@ -253,9 +253,6 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
swap(port, port_to);
|
||||
}
|
||||
|
||||
if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
|
||||
return -ERANGE;
|
||||
|
||||
ip2_to = ip2_from;
|
||||
if (tb[IPSET_ATTR_IP2_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
|
||||
@@ -282,9 +279,15 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
for (; p <= port_to; p++) {
|
||||
e.port = htons(p);
|
||||
do {
|
||||
i++;
|
||||
e.ip2 = htonl(ip2);
|
||||
ip2 = ip_set_range_to_cidr(ip2, ip2_to, &cidr);
|
||||
e.cidr = cidr - 1;
|
||||
if (i > IPSET_MAX_RANGE) {
|
||||
hash_ipportnet4_data_next(&h->next,
|
||||
&e);
|
||||
return -ERANGE;
|
||||
}
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
|
||||
@@ -136,11 +136,11 @@ static int
|
||||
hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct hash_net4 *h = set->data;
|
||||
struct hash_net4 *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_net4_elem e = { .cidr = HOST_MASK };
|
||||
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
|
||||
u32 ip = 0, ip_to = 0, ipn, n = 0;
|
||||
u32 ip = 0, ip_to = 0, i = 0;
|
||||
int ret;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
@@ -188,19 +188,16 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
if (ip + UINT_MAX == ip_to)
|
||||
return -IPSET_ERR_HASH_RANGE;
|
||||
}
|
||||
ipn = ip;
|
||||
do {
|
||||
ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr);
|
||||
n++;
|
||||
} while (ipn++ < ip_to);
|
||||
|
||||
if (n > IPSET_MAX_RANGE)
|
||||
return -ERANGE;
|
||||
|
||||
if (retried)
|
||||
ip = ntohl(h->next.ip);
|
||||
do {
|
||||
i++;
|
||||
e.ip = htonl(ip);
|
||||
if (i > IPSET_MAX_RANGE) {
|
||||
hash_net4_data_next(&h->next, &e);
|
||||
return -ERANGE;
|
||||
}
|
||||
ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
|
||||
@@ -202,7 +202,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
|
||||
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
|
||||
u32 ip = 0, ip_to = 0, ipn, n = 0;
|
||||
u32 ip = 0, ip_to = 0, i = 0;
|
||||
int ret;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
@@ -256,19 +256,16 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
} else {
|
||||
ip_set_mask_from_to(ip, ip_to, e.cidr);
|
||||
}
|
||||
ipn = ip;
|
||||
do {
|
||||
ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr);
|
||||
n++;
|
||||
} while (ipn++ < ip_to);
|
||||
|
||||
if (n > IPSET_MAX_RANGE)
|
||||
return -ERANGE;
|
||||
|
||||
if (retried)
|
||||
ip = ntohl(h->next.ip);
|
||||
do {
|
||||
i++;
|
||||
e.ip = htonl(ip);
|
||||
if (i > IPSET_MAX_RANGE) {
|
||||
hash_netiface4_data_next(&h->next, &e);
|
||||
return -ERANGE;
|
||||
}
|
||||
ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
|
||||
|
||||
@@ -163,13 +163,12 @@ static int
|
||||
hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct hash_netnet4 *h = set->data;
|
||||
struct hash_netnet4 *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netnet4_elem e = { };
|
||||
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
|
||||
u32 ip = 0, ip_to = 0;
|
||||
u32 ip2 = 0, ip2_from = 0, ip2_to = 0, ipn;
|
||||
u64 n = 0, m = 0;
|
||||
u32 ip2 = 0, ip2_from = 0, ip2_to = 0, i = 0;
|
||||
int ret;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
@@ -245,19 +244,6 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
} else {
|
||||
ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
|
||||
}
|
||||
ipn = ip;
|
||||
do {
|
||||
ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr[0]);
|
||||
n++;
|
||||
} while (ipn++ < ip_to);
|
||||
ipn = ip2_from;
|
||||
do {
|
||||
ipn = ip_set_range_to_cidr(ipn, ip2_to, &e.cidr[1]);
|
||||
m++;
|
||||
} while (ipn++ < ip2_to);
|
||||
|
||||
if (n*m > IPSET_MAX_RANGE)
|
||||
return -ERANGE;
|
||||
|
||||
if (retried) {
|
||||
ip = ntohl(h->next.ip[0]);
|
||||
@@ -270,7 +256,12 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
e.ip[0] = htonl(ip);
|
||||
ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
|
||||
do {
|
||||
i++;
|
||||
e.ip[1] = htonl(ip2);
|
||||
if (i > IPSET_MAX_RANGE) {
|
||||
hash_netnet4_data_next(&h->next, &e);
|
||||
return -ERANGE;
|
||||
}
|
||||
ip2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]);
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
|
||||
@@ -154,12 +154,11 @@ static int
|
||||
hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct hash_netport4 *h = set->data;
|
||||
struct hash_netport4 *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 };
|
||||
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
|
||||
u32 port, port_to, p = 0, ip = 0, ip_to = 0, ipn;
|
||||
u64 n = 0;
|
||||
u32 port, port_to, p = 0, ip = 0, ip_to = 0, i = 0;
|
||||
bool with_ports = false;
|
||||
u8 cidr;
|
||||
int ret;
|
||||
@@ -236,14 +235,6 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
} else {
|
||||
ip_set_mask_from_to(ip, ip_to, e.cidr + 1);
|
||||
}
|
||||
ipn = ip;
|
||||
do {
|
||||
ipn = ip_set_range_to_cidr(ipn, ip_to, &cidr);
|
||||
n++;
|
||||
} while (ipn++ < ip_to);
|
||||
|
||||
if (n*(port_to - port + 1) > IPSET_MAX_RANGE)
|
||||
return -ERANGE;
|
||||
|
||||
if (retried) {
|
||||
ip = ntohl(h->next.ip);
|
||||
@@ -255,8 +246,12 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
e.ip = htonl(ip);
|
||||
ip = ip_set_range_to_cidr(ip, ip_to, &cidr);
|
||||
e.cidr = cidr - 1;
|
||||
for (; p <= port_to; p++) {
|
||||
for (; p <= port_to; p++, i++) {
|
||||
e.port = htons(p);
|
||||
if (i > IPSET_MAX_RANGE) {
|
||||
hash_netport4_data_next(&h->next, &e);
|
||||
return -ERANGE;
|
||||
}
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
|
||||
@@ -173,17 +173,26 @@ hash_netportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
|
||||
}
|
||||
|
||||
static u32
|
||||
hash_netportnet4_range_to_cidr(u32 from, u32 to, u8 *cidr)
|
||||
{
|
||||
if (from == 0 && to == UINT_MAX) {
|
||||
*cidr = 0;
|
||||
return to;
|
||||
}
|
||||
return ip_set_range_to_cidr(from, to, cidr);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct hash_netportnet4 *h = set->data;
|
||||
struct hash_netportnet4 *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netportnet4_elem e = { };
|
||||
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
|
||||
u32 ip = 0, ip_to = 0, p = 0, port, port_to;
|
||||
u32 ip2_from = 0, ip2_to = 0, ip2, ipn;
|
||||
u64 n = 0, m = 0;
|
||||
u32 ip2_from = 0, ip2_to = 0, ip2, i = 0;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
@@ -285,19 +294,6 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
} else {
|
||||
ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
|
||||
}
|
||||
ipn = ip;
|
||||
do {
|
||||
ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr[0]);
|
||||
n++;
|
||||
} while (ipn++ < ip_to);
|
||||
ipn = ip2_from;
|
||||
do {
|
||||
ipn = ip_set_range_to_cidr(ipn, ip2_to, &e.cidr[1]);
|
||||
m++;
|
||||
} while (ipn++ < ip2_to);
|
||||
|
||||
if (n*m*(port_to - port + 1) > IPSET_MAX_RANGE)
|
||||
return -ERANGE;
|
||||
|
||||
if (retried) {
|
||||
ip = ntohl(h->next.ip[0]);
|
||||
@@ -310,13 +306,19 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
do {
|
||||
e.ip[0] = htonl(ip);
|
||||
ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
|
||||
ip = hash_netportnet4_range_to_cidr(ip, ip_to, &e.cidr[0]);
|
||||
for (; p <= port_to; p++) {
|
||||
e.port = htons(p);
|
||||
do {
|
||||
i++;
|
||||
e.ip[1] = htonl(ip2);
|
||||
ip2 = ip_set_range_to_cidr(ip2, ip2_to,
|
||||
&e.cidr[1]);
|
||||
if (i > IPSET_MAX_RANGE) {
|
||||
hash_netportnet4_data_next(&h->next,
|
||||
&e);
|
||||
return -ERANGE;
|
||||
}
|
||||
ip2 = hash_netportnet4_range_to_cidr(ip2,
|
||||
ip2_to, &e.cidr[1]);
|
||||
ret = adtfn(set, &e, &ext, &ext, flags);
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
|
||||
@@ -465,8 +465,9 @@ static int nft_delrule_by_chain(struct nft_ctx *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
|
||||
struct nft_set *set)
|
||||
static int __nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
|
||||
struct nft_set *set,
|
||||
const struct nft_set_desc *desc)
|
||||
{
|
||||
struct nft_trans *trans;
|
||||
|
||||
@@ -474,17 +475,28 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
|
||||
if (trans == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] != NULL) {
|
||||
if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] && !desc) {
|
||||
nft_trans_set_id(trans) =
|
||||
ntohl(nla_get_be32(ctx->nla[NFTA_SET_ID]));
|
||||
nft_activate_next(ctx->net, set);
|
||||
}
|
||||
nft_trans_set(trans) = set;
|
||||
if (desc) {
|
||||
nft_trans_set_update(trans) = true;
|
||||
nft_trans_set_gc_int(trans) = desc->gc_int;
|
||||
nft_trans_set_timeout(trans) = desc->timeout;
|
||||
}
|
||||
nft_trans_commit_list_add_tail(ctx->net, trans);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
|
||||
struct nft_set *set)
|
||||
{
|
||||
return __nft_trans_set_add(ctx, msg_type, set, NULL);
|
||||
}
|
||||
|
||||
static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
{
|
||||
int err;
|
||||
@@ -3635,8 +3647,7 @@ static bool nft_set_ops_candidate(const struct nft_set_type *type, u32 flags)
|
||||
static const struct nft_set_ops *
|
||||
nft_select_set_ops(const struct nft_ctx *ctx,
|
||||
const struct nlattr * const nla[],
|
||||
const struct nft_set_desc *desc,
|
||||
enum nft_set_policies policy)
|
||||
const struct nft_set_desc *desc)
|
||||
{
|
||||
struct nftables_pernet *nft_net = nft_pernet(ctx->net);
|
||||
const struct nft_set_ops *ops, *bops;
|
||||
@@ -3665,7 +3676,7 @@ nft_select_set_ops(const struct nft_ctx *ctx,
|
||||
if (!ops->estimate(desc, flags, &est))
|
||||
continue;
|
||||
|
||||
switch (policy) {
|
||||
switch (desc->policy) {
|
||||
case NFT_SET_POL_PERFORMANCE:
|
||||
if (est.lookup < best.lookup)
|
||||
break;
|
||||
@@ -3900,8 +3911,10 @@ static int nf_tables_fill_set_concat(struct sk_buff *skb,
|
||||
static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
|
||||
const struct nft_set *set, u16 event, u16 flags)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
u64 timeout = READ_ONCE(set->timeout);
|
||||
u32 gc_int = READ_ONCE(set->gc_int);
|
||||
u32 portid = ctx->portid;
|
||||
struct nlmsghdr *nlh;
|
||||
struct nlattr *nest;
|
||||
u32 seq = ctx->seq;
|
||||
int i;
|
||||
@@ -3937,13 +3950,13 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
|
||||
nla_put_be32(skb, NFTA_SET_OBJ_TYPE, htonl(set->objtype)))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (set->timeout &&
|
||||
if (timeout &&
|
||||
nla_put_be64(skb, NFTA_SET_TIMEOUT,
|
||||
nf_jiffies64_to_msecs(set->timeout),
|
||||
nf_jiffies64_to_msecs(timeout),
|
||||
NFTA_SET_PAD))
|
||||
goto nla_put_failure;
|
||||
if (set->gc_int &&
|
||||
nla_put_be32(skb, NFTA_SET_GC_INTERVAL, htonl(set->gc_int)))
|
||||
if (gc_int &&
|
||||
nla_put_be32(skb, NFTA_SET_GC_INTERVAL, htonl(gc_int)))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (set->policy != NFT_SET_POL_PERFORMANCE) {
|
||||
@@ -4244,15 +4257,94 @@ static int nf_tables_set_desc_parse(struct nft_set_desc *desc,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nft_set_expr_alloc(struct nft_ctx *ctx, struct nft_set *set,
|
||||
const struct nlattr * const *nla,
|
||||
struct nft_expr **exprs, int *num_exprs,
|
||||
u32 flags)
|
||||
{
|
||||
struct nft_expr *expr;
|
||||
int err, i;
|
||||
|
||||
if (nla[NFTA_SET_EXPR]) {
|
||||
expr = nft_set_elem_expr_alloc(ctx, set, nla[NFTA_SET_EXPR]);
|
||||
if (IS_ERR(expr)) {
|
||||
err = PTR_ERR(expr);
|
||||
goto err_set_expr_alloc;
|
||||
}
|
||||
exprs[0] = expr;
|
||||
(*num_exprs)++;
|
||||
} else if (nla[NFTA_SET_EXPRESSIONS]) {
|
||||
struct nlattr *tmp;
|
||||
int left;
|
||||
|
||||
if (!(flags & NFT_SET_EXPR)) {
|
||||
err = -EINVAL;
|
||||
goto err_set_expr_alloc;
|
||||
}
|
||||
i = 0;
|
||||
nla_for_each_nested(tmp, nla[NFTA_SET_EXPRESSIONS], left) {
|
||||
if (i == NFT_SET_EXPR_MAX) {
|
||||
err = -E2BIG;
|
||||
goto err_set_expr_alloc;
|
||||
}
|
||||
if (nla_type(tmp) != NFTA_LIST_ELEM) {
|
||||
err = -EINVAL;
|
||||
goto err_set_expr_alloc;
|
||||
}
|
||||
expr = nft_set_elem_expr_alloc(ctx, set, tmp);
|
||||
if (IS_ERR(expr)) {
|
||||
err = PTR_ERR(expr);
|
||||
goto err_set_expr_alloc;
|
||||
}
|
||||
exprs[i++] = expr;
|
||||
(*num_exprs)++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_set_expr_alloc:
|
||||
for (i = 0; i < *num_exprs; i++)
|
||||
nft_expr_destroy(ctx, exprs[i]);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool nft_set_is_same(const struct nft_set *set,
|
||||
const struct nft_set_desc *desc,
|
||||
struct nft_expr *exprs[], u32 num_exprs, u32 flags)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (set->ktype != desc->ktype ||
|
||||
set->dtype != desc->dtype ||
|
||||
set->flags != flags ||
|
||||
set->klen != desc->klen ||
|
||||
set->dlen != desc->dlen ||
|
||||
set->field_count != desc->field_count ||
|
||||
set->num_exprs != num_exprs)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < desc->field_count; i++) {
|
||||
if (set->field_len[i] != desc->field_len[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_exprs; i++) {
|
||||
if (set->exprs[i]->ops != exprs[i]->ops)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
const struct nlattr * const nla[])
|
||||
{
|
||||
u32 ktype, dtype, flags, policy, gc_int, objtype;
|
||||
struct netlink_ext_ack *extack = info->extack;
|
||||
u8 genmask = nft_genmask_next(info->net);
|
||||
u8 family = info->nfmsg->nfgen_family;
|
||||
const struct nft_set_ops *ops;
|
||||
struct nft_expr *expr = NULL;
|
||||
struct net *net = info->net;
|
||||
struct nft_set_desc desc;
|
||||
struct nft_table *table;
|
||||
@@ -4260,10 +4352,11 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
struct nft_set *set;
|
||||
struct nft_ctx ctx;
|
||||
size_t alloc_size;
|
||||
u64 timeout;
|
||||
int num_exprs = 0;
|
||||
char *name;
|
||||
int err, i;
|
||||
u16 udlen;
|
||||
u32 flags;
|
||||
u64 size;
|
||||
|
||||
if (nla[NFTA_SET_TABLE] == NULL ||
|
||||
@@ -4274,10 +4367,10 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
|
||||
ktype = NFT_DATA_VALUE;
|
||||
desc.ktype = NFT_DATA_VALUE;
|
||||
if (nla[NFTA_SET_KEY_TYPE] != NULL) {
|
||||
ktype = ntohl(nla_get_be32(nla[NFTA_SET_KEY_TYPE]));
|
||||
if ((ktype & NFT_DATA_RESERVED_MASK) == NFT_DATA_RESERVED_MASK)
|
||||
desc.ktype = ntohl(nla_get_be32(nla[NFTA_SET_KEY_TYPE]));
|
||||
if ((desc.ktype & NFT_DATA_RESERVED_MASK) == NFT_DATA_RESERVED_MASK)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -4302,17 +4395,17 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
dtype = 0;
|
||||
desc.dtype = 0;
|
||||
if (nla[NFTA_SET_DATA_TYPE] != NULL) {
|
||||
if (!(flags & NFT_SET_MAP))
|
||||
return -EINVAL;
|
||||
|
||||
dtype = ntohl(nla_get_be32(nla[NFTA_SET_DATA_TYPE]));
|
||||
if ((dtype & NFT_DATA_RESERVED_MASK) == NFT_DATA_RESERVED_MASK &&
|
||||
dtype != NFT_DATA_VERDICT)
|
||||
desc.dtype = ntohl(nla_get_be32(nla[NFTA_SET_DATA_TYPE]));
|
||||
if ((desc.dtype & NFT_DATA_RESERVED_MASK) == NFT_DATA_RESERVED_MASK &&
|
||||
desc.dtype != NFT_DATA_VERDICT)
|
||||
return -EINVAL;
|
||||
|
||||
if (dtype != NFT_DATA_VERDICT) {
|
||||
if (desc.dtype != NFT_DATA_VERDICT) {
|
||||
if (nla[NFTA_SET_DATA_LEN] == NULL)
|
||||
return -EINVAL;
|
||||
desc.dlen = ntohl(nla_get_be32(nla[NFTA_SET_DATA_LEN]));
|
||||
@@ -4327,34 +4420,34 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
if (!(flags & NFT_SET_OBJECT))
|
||||
return -EINVAL;
|
||||
|
||||
objtype = ntohl(nla_get_be32(nla[NFTA_SET_OBJ_TYPE]));
|
||||
if (objtype == NFT_OBJECT_UNSPEC ||
|
||||
objtype > NFT_OBJECT_MAX)
|
||||
desc.objtype = ntohl(nla_get_be32(nla[NFTA_SET_OBJ_TYPE]));
|
||||
if (desc.objtype == NFT_OBJECT_UNSPEC ||
|
||||
desc.objtype > NFT_OBJECT_MAX)
|
||||
return -EOPNOTSUPP;
|
||||
} else if (flags & NFT_SET_OBJECT)
|
||||
return -EINVAL;
|
||||
else
|
||||
objtype = NFT_OBJECT_UNSPEC;
|
||||
desc.objtype = NFT_OBJECT_UNSPEC;
|
||||
|
||||
timeout = 0;
|
||||
desc.timeout = 0;
|
||||
if (nla[NFTA_SET_TIMEOUT] != NULL) {
|
||||
if (!(flags & NFT_SET_TIMEOUT))
|
||||
return -EINVAL;
|
||||
|
||||
err = nf_msecs_to_jiffies64(nla[NFTA_SET_TIMEOUT], &timeout);
|
||||
err = nf_msecs_to_jiffies64(nla[NFTA_SET_TIMEOUT], &desc.timeout);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
gc_int = 0;
|
||||
desc.gc_int = 0;
|
||||
if (nla[NFTA_SET_GC_INTERVAL] != NULL) {
|
||||
if (!(flags & NFT_SET_TIMEOUT))
|
||||
return -EINVAL;
|
||||
gc_int = ntohl(nla_get_be32(nla[NFTA_SET_GC_INTERVAL]));
|
||||
desc.gc_int = ntohl(nla_get_be32(nla[NFTA_SET_GC_INTERVAL]));
|
||||
}
|
||||
|
||||
policy = NFT_SET_POL_PERFORMANCE;
|
||||
desc.policy = NFT_SET_POL_PERFORMANCE;
|
||||
if (nla[NFTA_SET_POLICY] != NULL)
|
||||
policy = ntohl(nla_get_be32(nla[NFTA_SET_POLICY]));
|
||||
desc.policy = ntohl(nla_get_be32(nla[NFTA_SET_POLICY]));
|
||||
|
||||
if (nla[NFTA_SET_DESC] != NULL) {
|
||||
err = nf_tables_set_desc_parse(&desc, nla[NFTA_SET_DESC]);
|
||||
@@ -4386,6 +4479,8 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
return PTR_ERR(set);
|
||||
}
|
||||
} else {
|
||||
struct nft_expr *exprs[NFT_SET_EXPR_MAX] = {};
|
||||
|
||||
if (info->nlh->nlmsg_flags & NLM_F_EXCL) {
|
||||
NL_SET_BAD_ATTR(extack, nla[NFTA_SET_NAME]);
|
||||
return -EEXIST;
|
||||
@@ -4393,13 +4488,29 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
if (info->nlh->nlmsg_flags & NLM_F_REPLACE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
err = nft_set_expr_alloc(&ctx, set, nla, exprs, &num_exprs, flags);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = 0;
|
||||
if (!nft_set_is_same(set, &desc, exprs, num_exprs, flags)) {
|
||||
NL_SET_BAD_ATTR(extack, nla[NFTA_SET_NAME]);
|
||||
err = -EEXIST;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_exprs; i++)
|
||||
nft_expr_destroy(&ctx, exprs[i]);
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return __nft_trans_set_add(&ctx, NFT_MSG_NEWSET, set, &desc);
|
||||
}
|
||||
|
||||
if (!(info->nlh->nlmsg_flags & NLM_F_CREATE))
|
||||
return -ENOENT;
|
||||
|
||||
ops = nft_select_set_ops(&ctx, nla, &desc, policy);
|
||||
ops = nft_select_set_ops(&ctx, nla, &desc);
|
||||
if (IS_ERR(ops))
|
||||
return PTR_ERR(ops);
|
||||
|
||||
@@ -4439,18 +4550,18 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
set->table = table;
|
||||
write_pnet(&set->net, net);
|
||||
set->ops = ops;
|
||||
set->ktype = ktype;
|
||||
set->ktype = desc.ktype;
|
||||
set->klen = desc.klen;
|
||||
set->dtype = dtype;
|
||||
set->objtype = objtype;
|
||||
set->dtype = desc.dtype;
|
||||
set->objtype = desc.objtype;
|
||||
set->dlen = desc.dlen;
|
||||
set->flags = flags;
|
||||
set->size = desc.size;
|
||||
set->policy = policy;
|
||||
set->policy = desc.policy;
|
||||
set->udlen = udlen;
|
||||
set->udata = udata;
|
||||
set->timeout = timeout;
|
||||
set->gc_int = gc_int;
|
||||
set->timeout = desc.timeout;
|
||||
set->gc_int = desc.gc_int;
|
||||
|
||||
set->field_count = desc.field_count;
|
||||
for (i = 0; i < desc.field_count; i++)
|
||||
@@ -4460,43 +4571,11 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
if (err < 0)
|
||||
goto err_set_init;
|
||||
|
||||
if (nla[NFTA_SET_EXPR]) {
|
||||
expr = nft_set_elem_expr_alloc(&ctx, set, nla[NFTA_SET_EXPR]);
|
||||
if (IS_ERR(expr)) {
|
||||
err = PTR_ERR(expr);
|
||||
goto err_set_expr_alloc;
|
||||
}
|
||||
set->exprs[0] = expr;
|
||||
set->num_exprs++;
|
||||
} else if (nla[NFTA_SET_EXPRESSIONS]) {
|
||||
struct nft_expr *expr;
|
||||
struct nlattr *tmp;
|
||||
int left;
|
||||
|
||||
if (!(flags & NFT_SET_EXPR)) {
|
||||
err = -EINVAL;
|
||||
goto err_set_expr_alloc;
|
||||
}
|
||||
i = 0;
|
||||
nla_for_each_nested(tmp, nla[NFTA_SET_EXPRESSIONS], left) {
|
||||
if (i == NFT_SET_EXPR_MAX) {
|
||||
err = -E2BIG;
|
||||
goto err_set_expr_alloc;
|
||||
}
|
||||
if (nla_type(tmp) != NFTA_LIST_ELEM) {
|
||||
err = -EINVAL;
|
||||
goto err_set_expr_alloc;
|
||||
}
|
||||
expr = nft_set_elem_expr_alloc(&ctx, set, tmp);
|
||||
if (IS_ERR(expr)) {
|
||||
err = PTR_ERR(expr);
|
||||
goto err_set_expr_alloc;
|
||||
}
|
||||
set->exprs[i++] = expr;
|
||||
set->num_exprs++;
|
||||
}
|
||||
}
|
||||
err = nft_set_expr_alloc(&ctx, set, nla, set->exprs, &num_exprs, flags);
|
||||
if (err < 0)
|
||||
goto err_set_destroy;
|
||||
|
||||
set->num_exprs = num_exprs;
|
||||
set->handle = nf_tables_alloc_handle(table);
|
||||
|
||||
err = nft_trans_set_add(&ctx, NFT_MSG_NEWSET, set);
|
||||
@@ -4510,7 +4589,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
err_set_expr_alloc:
|
||||
for (i = 0; i < set->num_exprs; i++)
|
||||
nft_expr_destroy(&ctx, set->exprs[i]);
|
||||
|
||||
err_set_destroy:
|
||||
ops->destroy(set);
|
||||
err_set_init:
|
||||
kfree(set->name);
|
||||
@@ -5815,7 +5894,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
|
||||
return err;
|
||||
} else if (set->flags & NFT_SET_TIMEOUT &&
|
||||
!(flags & NFT_SET_ELEM_INTERVAL_END)) {
|
||||
timeout = set->timeout;
|
||||
timeout = READ_ONCE(set->timeout);
|
||||
}
|
||||
|
||||
expiration = 0;
|
||||
@@ -5916,7 +5995,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
|
||||
if (err < 0)
|
||||
goto err_parse_key_end;
|
||||
|
||||
if (timeout != set->timeout) {
|
||||
if (timeout != READ_ONCE(set->timeout)) {
|
||||
err = nft_set_ext_add(&tmpl, NFT_SET_EXT_TIMEOUT);
|
||||
if (err < 0)
|
||||
goto err_parse_key_end;
|
||||
@@ -8771,14 +8850,20 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
|
||||
nft_flow_rule_destroy(nft_trans_flow_rule(trans));
|
||||
break;
|
||||
case NFT_MSG_NEWSET:
|
||||
nft_clear(net, nft_trans_set(trans));
|
||||
/* This avoids hitting -EBUSY when deleting the table
|
||||
* from the transaction.
|
||||
*/
|
||||
if (nft_set_is_anonymous(nft_trans_set(trans)) &&
|
||||
!list_empty(&nft_trans_set(trans)->bindings))
|
||||
trans->ctx.table->use--;
|
||||
if (nft_trans_set_update(trans)) {
|
||||
struct nft_set *set = nft_trans_set(trans);
|
||||
|
||||
WRITE_ONCE(set->timeout, nft_trans_set_timeout(trans));
|
||||
WRITE_ONCE(set->gc_int, nft_trans_set_gc_int(trans));
|
||||
} else {
|
||||
nft_clear(net, nft_trans_set(trans));
|
||||
/* This avoids hitting -EBUSY when deleting the table
|
||||
* from the transaction.
|
||||
*/
|
||||
if (nft_set_is_anonymous(nft_trans_set(trans)) &&
|
||||
!list_empty(&nft_trans_set(trans)->bindings))
|
||||
trans->ctx.table->use--;
|
||||
}
|
||||
nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
|
||||
NFT_MSG_NEWSET, GFP_KERNEL);
|
||||
nft_trans_destroy(trans);
|
||||
@@ -9000,6 +9085,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
||||
nft_trans_destroy(trans);
|
||||
break;
|
||||
case NFT_MSG_NEWSET:
|
||||
if (nft_trans_set_update(trans)) {
|
||||
nft_trans_destroy(trans);
|
||||
break;
|
||||
}
|
||||
trans->ctx.table->use--;
|
||||
if (nft_trans_set_bound(trans)) {
|
||||
nft_trans_destroy(trans);
|
||||
|
||||
Reference in New Issue
Block a user