public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: [syzbot] [kvm?] WARNING in kvm_gmem_fault_user_mapping
  2026-02-03 22:50 ` [PATCH 1/2] KVM: guest_memfd: Always use order 0 when allocating for guest_memfd Ackerley Tng
@ 2026-02-03 22:00   ` syzbot
  2026-02-04 12:36   ` [PATCH 1/2] KVM: guest_memfd: Always use order 0 when allocating for guest_memfd Deepanshu Kartikey
  1 sibling, 0 replies; 4+ messages in thread
From: syzbot @ 2026-02-03 22:00 UTC (permalink / raw)
  To: ackerleytng, linux-kernel, syzkaller-bugs

Hello,

syzbot tried to test the proposed patch but the build/boot failed:

[ T5892] bridge0: port 1(bridge_slave_0) entered disabled state
[   81.250782][ T5892] bridge_slave_0: entered allmulticast mode
[   81.258962][ T5892] bridge_slave_0: entered promiscuous mode
[   81.278262][ T5892] bridge0: port 2(bridge_slave_1) entered blocking state
[   81.285839][ T5892] bridge0: port 2(bridge_slave_1) entered disabled state
[   81.293092][ T5892] bridge_slave_1: entered allmulticast mode
[   81.300579][ T5892] bridge_slave_1: entered promiscuous mode
[   81.323935][ T5892] bond0: (slave bond_slave_0): Enslaving as an active interface with an up link
[   81.334917][ T5892] bond0: (slave bond_slave_1): Enslaving as an active interface with an up link
[   81.359447][ T5892] team0: Port device team_slave_0 added
[   81.367513][ T5892] team0: Port device team_slave_1 added
[   81.408524][ T5892] batman_adv: batadv0: Adding interface: batadv_slave_0
[   81.415517][ T5892] batman_adv: batadv0: The MTU of interface batadv_slave_0 is too small (1500) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to 1532 would solve the problem.
[   81.441455][ T5892] batman_adv: batadv0: Not using interface batadv_slave_0 (retrying later): interface not active
[   81.453632][ T5892] batman_adv: batadv0: Adding interface: batadv_slave_1
[   81.460613][ T5892] batman_adv: batadv0: The MTU of interface batadv_slave_1 is too small (1500) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to 1532 would solve the problem.
[   81.488313][  T925] cfg80211: failed to load regulatory.db
[   81.495132][ T5892] batman_adv: batadv0: Not using interface batadv_slave_1 (retrying later): interface not active
[   81.579848][ T5892] hsr_slave_0: entered promiscuous mode
[   81.586459][ T5892] hsr_slave_1: entered promiscuous mode
[   81.772551][ T5892] netdevsim netdevsim1 netdevsim0: renamed from eth0
[   81.785274][ T5892] netdevsim netdevsim1 netdevsim1: renamed from eth1
[   81.794987][ T5892] netdevsim netdevsim1 netdevsim2: renamed from eth2
[   81.804459][ T5892] netdevsim netdevsim1 netdevsim3: renamed from eth3
[   81.830752][ T5892] bridge0: port 2(bridge_slave_1) entered blocking state
[   81.837931][ T5892] bridge0: port 2(bridge_slave_1) entered forwarding state
[   81.846102][ T5892] bridge0: port 1(bridge_slave_0) entered blocking state
[   81.853188][ T5892] bridge0: port 1(bridge_slave_0) entered forwarding state
[   81.897540][ T5892] 8021q: adding VLAN 0 to HW filter on device bond0
[   81.910890][ T1309] bridge0: port 1(bridge_slave_0) entered disabled state
[   81.920082][ T1309] bridge0: port 2(bridge_slave_1) entered disabled state
[   81.938230][ T5892] 8021q: adding VLAN 0 to HW filter on device team0
[   81.950068][ T4559] bridge0: port 1(bridge_slave_0) entered blocking state
[   81.957340][ T4559] bridge0: port 1(bridge_slave_0) entered forwarding state
[   81.970244][ T1309] bridge0: port 2(bridge_slave_1) entered blocking state
[   81.977416][ T1309] bridge0: port 2(bridge_slave_1) entered forwarding state
[   82.117812][ T5892] 8021q: adding VLAN 0 to HW filter on device batadv0
[   82.154991][ T5892] veth0_vlan: entered promiscuous mode
[   82.165350][ T5892] veth1_vlan: entered promiscuous mode
[   82.191094][ T5892] veth0_macvtap: entered promiscuous mode
[   82.199927][ T5892] veth1_macvtap: entered promiscuous mode
[   82.216210][ T5892] batman_adv: batadv0: Interface activated: batadv_slave_0
[   82.231786][ T5892] batman_adv: batadv0: Interface activated: batadv_slave_1
[   82.244797][ T1309] netdevsim netdevsim1 netdevsim0: set [1, 0] type 2 family 0 port 6081 - 0
[   82.261190][ T1309] netdevsim netdevsim1 netdevsim1: set [1, 0] type 2 family 0 port 6081 - 0
[   82.270821][ T1309] netdevsim netdevsim1 netdevsim2: set [1, 0] type 2 family 0 port 6081 - 0
[   82.284641][ T1309] netdevsim netdevsim1 netdevsim3: set [1, 0] type 2 family 0 port 6081 - 0
2026/02/03 21:59:31 executed programs: 0
[   82.372872][ T5875] Bluetooth: hci0: unexpected cc 0x0c03 length: 249 > 1
[   82.382293][ T5875] Bluetooth: hci0: unexpected cc 0x1003 length: 249 > 9
[   82.390483][ T5875] Bluetooth: hci0: unexpected cc 0x1001 length: 249 > 9
[   82.399377][ T5875] Bluetooth: hci0: unexpected cc 0x0c23 length: 249 > 4
[   82.407179][ T5875] Bluetooth: hci0: unexpected cc 0x0c38 length: 249 > 2
[   82.532003][ T5934] chnl_net:caif_netlink_parms(): no params data found
[   82.594483][ T5934] bridge0: port 1(bridge_slave_0) entered blocking state
[   82.602243][ T5934] bridge0: port 1(bridge_slave_0) entered disabled state
[   82.609657][ T5934] bridge_slave_0: entered allmulticast mode
[   82.616572][ T5934] bridge_slave_0: entered promiscuous mode
[   82.626770][ T5934] bridge0: port 2(bridge_slave_1) entered blocking state
[   82.634336][ T5934] bridge0: port 2(bridge_slave_1) entered disabled state
[   82.641777][ T5934] bridge_slave_1: entered allmulticast mode
[   82.648703][ T5934] bridge_slave_1: entered promiscuous mode
[   82.680172][ T5934] bond0: (slave bond_slave_0): Enslaving as an active interface with an up link
[   82.691594][ T5934] bond0: (slave bond_slave_1): Enslaving as an active interface with an up link
[   82.716205][ T5934] team0: Port device team_slave_0 added
[   82.723696][ T5934] team0: Port device team_slave_1 added
[   82.743136][ T5934] batman_adv: batadv0: Adding interface: batadv_slave_0
[   82.750263][ T5934] batman_adv: batadv0: The MTU of interface batadv_slave_0 is too small (1500) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to 1532 would solve the problem.
[   82.777401][ T5934] batman_adv: batadv0: Not using interface batadv_slave_0 (retrying later): interface not active
[   82.789795][ T5934] batman_adv: batadv0: Adding interface: batadv_slave_1
[   82.796831][ T5934] batman_adv: batadv0: The MTU of interface batadv_slave_1 is too small (1500) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to 1532 would solve the problem.
[   82.822826][ T5934] batman_adv: batadv0: Not using interface batadv_slave_1 (retrying later): interface not active
[   82.861709][ T5934] hsr_slave_0: entered promiscuous mode
[   82.868122][ T5934] hsr_slave_1: entered promiscuous mode
[   82.874061][ T5934] debugfs: 'hsr0' already exists in 'hsr'
[   82.879937][ T5934] Cannot create hsr debugfs directory
[   82.991829][ T5934] netdevsim netdevsim0 netdevsim0: renamed from eth0
[   83.001861][ T5934] netdevsim netdevsim0 netdevsim1: renamed from eth1
[   83.013215][ T5934] netdevsim netdevsim0 netdevsim2: renamed from eth2
[   83.023136][ T5934] netdevsim netdevsim0 netdevsim3: renamed from eth3
[   83.050741][ T5934] bridge0: port 2(bridge_slave_1) entered blocking state
[   83.057927][ T5934] bridge0: port 2(bridge_slave_1) entered forwarding state
[   83.065345][ T5934] bridge0: port 1(bridge_slave_0) entered blocking state
[   83.072413][ T5934] bridge0: port 1(bridge_slave_0) entered forwarding state
[   83.120031][ T5934] 8021q: adding VLAN 0 to HW filter on device bond0
[   83.134601][   T13] bridge0: port 1(bridge_slave_0) entered disabled state
[   83.142944][   T13] bridge0: port 2(bridge_slave_1) entered disabled state
[   83.158979][ T5934] 8021q: adding VLAN 0 to HW filter on device team0
[   83.170550][   T13] bridge0: port 1(bridge_slave_0) entered blocking state
[   83.177700][   T13] bridge0: port 1(bridge_slave_0) entered forwarding state
[   83.190625][   T13] bridge0: port 2(bridge_slave_1) entered blocking state
[   83.197827][   T13] bridge0: port 2(bridge_slave_1) entered forwarding state
[   83.341329][ T5934] 8021q: adding VLAN 0 to HW filter on device batadv0
[   83.378958][ T5934] veth0_vlan: entered promiscuous mode
[   83.389241][ T5934] veth1_vlan: entered promiscuous mode
[   83.415371][ T5934] veth0_macvtap: entered promiscuous mode
[   83.427514][ T5934] veth1_macvtap: entered promiscuous mode
[   83.442500][ T5934] batman_adv: batadv0: Interface activated: batadv_slave_0
[   83.457848][ T5934] batman_adv: batadv0: Interface activated: batadv_slave_1
[   83.470032][   T13] netdevsim netdevsim0 netdevsim0: set [1, 0] type 2 family 0 port 6081 - 0
[   83.481273][   T13] netdevsim netdevsim0 netdevsim1: set [1, 0] type 2 family 0 port 6081 - 0
[   83.491068][ T1309] netdevsim netdevsim0 netdevsim2: set [1, 0] type 2 family 0 port 6081 - 0
[   83.503898][ T1309] netdevsim netdevsim0 netdevsim3: set [1, 0] type 2 family 0 port 6081 - 0
[   83.557255][   T13] wlan0: Created IBSS using preconfigured BSSID 50:50:50:50:50:50
[   83.570502][   T13] wlan0: Creating new IBSS network, BSSID 50:50:50:50:50:50
[   83.593580][ T4559] wlan1: Created IBSS using preconfigured BSSID 50:50:50:50:50:50
[   83.602431][ T4559] wlan1: Creating new IBSS network, BSSID 50:50:50:50:50:50
[   84.168287][ T4559] netdevsim netdevsim1 netdevsim3 (unregistering): unset [1, 0] type 2 family 0 port 6081 - 0
[   85.956893][ T4559] netdevsim netdevsim1 netdevsim2 (unregistering): unset [1, 0] type 2 family 0 port 6081 - 0
[   86.015502][ T4559] netdevsim netdevsim1 netdevsim1 (unregistering): unset [1, 0] type 2 family 0 port 6081 - 0
[   86.093966][ T4559] netdevsim netdevsim1 netdevsim0 (unregistering): unset [1, 0] type 2 family 0 port 6081 - 0
[   86.188820][ T4559] bridge_slave_1: left allmulticast mode
[   86.194577][ T4559] bridge_slave_1: left promiscuous mode
[   86.202899][ T4559] bridge0: port 2(bridge_slave_1) entered disabled state
[   86.214213][ T4559] bridge_slave_0: left allmulticast mode
[   86.220656][ T4559] bridge_slave_0: left promiscuous mode
[   86.226590][ T4559] bridge0: port 1(bridge_slave_0) entered disabled state
[   86.433971][ T4559] bond0 (unregistering): (slave bond_slave_0): Releasing backup interface
[   86.445424][ T4559] bond0 (unregistering): (slave bond_slave_1): Releasing backup interface
[   86.454915][ T4559] bond0 (unregistering): Released all slaves
[   86.751537][ T4559] hsr_slave_0: left promiscuous mode
[   86.759187][ T4559] hsr_slave_1: left promiscuous mode
[   86.765628][ T4559] batman_adv: batadv0: Interface deactivated: batadv_slave_0
[   86.773100][ T4559] batman_adv: batadv0: Removing interface: batadv_slave_0
[   86.782377][ T4559] batman_adv: batadv0: Interface deactivated: batadv_slave_1
[   86.790070][ T4559] batman_adv: batadv0: Removing interface: batadv_slave_1
[   86.810811][ T4559] veth1_macvtap: left promiscuous mode
[   86.816685][ T4559] veth0_macvtap: left promiscuous mode
[   86.822409][ T4559] veth1_vlan: left promiscuous mode
[   86.828558][ T4559] veth0_vlan: left promiscuous mode
[   87.103965][ T4559] team0 (unregistering): Port device team_slave_1 removed
[   87.133637][ T4559] team0 (unregistering): Port device team_slave_0 removed
[   87.695499][ T4559] netdevsim netdevsim0 netdevsim3 (unregistering): unset [1, 0] type 2 family 0 port 6081 - 0
[   87.754614][ T4559] netdevsim netdevsim0 netdevsim2 (unregistering): unset [1, 0] type 2 family 0 port 6081 - 0
[   87.833906][ T4559] netdevsim netdevsim0 netdevsim1 (unregistering): unset [1, 0] type 2 family 0 port 6081 - 0
[   87.903519][ T4559] netdevsim netdevsim0 netdevsim0 (unregistering): unset [1, 0] type 2 family 0 port 6081 - 0
[   88.019657][ T4559] bridge_slave_1: left allmulticast mode
[   88.026013][ T4559] bridge_slave_1: left promiscuous mode
[   88.031763][ T4559] bridge0: port 2(bridge_slave_1) entered disabled state
[   88.040560][ T4559] bridge_slave_0: left allmulticast mode
[   88.047223][ T4559] bridge_slave_0: left promiscuous mode
[   88.052958][ T4559] bridge0: port 1(bridge_slave_0) entered disabled state
[   88.234049][ T4559] bond0 (unregistering): (slave bond_slave_0): Releasing backup interface
[   88.244910][ T4559] bond0 (unregistering): (slave bond_slave_1): Releasing backup interface
[   88.254681][ T4559] bond0 (unregistering): Released all slaves
[   88.503276][ T4559] hsr_slave_0: left promiscuous mode
[   88.515190][ T4559] hsr_slave_1: left promiscuous mode
[   88.521144][ T4559] batman_adv: batadv0: Interface deactivated: batadv_slave_0
[   88.533055][ T4559] batman_adv: batadv0: Removing interface: batadv_slave_0
[   88.541418][ T4559] batman_adv: batadv0: Interface deactivated: batadv_slave_1
[   88.549624][ T4559] batman_adv: batadv0: Removing interface: batadv_slave_1
[   88.566813][ T4559] veth1_macvtap: left promiscuous mode
[   88.572380][ T4559] veth0_macvtap: left promiscuous mode
[   88.578459][ T4559] veth1_vlan: left promiscuous mode
[   88.583771][ T4559] veth0_vlan: left promiscuous mode
[   88.850925][ T4559] team0 (unregistering): Port device team_slave_1 removed
[   88.879924][ T4559] team0 (unregistering): Port device team_slave_0 removed


syzkaller build log:
go env (err=<nil>)
AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE='auto'
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/syzkaller/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/syzkaller/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build2311833903=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/syzkaller/jobs-2/linux/gopath/src/github.com/google/syzkaller/go.mod'
GOMODCACHE='/syzkaller/jobs-2/linux/gopath/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/syzkaller/jobs-2/linux/gopath'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/syzkaller/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.24.4'
GOWORK=''
PKG_CONFIG='pkg-config'

git status (err=<nil>)
HEAD detached at 004c195c04
nothing to commit, working tree clean


tput: No value for $TERM and no -T specified
tput: No value for $TERM and no -T specified
Makefile:31: run command via tools/syz-env for best compatibility, see:
Makefile:32: https://github.com/google/syzkaller/blob/master/docs/contributing.md#using-syz-env
go list -f '{{.Stale}}' -ldflags="-s -w -X github.com/google/syzkaller/prog.GitRevision=004c195c04b03dc0333690d4eef6f935ab80f739 -X github.com/google/syzkaller/prog.gitRevisionDate=20260128-101947"  ./sys/syz-sysgen | grep -q false || go install -ldflags="-s -w -X github.com/google/syzkaller/prog.GitRevision=004c195c04b03dc0333690d4eef6f935ab80f739 -X github.com/google/syzkaller/prog.gitRevisionDate=20260128-101947"  ./sys/syz-sysgen
make .descriptions
tput: No value for $TERM and no -T specified
tput: No value for $TERM and no -T specified
Makefile:31: run command via tools/syz-env for best compatibility, see:
Makefile:32: https://github.com/google/syzkaller/blob/master/docs/contributing.md#using-syz-env
bin/syz-sysgen
touch .descriptions
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -X github.com/google/syzkaller/prog.GitRevision=004c195c04b03dc0333690d4eef6f935ab80f739 -X github.com/google/syzkaller/prog.gitRevisionDate=20260128-101947"  -o ./bin/linux_amd64/syz-execprog github.com/google/syzkaller/tools/syz-execprog
mkdir -p ./bin/linux_amd64
g++ -o ./bin/linux_amd64/syz-executor executor/executor.cc \
	-m64 -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=16384 -Wno-stringop-overflow -Wno-array-bounds -Wno-format-overflow -Wno-unused-but-set-variable -Wno-unused-command-line-argument -static-pie -std=c++17 -I. -Iexecutor/_include   -DGOOS_linux=1 -DGOARCH_amd64=1 \
	-DHOSTGOOS_linux=1 -DGIT_REVISION=\"004c195c04b03dc0333690d4eef6f935ab80f739\"
/usr/bin/ld: /tmp/ccMi1lE0.o: in function `Connection::Connect(char const*, char const*)':
executor.cc:(.text._ZN10Connection7ConnectEPKcS1_[_ZN10Connection7ConnectEPKcS1_]+0x386): warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
./tools/check-syzos.sh 2>/dev/null


Error text is too large and was truncated, full error text is at:
https://syzkaller.appspot.com/x/error.txt?x=1676e25a580000


Tested on:

commit:         0499add8 Merge tag 'kvm-x86-fixes-6.19-rc1' of https:/..
git tree:       git://git.kernel.org/pub/scm/virt/kvm/kvm.git next
kernel config:  https://syzkaller.appspot.com/x/.config?x=3aec2f7e1730a8eb
dashboard link: https://syzkaller.appspot.com/bug?extid=33a04338019ac7e43a44
compiler:       gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44
patch:          https://syzkaller.appspot.com/x/patch.diff?x=15dae25a580000


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] KVM: guest_memfd: Always use order 0 when allocating for guest_memfd
       [not found] <cover.1770148108.git.ackerleytng@google.com>
@ 2026-02-03 22:50 ` Ackerley Tng
  2026-02-03 22:00   ` [syzbot] [kvm?] WARNING in kvm_gmem_fault_user_mapping syzbot
  2026-02-04 12:36   ` [PATCH 1/2] KVM: guest_memfd: Always use order 0 when allocating for guest_memfd Deepanshu Kartikey
  0 siblings, 2 replies; 4+ messages in thread
From: Ackerley Tng @ 2026-02-03 22:50 UTC (permalink / raw)
  To: syzbot+33a04338019ac7e43a44
  Cc: kartikey406, linux-kernel, syzkaller-bugs, Ackerley Tng

#syz test: git://git.kernel.org/pub/scm/virt/kvm/kvm.git next

filemap_{grab,get}_folio() and related functions, used since the early
stages of guest_memfd have determined the order of the folio to be
allocated by looking up mapping_min_folio_order(mapping). As identified by
syzbot, MADV_HUGEPAGE can be used to set the result of
mapping_min_folio_order() to a value greater than 0, leading to the
allocation of a huge page and subsequent WARNing.

Refactor the allocation code of guest_memfd to directly use
filemap_add_folio(), specifying an order of 0.

This refactoring replaces the original functionality where FGP_LOCK and
FGP_CREAT are requested. Opportunistically drop functionality provided by
FGP_ACCESSED. guest_memfd folios don't care about accessed flags because
guest_memfd memory is unevictable and there is no storage to write back to.

Reported-by: syzbot+33a04338019ac7e43a44@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=33a04338019ac7e43a44
Tested-by: syzbot+33a04338019ac7e43a44@syzkaller.appspotmail.com
Signed-off-by: Ackerley Tng <ackerleytng@google.com>
---
 virt/kvm/guest_memfd.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index fdaea3422c30..0c58f6aa5609 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -135,23 +135,35 @@ static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index)
 	/* TODO: Support huge pages. */
 	struct mempolicy *policy;
 	struct folio *folio;
+	gfp_t gfp;
+	int ret;

 	/*
 	 * Fast-path: See if folio is already present in mapping to avoid
 	 * policy_lookup.
 	 */
+repeat:
 	folio = __filemap_get_folio(inode->i_mapping, index,
 				    FGP_LOCK | FGP_ACCESSED, 0);
 	if (!IS_ERR(folio))
 		return folio;

+	gfp = mapping_gfp_mask(inode->i_mapping);
+
 	policy = mpol_shared_policy_lookup(&GMEM_I(inode)->policy, index);
-	folio = __filemap_get_folio_mpol(inode->i_mapping, index,
-					 FGP_LOCK | FGP_ACCESSED | FGP_CREAT,
-					 mapping_gfp_mask(inode->i_mapping), policy);
+	folio = filemap_alloc_folio(gfp, 0, policy);
 	mpol_cond_put(policy);
+	if (!folio)
+		return ERR_PTR(-ENOMEM);

-	return folio;
+	ret = filemap_add_folio(inode->i_mapping, folio, index, gfp);
+	if (ret)
+		folio_put(folio);
+
+	if (ret == -EEXIST)
+		goto repeat;
+
+	return ret ? ERR_PTR(ret) : folio;
 }

 static enum kvm_gfn_range_filter kvm_gmem_get_invalidate_filter(struct inode *inode)
--
2.53.0.rc2.204.g2597b5adb4-goog

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] KVM: guest_memfd: Always use order 0 when allocating for guest_memfd
  2026-02-03 22:50 ` [PATCH 1/2] KVM: guest_memfd: Always use order 0 when allocating for guest_memfd Ackerley Tng
  2026-02-03 22:00   ` [syzbot] [kvm?] WARNING in kvm_gmem_fault_user_mapping syzbot
@ 2026-02-04 12:36   ` Deepanshu Kartikey
  2026-02-04 16:30     ` Ackerley Tng
  1 sibling, 1 reply; 4+ messages in thread
From: Deepanshu Kartikey @ 2026-02-04 12:36 UTC (permalink / raw)
  To: Ackerley Tng; +Cc: syzbot+33a04338019ac7e43a44, linux-kernel, syzkaller-bugs

On Wed, Feb 4, 2026 at 4:21 AM Ackerley Tng <ackerleytng@google.com> wrote:
>
> #syz test: git://git.kernel.org/pub/scm/virt/kvm/kvm.git next
>
> filemap_{grab,get}_folio() and related functions, used since the early
> stages of guest_memfd have determined the order of the folio to be
> allocated by looking up mapping_min_folio_order(mapping). As identified by
> syzbot, MADV_HUGEPAGE can be used to set the result of
> mapping_min_folio_order() to a value greater than 0, leading to the
> allocation of a huge page and subsequent WARNing.
>
> Refactor the allocation code of guest_memfd to directly use
> filemap_add_folio(), specifying an order of 0.
>
> This refactoring replaces the original functionality where FGP_LOCK and
> FGP_CREAT are requested. Opportunistically drop functionality provided by
> FGP_ACCESSED. guest_memfd folios don't care about accessed flags because
> guest_memfd memory is unevictable and there is no storage to write back to.
>
> Reported-by: syzbot+33a04338019ac7e43a44@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=33a04338019ac7e43a44
> Tested-by: syzbot+33a04338019ac7e43a44@syzkaller.appspotmail.com
> Signed-off-by: Ackerley Tng <ackerleytng@google.com>
> ---
>  virt/kvm/guest_memfd.c | 20 ++++++++++++++++----
>  1 file changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
> index fdaea3422c30..0c58f6aa5609 100644
> --- a/virt/kvm/guest_memfd.c
> +++ b/virt/kvm/guest_memfd.c
> @@ -135,23 +135,35 @@ static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index)
>         /* TODO: Support huge pages. */
>         struct mempolicy *policy;
>         struct folio *folio;
> +       gfp_t gfp;
> +       int ret;
>
>         /*
>          * Fast-path: See if folio is already present in mapping to avoid
>          * policy_lookup.
>          */
> +repeat:
>         folio = __filemap_get_folio(inode->i_mapping, index,
>                                     FGP_LOCK | FGP_ACCESSED, 0);
>         if (!IS_ERR(folio))
>                 return folio;
>
> +       gfp = mapping_gfp_mask(inode->i_mapping);
> +
>         policy = mpol_shared_policy_lookup(&GMEM_I(inode)->policy, index);
> -       folio = __filemap_get_folio_mpol(inode->i_mapping, index,
> -                                        FGP_LOCK | FGP_ACCESSED | FGP_CREAT,
> -                                        mapping_gfp_mask(inode->i_mapping), policy);
> +       folio = filemap_alloc_folio(gfp, 0, policy);
>         mpol_cond_put(policy);

Hi Ackerley,

Thanks for working on this bug! I've been investigating the same issue
and have a concern about the fast-path in your patch.

In kvm_gmem_get_folio(), the fast-path returns any existing folio from
the page cache without checking if it's a large folio:

folio = __filemap_get_folio(inode->i_mapping, index,
    FGP_LOCK | FGP_ACCESSED, 0);
if (!IS_ERR(folio))
return folio;  // <-- No size check here

This means if a large folio was previously allocated (e.g., via
madvise(MADV_HUGEPAGE)), subsequent faults will find and return it
from the fast-path, still triggering the WARN_ON_ONCE at line 416 in
kvm_gmem_fault_user_mapping().

The issue is that while your patch prevents *new* large folio
allocations by hardcoding order=0 in filemap_alloc_folio(), it doesn't
handle large folios that already exist in the page cache.

Shouldn't we add a check for folio_test_large() on both the fast-path
and slow-path to ensure we reject large folios regardless of how they
were allocated? Something like:

folio = __filemap_get_folio(...);
if (!IS_ERR(folio))
goto check_folio;
// ... allocation code ...
check_folio:
if (folio_test_large(folio)) {
folio_unlock(folio);
folio_put(folio);
return ERR_PTR(-E2BIG);
}

Or am I missing something about how the page cache handles this case?

Thanks,
Deepanshu Kartikey

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] KVM: guest_memfd: Always use order 0 when allocating for guest_memfd
  2026-02-04 12:36   ` [PATCH 1/2] KVM: guest_memfd: Always use order 0 when allocating for guest_memfd Deepanshu Kartikey
@ 2026-02-04 16:30     ` Ackerley Tng
  0 siblings, 0 replies; 4+ messages in thread
From: Ackerley Tng @ 2026-02-04 16:30 UTC (permalink / raw)
  To: Deepanshu Kartikey
  Cc: syzbot+33a04338019ac7e43a44, linux-kernel, syzkaller-bugs

Deepanshu Kartikey <kartikey406@gmail.com> writes:

> On Wed, Feb 4, 2026 at 4:21 AM Ackerley Tng <ackerleytng@google.com> wrote:
>>
>> #syz test: git://git.kernel.org/pub/scm/virt/kvm/kvm.git next
>>
>> filemap_{grab,get}_folio() and related functions, used since the early
>> stages of guest_memfd have determined the order of the folio to be
>> allocated by looking up mapping_min_folio_order(mapping). As identified by
>> syzbot, MADV_HUGEPAGE can be used to set the result of
>> mapping_min_folio_order() to a value greater than 0, leading to the

I was wrong here, MADV_HUGEPAGE does not actually update mapping->flags
AFAICT, so it doesn't update the result of mapping_min_folio_order().

MADV_HUGEPAGE only operates on the VMA and doesn't update the mapping's
min or max order, which is a inode/mapping property.

>> allocation of a huge page and subsequent WARNing.
>>
>> Refactor the allocation code of guest_memfd to directly use
>> filemap_add_folio(), specifying an order of 0.
>>

This refactoring is not actually required, since IIUC guest_memfd never
tries to update mapping->flags, and so mapping_min_folio_order() and
mapping_max_folio_order() return the default of 0.

>> This refactoring replaces the original functionality where FGP_LOCK and
>> FGP_CREAT are requested. Opportunistically drop functionality provided by
>> FGP_ACCESSED. guest_memfd folios don't care about accessed flags because
>> guest_memfd memory is unevictable and there is no storage to write back to.
>>
>> Reported-by: syzbot+33a04338019ac7e43a44@syzkaller.appspotmail.com
>> Closes: https://syzkaller.appspot.com/bug?extid=33a04338019ac7e43a44
>> Tested-by: syzbot+33a04338019ac7e43a44@syzkaller.appspotmail.com
>> Signed-off-by: Ackerley Tng <ackerleytng@google.com>
>> ---
>>  virt/kvm/guest_memfd.c | 20 ++++++++++++++++----
>>  1 file changed, 16 insertions(+), 4 deletions(-)
>>
>> diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
>> index fdaea3422c30..0c58f6aa5609 100644
>> --- a/virt/kvm/guest_memfd.c
>> +++ b/virt/kvm/guest_memfd.c
>> @@ -135,23 +135,35 @@ static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index)
>>         /* TODO: Support huge pages. */
>>         struct mempolicy *policy;
>>         struct folio *folio;
>> +       gfp_t gfp;
>> +       int ret;
>>
>>         /*
>>          * Fast-path: See if folio is already present in mapping to avoid
>>          * policy_lookup.
>>          */
>> +repeat:
>>         folio = __filemap_get_folio(inode->i_mapping, index,
>>                                     FGP_LOCK | FGP_ACCESSED, 0);
>>         if (!IS_ERR(folio))
>>                 return folio;
>>
>> +       gfp = mapping_gfp_mask(inode->i_mapping);
>> +
>>         policy = mpol_shared_policy_lookup(&GMEM_I(inode)->policy, index);
>> -       folio = __filemap_get_folio_mpol(inode->i_mapping, index,
>> -                                        FGP_LOCK | FGP_ACCESSED | FGP_CREAT,
>> -                                        mapping_gfp_mask(inode->i_mapping), policy);
>> +       folio = filemap_alloc_folio(gfp, 0, policy);
>>         mpol_cond_put(policy);
>
> Hi Ackerley,
>
> Thanks for working on this bug! I've been investigating the same issue

Thank you for working on this bug too!

> and have a concern about the fast-path in your patch.
>
> In kvm_gmem_get_folio(), the fast-path returns any existing folio from
> the page cache without checking if it's a large folio:
>
> folio = __filemap_get_folio(inode->i_mapping, index,
>     FGP_LOCK | FGP_ACCESSED, 0);
> if (!IS_ERR(folio))
> return folio;  // <-- No size check here
>
> This means if a large folio was previously allocated (e.g., via

This is true, but I tried the above patch because back then I believed
that the filemap_add_folio() within the original
__filemap_get_folio_mpol() was the only place where folios get added to
the filemap.

I'm trying out another patch locally to disable khugepaged. I believe
the issue is that when MADV_HUGEPAGE is used on a guest_memfd vma, it
indirectly enabled khugepaged to work on guest_memfd folios, which we
don't want anyway.

I'm guessing now that the root cause is to disable khugepaged for
 guest_memfd, and I will be trying out a few options through the rest of
 today. My first thought was to set VM_NO_KHUGEPAGED (semantically
 suitable), but looks like it's triggering some hugetlb-related
 weirdness. I'm going to try VM_DONTEXPAND next.

Other notes: I trimmed the repro down by disabling calls 4, 5, 6, 9,
those are not necessary for repro. Calls 0, 1, 2, 3 is part of a regular
usage pattern of guest_memfd, so the uncommon usages are call 7
(MADV_HUGEPAGE) (likely culprit), or call 8. I believe call 8 is just
the trigger, since mlock() actually faults in the page to userspace
through gup.

> madvise(MADV_HUGEPAGE)), subsequent faults will find and return it

madvise(MADV_HUGEPAGE) does not allocate folios, it only marks the VMA
to allow huge pages

> from the fast-path, still triggering the WARN_ON_ONCE at line 416 in
> kvm_gmem_fault_user_mapping().
>
> The issue is that while your patch prevents *new* large folio
> allocations by hardcoding order=0 in filemap_alloc_folio(), it doesn't
> handle large folios that already exist in the page cache.
>
> Shouldn't we add a check for folio_test_large() on both the fast-path
> and slow-path to ensure we reject large folios regardless of how they
> were allocated? Something like:
>
> folio = __filemap_get_folio(...);
> if (!IS_ERR(folio))
> goto check_folio;
> // ... allocation code ...
> check_folio:
> if (folio_test_large(folio)) {
> folio_unlock(folio);
> folio_put(folio);
> return ERR_PTR(-E2BIG);

I saw your patch, I feel that returning -E2BIG doesn't address the root
cause of the issue.

> }
>
> Or am I missing something about how the page cache handles this case?
>
> Thanks,
> Deepanshu Kartikey

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-02-04 16:30 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <cover.1770148108.git.ackerleytng@google.com>
2026-02-03 22:50 ` [PATCH 1/2] KVM: guest_memfd: Always use order 0 when allocating for guest_memfd Ackerley Tng
2026-02-03 22:00   ` [syzbot] [kvm?] WARNING in kvm_gmem_fault_user_mapping syzbot
2026-02-04 12:36   ` [PATCH 1/2] KVM: guest_memfd: Always use order 0 when allocating for guest_memfd Deepanshu Kartikey
2026-02-04 16:30     ` Ackerley Tng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox