If you're developing some native executables (C, C++, whatever) on a GNU/Linux platform and possibly GNU/WhateverElse, and some of your object files are custom assembly language produced by hand (or not by a compiler whose developers are aware of this), and not inline assembly but in their own .S or .s file assembled to a separate .o, watch out!
If you do not have this blurb:
.section .note.GNU-stack,"",@progbits
in your assembly code, and do not use a linker option to prevent it, your entire executable or shared library will be silently marked as requiring an executable stack (in all threads).
When such an executable is loaded, the stack is made executable. So are any new thread stacks after that.
If such a shared library is loaded into an application (even late, with dlopen, I think), a hook is called out of the linker into glibc, which will call mprotect() on all of the existing thread stacks to allow execution.
Oops!
(This is, of course, a monumentally stupid programmer trap. Write correct, good assembly code without a secret GNU handshake: unknowingly inflict added security risk on your users.)
If you have your own .S files, and those do not contain the magic handshake, then the stack will stay executable, and this is indeed a programmer trap.
The reason for this is that historically the stack was always executable, so it could not be make non-executable by default, it had to be opt in. In fact, gcc will generate code that requires the stack to be executable if you use a certain gcc extension (related to nested functions).
The other way to opt-in into non-executable stack is passing --noexecstack to as(1) (or when via gcc, use -Wa,--noexecstack)
This ought to be better documented, but it's not. The rationaly is probably that you should not be writing assembly code if you don't know this kind of detail? I can only guess about this.