Sprintf("%s", $string): A few gems from the RAID controller I'm working on



  • I'm currently in the process of customizing the firmware for a RAID controller used  in some of my company's products. The LCD Controller Module (LCM) is written in PHP, a task for which PHP was NOT designed for. In addition to abusing exec all over the place, they poorly re-implement functions that are built-in to PHP:

     
    function strcenter($string, $len = LCM_ROW_LEN)
    {
        //printf("%s\n", __FUNCTION__);
        $size = strlen($string);
        if ($size > $len) return $string;

        $divisor = ($len - $size) / 2;
       
        unset($new_str);
        for ($i = 0; $i < $divisor; $i++) {
            $new_str .= " ";
        }

        $new_str .= sprintf("%s", $string);
       
        for ($i = strlen($new_str); $i < $len; $i++) {
            $new_str .= " ";
        }
        //$test = strlen($new_str);
        //echo "len = $test\n";
        return $new_str;
    }

    function strleft($string, $len = LCM_ROW_LEN)
    {
        //printf("%s\n", __FUNCTION__);
        $size = strlen($string);
        if ($size > $len) return $string;

        $remainder = $len - $size;
       
        unset($new_str);
        $new_str .= sprintf("%s", $string);
       
        for ($i = 0; $i < $remainder; $i++) {
            $new_str .= " ";
        }
        //$test = strlen($new_str);
        //echo "len = $test\n";
        return $new_str;
    }

     function LCM_get_base_position($length, $tag=TAG_NONE)
    {
        for ($i = 0; $i < $length; $i++) {
            $string .= "X";
        }
        
        switch ($tag) {
        case TAG_ENT:
        case TAG_SCROLL:
            $max = LCM_ROW_LEN - 1;
            break;
        case TAG_SCROLL_ENT:
        case TAG_UP_ENT:
        case TAG_DN_ENT:
            $max = LCM_ROW_LEN - 2;
            break;
        case TAG_NONE:
        default:
            break;
        }

        $string = strcenter($string, $max);
        //printf("%s: str = %s, max = %d, length = %d\n", __FUNCTION__, $string, $max, $length);
        $pos = strpos($string, 'X');
        
        if ($pos == false) {
            printf("%s: Failed to get postion\n", __FUNCTION__);
        } else {
            return $pos;
        }
    }

    I especially like the sprintf("%s", $string).

    Abusing exec():

     function alarm_mute()
    {
        //exec("echo 0 > /proc/ems/alarm/tone; echo 0 > /proc/ems/system/error_led");
        exec("echo 0 > /proc/ems/alarm/tone");
    }

     function GetIfaceInfo(&$config, &$address, &$submask, &$gateway, &$dns)
    {
        $dhcp_cmd = "grep \"iface eth0 inet dhcp\" /etc/network/interfaces";
        exec($dhcp_cmd, $a1);
        if ( count($a1) == 1 ) {
            $config = "dhcp";
        } else {
            $config = "static";
        }

        $get_addr_cmd = "ifconfig eth0 | awk '$1 ~ /inet/{print $2}' | awk -F: '{print $2}'";
        exec($get_addr_cmd, $temp);
        $address_string = $temp[0];
        GetIfaceforIP($gateway_string, $submask_string,$dns_string);
        TransIfaceInfo($address_string, $address);
        TransIfaceInfo($submask_string, $submask);
        TransIfaceInfo($gateway_string, $gateway);
        TransIfaceInfo($dsn_string, $dns);
    }

     

    Bonus: due in no small part to the crappy kernel module (which I have no access to the source), exec() is REALLY slow: nearly a whole second to fork and exec a process.  This also means it takes 2 or three seconds to write an event to the log.

    If there is a problem that affects all eight hard drives at once (like a power issue), this is what will happen.

    1. It will report the first drive failure and start alarming.
    2. You press the mute button.
    3. Three seconds later, it will report the second drive failure and start alarming again.
    4. You mash the mute button.
    5. Three seconds later ... 

     ... until it has logged the failure of all drives, as well as the RAID set itself, or until you yank the power plug in frustration.

     

    This is an all-around crappy RAID controller. 

     



  • @jspenguin said:

    Bonus: due in no small part to the crappy kernel module (which I have no access to the source)
     

    Good lord. After you've seen that code, how can you possibly trust any of the data that's written through the controller? That thing is a ticking time bomb.

    About the kernel module: How is that distributed? A precompiled binary module? A whole kernel that includes the module? Make sure all the source code that they are required to provide under the GPL is actually available. 



  • OMGWTFBBQ! 

    @jspenguin said:

        //$test = strlen($new_str);
        //echo "len = $test\n";

     

    Run away! It a sign! Trust me, you'll see something worse pretty soon...  

    @jspenguin said:

     

    If there is a problem that affects all eight hard drives at once (like a power issue), this is what will happen.

    1. It will report the first drive failure and start alarming.
    2. You press the mute button.
    3. Three seconds later, it will report the second drive failure and start alarming again.
    4. You mash the mute button.
    5. Three seconds later ... 
     ... until it has logged the failure of all drives, as well as the RAID set itself, or until you yank the power plug in frustration.

     

    What RAID controller is it? Just to be sure I'll never buy one ;-) But it seems quite a powerfull weapon against your competitors...



  • PHP controlling a low-level hardware device?  Seriously???  I'm speechless. 



  • @bighusker said:

    PHP controlling a low-level hardware device?  Seriously???  I'm speechless. 

     

     

    It's primarily for the Web interface, which is fine. I don't like PHP, but at least it's tolerable when used for its original purpose. Although, if I went through the web interface code, I would have no problem finding many more WTFs. The only reason I was mucking about in this PHP code at all is to add a couple of features and to fix some Engrish.

     

    As for the kernel module... well, modinfo *says* it's GPL... I wonder if I could hold them to that? They're already violating the GPL (Linux kernel, busybox, uClibc, etc.), but I don't pull enough weight in my company to demand from a vendor that they release the code.

     



  • @jspenguin said:

    As for the kernel module... well, modinfo says it's GPL... I wonder if I could hold them to that? They're already violating the GPL (Linux kernel, busybox, uClibc, etc.), but I don't pull enough weight in my company to demand from a vendor that they release the code.
    I think you can take it to the fsf.

    Cause, I think (I might be wrong, IANAL) you can give the kernel+modules+everything to someone else, (covered by GPL) and they should get access to the source as well, because you didn't modify, you can point them at your source.



  • Just a thought, but maybe it's better that you NOT have the code, considering what you've already seen...



  • What company is this again? 

    <hints id="hah_hints"></hints>


  • @jspenguin said:

    I especially like the sprintf("%s", $string).
     

    What, you think he should have used just

    sprintf($string)
    ?  That would introduce a format-string vulnerability!

     

     

    ;-) 



  • @jspenguin said:

    I'm currently in the process of customizing the firmware for a RAID controller used  in some of my company's products.
     

    Hmm, I'd be careful with this. If you take this heap of crap and include it in a product that you company then goes on to sell (distribute), you're either doing that without a license or under the GPL, which requires that source code is made available upon request. If your upstream vendors are not providing this, it's impossible to comply. This may come back to bite you in the ass in more ways than just the awful source code.



  • Just found another one... 

     

    function GetMemorySize()
    {
        global $memsize;
       
        $memstr = shell_exec("cat /proc/memory");
        sscanf($memstr, "%*[^1-9]%s\n", $memsize);
        if ($memsize == false) $memsize = "Unknown";
        $infolog = sprintf("Memory Size : %s\n", $memsize);
        writelog($infolog);
    }

     



  • @Aaron said:

    What company is this again? 
     

    I'm gonna bet on Areca, specifically this product: http://www.areca.us/products/sas_to_sas_cable.htm 

    Check out the PDF in the "Relatived Resource" link on that page. It's a small box with....

    • LCD Control Panel for setup, alarm mute and configuration
    • System status indication through LCD, LED and alarm buzzer
    • Firmware-embedded web browser-based RAID manager - access your RAID subsystem from any standard internet browser via 10/100 Lan port
    • Intel IOP341 I/O Processor

    Linux happens to run on the IOP341, so this fits all the requirements.

    I also don't see the GPL source code for the embedded linux system made available anywhere on the site. Uh-oh. 

     

    Edit: It's not just that specific product, but a range of external storage boxes that all share those same specs. 



  • @Nandurius said:

    I also don't see the GPL source code for the embedded linux system made available anywhere on the site.

    IANAL but you only have to hand out sources to people who get the binaries.



  • @Lingerance said:

    @Nandurius said:
    I also don't see the GPL source code for the embedded linux system made available anywhere on the site.
    IANAL but you only have to hand out sources to people who get the binaries.
     

    You're right, of course, but most companies who actually comply with the GPL simply make the sources available on the website. I wasn't trying to suggest that they had to have it there, publicly available, I only took that as an indicator of their interest in being compliant. The OP, on the other hand, is entitled to receive all gpl sources that were used in the product.

    Btw: The binaries (firmware images) _are_ actually available on the website, and available to anyone. Since they are distributing these, and if these images contain any GPL code (such as the kernel module that claims to be GPL) then the source of the affected parts should be made available also.



  • @Nandurius said:

    @Lingerance said:

    @Nandurius said:
    I also don't see the GPL source code for the embedded linux system made available anywhere on the site.

    IANAL but you only have to hand out sources to people who get the binaries.
     

    You're right, of course, but most companies who actually comply with the GPL simply make the sources available on the website. I wasn't trying to suggest that they had to have it there, publicly available, I only took that as an indicator of their interest in being compliant. The OP, on the other hand, is entitled to receive all gpl sources that were used in the product.

    Btw: The binaries (firmware images) are actually available on the website, and available to anyone. Since they are distributing these, and if these images contain any GPL code (such as the kernel module that claims to be GPL) then the source of the affected parts should be made available also.




    IANAL, but section 3b of GPL v2 states the following:



    b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,



    This means you can obtain the source, even without acess to the binary. This does not mean they must have it on their site however. They should provide it however if you ask for it wich is why most people just put it there. One can try to contact them by mail and see if they comply.



  • @Nandurius said:

    @Aaron said:

    What company is this again? 
     

    I'm gonna bet on Areca, specifically this product: http://www.areca.us/products/sas_to_sas_cable.htm 

    Check out the PDF in the "Relatived Resource" link on that page. It's a small box with....

    • LCD Control Panel for setup, alarm mute and configuration
    • System status indication through LCD, LED and alarm buzzer
    • Firmware-embedded web browser-based RAID manager - access your RAID subsystem from any standard internet browser via 10/100 Lan port
    • Intel IOP341 I/O Processor

    Linux happens to run on the IOP341, so this fits all the requirements.

    I also don't see the GPL source code for the embedded linux system made available anywhere on the site. Uh-oh. 

     

    Edit: It's not just that specific product, but a range of external storage boxes that all share those same specs. 

     

     

    It's not Areca. None of the Areca controllers I've seen run Linux. The company is called QSAN, and the controller is the S100C-8. 

     

    The firmware binaries aren't available on their site. In fact, to get the latest version of firmware when it comes out, I usually have to hack into a controller and dump the firmware image. We don't actually get the firmware file through the "proper" channels for several months.

     



  • @pinguis said:

    IANAL, but section 3b of GPL v2 states the following:

    b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,

    This means you can obtain the source, even without acess to the binary. This does not mean they must have it on their site however. They should provide it however if you ask for it wich is why most people just put it there. One can try to contact them by mail and see if they comply.

    Copyright law only applies to redistribution of a work.  If you do not give someone the binaries, then you cannot be required to comply with any license.  The source only has to be provided to those  you distrubute the binaries to. 



  • @morbiuswilters said:

    Copyright law only applies to redistribution of a work.  If you do not give someone the binaries, then you cannot be required to comply with any license.  The source only has to be provided to those  you distrubute the binaries to. 




    But then how do you define the third party? I take the meaning that the binding contract between the provider and recipient makes the distributor provide the source to whom requests it.



  • @pinguis said:

    But then how do you define the third party? I take the meaning that the binding contract between the provider and recipient makes the distributor provide the source to whom requests it.

    I don't understand what you are saying.  If I take GPL'd code and make changes to it, I do not have to provide anyone with my sources.  However, if I give you a copy of my binary changes, I must also provide the sources to you.  I am under no obligation to provide the sources to anyone I have not distributed the binaries to.  What part of this doesn't fly with you?



  • @morbiuswilters said:

    I don't understand what you are saying.  If I take GPL'd code and make changes to it, I do not have to provide anyone with my sources.  However, if I give you a copy of my binary changes, I must also provide the sources to you.  I am under no obligation to provide the sources to anyone I have not distributed the binaries to.  What part of this doesn't fly with you?




    But in your opinion who does the third party in the 3b section of the GPL refers to? not you who distributed the code, not he who recives it... Who then?



  • @pinguis said:

    But in your opinion who does the third party in the 3b section of the GPL refers to? not you who distributed the code, not he who recives it... Who then?

    It doesn't matter who the GPL is referring to -- you are only bound by the terms of the license when you redistribute the licensed source code.  So if you aren't providing someone a copy of the binaries, you don't have to provide them with the sources.  Obviously you get into some very untested legal waters if you take it far enough.  For example, if I provide a tool that applied a binary patch to someone else's binary kernel, I'm not redistributing the kernel itself so I'm not required to provide my sources.  Now, what if I provide the other binary kernel and its sources on a CD with my product with a second CD that contains my binary patch?  I'm distributing two different binaries -- those of the 3rd party kernel and my own, but I'm only compelled by the GPL to release the source provided by the kernel and not my modifications since my modifications do not themselves contain GPL'd code. 



  •  @morbiuswilters said:

    What part of this doesn't fly with you?

    One word for you: Portugal

    Need I say more?



  • @MasterPlanSoftware said:

    One word for you: Portugal

    Need I say more?

     

    Is this some new class of Award, like the (censored) HHGTTG Rory? Googling "gpl portugal" brings up a lot of gas station/liquified propane stuff. 



  • @MarcB said:

    Is this some new class of Award

    No, it's an "inside joke". Participate on IRC and you'd get it.


Log in to reply