# Is there a set(e)uid function, or equivalent?

**URL:** <https://racket.discourse.group/t/is-there-a-set-e-uid-function-or-equivalent/2766>\
**Category:** Questions & Answers\
**Tags:** question\
**Created:** [March 7, 2024, 4:24pm UTC](https://racket.discourse.group/t/is-there-a-set-e-uid-function-or-equivalent/2766 "2024-03-07T16:24:43Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![nxg](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/nxg/32/1723_2.png) [@nxg](https://racket.discourse.group/u/nxg)\
**Post date:** [March 7, 2024, 4:24pm UTC](https://racket.discourse.group/t/is-there-a-set-e-uid-function-or-equivalent/2766/1 "2024-03-07T16:24:43Z")

</div>

Is there a way of changing (unix) user? I can see `getpid` in the `racket/os` package, and if a setuid-a-like function exists, I'd expect to find it nearby, but I can't find it there or under any other search string I can think of.

Why? I'm trying to see if fork+setuid looks reasonably neat in a server program. The right thing to do is probably to use `daemon` or equivalent, but there are a couple of intricacies with that, and rather than fight with it I thought I'd look to see if doing it 'by hand' would be simpler in the long run.

---

<div class="post-metadata">

**Author:** ![bakgatviooldoos](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/bakgatviooldoos/32/1381_2.png) [@bakgatviooldoos](https://racket.discourse.group/u/bakgatviooldoos)\
**Post date:** [March 7, 2024, 6:29pm UTC](https://racket.discourse.group/t/is-there-a-set-e-uid-function-or-equivalent/2766/2 "2024-03-07T18:29:35Z")

</div>

Hi, @nxg.

I don't know much about operating systems, but a quick Github search revealed the following [code](https://github.com/arclanguage/anarki/blob/e49b1bfe1f7bf0e682d360eb677947264000de82/ac.rkt#L1250) for `setuid` and `Racket`.

Maybe C FFI (foreign function interface) would be the route somehow? Again, I know very little.

---

<div class="post-metadata">

**Author:** ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)\
**Post date:** [March 7, 2024, 6:29pm UTC](https://racket.discourse.group/t/is-there-a-set-e-uid-function-or-equivalent/2766/3 "2024-03-07T18:29:49Z")

</div>

You can probably (nonportably?) access the system interface for changing users or setuids with `define-c` or other parts of the [FFI](https://docs.racket-lang.org/foreign/Loading_Foreign_Libraries.html)

---

<div class="post-metadata">

**Author:** ![nxg](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/nxg/32/1723_2.png) [@nxg](https://racket.discourse.group/u/nxg)\
**Post date:** [March 8, 2024, 3:23pm UTC](https://racket.discourse.group/t/is-there-a-set-e-uid-function-or-equivalent/2766/4 "2024-03-08T15:23:50Z")

</div>

Thanks, both.

The FFI had occurred to me, but the fact that this wasn't in the `racket/os` module, where it seems an obvious member of the collection of random other OS facilities I'd expect to find there, made me think I was missing something thoughtful elsewhere.

It's slightly surprising that I can't do this in a library-standard way, but if I'm assured it's not there, then I can just stick with Plan A.

Best wishes,

Norman

---

<div class="post-metadata">

**Author:** ![greghendershott](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/greghendershott/32/98_2.png) [@greghendershott](https://racket.discourse.group/u/greghendershott)\
**Post date:** [March 8, 2024, 8:41pm UTC](https://racket.discourse.group/t/is-there-a-set-e-uid-function-or-equivalent/2766/5 "2024-03-08T20:41:44Z")

</div>

@nxg My guess is `racket/os` is intended to be portable but `setuid` isn't.

So for example its `getpid` (1) just _gets_ (2) some unique integer for the process. Even if some OS returned (say) a unique string instead of number ID, you could imagine implementing this to honor the contract.

* * *

Whereas that FFI example linked to by @bakgatviooldoos suggests "setuid" isn't portable:

```scheme
(require (prefix-in ffi: ffi/unsafe))

```

...

```scheme
; allow Arc to give up root privileges after it
; calls open-socket. thanks, Eli!
(define setuid (ffi:get-ffi-obj 'setuid #f
                 (ffi:_fun ffi:_int ffi:-> ffi:_int)
                 ; If we're on Windows, there is no setuid, so we make
                 ; a dummy version. See "Arc 3.1 setuid problem on
                 ; Windows," http://arclanguage.org/item?id=10625.
                 (lambda () (lambda (x) 'nil))))

```

I'm guessing that although Windows surely has some notion of a "user ID", it might lack the ability of a process to _change_ this for itself? (I don't think running as root and dropping privileges is really part of the Windows history/culture.)

Anyway, although the FFI "DSL" can take awhile to learn for complicated examples, as you can see it can be pretty painless in simple cases like this.

---

<div class="post-metadata">

**Author:** ![LiberalArtist](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/liberalartist/32/151_2.png) [@LiberalArtist](https://racket.discourse.group/u/LiberalArtist)\
**Post date:** [March 8, 2024, 11:12pm UTC](https://racket.discourse.group/t/is-there-a-set-e-uid-function-or-equivalent/2766/6 "2024-03-08T23:12:53Z")

</div>

> [@nxg](#):
>
> Why? I'm trying to see if fork+setuid looks reasonably neat in a server program. The right thing to do is probably to use `daemon` or equivalent, but there are a couple of intricacies with that, and rather than fight with it I thought I'd look to see if doing it 'by hand' would be simpler in the long run.

If possible, I recommend avoiding `setuid` by launching your program as an unprivileged user and only granting it the capabilities it actually needs. On a typical GNU/Linux system, you can allow an unprivileged process to bind to "privileged" ports (\< 1024) by granting it the `CAP_NET_BIND_SERVICE` capability, for example by adding the following to your `systemd` unit file:

```scheme
[Service]
AmbientCapabilities=CAP_NET_BIND_SERVICE

```

(Other full-featured init systems provide similar mechanisms: the underlying functionality is not specific to `systemd`.)

---

<div class="post-metadata">

**Author:** ![nxg](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/nxg/32/1723_2.png) [@nxg](https://racket.discourse.group/u/nxg)\
**Post date:** [March 9, 2024, 10:51am UTC](https://racket.discourse.group/t/is-there-a-set-e-uid-function-or-equivalent/2766/7 "2024-03-09T10:51:49Z")

</div>

[quote="greghendershott, post:5, topic:2766"]  
I'm guessing that although Windows surely has some notion of a "user ID", it might lack the ability of a process to _change_ this for itself? (I don't think running as root and dropping privileges is really part of the Windows history/culture.)[/quote]

It looks like you're right – thanks – and that makes a lot of sense.

> [@greghendershott](#):
>
> Anyway, although the FFI "DSL" can take awhile to learn for complicated examples, as you can see it can be pretty painless in simple cases like this.

I've been spoilt here, recently, by spending time with [s7](https://ccrma.stanford.edu/software/snd/snd/s7.html) which, as an extension language is, in a sense, all-FFI. It's a rather ascetic experience, as Schemes go, but the FFI is sweet.

---

<div class="post-metadata">

**Author:** ![nxg](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/nxg/32/1723_2.png) [@nxg](https://racket.discourse.group/u/nxg)\
**Post date:** [March 9, 2024, 11:08am UTC](https://racket.discourse.group/t/is-there-a-set-e-uid-function-or-equivalent/2766/8 "2024-03-09T11:08:01Z")

</div>

> [@LiberalArtist](#):
>
> If possible, I recommend avoiding `setuid` by launching your program as an unprivileged user and only granting it the capabilities it actually needs. On a typical GNU/Linux system, you can allow an unprivileged process to bind to "privileged" ports (\< 1024) by granting it the `CAP_NET_BIND_SERVICE` capability

Yes, that's my Plan A, really – it's an excellent suggestion.

I'm using [daemon](https://man.freebsd.org/cgi/man.cgi?daemon(8)) invoked from rc.d (this won't be running on a systemd box), but I think I'm slightly fumbling the invocation, and rather than read the manpage yet again, I (slightly self-indulgently) wondered if doing this the old-skool way might be simpler. I'm not surprised it's not: the last time I did this by hand I remember discovering how many moving parts there are to get subtly wrong.

I remain _slightly_ surprised that Racket doesn't have a portable implementation of the daemonise operation, but since things like systemd and /usr/sbin/daemon exist and do work, there isn't, when it comes down to it, a clearly demonstrable need for it.
