Cerita rakyat tentang programmer dan insinyur (bagian 3)





Bagian terakhir dari kumpulan cerita dari Internet tentang bagaimana bug terkadang memiliki manifestasi yang sangat luar biasa. Bagian satu , bagian dua .



SSH kecil yang (terkadang) tidak bisa



Ini adalah cerita tentang salah satu perburuan serangga paling menarik yang cukup beruntung untuk saya ikuti.



Di AdGear Technologies Inc., tempat saya bekerja, semuanya disimpan di SSH. Kami telah menggunakannya untuk pengelolaan, pemantauan, penerapan, pengumpulan log, bahkan untuk streaming langsung. Protokol ini kuat dan andal, memiliki prediktabilitas alat Unix asli, dan berfungsi dengan baik.



Tapi begitu surat tanpa waktu tertentu atau referensi tuan rumah memberi tahu kami bahwa protokol tidak berfungsi.



Waktu habis



Mesin di pusat data London kami mengalami error acak saat mengirim file log ke pusat data Montreal. Tugas ini dijalankan secara berkala dari Cron, dan kegagalannya terwujud seperti ini:



  • Email Cron melaporkan masalah dengan SSH.

    • Terkadang macet.
    • Terkadang keluar tanpa kesalahan batas waktu.
  • Dalam pemeriksaan kesehatan internal, Nagios memperingatkan adanya data yang hilang di Montreal.


Kami masuk ke mobil London, secara manual meluncurkan perintah pushdan berhasil. Kami menganggapnya sebagai masalah jaringan sementara.



Batas waktu



Tapi kecelakaan itu terus berulang secara acak. Sekali sehari, beberapa kali sehari, Jumat pagi, beberapa kali dalam satu jam. Jelas bahwa itu semakin buruk. Kami terus mendorong file secara manual sampai kami menemukan apa masalahnya.



Ada 17 lompatan antara London dan Montreal. Kami telah membuat profil penundaan dan kerugian paket. Ternyata 1-3% paket hilang dalam beberapa lompatan. Bersama dengan Departemen Operasi Pusat Data London, kami mengajukan pengubahan rute.



Saat warga London memeriksa informasi kehilangan paket, kami mulai mencari waktu tunggu acak dalam perjalanan dari London ke waktu tunggu keduaPusat data di Montreal. Lompatan pada rute ini berbeda, bukan yang kehilangan paket. Kami memutuskan bahwa kerugian bukanlah masalah utama, dan selain itu Londoners melaporkan bahwa mereka tidak dapat mereproduksi kehilangan paket atau batas waktu, dan semuanya tampak baik-baik saja di pihak mereka.



Wahyu



Saat meneruskan email Cron yang buruk secara manual, kami melihat pola yang menarik. File berhasil ditransfer dengan kecepatan tinggi, atau tidak ditransfer sama sekali dan digantung tepat waktu. Tidak ada kasus file berhasil diunduh dengan kecepatan rendah.



Dengan menghapus sebagian besar data dari persamaan, kami dapat membuat ulang skrip menggunakan SSH vanilla sederhana. Di pusat data London, server "SSH mtl-machine" baik segera menyelesaikan tugas atau macet dan tidak dapat membuat sambungan. Kejutan mulai tumbuh.



Kemana perginya paket?



Kami memeriksa konfigurasi dan sistem server SSH di Montreal tiga kali:



  • Server DNS merespons dengan cepat.
  • Zona pencarian DNS terbalik telah dinonaktifkan.
  • Jumlah maksimum koneksi klien cukup besar.
  • Kami tidak diserang.
  • Saluran tidak tersumbat.


Selain itu, bahkan jika ada yang tidak berfungsi, kami akan mengamati pembekuan saat bekerja dengan dua pusat data berbeda di Montreal. Selain itu, pusat data non-London kami berhasil berkomunikasi dengan Montreal. Artinya, masalah itu terkait dengan London.



Kami menjalankan tcpdump dan melihat paket-paketnya. Kami tertarik dengan dinamika umum dan data yang diperoleh menggunakan Pcaps dan dimuat ke Wireshark. Kami melihat tanda-tanda kehilangan paket dan transmisi ulang, tetapi semuanya minimal dan tidak perlu dikhawatirkan.



Kemudian kami menganalisis seluruh koneksi dalam situasi di mana komunikasi SSH berhasil dibuat, dan kemudian - koneksi dalam situasi di mana komunikasi SSH terhenti.



Ketika koneksi dari London ke Montreal macet, kami sampai pada kesimpulan berikut:



  • Membuat koneksi TCP berjalan lancar.
  • Informasi SSH layanan dikirim bolak-balik. Jika perlu, ada paket ack TCP normal.
  • Paket khusus dikirim dari London dan diterima di Montreal.
  • Paket yang sama dikirim ulang beberapa kali dari London dan diterima di Montreal.
  • Montreal tidak menjawab ini!


Tidak jelas mengapa Montreal tidak menanggapi (karena ini, London mengirim data lagi). Koneksi tergantung pada ini karena protokol Layer 4 menggantung. Yang lebih menarik adalah fakta bahwa jika Anda menghentikan pengiriman SSH berulang di London dan segera memulai ulang, maka itu akan berhasil. Dalam kasus ini, tcpdump menunjukkan bahwa Montreal menerima paket tersebut dan menanggapinya, dan pekerjaan dilanjutkan.



Pada klien SSH di London, kami mengaktifkan debugging verbose ( -vvv), dan setelah entri log ini, koneksi berhenti:



debug2: kex_parse_kexinit: first_kex_follows 0 
debug2: kex_parse_kexinit: reserved 0 
debug2: mac_setup: found hmac-md5
debug1: kex: server->client aes128-ctr hmac-md5 none
debug2: mac_setup: found hmac-md5
debug1: kex: client->server aes128-ctr hmac-md5 none
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP


Kami mencari di Google "SSH hang SSH2_MSG_KEX_DH_GEX_GROUP" dan mendapatkan banyak hasil, dari masalah Wi-Fi hingga bug TCP di Windows dan router buggy kehilangan fragmen TCP. Salah satu solusi untuk LAN adalah menghitung MSS jalur dan menetapkan nilai ini sebagai MTU di kedua ujung rute.



Saya terus menurunkan MTU di server London dari 1500 - itu tidak membantu sampai saya mencapai nilai ajaib 576. Setelah itu, SSH tidak hang lagi. Saya menjalankan skrip dengan loop SSH, dan jika saya mau, saya dapat menyebabkan batas waktu dengan mengembalikan MTU ke 1500, atau menghapusnya dengan menyetel 576. Sayangnya, ini adalah server iklan publik, dan menetapkan MTU 1500 secara global tidak akan menyelesaikan masalah. Namun, telah disebutkan di atas bahwa proses fragmentasi atau pemasangan kembali paket mungkin rusak di suatu tempat.



Mari kita kembali untuk memeriksa paket yang diterima dengan tcpdump: tidak ada tanda-tanda fragmentasi. Ukuran paket yang diterima sepenuhnya sesuai dengan ukuran paket yang dikirim. Jika sesuatu memecah paket pada byte 576+, maka sesuatu telah berhasil dipasang kembali.



Binar binar, bintang kurva



Saat saya masuk lebih dalam ke analisis, saya melihat paket dumps lengkap ( tcpdump -s 0 -X), bukan hanya header. Ketika membandingkan paket ajaib dari pengiriman yang berhasil dengan paket dari pengiriman yang gagal, saya hampir tidak menemukan perbedaan kecuali untuk header TCP / IP. Tetapi jelas bahwa ini adalah paket pertama pada koneksi TCP yang berisi cukup data untuk melewati tanda 576 byte. Semua paket sebelumnya jauh lebih kecil.



Membandingkan paket yang sama dari pengiriman yang gagal, dalam bentuk paket yang meninggalkan London dan datang ke Montreal, mata saya tertuju pada sesuatu. Untuk sesuatu yang halus, dan saya mengabaikannya karena kelelahan (saat itu Jumat larut malam). Tetapi setelah beberapa pembaruan dan perbandingan, saya tidak lagi membayangkan.



Ini adalah tampilan paket setelah meninggalkan London (dikurangi beberapa byte pertama yang mengidentifikasi alamat IP)
0x0040:  0b7c aecc 1774 b770 ad92 0000 00b7 6563  .|...t.p......ec
0x0050:  6468 2d73 6861 322d 6e69 7374 7032 3536  dh-sha2-nistp256
0x0060:  2c65 6364 682d 7368 6132 2d6e 6973 7470  ,ecdh-sha2-nistp
0x0070:  3338 342c 6563 6468 2d73 6861 322d 6e69  384,ecdh-sha2-ni
0x0080:  7374 7035 3231 2c64 6966 6669 652d 6865  stp521,diffie-he
0x0090:  6c6c 6d61 6e2d 6772 6f75 702d 6578 6368  llman-group-exch
0x00a0:  616e 6765 2d73 6861 3235 362c 6469 6666  ange-sha256,diff
0x00b0:  6965 2d68 656c 6c6d 616e 2d67 726f 7570  ie-hellman-group
0x00c0:  2d65 7863 6861 6e67 652d 7368 6131 2c64  -exchange-sha1,d
0x00d0:  6966 6669 652d 6865 6c6c 6d61 6e2d 6772  iffie-hellman-gr
0x00e0:  6f75 7031 342d 7368 6131 2c64 6966 6669  oup14-sha1,diffi
0x00f0:  652d 6865 6c6c 6d61 6e2d 6772 6f75 7031  e-hellman-group1
0x0100:  2d73 6861 3100 0000 2373 7368 2d72 7361  -sha1...#SSH-rsa
0x0110:  2c73 7368 2d64 7373 2c65 6364 7361 2d73  ,SSH-dss,ecdsa-s
0x0120:  6861 322d 6e69 7374 7032 3536 0000 009d  ha2-nistp256....
0x0130:  6165 7331 3238 2d63 7472 2c61 6573 3139  aes128-ctr,aes19
0x0140:  322d 6374 722c 6165 7332 3536 2d63 7472  2-ctr,aes256-ctr
0x0150:  2c61 7263 666f 7572 3235 362c 6172 6366  ,arcfour256,arcf
0x0160:  6f75 7231 3238 2c61 6573 3132 382d 6362  our128,aes128-cb
0x0170:  632c 3364 6573 2d63 6263 2c62 6c6f 7766  c,3des-cbc,blowf
0x0180:  6973 682d 6362 632c 6361 7374 3132 382d  ish-cbc,cast128-
0x0190:  6362 632c 6165 7331 3932 2d63 6263 2c61  cbc,aes192-cbc,a
0x01a0:  6573 3235 362d 6362 632c 6172 6366 6f75  es256-cbc,arcfou
0x01b0:  722c 7269 6a6e 6461 656c 2d63 6263 406c  r,rijndael-cbc@l
0x01c0:  7973 6174 6f72 2e6c 6975 2e73 6500 0000  ysator.liu.se...
0x01d0:  9d61 6573 3132 382d 6374 722c 6165 7331  .aes128-ctr,aes1
0x01e0:  3932 2d63 7472 2c61 6573 3235 362d 6374  92-ctr,aes256-ct
0x01f0:  722c 6172 6366 6f75 7232 3536 2c61 7263  r,arcfour256,arc
0x0200:  666f 7572 3132 382c 6165 7331 3238 2d63  four128,aes128-c
0x0210:  6263 2c33 6465 732d 6362 632c 626c 6f77  bc,3des-cbc,blow
0x0220:  6669 7368 2d63 6263 2c63 6173 7431 3238  fish-cbc,cast128
0x0230:  2d63 6263 2c61 6573 3139 322d 6362 632c  -cbc,aes192-cbc,
0x0240:  6165 7332 3536 2d63 6263 2c61 7263 666f  aes256-cbc,arcfo
0x0250:  7572 2c72 696a 6e64 6165 6c2d 6362 6340  ur,rijndael-cbc@
0x0260:  6c79 7361 746f 722e 6c69 752e 7365 0000  lysator.liu.se..
0x0270:  00a7 686d 6163 2d6d 6435 2c68 6d61 632d  ..hmac-md5,hmac-
0x0280:  7368 6131 2c75 6d61 632d 3634 406f 7065  sha1,umac-64@ope
0x0290:  6e73 7368 2e63 6f6d 2c68 6d61 632d 7368  nSSH.com,hmac-sh
0x02a0:  6132 2d32 3536 2c68 6d61 632d 7368 6132  a2-256,hmac-sha2
0x02b0:  2d32 3536 2d39 362c 686d 6163 2d73 6861  -256-96,hmac-sha
0x02c0:  322d 3531 322c 686d 6163 2d73 6861 322d  2-512,hmac-sha2-
0x02d0:  3531 322d 3936 2c68 6d61 632d 7269 7065  512-96,hmac-ripe
0x02e0:  6d64 3136 302c 686d 6163 2d72 6970 656d  md160,hmac-ripem
0x02f0:  6431 3630 406f 7065 6e73 7368 2e63 6f6d  d160@openSSH.com
0x0300:  2c68 6d61 632d 7368 6131 2d39 362c 686d  ,hmac-sha1-96,hm
0x0310:  6163 2d6d 6435 2d39 3600 0000 a768 6d61  ac-md5-96....hma
0x0320:  632d 6d64 352c 686d 6163 2d73 6861 312c  c-md5,hmac-sha1,
0x0330:  756d 6163 2d36 3440 6f70 656e 7373 682e  umac-64@openSSH.
0x0340:  636f 6d2c 686d 6163 2d73 6861 322d 3235  com,hmac-sha2-25
0x0350:  362c 686d 6163 2d73 6861 322d 3235 362d  6,hmac-sha2-256-
0x0360:  3936 2c68 6d61 632d 7368 6132 2d35 3132  96,hmac-sha2-512
0x0370:  2c68 6d61 632d 7368 6132 2d35 3132 2d39  ,hmac-sha2-512-9
0x0380:  362c 686d 6163 2d72 6970 656d 6431 3630  6,hmac-ripemd160
0x0390:  2c68 6d61 632d 7269 7065 6d64 3136 3040  ,hmac-ripemd160@
0x03a0:  6f70 656e 7373 682e 636f 6d2c 686d 6163  openSSH.com,hmac
0x03b0:  2d73 6861 312d 3936 2c68 6d61 632d 6d64  -sha1-96,hmac-md
0x03c0:  352d 3936 0000 0015 6e6f 6e65 2c7a 6c69  5-96....none,zli
0x03d0:  6240 6f70 656e 7373 682e 636f 6d00 0000  b@openSSH.com...
0x03e0:  156e 6f6e 652c 7a6c 6962 406f 7065 6e73  .none,zlib@opens
0x03f0:  7368 2e63 6f6d 0000 0000 0000 0000 0000  sh.com..........
0x0400:  0000 0000 0000 0000 0000 0000            ............




Dan beginilah tampilan paket yang sama ketika tiba di Montreal
0x0040:  0b7c aecc 1774 b770 ad92 0000 00b7 6563  .|...t.p......ec
0x0050:  6468 2d73 6861 322d 6e69 7374 7032 3536  dh-sha2-nistp256
0x0060:  2c65 6364 682d 7368 6132 2d6e 6973 7470  ,ecdh-sha2-nistp
0x0070:  3338 342c 6563 6468 2d73 6861 322d 6e69  384,ecdh-sha2-ni
0x0080:  7374 7035 3231 2c64 6966 6669 652d 6865  stp521,diffie-he
0x0090:  6c6c 6d61 6e2d 6772 6f75 702d 6578 6368  llman-group-exch
0x00a0:  616e 6765 2d73 6861 3235 362c 6469 6666  ange-sha256,diff
0x00b0:  6965 2d68 656c 6c6d 616e 2d67 726f 7570  ie-hellman-group
0x00c0:  2d65 7863 6861 6e67 652d 7368 6131 2c64  -exchange-sha1,d
0x00d0:  6966 6669 652d 6865 6c6c 6d61 6e2d 6772  iffie-hellman-gr
0x00e0:  6f75 7031 342d 7368 6131 2c64 6966 6669  oup14-sha1,diffi
0x00f0:  652d 6865 6c6c 6d61 6e2d 6772 6f75 7031  e-hellman-group1
0x0100:  2d73 6861 3100 0000 2373 7368 2d72 7361  -sha1...#SSH-rsa
0x0110:  2c73 7368 2d64 7373 2c65 6364 7361 2d73  ,SSH-dss,ecdsa-s
0x0120:  6861 322d 6e69 7374 7032 3536 0000 009d  ha2-nistp256....
0x0130:  6165 7331 3238 2d63 7472 2c61 6573 3139  aes128-ctr,aes19
0x0140:  322d 6374 722c 6165 7332 3536 2d63 7472  2-ctr,aes256-ctr
0x0150:  2c61 7263 666f 7572 3235 362c 6172 6366  ,arcfour256,arcf
0x0160:  6f75 7231 3238 2c61 6573 3132 382d 6362  our128,aes128-cb
0x0170:  632c 3364 6573 2d63 6263 2c62 6c6f 7766  c,3des-cbc,blowf
0x0180:  6973 682d 6362 632c 6361 7374 3132 382d  ish-cbc,cast128-
0x0190:  6362 632c 6165 7331 3932 2d63 6263 2c61  cbc,aes192-cbc,a
0x01a0:  6573 3235 362d 6362 632c 6172 6366 6f75  es256-cbc,arcfou
0x01b0:  722c 7269 6a6e 6461 656c 2d63 6263 406c  r,rijndael-cbc@l
0x01c0:  7973 6174 6f72 2e6c 6975 2e73 6500 0000  ysator.liu.se...
0x01d0:  9d61 6573 3132 382d 6374 722c 6165 7331  .aes128-ctr,aes1
0x01e0:  3932 2d63 7472 2c61 6573 3235 362d 6374  92-ctr,aes256-ct
0x01f0:  722c 6172 6366 6f75 7232 3536 2c61 7263  r,arcfour256,arc
0x0200:  666f 7572 3132 382c 6165 7331 3238 2d63  four128,aes128-c
0x0210:  6263 2c33 6465 732d 6362 632c 626c 6f77  bc,3des-cbc,blow
0x0220:  6669 7368 2d63 6263 2c63 6173 7431 3238  fish-cbc,cast128
0x0230:  2d63 6263 2c61 6573 3139 322d 6362 632c  -cbc,aes192-cbc,
0x0240:  6165 7332 3536 2d63 6263 2c61 7263 666f  aes256-cbc,arcfo
0x0250:  7572 2c72 696a 6e64 6165 6c2d 6362 7340  ur,rijndael-cbs@
0x0260:  6c79 7361 746f 722e 6c69 752e 7365 1000  lysator.liu.se..
0x0270:  00a7 686d 6163 2d6d 6435 2c68 6d61 732d  ..hmac-md5,hmas-
0x0280:  7368 6131 2c75 6d61 632d 3634 406f 7065  sha1,umac-64@ope
0x0290:  6e73 7368 2e63 6f6d 2c68 6d61 632d 7368  nSSH.com,hmac-sh
0x02a0:  6132 2d32 3536 2c68 6d61 632d 7368 7132  a2-256,hmac-shq2
0x02b0:  2d32 3536 2d39 362c 686d 6163 2d73 7861  -256-96,hmac-sxa
0x02c0:  322d 3531 322c 686d 6163 2d73 6861 322d  2-512,hmac-sha2-
0x02d0:  3531 322d 3936 2c68 6d61 632d 7269 7065  512-96,hmac-ripe
0x02e0:  6d64 3136 302c 686d 6163 2d72 6970 756d  md160,hmac-ripum
0x02f0:  6431 3630 406f 7065 6e73 7368 2e63 7f6d  d160@openSSH.c.m
0x0300:  2c68 6d61 632d 7368 6131 2d39 362c 786d  ,hmac-sha1-96,xm
0x0310:  6163 2d6d 6435 2d39 3600 0000 a768 7d61  ac-md5-96....h}a
0x0320:  632d 6d64 352c 686d 6163 2d73 6861 312c  c-md5,hmac-sha1,
0x0330:  756d 6163 2d36 3440 6f70 656e 7373 782e  umac-64@openssx.
0x0340:  636f 6d2c 686d 6163 2d73 6861 322d 3235  com,hmac-sha2-25
0x0350:  362c 686d 6163 2d73 6861 322d 3235 362d  6,hmac-sha2-256-
0x0360:  3936 2c68 6d61 632d 7368 6132 2d35 3132  96,hmac-sha2-512
0x0370:  2c68 6d61 632d 7368 6132 2d35 3132 3d39  ,hmac-sha2-512=9
0x0380:  362c 686d 6163 2d72 6970 656d 6431 3630  6,hmac-ripemd160
0x0390:  2c68 6d61 632d 7269 7065 6d64 3136 3040  ,hmac-ripemd160@
0x03a0:  6f70 656e 7373 682e 636f 6d2c 686d 7163  openSSH.com,hmqc
0x03b0:  2d73 6861 312d 3936 2c68 6d61 632d 7d64  -sha1-96,hmac-}d
0x03c0:  352d 3936 0000 0015 6e6f 6e65 2c7a 7c69  5-96....none,z|i
0x03d0:  6240 6f70 656e 7373 682e 636f 6d00 0000  b@openSSH.com...
0x03e0:  156e 6f6e 652c 7a6c 6962 406f 7065 6e73  .none,zlib@opens
0x03f0:  7368 2e63 6f6d 0000 0000 0000 0000 0000  sh.com..........
0x0400:  0000 0000 0000 0000 0000 0000            ............




Apakah kamu memperhatikan sesuatu? Jika tidak, tidak apa-apa. Anda dapat menyalin ke dalam dua jendela di editor teks dan dengan cepat beralih di antara keduanya untuk melihat perubahan simbol.



Baiklah. Ini bukan kehilangan paket, tetapi kerusakan paket! Sangat sedikit, kerusakan sangat bisa diprediksi. Pengamatan menarik:



  • Bagian awal dari paket (<576 byte) masih utuh.
  • Setiap byte 15 dari 16 rusak.
  • Kerusakannya bisa diprediksi. Semua hmenjadi x, semua cmenjadi s.


Anda mungkin sudah melihat tabel ASCII dan menyimpulkan bahwa satu bit macet pada nilainya 1. Beralih ke 1bit keempat dalam satu byte merusak huruf sebelumnya di sebelah kiri ke nilai di sebelah kanan.



Penyebab yang jelas dalam bidang pandang kami (server penerima NIC) tidak dapat dicurigai karena kegagalan memiliki pola (beberapa mesin London → beberapa pusat data dan mesin Montreal). Alasannya harus pada rute dan lebih dekat ke London.



Situasinya mulai masuk akal. Saya juga memperhatikan sedikit petunjuk dalam mode tcpdump verbose (tcp cksum bad), yang belum pernah saya perhatikan sebelumnya. Server Montreal menjatuhkan paket tingkat kernel ketika menyadari bahwa paket tersebut rusak dan tidak meneruskan paket tersebut ke daemon SSH di ruang pengguna. Kemudian London mengirim paket itu lagi, itu rusak lagi, dan Montreal secara diam-diam membuangnya. Dari sudut pandang SSH dan SSHd, koneksi macet. Dari sudut pandang tcpdump, tidak ada kerugian dan server Montreal mengabaikan datanya.



Kami melaporkan temuan kami ke Departemen Operasi Pusat Data London, dan dalam beberapa menit mereka mengubah rute keluar secara dramatis. Lompatan pertama dan sebagian besar lompatan berikutnya berbeda. Masalah pembekuan hilang.



Perbaikan larut malam Jumat bagus, karena di akhir pekan Anda bisa bersantai dan tidak memikirkan masalah dan dukungan :)



Dimana Wally?



Senang karena kami tidak lagi menderita masalah ini dan sistem kami mengejar, saya memutuskan untuk menemukan perangkat yang bertanggung jawab atas kerusakan paket ini.



Memperbarui rute London untuk mencegah lalu lintas keluar dari rute lama berarti saya tidak dapat mereproduksi masalah tersebut dengan mudah. Saya menemukan seorang teman di Montreal dengan mesin FreeBSD yang sesuai yang tersedia dari London melalui rute lama.



Saya ingin memastikan kerusakan dapat diprediksi bahkan tanpa adanya SSH. Saya mengelola ini dengan mudah dengan beberapa saluran pipa.



Di Montreal:



nc -l -p 4000 > /dev/null


Kemudian di London:



cat /dev/zero | nc mtl 4000


Mengingat faktor keacakan dan penyesuaian dalam siklus coba lagi, saya menerima beberapa paket yang menghilangkan keraguan tentang kesimpulan sebelumnya. Inilah bagian dari salah satu paket:



Kami baru saja mengirim paket nol
0x0210  .....
0x0220  0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0230  0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0240  0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0250  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x0260  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x0270  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x0280  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x0290  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x02a0  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x02b0  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x02c0  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x02d0  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x02e0  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x02f0  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x0300  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x0310  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x0320  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x0330  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x0340  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x0350  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x0360  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x0370  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x0380  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x0390  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x03a0  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x03b0  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x03c0  0000 0000 0000 0000 0000 0000 0000 1000 ................
0x03d0  0000 0000 0000 0000 0000 0000 0000 0000 ................
0x03e0  .....




Saat mereproduksi bug, saya perlu menemukan salah satu dari 17 lompatan tempat terjadinya kerusakan. Saya tidak bisa begitu saja menelepon penyedia semua cluster dan meminta mereka untuk memeriksa sistem mereka.



Saya memutuskan untuk melakukan ping ke setiap router secara berurutan, ini mungkin membantu. Menulis paket ICMP khusus yang cukup besar untuk melebihi batas aman 576 byte dan mengisinya dengan nol. Kemudian menggunakan paket-paket ini saya melakukan ping ke server Montreal dari London.



Paket kembali utuh.



Saya sudah mencoba setiap kombinasi kecepatan, konten, ukuran - tetapi tidak berhasil. Saya tidak menemukan kerusakan pada paket ping ICMP yang dikembalikan.



Di pipeline netcat, saya telah mengganti TCP dengan UDP. Sekali lagi, tidak ada kerusakan.



Itu membutuhkan TCP untuk mereproduksi kerusakan, dan TCP membutuhkan dua titik akhir yang berkomunikasi. Saya mencoba dengan sia-sia untuk mengetahui apakah semua router memiliki port TCP terbuka yang dapat saya hubungi secara langsung.



Tampaknya tidak mungkin untuk mengidentifikasi lompatan yang salah dari luar. Atau mungkinkah?



Cermin cermin di dinding



Untuk menentukan apakah kerusakan terjadi, salah satu dari skenario berikut harus digunakan:



  • Periksa paket di tujuan melalui node TCP yang berkomunikasi dengannya.

    • Bukan di ruang pengguna, di mana paket tidak akan dikirim jika terjadi kesalahan selama verifikasi checksum, tetapi periksa paket yang diterima untuk mengetahui adanya kerusakan menggunakan root dan tcpdump.
  • Menggunakan node TCP yang bertindak sebagai server gema dan mencerminkan kembali data yang diterima, periksa paket pada node pengirim.


Tiba-tiba ternyata titik pengukuran kedua tersedia bagi kami. Tidak tersedia secara langsung, namun tetap: dalam pendekatan pertama untuk memecahkan masalah, kami melihat bahwa klien SSH mengalami hang saat berkomunikasi dengan server SSH melalui lompatan yang merusak. Ini adalah sinyal pasif yang baik yang dapat digunakan untuk menggantikan sinyal "gema" yang aktif.



Dan dalam hal ini kami dapat dibantu oleh banyak server SSH terbuka di Internet.



Kami tidak memerlukan akun saat ini di server ini, kami hanya perlu memulai koneksi SSH, lihat apakah fase pertukaran sandi akan berhasil (dengan jumlah percobaan ulang yang wajar untuk memperhitungkan kerusakan yang tidak disengaja).



Rencananya adalah ini:



  • Gunakan alat nmap yang luar biasa dalam mode "IP acak" untuk menyusun daftar server SSH terbuka yang didistribusikan secara geografis.
  • :

    • , → .
    • N- → «».
    • telltale N- → «».
  • «» «».


Saya pikir ini: dalam jejak semua server "buruk", beberapa lompatan identik akan digunakan. Kami akan dapat mengisolasi hop yang mencurigakan dan mengidentifikasi hop yang digunakan dalam jejak server "baik". Dengan harapan satu atau dua orang akan tetap tinggal.



Setelah menghabiskan satu jam mengklasifikasikan server secara manual, saya berhenti menjelajahi data. Saya memiliki 16 server "buruk" dan 25 server "baik".



Langkah pertama adalah membuat daftar hop yang ditemukan di semua jejak server yang buruk. Setelah membersihkan daftar, saya menyadari bahwa saya bahkan tidak perlu membuka daftar yang "baik" untuk menghilangkan lompatan positif palsu. Orang jahat hanya memiliki satu lompatan yang sama.



Namun, ada dua penyedia sebelumnya: London → N hop upstream1 → Y hop upstream2.



Ini adalah lompatan Y pertama di upstream2, tepat di perbatasan antara upstream1 dan upstream2. Itu merusak paket TCP acak, yang menyebabkan banyak transmisi ulang dan, tergantung pada spesifikasi pertukaran data protokol, membekukan atau mengurangi volume transmisi.



Bersama dengan departemen operasi pusat data London, kami melacak alamat IP hop ini. Saya berharap bahwa melalui koneksi langsung mereka ke upstream1 akan memungkinkan untuk memaksa koreksi.



Melalui upstream1, saya menerima konfirmasi bahwa hop yang saya tentukan (yang pertama di upstream2) memiliki "kegagalan modul kontrol" internal yang memengaruhi BGP dan perutean antara dua jaringan internal. Mereka mengubah rute perangkat yang rusak dan mematikannya menunggu penggantian.



Filter musik rock



Saya membantu pengguna aplikasi audio streaming untuk mengatur pengalaman LAN. Pengguna hanya memainkan musik klasik, bukan musik rock. Sungguh. Musik klasik dialirkan dengan mulus, dan saat mencoba mengalirkan musik rock, koneksi terputus setelah beberapa menit.



Aplikasi menerima potongan audio, mengompresnya dengan codec kompresi lossless, lalu mengirim setiap potongan dalam paket UDP terpisah ke titik akhir. Jika memungkinkan, aplikasi mencoba menggunakan IPv6, karena lebih dapat diandalkan daripada lingkungan LAN, meskipun dapat bekerja melalui IPv4 jika perlu.



Setelah pencarian tanpa henti dan membosankan untuk penyebab masalah, akhirnya saya menemukan apa masalahnya. Entah bagaimana pengguna mengatur MTU ke 1200 byte di antarmuka jaringan. Dan IPv6 tidak akan secara otomatis memecah paket pada tingkat IP saat MTU di bawah 1280 byte, sehingga paket yang lebih besar tidak dapat dikirim. Aplikasi streaming akan mencoba mengirim paket audio yang lebih besar dari 1200 byte, menerima kesalahan, dan memutuskan sambungan.



Mengapa ini hanya terjadi pada musik rock? Itu mudah. Codec lossless menggunakan bitrate variabel, dan musik klasik dikompresi lebih baik daripada musik rock. Saat streaming klasik, audio secara konsisten dikompresi menjadi paket kurang dari 1.200 byte, dan paket musik rock secara acak melebihi ambang batas ini.



Pengguna tidak tahu mengapa MTU-nya berkurang, dia tidak membutuhkannya, jadi kami meningkatkan nilainya dan semuanya berfungsi dengan baik.



Gangguan Internet yang Menghilang Sendiri



Ketika saya masuk universitas pada tahun 1999, saya tinggal di asrama pelajar yang tua dan bobrok karena saya tidak mampu membeli yang lebih baik. Tapi setidaknya ada internet yang lumayan lumayan di hostel, yang belum tersebar luas di negara saya. Dan karena dilarang pindah gedung, kabel jaringan (masih koaksial) diceraikan menurut skema sementara. Mereka disembunyikan di balik langit-langit palsu di koridor dan ditarik melalui pintu ke kamar di mana mereka hanya berbaring di lantai. Putusnya komunikasi apa pun dapat mengarah pada fakta bahwa seluruh lantai dibiarkan tanpa jaringan. Sejak saya belajar di Fakultas Ilmu Komputer, saya dengan cepat dan tanpa sadar berubah menjadi seseorang di lantai saya yang sering memperbaiki pemadaman, meskipun saya tidak memiliki pengalaman sama sekali dengan jaringan.



Terkadang gangguan ada di pihak penyedia, terkadang masalah terkait dengan proxy kami, tetapi lebih sering daripada tidak seseorang hanya memutus beberapa kabel dan tidak memasukkan terminator ke dalamnya.



Suatu malam Internet mati, tetapi hanya untuk beberapa menit. Kemudian dia muncul kembali, jadi saya tidak terlalu memikirkannya. Tapi keesokan harinya interupsi singkat diulangi, dan pada hari ketiga juga. Biasanya terjadi sekitar 20 jam, waktu yang tepat melayang, dan terkadang tidak sama sekali. Tetapi setiap kali jaringan mati, telepon di tempat saya mulai berdering, dan orang-orang semakin kesal dengan gangguan yang berulang ini.



Karena setiap gangguan hanya berlangsung beberapa menit, saya tidak dapat menentukan lokasi tertentu sebelum jaringan muncul kembali. Saya mencoba untuk berlari melintasi lantai dan mengetuk semua pintu, menanyakan apakah seseorang telah mencabut kabel atau telah melakukan sesuatu dengannya, tetapi gagasan itu tidak membantu. Akhirnya saya memutuskan untuk menunggu interupsi harian dengan multimeter terpercaya saya di tangan. Dalam seminggu, saya mengeluarkan kamar demi kamar dari tersangka. Akhirnya, di salah satu kabel ruangan, saya melihat lonjakan resistansi selama gangguan lain.



Saya mengetuk, tetapi mereka tidak membukanya. Kastil itu terkunci. Tetapi jika tidak ada orang di ruangan yang melakukan sesuatu dengan komputer atau kabel, lalu mengapa sambungan terputus? Dan mengapa itu pulih? Keesokan harinya semuanya terjadi lagi, mereka tidak membuka pintu lagi. Saya memutuskan untuk benar-benar mematikan ruangan ini sehingga Internet akan berfungsi di lantai lainnya.



Keesokan paginya, penyewa kamar itu memberi tahu saya bahwa internet mereka tidak berfungsi. Saya pergi ke sana dan mengukur resistansi di semua kabel, memeriksa semua koneksi dan terminator. Semua kabel memiliki nol ohm, semuanya dalam urutan yang sempurna. Saya bertanya kepada pria itu apa yang dia lakukan tadi malam? Saya membaca buku teks sebelum ujian, tidak ada yang berhubungan dengan komputer, jawabnya. Saya memeriksa ulang semuanya untuk kedua dan ketiga kalinya, tetapi tidak menemukan masalah. Saya hampir menyerah, dan kemudian saya perhatikan: kabel diikat di bawah tempat tidur. Tentu saja inti tembaga dari kabel itu putus persis di tempat ini, tetapi dipegang erat oleh selubungnya sehingga, dalam kondisi normal, kontak tetap terjaga, sekalipun Anda duduk di atas ranjang. Tetapi ketika saya mulai mengayunkannya, kontaknya menghilang selama beberapa detik dengan setiap dorongan.



Anda sendiri dapat menebak apa yang terjadi di tempat tidur itu selama beberapa menit setiap malam, di balik pintu yang terkunci dan tanpa ada yang menjawab ketukan.



Cerita Mel



Pemrogram sejati menulis di Fortran



Ini mungkin terjadi sekarang, di era dekaden bir non-alkohol, kalkulator dan aplikasi "ramah pengguna", tetapi di Good Old Times, ketika istilah "perangkat lunak" terdengar lucu dan Komputer Nyata terbuat dari drum magnet dan tabung radio, Programmer Nyata menulis di kode mesin. Tidak di FORTRAN. Bukan di RATFOR. Bahkan tidak bahasa assembly. Dalam kode mesin. Pada bilangan heksadesimal yang nyata, tanpa hiasan, dan tidak dapat dipahami. Seperti itu. Beberapa generasi programmer telah tumbuh tanpa mengetahui tentang masa lalu yang gemilang ini, dan saya percaya bahwa saya harus mencoba menjembatani kesenjangan generasi dan berbicara tentang bagaimana Programmer Sejati menulis kode. Saya akan memanggilnya Mel karena itu namanya.



Saya bertemu Mel ketika saya mendapat pekerjaan di Royal McBee Computer Corp., anak perusahaan produsen mesin tik yang sekarang sudah tidak beroperasi. Perusahaan sedang membangun LGP-30 - komputer drum yang kecil dan murah (menurut standar saat ini) - dan baru saja mulai memproduksi RPC-4000, juga pada memori drum, jauh lebih baik, lebih besar dan lebih cepat. Inti magnet terlalu mahal, dan tidak dapat bertahan dalam persaingan (itulah sebabnya Anda belum pernah mendengar tentang perusahaan ini atau komputernya). Saya dipekerjakan untuk menulis kompiler FORTRAN untuk keajaiban baru ini, dan Mel adalah panduan saya untuk kemampuannya. Mel tidak menyetujui kompiler. “Apa gunanya sebuah program tidak dapat menulis ulang kodenya sendiri?” Tanyanya. Mel menulis program paling populer perusahaan dalam hex.Dia bekerja untuk LGP-30 dan bermain blackjack dengan pembeli potensial di pameran komputer. Itu selalu memberikan efek dramatis. Booth LGP-30 ditampilkan di setiap pameran dagang, dan vendor IBM berkumpul dan berbicara satu sama lain. Apakah itu membantu menjual komputer? Kami tidak pernah membahas masalah ini.



Tugas Mel adalah menulis ulang program blackjack untuk RPC-4000. (Porting? Apa itu?) Komputer baru memiliki skema pengalamatan satu-plus-satu: selain opcode dan alamat operan yang diperlukan, setiap instruksi mesin juga memiliki alamat kedua, yang menunjukkan di mana instruksi berikutnya ditulis pada drum magnet yang berputar ... Artinya, setelah setiap instruksi berjalan GO TO! Masukkan ini ke dalam pipa Pascal dan hisap.



Mel menyukai RPC-4000 karena dia bisa mengoptimalkan kodenya: menempatkan instruksi pada reel sehingga segera setelah selesai, yang kedua langsung berada di bawah "kepala baca" dan siap untuk dieksekusi segera. Untuk melakukan ini, sebuah program telah ditulis untuk mengoptimalkan assembler, tetapi Mel menolak untuk menggunakannya. "Anda tidak pernah tahu di mana ia akan meletakkan datanya," jelasnya, "jadi Anda harus menggunakan konstanta terpisah." Saya memahami inti dari kalimat ini jauh di kemudian hari. Karena Mel mengetahui nilai numerik dari semua kode operasi dan menetapkan alamatnya sendiri di memori drum, setiap instruksi yang dia tulis dapat dianggap sebagai konstanta numerik. Misalnya, dia dapat memilih instruksi “tambah” sebelumnya dan mengalikannya jika instruksi tersebut memiliki nilai numerik yang sesuai. Sangat sedikit orang yang dapat mengubah kodenya.Saya membandingkan program Mel yang dioptimalkan secara manual dengan kode yang sama yang telah diproses oleh assembler yang mengoptimalkan, dan kode Mel selalu berjalan lebih cepat. Faktanya adalah bahwa metode arsitektur bangunan top-down belum ditemukan, dan Mal tetap tidak akan menggunakannya. Pertama, dia menulis bagian dalam loop pemrogramannya sehingga mereka yang pertama mendapatkan alamat optimal pada reel. Dan assembler yang mengoptimalkan tidak mampu melakukan itu. Mel tidak pernah menulis loop waktu tertunda, bahkan ketika Flexowriter raksasa membutuhkan penundaan antara keluaran karakter. Mel hanya meletakkan instruksi pada reel sehingga ketika instruksi berikutnya harus dibaca, itu akan masukbahwa metode arsitektur top-down belum ditemukan, dan Mel tidak akan menggunakannya. Pertama, dia menulis bagian dalam loop pemrogramannya sehingga mereka yang pertama mendapatkan alamat optimal pada reel. Dan assembler yang mengoptimalkan tidak mampu melakukan itu. Mel tidak pernah menulis loop waktu tertunda, bahkan ketika Flexowriter raksasa membutuhkan penundaan antara keluaran karakter. Mel hanya meletakkan instruksi pada reel sehingga ketika instruksi berikutnya harus dibaca, itu akan masukbahwa metode arsitektur top-down belum ditemukan, dan Mal tetap tidak akan menggunakannya. Pertama, dia menulis bagian dalam loop pemrogramannya sehingga mereka yang pertama mendapatkan alamat optimal pada reel. Dan assembler yang mengoptimalkan tidak mampu melakukan itu. Mel tidak pernah menulis loop waktu tertunda, bahkan ketika Flexowriter raksasa membutuhkan penundaan antara keluaran karakter. Mel hanya meletakkan instruksi pada reel sehingga ketika instruksi berikutnya harus dibaca, itu akan masukbahkan ketika Flexowriter raksasa membutuhkan jeda antara keluaran karakter. Mel hanya meletakkan instruksi pada reel sehingga ketika instruksi berikutnya harus dibaca, itu akan masukbahkan ketika Flexowriter raksasa membutuhkan jeda antara keluaran karakter. Mel hanya meletakkan instruksi pada reel sehingga ketika instruksi berikutnya harus dibaca, itu akan masukmelewati kepala baca, dan drum harus membuat satu revolusi lagi untuk menemukannya. Mel menemukan istilah yang tak ada bandingannya untuk prosedur ini. Kata "optimal" (optimal) memiliki arti absolut, sekaligus "unik", sehingga dalam bahasa sehari-hari sering kali dibuat relatif: "kurang optimal" atau "kurang optimal" atau "tidak terlalu optimal". Mel menyebut tempat-tempat pada drum dengan jeda waktu terpanjang "paling pessimum" ( pessimum - kondisi lingkungan terburuk yang dapat ditoleransi oleh tubuh ).



Setelah menyelesaikan pengerjaan program blackjack dan menjalankannya (“Bahkan penginisialisasinya pun dioptimalkan,” ujarnya bangga), Mel menerima permintaan dari bagian penjualan untuk melakukan perubahan. Generator nomor acak yang elegan (dioptimalkan) bertanggung jawab untuk mengocok kartu dan menangani dari tumpukan dalam program. Dan sebagian tenaga penjual menganggapnya terlalu jujur, karena terkadang pembeli rugi. Mereka meminta Mel untuk mengubah program sehingga tombol sentuh di konsol dapat mengubah peluang pemain dan membiarkan pembeli menang. Mel menolak. Dia menganggapnya tidak jujur ​​- memang begitu - dan itu melanggar moralitas programmernya - memang begitu - jadi dia menolak untuk berpartisipasi. Mel dibujuk oleh kepala departemen penjualan, dan Big Boss, serta sesama programmer atas desakan Boss. Akhirnya Mel menyerah dan menulis kodenyatetapi apakah cheat tersebut memeriksa sebaliknya: ketika sakelar dinyalakan, program tersebut curang dan selalu menang. Mel senang dengan keputusannya. Dia mengklaim bahwa pikiran bawah sadarnya menunjukkan etika yang tidak terkendali dan dengan tegas menolak untuk memperbaiki program tersebut. Ketika Mel keluar dari perusahaan untuk mendapatkan penghasilan yang lebih tinggi, Bos Besar meminta saya untuk melihat kodenya dan memberi tahu saya apakah saya dapat menemukan validator dan mengubah cara kerjanya. Saya setuju dengan enggan.dapatkah saya menemukan modul verifikasi dan mengubah cara kerjanya. Saya setuju dengan enggan.dapatkah saya menemukan modul verifikasi dan mengubah cara kerjanya. Saya setuju dengan enggan.



Berurusan dengan kode Mel adalah petualangan nyata. Seringkali bagi saya pemrograman adalah sebuah bentuk seni yang nilai riilnya hanya dapat diapresiasi oleh mereka yang memahami seni misterius ini. Ini berisi permata nyata dan gerakan brilian, tersembunyi dari pandangan manusia dan kekaguman oleh sifat prosesnya, terkadang selamanya. Anda dapat belajar banyak tentang seseorang hanya dengan membaca kode mereka, bahkan heksadesimal. Saya pikir Mel adalah seorang jenius yang tidak dikenal. Mungkin kejutan paling kuat adalah siklus tidak bersalah yang saya temukan, di mana tidak ada verifikasi yang curang. Tidak ada verifikasi. Tidak .



Akal sehat menentukan bahwa ini harus menjadi loop tertutup, di mana program bersirkulasi, selamanya, tanpa henti. Namun, kontrol perangkat lunak berhasil melewatinya dan keluar dengan aman di sisi lain. Aku butuh waktu dua minggu untuk memikirkannya. RPC-4000 dilengkapi dengan perangkat modern - register indeks. Itu memungkinkan penulisan loop program, di dalamnya instruksi yang diindeks digunakan. Setiap kali melewati loop, nomor dari register ditambahkan ke alamat instruksi sehingga merujuk ke posisi berikutnya dalam rangkaian. Yang tersisa hanyalah menaikkan register indeks dengan setiap pass. Mel tidak memanfaatkan ini. Sebagai gantinya, dia menarik instruksi ke register mesin, menambahkan satu ke alamatnya, dan menyimpannya kembali. Dan kemudian menjalankan instruksi yang dimodifikasi langsung dari register.Siklus ditulis dengan mempertimbangkan waktu eksekusi tambahan: segera setelah instruksi diselesaikan, siklus berikutnya muncul di bawah kepala baca drum. Tapi tidak ada pemeriksaan nakal dalam pengulangan. Petunjuk penyimpanannya adalah bahwa sedikit di register indeks dihidupkan - itu terletak di kode perintah antara alamat dan kode operasi. Namun, Mel tidak menggunakan register indeks, meninggalkannya di nol.



Ketika pencerahan saya datang, saya hampir menjadi buta. Data yang dia kerjakan mendekati memori tingkat tinggi - alamat terbesar yang dapat dirujuk instruksi - Mel diatur sehingga setelah posisi terakhir diproses, menambah alamat instruksi akan menyebabkan luapan. Selama transfer, seseorang telah ditambahkan ke kode operasi, mengubahnya menjadi kode berikut di set: instruksi lompat. Tentu saja, instruksi selanjutnya ini terletak di alamat nol, dan program dengan senang hati pergi ke sana. Saya belum berbicara dengan Mel dan saya tidak tahu apakah dia menyerah menghadapi banjir perubahan yang membanjiri program sejak saat itu. Saya lebih suka berpikir saya tidak menyerah. Saya sangat terkesan sehingga saya berhenti mencari cek cheat dan memberi tahu Big Boss bahwa saya tidak dapat menemukannya. Dia tidak terkejut. Saat saya keluar dari perusahaanprogram blackjack masih curang jika tombol kanan dihidupkan, dan memang demikian, saya kira. Saya tidak suka meretas kode Programmer Nyata.



Masalah USB yang luar biasa



Setelah lulus kuliah, saya bergabung dengan sebuah perusahaan dan mengerjakan perangkat konsumen selama lima bulan sebelum diperlihatkan kepada publik. Perangkat menjalankan Linux. Dan sementara saya terbiasa dengan gagasan memanjakan di ruang kernel, saya ditarik ke pertemuan untuk memprioritaskan bug. Banyak bug. Ratusan serangga. Masing-masing berbunyi: "Ini tidak mungkin, bagaimana ini bisa terjadi?"



Mereka berteriak: "Memori rusak!" Saya pikir, "Hospadi, perbaiki bug Anda." Melihat tempat pembuangan sampah, kami melihat ... apa itu? Program mengeksekusi instruksi terlarang dengan menggabungkan dua string menggunakan fungsi dari pustaka standar. Hmm, aneh ... Log berikutnya: Tidak dapat mengambil halaman dari file halaman di perangkat yang tidak memiliki ruang file halaman yang dialokasikan sama sekali (Saya rasa saya mengerti mengapa kami tidak dapat mengambil halaman!).



Saya pernah menulis program pendek. Ini mengalokasikan 80% dari memori sistem ke array tunggal dan menulis bilangan bulat berurutan untuk itu. Kemudian saya menunggu Enter ditekan dan diperiksa untuk melihat apakah isi dari array telah berubah. Sekarang saya mengunduh program ini, menunggu 30 detik dan kemudian menjalankan pemeriksaan. Tidak masalah. Saya mencoba beberapa kali lagi - ha, saya tahu tidak ada kerusakan memori! Saya mencabut kabel debug (USB), setelah 10 detik saya dengan cepat memasukkan dan mencabut, lalu memasukkan kembali. Bam! 90 kesalahan.



Milikmu.



Oke, saya harus mengutak-atik port USB. Jadi masalahnya ada hubungannya dengan dia? Driver USB tampaknya tidak menerapkan algoritma peri bit ajaib yang secara acak melempar kesalahan bit. Mungkin ada masalah dengan perangkat kerasnya? Tidak, tidak dengan dia, tapi itu tidak menghentikan kami untuk melakukan segala macam kecurangan dengan port USB. Mereka memanggil insinyur yang telah lama beralih ke produk lain, dan sekarang mereka sedang memikirkan masalahnya. Saya tidak ingat berapa banyak waktu yang kami habiskan untuk membuktikan kepada diri kami sendiri bahwa perangkat keras itu dalam urutan yang lengkap, lengkap, oooooo. Pembumiannya teratur, voltase stabil, jam berjalan akurat, dan saluran DDR begitu sempurna sehingga Anda pasti akan menangis bahagia saat melihatnya.



Perangkat yang diuji oleh para insinyur menjadi semakin tidak stabil. Saya berasumsi bahwa mesin dapat memuat data ke dalam memori, mendapatkan kesalahan bit, dan kemudian membuangnya kembali ke memori flash, bahkan mungkin di tempat yang salah (tabel halaman sering rusak, jadi dapat diasumsikan bahwa ini juga terjadi dengan struktur pelacakan file Konten dapat ditulis ke tempat yang salah, dan struktur sistem file dapat rusak, dll.) Seiring waktu, perangkat sangat terdegradasi sehingga tidak dapat lagi melakukan boot dengan andal. Akhirnya, salah satu teknisi merusak dan menimpa gambar yang ada di laptopnya. Gambar ini relatif kuno.



- Bung. Ini tentang perangkat lunak.



- Apa?!?!?! Saya jamin kami tidak menulis sedikit peri!



Tidak: dia mengunggah perakitan tiga bulan lalu dan masalahnya hilang. Pada saat itu, saya merasa bertanggung jawab karena telah melibatkan banyak orang dalam usaha yang sangat lama dan tidak berarti, jadi saya menginap dan melakukan pencarian biner di semua patch selama beberapa bulan terakhir (butuh lebih banyak waktu untuk mempelajari rakitan lengkap dari keseluruhan OS daripada yang saya inginkan. ...).



Jadi, tambalan ajaib apa itu? Seseorang menambahkan driver untuk chip yang kami analisis ke kernel. Chip ini tidak ada di perangkat.



Ha! Kami menemukan penyihir! BAKAR ITU!



Banyak yang mengumumkan bahwa masalah telah terpecahkan. Mereka senang bahwa di rilis berikutnya mereka dapat memutar kembali tambalan dan melanjutkan. Kami memutarnya kembali dengan sangat pemilih, mengumpulkan gambar, mengujinya, semuanya baik-baik saja. Kami tidak mengharapkan cacat yang sama muncul di nukleus dalam beberapa hari.



Tunggu. Jika chip tidak ada di papan, bagaimana pengemudi mencegah kami? Saya menjalankan lsmod, driver tidak dimuat ... “Pokoknya apa bedanya, hapus file modulnya dan muat ulang. Nifiga, masalahnya tetap ada. Ini tidak normal ... "



Sekarang saya sendirian dan menyaksikan kejahatan terjadi. Saya mulai menganalisis tambalan dengan hati-hati. Itu adalah file baris C 10K bagus yang disediakan oleh produsen chip. Akan terlalu merendahkan untuk menggambarkannya dengan kata "chaos" (dalam keadilan, setelah beberapa minggu mereka mengirimi kami pengemudi yang jauh lebih bijaksana). Setelah menggali sedikit, saya memutuskan bahwa bit-juggling-for-fun tidak diterapkan pada pengemudi. Jadi apa masalahnya? 48 byte dari lima baris kode. Sebuah struktur kecil di file boot yang mengatakan alamat bus mana yang akan dicari chipnya. Saya menghapus sebagian besar driver, tetapi meninggalkan struktur yang berbeda di dalamnya. Masalahnya belum hilang.



Jadi anak laki-laki dan perempuan, kita memiliki masalah kesejajaran! Entah bagaimana struktur 48-byte ini memindahkan sesuatu dalam memori dan menyebabkan kesalahan. Saya menemukan bahwa masalah terjadi ketika Anda memasukkan sesuatu yang lebih besar dari 32 dan kurang dari 64 byte dalam sebuah file. Pengetahuan ini tidak banyak membantu, tetapi setidaknya menciptakan rasa kemajuan.



Kompilasi kernel menghasilkan file System.map yang rapi. Ini terdaftar di mana semua variabel yang dikompilasi di kernel berada di ruang alamat virtual kernel. Saya menemukan bahwa struktur kecil saya ada di tengah-tengah bagian ".data". Bagian ini diisi dengan variabel yang diinisialisasi, sehingga ketika biner kernel diurai ke dalam memori, ia akan menulis semua variabel tersebut dari gambar yang dikompilasi. Menggunakan System.map sebagai referensi, saya telah menerapkan pencarian biner yang agak konyol. Untuk sebagian besar saya mencari linker dari file C yang berbeda. Saya menemukan variabel untuk dibandingkan; menemukan file kernel yang berisi itu; letakkan struktur ajaib saya di samping saya dalam file acak dan mulai melihat apakah masalahnya muncul kembali.



Pencarian dilanjutkan ke beberapa elemen .data terakhir dan kembali dengan tangan kosong. Tidak ada data yang diperlukan dalam memori dengan variabel yang diinisialisasi. Saat saya menelusuri file System.map, saya melihat bahwa saya tidak memperhatikan keseluruhan bagian .bss, yang berisi variabel yang tidak diinisialisasi. Belajar dari kesalahan masa lalu, pertama saya memeriksa awal dan akhir. Tentu saja, variabel yang tidak diinisialisasi di awal bagian menghasilkan kesalahan, sedangkan variabel di akhir bagian tidak. Menemukan pelakunya hanya masalah waktu. Variabel yang gerakannya menyebabkan masalah adalah ...



Penunjuk fungsi?!



Bagaimana sih fungsi pointer alignment merusak sistem kita? Dalam arsitektur ARM, Anda tidak dapat membaca kata-kata saat mengakses tanpa penyelarasan, artinya, setiap variabel 32-bit harus dimasukkan ke dalam memori pada alamat yang kelipatan 4. Tidak terkecuali penunjuk fungsi, yang selalu mendapat alamat minimum. Ternyata dalam situasi masalah kami, alamatnya adalah kelipatan 2 n , lebih besar dari atau sama dengan 64. Nilai apa pun yang kurang dari ambang batas ini - dan masalah hilang. Ada juga urutan dengan penunjuk arah.



Tidak ada keselarasan yang baik. Setidaknya sebelum bug ini terjadi.



Sekarang penunjuk fungsi ini bukan penunjuk "kakek". Dia mengacu pada sesuatu yang istimewa. Ada area di CPU SRAM yang dapat kami gunakan untuk memuat tugas terkait jika kami tidak dapat menggunakan RAM. Untuk menghemat energi saat menganggur, kami menyalin subrutin ke area ini, menyetel penunjuk khusus yang merujuknya, lalu memanggilnya. Apa yang dilakukan subrutin itu? Mari kita lihat assembler. Saya bukan ahli assembler ARM, tetapi komentarnya cukup fasih.



//       ... 
... 
//       LPDDR   


Apa yang sedang kamu lakukan?! Anda dengan cepat berpindah dari operasi register dasar ke menonaktifkan pengontrol memori. Saya mengirim email ke pabrikan yang menulis subrutin dan bertanya apakah mereka melewatkan sesuatu.



Tiga hari kemudian, saya menerima jawaban dengan gaya "Oh ya, pasti ada penghalang memori." Ternyata, karena struktur cache L2 mereka, mereka juga harus mendukung TLB jika kami secara tidak sengaja menulis kelipatan 64 ke alamat memori. Dalam kasus seperti itu, kami masih dapat menggunakan RAM saat pengontrol mati.



Mempertimbangkan bahwa penyelarasan variabel memerlukan kelipatan minimum 4, dan bahwa catatan terakhir tidak dapat memiliki kelipatan 64 atau lebih, pada setiap kompilasi, seperenam belas data sama sekali tidak dapat digunakan oleh sistem.



Pada akhirnya, kami mengirimkan produk yang dapat diandalkan dengan penghalang memori, dan pelanggan menyukainya. Ya, dan jika Anda bertanya-tanya, saya tidak dapat menyadarinya dengan kabel USB karena kami tidak dapat memasuki mode daya rendah karena penggunaan USB. Ini murni masalah USB.



Pesan kesalahan tidak valid



Pada jam-jam terakhir tanggal 17 September 1996, sehari sebelum jadwal peluncuran layanan WebTV, kelompok kami berkumpul di pusat operasi di Palo Alto. Kerumunan sysadmin jaringan dan pengembang perangkat lunak layanan nongkrong di dekatnya untuk menyaksikan peluncuran resmi.



Ketika waktu yang ditentukan tiba, salah satu penggiat jejaring mulai mendaftar di perangkat WebTV-nya. Kami memahami bahwa nama panggilan yang baik akan cepat berakhir, jadi penting untuk mendaftar sebelum pengguna mulai melakukannya. Selain itu, senang menjadi orang pertama yang mendaftar untuk layanan "nyata" pertama. Sebelumnya, semua akun adalah akun uji "satu kali".



Beberapa orang berkerumun, mengawasinya mengetik di keyboard, merasa pusing karena antisipasi dan kurang tidur. Bryce memasukkan nama, alamat, dan informasi lainnya, lalu mulai mengetik nama panggilan. Itu namanya untuk alamat email. Dia mengetik "jazz", yang berarti emailnya harus "jazz@webtv.net". Saat dia menekan Enter pada keyboard nirkabel, kami mendengar suara khas yang menandakan munculnya pesan kesalahan. Semua orang melihat ke layar.



Untuk memahami apa yang terjadi selanjutnya, penting untuk mengetahui satu atau dua hal tentang layanan tersebut. WebTV diposisikan sebagai TV keluarga, jadi perlu untuk memeriksa bahasa kotor dan menyaring nama pengguna dan informasi lain yang terlihat oleh pengguna. Tidak mungkin untuk menangkap semuanya, tetapi tidak sulit untuk menyaring hal-hal yang jelas.



Nama kustom dibandingkan dengan daftar ekspresi reguler, yang memungkinkannya untuk dicocokkan dengan pola. Misalnya, "fu. * Bar" akan dibandingkan dengan semua nama yang dimulai dengan "fu" dan diakhiri dengan "bar". Jika Anda memilih pola dengan hati-hati, Anda dapat menangkap dan menolak variasi yang mengerikan seperti "shitake" dan "matsushita", yang memiliki kutukan bawaan.



Mekanisme yang sama digunakan untuk mencegah pengguna memilih nama "terlarang" seperti "postmaster", "root", "admin" dan "help". Kami memiliki file teks seperti ini:



admin.*
      "admin".
postmaster
  postmaster.
poop
  .
weenie
  .


Setiap entri terdiri dari dua baris. Yang pertama adalah ekspresi reguler yang akan dibandingkan, dan baris kedua adalah pesan kesalahan yang ditampilkan kepada pengguna. Sistem membaca file dua baris sekaligus, dan ketika pengguna memasukkan nama, itu dibandingkan dengan semua ekspresi reguler. Pesan kesalahan ditampilkan untuk kecocokan pertama yang ditemukan. Jika tidak ada yang cocok, nama kustom diterima.



Kode yang membaca file tersebut tahu bagaimana melewatkan komentar. Tapi dia tidak tahu bagaimana menangani antrean kosong.



Seseorang membuat perubahan pada file sumpah serapah, sambil menambahkan satu baris kosong setelah nama yang "dipesan" dan sebelum kata umpatan. Saat kode membaca daftar, string kosong itu diambil sebagai ekspresi reguler, dan kata yang mengikutinya sebagai pesan kesalahan. Ekspresi string kosong cocok dengan apa pun.



Tengah malam. Kami semua sedikit gelisah. Bryce menulis namanya, dan sistem merespons dengan pesan sederhana:





Kami mulai tertawa histeris. Orang lain mendatangi kami untuk mencari tahu apa yang sedang terjadi. Kami menunjukkannya ke layar. Mereka mulai tertawa histeris.



Saat itu, di gedung lain, Mark Armstrong (penanggung jawab QA), bersama dengan Bruce Leek (salah satu pendiri perusahaan), duduk di depan counter enam belas konsol WebTV. Rak ini, dijuluki "racksville", dihubungkan melalui multiplexer video ke TV besar yang menampilkan gambar dari semua 16 kotak secara bersamaan. Mark dan Bruce mulai mendaftarkan dekoder menggunakan keyboard dengan pemancar inframerah. Kami memanggil mereka melalui interkom:



- Bagaimana kabarnya?



- Semuanya sempurna.



- Oh bagus. Anda mungkin telah memperhatikan beberapa hal saat mendaftar.



- Iya? Kami tidak melihat ada yang aneh.



- Memperhatikan.



- Baik. Memasukkan kode pos ... sejauh ini semuanya baik-baik saja. OGO !!!



Sebuah pesan bersahabat muncul pada gambar dari semua 16 konsol. Bos menyarankan bahwa kami mungkin perlu memperbaiki kesalahan ini secepat mungkin. Ini sepertinya ide yang bagus bagi kami.



Kami memperbaiki file dan mengajarkan kode untuk mengenali dan mengabaikan baris kosong. Sejauh yang saya tahu, WebTV belum mengatakan "f - k" kepada pelanggan mana pun.



Masalah Xbox crash



Pada saat itu, tim sedang mengerjakan salah satu game pertama untuk konsol baru yang disebut Xbox. Saat pengujian terakhir dipercepat, QA meluncurkan tiga set-top box dari kumpulan instalasi untuk menjalankan pengujian otomatis di malam hari. Jika build game kemarin masih diuji di pagi hari, ini menunjukkan stabilitasnya.



Sayangnya, salah satu konsol rusak di pagi hari. Kerusakan selalu buruk, tetapi ini adalah kasus yang sangat buruk: sesuatu yang dieksekusi oleh kartu video merusak seluruh sistem. Sulit mendiagnosis masalah kartu grafis: tanpa debugger, tanpa jejak tumpukan, tanpa debugging printf. Anda hanya dapat membaca kode dan eksperimen.



Maka dimulailah Perburuan Serangga. Setiap hari, insinyur utama meninjau bukti yang tersedia, membuat hipotesis, dan mengesampingkan kemungkinan. Setiap malam, QA mendapat penurunan "acak" tanpa alasan. "Ini tidak mungkin", "Bagaimana ini bisa terjadi?", "Mungkinkah ini bug di kompiler?" - semua lagu terpopuler.



Di mobil para insinyur, permainan itu bekerja dengan sempurna selama beberapa hari. Tapi ini sedikit menghibur, karena batas waktu pengiriman game untuk dicetak dan dikirim ke toko sudah dekat.



Untungnya, kami segera menemukan polanya, meskipun agak aneh. Gim ini mogok hanya pada malam hari dan hanya di salah satu dari tiga konsol. Kami mulai mencari perbedaan di antara mereka. Ini bukan tentang kabel listrik. Tidak dalam pengontrol. DVD terbakar rusak. Mentransfer konsol ke meja Anda - tidak jatuh. Taruh kembali - itu jatuh. Itu tentang stand khusus yang digunakan QA.



Sekarang proses pengecualian faktor diperlukan untuk mengecualikan semua variabel. Akhirnya, dengan putus asa, insinyur itu mencoba menukar perlengkapan meja.



Ternyata itu bukan awalan tertentu yang tidak berfungsi. Awalan apa pun di tabel ini jatuh. Di tengah malam. Terkadang demi sains Anda harus bertindak aneh, dan ini adalah salah satu kasusnya. Insinyur itu duduk dengan tenang di kursi, menuangkan kaleng Red Bull, dan Bug Hunt menjadi Bug Watch. Insinyur itu bersumpah bahwa dia akan menonton tes otomatis yang dijalankan di konsol di atas meja sialan ini sampai dia melihat kegagalan dengan matanya sendiri.



Malam berlalu perlahan, lalu cepat, dan akhirnya fajar tiba. Pertandingan terus berjalan. Itu sangat menginspirasi. Matahari mulai terbit.



Dan kemudian sesuatu yang menarik akhirnya terjadi: sinar matahari terbit jatuh di atas meja. Menit demi menit, sinar itu merayap melintasi meja ke bagian-bagian yang melekat, cahaya hangatnya dengan tenang menyelimuti kubah hitam dari alat tambahan.



Yang jatuh dengan cepat.



Xbox pertama mengalami masalah: kartu video dapat rusak jika suhu konsol mencapai nilai tertentu. Perangkat lunak tidak ada hubungannya dengan itu. Masalah perangkat keras dilaporkan, permainan dirilis, dan Red Bull diganti dengan bir. Oke, jujur ​​saja, untuk wiski. Satu: nol untuk sains.



All Articles