Skip to content

Commit

Permalink
os/user: zero-initialize C structs returned to Go
Browse files Browse the repository at this point in the history
In the wrappers for getgrnam_r and similar, the structs to be returned
are allocated on the C stack and may be uninitialized. If the call to
the wrapped C function returns an error (such as ERANGE), it may leave
the struct uninitialized, expecting that the caller will not read it.

However, when that struct is returned to Go, it may be read by the Go
garbage collector. If the uninitialized struct fields happen to
contain wild pointers, the Go garbage collector will throw an error.
(Prior to CL 449335, the Go runtime would not scan the struct fields
because they did not reside in Go memory.)

Fix this by always zeroing the struct before the C call.

Fixes #57170.

Change-Id: I241ae8e4added6f9a406dac37a7f6452341aa0cf
Reviewed-on: https://go-review.googlesource.com/c/go/+/456121
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
  • Loading branch information
Bryan C. Mills authored and gopherbot committed Dec 9, 2022
1 parent e738a2f commit 80f7484
Showing 1 changed file with 21 additions and 16 deletions.
37 changes: 21 additions & 16 deletions src/os/user/cgo_lookup_cgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,42 @@ import (
#include <pwd.h>
#include <grp.h>
#include <stdlib.h>
#include <string.h>
static struct passwd mygetpwuid_r(int uid, char *buf, size_t buflen, int *found, int *perr) {
struct passwd pwd;
struct passwd *result;
*perr = getpwuid_r(uid, &pwd, buf, buflen, &result);
*found = result != NULL;
return pwd;
struct passwd *result;
memset (&pwd, 0, sizeof(pwd));
*perr = getpwuid_r(uid, &pwd, buf, buflen, &result);
*found = result != NULL;
return pwd;
}
static struct passwd mygetpwnam_r(const char *name, char *buf, size_t buflen, int *found, int *perr) {
struct passwd pwd;
struct passwd *result;
*perr = getpwnam_r(name, &pwd, buf, buflen, &result);
*found = result != NULL;
return pwd;
struct passwd *result;
memset(&pwd, 0, sizeof(pwd));
*perr = getpwnam_r(name, &pwd, buf, buflen, &result);
*found = result != NULL;
return pwd;
}
static struct group mygetgrgid_r(int gid, char *buf, size_t buflen, int *found, int *perr) {
struct group grp;
struct group *result;
*perr = getgrgid_r(gid, &grp, buf, buflen, &result);
*found = result != NULL;
return grp;
struct group *result;
memset(&grp, 0, sizeof(grp));
*perr = getgrgid_r(gid, &grp, buf, buflen, &result);
*found = result != NULL;
return grp;
}
static struct group mygetgrnam_r(const char *name, char *buf, size_t buflen, int *found, int *perr) {
struct group grp;
struct group *result;
*perr = getgrnam_r(name, &grp, buf, buflen, &result);
*found = result != NULL;
return grp;
struct group *result;
memset(&grp, 0, sizeof(grp));
*perr = getgrnam_r(name, &grp, buf, buflen, &result);
*found = result != NULL;
return grp;
}
*/
import "C"
Expand Down

0 comments on commit 80f7484

Please sign in to comment.