Infrastructure in place to run each app as a separate user
The 'spot' user was broken in EasyOS, for the situation in which a password is entered at bootup and folders in the working-partition are encrypted. After some experimenting and lucky guesses, this problem was solved, see previous blog post:
https://bkhome.org/news/202109/fscrypt-now-works-in-user-spot.html
I have now embarked on a significant change in how EasyOS works: run
any app that accesses the Internet as a non-root user. Not 'spot', but
each app will run as its own user.
I got this idea a couple of years ago, when reading how Android
works. This is how Android works, each app runs as a separate user. This
then can be the basic mechanism for access permissions. For example, if
file /etc/group has a group for "camera", like this:
camera::118:root,spot
...on the end is a comma-delimited list of users allowed to access the "camera" group.
Running an app as a non-root user also means that it can't write just
anywhere in the filesystem, can be constrained to only write in its own
home folder. And if required, can be prevented from reading critical
files.
Of course Easy already has "crippled root" in containers, so running,
say, SeaMonkey, on the main desktop as a non-root user would have to be
seen as an alternative security strategy. SeaMonkey will run a little
bit faster, and won't have the issues that some people have reported
with running SM in a container, such as problem with network
connectivity.
If each app is run as its own user, this means that EasyOS can
implement a permissions management GUI like in Android. Like, do you
want this app to be able to access the camera, network, audio, folders
outside the "home" folder? ...etc.
So, have started to setup the infrastructure to support this. The
idea is that top-level /clients folder will have these non-root users,
though I would like to refer to them as "clients".
WoofQ is now defaulting to run SeaMonkey as a client. That is, it
will run as user "seamonkey" and group "seamonkey". So, in woofQ, have
built EasyOS, and running it, this is what is seen under /clients
folder:
...'rover' and 'zeus' were experiments, they may get removed. 'spot' is deprecated, may also get removed.
The idea is that each client app will have a folder under /clients,
which is actually the home-folder for that app. Clicking on 'seamonkey'
will show what that client has to "offer":
The 'Downloads' folder is SeaMonkey's default file download and open
location. Clicking on the 'seamonkey' icon will run SeaMonkey. I don't
know what 'Desktop' folder is for, SeaMonkey created that automatically.
Of course, SM can still be launched in the usual way, from the "www"
icon on the desktop, or via the menu. And it will run as a client, that
is, as user 'seamonkey'.
As before, SeaMonkey can be changed to run either as a root user, or
client 'seamonkey', via the menu "System -> Login & Security
Manager". Just like before, with 'spot'.
There is a file that shows what apps are running as a client, it is
file /root/.clients-status. Here it what it has on my currenly running
EasyOS:
seamonkey=true
Which means that SM will run as a client. If it had
"seamonkey=false", or seamonkey completely missing from the file, then
SM will run as root. The "Login & Security Manager" writes to this
file.
Scripts for client management are now grouped under
/usr/local/clients. WoofQ runs one of these, 'setup-client', when
building EasyOS, if it is chosen to run SM as a client. The main thing
that the script does is create a special script for running SM,
/usr/bin/seamonkey (and the original is renamed to seamonkey.bin). Here
is the script:
#!/bin/sh
APPbin='/usr/bin/seamonkey.bin'
APPname='seamonkey'
DISPLAY=:0
[ -f /clients/seamonkey/.mozilla/seamonkey/a2bvafqx.default/places.sqlite ] && ln -snf /usr/lib/seamonkey/seamonkey /usr/bin/seamonkey.bin
#script to run $APPbin as a client...
ARGS=""
if [ $1 ];then
while [ "$1" ]
do
#do not put quotes around if a single word. example is "-edit" for seamonkey, the quotes stuff it up entirely...
if [ "${1/ /}" == "${1}" ];then
ARGS="${ARGS} ${1}"
else
ARGS="${ARGS} \"${1}\""
fi
shift
done
fi
if [ $(id -u) -ne 0 ]; then
exec "$APPbin" $ARGS
fi
#if inside a container, do not run as client...
if [ -f /INSIDE_* ];then
exec "$APPbin" ${ROOTOPTS} ${ARGS}
fi
#this is a method to authorize x server to run by user. works when server running.
#note: this setting does not seem to be stored in a file. it affects the currently
# running x server and will be lost when x quits.
ALLOWflg="$(xhost | grep -o ":${APPname}$")"
if [ ! "$ALLOWflg" ];then
xhost +SI:localuser:${APPname}
fi
[ $XAUTHORITY ] && cp $XAUTHORITY -f /clients/${APPname}/.Xauthority 2>/dev/null
touch /clients/${APPname}/.Xauthority
#following line is mostly there to catch any root:root files that may have got copied in...
chown -R ${APPname}:${APPname} /clients/${APPname} &
sleep 0.1
export XAUTHORITY=/clients/${APPname}/.Xauthority
export XDG_CONFIG_HOME=/clients/${APPname}/.config
export XDG_CACHE_HOME=/clients/${APPname}/.cache
export XDG_DATA_HOME=/clients/${APPname}/.local/share
#20210912 need to allow write inside encrypted fs...
which keyctl >/dev/null
if [ $? -eq 0 ];then
IDflg="$(grep -o " logon " /proc/keys)"
else
IDflg=""
fi
if [ "$IDflg" ];then
exec su -l ${APPname} -s /bin/sh -c "DISPLAY=${DISPLAY} /usr/local/clients/run-client-indirect \"$APPbin\" $ARGS"
else
exec su -l ${APPname} -s /bin/sh -c "DISPLAY=${DISPLAY} \"$APPbin\" $ARGS"
fi
This is the content of /usr/local/clients/run-client-indirect:
#!/bin/sh
#when running in fscrypt encrypted folder, need to run this so as
#to enable write-permission when logged into a non-root client.
APP="$1"; shift
ARGS=""
#[ $1 ] && while [ "$1" ]; do ARGS="$ARGS \"$1\""; shift; done
if [ $1 ];then
while [ "$1" ]
do
#do not put quotes around if a single word. example is "-edit" for seamonkey, the quotes stuff it up entirely...
if [ "${1/ /}" == "${1}" ];then
ARGS="${ARGS} ${1}"
else
ARGS="${ARGS} \"${1}\""
fi
shift
done
fi
ID="$(grep " logon " /proc/keys | head -n 1 | cut -f 1 -d " ")"
if [ "$ID" ];then
keyctl link 0x${ID} @us #link fscrypt key to user-session.
fi
exec ${APP} ${ARGS}
###end###
Have posted these technical details for whoever is interested, but
from the user perspective, you just want it to work, and be easy to use.
Well, it should be easy. SeaMonkey works as normal, except that
cannot save files outside its home, /clients/seamonkey. Not by default
anyway.
By means of the "Login & Security Manager", you should be able to select any app to run as a client.
Testing with SeaMonkey, all is good, except for the Composer module. I
use this regularly, and want to be able to edit html files anywhere.
Not quite sure how to handle this -- might setup SeaMonkey-Composer to
run as root only.
There are some issues to resolve, so it will be awhile before the
next release. It is likely that the next release of EasyOS will have a
version bump to 3.0.
I have got Chromium SFS running as a non-root user. This was a
problem, see earlier posts. Will probably have it default to run as a
client, so there will be a folder /clients/chromium, just like have for
SM.
So, what to choose? Do you run SM as a client on the main desktop, or
as "crippled root" in a container. Or... this is a possibility, run SM
as a non-root client inside a container -- I don't yet know if that will
work, but it sure would be the ultimate in security.
EDIT 2021-09-19:
Folder /clients has moved to traditional /home, see announcement:
https://bkhome.org/news/202109/sfsget-improved-and-folder-hierarchy-reconsidered.html
Tags: easy