pangzhen1xiaomi opened a new pull request, #18086:
URL: https://github.com/apache/nuttx/pull/18086
casting from signed int to unsigned int is not safe and should not be allowed
## Summary
What This Patch Does
This patch eliminates unsafe implicit type conversions from signed int to
unsigned int in the IRQ handling subsystem. The changes address a critical
safety issue where negative IRQ numbers could be silently converted to large
positive values, bypassing range checks.
## Impact
Positive Impact
1.Security: Prevents negative IRQ values from bypassing range checks
2.Robustness: Eliminates undefined behavior from implicit type conversions
3.Code Clarity: Explicit range checks are easier to understand
4.Static Analysis: Improves static analyzer detection of issues
5.Type Safety: Maintains type consistency throughout the code
6.Standards Compliance: Follows CERT INT31-C guidelines
7.Maintainability: Clear intent of what values are acceptable
Use Cases
1.Embedded Systems: Prevents IRQ handling vulnerabilities
2.Safety-Critical: Meets requirements for automotive/aerospace
3.Security: Closes potential attack vectors through invalid IRQs
4.Reliability: Prevents unexpected behavior from malformed input
Risk Assessment
1.No behavioral change for valid IRQ numbers (0 to NR_IRQS-1)
2.Actually fixes incorrect behavior for invalid IRQs
3.More restrictive checking (rejects negative values explicitly)
4.Existing code should only pass valid IRQ numbers
5.No API or ABI changes
## Testing
Test Case 1: Valid IRQ Range Check
/**
* Test: Verify valid IRQs pass the new range check
* Purpose: Ensure legitimate IRQs are accepted
* Expected: All IRQ numbers from 0 to NR_IRQS-1 are accepted
*/
static void test_valid_irq_range(void)
{
int valid_irqs[] = {0, 1, 2, 5, 10, NR_IRQS-1};
int num_valid = sizeof(valid_irqs) / sizeof(valid_irqs[0]);
for (int i = 0; i < num_valid; i++)
{
int irq = valid_irqs[i];
// New check: irq >= 0 && irq < NR_IRQS
if (irq >= 0 && irq < NR_IRQS)
{
printf("IRQ %d: PASS (within valid range)\n", irq);
}
else
{
printf("IRQ %d: FAIL (should be valid)\n", irq);
assert(0);
}
}
printf("Test PASS: Valid IRQ range check successful\n");
}
Test Case 2: Negative IRQ Rejection
/**
* Test: Verify negative IRQs are rejected
* Purpose: Ensure negative IRQs don't bypass checks
* Expected: Negative IRQs are explicitly rejected
*/
static void test_negative_irq_rejection(void)
{
int negative_irqs[] = {-1, -2, -10, -100};
int num_negatives = sizeof(negative_irqs) / sizeof(negative_irqs[0]);
for (int i = 0; i < num_negatives; i++)
{
int irq = negative_irqs[i];
// New check: irq >= 0 && irq < NR_IRQS
if (!(irq >= 0 && irq < NR_IRQS))
{
printf("IRQ %d: PASS (correctly rejected)\n", irq);
}
else
{
printf("IRQ %d: FAIL (should be rejected)\n", irq);
assert(0);
}
}
printf("Test PASS: Negative IRQ rejection working\n");
}
Test Case 3: Out-of-Range IRQ Rejection
/**
* Test: Verify IRQs above NR_IRQS are rejected
* Purpose: Ensure upper boundary is enforced
* Expected: All IRQs >= NR_IRQS are rejected
*/
static void test_out_of_range_irq_rejection(void)
{
int out_of_range_irqs[] = {NR_IRQS, NR_IRQS+1, NR_IRQS+100, INT_MAX};
int num_oob = sizeof(out_of_range_irqs) / sizeof(out_of_range_irqs[0]);
for (int i = 0; i < num_oob; i++)
{
int irq = out_of_range_irqs[i];
// New check: irq >= 0 && irq < NR_IRQS
if (!(irq >= 0 && irq < NR_IRQS))
{
printf("IRQ %d: PASS (correctly rejected)\n", irq);
}
else
{
printf("IRQ %d: FAIL (should be out of range)\n", irq);
assert(0);
}
}
printf("Test PASS: Out-of-range IRQ rejection working\n");
}
Test Case 4: IRQ Attach Safety
/**
* Test: Verify irq_attach rejects invalid IRQs
* Purpose: Ensure the fixed irq_attach properly validates input
* Expected: Invalid IRQs return -EINVAL
*/
static void test_irq_attach_safety(void)
{
xcpt_t dummy_isr = (xcpt_t)test_isr_handler;
// Test valid IRQ
int valid_ret = irq_attach(0, dummy_isr, NULL);
printf("Valid IRQ (0): %s\n", valid_ret == OK ? "PASS" : "SKIP");
// Test negative IRQ (should be rejected)
int negative_ret = irq_attach(-1, dummy_isr, NULL);
if (negative_ret == -EINVAL)
{
printf("Negative IRQ (-1): PASS (rejected with -EINVAL)\n");
}
else
{
printf("Negative IRQ (-1): FAIL (should return -EINVAL, got %d)\n",
negative_ret);
assert(0);
}
// Test out-of-range IRQ
int oob_ret = irq_attach(NR_IRQS, dummy_isr, NULL);
if (oob_ret == -EINVAL)
{
printf("Out-of-range IRQ (%d): PASS (rejected with -EINVAL)\n",
NR_IRQS);
}
else
{
printf("Out-of-range IRQ (%d): FAIL (should return -EINVAL, got
%d)\n",
NR_IRQS, oob_ret);
assert(0);
}
printf("Test PASS: IRQ attach safety verified\n");
}
Test Case 5: Thread IRQ Attach Safety
/**
* Test: Verify thread IRQ attachment rejects invalid IRQs
* Purpose: Ensure fixed irq_attach_thread validates input
* Expected: Invalid IRQs return -EINVAL
*/
static void test_thread_irq_attach_safety(void)
{
xcpt_t dummy_isr = (xcpt_t)test_isr_handler;
xcpt_t dummy_thread = (xcpt_t)test_thread_handler;
// Test valid IRQ
int valid_ret = irq_attach_thread(1, dummy_isr, dummy_thread, NULL, 100,
2048);
printf("Valid IRQ (1): %s\n", valid_ret == OK ? "PASS" : "SKIP");
// Test negative IRQ (should be rejected)
int negative_ret = irq_attach_thread(-1, dummy_isr, dummy_thread, NULL,
100, 2048);
if (negative_ret == -EINVAL)
{
printf("Negative IRQ (-1): PASS (rejected)\n");
}
else
{
printf("Negative IRQ (-1): FAIL (should be rejected)\n");
assert(0);
}
printf("Test PASS: Thread IRQ attach safety verified\n");
}
Test Case 6: Work Queue IRQ Attach Safety
/**
* Test: Verify work queue IRQ attachment rejects invalid IRQs
* Purpose: Ensure fixed irq_attach_wqueue validates input
* Expected: Invalid IRQs return -EINVAL
*/
static void test_wqueue_irq_attach_safety(void)
{
xcpt_t dummy_isr = (xcpt_t)test_isr_handler;
xcpt_t dummy_work = (xcpt_t)test_work_handler;
// Test valid IRQ
int valid_ret = irq_attach_wqueue(1, dummy_isr, dummy_work, NULL, 200);
printf("Valid IRQ (1): %s\n", valid_ret == OK ? "PASS" : "SKIP");
// Test negative IRQ (should be rejected)
int negative_ret = irq_attach_wqueue(-1, dummy_isr, dummy_work, NULL, 200);
if (negative_ret == -EINVAL)
{
printf("Negative IRQ (-1): PASS (rejected)\n");
}
else
{
printf("Negative IRQ (-1): FAIL (should be rejected)\n");
assert(0);
}
// Test out-of-range IRQ
int oob_ret = irq_attach_wqueue(NR_IRQS, dummy_isr, dummy_work, NULL, 200);
if (oob_ret == -EINVAL)
{
printf("Out-of-range IRQ: PASS (rejected)\n");
}
else
{
printf("Out-of-range IRQ: FAIL (should be rejected)\n");
assert(0);
}
printf("Test PASS: Work queue IRQ attach safety verified\n");
}
Test Case 7: IRQ Dispatch Safety
/**
* Test: Verify IRQ dispatch handles invalid IRQs safely
* Purpose: Ensure irq_dispatch doesn't crash on negative/invalid IRQs
* Expected: Invalid IRQs are safely handled
*/
static void test_irq_dispatch_safety(void)
{
// Note: Direct irq_dispatch testing requires platform setup
// This is more of a compile-time test
// Test the type checking logic
int valid_irq = 5;
int invalid_irq = -1;
int oob_irq = NR_IRQS;
// Check logic for valid IRQ
if (valid_irq >= 0 && valid_irq < NR_IRQS)
{
printf("Valid IRQ dispatch: PASS\n");
}
else
{
printf("Valid IRQ dispatch: FAIL\n");
assert(0);
}
// Check logic for invalid IRQ
if (!(invalid_irq >= 0 && invalid_irq < NR_IRQS))
{
printf("Invalid IRQ dispatch: PASS (rejected)\n");
}
else
{
printf("Invalid IRQ dispatch: FAIL (should be rejected)\n");
assert(0);
}
// Check logic for out-of-range IRQ
if (!(oob_irq >= 0 && oob_irq < NR_IRQS))
{
printf("OOB IRQ dispatch: PASS (rejected)\n");
}
else
{
printf("OOB IRQ dispatch: FAIL (should be rejected)\n");
assert(0);
}
printf("Test PASS: IRQ dispatch safety verified\n");
}
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]