NetBSD Problem Report #58438
From www@netbsd.org Thu Jul 18 08:02:23 2024
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits)
client-signature RSA-PSS (2048 bits))
(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id 167001A9239
for <gnats-bugs@gnats.NetBSD.org>; Thu, 18 Jul 2024 08:02:23 +0000 (UTC)
Message-Id: <20240718080221.B33781A923A@mollari.NetBSD.org>
Date: Thu, 18 Jul 2024 08:02:21 +0000 (UTC)
From: 13mdf@fege.net
Reply-To: 13mdf@fege.net
To: gnats-bugs@NetBSD.org
Subject: Compatibility issues with per-user-temp [described security(7) man page]
X-Send-Pr-Version: www-1.0
>Number: 58438
>Category: kern
>Synopsis: Compatibility issues with per-user-temp [described security(7) man page]
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: kern-bug-people
>State: analyzed
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Jul 18 08:05:00 +0000 2024
>Closed-Date:
>Last-Modified: Fri Dec 27 17:19:22 +0000 2024
>Originator: Marc Fege
>Release: 10.0
>Organization:
>Environment:
NetBSD rpi.familie.fege.local 10.0 NetBSD 10.0 (GENERIC64) #0: Thu Mar 28 08:33:33 UTC 2024 mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/evbarm/compile/GENERIC64 evbarm
>Description:
Dear NetBSD community,
there seems to be a problem with the per-user-temp-function in the kernel, which seems to be incompatible with certain system-softwares like X(1) or even tmux(1), which expect to write their magic cookies and temp files directly to /tmp. Those softwares might have a problem with those symlinks which relocates /tmp per-user-wise to a separate /private/tmp as stated in the security(7) man page. Other programs like ed(1) or vi(1) do not have a problem to write to this symlinked temp directory on the other hand.
As I undertook correspondence in advance with the original author of this security enhancement from back in the day of 2006 and following, Elad Efrat, before opening this bug report, he recommended personally I should write here.
He says "it wouldn’t surprise [him] if some programs use a syscall or library function that prevents symlinks from working".
What did I do? I tested on arm64, amd64, i386 and vax the following steps with identical results as described above:
As root:
1.: mkdir -p /private/tmp
2.: chmod -R 755 /private
3.: Added in /etc/rc.conf:
per_user_tmp="YES"
4.: Replaced /tmp mount point in /etc/fstab with following lines:
#tmpfs /tmp tmpfs rw,-m1777,-sram%65
tmpfs /private/tmp tmpfs rw,-m1755,-sram%65
5.: Rebooted.
I tried even to mess around with the file permissions of the directories (chmod -R 777 for example). No effect what so ever for me. Maybe one tries to reproduce that behaviour. Does anyone has a clue, what might be the issue here in my procedures? Maybe I forgot something or did something wrong, that Elad did not anticipated when he wrote this man page back in the day.
A propos man page: as an ordinary user in the field I would recommend to exemplificate the necessary steps in the man page a bit broader and give a few more examples or a detailed list of steps, what users should do to activate this feature successfully. As you see, I took five steps to activate this feature whatsoever. As mentioned: maybe I forgot something or did something wrong what was not anticipated when writing this man page.
Thank you in advance for an reply and
best regards -
Marc Fege
>How-To-Repeat:
As root:
1.: mkdir -p /private/tmp
2.: chmod -R 755 /private
3.: Added in /etc/rc.conf:
per_user_tmp="YES"
4.: Replaced /tmp mount point in /etc/fstab with following lines:
#tmpfs /tmp tmpfs rw,-m1777,-sram%65
tmpfs /private/tmp tmpfs rw,-m1755,-sram%65
5.: Reboot.
6. Try to launch X(1) or tmux(1).
>Fix:
>Release-Note:
>Audit-Trail:
From: "David H. Gutteridge" <david@gutteridge.ca>
To: Gnats Bugs <gnats-bugs@netbsd.org>
Cc:
Subject: Re: kern/58438 (Compatibility issues with per-user-temp [described
security(7) man page])
Date: Sat, 26 Oct 2024 20:41:33 -0400
I've never used this feature, but from looking at what's documented in
security(7) and what /etc/rc.d/perusertmp does, I can't see how it
would work at all as-is. According to the steps you've listed, you'd
end up with a /tmp link that points to /private/tmp/@ruid. But nothing
has populated the actual per-user directories at this point. If you're
root, it would expect /private/tmp/0 as a directory, for example. Each
UID-specific directory would need (secured) permissions appropriate to
that account, of course. I see nothing in the rc.d infrastructure that
would create this (nor is it mentioned in the man page).
So you'd need to also create each directory that @ruid would
contextually point to under /private/tmp before it will work. Since
you're using tmpfs, you'd have to redo this each time after boot (or
otherwise initiating the feature). You'd need to figure out which UIDs
are relevant for you, presumably at least two. (I'm not sure there'd be
any point applying a sticky bit to these directories, given they're
supposed to be isolated per-user anyway.)
(Well, if you were using a non-volatile tmp, by default, you'd still
have to recreate each user's directory every time, as from what I see
/etc/rc.d/cleartmp also doesn't take this concept into account and
would remove all the per-UID directories each time, too. In that case
you could disable it via rc.conf(5), of course. If you just tweaked
perusertmp to create the extra directories, cleartmp would immediately
remove them out from under you, too, since it runs afterwards.)
You wrote "Other programs like ed(1) or vi(1) do not have a problem to
write to this symlinked temp directory on the other hand." Are you
certain that those actually tried to use /tmp in the first place, and
successfully wrote there? vi(1) uses /var/tmp, not /tmp, for its
recovery files. (Yes, it can use /tmp for other purposes.) Based on
what you shared, I can't follow how vi(1) would have written to "/tmp"
successfully either.
It seems there are functional and probably documentation issues with
this feature. (I suppose if it really "just worked" the man page
wouldn't need to spell out that there are dedicated per-user
directories, but there'd still need to be a facility provided to
specify which ones to create, so that would be documented as well.)
Regards,
Dave
From: "David H. Gutteridge" <david@gutteridge.ca>
To: Gnats Bugs <gnats-bugs@netbsd.org>
Cc:
Subject: Re: kern/58438 (Compatibility issues with per-user-temp [described
security(7) man page])
Date: Sat, 26 Oct 2024 21:17:11 -0400
Several web search tries eventually turned up that this is evidently a
known issue that someone already proposed a patch to address, which is
here: https://gist.github.com/nonakap/3802982
I haven't actually found a mailing list discussion about any of this
specific context yet (including that patch), nor did initial attempts
at searching GNATS turn up anything. That patch lines up pretty much
exactly with what my take on this was.
Regards,
Dave
From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc: "David H. Gutteridge" <gutteridge@netbsd.org>
Subject: Re: kern/58438 (Compatibility issues with per-user-temp [described
security(7) man page])
Date: Sun, 27 Oct 2024 11:38:42 +0000 (UTC)
On Sun, 27 Oct 2024, David H. Gutteridge via gnats wrote:
> I've never used this feature, but from looking at what's documented in
> security(7) and what /etc/rc.d/perusertmp does, I can't see how it
> would work at all as-is. According to the steps you've listed, you'd
> end up with a /tmp link that points to /private/tmp/@ruid. But nothing
> has populated the actual per-user directories at this point. If you're
> root, it would expect /private/tmp/0 as a directory, for example. Each
> UID-specific directory would need (secured) permissions appropriate to
> that account, of course. I see nothing in the rc.d infrastructure that
> would create this (nor is it mentioned in the man page).
>
There's a very obscure trick which makes per-user-tmp dirs work. See
the code in setusercontext() which every login-type program (eg. sshd)
ends up calling:
https://github.com/NetBSD/src/blob/trunk/lib/libutil/login_cap.c#L624
This creates the /private/tmp/NNNN dirs for each user logging into the
system.
> You wrote "Other programs like ed(1) or vi(1) do not have a problem to
> write to this symlinked temp directory on the other hand."
>
Programs like ed(1) and vi(1) work because they don't apply realpath(3)
to their temp. filenames. tmux(1), however, uses realpath() on its socket
pathname. And, the way realpath() works, testing each component for a
symlink, then using readlink(2) on symlinks, is what causes this failure
because what readlink() returns contains `@ruid' which is _not_ expanded
because that's _not_ a symlink. The kernel only expands magic tokens in
_symlinks_ and no where else. This is easily seen; to wit:
$ realpath /tmp
/private/tmp/@ruid # <--- note: @ruid, not 1000 or whatever
$ realpath /private/tmp/@ruid
/private/tmp/@ruid # <--- no expansion as not a symlink
$ readlink /tmp
/private/tmp/@ruid # as expected
$ readlink -v /private/tmp/@ruid
readlink: /private/tmp/@ruid: lstat: No such file or directory
$
I made a hacky patch (duplicating the entire symlink_magic() machinery
present in kern/vfs_lookup.c) awhile back for do_sys_readlinkat() which
expands these magic tokens, but, that then needed a lot more elsewhere
(because of the expansion removing the tokens). I've given up for the
time-being.
-RVP
-RVP
From: "David H. Gutteridge" <david@gutteridge.ca>
To: RVP <rvp@SDF.ORG>, gnats-bugs@netbsd.org
Cc:
Subject: Re: kern/58438 (Compatibility issues with per-user-temp [described
security(7) man page])
Date: Sun, 27 Oct 2024 17:53:59 -0400
On Sun, 2024-10-27 at 11:38 +0000, RVP wrote:
> On Sun, 27 Oct 2024, David H. Gutteridge via gnats wrote:
>=20
> > I've never used this feature, but from looking at what's documented
> > in
> > security(7) and what /etc/rc.d/perusertmp does, I can't see how it
> > would work at all as-is. According to the steps you've listed, you'd
> > end up with a /tmp link that points to /private/tmp/@ruid. But
> > nothing
> > has populated the actual per-user directories at this point. If
> > you're
> > root, it would expect /private/tmp/0 as a directory, for example.
> > Each
> > UID-specific directory would need (secured) permissions appropriate
> > to
> > that account, of course. I see nothing in the rc.d infrastructure
> > that
> > would create this (nor is it mentioned in the man page).
> >=20
>=20
> There's a very obscure trick which makes per-user-tmp dirs work. See
> the code in setusercontext() which every login-type program (eg. sshd)
> ends up calling:
>=20
> https://github.com/NetBSD/src/blob/trunk/lib/libutil/login_cap.c#L624
>=20
> This creates the /private/tmp/NNNN dirs for each user logging into the
> system.
>=20
Well, I guess that teaches me not to rely on code inspection instead of
turning the feature on to check! Heh. I looked into login(1) itself, but
not there.
I wonder what nonaka@ intended to address with that GitHub gist patch,
then. It was created five years after the code you reference was added.
Perhaps in attempted response to this very type of issue.
> > You wrote "Other programs like ed(1) or vi(1) do not have a problem
> > to
> > write to this symlinked temp directory on the other hand."
> >=20
>=20
> Programs like ed(1) and vi(1) work because they don't apply
> realpath(3)
> to their temp. filenames. tmux(1), however, uses realpath() on its
> socket
> pathname. And, the way realpath() works, testing each component for a
> symlink, then using readlink(2) on symlinks, is what causes this
> failure
> because what readlink() returns contains `@ruid' which is _not_
> expanded
> because that's _not_ a symlink. The kernel only expands magic tokens
> in
> _symlinks_ and no where else.=C2=A0 This is easily seen; to wit:
>=20
> $ realpath /tmp
> /private/tmp/@ruid # <--- note: @ruid, not 1000 or
> whatever
> $ realpath /private/tmp/@ruid
> /private/tmp/@ruid # <--- no expansion as not a symlink
> $ readlink /tmp
> /private/tmp/@ruid # as expected
> $ readlink -v /private/tmp/@ruid
> readlink: /private/tmp/@ruid: lstat: No such file or directory
> $
>=20
> I made a hacky patch (duplicating the entire symlink_magic() machinery
> present in kern/vfs_lookup.c) awhile back for do_sys_readlinkat()
> which
> expands these magic tokens, but, that then needed a lot more elsewhere
> (because of the expansion removing the tokens). I've given up for the
> time-being.
I guess I find it a bit concerning that this feature was added which (1)
doesn't work with some basic use cases and (2) doesn't document this
limitation. #2 is easy enough to remedy.
Thanks,
Dave
From: "David H. Gutteridge" <gutteridge@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/58438 CVS commit: src/share/man/man7
Date: Wed, 30 Oct 2024 01:44:43 +0000
Module Name: src
Committed By: gutteridge
Date: Wed Oct 30 01:44:43 UTC 2024
Modified Files:
src/share/man/man7: security.7
Log Message:
security.7: note some programs won't work with per-user-tmp
Addresses a documentation aspect of PR kern/58438.
To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/share/man/man7/security.7
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
State-Changed-From-To: open->feedback
State-Changed-By: gutteridge@NetBSD.org
State-Changed-When: Thu, 31 Oct 2024 01:24:32 +0000
State-Changed-Why:
You stated this is "incompatible with certain system-softwares like
X(1) or even tmux(1)". I'm able to reproduce the issue with tmux(1), as
RVP has explained in detail. I'm not able to reproduce with an X
session, that works fine for me. Can you give more specific details
about what is failing for you in an X11 context, please?
From: Marc Daniel Fege <13mdf@fege.net>
To: kern-bug-people@netbsd.org, netbsd-bugs@netbsd.org,
gnats-admin@netbsd.org, gutteridge@netbsd.org, gnats-bugs@netbsd.org
Cc:
Subject: Re: kern/58438 (Compatibility issues with per-user-temp [described
security(7) man page])
Date: Thu, 31 Oct 2024 07:29:11 +0100
Hello,
Of course. X in terms of xdm session manager won't start up for me=20
(booted via xdm=3D"YES" in /etc/rc.conf), neither on a Raspberry PI 4, nor=
=20
on an old x86 machine, whatsoever if I activate per-user-temp. I could=20
not see, whether xdm itself produces some session files within temp or=20
expects certain folders to be writable in a certain way at least, but=20
once the per-user-temp-feature is deactivated and rebooted, xdm comes up=20
again as it should be.
I hope this hint helps a bit.
Best regards =E2=80=93
Marc.
Am Donnerstag, 31. Oktober 2024, 02:24:32 Mitteleurop=C3=A4ische Normalzeit=
=20
schrieb gutteridge@NetBSD.org:
> Synopsis: Compatibility issues with per-user-temp [described
> security(7) man page]
>=20
> State-Changed-From-To: open->feedback
> State-Changed-By: gutteridge@NetBSD.org
> State-Changed-When: Thu, 31 Oct 2024 01:24:32 +0000
> State-Changed-Why:
> You stated this is "incompatible with certain system-softwares like
> X(1) or even tmux(1)". I'm able to reproduce the issue with tmux(1),
> as RVP has explained in detail. I'm not able to reproduce with an X
> session, that works fine for me. Can you give more specific details
> about what is failing for you in an X11 context, please?
From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc: "David H. Gutteridge" <gutteridge@netbsd.org>
Subject: Re: kern/58438 (Compatibility issues with per-user-temp [described
security(7) man page])
Date: Fri, 1 Nov 2024 00:49:06 +0000 (UTC)
On Sun, 27 Oct 2024, David H. Gutteridge via gnats wrote:
> I guess I find it a bit concerning that this feature was added which (1)
> doesn't work with some basic use cases and (2) doesn't document this
> limitation. #2 is easy enough to remedy.
>
Since userspace needs to see the @magic tokens (as we've seen), and realpath(3)
seems to the cause of all this, I think we should just fix it to expand those
tokens when magic-symlinks are active. That should take care of 1)--even though
this means duplicating the expansion already being done in the kernel.
Shouldn't be hard. I'll do it--but, prolly only next week.
Thx,
-RVP
From: Martin Husemann <martin@duskware.de>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: kern/58438 (Compatibility issues with per-user-temp [described
security(7) man page])
Date: Fri, 1 Nov 2024 08:29:33 +0100
On Fri, Nov 01, 2024 at 12:50:01AM +0000, RVP via gnats wrote:
> Since userspace needs to see the @magic tokens (as we've seen), and realpath(3)
> seems to the cause of all this, I think we should just fix it to expand those
> tokens when magic-symlinks are active. That should take care of 1)--even though
> this means duplicating the expansion already being done in the kernel.
>
> Shouldn't be hard. I'll do it--but, prolly only next week.
I agree with the aproach, but it is not as trivial as it sounds, see
PR kern/58801.
I wonder if we should make the mapping table the kernel uses available
(read only) to userland via a sysctl, so besides realpath(3) it could
also be used in the ATF tests. The ATF tests also should grow a realpath
test.
Or we define (and document) a fixed mapping/semantics for
machine/machine_arch that we can hardcode in both places.
Martin
From: mlelstv@serpens.de (Michael van Elst)
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: kern/58438 (Compatibility issues with per-user-temp [described security(7) man page])
Date: Fri, 1 Nov 2024 07:55:04 -0000 (UTC)
gnats-admin@NetBSD.org ("Martin Husemann via gnats") writes:
> Or we define (and document) a fixed mapping/semantics for
> machine/machine_arch that we can hardcode in both places.
sysctl does the mapping, so you can just query the kernel
and cache the result.
State-Changed-From-To: feedback->open
State-Changed-By: gutteridge@NetBSD.org
State-Changed-When: Sat, 02 Nov 2024 01:51:37 +0000
State-Changed-Why:
Feedback provided. I'll take a look at xdm(8).
From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc: gutteridge@NetBSD.org
Subject: Re: kern/58438 (Compatibility issues with per-user-temp [described
security(7) man page])
Date: Sat, 2 Nov 2024 08:28:12 +0000 (UTC)
OK, this patch seems to work.
When xdm is started using the rc(8) framework, setusercontext(3) never gets
called (this is only called in xdm _after_ user authentication), so the X
server can't start without /private/tmp/0 existing. Do a bogus su(1) in
/etc/rc.d/xdm to create this.
Next, do the same for each user before _their_ X session is started; _and_
since now X is running as root and the user is not, and there's no shared
/tmp anymore, link root's X11 lock-file and socket into the user's per-user
/tmp dir.
Thankfully, both files are normally world-readable and -writable by default.
This is a terrible hack... (note that if you change xdm-config to use a
different DisplayManager._0.startup, you'll have to put that hack in the new
file.)
-RVP
```
--- etc/rc.d/xdm.orig 2024-01-29 23:14:46.000000000 +0000
+++ etc/rc.d/xdm 2024-11-02 07:40:02.031867487 +0000
@@ -17,4 +17,9 @@
extra_commands="reload"
load_rc_config $name
+
+if readlink /tmp | grep -q @ruid && [ $1 = start ]
+then su root -c 'echo "Bogus su(1) to create /private/tmp/0"'
+fi
+
run_rc_command "$1"
--- etc/X11/xdm/GiveConsole.orig 2024-01-29 23:14:46.000000000 +0000
+++ etc/X11/xdm/GiveConsole 2024-11-02 07:35:40.902195347 +0000
@@ -7,3 +7,18 @@
# causing serious grief.
#
chown $USER /dev/console
+
+UID=$(id -u $USER)
+if readlink /tmp | grep -q @ruid && [ $UID -ne 0 ]
+then
+ # First, do a bogus su(1) to create $USER's "/tmp" dir.;
+ # then force create _hard-links_ to root's X socket and
+ # lock-file _every time_--as the inodes of root's files
+ # could change with every session.
+
+ su "$USER" -c "echo 'This creates /private/tmp/$UID'"
+ cd /private/tmp/$UID || exit 1 # sanity chk.
+ test -d .X11-unix || install -dm 700 -o $USER .X11-unix
+ ln -f /private/tmp/0/.X0-lock .X0-lock
+ ln -f /private/tmp/0/.X11-unix/X0 .X11-unix/X0
+fi
```
From: "David H. Gutteridge" <david@gutteridge.ca>
To: RVP <rvp@SDF.ORG>, gnats-bugs@netbsd.org
Cc:
Subject: Re: kern/58438 (Compatibility issues with per-user-temp [described
security(7) man page])
Date: Thu, 07 Nov 2024 00:47:01 -0500
On Sat, 2024-11-02 at 08:28 +0000, RVP wrote:
> OK, this patch seems to work.
>=20
> When xdm is started using the rc(8) framework, setusercontext(3) never
> gets
> called (this is only called in xdm _after_ user authentication), so
> the X
> server can't start without /private/tmp/0 existing. Do a bogus su(1)
> in
> /etc/rc.d/xdm to create this.
>=20
> Next, do the same for each user before _their_ X session is started;
> _and_
> since now X is running as root and the user is not, and there's no
> shared
> /tmp anymore, link root's X11 lock-file and socket into the user's
> per-user
> /tmp dir.
>=20
> Thankfully, both files are normally world-readable and -writable by
> default.
>=20
> This is a terrible hack... (note that if you change xdm-config to use
> a
> different DisplayManager._0.startup, you'll have to put that hack in
> the new
> file.)
Thanks for doing all this!
This makes me wonder if the patch I'd found from nonaka@ existed for
reasons somewhat like this; if there are various programs that have
issues here if there's no /private/tmp/0 or what-have-you created
without recourse to that login trick. Seems like it wouldn't have
fully helped here, mind you, given the assumptions xdm makes.
Dave
State-Changed-From-To: open->analyzed
State-Changed-By: gutteridge@NetBSD.org
State-Changed-When: Fri, 27 Dec 2024 17:19:22 +0000
State-Changed-Why:
Issue is understood, and fix under discussion.
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.47 2022/09/11 19:34:41 kim Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2024
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.