Yeni -C
seçenek tatminkar değildir, çünkü kullanım zamanı (TOCTTOU) yarış koşullarına açıktır. İki işlem aynı kuralı aynı anda eklemeye çalışırsa, -C
iki defa eklemelerini engellemez.
Yani, grep
çözümden gerçekten daha iyi değil . Çıktı üzerinden doğru bir metin işleme işi , bu çıktı tabloların durumunun güvenilir bir anlık görüntüsü olduğundan, o iptables-save
kadar güvenilir bir şekilde çalışabilir -C
.
İhtiyaç duyulan şey, --ensure
yalnızca zaten mevcut değilse, atomik olarak kontrol eden ve bir kural ekleyen bir seçenektir. Dahası, eğer kural mevcut değilse yeni bir kuralın ekleneceği doğru konuma getirildiyse iyi olurdu ( --ensure-move
). Örneğin iptables -I 1
, bir zincirin başında bir kural oluşturmak için kullanılıyorsa, ancak bu kural zaten yedinci konumda mevcutsa, mevcut kural ilk konuma taşınmalıdır.
Bu özellikler olmadan, uygulanabilir bir geçici çözümün bu sözde koda dayalı bir kabuk betiği döngüsü yazmak olduğunu düşünüyorum:
while true ; do
# delete all copies of the rule first
while copies_of_rule_exist ; do
iptables -D $RULE
done
# now try to add the rule
iptables -A $RULE # or -I
# At this point there may be duplicates due to races.
# Bail out of loop if there is exactly one, otherwise
# start again.
if exactly_one_copy_of_rule_exists ; then
break;
fi
done
Bu kod etrafta dönebilir; iki veya daha fazla yarışçının belirli sayıda tekrar içinde bulunacağını garanti etmez. Buna yardımcı olmak için bazı randomize üssel backoff uykuları eklenebilir.