Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
bgColor#FFCCCC
#include <stddef.h>

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

/* ... safely copy databytes 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};

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

  /* copy arg to user space */
  copy_to_user(usr_buf, &arg, sizeof(arg));

  /* ... */
}

The padding bytes could be explicitly initialized using memset to zero as shown below.

Code Block
bgColor#FFCCCC
#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;

  /* initializes all bytes (including padding bytes) of the struct to zero */
  memset(&arg, 0, sizeof(arg));

  arg.a = 1;
  arg.b = 2;
  arg.c = 3;

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

  /* copy arg to user space */
  copy_to_user(usr_buf, &arg, sizeof(arg));

  /* ... */
}

Here, the compiler could implement arg.b =2 in the following way,

...

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

struct test{
  int a;
  char b;
  int c;
} __attribute__((__packed__));

/* ... 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};

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

  /* copy arg to user space */
  copy_to_user(usr_buf, &arg, sizeof(arg));

  /* ... */
}

Compliant Solution 2(Structure Packing - MSVC)

...

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

#pragma pack(1) /* 1 byte */
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};

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

  /* copy arg to user space */
  copy_to_user(usr_buf, &arg, sizeof(arg));

  /* ... */
}

pack takes effect at the first struct declaration after the pragma is seen. The alignment of a member will be on a boundary that is a multiple of 1 byte.

...

Code Block
bgColor#CCCCFF
borderStylesolid

#include <stddef.h>
#include <string.h>

struct test{
 int  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  argarg = { .a = 1, .b = 2, .c = 3 };
  unsigned char r[sizeof (arg)];
.
.
  //* Do... allperform operations on arg
.
.
// ... */

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

  /* ... */
}

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

...