I am trying to use yocto to build an image for a zedboard. My first build failed when it attempted to chown a bunch of files to root. It failed as part of a do_install command in one of the meta layers. The command executed this chown line:
chown -R root:root ${D}
I run bitbake as a normal, non-root user. Shouldn't I be able to compile it as non-root?
Just to test I created a new file and tried to chown to root:root and it failed in exactly the same way.
What am I missing here?
UPDATE: Looks like this is related to the use pseudo. I tried building poky without any additional layers (no xilinx, openembedded, etc) and it still failed with the same error. I tried both the jethro and fido releases with the same error.
UPDATE 2: Apparently pseudo is disabled in meta/conf/bitbake.conf. I am not sure why or how to proceed knowing this:
# Use pseudo as the fakeroot implementation
PSEUDO_LOCALSTATEDIR ?= "${WORKDIR}/pseudo/"
PSEUDO_PASSWD ?= "${STAGING_DIR_TARGET}:${STAGING_DIR_NATIVE}"
export PSEUDO_DISABLED = "1"
#export PSEUDO_PREFIX = "${STAGING_DIR_NATIVE}${prefix_native}"
#export PSEUDO_BINDIR = "${STAGING_DIR_NATIVE}${bindir_native}"
#export PSEUDO_LIBDIR = "${STAGING_DIR_NATIVE}$PSEUDOBINDIR/../lib/pseudo/lib
FAKEROOTBASEENV = "PSEUDO_BINDIR=${STAGING_BINDIR_NATIVE} PSEUDO_LIBDIR=${STAGING_BINDIR_NATIVE}/../lib/pseudo/lib PSEUDO_PREFIX=${STAGING_BINDIR_NATIVE}/../../ PSEUDO_DISABLED=1"
FAKEROOTCMD = "${STAGING_BINDIR_NATIVE}/pseudo"
FAKEROOTENV = "PSEUDO_PREFIX=${STAGING_DIR_NATIVE}${prefix_native} PSEUDO_LOCALSTATEDIR=${PSEUDO_LOCALSTATEDIR} PSEUDO_PASSWD=${PSEUDO_PASSWD} PSEUDO_NOSYMLINKEXP=1 PSEUDO_DISABLED=0"
FAKEROOTNOENV = "PSEUDO_UNLOAD=1"
FAKEROOTDIRS = "${PSEUDO_LOCALSTATEDIR}"
PREFERRED_PROVIDER_virtual/fakeroot-native ?= "pseudo-native"
What recipe in what layer? do_install for target packages runs under pseudo (a fake-root utility) so it can chown to root as a non-root user.
You should not chown files to root this is most probably the reason you get such kind of errors.
Why you want to do so?
This happened to me many times when I use bitbake as a root or when compiling with sudo. You no need privilege user for building. Actually what you really need is a user within the sudo group.
Instead can you tried the following
create yocto build user
groupadd -g 1000 build && useradd -u 1000 -g 1000 -ms /bin/bash build && usermod -a -G sudo build && usermod -a -G root build && usermod -a -G staff build
useradd -u 1000 -g 1000 -ms /bin/bash 1001 && usermod -a -G sudo 1001 && usermod -a -G root 1001 && usermod -a -G staff 1001
Chown all your files to sudo group user e.g build.
Then, grant read and write permissions
Remove tmp and cache files in the build folder.
Source the bitbake
Finally try to build.
Related
When I'm trying to create user with UID=1000 in Dockerfile
FROM alpine:3.16
RUN addgroup -g 1000 sail
RUN adduser -g 1000 -u 1000 sail
I'm getting error:
Step 3/3 : RUN adduser -g 1000 -u 1000 sail
---> Running in 0c4ce7e0bddf
adduser: uid '1000' in use
The command '/bin/sh -c adduser -g 1000 -u 1000 sail' returned a non-zero code: 1
But if I'm build a container without this stage and look to /etc/passwd there is no user with UID=1000. So it's exists only while building.
How to create user with UID=1000 properly in alpine?
Your syntax is incorrect, the adduser command of Alpine is the BusyBox one, so, unlike the "regular" adduser, here are its help page:
BusyBox v1.35.0 (2022-08-01 15:14:44 UTC) multi-call binary.
Usage: adduser [OPTIONS] USER [GROUP]
Create new user, or add USER to GROUP
-h DIR Home directory
-g GECOS GECOS field
-s SHELL Login shell
-G GRP Group
-S Create a system user
-D Don't assign a password
-H Don't create home directory
-u UID User id
-k SKEL Skeleton directory (/etc/skel)
You can easily go through it, running the command:
docker run -ti --rm alpine:3.16 adduser
The important part of information here are:
-g GECOS GECOS field
-G GRP Group
Where you can see that, a group, in BusyBox adduser requires your to be added with the option G, in capital letter, and that the option g in lowercase if for something else.
The option allows you to add a group, and not a GID, so you'll need the command:
RUN adduser -G sail -u 1000 sail
Furthermore, if you run that command, the shell will prompt you to fill in a password. You will need to skip this with the D option:
-D Don't assign a password
And so, your Dockerfile ends up being:
FROM alpine:3.16
RUN addgroup -g 1000 sail \
&& adduser -G sail -u 1000 sail -D
Note that it is always a good idea, in Docker, to reduce as much as possible the number of layers you are creating by running subsequent RUN instruction, for further reading on this, see here.
In my project, I have to introduce a new 'non-root' user. I referred standard yocto recipe model mentioned in below link for creating user and group entry in /etc/passwd and /etc/group files.
https://git.yoctoproject.org/cgit.cgi/poky/tree/meta-skeleton/recipes-skeleton/useradd/useradd-example.bb
I also tried the same way in my recipe file.
Recipe file path : recipes-connectivity/dibbler/dibbler_%.bbappend
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
#dibbler process non-root user
SRC_URI += "file://dibbler-nonroot-changes.patch"
inherit useradd
USERADD_PACKAGES = "${PN}"
GROUPADD_PARAM_${PN} = "--system dibbler"
USERADD_PARAM_${PN} = "--system --gid dibbler --no-user-group \
--home /var/lib/dibbler --no-create-home \
--shell /bin/false dibbler"
After building the component, entry for user 'dibbler' and group 'dibbler' are not found in the target rootfs which is 'tmp/work/brcm-linux-gnueabi/generic-dev-image/1.0-r0/rootfs/etc/passwd'
But I found the entry present in sysroot path which is 'tmp/sysroots/brcm/etc/passwd' and 'tmp/sysroots/brcm/etc/group'
tmp/sysroots/brcm/etc/group-
tmp/sysroots/brcm/etc/group
dibbler:x:983:
tmp/sysroots/brcm/etc/passwd-
tmp/sysroots/brcm/etc/passwd
dibbler:!:988:983::/var/lib/dibbler:/bin/false
Even I checked logs and run scripts from bitbake tasks like do_install, do_populate_package, ... I didn't get any clue to proceed further.
Bitbake install logs after clean rebuild:
Install outputs from file : tmp/work/cortexa15hf-neon-vfpv4-rdk-linux-gnueabi/dibbler/1.0.1-r0/temp/log.do_install
DEBUG: Executing shell function useradd_sysroot
NOTE: dibbler: Performing groupadd with [--root /home/vre/dmz/build-tch_broadband_93390smwvg2/tmp/sysroots/brcm93390smwvg2 --system dibbler]
NOTE: dibbler: Performing useradd with [--root /home/vre/dmz/build-tch_broadband_93390smwvg2/tmp/sysroots/brcm93390smwvg2 --system --gid dibbler --no-user-group --home /var/lib/dibbler --no-create-home --shell /bin/false dibbler]
Running groupadd commands...
Running useradd commands...
It would be helpful if anyone points what I missed or anything extraneous/unnecessary.
After analysing the rootfs logs(dev-image/1.0-r0/temp/log.do_rootfs), found that dibbler is installed as two different packages with the package names as below:
dibbler-client and
dibbler-server.
After changing 'USERADD_PARAM_${PN}' to 'USERADD_PARAM_dibbler-client', the entries for user 'dibbler' got added in rootfs also.
Below are the changes in bb recipe file:
USERADD_PACKAGES = "dibbler-client"
GROUPADD_PARAM_dibbler-client = "--system dibbler"
USERADD_PARAM_dibbler-client = "--system --gid dibbler --no-user-group \
--home /var/lib/dibbler --no-create-home \
--shell /bin/false dibbler"
I have an ECS Fargate container running a nodejs application with non-root permissions and is also mounted to EFS on /.user_data inside the container.
I followed this AWS tutorial. My setup is almost similar.
Here is the Docker file:
FROM node:12-buster-slim
RUN apt-get update && \
apt-get install -y build-essential \
wget \
python3 \
make \
gcc \
libc6-dev \
git
# delete old user
RUN userdel -r node
# Run as a non-root user
RUN addgroup "new_user_group" && \
useradd "new_user" --gid "new_user_group" \
--home-dir "/home/new_user"
RUN git clone https://github.com/test-app.git /home/new_user/app
RUN chown -R new_user:new_user_group /home/new_user
RUN mkdir -p /home/new_user/.user_data
RUN chown -R new_user:new_user_group /home/new_user/.user_data
RUN chmod -R 755 /home/new_user/
WORKDIR /home/new_user/app
RUN npm install
RUN npm run build
EXPOSE 1880
USER new_user
CMD [ "npm", "start" ]
When the Node app tries to write inside /.user_data I am getting read-write permission denied error.
If I run the container as root the app is able to read/write data.
I tried adding an access point to EFS with UID and permissions but that didn't help as well.
Please note: The Dockerfile works fine on my local machine.
Update
Read this blog post - Developers guide to using Amazon EFS with Amazon ECS and AWS Fargate – Part 2 > POSIX permissions
Might be related to the IAM Policy that was assigned to the ECS Task's IAM Role.
"...if the AWS policies do not allow the ClientRootAccess action, your user is going to be squashed to a pre-defined UID:GID that is 65534:65534. From this point on, standard POSIX permissions apply: what this user can do is determined by the POSIX file system permissions. For example, a folder owned by any UID:GID other than 65534:65534 that has 666 (rw for owner and rw for everyone) will allow this reserved user to create a file. However, a folder owned by any UID:GID other than 65534:65534 that has 644 (rw for owner and r for everyone) will NOT allow this squashed user to create a file."
Make sure that your root-dir permissions are set to 777. This way any UID can read/write this dir.
To be less permissive, set the root-dir to 755, which is set by default, see the docs. This provides read-write-execute to the root user, read-execute to group and read-execute to all other users.
A user (UID) can't access (read) a sub-directory if there's no read access to its parents (directories).
You can test it easily with Docker, here's a quick example
Create a Dockerfile -
FROM ubuntu:20.04
# Fetch values from ARGs that were declared at the top of this file
ARG APP_NAME
ARG APP_ARTIFACT_DIR
ARG APP_HOME_DIR="/app"
ARG APP_USER_NAME="appuser"
ARG APP_GROUP_ID="appgroup"
# Define workdir
ENV HOME="${APP_HOME_DIR}"
WORKDIR "${HOME}"
RUN apt-get update -y && apt-get install tree
# Define env vars
ENV PATH="${HOME}/.local/bin:${PATH}"
# Run as a non-root user
RUN addgroup "${APP_GROUP_ID}" && \
useradd "${APP_USER_NAME}" --gid "${APP_GROUP_ID}" --home-dir "${HOME}" && \
chown -R ${APP_USER_NAME} .
RUN mkdir -p rootdir && \
mkdir -p rootdir/subdir && \
touch rootdir/root.file rootdir/subdir/sub.file && \
chown -R root:root rootdir && \
chmod 600 rootdir rootdir/root.file && \
chmod -R 775 rootdir/subdir
You should play with chmod 600 and chmod -R 775, try different permissions sets such as 777 and 644, and see if it makes sense.
Build an image, run a container, and test the permissions -
docker build boyfromnorth .
docker run --rm -it boyfromnorth bash
root#e0f043d9884c:~$ su appuser
$ ls -la
total 12
drwxr-xr-x 1 appuser root 4096 Jan 30 12:23 .
drwxr-xr-x 1 root root 4096 Jan 30 12:33 ..
drw------- 3 root root 4096 Jan 30 12:23 rootdir
$ ls rootdir
ls: cannot open directory 'rootdir': Permission denied
I am trying to create a user and add it to the dialout group.
I have made a recipe that inherits useradd and adds the users my system needs.
Here is the relevant part of my recipe:
inherit useradd
USERADD_PACKAGES = "${PN}"
USERADD_PARAM_${PN} = "-d /home/myuser -r -m -s /bin/bash myuser -g
mygroup -G dialout;"
GROUPADD_PARAM_${PN} = "-g 870 mygroup;"
The build gets to the rootfs_build step before getting an error. The log shows:
NOTE: useradd: Performing useradd with [--root
/mnt/hdd1/yocto/build/tmp/work/intel_corei7_64-poky-
linux/core-image-sato/1.0-r0/rootfs -d /home/myuser -r -m -s /bin/bash
myuser -g mygroup -G dialout]
ERROR: useradd: useradd command did not succeed
Without the -G dialout option it works flawlessly.
Any idea on how to solve this?
I have also tried inheriting extrausers and doing usermod -aG dialout myuser.
I suspect this is due to the fact that the dialout group does not exist, at least not at the time when myuser is being added.
If you skip the -G dialout part and build an image, do you have a group called dialout in /etc/group? If not, you can create the dialout group in the same way you create mygroup. If it already exists I suspect you will need to make sure the package adding the dialout group is installed before your package using something like RDEPENDS_${PN} += "<package that provides dialout group>.
I encountered the same issue. The solution was to use : instead of _ when ${PN} was appended:
inherit useradd
USERADD_PACKAGES = "${PN}"
USERADD_PARAM:${PN} = "-d /home/myuser -r -m -s /bin/bash myuser -g mygroup -G dialout;"
GROUPADD_PARAM:${PN} = "-g 870 mygroup;"
I believe this is due to the new override syntax. In other cases, bitbake complains (I use "honister"), for example:
do_install_append() {
...
}
results this error message:
Variable do_install_append contains an operation using the old override syntax. Please convert this layer/metadata before attempting to use with a newer bitbake.
This can be resolved by using do_install:append().
Here is the full reference of the override syntax:
https://docs.yoctoproject.org/bitbake/bitbake-user-manual/bitbake-user-manual-metadata.html#conditional-syntax-overrides
What solved it in the end was to split up each useradd in its own recipe. I have no idea why it didn't work to have them in the same recipe, as that is based on this example in meta-skeleton.
So instead of having one users.bb with several users, I now have user1.bb, user2.bb etc., and it is working like a charm.
I would like to create a directory using a bash script and then set the mode to 00755 at the same time
mkdir -p -m=00755 "/dir/dir2"
Is this the correct way of using them together and can I also add chown command to the same line while creating them?
It goes a little like this:
install -d -m 0755 -o someuser -g somegroup /dir/dir2
If you want to set the owner during creation, you can simply impersonate as this user, using sudo for example:
sudo -uTHE_USER mkdir -p -m=00755 "/dir/dir2"
This has the advantage that there will be no time difference between creation and changing the ownership, which could otherwise being harmful if exploited.
Yes that should work. As for the chown, simply follow the command ' && chown... '. && is similar to ; except the next command ONLY executes if the previous command exits success (0).