Identifying architecture dependent location of nsswitch libraries - linux

I have a DEB package which dynamically creates a chroot filesystem in package postinst helper script. The package works fine for x86, amd64, and arm64 on Debian Stretch/Buster/Bullseye and Ubuntu Bionic/Focal/Jammy. However, I recently tried to install it on Raspbian arm32 and it failed.
The problem is that the pathname of the nsswitch libraries is constructed differently than on the other platforms. In other words, the piece meal assembly of the library path using uname -m is not matching what's present in the file-system.
#!/bin/bash -eu
U=chroot_user
UHOME=/home/$U
ARCH=$(uname -m)
function add_executable () {
FROM="$1"; shift
TO="$(basename $FROM)"
if [ $# -ge 1 ]; then
TO=$1; shift
fi
cp "$FROM" "$UHOME/bin/$TO"
ldd "$FROM" | grep "=> /" | awk '{print $3}' | xargs -I '{}' cp '{}' $UHOME/lib/
LIBNAME="ld-linux-$(echo $ARCH | tr '_' '-').so*"
if compgen -G "/lib64/${LIBNAME}" > /dev/null; then
cp /lib64/${LIBNAME} $UHOME/lib64/
elif compgen -G "/lib/${LIBNAME}" > /dev/null; then
cp /lib/${LIBNAME} $UHOME/lib/
fi
}
if [ "$1" = "configure" ]; then
# Create a system user that has restricted bash as its login shell.
IS_USER=$(grep $U /etc/passwd || true)
if [ ! -z "$IS_USER" ]; then
killall -u $U || true
userdel -f $U > /dev/null 2>&1 || true
fi
adduser --system --home ${UHOME} --no-create-home --group --shell /bin/rbash ${U}
# Create a clean usable chroot
rm -rf $UHOME
mkdir -p $UHOME
mkdir -p $UHOME/dev/
mknod -m 666 $UHOME/dev/null c 1 3
mknod -m 666 $UHOME/dev/tty c 5 0
mknod -m 666 $UHOME/dev/zero c 1 5
mknod -m 666 $UHOME/dev/random c 1 8
mknod -m 644 $UHOME/dev/urandom c 1 9
chown root:root $UHOME
chmod 0755 $UHOME
mkdir -p $UHOME/bin
mkdir -p $UHOME/etc
mkdir -p $UHOME/lib
mkdir -p $UHOME/usr
cd $UHOME/usr
ln -s ../bin bin
cd - > /dev/null
cd $UHOME
ln -s lib lib64
cd - > /dev/null
mkdir $UHOME/lib/${ARCH}-linux-gnu
cp /lib/${ARCH}-linux-gnu/libnss* $UHOME/lib/${ARCH}-linux-gnu
cat <<EOT>$UHOME/etc/nsswitch.conf
passwd: files
group: files
EOT
chmod 0444 $UHOME/etc/nsswitch.conf
echo "127.0.0.1 localhost" > $UHOME/etc/hosts
chmod 0444 $UHOME/etc/hosts
if [ -d /etc/terminfo/ ]; then
cp -R /etc/terminfo $UHOME/etc
fi
if [ -d /lib/terminfo/ ]; then
cp -R /lib/terminfo $UHOME/lib
fi
# Add restricted bash and ssh/scp executables into the chroot. There is no
# need for any other executable.
add_executable /bin/bash rbash
add_executable /usr/bin/ssh
add_executable /usr/bin/scp
add_executable /bin/date
add_executable /bin/ls
add_executable /bin/rm
add_executable /bin/mv
add_executable /bin/cp
grep $U /etc/passwd > $UHOME/etc/passwd
grep $U /etc/group > $UHOME/etc/group
mkdir -p $UHOME/.ssh
chmod 700 $UHOME/.ssh
chown -R $U:$U $UHOME/.ssh
# When using SSH to get out of the jail onto localhost machine, we don't want
# to be constantly told about fingerprints and permanently added hosts
mkdir -p $UHOME/home/$U/.ssh
chmod 0700 $UHOME/home/$U/.ssh
chown -R $U:$U $UHOME/home/$U
fi
#DEBHELPER#
exit 0
# vim: set ts=2 sw=2 tw=0 et :

Not in the expected location ... well, more like: the architecture type in uname's output doesn't match the directory name you want to construct ...
But you could find the directory in a different way, since you're on apt based distros.
dpkg -L libnss3 | awk '/libnss3.so/{gsub(/\/libnss3.so/,"",$0);print}'
This worked for me on both Ubuntu 20.04 and Raspbian GNU/Linux 10 (buster)
Raspbian:
$ dpkg -L libnss3 | awk '/libnss3.so/{gsub(/\/libnss3.so/,"",$0);print}'
/usr/lib/arm-linux-gnueabihf
Ubuntu:
$ dpkg -L libnss3 | awk '/libnss3.so/{gsub(/\/libnss3.so/,"",$0);print}'
/usr/lib/x86_64-linux-gnu

Related

Limited a user with creating rbash, exporting the path in .bashrc but /bin/ls still works

I tried limiting ls command to a specific user. It works, but when I execute /bin/ls, it executes successfully again, how to restrict here.
useradd -m $username -s /bin/rbash
echo "$username:$password" | chpasswd
mkdir /home/$username/bin
chmod 755 /home/$username/bin
echo "PATH=$HOME/bin" >> /home/$username/.bashrc
echo "export PATH" >> /home/$username/.bashrc
ln -s /bin/ls /home/$username/bin/

How to change dqpk-query -L <package-name> view?

I use dpkg-query -L <package-name> to list all files belong to the specific package.
The result is a lot of files with their directory:
/.
/usr
/usr/bin
/usr/bin/tree
/usr/share
/usr/share/doc
/usr/share/doc/tree
/usr/share/doc/tree/TODO
/usr/share/doc/tree/copyright
/usr/share/doc/tree/README.gz
/usr/share/doc/tree/changelog.Debian.gz
/usr/share/man
/usr/share/man/man1
/usr/share/man/man1/tree.1.gz
Because the outpu is too many,i always use this command like this:
dpkg-query -L tree > tree.txt
My question is how to change the view of the list in tree.txt to become more human readable,let the output be sorted by their directory prefix.
The rpm -ql <package-name> comand has the same use on Centos.
If you are only interested in the folders:
dpkg -L <pkg-name> | xargs -I{} dirname {} | sort -u
A version which groups files by directory could be done using a shell function:
lspkg() {
pkg="${1}"
if [ -t 1 ] ; then
color_dir=$'\x1b\x5b34;1m'
color_link=$'\x1b\x5b36m'
color_end=$'\x1b\x5b0m'
fi
LANG=C dpkg -L "${pkg}" \
| awk -F: '{printf "%s%s\n",$NF,(NF>1?" (pkg set link)":"")}' \
| sort \
| while read -r file ; do
if [ -d "${file}" ] ; then
echo "${color_dir}${file}${color_end}"
elif /bin/grep -q 'set link)' <<< "$file" ; then
echo " - ${color_link}${file}${color_end}"
else
echo " - ${file}"
fi
done
}

Creating a docker Base Image

I have a private Linux distribution (based on redhat7).
I have an ISO file which holds the installation of that distribution, which can be used to install the OS on a clear system only.
I have some programs I would like to run as images on docker, each program on a different image.
Each program can only run on my Linux environment and so I am looking for a way to create the appropriate images, so they can be ran under docker.
I tried following Solomon instructions here:
mkdir rootfs
mount -o loop /path/to/iso rootfs
tar -C rootfs -c . | docker import - rich/mybase
But I don't know how to proceed. I can't run any command since the machine isn't running yet (no /bin/bash/ etc.)
How can I open the installation shell?
Is there a better way to run programs via docker on a private Linux distribution?
(Just to be clear, the programs can run only on that specific OS and that OS can only be installed on a clear machine. Not sure if I need a base image but I'd like to run these programs with Docker and that is possible only over this OS)
I ran into many questions like mine (like this) but I couldn't find answer that helped me.
Assumption
Server A where the ISO will be mount
Server R your private repositoy
Server N where container will be run
All server can connect to server R.
How to
build a base image as mentioned in your OP (named base/myimage)
Push the image to your private repository https://docs.docker.com/registry/deploying/
Create application images from your base base/myimage then push them to your private repo
From Server N, run the application image
docker run application/myapp
This script is from the official Docker contrib repo. It's used to create CentOS images from scratch. It should work with any Redhat/Centos based system and gives you plenty of control over the various steps. Anything beyond that you can then modify post-base-image through a Dockerfile.
The file is here
#!/usr/bin/env bash
#
# Create a base CentOS Docker image.
#
# This script is useful on systems with yum installed (e.g., building
# a CentOS image on CentOS). See contrib/mkimage-rinse.sh for a way
# to build CentOS images on other systems.
usage() {
cat <<EOOPTS
$(basename $0) [OPTIONS] <name>
OPTIONS:
-p "<packages>" The list of packages to install in the container.
The default is blank.
-g "<groups>" The groups of packages to install in the container.
The default is "Core".
-y <yumconf> The path to the yum config to install packages from. The
default is /etc/yum.conf for Centos/RHEL and /etc/dnf/dnf.conf for Fedora
EOOPTS
exit 1
}
# option defaults
yum_config=/etc/yum.conf
if [ -f /etc/dnf/dnf.conf ] && command -v dnf &> /dev/null; then
yum_config=/etc/dnf/dnf.conf
alias yum=dnf
fi
install_groups="Core"
while getopts ":y:p:g:h" opt; do
case $opt in
y)
yum_config=$OPTARG
;;
h)
usage
;;
p)
install_packages="$OPTARG"
;;
g)
install_groups="$OPTARG"
;;
\?)
echo "Invalid option: -$OPTARG"
usage
;;
esac
done
shift $((OPTIND - 1))
name=$1
if [[ -z $name ]]; then
usage
fi
target=$(mktemp -d --tmpdir $(basename $0).XXXXXX)
set -x
mkdir -m 755 "$target"/dev
mknod -m 600 "$target"/dev/console c 5 1
mknod -m 600 "$target"/dev/initctl p
mknod -m 666 "$target"/dev/full c 1 7
mknod -m 666 "$target"/dev/null c 1 3
mknod -m 666 "$target"/dev/ptmx c 5 2
mknod -m 666 "$target"/dev/random c 1 8
mknod -m 666 "$target"/dev/tty c 5 0
mknod -m 666 "$target"/dev/tty0 c 4 0
mknod -m 666 "$target"/dev/urandom c 1 9
mknod -m 666 "$target"/dev/zero c 1 5
# amazon linux yum will fail without vars set
if [ -d /etc/yum/vars ]; then
mkdir -p -m 755 "$target"/etc/yum
cp -a /etc/yum/vars "$target"/etc/yum/
fi
if [[ -n "$install_groups" ]];
then
yum -c "$yum_config" --installroot="$target" --releasever=/ --setopt=tsflags=nodocs \
--setopt=group_package_types=mandatory -y groupinstall $install_groups
fi
if [[ -n "$install_packages" ]];
then
yum -c "$yum_config" --installroot="$target" --releasever=/ --setopt=tsflags=nodocs \
--setopt=group_package_types=mandatory -y install $install_packages
fi
yum -c "$yum_config" --installroot="$target" -y clean all
cat > "$target"/etc/sysconfig/network <<EOF
NETWORKING=yes
HOSTNAME=localhost.localdomain
EOF
# effectively: febootstrap-minimize --keep-zoneinfo --keep-rpmdb --keep-services "$target".
# locales
rm -rf "$target"/usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive}
# docs and man pages
rm -rf "$target"/usr/share/{man,doc,info,gnome/help}
# cracklib
rm -rf "$target"/usr/share/cracklib
# i18n
rm -rf "$target"/usr/share/i18n
# yum cache
rm -rf "$target"/var/cache/yum
mkdir -p --mode=0755 "$target"/var/cache/yum
# sln
rm -rf "$target"/sbin/sln
# ldconfig
rm -rf "$target"/etc/ld.so.cache "$target"/var/cache/ldconfig
mkdir -p --mode=0755 "$target"/var/cache/ldconfig
version=
for file in "$target"/etc/{redhat,system}-release
do
if [ -r "$file" ]; then
version="$(sed 's/^[^0-9\]*\([0-9.]\+\).*$/\1/' "$file")"
break
fi
done
if [ -z "$version" ]; then
echo >&2 "warning: cannot autodetect OS version, using '$name' as tag"
version=$name
fi
tar --numeric-owner -c -C "$target" . | docker import - $name:$version
docker run -i -t --rm $name:$version /bin/bash -c 'echo success'
rm -rf "$target"

Update bash script, file check, how?

#!/bin/sh
LOCAL=/var/local
TMP=/var/tmp
URL=http://um10.eset.com/eset_upd
USER=""
PASSWD=""
WGET="wget --user=$USER --password=$PASSWD -t 15 -T 15 -N -nH -nd -q"
UPDATEFILE="update.ver"
cd $LOCAL
CMD="$WGET $URL/$UPDATEFILE"
eval "$CMD" || exit 1;
if [ -n "`file $UPDATEFILE|grep -i rar`" ]; then
(
cd $TMP
rm -f $TMP/$UPDATEFILE
unrar x $LOCAL/$UPDATEFILE ./
)
UPDATEFILE=$TMP/$UPDATEFILE
URL=`echo $URL|sed -e s:/eset_upd::`
fi
TMPFILE=$TMP/nod32tmpfile
grep file=/ $UPDATEFILE|tr -d \\r > $TMPFILE
FILELIST=`cut -c 6- $TMPFILE`
rm -f $TMPFILE
echo "Downloading updates..."
for FILE in $FILELIST; do
CMD="$WGET \"$URL$FILE\""
eval "$CMD"
done
cp $UPDATEFILE $LOCAL/update.ver
perl -i -pe 's/\/download\/\S+\/(\S+\.nup)/\1/g' $LOCAL/update.ver
echo "Done."
So I have this code to download definitions for my antivirus. The only problem is that, it downloads all files everytime i run script. Is it possible to implement some sort file checking ?, let's say for example,
"if that file is present and have same filesize skip it"
Bash Linux
The -nc argument to wget will not re-fetch files that already exist. It is, however, not compatible with the -N switch. So you'll have to change your WGET line to:
WGET="wget --user=$USER --password=$PASSWD -t 15 -T 15 -nH -nd -q -nc"

Linux Malware Detect on shared hosting

I am trying to install the excellent http://www.rfxn.com/projects/linux-malware-detect/ on a shared hosting.
I have changed the inspath to my local dir but it gives errors on creating symbolic links, read only on /usr/lib/, and finally /usr/local/maldetect/conf.maldet not found.
Thanks for any help. I think solving this would prove very useful to a lot of people.
Here's the error:
./install.sh
ln: creating symbolic link `/usr/local/sbin/maldet' to `/home6/anton/mal/maldet': No such file or directory
ln: creating symbolic link `/usr/local/sbin/lmd' to `/home6/anton/mal/maldet': No such file or directory
cp: cannot create regular file `/usr/lib/libinotifytools.so.0': Read-only file system
Linux Malware Detect v1.3.9
(C) 2002-2011, R-fx Networks <proj#r-fx.org>
(C) 2011, Ryan MacDonald <ryan#r-fx.org>
inotifywait (C) 2007, Rohan McGovern <rohan#mcgovern.id.au>
This program may be freely redistributed under the terms of the GNU GPL v2
maldet(15528): {glob} /usr/local/maldetect/conf.maldet not found, aborting.
installation completed to /home6/anton/mal
config file: /home6/anton/mal/conf.maldet
exec file: /home6/anton/mal/maldet
exec link: /usr/local/sbin/maldet
exec link: /usr/local/sbin/lmd
cron.daily: /etc/cron.daily/maldet
.ca.def: line 1: /usr/local/maldetect/conf.maldet: No such file or directory
imported config options from /home6/anton/mal.last/conf.maldet
maldet(15578): {glob} /usr/local/maldetect/conf.maldet not found, aborting.
And here's the install bash:
#!/bin/bash
#
##
# Linux Malware Detect v1.3.9
# (C) 2002-2011, R-fx Networks <proj#r-fx.org>
# (C) 2011, Ryan MacDonald <ryan#r-fx.org>
# inotifywait (C) 2007, Rohan McGovern <rohan#mcgovern.id.au>
# This program may be freely redistributed under the terms of the GNU GPL v2
##
#
inspath=/home6/anton/mal
logf=$inspath/event_log
cnftemp=.ca.def
if [ ! -d "$inspath" ] && [ -d "files" ]; then
mkdir -p $inspath
chmod 750 $inspath
cp -pR files/* $inspath
chmod 750 $inspath/maldet
ln -fs $inspath/maldet /usr/local/sbin/maldet
ln -fs $inspath/maldet /usr/local/sbin/lmd
cp $inspath/inotify/libinotifytools.so.0 /usr/lib/
else
$inspath/maldet -k >> /dev/null 2>&1
mv $inspath $inspath.bk$$
rm -f $inspath.last
ln -fs $inspath.bk$$ $inspath.last
mkdir -p $inspath
chmod 750 $inspath
cp -pR files/* $inspath
chmod 750 $inspath/maldet
ln -fs $inspath/maldet /usr/local/sbin/maldet
ln -fs $inspath/maldet /usr/local/sbin/lmd
cp $inspath/inotify/libinotifytools.so.0 /usr/lib/
cp -f $inspath.bk$$/sess/* $inspath/sess/ >> /dev/null 2>&1
cp -f $inspath.bk$$/tmp/* $inspath/tmp/ >> /dev/null 2>&1
cp -f $inspath.bk$$/quarantine/* $inspath/quarantine/ >> /dev/null 2>&1
fi
if [ -d "/etc/cron.daily" ]; then
cp -f cron.daily /etc/cron.daily/maldet
chmod 755 /etc/cron.daily/maldet
fi
touch $logf
$inspath/maldet --alert-daily
$inspath/maldet --alert-weekly
echo "Linux Malware Detect v1.3.9"
echo " (C) 2002-2011, R-fx Networks <proj#r-fx.org>"
echo " (C) 2011, Ryan MacDonald <ryan#r-fx.org>"
echo "inotifywait (C) 2007, Rohan McGovern <rohan#mcgovern.id.au>"
echo "This program may be freely redistributed under the terms of the GNU GPL"
echo ""
echo "installation completed to $inspath"
echo "config file: $inspath/conf.maldet"
echo "exec file: $inspath/maldet"
echo "exec link: /usr/local/sbin/maldet"
echo "exec link: /usr/local/sbin/lmd"
echo "cron.daily: /etc/cron.daily/maldet"
echo ""
if [ -f "$cnftemp" ] && [ -f "$inspath.bk$$/conf.maldet" ]; then
. files/conf.maldet
. $inspath.bk$$/conf.maldet
. $cnftemp
echo "imported config options from $inspath.last/conf.maldet"
fi
$inspath/maldet --update 1
Most shared hosting doesn't allow its user to access the system folder.
/usr/lib/
/usr/local/
is one example of the system folder. So, I guess you can't install that software due to this limitation.

Resources