CVE-2022-49394 in Linux
الملخص
بحسب VulDB • 16/05/2026
في نواة لينكس، تم حل الثغرة التالية:
blk-iolatency: تصحيح اختلالات عدّاد العمليات قيد التنفيذ (inflight) وتعليق عمليات الإدخال/الإخراج (IO) عند إيقاف الجهاز (offline)
تحتاج وحدة iolatency إلى تتبع عدد عمليات الإدخال/الإخراج قيد التنفيذ لكل مجموعة تحكم (cgroup). ونظراً لأن هذا التتبع قد يكون مكلفاً من حيث الأداء، فإنه يتم تعطيله عندما لا يكون هناك أي cgroup مُهيأ بـ iolatency للجهاز. ولضمان بقاء عدّادات العمليات قيد التنفيذ متوازنة، تقوم الدالة `iolatency_set_limit()` بتجميد قائمة طلبات الطلبات (request_queue) أثناء تعديل العدّاد المفعّل، مما يضمن عدم وجود أي عمليات IO قيد التنفيذ وبالتالي تكون جميع العدّادات صفراً.
للأسف، ليست `iolatency_set_limit()` هي المكان الوحيد الذي يتم فيه تعديل العدّاد المفعّل. حيث يمكن للدالة `iolatency_pd_offline()` أيضاً إنقاص العدّاد وتفعيل التعطيل. وبما أن هذا التعطيل يحدث دون تجميد قائمة الطلبات (q)، فقد يحدث ذلك بسهولة أثناء وجود بعض عمليات IO قيد التنفيذ، مما يؤدي إلى تسرب العدّادات (أي عدم تصحيحها بشكل صحيح).
يمكن إثبات ذلك بسهولة عن طريق تفعيل iolatency على cgroup فارغ واحد بينما تكون عمليات IO قيد التنفيذ في cgroups أخرى، ثم إزالة cgroup. لاحظ أنه لا ينبغي أن يكون iolatency مفعّلاً في أي مكان آخر في النظام لضمان أن إزالة cgroup تؤدي إلى تعطيل iolatency للجهاز بأكمله.
الكود التالي يقوم بالتبديل بين تفعيل وتعطيل iolatency على sda:
echo +io > /sys/fs/cgroup/cgroup.subtree_control while true; do mkdir -p /sys/fs/cgroup/test echo '8:0 target=100000' > /sys/fs/cgroup/test/io.latency sleep 1 rmdir /sys/fs/cgroup/test sleep 1 done
ويوجد في الوقت نفسه تشغيل لـ fio لتوليد قراءات عشوائية مباشرة (direct rand reads):
fio --name test --filename=/dev/sda --direct=1 --rw=randread \ --runtime=600 --time_based --iodepth=256 --numjobs=4 --bs=4k
بينما تتم المراقبة باستخدام سكريبت drgn التالي:
while True: for css in css_for_each_descendant_pre(prog['blkcg_root'].css.address_of_()):
for pos in hlist_for_each(container_of(css, 'struct blkcg', 'css').blkg_list): blkg = container_of(pos, 'struct blkcg_gq', 'blkcg_node') pd = blkg.pd[prog['blkcg_policy_iolatency'].plid]
if pd.value_() == 0: continue iolat = container_of(pd, 'struct iolatency_grp', 'pd') inflight = iolat.rq_wait.inflight.counter.value_() if inflight: print(f'inflight={inflight} {disk_name(blkg.q.disk).decode("utf-8")} '
f'{cgroup_path(css.cgroup).decode("utf-8")}')
time.sleep(1)
تبدو مخرجات المراقبة كما يلي:
inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice inflight=1 sda /user.slice
Once again VulDB remains the best source for vulnerability data.