Other

  • The Old New Thing

    It rather involved being on the other side of this airtight hatchway: Denial of service by high CPU usage

    • 40 Comments

    We received the following security vulnerability report:

    Windows is vulnerable to a denial of service attack that consumes 100% CPU.

    1. Use the following procedure to create a file that is enchanted by magic pixie dust: [...]
    2. Rename the file to TEST.EXE.
    3. Execute as many copies of the program as you have CPU cores.

    Observe that CPU usage climbs to 100% and never goes down. This a clear demonstration that Windows is vulnerable to a denial of service attack from magic pixie dust.

    The magic pixie dust is a red herring. This vulnerability report is basically saying "If you are allowed to run arbitrary programs, then it is possible to run a program that consumes all the available CPU."

    Well, duh.

    This is another case of if I can run an arbitrary program, then I can do arbitrary things, also known as MS07-052: Code execution results in code execution. (Or in the lingo of Internet memes, "High CPU is high.")

    Now, of course, if the magic pixie dust somehow allows a user to do things like access resources they do not have access to, or to circumvent resource usage quotas, then there would be a serious problem here, and if if the high CPU usage could be triggered remotely, then there is a potential for a denial-of-service attack. But there was nothing of the sort. Here's a much less complicated version of magic pixie dust:

    int __cdecl main(int, char **) { for (;;) { } /*NOTREACHED*/ }
    
  • The Old New Thing

    Cargo-cult registry settings and the people who swear by them

    • 14 Comments

    Two customers (so far) wanted to know how to increase the duration of taskbar balloon notifications on Windows Vista. (By the way, I gave the answer some time ago.)

    They claimed that on Windows XP, they were using the registry key HKEY_CURRENT_USER\Software\Microsoft\Windows\Current­Version\Explorer\Tray­Notify, setting the value Balloon­Tip to a REG_DWORD specifying the number of seconds the balloon should appear. They wanted to know if this still worked in Vista.

    Heck, it didn't work even in Windows XP!

    That undocumented registry key actually controls whether the Windows XP taskbar should show the "To see the hidden icons, click this button" tip. It has nothing to do with how long the balloon stays on the screen.

    A quick Web search suggests that that particular setting has reached cult status, with everybody saying that the setting controls balloon duration, and nobody actually testing it. It's just a matter of faith.

    Even the sometimes-suggested trick of putting the registry key name in MSDN so searches can find it and direct users to the correct method wouldn't have helped, because this was the wrong registry key to begin with.

    (Remember, the answer is in the linked article.)

  • The Old New Thing

    Only senior executives can send email to the All Employees distribution list, but mistakes still happen

    • 26 Comments

    Some time ago, a senior executive sent email to the All Employees distribution list at Microsoft announcing that a particular product was now available for dogfood. The message included a brief introduction to the product and instructions on how to install it.

    A few hours later, a second message appeared in reply to the announcement. The second message came from a different senior executive, and it went

    I got your note and tried it out. Looks good so far.

    Oopsie. The second senior executive intended to reply just to the first senior executive, but hit the Reply All button by mistake. This would normally have been caught by the You do not have permission to send mail to All Employees rule, but since the mistake was made by a senior executive, that rule did not apply, and the message went out to the entire company.

    People got a good chuckle out of this. At least he didn't say anything embarrassing.

    Bonus chatter: I'd have thought that these extra-large distribution lists would be marked Nobody can send to this distribution list, and then when somebody needed to send a message to the entire company, the email admins would create a one-day-only rule which allowed a specific individual to send one message.

  • The Old New Thing

    If a lot of settings are ignored when set in a DLL, why bother even letting you set them on a DLL?

    • 34 Comments

    There are many settings that are ignored when set in a DLL. /LARGE­ADDRESS­AWARE. Size­Of­Stack­Reserve and Size­Of­Stack­Commit. There are plenty of others. Commenter 640k asks why these settings even exist for DLLs if they has no effect.

    Because they are settings for PE modules in general.

    If there were separate file formats for EXEs and DLLs, then there would have to be two different module loaders, one for EXEs and one for DLLs. This creates extra work for no particular benefit aside from satisfying some anal-retentive compulsion that nothing be wasted. As far as I can tell, all operating systems use a common file format for both executables and libraries.

    If it really bothers you, you can consider this flags as Reserved for future use when applied to DLLs.

  • The Old New Thing

    A discovered quirk is just few steps away from becoming a feature

    • 24 Comments

    Commenter Cherry wonders who invented all those strange syntaxes, like set " to show all environment variables, including the hidden ones.

    An interesting historical note is the origin of the convention in unix that files whose names begin with a dot are hidden by default (here's the relevant portion). That article highlights how a discovered quirk is just a few steps away from becoming a feature.

    As Master Yoda might put it: Discovery leads to dissemination. Dissemination leads to adoption. Adoption leads to entrenchment. Entrenchment creates a compatibility constraint.

    As I've noted many times, the batch language was not designed. It simply evolved out of the old CP/M program SUBMIT, which was an even more rudimentary batch processor. (The original SUBMIT.COM didn't have conditional branches. It merely ran every line in your batch file one after another.)

    One of the consequences of something that old is that any quirk, once discovered, can turn into a feature, and from there it becomes a support burden and compatibility constraint. We've seen this many times before: Counting the number of lines in a file by exploiting a buffer underflow bug in FIND.COM. Update the last-modified time of a file by using a magic sequence of punctuation marks. Echoing a blank line by typing ECHO.. All of these were accidental discovered behaviors (just like unix dot files) which became entrenched. Even when the underlying program was completely rewritten, these special quirks had to be specifically detected and painstakingly reproduced because so many programs (i.e., batch files) relied on them.

    For set ", it's a case of taking advantage of two quirks in the implementation: The first quirk is that a missing close-quotation mark is forgiven. That means that set " is logically equivalent to set "".

    You are therefore asking for a filtered list of environment variables, but passing the logical equivalent of no filter. Specifically, you're asking for all environment variables which begin with the empty string, and it so happens that every string begins with the empty string. The second quirk is that when an explicit filter is applied, the set command disables its default filter of "Hide environment variables whose names begin with an equals sign."

    In other words, the code goes like this:

    foreach (var entry in Environment.GetEnvironmentVariables()) {
     if (prefixFilter != null ?
         entry.Key.StartsWith(prefixFilter) :
         !entry.Key.StartsWith("=")) {
      Console.WriteLine("{0}={1}", entry.Key, entry.Value);
     }
    }
    

    Perhaps this is a bug, and it should have been written like this:

    foreach (var entry in Environment.GetEnvironmentVariables()) {
     if (!entry.Key.StartsWith("=") &&
         (prefixFilter == null || entry.Key.StartsWith(prefixFilter))) {
      Console.WriteLine("{0}={0}", entry.Key, entry.Value);
     }
    }
    

    But it's too late to fix it now. People have discovered the quote trick, so it's now a feature and therefore a compatibility constraint.

  • The Old New Thing

    Le Chatelier's Principle in action: Administrative overrides

    • 43 Comments

    Today we have another example of Le Chatelier's Principle as interpreted by John Gall: Every system resists its proper functioning.

    There was a video card manufacturer which was using the AppInit_DLLs key so that they could inject their DLL into every process. I have no idea why. Perhaps to get a nice bonus.

    In Windows Vista, the AppInit_DLLs registry key was deactivated for both engineering and security reasons. Oh no! Undeterred, the video card manufacturer issued an update to their driver so that in addition to adding themselves to AppInit_DLLs, they also set the administrative override switch that re-enabled the feature. Boom, they probably got a second bonus for that.

    Another lesson from this story is that if you provide an administrative override to restore earlier behavior, then you never really removed the earlier behavior. Since installers run with administrator privileges, they can go ahead and flip the setting that is intended to be set only by system administrators.

  • The Old New Thing

    How do I set a breakpoint on a function whose name contains spaces or other special characters?

    • 3 Comments

    If you use one of the command line debuggers based on the Debugger Engine, you can set a breakpoint on a function whose name contains spaces or other special characters by quoting the symbol name. The trick here is that you do not quote the entire string; you quote only the symbol name.

    0:001> bu @!"CSimpleArray<wchar_t *>::CSimpleArray<wchar_t *>"
    

    Note that the quotation marks do not go around the @! part. They go only around the symbol. (Otherwise, the debugger thinks you are setting a breakpoint action.)

    Another trick for setting breakpoints is using tab autocompletion for symbols. If you type bp contoso!*Widget* and then hit Tab repeatedly, you will cycle through all the matches. (It takes a few seconds to build the list of matches, so be patient the first time you hit Tab.)

    Personally, I use the x command to print out all the matches, and then cherry-pick the one I want.

    0:001> x contoso!*Widget*
    00af114c contoso!CreateWidget
    009fe863 contoso!DestroyWidget
    00a2e161 contoso!MakeWidgetReadOnly
    00a93168 ...
    
    0:001> bp 00a2e161     set breakpoint on MakeWidgetReadOnly
    
  • The Old New Thing

    Microspeak: bar check

    • 15 Comments

    A bar check sounds like the sort of thing you receive at the end of a long evening of drinking, but that's not what a bar check is.

    Among the things that happen at ship room meetings is reviewing each bug that has a proposed fix and deciding whether to accept or reject the fix.

    Another thing that happens at ship room meetings is the bar check: The person representing the bug describes the issue and what is known about it so far and asks for a preliminary assessment from the ship room as to whether this is the sort of bug they would approve if a fix were available, in other words, whether it meets the bug bar. If the answer is No, then there is no need to go to the effort of developing a fix for it right now, since you know it would get rejected anyway.

  • The Old New Thing

    The geeky thrill of discovering that two things are really the same thing, just with different labels

    • 15 Comments

    Today's post about binomial coefficients was intended to be a warm-up for Catalan numbers, but it turns out Eric Lippert already covered them, first in the context of binary trees, then in the context of arbitrary trees and forests, and then again in the context of matched parentheses. Another way of seeing the correspondence between forests and matched parentheses is simply to consider each { as an XML open-tag and each } as an XML end-tag.

    One thing to take away from the enumeration of objects controlled by Catalan numbers is that when you see multiplication in a recurrence relation, that typically corresponds to a nested loop. (We saw this ourselves when we studied Stirling numbers of the second kind.)

    The correspondence between binary trees and arbitrary forests is done by simply renaming variables: left­Child and right­Child turn into first­Child and next­Sibling.

    Renaming variables also reveals an interesting equivalence between the two algorithms for reversing a linked list. One technique is to do link rewriting:

    Node *Reverse(Node *head)
    {
     Node *prev = nullptr;
     while (head) {
      // The node we are rewriting
      Node *current = head;
    
      // Advance to next node before
      // we overwrite the outbound pointer
      head = current->next;
    
      // Repoint to previous node
      current->next = prev;
    
      // Advance the trailing pointer
      prev = current;
     }
     return prev;
    }
    

    Another technique is to pop nodes off one list while pushing them onto another.

    Node *Reverse(Node *head)
    {
     Node *result = nullptr;
     while (head) {
      // Pop
      Node *current = head;
      head = current->next;
    
      // Push
      current->next = result;
      result = current;
     }
     return result;
    }
    

    But if you look more closely at the two versions, you'll see that they are not really two algorithms. They are the same algorithm, just with different comments and variable names!

    One of my colleagues used this as an interview question and guided candidates through both algorithms, only to discover later that they were actually the same algorithm, merely viewed through different-colored glasses.

  • The Old New Thing

    Why does the access violation error message put the operation in quotation marks? Is is some sort of euphemism?

    • 24 Comments

    When an application crashes with an access violation, the error message says something like

    The instruction at "XX" referenced memory at "YY". The memory could not be "read".

    Why is the operation in quotation marks? Is this some sort of euphemism?

    The odd phrasing is a consequence of globalization. The operation name is a verb in the infinitive ("read", "write"), but depending on how the containing message is localized, it may need to take a different form. Since the kernel doesn't understand grammar, it just puts the words in quotation marks to avoid having to learn every language on the planet. Imagine if it tried:

    The memory could not be readed.

    The kernel tried to form the passive, which is normally done in English by adding "–ed" to the end of the verb. Too bad "read" and "write" are irregular verbs!

    The more conventional solution for this type of problem is to create a separate error message for each variant so that the text can be translated independently. rather than building sentences at runtime,

    The access violation error message is in a pickle, though, because the underlying status code is STATUS_ACCESS_VIOLATION, and that message contains three insertions, one for the instruction address, one for the address being accessed, and one for the operation. If there were three different status codes, like STATUS_ACCESS_VIOLATION_READ, STATUS_ACCESS_VIOLATION_WRITE, and STATUS_ACCESS_VIOLATION_EXECUTE, then a separate string could be created for each. But that's not how the status codes folks decided to do things, and the translation team was stuck having to use the ugly quotation marks.

Page 3 of 94 (935 items) 12345»