Padding bytes between functions

834 views
Skip to first unread message

Gregory Shimansky

unread,
Oct 19, 2015, 11:56:36 AM10/19/15
to golang-dev
Hello

When Go compiler and assembly generate code, functions are aligned on FuncAlign bytes boundary. For x86 architecture it is 16 bytes. Padding bytes between functions are filled with zero bytes. Two zero bytes 0x00 0x00 on x86 architecture mean instruction "add %al,(%rax)" which is valid and can be executed by processor. If instead of zeroes we used 0xCC byte, this would generate one-byte int3 opcode (trap) for padding bytes, which in some cases could help to find bugs in execution control transfer on a wrong address, or execution going past a function end. What do you think?

If you think that this is a good idea, I have a patch ready. It is a small change in asm6.go file.

Keith Randall

unread,
Oct 19, 2015, 12:02:05 PM10/19/15
to Gregory Shimansky, golang-dev
Sounds fine to me.


--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Austin Clements

unread,
Oct 19, 2015, 12:42:29 PM10/19/15
to Keith Randall, Gregory Shimansky, golang-dev
Does this have any performance implications? Intel goes to some lengths to specify single instruction NOPs of many different byte lengths for purposes of padding, but I don't know if those only matter if you're actually going to execute them.

Ian Lance Taylor

unread,
Oct 19, 2015, 12:54:49 PM10/19/15
to Austin Clements, Keith Randall, Gregory Shimansky, golang-dev
On Mon, Oct 19, 2015 at 9:42 AM, 'Austin Clements' via golang-dev
<golan...@googlegroups.com> wrote:
> Does this have any performance implications? Intel goes to some lengths to
> specify single instruction NOPs of many different byte lengths for purposes
> of padding, but I don't know if those only matter if you're actually going
> to execute them.

That is only if you are going to execute them. Intel documents them
because on some processors you get a big benefit from aligned branch
targets, especially for loops.

Ian

minux

unread,
Oct 19, 2015, 1:43:40 PM10/19/15
to Gregory Shimansky, golang-dev
On Mon, Oct 19, 2015 at 11:00 AM, Gregory Shimansky <gregory....@intel.com> wrote:
When Go compiler and assembly generate code, functions are aligned on FuncAlign bytes boundary. For x86 architecture it is 16 bytes. Padding bytes between functions are filled with zero bytes. Two zero bytes 0x00 0x00 on x86 architecture mean instruction "add %al,(%rax)" which is valid and can be executed by processor. If instead of zeroes we used 0xCC byte, this would generate one-byte int3 opcode (trap) for padding bytes, which in some cases could help to find bugs in execution control transfer on a wrong address, or execution going past a function end. What do you think?

If you think that this is a good idea, I have a patch ready. It is a small change in asm6.go file.

I don't think this is necessary.

Even if the code does indeed jump to the wrong target, most of the time, it will
hit somewhere inside a function, and this change won't help. Our liblink will
make sure functions won't fall off the end (it inserts a self jump if the function
doesn't end with a RET instruction.)

Note that even for a unsafe language like C, gcc uses various NOP instruction
to align a function.

Gregory Shimansky

unread,
Oct 20, 2015, 8:08:30 AM10/20/15
to golang-dev, gregory....@intel.com
The change is basically free of cost because bytes are wasted in any case to make function addresses aligned. So why not add some more security? The patch is quite simple, it was can be reviewed here https://go-review.googlesource.com/#/c/16102/

hawtp...@email.com

unread,
Oct 28, 2015, 4:31:39 PM10/28/15
to golang-dev, gregory....@intel.com
most of the time? so this feature wouldn't be helpful some of the time? Please explain thoroughly why you so adamantly object. I am asking this from both minux and russ cox.

Ian Lance Taylor

unread,
Oct 28, 2015, 6:58:59 PM10/28/15
to hawtp...@email.com, golang-dev, Gregory Shimansky
On Wed, Oct 28, 2015 at 10:59 AM, <hawtp...@email.com> wrote:
> most of the time? so this feature wouldn't be helpful some of the time?
> Please explain thoroughly why you so adamantly object. I am asking this from
> both minux and russ cox.

It's a cost-benefit decision. Increasing the complexity of the
toolchain always has a cost in comprehension, maintenance, testing,
and verification that the change does not regress. They are saying
that the benefit of the change is very small and it is therefore not
worth the cost.

In any case I believe the change went in.

Ian


> On Monday, October 19, 2015 at 1:43:40 PM UTC-4, minux wrote:
>>
>>
>> On Mon, Oct 19, 2015 at 11:00 AM, Gregory Shimansky
>> <gregory....@intel.com> wrote:
>>>
>>> When Go compiler and assembly generate code, functions are aligned on
>>> FuncAlign bytes boundary. For x86 architecture it is 16 bytes. Padding bytes
>>> between functions are filled with zero bytes. Two zero bytes 0x00 0x00 on
>>> x86 architecture mean instruction "add %al,(%rax)" which is valid and can be
>>> executed by processor. If instead of zeroes we used 0xCC byte, this would
>>> generate one-byte int3 opcode (trap) for padding bytes, which in some cases
>>> could help to find bugs in execution control transfer on a wrong address, or
>>> execution going past a function end. What do you think?
>>>
>>> If you think that this is a good idea, I have a patch ready. It is a
>>> small change in asm6.go file.
>>
>>
>> I don't think this is necessary.
>>
>> Even if the code does indeed jump to the wrong target, most of the time,
>> it will
>> hit somewhere inside a function, and this change won't help. Our liblink
>> will
>> make sure functions won't fall off the end (it inserts a self jump if the
>> function
>> doesn't end with a RET instruction.)
>>
>> Note that even for a unsafe language like C, gcc uses various NOP
>> instruction
>> to align a function.
>

Russ Cox

unread,
Oct 29, 2015, 10:20:30 AM10/29/15
to Ian Lance Taylor, hawtp...@email.com, golang-dev, Gregory Shimansky
On Wed, Oct 28, 2015 at 6:58 PM, Ian Lance Taylor <ia...@golang.org> wrote:
On Wed, Oct 28, 2015 at 10:59 AM,  <hawtp...@email.com> wrote:
> most of the time? so this feature wouldn't be helpful some of the time?
> Please explain thoroughly why you so adamantly object. I am asking this from
> both minux and russ cox.

It's a cost-benefit decision.  Increasing the complexity of the
toolchain always has a cost in comprehension, maintenance, testing,
and verification that the change does not regress.  They are saying
that the benefit of the change is very small and it is therefore not
worth the cost.

In any case I believe the change went in.

Also, there was a claim that this would add "more security", but the change is at best security theater. Improved security would require the existence of an attack that is possible with 0x00 padding but becomes impossible or at least appreciably harder with 0xCC padding. No one has described such an attack, and I can't think of any myself. Any attack that needs 0x00 bytes in memory can find them elsewhere, and any attack based on code specially constructed to trigger a compiler bug generating a function that runs off the end of the generated code can avoid the 0xCC by adjusting the function to need no padding.

But again, the change went in, and it will stay in (unless we find that it causes a real problem!). Let's move on.

Russ

hawtp...@email.com

unread,
Oct 30, 2015, 2:53:38 AM10/30/15
to golang-dev
dubious claims. but whatever.

minux

unread,
Oct 30, 2015, 3:36:42 AM10/30/15
to golang-dev

On Fri, Oct 30, 2015 at 2:53 AM, <hawtp...@email.com> wrote:
dubious claims. but whatever.

You're free to give evidence to back that use 0xcc to pad function can indeed
thwart real attacks.

I want to add one more point:
The two major open source compilers for C/C++, two major unsafe languages,
don't use int3 to pad functions.

If that's not enough,  I just checked that Intel's own C/C++ compiler doesn't use
int3 to pad functions either (at least not on Linux). Instead, it uses various NOP
instructions, a practice also used by the major open source C compilers.

David Chase

unread,
Oct 30, 2015, 8:42:56 AM10/30/15
to minux, golang-dev
Might be interesting to look at what we use to pad stuff in our heaps, so as to complicate spraying attacks on programs written in Go.


Reply all
Reply to author
Forward
0 new messages