প্রকাশিত: ১৯ মার্চ, ২০২৫
স্ক্রিফা রাস্ট (Rust) ভাষায় লেখা এবং আমাদের সকল ব্যবহারকারীর জন্য ক্রোমে ফন্ট প্রসেসিং সুরক্ষিত করতে ফ্রিটাইপ (FreeType)-এর বিকল্প হিসেবে তৈরি করা হয়েছে। স্ক্রিফা রাস্টের মেমরি সেফটির সুবিধা গ্রহণ করে এবং ক্রোমের ফন্ট প্রযুক্তির উন্নতিতে আমাদের আরও দ্রুত কাজ করতে সাহায্য করে। ফ্রিটাইপ থেকে স্ক্রিফাতে স্থানান্তরিত হওয়ায় আমরা আমাদের ফন্ট কোডে পরিবর্তন আনার ক্ষেত্রে আরও ক্ষিপ্র ও নির্ভীক হতে পেরেছি। এখন আমরা নিরাপত্তাজনিত ত্রুটি সংশোধনে অনেক কম সময় ব্যয় করি, যার ফলে আপডেট আরও দ্রুত হয় এবং কোডের মানও উন্নত হয়।
এই পোস্টে আলোচনা করা হয়েছে কেন ক্রোম ফ্রিটাইপ (FreeType) থেকে সরে এসেছে এবং এই পদক্ষেপের ফলে কী কী উন্নতি সম্ভব হয়েছে তার কিছু আকর্ষণীয় প্রযুক্তিগত বিবরণ দেওয়া হয়েছে।
কেন FreeType প্রতিস্থাপন করা উচিত?
ওয়েব এই দিক থেকে অনন্য যে, এটি ব্যবহারকারীদের বিভিন্ন অবিশ্বস্ত উৎস থেকে অবিশ্বস্ত রিসোর্স সংগ্রহ করার সুযোগ দেয় এই প্রত্যাশায় যে, সবকিছু ঠিকঠাক কাজ করবে এবং এতে তারা নিরাপদ থাকবে। এই ধারণাটি সাধারণত সঠিক, কিন্তু ব্যবহারকারীদের কাছে সেই প্রতিশ্রুতি রক্ষা করার জন্য একটি মূল্য দিতে হয়। উদাহরণস্বরূপ, একটি ওয়েব ফন্ট (নেটওয়ার্কের মাধ্যমে সরবরাহ করা ফন্ট) নিরাপদে ব্যবহার করার জন্য ক্রোম বেশ কিছু নিরাপত্তা ব্যবস্থা গ্রহণ করে:
- ফন্ট প্রসেসিং ' দুইয়ের নিয়ম' অনুসারে স্যান্ডবক্স করা হয়: ফন্টগুলো অবিশ্বস্ত এবং ব্যবহারকারী কোডটি অনিরাপদ।
- প্রক্রিয়াকরণের পূর্বে ফন্টগুলোকে ওপেনটাইপ স্যানিটাইজারের মাধ্যমে যাচাই করা হয়।
- ফন্ট ডিকম্প্রেস ও প্রসেস করার কাজে ব্যবহৃত সমস্ত লাইব্রেরি ফাজ টেস্ট করা হয়।
ক্রোমের সাথে ফ্রিটাইপ আগে থেকেই দেওয়া থাকে এবং অ্যান্ড্রয়েড, ক্রোমওএস ও লিনাক্সে এটি প্রধান ফন্ট প্রসেসিং লাইব্রেরি হিসেবে ব্যবহৃত হয়। এর মানে হলো, ফ্রিটাইপে কোনো দুর্বলতা থাকলে বহু ব্যবহারকারী ঝুঁকির মুখে পড়বেন।
ক্রোম মেট্রিক্স গণনা করতে এবং ফন্ট থেকে হিন্টেড আউটলাইন লোড করতে ফ্রিটাইপ লাইব্রেরি ব্যবহার করে। সামগ্রিকভাবে, ফ্রিটাইপের ব্যবহার গুগলের জন্য একটি বিশাল সাফল্য। এটি একটি জটিল কাজ করে এবং তা ভালোভাবে করে, আমরা এর উপর ব্যাপকভাবে নির্ভর করি এবং এতে অবদান রাখি। তবে, এটি অনিরাপদ কোডে লেখা এবং এর উৎপত্তি এমন এক সময়ে যখন ক্ষতিকারক ইনপুটের সম্ভাবনা কম ছিল। শুধুমাত্র ফাজিংয়ের মাধ্যমে খুঁজে পাওয়া সমস্যাগুলোর স্রোতের সাথে তাল মিলিয়ে চলতেই গুগলের অন্তত ০.২৫ জন পূর্ণকালীন সফটওয়্যার ইঞ্জিনিয়ারের খরচ হয়। আরও খারাপ ব্যাপার হলো, আমরা দৃশ্যত সবকিছু খুঁজে পাই না অথবা কোড ব্যবহারকারীদের কাছে পৌঁছে যাওয়ার পরেই কেবল কিছু জিনিস খুঁজে পাই।
এই ধরনের সমস্যা শুধু FreeType-এর ক্ষেত্রেই সীমাবদ্ধ নয়, আমরা দেখেছি যে অন্যান্য আনসেফ লাইব্রেরিগুলোতেও সমস্যা দেখা দেয়, এমনকি যখন আমরা আমাদের খুঁজে পাওয়া সেরা সফটওয়্যার ইঞ্জিনিয়ারদের নিয়োগ করি, প্রতিটি পরিবর্তন কোড রিভিউ করি এবং টেস্ট বাধ্যতামূলক করি।
কেন সমস্যাগুলো বারবার ঢুকে পড়ে
FreeType-এর নিরাপত্তা মূল্যায়ন করার সময় আমরা তিন ধরনের প্রধান সমস্যা ঘটতে দেখেছি (এটি সম্পূর্ণ তালিকা নয়):
অনিরাপদ ভাষার ব্যবহার
| প্যাটার্ন/সমস্যা | উদাহরণ |
|---|---|
| ম্যানুয়াল মেমরি ব্যবস্থাপনা |
|
| অনিয়ন্ত্রিত অ্যারে অ্যাক্সেস | CVE-2022-27404 |
| পূর্ণসংখ্যা ওভারফ্লো | সিএফএফ ড্রয়িং এবং হিন্টিং-এর ট্রু-টাইপ হিন্টিং-এর জন্য এমবেডেড ভার্চুয়াল মেশিনগুলি কার্যকর করার সময় https://issues.oss-fuzz.com/issues?q=FreeType%20Integer-overflow |
| জিরোয়িং এবং নন-জিরোয়িং অ্যালোকেশনের ভুল ব্যবহার | https://gitlab.freedesktop.org/freetype/freetype/-/merge_requests/94- এ আলোচনার পর ৮টি ফাজার ইস্যু পাওয়া গেছে। |
| অবৈধ কাস্ট | ম্যাক্রো ব্যবহার সম্পর্কে জানতে নিম্নলিখিত সারিটি দেখুন। |
প্রকল্প-নির্দিষ্ট সমস্যা
| প্যাটার্ন/সমস্যা | উদাহরণ |
|---|---|
| ম্যাক্রো সুস্পষ্ট আকার টাইপিংয়ের অভাবকে অস্পষ্ট করে। |
|
| সুরক্ষামূলকভাবে লেখা হলেও, নতুন কোড ক্রমাগত বাগ তৈরি করে। |
|
| পরীক্ষার অভাব |
|
নির্ভরশীলতার সমস্যা
ফাজিং বারবার FreeType-এর উপর নির্ভরশীল লাইব্রেরি, যেমন bzip2, libpng, এবং zlib-এ সমস্যা চিহ্নিত করেছে। উদাহরণস্বরূপ, freetype_bdf_fuzzer: Use-of-uninitialized-value in inflate . তুলনা করুন।
ঝাপসা করা যথেষ্ট নয়
ফাজিং হলো এলোমেলোভাবে দেওয়া ভুল ইনপুটসহ বিভিন্ন ধরনের ইনপুট ব্যবহার করে করা একটি স্বয়ংক্রিয় পরীক্ষা, যার উদ্দেশ্য হলো ক্রোমের স্থিতিশীল সংস্করণে চলে আসা নানা ধরনের সমস্যা খুঁজে বের করা। আমরা গুগলের oss-fuzz প্রকল্পের অংশ হিসেবে ফ্রিটাইপ (FreeType) ফাজ করি। এটি সমস্যা খুঁজে পেলেও, নিম্নলিখিত কারণগুলোর জন্য ফন্টগুলো ফাজিংয়ের বিরুদ্ধে কিছুটা প্রতিরোধী বলে প্রমাণিত হয়েছে।
ফন্ট ফাইলগুলো জটিল এবং ভিডিও ফাইলের সাথে তুলনীয়, কারণ এগুলোতে বিভিন্ন ধরনের তথ্য থাকে। ফন্ট ফাইল হলো একাধিক টেবিলের জন্য একটি ধারক ফরম্যাট, যেখানে প্রতিটি টেবিল স্ক্রিনে একটি সঠিক অবস্থানে থাকা গ্লিফ তৈরি করার জন্য টেক্সট এবং ফন্টকে একসাথে প্রক্রিয়াকরণে ভিন্ন ভিন্ন উদ্দেশ্য পূরণ করে। একটি ফন্ট ফাইলে আপনি পাবেন:
- পরিবর্তনশীল ফন্টের জন্য ফন্টের নাম এবং প্যারামিটারের মতো স্থির মেটাডেটা।
- ইউনিকোড অক্ষর থেকে গ্লিফে ম্যাপিং।
- গ্লিফসমূহের স্ক্রিন বিন্যাসের জন্য একটি জটিল নিয়মাবলী ও ব্যাকরণ।
- চাক্ষুষ তথ্য: স্ক্রিনে স্থাপিত গ্লিফগুলো দেখতে কেমন, তা বর্ণনা করে এমন গ্লিফের আকৃতি এবং ছবির তথ্য।
- ভিজ্যুয়াল টেবিলগুলোতে আবার ট্রু-টাইপ হিন্টিং প্রোগ্রাম অন্তর্ভুক্ত থাকতে পারে, যেগুলো হলো ক্ষুদ্র প্রোগ্রাম এবং গ্লিফের আকৃতি পরিবর্তন করার জন্য সেগুলো চালানো হয়।
- CFF বা CFF2 টেবিলের মধ্যে থাকা ক্যারেক্টার স্ট্রিংগুলো হলো অপরিহার্য কার্ভ অঙ্কন এবং হিন্টিং নির্দেশাবলী, যা CFF রেন্ডারিং ইঞ্জিনে সম্পাদিত হয়।
ফন্ট ফাইলগুলোতে এমন জটিলতা রয়েছে যা নিজস্ব প্রোগ্রামিং ভাষা এবং স্টেট মেশিন প্রসেসিং থাকার সমতুল্য, এবং এগুলো কার্যকর করার জন্য নির্দিষ্ট ভার্চুয়াল মেশিনের প্রয়োজন হয়।
ফর্ম্যাটের জটিলতার কারণে, ফন্ট ফাইলের সমস্যা খুঁজে বের করার ক্ষেত্রে ফাজিংয়ের সীমাবদ্ধতা রয়েছে।
নিম্নলিখিত কারণগুলোর জন্য ভালো কোড কভারেজ বা ফাজার অগ্রগতি অর্জন করা কঠিন:
- সাধারণ বিট-ফ্লিপিং/শিফট/ইনসারশন/ডিলিশন-ধাঁচের মিউটেটর ব্যবহার করে ট্রু-টাইপ হিন্টিং প্রোগ্রাম, সিএফএফ ক্যারেক্টার স্ট্রিং এবং ওপেন-টাইপ লেআউট ফাজিং করার ক্ষেত্রে স্টেটগুলোর সমস্ত সংমিশ্রণে পৌঁছানো কঠিন হয়ে পড়ে।
- ফাজিংয়ের মাধ্যমে অন্তত আংশিকভাবে বৈধ কাঠামো তৈরি হওয়া প্রয়োজন। র্যান্ডম মিউটেশন খুব কমই তা করতে পারে, ফলে ভালো কভারেজ অর্জন করা কঠিন হয়ে পড়ে, বিশেষ করে কোডের গভীর স্তরগুলোর ক্ষেত্রে।
- ClusterFuzz এবং oss-fuzz-এর বর্তমান ফাজিং প্রচেষ্টাগুলিতে এখনও কাঠামো-সচেতন মিউটেশন ব্যবহার করা হচ্ছে না। ব্যাকরণ- বা কাঠামো-সচেতন মিউটেটরের ব্যবহার এমন ভ্যারিয়েন্ট তৈরি হওয়া এড়াতে সাহায্য করতে পারে যা শুরুতেই বাতিল হয়ে যায়, তবে এর জন্য ডেভেলপমেন্টে বেশি সময় লাগবে এবং সার্চ স্পেসের কিছু অংশ বাদ পড়ার সম্ভাবনা তৈরি হবে।
ফাজিং প্রক্রিয়ার অগ্রগতির জন্য একাধিক টেবিলের ডেটা সিঙ্ক থাকা প্রয়োজন:
- ফাজারের সাধারণ মিউটেশন প্যাটার্ন আংশিকভাবে বৈধ ডেটা তৈরি করে না, ফলে অনেক ইটারেশন বাতিল হয়ে যায় এবং অগ্রগতি ধীর হয়ে পড়ে।
- গ্লিফ ম্যাপিং, ওপেনটাইপ লেআউট টেবিল এবং গ্লিফ ড্রয়িং পরস্পরের সাথে সংযুক্ত ও নির্ভরশীল, যা এমন একটি কম্বিনেটোরিয়াল স্পেস গঠন করে যার কোণগুলোতে ফাজিংয়ের মাধ্যমে পৌঁছানো কঠিন।
- উদাহরণস্বরূপ, উচ্চ-গুরুত্বপূর্ণ tt_face_get_paint COLRv1 দুর্বলতাটি খুঁজে বের করতে ১০ মাসেরও বেশি সময় লেগেছিল।
আমাদের সর্বোত্তম প্রচেষ্টা সত্ত্বেও, ফন্ট নিরাপত্তাজনিত সমস্যা বারবার সাধারণ ব্যবহারকারীদের কাছে পৌঁছেছে। FreeType-কে Rust-এর কোনো বিকল্প দিয়ে প্রতিস্থাপন করলে একাধিক সম্পূর্ণ শ্রেণীর দুর্বলতা প্রতিরোধ করা যাবে।
ক্রোমে স্ক্রিফা
স্কিয়া হলো ক্রোমে ব্যবহৃত গ্রাফিক্স লাইব্রেরি। ফন্ট থেকে মেটাডেটা এবং অক্ষরের গঠন লোড করার জন্য স্কিয়া ফ্রিটাইপের ওপর নির্ভর করে। স্ক্রিফা হলো ফন্টেশনস লাইব্রেরি পরিবারের একটি রাস্ট লাইব্রেরি, যা স্কিয়া দ্বারা ব্যবহৃত ফ্রিটাইপের অংশগুলোর একটি নিরাপদ বিকল্প প্রদান করে।
FreeType-কে Skia-তে রূপান্তর করার জন্য Chrome টিম Skrifa-র উপর ভিত্তি করে একটি নতুন Skia ফন্ট ব্যাকএন্ড তৈরি করেছে এবং পর্যায়ক্রমে ব্যবহারকারীদের কাছে এই পরিবর্তনটি পৌঁছে দিয়েছে:
- ক্রোম ১২৮ (আগস্ট ২০২৪)-এ আমরা একটি নিরাপদ পরীক্ষামূলক পদক্ষেপ হিসেবে, কালার ফন্ট এবং CFF2-এর মতো কম ব্যবহৃত ফন্ট ফরম্যাটগুলোতে ফন্টেশন ব্যবহারের সুযোগ চালু করেছি ।
- ক্রোম ১৩৩ (ফেব্রুয়ারি ২০২৫)-এ আমরা লিনাক্স, অ্যান্ড্রয়েড এবং ক্রোমওএস-এ সমস্ত ওয়েব ফন্ট ব্যবহারের জন্য এবং উইন্ডোজ ও ম্যাক-এ ফলব্যাক হিসেবে ওয়েব ফন্ট ব্যবহারের জন্য ফন্টেশন চালু করেছি —এমন ক্ষেত্রে যেখানে সিস্টেম কোনো ফন্ট ফরম্যাট সমর্থন করে না কিন্তু ক্রোমকে তা প্রদর্শন করতে হয়।
ক্রোমে ইন্টিগ্রেশনের জন্য, আমরা ক্রোম নিরাপত্তা দল কর্তৃক কোডবেসে রাস্টের সাবলীল ইন্টিগ্রেশনের উপর নির্ভর করি।
ভবিষ্যতে আমরা অপারেটিং সিস্টেম ফন্টের জন্যও ফন্টেশনস ব্যবহার শুরু করব, যা প্রথমে লিনাক্স ও ক্রোমওএস-এ এবং তারপর অ্যান্ড্রয়েডে চালু হবে।
নিরাপত্তা, সর্বাগ্রে
আমাদের প্রধান লক্ষ্য হলো মেমোরিতে সীমার বাইরের অ্যাক্সেসের কারণে সৃষ্ট নিরাপত্তা দুর্বলতাগুলো হ্রাস করা (অথবা আদর্শগতভাবে, নির্মূল করা!)। রাস্ট এই সুবিধাটি স্বয়ংক্রিয়ভাবেই প্রদান করে, যতক্ষণ পর্যন্ত আপনি কোনো অনিরাপদ কোড ব্লক এড়িয়ে চলেন।
আমাদের পারফরম্যান্সের লক্ষ্য পূরণের জন্য এমন একটি অপারেশন সম্পাদন করা প্রয়োজন যা বর্তমানে অনিরাপদ: যথেচ্ছ বাইটকে একটি স্ট্রংলি টাইপড ডেটা স্ট্রাকচার হিসেবে পুনঃব্যাখ্যা করা। এটি আমাদেরকে অপ্রয়োজনীয় অনুলিপি তৈরি না করেই একটি ফন্ট ফাইল থেকে ডেটা পড়তে সাহায্য করে এবং একটি দ্রুত ফন্ট পার্সার তৈরির জন্য এটি অপরিহার্য।
আমাদের নিজেদের অনিরাপদ কোড এড়ানোর জন্য, আমরা এই দায়িত্বটি বাইটমাক (bytemuck) -এর উপর অর্পণ করার সিদ্ধান্ত নিয়েছি। এটি একটি রাস্ট (Rust) লাইব্রেরি যা বিশেষভাবে এই কাজের জন্যই ডিজাইন করা হয়েছে এবং ইকোসিস্টেম জুড়ে ব্যাপকভাবে পরীক্ষিত ও ব্যবহৃত হয়। বাইটমাক-এ র ডেটা পুনঃব্যাখ্যার কাজটি কেন্দ্রীভূত করার ফলে আমরা নিশ্চিত করতে পারি যে এই কার্যকারিতাটি একটি স্থানেই রয়েছে এবং নিরীক্ষিত, এবং এর জন্য অনিরাপদ কোডের পুনরাবৃত্তি এড়ানো যায়। সেফ ট্রান্সমিউট (safe transmute) প্রকল্পের লক্ষ্য হলো এই কার্যকারিতাটি সরাসরি রাস্ট কম্পাইলারে অন্তর্ভুক্ত করা এবং এটি উপলব্ধ হওয়া মাত্রই আমরা এই পরিবর্তনটি গ্রহণ করব।
সঠিকতা গুরুত্বপূর্ণ
স্ক্রিফা স্বাধীন উপাদান দিয়ে তৈরি, যেখানে বেশিরভাগ ডেটা স্ট্রাকচার অপরিবর্তনীয় (immutable) করে ডিজাইন করা হয়েছে। এটি কোডের পঠনযোগ্যতা, রক্ষণাবেক্ষণযোগ্যতা এবং মাল্টিথ্রেডিং উন্নত করে। এটি কোডকে ইউনিট টেস্টিংয়ের জন্যও আরও উপযোগী করে তোলে। আমরা এই সুযোগটি কাজে লাগিয়েছি এবং প্রায় ৭০০টি ইউনিট টেস্টের একটি স্যুট তৈরি করেছি, যা আমাদের লো-লেভেল পার্সিং রুটিন থেকে শুরু করে হাই-লেভেল হিটিং ভার্চুয়াল মেশিন পর্যন্ত সম্পূর্ণ স্ট্যাককে কভার করে।
সঠিকতার অর্থ বিশ্বস্ততাও বোঝায় এবং ফ্রিটাইপ তার উচ্চ মানের আউটলাইন তৈরির জন্য অত্যন্ত সমাদৃত। একটি উপযুক্ত বিকল্প হতে হলে আমাদেরও এই মানের সাথে সামঞ্জস্য রাখতে হবে। সেই লক্ষ্যে, আমরা ফন্টলেট (fauntlet) নামে একটি বিশেষ টুল তৈরি করেছি, যা বিভিন্ন কনফিগারেশনের ফন্ট ফাইলের ব্যাচের জন্য স্ক্রিফা (Skrifa) এবং ফ্রিটাইপের আউটপুট তুলনা করে। এটি আমাদের এই নিশ্চয়তা দেয় যে আমরা মানের অবনতি এড়াতে পারব।
এছাড়াও, Chromium-এ একীভূত করার আগে, আমরা Skia-তে FreeType রেন্ডারিং-এর সাথে Skrifa এবং Skia রেন্ডারিং- এর ব্যাপক পিক্সেল তুলনা করেছি, যাতে সমস্ত প্রয়োজনীয় রেন্ডারিং মোডে (বিভিন্ন অ্যান্টি-এলাইজিং এবং হিন্টিং মোড জুড়ে) পিক্সেলের পার্থক্য একেবারে নগণ্য থাকে তা নিশ্চিত করা যায়।
কোনো সফটওয়্যার ত্রুটিপূর্ণ এবং ক্ষতিকারক ইনপুটের প্রতি কীভাবে প্রতিক্রিয়া দেখাবে, তা নির্ধারণ করার জন্য ফাজ টেস্টিং একটি গুরুত্বপূর্ণ টুল। আমরা ২০২৪ সালের জুন মাস থেকে আমাদের নতুন কোড ক্রমাগত ফাজিং করে আসছি। এর আওতায় মূল রাস্ট লাইব্রেরি এবং ইন্টিগ্রেশন কোড অন্তর্ভুক্ত। যদিও ফাজারটি (এই লেখা পর্যন্ত) ৩৯টি বাগ খুঁজে পেয়েছে, তবে এটি উল্লেখ্য যে এগুলোর কোনোটিই নিরাপত্তার জন্য গুরুতর ছিল না । এগুলোর কারণে অনাকাঙ্ক্ষিত ভিজ্যুয়াল ফলাফল বা এমনকি নিয়ন্ত্রিত ক্র্যাশও হতে পারে, কিন্তু এগুলো থেকে এক্সপ্লয়টেবল ভালনারেবিলিটি তৈরি হবে না।
এগিয়ে চলো!
টেক্সটের জন্য রাস্ট ব্যবহারের প্রচেষ্টার ফলাফলে আমরা অত্যন্ত সন্তুষ্ট। ব্যবহারকারীদের কাছে আরও নিরাপদ কোড পৌঁছে দেওয়া এবং ডেভেলপারদের উৎপাদনশীলতা বৃদ্ধি করা আমাদের জন্য একটি বিশাল সাফল্য। আমরা আমাদের টেক্সট স্ট্যাকে রাস্ট ব্যবহারের সুযোগ অন্বেষণ অব্যাহত রাখার পরিকল্পনা করছি। আপনি যদি আরও জানতে চান, তাহলে অক্সিডাইজ গুগল ফন্টসের কিছু ভবিষ্যৎ পরিকল্পনা তুলে ধরেছে।