Dela via


/GS (Buffer Security Check)

Detects some buffer overruns that overwrite the return address, a common technique for exploiting code that does not enforce buffer size restrictions. This is achieved by injecting security checks into the compiled code.

/GS[-]

Remarks

/GS is on by default. Use /GS- if you expect your application to have no security exposure.

For additional information on /GS see Compiler Security Checks In Depth.

The compiler injects checks in functions with local string buffers or, on x86, functions with exception handling. A string buffer is defined as an array whose element size is one or two bytes, and where the size of the whole array is at least five bytes, or, any buffer allocated with _alloca.

On all platforms, the compiler injects a cookie to protect the function's return address if the function has local string buffers. This cookie is checked on function exit, and during frame unwinding on 64-bit operating systems or on x86 for functions with some form of exception handling. On x86, the compiler also injects a cookie to protect the address of the function's exception handler. This cookie is checked during frame unwinding.

/GS primarily attempts to detect direct buffer overruns into the return address. Buffer overruns are more easily exploited on machines with calling conventions that store the return address of function calls on the stack. For example, x86 uses calling conventions that store the return address of function calls on the stack.

On functions that the compiler thinks might be subject to buffer overrun problems, the compiler will allocate space on the stack before the return address. On function entry, the allocated space is loaded with a security cookie that is computed once at module load. Then, on function exit, a helper function is called to make sure the cookie's value is still the same.

If the value is not the same, an overwrite of the stack has potentially occurred and the process simply terminates. Prior to Visual C++ 2005 a dialog box displayed reporting the stack overwrite.

/GS also protects against vulnerable parameters passed into a function. A vulnerable parameter is a pointer, C++ reference, or a C-structure (C++ POD type) that contains a pointer, string buffer, or C++ reference.

A vulnerable parameter is allocated before the cookie and local variables. A buffer overrun can overwrite these parameters. Code in the function that uses these parameters can lead to an attack before the function returns, thus avoiding the security check. To minimize this danger, the compiler will make a copy of the vulnerable parameters during the function prolog and put them below the storage area for any buffers.

The compiler does not provide security protection for vulnerable parameters in the following situations:

  • Functions that do not contain a buffer.

  • If optimizations (/O Options (Optimize Code)) are not enabled.

  • Functions with a variable argument list (...).

  • Functions marked with naked (C+).

  • Functions containing inline assembly code in the first statement.

  • If a parameter is used only in ways that are less likely to be exploitable in the event of a buffer overrun.

/GS requires initialization of the security cookie. This cookie must be initialized before any function using the cookie runs. The security cookie must be initialized upon entry to an EXE or DLL. This is done automatically when using the default CRT entry points (mainCRTStartup, wmainCRTStartup, WinMainCRTStartup, wWinMainCRTStartup, or _DllMainCRTStartup), but must be done manually, via a call to __security_init_cookie, if you use an alternate entry point.

/GS is supported for managed functions when compiling with /clr (Common Language Runtime Compilation).

/GS does not protect against all buffer overrun security attacks. For example, if you have a buffer and a vtable in an object, the buffer overrun could corrupt the vtable and allow an attack to occur.

Even if you use /GS, you should strive to write secure code. That is, make sure that your code has no buffer overruns. /GS might protect your application from buffer overruns that do remain in your code.

To set this compiler option in the Visual Studio development environment

  1. Open the project's Property Pages dialog box. For details, see How to: Open Project Property Pages.

  2. Click the C/C++ folder.

  3. Click the Code Generation property page.

  4. Modify the Buffer Security Check property.

To set this compiler option programmatically

Example

This sample overruns a buffer, which causes the application to fail at runtime.

// compile with: /c /W1
#include <cstring>
#include <stdlib.h>
#pragma warning(disable : 4996)   // for strcpy use

// Vulnerable function
void vulnerable(const char *str) {
   char buffer[10];
   strcpy(buffer, str); // overrun buffer !!!

   // use a secure CRT function to help prevent buffer overruns
   // truncate string to fit a 10 byte buffer
   // strncpy_s(buffer, _countof(buffer), str, _TRUNCATE);
}

int main() {
   // declare buffer that is bigger than expected
   char large_buffer[] = "This string is longer than 10 characters!!";
   vulnerable(large_buffer);
}

See Also

Reference

Compiler Options

Setting Compiler Options