Cross compilation and os/user (cgo problem)

575 views
Skip to first unread message

Tom Payne

unread,
Mar 16, 2014, 4:21:41 PM3/16/14
to golang-nuts
Hi,

I'm developing on Mac OS X but deploying to Linux. I can cross-compile my binary just fine, but when I run it on Linux I get the error:
  user: LookupId not implemented on linux/386

I want to drop privileges for my server process via the Setuid function in the syscall package. I'm use the Lookup and LookupId functions in the os/user package to convert a string username to a user id. 

Further investigation reveals this previous thread to golang-nuts:

Thread summary:
- syscall requires cgo
- cgo is disabled when cross-compiling

A workaround is to use numerical user ids so I can avoid using the os/user package completely, but do I have any other options to be able to use the os/user package when cross-compiling?

Extra info (in case relevant):
- go installed on Mac OS X using Homebrew (brew install go --cross-compile-common)
- current source code at the end of the email

Many thanks!

Tom


Source code follows:

import (
"flag"
"log"
"os/user"
"strconv"
"syscall"
)

// ...

user_ := flag.String("user", "", "user")
flag.Parse()

if *user_ != "" {
u, err := user.Lookup(*user_)
if err != nil {
u, err = user.LookupId(*user_)
}
if err != nil {
log.Fatal(err)
}
uid, err := strconv.Atoi(u.Uid)
if err != nil {
log.Panic(err)
}
if err := syscall.Setuid(uid); err != nil {
log.Fatal(err)
}
}

Tom Payne

unread,
Mar 16, 2014, 4:31:44 PM3/16/14
to golang-nuts
On 16 March 2014 21:21, Tom Payne <t...@tompayne.org> wrote:
Thread summary:
- syscall requires cgo

Oops, that should be os/user requires cgo, not syscall.

Elias Naur

unread,
Mar 17, 2014, 6:05:28 AM3/17/14
to golan...@googlegroups.com, t...@tompayne.org
FWIW, cross compilation with cgo is now possible: https://code.google.com/p/go/source/detail?r=6d3bdbd27761

 - elias

Carlos Castillo

unread,
Mar 17, 2014, 7:12:08 AM3/17/14
to golan...@googlegroups.com, t...@tompayne.org
As far as I know such a solution would currently need:
  1. Go to be built from source, using the latest tip version (user is using a package manager version of go 1.2)
  2. A C compiler that can cross-compile as well, with associated headers and libraries (I have had lots of headaches with this)
  3. Correctly configure #1 to use #2
A far simpler solution would be to build on the target machine, or on a VM that approximates it. With vagrant (http://www.vagrantup.com/) it is actually quite easy to set up a small reproducible ubuntu based VM using a single config file.

Gyepi SAM

unread,
Mar 17, 2014, 8:03:27 AM3/17/14
to Tom Payne, golang-nuts
On Sun, Mar 16, 2014 at 09:21:41PM +0100, Tom Payne wrote:
> I'm developing on Mac OS X but deploying to Linux. I can cross-compile my
> binary just fine, but when I run it on Linux I get the error:
> user: LookupId not implemented on linux/386
>
> I want to drop privileges for my server process via the Setuid function in
> the syscall package. I'm use the Lookup and LookupId functions in the
> os/user package to convert a string username to a user id.

Obviously not a solution the general problem, but in this case,
you may want to use runit's chpst or similar tool and avoid
handling user privileges in your app.

I develop and deploy on Linux and almost always use external tools for process state management.

It has the beneficial effects of simplifying the application,
eliminating a whole class of security issues, and providing
more flexibility in deployment configurations.

Of course, your application may well be the rare one that requires root
privileges by design...

-Gyepi


Tom Payne

unread,
Mar 17, 2014, 10:59:32 AM3/17/14
to Tom Payne, golang-nuts
Thanks for the responses.

My application only needs root access to create the log files in /var/log if they don't already exist, otherwise it requires no special privileges.

Therefore, it sounds like runit's chpst or similar is a better fit in this case.

Thanks again,
Tom

Steve McCoy

unread,
Mar 17, 2014, 11:12:40 AM3/17/14
to golan...@googlegroups.com, Tom Payne
That's definitely what you want; setuid/etc. sycalls on linux have problems in Go programs:

https://code.google.com/p/go/issues/detail?id=1435

This coincidentally just came up in another thread.
Reply all
Reply to author
Forward
0 new messages