Safe Computing: Integer Arithmetic

August 19, 2011

A few quick notes to set the scene.  Firstly, the need for safe integer arithmetic was pointed out in the CWE list and there’s an excellent example here.   I’m going to use C-like syntax for my examples because it’s the language I’m most familiar with, although the same principles apply to other languages.  Finally, I’ll be using 16-bit arithmetic most of the time because it makes it easier to demonstrate overflow without using inconveniently large numbers.  Where appropriate it will be necessary to imagine that the code is running on a 16-bit system so that the 16-bit values are not automatically widened to 32 bits or more.

I’m going to use new keywords for integer variable types: int<n> to indicate a signed integer n bits wide, e.g., int32 for a 32-bit signed integer; and nat<n> to indicate an unsigned integer, e.g., nat32 for a 32-bit unsigned integer.  In mathematics, natural numbers are the positive integers, sometimes (as in this case) including zero, and I find “unsigned int” unnecessarily long-winded and abbreviations like “uint” ugly.

Making integer arithmetic safe is simple in principle and can be summed up briefly: all integer arithmetic must either produce the right answer or cause execution to stop.  I’ll leave vague exactly what “stop” means because it depends on context, but the same sort of mechanisms already used to deal with a divide-by-zero are probably suitable.

In the following example, execution will stop on the second line:

nat16 a = 65535;
nat16 b = a + 1;

Execution will also stop on the second line in this example:

nat16 a = 32767;
int16 b = a + 1;

More subtly, this also needs to cause execution to stop:

nat16 a = 32768;
int16 b = a;

Technically an assignment isn’t arithmetic, but it still needs to be safe. :-)

We need to detect underflow as well as overflow:

nat16 a = 5;
nat16 b = a - 10;

This is a bit trickier:

nat16 a = 32768;
nat16 b = 32768;
nat16 c = (a + b) / 2;

The correct answer is 32768, which will fit into the nat16 type, but the intermediate value of 65536 won’t.  Whether you will get the right answer depends on what type the compiler uses when working out the expression.  In some cases (such as C in a 32-bit environment) the language specification will guarantee that the code succeeds; in other cases, I would suggest that the compiler be permitted to either succeed or to stop at its own convenience.  The only thing it shouldn’t be allowed to do is decide that the answer is zero.  (Unfortunately, that’s exactly what will happen with most real-world compilers!)

On occasion the programmer needs to allow an overflow to occur, so the language  should define a way to do that.  There are a number of options.  The simplest and most elegant would be to introduce a keyword:

nat16 a = 65535;
nat16 b = lenient a + 1; // b will be set to zero

One problem: this code then wouldn’t compile if the compiler didn’t know about the keyword.  Perhaps a pragma, then:

nat16 a = 65535;
#pragma lenient
nat16 b = a + 1; // b will be set to zero
#pragma strict

Yet another alternative would be to require the compiler to ensure that an overflow in an intermediate calculation won’t stop execution if the final result is still correct:

nat16 a = 65535;
nat16 b = (a + 1) & 65535;

However, I’m not sure this approach is feasible in general, i.e., for more complicated expressions.

On a side note, it might also be desirable to simplify the rules determining the types used in expressions, including a straightforward mechanism for the programmer to override the defaults.  I don’t think I should discuss that now, but I’ll try to write about it later in a separate post.

Now it is of course possible for a compiler to do all the above using the standard x86 instruction set – it just needs to check the carry or overflow flag as appropriate after each step.  Why doesn’t this happen?  Nowadays, backwards compatibility would be a problem, but presumably the original issue was performance, and I suspect this is still a concern, particularly where branch instructions would be necessary.  (The INTO instruction is presumably quite efficient, but there is no corresponding INTC instruction for unsigned arithmetic.)

It shouldn’t be too hard for the CPU to come to our aid here.  For unsigned arithmetic, I think the best approach would be introduce a separate overflow bit for each register, rather than (or as well as) having carry and overflow flags.  Writing the register to memory would trigger a software interrupt (or equivalent) if the overflow bit is set, as would using the register in any other inappropriate way.

Also, instructions for writing only part of a register to memory (the low byte, for example) should generate a software interrupt if the remainder of the register is not zero.

For example, on a 16-bit processor and using a hopefully self-explanatory syntax:

move 65535 -> a0     # register a0 is set to 65535 and the a0 overflow bit is cleared.
move a0 -> nat8 x    # write a0 to 8-bit memory location x;
                     # this causes a software exception because a0 doesn't fit in 8 bits.
add 1 -> a0          # a0 is now zero and the a0 overflow bit is set.
move a0 -> nat16 y   # this causes a software exception, because the overflow bit is set.
add a0 -> a1         # add the value of a0 to a1;
                     # this causes a software exception because the a0 overflow bit is set.

move 65535 -> a0    # a0 is set to 65535 and the a0 overflow bit is cleared.
move 65535 -> a1    # a1 is set to 65535 and the a1 overflow bit is cleared.
add 1 -> a0         # a0 is set to zero and the a0 overflow bit is set.
addc a0, 0 -> a1    # the a0 overflow bit is added to a1;
                    # the a0 overflow bit is now clear;
                    # a1 is now zero and the a1 overflow bit is set.
move a0 -> nat16 x  # zero is written to the sixteen-bit memory location.
move a1 -> nat16 y  # this causes a software exception.
clc a1              # but, if we were to clear the a1 overflow bit first ...
move a1 -> nat16 y  # then this would succeed.

Hopefully, this is clear.  There are details that need filling in, but I think nothing difficult.

Signed arithmetic is much the same, except for one edge case.  There are at least three different ways of distinguishing between signed and unsigned arithmetic; the simplest is distinct arithmetic instructions:

move 255 -> a0       # register a0 is set to 255 and the a0 overflow bit is cleared.
move a0 -> nat8 x    # this will write 255 to the 8-bit memory location x.
move a0 -> int8 x    # this causes a software exception because 255 doesn't fit in
                     # an 8-bit signed variable.  Note that this is a different
                     # instruction code to the above instruction.
adds 32767 -> a0     # a0 is now 33022 (meaning -32514) and the a0 overflow bit is set.
move a0 -> int16 y   # this causes a software exception because the a0 overflow bit is set.
move a0 -> nat16 y   # so does this.

move 65535 -> a0   # a0 is set to 65535 and the a0 overflow bit is cleared.
move 32767 -> a1   # a1 is set to 32767 and the a1 overflow bit is cleared.
add 1 -> a0        # a0 is set to zero and the a0 overflow bit is set.
addcs a0, 0 -> a1  # the a0 overflow bit is added to a1 using signed arithmetic;
                   # the a0 overflow bit is now clear;
                   # a1 is now 32768 (meaning -32768) and the a1 overflow bit is set.
move a0 -> nat16 x  # zero is written to the sixteen-bit memory location.
move a1 -> int16 y  # this causes a software exception.
clc a1              # but, if we were to clear the a1 overflow bit first ...
move a1 -> int16 y  # then this would succeed.

I mentioned an edge case.  This is adding a signed number to an unsigned number.  Consider this code:

nat32 total;
void add_to_total(int32 x)
{
  total = total + x;
}

Simple enough, but … do you do the addition with signed or unsigned arithmetic?  You can’t use unsigned arithmetic because x may be negative.  But you can’t always convert total to int32, either; it may be too large.

One solution would be to convert to int64, but this is inefficient if the processor is 32 bits.  Another is to rewrite the code:

void add_to_total(int32 x)
{
  if (x > 0) total = total + (nat32)x;
  if (x < 0) total = total - (nat32)(-x);
}

But now we’re introducing branches, which is also inefficient.

My suggestion is to introduce a new type, int33 (as well as int9, int17, and int65) which is that extra bit longer.  These types would only be valid as intermediate values in expressions, not as variables.  The code then becomes:

void add_to_total(int32 x)
{
  total = (int33)total + x;
}

The compiler is then free to deal with this in the best way available to it in the given instruction set.  Note that by requiring the programmer to explicitly request this special treatment, we avoid inefficiency in cases where the programmer expects total to always be small enough to convert to int32.  In these cases it might be wise for the compiler to generate a warning unless the programmer explicitly says this is OK:

void add_to_total(int32 x)
{
  total = (int32)total + x;
}

Going back to the CPU, there are several ways a new design could help the compiler out in implementing int33.  The simplest would be to give the arithmetic registers a dedicated sign bit, so that register values are always int33 (or int65, or int129).  This would require separate instructions for loading signed and unsigned values from memory (so the CPU knows whether to sign-extend) but since this is already required when loading values smaller than the register size this probably isn’t a big issue.

I hope this is all clear enough.  Please email me or leave a comment if you have any questions.

Harry.

2011 CWE/SANS Top 25 Most Dangerous Software Errors

July 1, 2011

The list can be found here.  The following is my take on what we (meaning society as a whole) should be doing to reduce the risks; remember, I (almost) never care about backwards compatibility so not all of my suggestions are very practical. :-)

1CWE-89: Improper Neutralization of Special Elements used in an SQL Command (‘SQL Injection’)

Developers need to stick to parametrized queries.  Programming languages and database interfaces should be designed so as to prohibit the construction and execution of ad-hoc query strings.  Programming languages should be developed that mix SQL (or SQL-like) functionality with traditional code, to make parametrized queries (or the equivalent) more natural.

Also, I suspect that putting the back-end code in the database itself (rather than, for example, on a web server) would prove a safer programming model; this can already be done to some extend with SQL stored procedures, but the language is clunky and you’re still using SQL procedure calls as the interface.

2CWE-78: Improper Neutralization of Special Elements used in an OS Command (‘OS Command Injection’)

This is all about software that uses subprocesses to run command-line OS tools, although the same issue applies to the use of third-party software via a subprocess.  This one is easy: developers shouldn’t do that, ever.  Operating systems should ensure that there is always an alternative; future operating systems (if unencumbered by backwards compatibility issues) should eliminate exec and similar functions.  (Instead, a well-defined plugin mechanism should exist to allow software to cooperatively interact.)

3CWE-120: Buffer Copy without Checking Size of Input (‘Classic Buffer Overflow’)

Programming languages should be updated and/or modified to provide for safe pointer arithmetic.  It would be preferable if this was supported by the CPU.  Safe integer arithmetic is also essential.  In the meantime, developers need to do their best to be very very careful when dealing with buffers; the CWE discussion covers this in some detail.

4CWE-79: Improper Neutralization of Input During Web Page Generation (‘Cross-site Scripting’)

HTTP and HTML need to go.  They aren’t even close to adequate for the way we use the web nowadays.  I’d like to see a new protocol, www://mysite.com, with all the obvious changes (and perhaps a few not so obvious ones).  During the (no doubt extended) migration period, sites could be available in both flavors via automated conversion in one form or another.

5CWE-306: Missing Authentication for Critical Function

Not much to say about this one; it mostly boils down to developer common sense.  It could be helpful if future internet protocols (i.e., either a hypothetical replacement for TCP or a replacement for or variant of SSL) came with built-in multiplexing functionality.

6CWE-862: Missing Authorization

Much the same as #5, except that I suspect it is most prevalent in web applications, in which case my comments for #4 apply as well.

7CWE-798: Use of Hard-coded Credentials

I think a mandatory death penalty for programmers who do this is probably the most reasonable approach.  Better programming models for database-backed applications (as per #1) may be of some help.

8CWE-311: Missing Encryption of Sensitive Data

Built-in encryption support in operating systems and perhaps in network protocols.  It needs to be easier for programmers to use encryption, and in particular for them to use it correctly.  Windows has done quite well in this regard, I think.  In particularly sensitive situations, though, nothing beats expert assistance.

9CWE-434: Unrestricted Upload of File with Dangerous Type

The underlying issue is lousy web server design, in particular the use of a general-purpose file system (rather than a dedicated one) for storing web content, including executable content.  This could be improved in combination with #4 or independently.

10CWE-807: Reliance on Untrusted Inputs in a Security Decision

Largely developer carelessness, I suppose.  Better languages could help.  So could banning PHP.  Relates somewhat to #4 in many cases.  (The hypothetical www: protocol would certainly include login sessions as a native concept.)

11CWE-250: Execution with Unnecessary Privileges

Operating systems (and perhaps languages) need to provide better support for reduced-privilege execution.  Future (backwards-compatibility-unencumbered) operating systems should run most applications with very limited privileges as a matter of course.

12CWE-352: Cross-Site Request Forgery (CSRF)

See #4.

13CWE-22: Improper Limitation of a Pathname to a Restricted Directory (‘Path Traversal’)

Again, the underlying problem here is the use of a general-purpose file system for storing potentially malicious data (or data that may be maliciously retrieved).  Either operating system support or good open-source code libraries would be helpful.  In the case where the content is part of the application, development tool support would be helpful.  (That is, development tools should allow programmers to easily incorporate read-only embedded file systems into an application.)

14CWE-494: Download of Code Without Integrity Check

Software shouldn’t usually be downloading code of its own accord. On the rare occasions when it is necessary, the developer needs to take great care.  Better operating system support for the appropriate cryptographic tools might help.

Operating systems should also include built-in mechanisms for third-party software to stay up to date.  This would help significantly with what is probably the most common scenario.

15CWE-863: Incorrect Authorization

I’m guessing this is only really common in web-based applications, so once again, see #4.

16CWE-829: Inclusion of Functionality from Untrusted Control Sphere

Partly developer laziness and/or carelessness, but better development tools could help.  In the case of a web application, see #4.

To expand on this a little: I’m not sure whether CWE/SANS consider DLL hijacking (aka Binary Planting) in this category but it’s certainly analogous; the proper solution to DLL hijacking is to use static libraries (preferably source code!) instead.  I imagine there is a similar option in most other scenarios in which this issue comes up, but better development tools may be necessary.

17CWE-732: Incorrect Permission Assignment for Critical Resource

Operating systems should provide better support for developers when it comes to storing critical resources.  Developers shouldn’t always need to assign permissions explicitly.  Better use of and support for embedded file systems could also help.  Ideally, all applications should contain only a single file (with an embedded file system or the equivalent if necessary) and operating systems and developer tools should assist programmers in this goal.  Data stores such as the Windows registry and application data stores should be automatically divided into segments that are only accessible by the application that created them.

18CWE-676: Use of Potentially Dangerous Function

Better languages and run-time libraries.

19CWE-327: Use of a Broken or Risky Cryptographic Algorithm

As per #8, operating system support can help.  Developer education is essential.

20CWE-131: Incorrect Calculation of Buffer Size

See #3, as this is the just same problem from the other end.

21CWE-307: Improper Restriction of Excessive Authentication Attempts

I don’t have anything more to suggest on this one.  (Shocking, isn’t it?)  Developer education (such as this list!) is the key.

22CWE-601: URL Redirection to Untrusted Site (‘Open Redirect’)

See #4.

23CWE-134: Uncontrolled Format String

Special case of #18, same solution.

24CWE-190: Integer Overflow or Wraparound

Already mentioned in #3, modifying languages (or providing new languages) to support safe integer arithmetic is essential to safe computing, and CPU support would be very helpful.  I’m planning to write more about this later.

25CWE-759: Use of a One-Way Hash without a Salt

Developer education.  Operating system support and good open-source libraries would help.  Since this is probably most prevalent on the web, the hypothetical www: protocol could probably help out as well by mandating authentication methods that don’t actually give the password to the web site in the first place.

 

 

 

 

 

 

 

Safe Computing: Heterogeneous Multi-Core

June 10, 2011

It was bought to my attention recently that it’s been a long time since I’ve posted anything in my Safe Computing series.  Today I want to talk about an idea for post-modern CPUs that I’m going to call Heterogeneous Multi-Core (HMC).  As always, this is strictly a theoretical exercise; I’d be delighted if CPU designers picked up my ideas, but I don’t actually expect it to happen, so don’t bother pointing out that it won’t.  On the other hand, please do point out any logical errors or oversights on my part.

Heterogeneous Multi-Core means exactly what it says: the CPU has more than one type of core.  Such CPUs may well exist already, but the best known lines of CPU are homogeneous, that is, each core is (more or less) the same as the others.  (I don’t count integrating a GPU into a CPU because this is such a trivial case, and because if I understand correctly the CPU and GPU are still logically distinct even if they are on a single chip.)  Note that in this context I’m talking about differences as seen by a software developer, rather than hardware differences, although of course the one largely determines the other.

There are all sorts of possibilities within this general concept.  For example, you could have cores of varying speeds (in fact I gather this is already done).  I’m mainly interested in possibilities that would help with Safe Computing, though, so I’m going to concentrate on that.

Master Core

The master core (or perhaps cores) runs the top-level kernel.  The key idea here is that each master core determines all execution context for the cores under its command.  The various servant cores don’t have a kernel mode; everything that would normally be done in kernel mode is instead handled by instructions from the master core over a dedicated channel.

In principle, the master core could run the OS kernel, but I think it would be preferable for it to run a hypervisor instead.  Also, to minimize compatibility issues, the hypervisor code should be part of the CPU firmware rather than being a third-party product.  You’d need some kind of message queue from the servant cores so that the OS kernel(s) can give the hypervisor instructions.

The master core should use an instruction set suitable for the purpose and the hypervisor should be single-threaded.  The source code should also be available to the public so it can be analyzed for possible flaws.

Hypervisor device drivers for on-board devices could be included in the motherboard firmware.  (These wouldn’t be run on the master core itself, of course.)  Similarly, the motherboard can provide a base OS in firmware to serve the user interface functions currently provided by the BIOS as well as those normally provided by a host OS or hypervisor console.

I’m guessing that each master core could handle at least 64 servant cores, and quite possibly many more than that.  So it seems likely that for the time being only one master core would be needed.  This would be preferable, because it simplifies the hypervisor design significantly.

Central Processing Cores

I’m going to call servant cores intended for general processing, i.e., running the OS and applications, Central Processing Cores, or CPCs for short.  As previously discussed, these cores wouldn’t have any form of kernel mode.  Instead, they would receive instructions from the Master Core (MC) to set security context, load or save register values, start, stop, and so on.

One useful optimization would be for the CPCs to have two sets of registers – somewhat similar to hyperthreading – so that all the information necessary for the next thread to execute can be loaded into the core ahead of time.  When the MC issues the instruction to switch context, the core could begin executing the new thread almost immediately.  The register contents for the old thread could then be lazily saved back to main memory before setting up for the next context switch.

As a special exception to the “no kernel mode instructions” rule, a halt command could be available to code running on the CPC.  If the MC has already configured and approved the next context switch, that could happen immediately, if not, the CPC would halt execution until instructed by the MC to continue.

x86/AMD64 Cores

Although I don’t normally talk about backwards compatibility in my “Safe Computing” posts, this particular possibility is too significant to overlook.  An x86 core would implement the user mode parts of the x86 instruction set.  It should be simpler than a “real” x86 core because it doesn’t need kernel mode.  An AMD64 core would implement the AMD 64-bit instruction set.  It might be preferable to provide cores that can do either, but I’d leave this to the experts to decide. :-)

The theory here is that operating systems could be ported to the HMC CPU while retaining the ability to run existing PC applications.  That is, the operating system would need to be ported, but the applications wouldn’t.  Windows already supports multiple CPU architectures, so it should be (relatively!) simple for Microsoft to port it to HMC.  I’m not sure about Linux, but I know there is already support for paravirtualization under Xen, so one option would be to port Xen, or, rather, re-implement the Xen guest machine interface.

It would also be desirable to be able to run unmodified PC operating systems in virtual machines.  This would require a bit more work.  Conceptually it would be cleaner to handle the kernel mode parts entirely (or almost entirely) in software.  There are some instructions which exist in both kernel and user mode but behave differently, so these would need to be implemented carefully to avoid causing problems.  We would also need x86-like address space mapping, which is a shame, but would probably be worth it.

In summary, some additional hardware assistance might be appropriate, but only if it doesn’t complicate the cores too much.

Non-x86 Processing Cores

Just because we want some x86/AMD64 cores for running legacy applications doesn’t mean we shouldn’t have better instruction sets available as well.  I keep meaning to write about some of the ways a CPU instruction set could help make software more reliable, but so far I’ve only posted about protecting the flow of execution.  I’ll try to do better in the coming months.

Since I mentioned it already, I will point out that while we of course need to be able to restrict which parts of memory the CPC can read and/or write to, we don’t necessarily need a fully mappable per-process address space of the sort x86 CPUs provide.  Once again, I’ll try to discuss this in more detail later this year.

Kernel Cores

There could be some advantage to having a separate core type designed specifically for OS kernels, but my ideas on this front are still pretty unformed.  I’d probably insist on a single-threaded design, so that wouldn’t work for ported operating systems. :-)

IO Cores

When it comes to the hypervisor’s device drivers, we’re free to insist on a new instruction set, since architectural differences would almost certainly make porting existing drivers infeasible anyway.  (Also, we’re talking about a brand new hardware platform, so it seems likely that most of the core devices will be new designs.  Conventional motherboard designs are fairly unsatisfactory from a security standpoint – with luck, the subject of a future post – so that further reduces any risk from changing the instruction set.)

I don’t really have many solid ideas about IO core design either, but I’m of the opinion that it would be beneficial to use a customized instruction set.  Again, the drivers should be single-threaded.  We’d need an efficient way of passing packets of data between related drivers, including both hypervisor and OS-level drivers.  Some IO cores might be dedicated to running a single driver, i.e., without multitasking, which I think would make programming some sorts of drivers a whole bunch easier.

I’d also want to investigate whether we could eliminate the need for DMA by using dedicated IO cores with a suitable instruction set and direct access to the IO bus(es).  As well as potential security benefits, if we assume that there will be only a single multi-core CPU per motherboard, this would mean that only the CPU would need to talk to the RAM, which has to simplify all sorts of issues around caching and locking memory access.

Multimedia Cores

It might be useful to have a cheap and simple core designed specifically for applications that are generating sounds; it shouldn’t need to be all that fast, since audio frequencies are 20kHz or lower, although you’d need enough power to process, say, MP3 data in real-time.  (I presume dedicated hardware support would speed this up.)

The main idea here is to ensure that audio applications aren’t being interrupted arbitrarily by other tasks, so as to reduce pops and crackles and to make it possible to minimize latency.  A direct channel from the audio multimedia core to the audio IO core might be sensible – personally I’d be inclined to bypass the need for audio device drivers altogether and just have a couple of analog output pins on the CPU, but I imagine that would horrify all the audiophiles. :-)

Video multimedia is a different story.  I’m not sure that a completely distinct instruction set would be sensible, but perhaps an extended instruction set to provide hardware assistance to codecs could be provided on only some of the CPCs?  On the other hand, the OS would then have keep track of which threads needed which cores, which might be more trouble than it was worth.

GPU Cores

Mentioned only because it is so obvious.  I don’t have the background knowledge to weigh in on the argument about whether separate or integrated GPUs are better, although I do want to see standardization on the instruction set.

Well, I guess that’s all.  Thanks for reading.

Harry.

When Guest is the administrator

May 5, 2011

Nommo was kind enough to point me to his latest blog entry which discusses a troubleshooting case where the Guest account had somehow wound up being the only active administrator account on a Windows Vista computer.  This was reasonably easy to reproduce (although I used Windows 7 instead) and, indeed, user management tools don’t work as might be expected.

This is interesting.  In most other respects the Guest account still functions as an administrative account.  At first I thought I understood exactly why this happened (to do with the way LAN Manager handled security way back in the days of DOS) but a bit of experimentation showed I was wrong.  It now looks as though a Guest logon is tagged in some way and prohibited from doing any user management – the Guest account can’t even look up its own details – unless you elevate to it from another account, in which case it has user-level access to account management but not administrator-level.  Weird, huh?

Only the actual Guest account is affected; other accounts that are in both Administrators and Guests are not.

Because only account management is blocked, you can get around this in a few ways.  Probably the simplest in most cases is to download the psexec tool from Microsoft.  Start an elevated command-line window by typing “cmd” into the “Search Programs and Files” box in the Start Menu and pressing Control-Shift-Enter.  Then type:

cd /d c:\directory\where\psexec\was\downloaded\to
psexec -s \\127.0.0.1 net localgroup Administrators /add myusername

pressing ENTER after each line and changing “myusername” to the username of the other (currently non-administrative) account.

Alternately, you could edit the registry as described in my earlier post but you don’t need to boot from external media:

  1. Go to the Start Menu and type “regedit” and press ENTER.
  2. Open HKEY_LOCAL_MACHINE, then SYSTEM, then Setup.
  3. Double-click on SetupType in the right-hand pane.  Enter 2 and press OK.
  4. Double-click on CmdLine.  Enter cmd.exe and press OK.
  5. Reboot the machine.  A command window should appear.
  6. Type “net localgroup Administrators /add myusername” and press ENTER.
  7. Type: “exit” and press ENTER.

Again, “myusername” should be replaced with the username of an existing, non-administrative account.  After this procedure, the account is administrative.  You could also use “net user myusername newpassword” to change the password if necessary.  (The same caveat applies as in my previous post: doing this permanently locks you out of any encrypted files in the account.)

Now, obviously Guest shouldn’t be an administrator.  The fact that things behave oddly in this situation is not a bug.  However, if Guest is an administrator the normal recovery options don’t work properly.  In particular you are supposed to be able to log in as Administrator if no usable administrative accounts exist, and in this situation you can’t, and this is a bug.

Hope this helps.

Wikileaks vs. Facebook

May 5, 2011

Authors note: I was recently involved in a discussion on a private mailing list about Julian Assange’s recent diatribe against Facebook concerning privacy.  I suggested this was hypocritical, and was asked why I thought Wikileaks had invaded people’s privacy.  This is my reply, with only a few minor edits.

I believe that employees, including government/diplomatic employees (such as ambassadors) are entitled to a reasonable degree of privacy with regards to their work in the absence of evidence that they have misused it.  This privacy was violated, IMO, by the public release of confidential advice (the diplomatic cables) that they had given their employer.

For my part I would certainly consider my privacy violated if my work email was publicly released, although I don’t think I have a great deal to be embarrassed about.

Mr. Assange is reported to have said that diplomats should only “write reports they are proud of” or something to that effect.  This doesn’t make sense to me.  A diplomat might be justifiably proud of accurate reporting and/or insight, but this doesn’t mean that the report won’t cause embarrassment, and quite possibly harm their career, if made public.

Facts exist, they aren’t something to be proud of or not.  It is in the interest of everybody that the people making decisions know the facts as accurately as is possible, even if it is not reasonable under the circumstances to release them publicly.  (For example, the public release of allegations of misconduct or criminal activity when you are unable to provide evidence would be unfair to the accused; the public release of information on the idiosyncrasies of foreign leaders would lead to your diplomatic service being expelled.)

HOWEVER, even if you disagree that diplomats have any right to privacy, the release of the cables also invaded the privacy of those that the diplomats were writing about.  Making public various allegations of misconduct, when you have no knowledge yourself of the truth or falsity of these allegations, surely counts as an invasion of privacy?

Mr. Assange is also reported to have complained about the public release of the Swedish police report concerning the allegations against him.  I see this as an even clearer case of hypocrisy, since the police (like the diplomats) are a Government agency; if the US diplomatic service shouldn’t keep secrets about third parties from the public, why should the Swedish police do so?

If only those cables (if any) that spoke to misconduct of the diplomats or of the US government had been released, I wouldn’t have any complaints.  But so far I don’t think I’ve heard of a single released cable meeting that criteria.  (If you would like to propose an example, please post a comment.)

Cultural Values and Racism

March 18, 2011

The honorable Tariana Turia MP was quoted today in the New Zealand Herald as saying “But when someone denigrates another culture then for me that’s racist.”  I like this quote.  I think it nicely sums up that aspect of our responsibility to treat one another with due respect.

There are two particular points I want to make about it: firstly, this needs to work both ways.  Let me make it clear that I have absolutely no complaints about the honorable Ms. Turia’s behaviour, but the name of one prominent Maori leader does spring to mind whose attitude towards Pakeha culture has often been less than respectful.

Secondly, there is an important difference between denigrating a culture and questioning it.  Where cultural values are in conflict (as in the case of the foreshore) it should be possible to at least discuss our differences openly and respectfully, so as to hopefully reach a reasonable compromise.  I don’t really understand politics, but it seems to me that one of the big problems with the foreshore debate is that this isn’t happening; the Maori party and the National party have reached a compromise, which seems to me [1] to be reasonable, but the discussion was not (as far as I know) open and the philosophical basis (if any!) for the various decisions has not been presented to the public.

Since this is a widely emotional issue, I will refrain from presenting my own viewpoint on the foreshore debate.

Harry.

[1] From what little I understand of it.

Christchurch: Let’s Not

March 15, 2011

Reports say that the cost of rebuilding Christchurch could be as high as $30 billion dollars.  That’s nearly $7000 for every man, woman and child in New Zealand.  What does that tell you?  It tells me that Christchurch was too darn big.  More than one in every eleven people in New Zealand live in Christchurch – proportionately, that’s nearly half again as large as New York.

Now of course we have to spend that money.  I’m not proposing that the residents of Christchurch live in a tent for the rest of their lives!  But do we have to rebuild it as a single city?  What if there’s another earthquake ten years from now?

Better, I’d have thought, to expand other towns and cities where possible, and perhaps even build one or two new towns or cities if suitable areas can be found.  How about we try to limit population in any one city to 100,000 or so?  Modern technology has reduced the advantages of centralization, at least to some extent; I suspect we cluster together as much out of habit as anything else.  (Water supply is perhaps the main practical issue in terms of where new towns could be placed, and which towns could or could not be expanded.)

And yes, I know … don’t even get me started on Auckland. :-)

Harry.

One More Time: Penalising People for Accidents Doesn’t Help

March 15, 2011

The Herald has an article concerning the sentence handed down to Christopher David McClelland following an accident which killed a cyclist, Patricia Anne-Veronica Fraser, on the 13th of November.

Patricia’s mother, of course, can hardly be expected to take a dispassionate viewpoint; nor can her husband.  It’s very human to seek someone to blame, and in a situation like this it would surely be almost impossible not to.  I’m concerned with Suzanne Charles’ comments, though, particularly in comparing this case with the accidental fatal shooting of Rosemary Ives.

Now, the only information I have on these accidents is what has been in the news, so perhaps I’ve missed an important point, but from what I have read it really was an accident.  Mr. McClelland misjudged the relationship between his car and the cyclists, and struck Mrs. Fraser while passing.

The important difference between this accident and the fatal shooting of Ms. Ives is that in the latter case the killer was not taking those precautions that are appropriate and usual when handling a firearm.  It could be argued that Mr. McClelland did not take an appropriate precaution (pulling into the oncoming lane in order to overtake a cyclist) but it cannot be denied that this is not a usual precaution.  (It’s one I take myself, but that’s because I’m paranoid, and I’m also well aware that I both annoy other drivers and worry the cyclists by doing so.)

My conclusion is that (almost) anyone could have had the same accident.  Punishing Mr. McClelland won’t make cyclists safer.  Neither will changing the law to increase the maximum sentence in future similar cases.  In particular, note that keeping Mr. McClelland off the road for longer wouldn’t make anyone safer, because he is no more likely to cause another such accident than is anyone else; probably less so, in fact.  (Please note, however, that I do not disagree with the sentence that was in fact handed down, but only with the argument that it should have been more severe; there are quite rightly other considerations than road safety.)

The same fallacy comes up regularly in the context of dog safety.  Punishing people whose dog has attacked someone is neither fair nor helpful, unless they actually did something unusual to increase the risk, or failed to take some appropriate and usual precaution.  Nine times out of ten the dog owner being prosecuted acted no differently to any other dog owner, but was merely unlucky in his or her choice of canine.

If we want to change the law, we should determine what precautions are appropriate, and mandate them.  To reduce the risk of dog attacks, we could (for example) require all dogs to undergo some appropriate level of professional training.  Punishing people who failed to have their dogs properly trained (regardless of whether or not there has been an incident) would then encourage people to comply, therefore (presumably!) reducing the risk.

To reduce the risk of cyclists being killed by passing vehicles, the only suggestion I can think of is to make it illegal to pass a cyclist in your lane without pulling into the lane to your right (as you would if overtaking a car).  We would also need to create national standards for cycle lanes, many of which seem far too close to the motorized traffic.

Of course, in many cases this would mean a long queue of traffic waiting behind the cyclist for an opportunity to overtake.  Impatience would be likely to cause accidents with oncoming vehicles, so this might well increase the net risk to the population at large rather than reducing it.  It would be better, perhaps, to prohibit overtaking moving vehicles altogether [1] which would also reduce certain risks at intersections, especially those associated with the right-hand rule.

Realistically, such a law would be impossible to pass, because it would annoy far too many people.  But these, as far as I can see, are our three choices: ban overtaking, ban cyclists from the road [2], or accept that there will be accidents [3].  If anyone has a better idea, speak up – please!

Harry.

[Added 16 March: please see my earlier entry on a related subject.]

[1] Not including the case where you are in a separate lane, obviously. :-)

[2] Ideally, we’d put in cycle lanes everywhere instead, perhaps located next to the sidewalk, on the side opposite the road.  We couldn’t possibly afford to, of course, unless perhaps we did it as part of a work-for-the-dole scheme – which is also politically infeasible.

[3] Actually, given my druthers, I’d probably compromise for urban areas: have slow-moving roads (20kph) which cars share with cyclists and pedestrians, plus faster roads for cars only.  The idea is that any trip by car should involve traveling through at most two slow-moving areas, one when leaving your house and the second when arriving at your destination.  Ideally people would also be able to cycle between any two points without dismounting too often.  Whether or not this would be practicable would depend largely on the existing road layout.  Whether it would be acceptable to the public in general is anyone’s guess.

Installing 32-bit software as SYSTEM in Windows 7 x64

February 20, 2011

Hi,

I recently ran into an issue updating the Sun Java runtime on our x64 machines.  We don’t have the budget for fancy deployment solutions, so we just use a startup script (actually an executable, but that’s just fine-tuning) that checks the version number and runs the installer(s) as necessary.

Installing the 32-bit JRE results in error code 1619, which NET HELPMSG translates as “This installation package could not be opened. Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer package.”  Running the installer in interactive mode produces the same message.  The installer works normally when run from the context of a logged-in user.

Several hours of troubleshooting later, I identified the source of the problem.  Startup scripts run as local system.  In Windows 7, processes that run as local system have a special profile found in c:\windows\system32\config\systemprofile.  Unfortunately, on 64-bit systems, there are two system32 folders; one for 64-bit processes,and another (whose real name is syswow64) for 32-bit processes.  As a result, there are two separate system profiles; one for 32-bit, one for 64-bit.

So what?  Well, the Sun Java installer unpacks into a subfolder of the LocalLow application data directory.  In this case, the folder in question is c:\windows\system32\config\systemprofile\AppData\LocalLow\Sun\Java\jre1.6.0_24.  Because this is a 32-bit process, though, it is really writing to syswow64 instead of system32.

The Windows Installer, however, is a 64-bit process.  So when it is asked to open the MSI file, it’s looking in the wrong place; hence error code 1619.  The file can’t be opened because it can’t be found.

The same underlying problem (duplication of the system profile) seems to be the cause of this problem with Known Folders warning 1002 appearing repeatedly in the event log.  Some 32-bit system process is registering folder paths inside the (32-bit) system profile and of course these folders can’t be found by 64-bit processes.

For the problem with installing 32-bit software, there are a number of possible workarounds.  You could manually extract the installer files, copy them to a suitable path on the local system, and run them directly.  Most installers won’t mind this, although some will balk or fail to function properly.  Alternatively (and this is the solution I chose) you could create the necessary directory ahead of time and add a junction point (mklink /J) from the 64-bit profile to the 32-bit profile (note that this command line assumes you are in a 32-bit context, and has been split for readability):

mklink /J c:\windows\sysnative\config\systemprofile\AppData\LocalLow\Sun\Java\jre1.6.0_24
 c:\windows\syswow64\config\systemprofile\AppData\LocalLow\Sun\Java\jre1.6.0_24

This is the equivalent command if you are in a 64-bit context:

mklink /J c:\windows\system32\config\systemprofile\AppData\LocalLow\Sun\Java\jre1.6.0_24
 c:\windows\syswow64\config\systemprofile\AppData\LocalLow\Sun\Java\jre1.6.0_24

Another possible approach would be to merge the two system profiles together and create a junction point from one to the other.  That would solve this issue for all installers, as well as the Known Folders issue and any other variants.  However, I can’t recommend doing this; it’s too broad a change, and there’s no way to predict what it might break.  If you’re very brave, go ahead, but test thoroughly – and don’t blame me!

Hope this helps.

Harry.

KB2264107 and CWDIllegalInDllSearch

October 10, 2010

This is an FYI for administrators who have installed or who are considering installing KB2264107 and using the 0xFFFFFFFF option for CWDIllegalInDllSearch.

The documentation in KB2264107 (as of August 31, 2010) does not appear to be entirely accurate.  Based on an analysis of the actual behaviour of Windows when loading DLLs, using Process Monitor, I have concluded that the current directory remains in the search order; however, if the DLL is found in the current directory, the load fails.

Under most circumstances this distinction doesn’t matter.  However, it does mean that if the DLL is found in the current directory, the directories specified by the PATH environment variable are not searched.  So if the DLL is normally found by searching PATH, the load will fail if the current directory contains the DLL but not otherwise.  This behaviour may be surprising.

I ran across this problem during an Oracle 10g client installation.  The batch file netca.bat runs a Java program that loads DLLs from the Oracle binary directory; the binary directory is on the search path but is also the current directory.  The DLL specified by the Java program (oranjni10.dll) is located successfully but its dependency (oranl10.dll) is not.  The symptom is an error message from java.exe saying “The program can’t start because oranl10.dll is missing from your computer.  Try reinstalling the program to fix this problem.”

This problem can be worked around in two ways.  You can specify a different CWDIllegalInDllSearch value for java.exe, or you can modify netca.bat so that it doesn’t change the current directory to the Oracle binary directory.  Of course, I can’t be certain that the latter change won’t cause netca.bat to fail under some circumstances, but it seems to be working for me.

Hope this helps.

Harry.


Follow

Get every new post delivered to your Inbox.