Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

A compiler might insert padding bytes to a structure to ensure that structure members appear in the correct location. Initializing the members of the structure does not always initialize the padding bytes.

According to ISO/IEC 9899:1999 (C99), in 6.2.6.1, paragraph 6,

When a value is stored in an object of structure or union type, including in a member object, the bytes of the object representation that correspond to any padding bytes take unspecified values.42)

42) Thus, for example, structure assignment may be implemented element-at-a-time or via memcpy.

As a result of being uninitialized, padding bytes could have random data (sensitive data). This structure could be passed to functions that do not have privilege.

...

The static_assert() macro, a feature of the C1X standard, accepts a constant expression and an error message. The expression is evaluated at compile time and, if false, the compilation is terminated and the error message is output.

See recommendation DCL03-C. Use a static assertion to test the value of a constant expression

For example, in an IA-32 machine,

...

If memset of the original structure to zero (as mentioned in the Non-Compliant example 2) does not work under some compilers, then copy the original structure to an unsigned char memory and pass that memory to the user as shown below.

Code Block
bgColor#CCCCFF
borderStylesolid
#include <stddef.h>
#include <string.h>

struct test{
  int a;
  char b;
  int c;
};

/* ... safely copy bytes to user space ... */
extern int copy_to_user(void *dest, void *src, size_t size);

void do_stuff(void *usr_buf) {
  struct test arg = {.a=1,.b=2,.c=3};
  unsigned char r[sizeof(arg)];

  /* ... perform operations on arg ... */

  /* just before passing arg to the function */
  memset(r, 0, sizeof(r));
  memset(r+offsetof(struct test,a), arg.a, sizeof(arg.a));
  memset(r+offsetof(struct test,b), arg.b, sizeof(arg.b));
  memset(r+offsetof(struct test,c), arg.c, sizeof(arg.c));
  /* now pass r to the function */
  copy_to_user(usr_buf, r, sizeof(r));

  /* ... */
}

This ensures that no uninitialized padding bytes are copied to unprivileged users.

Risk Assessment

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

DCL39-C

low

unlikely

medium

P2

L3

Related Guidelines

ISO/IEC 9899:1999 Section 6.2.6.1 p6

...