فا

‫ برنامه‌نويسي امن با زبان C - سيگنالها - قسمت اول

IRCAR201104094
تاريخ: 26/01/90
عنصر اصلي در برنامه‌نويسي امن با زبان‌هاي مختلف برنامه‌نويسي، مستندسازي خوب و استفاده از استانداردهاي قابل اجرا است. استانداردهاي كدنويسي، برنامه نويسان را ترغيب به پيروي از مجموعه‌اي متحدالشكل از قوانين و راهنمايي‌هايي مي‌كند كه بر اساس نيازمندي‌هاي پروژه و سازمان تعيين شده است، نه بر اساس سلايق و مهارت‌هاي مختلف برنامه‌نويسان. به محض تعيين استانداردهاي مذكور، ميتوان از آن به عنوان معياري براي ارزيابي كدهاي منبع، چه به صورت دستي و چه به صورت اتوماتيك استفاده كرد.
از استانداردهاي معروف در اين زمينه مي‌توان به استانداردCERT براي كدنويسي امن اشاره كرد كه يك سري از قوانين و پيشنهادات را براي كدنويسي امن با زبان‌هاي برنامه‌نويسي C، C++ و جاوا ارائه مي‌دهد. هدف از اين قوانين و پيشنهادات، حذف عادت‌هاي كدنويسي ناامن و رفتارهاي تعريف نشده است كه منجر به آسيب‌پذيري‌هاي قابل سوءاستفاده مي‌شود. به كارگيري استانداردهاي مذكور منجر به توليد سيستم‌هاي با كيفيت بالاتر مي‌شود كه در برابر حملات بالقوه، پايدارتر و مقاوم‌تر هستند.
در مقاله هاي قبلي، كليات استاندارد CERT در زمينه مزبور را توضيح داديم و در سري مقاله‌هاي برنامه‌نويسي امن به زبان C به صورت تخصصي‌تر شيوه برنامه‌نويسي امن با اين زبان را مورد بررسي قرار مي‌دهيم. قابل ذكر است كه در اين استاندارد 89 قانون و 134 پيشنهاد براي برنامه‌نويسي امن با زبان C ارائه شده است كه در اين سري مقالات، مهمترين آنها را كه در سطح يك قرار دارند، شرح خواهيم داد. براي كسب اطلاعات بيشتر در مورد سطح‌بندي قوانين و پيشنهادات به مقاله "آشنايي با استاندارد CERT براي برنامه نويسي امن" مراجعه فرماييد. در مقاله حاضر به پيشنهادات و قوانين ارائه شده سطح اول در مورد سيگنالها خواهيم پرداخت.
40. SIG02-C– از سيگنال ها براي پياده سازي عمليات هاي نرمال استفاده نكنيد.
از استفاده از سيگنال ها براي پياده سازي كاربردهاي نرمال اجتناب كنيد. تابع هاي تك منظوره (handler) سيگنال ها به شدت در اجراي عمليات هاي خود به شيوه اي امن محدود هستند.
در زير نمونه كدي را كه از قانون فوق پيروي نكرده است مشاهده مي كنيد كه از سيگنالها به عنوان وسيله اي براي منتقل كردن تغييرات وضعيت در يك محيط چندرشته اي استفاده مي كند.

استفاده از سيگنال ها براي چنين عملياتي اغلب منجر به راه حل هاي پيچيده مي شود. اين كد يك رشته را با استفاده از يك سيگنال براي بيدار كردن يك رشته ديگر پياده سازي كرده است. استفاده از معماري كتابخانه رشته ها راه حل هاي به مراتب كامل تري را براي انتقال پيغام بين رشته ها در اختيار مي گذارد.
در راه حل جايگزين و امن تر زير مثالي را مشاهده مي كنيد كه از يك متغير شرطي از Win32 API استفاده كرده است.
  1. ENV04-C – در سيگنالها فقط توابع غيرهمزمان امن را فراخواني كنيد.
تنها توابع غير همزمان امن را در توابع تك منظوره سيگنال مورد استفاده قرار دهيد. اين قانون در مورد هم توابع كتابخانه اي و هم توابعي كه در داخل برنامه تعريف مي شوند، بايد به كار گرفته شود.
ليست توابع غير همزمان كه به كارگيري آنها در سيگنالها امنيت دارد، در زير آورده شده است:
در زير يك برنامه را مي بينيد كه از قانون فوق تخطي كرده است. اين برنامه به يك رشته حافظه اختصاص داده و سپس از آن رشته براي ثبت پيغام ها در يك حلقه استفاده مي كند. اين برنامه همچنين يك برنامه تك منظوره سيگنال (signal handler) به نام int_handler را براي مديريت وقفه سيگنال خروجي SIGINT، ثبت مي كند. تابع int_handler() آخرين پيغام را ثبت كرده، free() را فراخواني كرده و از برنامه خارج مي شود.
تابع تك منظوره سيگنال در اين برنامه چهار مشكل دارد. اول اينكه استفاده از تابع fprintf() در چنين توابعي (signal handlers) ناامن است زيرا ممكن است handler زماني فراخواني شود كه داده هاي عمومي همچون stderr در وضعيت غيرثابتي قرار دارند. در حالت كلي استفاده از توابع I/O در داخل توابع تك منظوره سيگنال امن نيست.
دومين مشكل نيز مربوط به تابع free() است كه جزء توابع امن غيرهمزمان نيست و استفاده از آن در داخل يك تابع تك منظوره سيگنال تخطي از اين قانون است و در صورتي كه يك وقفه سيگنال در زمان فراخواني تابع free() در درون handler() اتفاق بيفتد، ممكن است heap دچار خرابي شود.
سومين مشكل اينست كه اگر SIGINT بعد از فراخواني free() اتفاق بيفتد منجر مي شود كه حافظه اي كه به info اختصاص پيدا كرده است، دو بار آزاد شود.
چهارمين مشكل اينست كه تابع تك منظوره سيگنال يك متغير به نام Info را مي خواند كه به عنوان يك نوع volatile sig_atomic_t تعريف نشده است و اين خلاف قانوني است كه مي گويد در درون توابع تك منظوره سيگنال، اشياء مشترك را تغيير نداده و يا به آنها دسترسي پيدا نكنيد.
علاوه بر اين مشكلاتي نيز در درون تابع main() وجود دارد، براي مثال امكان دارد كه تقاضاي دسترسي به تابع تك منظوره سيگنال در زمان فراخواني malloc() در main() اتفاق بيفتد.
در زير نسخه اصلاح شده برنامه فوق را مشاهده مي كنيد كه در آن آخرين پيغام ثبت و همچنين تابع free() به خارج از تابع تك منظوره سيگنال منتقل شده اند.
يكي از قوانين مربوط به بخش سيگنال ها باقي مانده است كه در مقاله بعدي به آن خواهيم پرداخت.

نظرات

بدون نظر
شما برای نظر دادن باید وارد شوید

نوشته

 
تاریخ ایجاد: 18 مرداد 1393

دسته‌ها

امتیاز

امتیاز شما
تعداد امتیازها: 0