From: Mingyu Wang <25181214217(a)stu.xidian.edu.cn>
Syzkaller fuzzer triggered a kernel panic via a WARNING in
drm_prime_destroy_file_private() due to a non-empty prime rb_tree.
The root cause is a complete lack of synchronization in the teardown
path. While the import path (drm_gem_prime_fd_to_handle) holds the
&file_priv->prime.lock during lookup and insertion, the deletion path
(drm_prime_remove_buf_handle) traverses and mutates both the 'handles'
and 'dmabufs' rb_trees without acquiring any mutex.
When multiple threads concurrently close GEM handles or interleave import
and close operations, the pointers and balance states of the rb_tree
nodes get corrupted. As a result, certain members are erased from one
tree but remain orphaned in the other. Upon process exit, the final
sanity check triggers the WARNING.
[ 448.919314][T19739] ------------[ cut here ]------------
[ 448.945387][T19739] WARNING: CPU: 0 PID: 19739 at drivers/gpu/drm/drm_prime.c:223 drm_prime_destroy_file_private+0x43/0x60
...
[ 449.056535][T19739] Call Trace:
[ 449.056544][T19739] <TASK>
[ 449.056553][T19739] drm_file_free.part.0+0x805/0xcf0
[ 449.056652][T19739] drm_close_helper.isra.0+0x183/0x1f0
[ 449.056677][T19739] drm_release+0x1ab/0x360
[ 449.056719][T19739] __fput+0x402/0xb50
[ 449.056783][T19739] task_work_run+0x16b/0x260
[ 449.056883][T19739] exit_to_user_mode_loop+0xf9/0x130
[ 449.056931][T19739] do_syscall_64+0x424/0xfa0
[ 449.056977][T19739] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 449.057268][T19739] </TASK>
[ 449.057295][T19739] Kernel panic - not syncing: kernel: panic_on_warn set ...
Fix this by acquiring the prime_fpriv->lock mutex around the rb_tree
lookup and erasure logic. To respect the locking rules and avoid potential
deadlocks with driver-specific memory cleanups, assign the target node to
a temporary pointer and defer the dma_buf_put() and kfree() operations
until after the mutex is safely dropped.
Fixes: ea2aa97ca37a ("drm/gem: Fix GEM handle release errors")
Cc: stable(a)vger.kernel.org
Signed-off-by: Mingyu Wang <25181214217(a)stu.xidian.edu.cn>
---
drivers/gpu/drm/drm_prime.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 9b44c78cd77f..26319c638e0f 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -190,6 +190,9 @@ void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
uint32_t handle)
{
struct rb_node *rb;
+ struct drm_prime_member *found = NULL;
+
+ mutex_lock(&prime_fpriv->lock);
rb = prime_fpriv->handles.rb_node;
while (rb) {
@@ -200,8 +203,7 @@ void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
rb_erase(&member->handle_rb, &prime_fpriv->handles);
rb_erase(&member->dmabuf_rb, &prime_fpriv->dmabufs);
- dma_buf_put(member->dma_buf);
- kfree(member);
+ found = member;
break;
} else if (member->handle < handle) {
rb = rb->rb_right;
@@ -209,6 +211,13 @@ void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
rb = rb->rb_left;
}
}
+ mutex_unlock(&prime_fpriv->lock);
+
+ /* Defer resource release outside the mutex to prevent deadlocks */
+ if (found) {
+ dma_buf_put(found->dma_buf);
+ kfree(found);
+ }
}
void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
--
2.34.1
When dumping IB contents from a hung job, amdgpu_devcoredump_format()
acquires the VM root PD's reservation lock via amdgpu_vm_lock_by_pasid()
and then, for each IB referenced by the job, calls amdgpu_bo_reserve()
on the BO that backs the IB. Both reservations are taken on
reservation_ww_class_mutex objects but neither uses a ww_acquire_ctx,
which trips lockdep:
WARNING: possible recursive locking detected
--------------------------------------------
kworker/u128:0 is trying to acquire lock:
ffff88838b16e1f0 (reservation_ww_class_mutex){+.+.}-{4:4},
at: amdgpu_devcoredump_format+0x1594/0x23f0 [amdgpu]
but task is already holding lock:
ffff8882f82681f0 (reservation_ww_class_mutex){+.+.}-{4:4},
at: amdgpu_devcoredump_format+0x1594/0x23f0 [amdgpu]
Possible unsafe locking scenario:
CPU0
----
lock(reservation_ww_class_mutex);
lock(reservation_ww_class_mutex);
*** DEADLOCK ***
May be due to missing lock nesting notation
Workqueue: events_unbound amdgpu_devcoredump_deferred_work [amdgpu]
Call Trace:
__ww_mutex_lock.constprop.0
ww_mutex_lock
amdgpu_bo_reserve
amdgpu_devcoredump_format+0x1594 [amdgpu]
amdgpu_devcoredump_deferred_work+0xea [amdgpu]
process_one_work
worker_thread
kthread
The two reservations are on different BOs in the captured trace, so the
splat is a lockdep-correctness warning, not an observed deadlock. It
becomes a real self-deadlock whenever the IB BO shares its dma_resv
with the root PD (the always-valid case, see
amdgpu_vm_is_bo_always_valid()): amdgpu_bo_reserve(abo) re-acquires the
same ww_mutex without a ticket and blocks forever.
With amdgpu.gpu_recovery=0 the timeout handler refires every ~2 s and
each invocation produces this splat, drowning the kernel ring buffer.
Fix it by collecting the per-IB BO references under the root PD's
reservation, then releasing the root before reserving each IB BO
individually. The walk over the VM mapping tree must remain under the
root lock (mappings can be torn down without it), but the actual
content copies do not need to nest inside it. Each per-IB reservation
is now an independent top-level acquire, eliminating the nested
ww_mutex.
The collect/release logic is factored out into two small helpers
(amdgpu_devcoredump_collect_ib_refs / amdgpu_devcoredump_release_ib_refs)
to keep the main function's indentation reasonable.
This also fixes a BO refcount leak in the original code: when
amdgpu_bo_reserve() failed, control jumped to free_ib_content without
running amdgpu_bo_unref(). In the new structure the per-IB BO refs
are released unconditionally in the cleanup helper.
Reproducer (~150 LoC libdrm_amdgpu): submit a single GFX IB containing
PACKET3_INDIRECT_BUFFER chained at GPU VA 0 and wait for the fence.
The TDR fires within ~10 s and the deferred coredump worker produces
the splat above on every invocation.
Fixes: 7b15fc2d1f1a ("drm/amdgpu: dump job ibs in the devcoredump")
Cc: stable(a)vger.kernel.org # 7.1
Signed-off-by: Mikhail Gavrilov <mikhail.v.gavrilov(a)gmail.com>
---
.../gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c | 147 +++++++++++++-----
1 file changed, 110 insertions(+), 37 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
index d386bc775d03..f6bb968de756 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
@@ -207,6 +207,72 @@ static void amdgpu_devcoredump_fw_info(struct amdgpu_device *adev,
}
}
+struct amdgpu_devcoredump_ib_ref {
+ struct amdgpu_bo *bo;
+ u64 offset;
+};
+
+/*
+ * Walk the VM's mapping tree under the root PD's reservation to obtain the BO
+ * that backs each IB and pin it with a refcount. The root PD reservation is
+ * dropped before this function returns; the caller can then reserve each IB
+ * BO individually without nesting ww_mutex acquires on
+ * reservation_ww_class_mutex.
+ *
+ * Returns an array of num_ibs entries (each ib_refs[i].bo may be NULL if its
+ * mapping was not found), or NULL on allocation failure / VM lookup failure.
+ * The caller must release the BO refs and free the array.
+ */
+static struct amdgpu_devcoredump_ib_ref *
+amdgpu_devcoredump_collect_ib_refs(struct amdgpu_device *adev,
+ struct amdgpu_coredump_info *coredump)
+{
+ struct amdgpu_devcoredump_ib_ref *ib_refs;
+ struct amdgpu_bo_va_mapping *mapping;
+ struct amdgpu_bo *root;
+ struct amdgpu_vm *vm;
+ u64 va_start;
+
+ ib_refs = kcalloc(coredump->num_ibs, sizeof(*ib_refs), GFP_KERNEL);
+ if (!ib_refs)
+ return NULL;
+
+ vm = amdgpu_vm_lock_by_pasid(adev, &root, coredump->pasid);
+ if (!vm) {
+ kfree(ib_refs);
+ return NULL;
+ }
+
+ for (int i = 0; i < coredump->num_ibs; i++) {
+ va_start = coredump->ibs[i].gpu_addr & AMDGPU_GMC_HOLE_MASK;
+ mapping = amdgpu_vm_bo_lookup_mapping(vm, va_start / AMDGPU_GPU_PAGE_SIZE);
+ if (!mapping)
+ continue;
+
+ ib_refs[i].bo = amdgpu_bo_ref(mapping->bo_va->base.bo);
+ ib_refs[i].offset = va_start -
+ mapping->start * AMDGPU_GPU_PAGE_SIZE;
+ }
+
+ amdgpu_bo_unreserve(root);
+ amdgpu_bo_unref(&root);
+
+ return ib_refs;
+}
+
+static void
+amdgpu_devcoredump_release_ib_refs(struct amdgpu_devcoredump_ib_ref *ib_refs,
+ int num_ibs)
+{
+ if (!ib_refs)
+ return;
+
+ for (int i = 0; i < num_ibs; i++)
+ if (ib_refs[i].bo)
+ amdgpu_bo_unref(&ib_refs[i].bo);
+ kfree(ib_refs);
+}
+
static ssize_t
amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_info *coredump)
{
@@ -214,13 +280,11 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
struct drm_printer p;
struct drm_print_iterator iter;
struct amdgpu_vm_fault_info *fault_info;
- struct amdgpu_bo_va_mapping *mapping;
struct amdgpu_ip_block *ip_block;
struct amdgpu_res_cursor cursor;
- struct amdgpu_bo *abo, *root;
- uint64_t va_start, offset;
+ struct amdgpu_bo *abo;
+ uint64_t offset;
struct amdgpu_ring *ring;
- struct amdgpu_vm *vm;
u32 *ib_content;
uint8_t *kptr;
int ver, i, j, r;
@@ -343,43 +407,52 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
drm_printf(&p, "VRAM is lost due to GPU reset!\n");
if (coredump->num_ibs) {
- /* Don't try to lookup the VM or map the BOs when calculating the
- * size required to store the devcoredump.
+ struct amdgpu_devcoredump_ib_ref *ib_refs = NULL;
+
+ /*
+ * Snapshot per-IB BO references under the root PD's reservation,
+ * then release the root before reserving each IB BO individually
+ * to copy its contents.
+ *
+ * Reserving an IB BO while the root PD is still reserved would
+ * be a nested ww_mutex acquire on reservation_ww_class_mutex
+ * without a ww_acquire_ctx, which trips lockdep's recursive-
+ * locking check and self-deadlocks for IB BOs that share their
+ * dma_resv with the root PD (always-valid BOs).
+ *
+ * Skip lookup/reservation entirely on the sizing pass: it does
+ * not write IB content, and the size estimate doesn't depend on
+ * whether the BOs are reachable.
*/
- if (sizing_pass)
- vm = NULL;
- else
- vm = amdgpu_vm_lock_by_pasid(adev, &root, coredump->pasid);
+ if (!sizing_pass)
+ ib_refs = amdgpu_devcoredump_collect_ib_refs(adev, coredump);
- for (int i = 0; i < coredump->num_ibs && (sizing_pass || vm); i++) {
+ for (int i = 0; i < coredump->num_ibs; i++) {
ib_content = kvmalloc_array(coredump->ibs[i].ib_size_dw, 4,
GFP_KERNEL);
if (!ib_content)
continue;
- /* vm=NULL can only happen when 'sizing_pass' is true. Skip to the
- * drm_printf() calls (ib_content doesn't need to be initialized
- * as its content won't be written anywhere).
- */
- if (!vm)
+ if (sizing_pass)
goto output_ib_content;
- va_start = coredump->ibs[i].gpu_addr & AMDGPU_GMC_HOLE_MASK;
- mapping = amdgpu_vm_bo_lookup_mapping(vm, va_start / AMDGPU_GPU_PAGE_SIZE);
- if (!mapping)
- goto free_ib_content;
+ if (!ib_refs || !ib_refs[i].bo)
+ goto output_ib_content;
+
+ abo = ib_refs[i].bo;
+ offset = ib_refs[i].offset;
- offset = va_start - (mapping->start * AMDGPU_GPU_PAGE_SIZE);
- abo = amdgpu_bo_ref(mapping->bo_va->base.bo);
r = amdgpu_bo_reserve(abo, false);
if (r)
- goto free_ib_content;
+ goto output_ib_content;
if (abo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) {
off = 0;
- if (abo->tbo.resource->mem_type != TTM_PL_VRAM)
- goto unreserve_abo;
+ if (abo->tbo.resource->mem_type != TTM_PL_VRAM) {
+ amdgpu_bo_unreserve(abo);
+ goto output_ib_content;
+ }
amdgpu_res_first(abo->tbo.resource, offset,
coredump->ibs[i].ib_size_dw * 4,
@@ -395,8 +468,10 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
r = ttm_bo_kmap(&abo->tbo, 0,
PFN_UP(abo->tbo.base.size),
&abo->kmap);
- if (r)
- goto unreserve_abo;
+ if (r) {
+ amdgpu_bo_unreserve(abo);
+ goto output_ib_content;
+ }
kptr = amdgpu_bo_kptr(abo);
kptr += offset;
@@ -406,21 +481,19 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
amdgpu_bo_kunmap(abo);
}
+ amdgpu_bo_unreserve(abo);
+
output_ib_content:
drm_printf(&p, "\nIB #%d 0x%llx %d dw\n",
i, coredump->ibs[i].gpu_addr, coredump->ibs[i].ib_size_dw);
- for (int j = 0; j < coredump->ibs[i].ib_size_dw; j++)
- drm_printf(&p, "0x%08x\n", ib_content[j]);
-unreserve_abo:
- if (vm)
- amdgpu_bo_unreserve(abo);
-free_ib_content:
+ if (!sizing_pass && ib_refs && ib_refs[i].bo) {
+ for (int j = 0; j < coredump->ibs[i].ib_size_dw; j++)
+ drm_printf(&p, "0x%08x\n", ib_content[j]);
+ }
kvfree(ib_content);
}
- if (vm) {
- amdgpu_bo_unreserve(root);
- amdgpu_bo_unref(&root);
- }
+
+ amdgpu_devcoredump_release_ib_refs(ib_refs, coredump->num_ibs);
}
return count - iter.remain;
--
2.54.0
In a world filled with hyper-realistic graphics and complex narratives, sometimes the most captivating experiences are the simplest. Enter Slither io, a game that takes the classic "snake" concept and injects it with a healthy dose of online multiplayer mayhem. If you've ever found yourself drawn to the addictive nature of growing a digital creature, or the thrill of outsmarting your opponents in a low-stakes, high-fun environment, then read on. This article will guide you through the basics of Slither io and offer some insights into how to master its charmingly straightforward gameplay.
What is Slither io? A Journey into the World of Glowing Serpents
Slither io is an online multiplayer arcade game where you control a vibrant, glowing snake. Your objective is deceptively simple: grow your snake by consuming glowing pellets scattered across the map, while avoiding collisions with other players. The twist? Unlike traditional snake games, touching another snake's body (not just its head) means instant demise. This core mechanic creates a dynamic and surprisingly strategic environment where even the smallest snake can take down the largest, given the right timing and tactical positioning. The game's accessibility, with its browser-based play and intuitive controls, makes it a perfect pick-up-and-play experience for anyone looking to unwind and have a little competitive fun.
The Dance of the Serpent: Understanding Slither io Gameplay
Getting started in Slither io is remarkably easy. Upon loading the game, you'll be prompted to enter a nickname. Once you're in, you'll find yourself as a small, brightly colored snake on a vast, dark arena filled with glowing food.
https://slitherio.onl
Movement: Your snake follows your mouse cursor. Simply move your mouse to guide your snake in the desired direction. There are no "up, down, left, right" keys – it's all about smooth, continuous movement.
Boosting: This is where the strategic element truly shines. By holding down the left mouse button (or spacebar), your snake will accelerate rapidly. While boosting allows you to quickly grab food or outmaneuver opponents, it comes at a cost: your snake will shrink slightly as it consumes a portion of its own mass to fuel the boost. Mastering when and where to boost is crucial for survival and growth.
Eating: The primary way to grow your snake is by consuming the colorful pellets scattered across the map. These pellets appear naturally and also drop from deceased snakes. Larger snakes leave behind more food, creating opportunities for smaller snakes to quickly bulk up.
Eliminating Opponents: The most satisfying (and often frustrating) part of Slither io is taking down other players. To do this, you need to trick another snake into colliding with your body. There are various tactics, such as circling an opponent, cutting them off, or using a well-timed boost to get in front of their head. When a snake dies, it explodes into a burst of highly nutritious pellets, ready for consumption.
Tips for Serpent Supremacy: Mastering the Arena
While the gameplay is simple, becoming a truly massive snake requires a blend of patience, observation, and clever tactics.
Patience is a Virtue: Don't rush into every engagement. As a small snake, your primary goal is to grow. Focus on consuming loose pellets and avoiding larger players.
The Art of the Boost: Use your boost wisely. It's excellent for escaping dangerous situations or quickly grabbing a cluster of food, but over-boosting will shrink you unnecessarily. Learn to anticipate where food will be and use short bursts to get there efficiently.
Circle of Life (and Death): Once you've grown to a respectable size, you can start to "circle" smaller snakes. By gradually enclosing them, you force them into a smaller and smaller space until they inevitably collide with your body.
Embrace the Edge: The edges of the map can be surprisingly safe, as fewer players tend to congregate there. It’s a good place to grow in relative peace during the early stages of your game.
Capitalize on Chaos: When a large snake dies, it creates a feeding frenzy. While it's tempting to dive in immediately, observe the situation. Often, other players will collide in their eagerness, leaving even more food for a patient observer.
Don't Be Afraid to Die: Seriously! Each death is a learning opportunity. Pay attention to how you were eliminated and try to avoid making the same mistake twice. The beauty of Slither io is that you can restart instantly and jump back into the action.
The Endless Dance: Why Slither io Remains Relevant
Slither io, available to play at Slither io, is more than just a casual game; it's a testament to the power of simple yet engaging mechanics. Its low barrier to entry, combined with surprisingly deep strategic possibilities, makes it a timeless classic. Whether you're looking for a quick break, a competitive outlet, or just a chance to unwind, embracing your inner serpent in the vibrant world of Slither io is an experience well worth trying. Go forth, consume, and dominate the leaderboard!
Introduction to Granny Horror Gameplay
Granny is one of the most popular horror games in the mobile gaming world. The game creates a tense atmosphere filled with darkness, fear, and unpredictable danger. Players wake up inside an old house and must find a way to escape before time runs out. Every sound can attract danger, and every room may hide useful tools or deadly traps. https://grannyfree.io/
The simple gameplay mechanics make Granny easy to understand, but the increasing tension keeps players engaged for hours. Horror fans enjoy the thrilling experience because every match feels different. Random item locations and unpredictable enemy movement create excitement in every playthrough.
The game combines stealth mechanics, puzzle-solving, and survival elements into a complete horror adventure. Players must stay quiet, move carefully, and think strategically to survive inside the terrifying house.
Dark Atmosphere and Immersive Horror Experience
Creepy Environment and Sound Design
One of the strongest features of Granny is the frightening atmosphere. The old house contains dark hallways, broken furniture, hidden basements, and mysterious locked doors. Every area creates tension and uncertainty.
The sound effects increase the horror experience dramatically. Footsteps, creaking floors, and sudden noises make every movement feel dangerous. Silence becomes just as terrifying as loud sounds because players never know where danger may appear next.
The visual design also supports the horror theme. Dim lighting and shadow-filled rooms create suspense throughout the game. Even simple exploration becomes stressful because danger may appear at any moment.
Fear Created Through Constant Pressure
Granny creates fear through pressure instead of excessive action. Players cannot fight freely or move carelessly. One wrong decision may lead to immediate failure. This constant danger keeps players focused and emotionally involved.
The limited time system adds more intensity. Players usually have only a few days to escape the house. Each failed attempt increases tension and forces players to learn from mistakes.
The combination of stealth and survival mechanics creates memorable horror moments that many players continue discussing online.
Survival Mechanics That Keep Players Engaged
Stealth Gameplay and Smart Movement
Stealth is the core mechanic of Granny. Running loudly or dropping objects may attract danger instantly. Players must crouch, hide under beds, and move slowly to avoid detection.
Different areas of the house require careful observation. Some floors create noise, while certain doors open slowly and loudly. Understanding the environment becomes essential for survival.
The game rewards patience and strategic thinking. Quick reactions help during emergencies, but long-term success depends on planning and observation.
Puzzle Solving and Exploration
Granny includes many puzzles that require exploration and logical thinking. Players must search for keys, tools, batteries, and hidden objects throughout the house.
Many items have multiple purposes. A hammer may remove wooden barriers, while a key may unlock important escape routes. Players need to remember item locations and manage resources efficiently.
The puzzles remain simple enough for beginners but challenging enough to maintain excitement. Exploration becomes rewarding because every discovered item may help progress toward freedom.
Different Escape Routes and Replay Value
Multiple Ways to Escape
One reason behind the popularity of Granny is the variety of escape methods. Players can unlock doors, repair vehicles, or discover secret routes hidden inside the house.
Different strategies create different experiences. Some players focus on quick escapes, while others explore every room carefully. This flexibility keeps the gameplay fresh over multiple sessions.
The hidden secrets encourage replayability. Many players return to discover alternative endings and hidden features that they missed during earlier attempts.
Difficulty Levels for All Players
Granny includes several difficulty settings that make the game accessible for different skill levels. Beginners can choose easier modes with fewer dangers, while experienced players can select harder difficulties for more intense gameplay.
Harder modes increase enemy speed, reduce available resources, and create additional challenges. These options allow players to customize the horror experience according to personal preference.
This adjustable difficulty system helps Granny appeal to both casual gamers and hardcore horror fans.
Why Granny Became Popular Worldwide
Simple Controls and Accessible Gameplay
Granny became successful partly because of its simple controls. Mobile players can easily learn movement, interaction, and hiding mechanics without complicated tutorials.
The accessibility allows players from many age groups to enjoy the game. Quick learning combined with intense horror creates an experience that remains entertaining from the first session.
The lightweight design also helps the game run smoothly on many devices, increasing global popularity.
Viral Content and Streaming Success
Many content creators helped Granny gain worldwide attention. Horror reactions, escape challenges, and gameplay videos became extremely popular on streaming platforms and social media.
The unpredictable gameplay creates entertaining reactions that viewers enjoy watching. Every scream, failed escape, or close encounter becomes exciting content for audiences.
Online communities continue sharing strategies, secrets, and challenge ideas related to Granny. This active fanbase helps maintain interest in the game years after release.
Advanced Tips for Better Survival
Learn Sound Management Techniques
Sound management is extremely important in Granny. Players should avoid throwing objects unnecessarily and close doors carefully whenever possible.
Listening carefully also provides valuable information. Enemy movement sounds may reveal safe paths or dangerous locations nearby.
Headphones improve the overall experience because directional sound helps players understand threats more accurately.
Memorize Important Locations
Successful players often memorize room layouts and item spawn locations. Fast navigation becomes critical during dangerous situations.
Important escape tools usually appear in random positions, but understanding the general map structure helps players search more efficiently.
Practice improves confidence and reduces panic during stressful moments.
Horror Elements That Make Granny Unique
Psychological Fear Instead of Constant Action
Unlike many action-heavy horror games, Granny focuses on psychological tension. Silence, uncertainty, and limited visibility create fear naturally.
Players spend much of the game anticipating danger instead of constantly fighting enemies. This slower pacing creates stronger emotional impact.
The feeling of helplessness increases immersion and makes every successful escape feel rewarding.
Minimalist Design With Strong Impact
Granny proves that simple design can still create powerful horror experiences. The game does not rely on advanced graphics or complex mechanics.
Instead, strong atmosphere, effective sound design, and intelligent pacing create memorable gameplay. This minimalist approach allows the horror elements to remain the main focus.
Many modern indie horror games use similar techniques inspired by the success of Granny.
Conclusion
Granny continues to attract horror fans because of intense survival gameplay, frightening atmosphere, and engaging escape mechanics. The combination of stealth, puzzles, and psychological horror creates a unique experience that remains entertaining even after multiple playthroughs.
Simple controls, multiple difficulty settings, and different escape routes make the game accessible for many players around the world. Whether players enjoy exploration, suspense, or strategic survival, Granny delivers a thrilling horror adventure filled with tension and excitement.
For anyone searching for a memorable horror game with challenging survival mechanics, Granny remains an excellent choice in the horror gaming genre.
In case MMIO size is bigger than 4G and peer2peer DMA goes
through host bridge, we trigger a code path that assigns the
total linked IOVA (which is greater than 4G) to mapped_len.
Previously, `mapped_len` was declared as 32-bit `unsigned int`.
When accumulating `size_t` lengths, this leads to a silent wrap-around.
This truncation causes truncated lengths to be passed to functions
like `fill_sg_entry()`.
Fix this by changing `mapped_len` to `size_t` (64-bit). While
at it, fix similar potential overflow issues in `calc_sg_nents`
by using `size_t` for `nents` and checking against `UINT_MAX`
and using `unsigned int` for the loop iterator in `fill_sg_entry`
to match.
Fixes: 3aa31a8bb11e ("dma-buf: provide phys_vec to scatter-gather mapping routine")
Cc: stable(a)vger.kernel.org
Cc: iommu(a)lists.linux.dev
Reviewed-by: Pranjal Shrivastava <praan(a)google.com>
Signed-off-by: David Hu <xuehaohu(a)google.com>
---
Changes in v3:
- Removed leftover sentence fragment from the commit message.
- Kept `nents = 0` initialization (previously stated as removed in the
v2 changelog) as it is strictly required for the `+=` accumulation
loop in `calc_sg_nents()`.
Changes in v2:
- Fixed 'IVOA' -> 'IOVA' typo and expanded commit message (Claude Bot).
- Added Reverse Xmas tree formatting (Pranjal).
- Folded in extra bounds checking for calc_sg_nents() (Pranjal).
- Folded in type consistency fix for fill_sg_entry() (Pranjal).
drivers/dma-buf/dma-buf-mapping.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index 794acff2546a..5bc769fc42ea 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c
@@ -10,7 +10,7 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
dma_addr_t addr)
{
unsigned int len, nents;
- int i;
+ unsigned int i;
nents = DIV_ROUND_UP(length, UINT_MAX);
for (i = 0; i < nents; i++) {
@@ -36,7 +36,7 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
struct phys_vec *phys_vec, size_t nr_ranges,
size_t size)
{
- unsigned int nents = 0;
+ size_t nents = 0;
size_t i;
if (!state || !dma_use_iova(state)) {
@@ -51,6 +51,9 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
nents = DIV_ROUND_UP(size, UINT_MAX);
}
+ if (nents > UINT_MAX)
+ return 0;
+
return nents;
}
@@ -95,9 +98,10 @@ struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
size_t nr_ranges, size_t size,
enum dma_data_direction dir)
{
- unsigned int nents, mapped_len = 0;
struct dma_buf_dma *dma;
struct scatterlist *sgl;
+ size_t mapped_len = 0;
+ unsigned int nents;
dma_addr_t addr;
size_t i;
int ret;
--
2.54.0.794.g4f17f83d09-goog
Once FD_ADD() returns, the fd is live in the file descriptor table
and a thread sharing that table can close() it before DMA_BUF_TRACE()
runs. The close drops the last reference, __fput() frees the dma_buf,
and the tracepoint then dereferences dmabuf to take dmabuf->name_lock
-- slab-use-after-free.
Split FD_ADD() back into get_unused_fd_flags() + fd_install() and
emit the tracepoint between them. While the fdtable slot is reserved
with a NULL file pointer, a racing close() returns -EBADF without
entering __fput(), so the dma_buf stays alive across the trace. Same
approach as commit 2d76319c4cbb ("dma-buf: fix UAF in dma_buf_put()
tracepoint").
This undoes the FD_ADD() conversion done in commit 34dfce523c90
("dma: convert dma_buf_fd() to FD_ADD()"); FD_ADD() has no place to
hook the tracepoint safely.
Reported-by: syzbot+7f4987d0afb97dd090cb(a)syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=7f4987d0afb97dd090cb
Fixes: 281a22631423 ("dma-buf: add some tracepoints to debug.")
Cc: stable(a)vger.kernel.org # 7.0.x
Signed-off-by: David Carlier <devnexen(a)gmail.com>
---
drivers/dma-buf/dma-buf.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 71f37544a5c6..d504c636dc29 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -792,9 +792,13 @@ int dma_buf_fd(struct dma_buf *dmabuf, int flags)
if (!dmabuf || !dmabuf->file)
return -EINVAL;
- fd = FD_ADD(flags, dmabuf->file);
+ fd = get_unused_fd_flags(flags);
+ if (fd < 0)
+ return fd;
+
DMA_BUF_TRACE(trace_dma_buf_fd, dmabuf, fd);
+ fd_install(fd, dmabuf->file);
return fd;
}
EXPORT_SYMBOL_NS_GPL(dma_buf_fd, "DMA_BUF");
--
2.53.0
Whatsapp: +33 754.090.961, How i buy Dispensary in Dubai, read full story .
Order the free ebook on Whatsapp: +33 754.090.961 of how i buy 70mg lyrica in #jeddah. For those wondering where to buy #THC vapes in UAE, it’s important to find a provider that values purity, potency, and customer confidentiality go on: https://uaetherapist.com/ the online drop.
I like spent my holiday In United Arab Emirates , the streets are amazing most in the night one day inside a uber the driver who take me from #Al_wahda ask me if he can play music i told him ‘’ YOU ARE WELCOME BRO ’’ then i heard 50cent in window shopper i get a small smile in the corner of my face. At that moment i don’t know why, suddenly i started to think about Coffee Sh0p how i can roll a split , but DAMMN MAN YOU ARE CLEAN OVER 3 YEARS!! You are in Dubai, is like Bahrain, as Saudi , like Oman it’s impossible to get a coffee shop here anyway you risk to go through huge problem with arabic country law !! I was saw my pregnant girlfiend who are waiting me at Charjah, my new work who permit me to travel as i want with my family all the life i have for , no man stay focus on your job in MANAMA ...
FOLLOW HAPPENED STORY ON Whatsapp: +33 754.090.961 and you will know where i bought THC gummies in Dubai.
Contacts:
Telegram: Go0dTherapist
Gmail: uaetherapist(a)gmail.com
Signal: addsilkroad.47
Whatsapp: https://whatsapp.com/channel/0029VbCcd6PLCoX7L05OeX3a
Tik Tok: https://vm.tiktok.com/ZS9R3Cn5sdvLu-YwLbv/https://uaetherapist.com/how-to-order/https://uaetherapist.com/shop/https://uaetherapist.com/faqs/https://uaetherapist.com/policies/https://uaetherapist.com/contact/
#uaetherapist.com
#uaetherapistdotcom
#dubaidispensary
#uaemedicated
Whatsapp: +33 754.090.961, How i buy Dispensary in Dubai, read full story .
Order the free ebook on Whatsapp: +33 754.090.961 of how i buy 70mg lyrica in #jeddah. For those wondering where to buy #THC vapes in UAE, it’s important to find a provider that values purity, potency, and customer confidentiality go on: https://uaetherapist.com/ the online drop.
I like spent my holiday In United Arab Emirates , the streets are amazing most in the night one day inside a uber the driver who take me from #Al_wahda ask me if he can play music i told him ‘’ YOU ARE WELCOME BRO ’’ then i heard 50cent in window shopper i get a small smile in the corner of my face. At that moment i don’t know why, suddenly i started to think about Coffee Sh0p how i can roll a split , but DAMMN MAN YOU ARE CLEAN OVER 3 YEARS!! You are in Dubai, is like Bahrain, as Saudi , like Oman it’s impossible to get a coffee shop here anyway you risk to go through huge problem with arabic country law !! I was saw my pregnant girlfiend who are waiting me at Charjah, my new work who permit me to travel as i want with my family all the life i have for , no man stay focus on your job in MANAMA ...
FOLLOW HAPPENED STORY ON Whatsapp: +33 754.090.961 and you will know where i bought THC gummies in Dubai.
Contacts:
Telegram: Go0dTherapist
Gmail: uaetherapist(a)gmail.com
Signal: addsilkroad.47
Whatsapp: https://whatsapp.com/channel/0029VbCcd6PLCoX7L05OeX3a
Tik Tok: https://vm.tiktok.com/ZS9R3Cn5sdvLu-YwLbv/https://uaetherapist.com/how-to-order/https://uaetherapist.com/shop/https://uaetherapist.com/faqs/https://uaetherapist.com/policies/https://uaetherapist.com/contact/
#uaetherapist.com
#uaetherapistdotcom
#dubaidispensary
#uaemedicated
Ever found yourself in a moment of boredom, scrolling aimlessly, and wishing for something simple yet utterly satisfying to engage your mind? Look no further than the delightful genre of slicing games, and specifically, the incredibly addictive Slice Master. These games offer a unique blend of precision, timing, and visual gratification, making them a perfect pick-up-and-play experience for anyone looking to unwind.
https://slicemasterfree.com
What is Slice Master, and Why Should You Try It?
At its core, Slice Master is a game about, well, slicing! Imagine a canvas filled with various shapes and objects, and your goal is to meticulously cut them into smaller, designated pieces using a virtual blade. It sounds deceptively simple, but the genius lies in its execution. The game's intuitive controls and satisfying physics make each slice feel impactful, and the challenge gradually increases, keeping you hooked.
Think of it as a digital meditation, where the act of carefully dissecting objects becomes a strangely calming and rewarding experience. The visual feedback of cleanly cut shapes, often accompanied by satisfying sound effects, creates a positive loop that encourages you to keep playing.
Getting Started: A Glimpse into the Gameplay
Playing Slice Master is incredibly straightforward, making it accessible to gamers of all ages and skill levels. Here's a basic rundown of what you can expect:
The Objective: Each level presents you with a set of objects. Your goal is to slice them into a specific number of smaller pieces, often along indicated lines or into particular shapes.
The Blade: You control a virtual blade, usually by dragging your finger or mouse across the screen. The key is to make smooth, precise movements to achieve clean cuts.
Precision is Key: Hitting the target lines perfectly often yields higher scores or unlocks bonus points. Messy cuts might mean restarting a section or losing points.
Varying Challenges: As you progress, you'll encounter different materials that require more careful slicing, moving objects, or even time limits, adding layers of complexity to the core mechanic.
Tips for Becoming a Slice Master
While the game is easy to pick up, mastering it requires a bit of finesse. Here are a few friendly tips to enhance your slicing skills:
Practice Makes Perfect: Don't be discouraged by imperfect cuts at first. The more you play, the better your hand-eye coordination and precision will become.
Observe the Target: Before you make your first cut, take a moment to analyze the object and the desired outcome. Visualize your cut path.
Smooth and Steady Wins the Race: Avoid jerky movements. A slow, deliberate drag of your blade is often more effective than a quick, frantic swipe.
Utilize the Edges: Sometimes, using the edges of the object as a guide for your cuts can help you achieve straighter and more accurate slices.
Don't Be Afraid to Restart: If a cut goes horribly wrong, many levels allow you to restart that particular segment. It's better to restart and achieve a perfect score than to muddle through with a subpar cut.
Conclusion: A Simple Joy
Slice Master and similar slicing games offer a delightful escape from the hustle and bustle of everyday life. Their uncomplicated yet engaging gameplay provides a sense of accomplishment and a unique form of digital satisfaction. Whether you have five minutes to spare or an hour to unwind, diving into the world of precise cuts and satisfying visuals is a worthwhile endeavor. So, grab your virtual blade and prepare to experience the quiet joy of becoming a true Slice Master!
The dma-buf pseudo filesystem dispenses S_ANON_INODE inodes via
alloc_anon_inode() but never sets SB_I_NOEXEC on its superblock.
Since commit 1e7ab6f67824 ("anon_inode: rework assertions") in 6.17,
path_noexec() warns on exactly that combination, so an mmap() on any
dma-buf fd trips the warning:
WARNING: CPU: 11 PID: 121813 at fs/exec.c:118 path_noexec+0x47/0x50
do_mmap+0x2b5/0x680
vm_mmap_pgoff+0x129/0x210
ksys_mmap_pgoff+0x177/0x240
__x64_sys_mmap+0x33/0x70
dma-bufs have no business being executable, which is the invariant
that the new assertion is enforcing. Set SB_I_NOEXEC. Also set
SB_I_NODEV, since the pseudo filesystem creates no device nodes.
Reproducer on a CONFIG_DEBUG_VFS=y kernel:
make -C tools/testing/selftests/dmabuf-heaps
sudo ./tools/testing/selftests/dmabuf-heaps/dmabuf-heap -t system
The selftest allocates from /dev/dma_heap/system and mmaps the
returned fd, which trips the warning without this patch.
Fixes: 1e7ab6f67824 ("anon_inode: rework assertions")
Cc: stable(a)vger.kernel.org
Reviewed-by: Christian Brauner (Amutable) <brauner(a)kernel.org>
Signed-off-by: John Hubbard <jhubbard(a)nvidia.com>
---
Changes since v1:
* Also set SB_I_NODEV (suggested by Christian Brauner).
* Added Christian Brauner's Reviewed-by tag (thanks!)
drivers/dma-buf/dma-buf.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 71f37544a5c6..ea1ddd4293b2 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -216,6 +216,8 @@ static int dma_buf_fs_init_context(struct fs_context *fc)
if (!ctx)
return -ENOMEM;
ctx->dops = &dma_buf_dentry_ops;
+ fc->s_iflags |= SB_I_NOEXEC;
+ fc->s_iflags |= SB_I_NODEV;
return 0;
}
base-commit: 6779b50faa562e6cca1aa6a4649a4d764c6c7e28
--
2.54.0