[PATCH] selinux-policy: update to version v2.0
Dominick Grift
dominick.grift at defensec.nl
Tue Jan 14 02:51:23 PST 2025
Dominick Grift <dominick.grift at defensec.nl> writes:
> Dominick Grift <dominick.grift at defensec.nl> writes:
>
>> Stefan Hellermann <stefan at the2masters.de> writes:
>>
>>> Hi! Thank you for your really fast changes!
>>
>> Thank you for your feedback. It is appreciated. Comments below:
>>
>>>
>>> With your last commit f86def7e there are 3 new errors for /dev/urandom:
>>>
>>> [...]
>>> [ 1.749370] init: - preinit -
>>> [ 2.437887] audit: type=1400 audit(1736810585.360:3): avc: denied
>>> { getattr } for pid=886 comm="jshn" path="/dev/urandom" dev="tmpfs"
>>> ino=31 scontext=sys.id:sys.role:jshn.subj
>>> tcontext=sys.id:sys.role:random.nodedev tclass=chr_file permissive=1
>>> [ 2.438371] audit: type=1400 audit(1736810585.360:4): avc: denied
>>> { read } for pid=886 comm="jshn" name="urandom" dev="tmpfs" ino=31
>>> scontext=sys.id:sys.role:jshn.subj
>>> tcontext=sys.id:sys.role:random.nodedev tclass=chr_file permissive=1
>>> [ 2.439138] audit: type=1400 audit(1736810585.360:5): avc: denied
>>> { open } for pid=886 comm="jshn" path="/dev/urandom" dev="tmpfs"
>>> ino=31 scontext=sys.id:sys.role:jshn.subj
>>> tcontext=sys.id:sys.role:random.nodedev tclass=chr_file permissive=1
>>> [ 4.994969] random: crng init done
>>> [...]
>>
>> I will add this.
>>
>>>
>>> And I cannot login on ttyAMA0:
>>>
>>> Please press Enter to activate this console.
>>>
>>> login: can't get SID for root
>>
>> This is a bug in busybox-selinux. A fix for this was posted:
>> http://lists.busybox.net/pipermail/busybox/2022-July/089800.html but it
>> was never adopted. The aformentioned patch is tested and reviewed. It
>> address this bug.
>>
>> Maybe OpenWrt can carry this patch or maybe someone with sway in the
>> busybox community can figure out why it was not committed and get it
>> in. I tried and failed. So unless something gets done this is going to
>> linger on forever.
>>
>>>
>>>
>>> Login with ssh is ok. There is already a bug report for this, it's
>>> working fine without selinux:
>>> https://github.com/openwrt/openwrt/issues/17038
>>
>> Here is the fix:
>> http://lists.busybox.net/pipermail/busybox/2022-July/089800.html
>>
>> I just needs to be applied.
>>
>>>
>>>
>>> After sysupgrade the "sysupgrade.tgz" error remains the same:
>>>
>>> [ 12.155085] audit: type=1400 audit(1736811933.100:6): avc: denied
>>> { associate } for pid=1006 comm="mv" name="sysupgrade.tgz"
>>> scontext=sys.id:sys.role:dos.fs tcontext=sys.id:sys.role:xattr.fs
>>> tclass=filesystem permissive=1
>>>
>>
>> This is not something I can fix in the policy. Whatever does this needs
>> to be asked not to and to use cp instead of mv. Fortunately this does
>> not happen in a stock system because it involves fat.
>>
>>>
>>> And while doing sysupgrade from a local file in /tmp I get a bunch
>>> more (no luci here, just scp file to /tmp and start sysupgrade from
>>> ssh):
>
> I added limited support for scp -O with firmware images and
> backups. Untested but the pre-requisite for this to work is that that
> you scp -O the files with the names specified in the commit:
>
> https://git.defensec.nl/?p=selinux-policy.git;a=commitdiff;h=20cd42a573762ada41077c91fd14ad77c6aac6f3
>
> Still, my advice is to move away from scp -O. Its a dead end.
>
>>
>> Its comlicated and theres quite a bit involved but let me touch on some
>> of it:
>>
>> Youre using scp -O. This is legacy scp and it should be killed. If you
>> dont want to install the openssh-sftp-server package then use:
>>
>> `cat openwrt-armsr-armv8-generic-squashfs-combined.img.gz | ssh
>> root at 192.168.1.1 "cat > /tmp/sysupgrade.img"`
>>
>> dropbear uses /tmp to generate its hostkey and the way it does it is
>> selinux unfriendly. It means that if you use scp -O and you transfer a
>> file to /tmp that it ends up with the ssh hostkey label because usually
>> dropbear creates its hostkey in /tmp and then it moves it to
>> /etc/dropbear (again that stupid mv issue). Anyway I had to make do but
>> the gist is this: don't use scp -O. its dead and it needs to be burried.
>>
>> I was expecting this and I documented it in the README and I will also
>> document it elsewhere. I will also think about this some more but I kind
>> of like this implementation so far. Anyway:
>>
>> Youve scp'd the file as-is (with name
>> openwrt-armsr-armv8-generic-squashfs-combined.img.gz) and this caused
>> the file to be copied with a context that validate-firmware-image cannot
>> validate (read).
>>
>> The solution is to either use LuCI (I worked on it yesterday) or to scp
>> the file with one of these names: firmware.bin sysupgrade.img
>> sysupgrade.bin. for example:
>>
>> cat openwrt-ipq40xx-generic-linksys_mr8300-squashfs-sysupgrade.bin | ssh
>> root at openwrt "cat > /tmp/sysupgrade.bin"
>>
>> I know its a bit fragile but I kind of like it and Luci and sysupgrade
>> https://... both do something like that so I figured that if i would
>> just clearly document this requirement it would be fine
>>
>> https://git.defensec.nl/?p=selinux-policy.git;a=blob;f=src/file/tmpfile/sysupgradetmpfile.cil;h=325e12c7a4d014ca7ee1af6786d00b532846dac7;hb=HEAD
>>
>> Long story short:
>> 1. don't use scp -O
>> 2. if you use openssh-sftp-server (scp without -O) then make sure that
>> you transfer the image as either firmware.bin, sysupgrade.bin or sysupgrade.img
>> 3. if you just use plain `ssh` in a pipe (example) then you get full access so
>> that is the most flexible way to use ssh (and you dont need
>> openssh-sftp-server for it either).
>> 4. you can also use sysupgrade online if you have a local webserver:
>>
>> root at OpenWrt:~# getenforce && sysupgrade -v --test
>> http://192.168.1.192/~kcinimod/stuff/openwrt-ipq40xx-generic-linksys_mr8300-squashfs-sysupgrade.bin
>> Enforcing
>> Downloading 'http://192.168.1.192/~kcinimod/stuff/openwrt-ipq40xx-generic-linksys_mr8300-squashfs-sysupgrade.bin'
>> Connecting to 192.168.1.192:80
>> Writing to '/tmp/sysupgrade.img'
>> /tmp/sysupgrade.img 100% |*******************************| 13111k 0:00:00 ETA
>> Download completed (13426016 bytes)
>> root at OpenWrt:~# echo $?
>> 0
>>
>> Yes, quite a bit to digest any I will consider supporting firmware
>> images with random names but eventually it is still fragile when people
>> try to use scp -O ...
>>
>>>
>>> [ 74.345700] audit: type=1400 audit(1736811834.460:6): avc: denied
>>> { read write } for pid=2854 comm="fwtool"
>>> name="openwrt-armsr-armv8-generic-squashfs-combined.img.gz"
>>> dev="tmpfs" ino=93 scontext=sys.id:sys.role:fwtool.subj
>>> tcontext=sys.id:sys.role:ssh.server.hostkey.file tclass=file
>>> permissive=1
>>> [ 74.347589] audit: type=1400 audit(1736811834.460:7): avc: denied
>>> { open } for pid=2854 comm="fwtool"
>>> path="/tmp/openwrt-armsr-armv8-generic-squashfs-combined.img.gz"
>>> dev="tmpfs" ino=93 scontext=sys.id:sys.role:fwtool.subj
>>> tcontext=sys.id:sys.role:ssh.server.hostkey.file tclass=file
>>> permissive=1
>>> [ 74.349106] audit: type=1400 audit(1736811834.460:8): avc: denied
>>> { ioctl } for pid=2854 comm="fwtool"
>>> path="/tmp/openwrt-armsr-armv8-generic-squashfs-combined.img.gz"
>>> dev="tmpfs" ino=93 ioctlcmd=0x5413
>>> scontext=sys.id:sys.role:fwtool.subj
>>> tcontext=sys.id:sys.role:ssh.server.hostkey.file tclass=file
>>> permissive=1
>>> [ 74.770422] audit: type=1400 audit(1736811834.890:9): avc: denied
>>> { read } for pid=2864 comm="cat" name="cmdline" dev="proc"
>>> ino=4026531972 scontext=sys.id:sys.role:validatefirmwareimage.subj
>>> tcontext=sys.id:sys.role:cmdline.procfile tclass=file permissive=1
>>> [ 74.771728] audit: type=1400 audit(1736811834.890:10): avc: denied
>>> { open } for pid=2864 comm="cat" path="/proc/cmdline" dev="proc"
>>> ino=4026531972 scontext=sys.id:sys.role:validatefirmwareimage.subj
>>> tcontext=sys.id:sys.role:cmdline.procfile tclass=file permissive=1
>>> [ 74.800695] audit: type=1400 audit(1736811834.920:11): avc: denied
>>> { read } for pid=2865 comm="find" name="/" dev="tmpfs" ino=1
>>> scontext=sys.id:sys.role:validatefirmwareimage.subj
>>> tcontext=sys.id:sys.role:tmp.fs tclass=dir permissive=1
>>> [ 74.801449] audit: type=1400 audit(1736811834.920:12): avc: denied
>>> { open } for pid=2865 comm="find" path="/dev" dev="tmpfs" ino=1
>>> scontext=sys.id:sys.role:validatefirmwareimage.subj
>>> tcontext=sys.id:sys.role:tmp.fs tclass=dir permissive=1
>>> [ 74.807108] audit: type=1400 audit(1736811834.930:13): avc: denied
>>> { getattr } for pid=2865 comm="find" path="/dev/pts" dev="devpts"
>>> ino=1 scontext=sys.id:sys.role:validatefirmwareimage.subj
>>> tcontext=sys.id:sys.role:devpts.fs tclass=dir permissive=1
>>> [ 74.807988] audit: type=1400 audit(1736811834.930:14): avc: denied
>>> { read } for pid=2865 comm="find" name="/" dev="devpts" ino=1
>>> scontext=sys.id:sys.role:validatefirmwareimage.subj
>>> tcontext=sys.id:sys.role:devpts.fs tclass=dir permissive=1
>>> [ 74.808726] audit: type=1400 audit(1736811834.930:15): avc: denied
>>> { open } for pid=2865 comm="find" path="/dev/pts" dev="devpts" ino=1
>>> scontext=sys.id:sys.role:validatefirmwareimage.subj
>>> tcontext=sys.id:sys.role:devpts.fs tclass=dir permissive=1
>>> [ 80.140951] kauditd_printk_skb: 35 callbacks suppressed
>>> [ 80.140985] audit: type=1400 audit(1736811840.260:51): avc: denied
>>> { remove_name } for pid=3459 comm="rm" name="image.bs" dev="tmpfs"
>>> ino=96 scontext=sys.id:sys.role:validatefirmwareimage.subj
>>> tcontext=sys.id:sys.role:tmp.fs tclass=dir permissive=1
>>> [ 80.141666] audit: type=1400 audit(1736811840.260:52): avc: denied
>>> { unlink } for pid=3459 comm="rm" name="image.bs" dev="tmpfs" ino=96
>>> scontext=sys.id:sys.role:validatefirmwareimage.subj
>>> tcontext=sys.id:sys.role:tmp.fs tclass=file permissive=1
>>> [ 87.255570] audit: type=1400 audit(1736811847.370:53): avc: denied
>>> { getattr } for pid=3955 comm="find" path="/dev/hwrng" dev="tmpfs"
>>> ino=14 scontext=sys.id:sys.role:validatefirmwareimage.subj
>>> tcontext=sys.id:sys.role:hwrng.nodedev tclass=chr_file permissive=1
>>
>> I will look into adding rules for some of these validate-firmware-image
>> related events. Not sure what is happening there with "image.bs" ...
Looks like I will need to look into this (open up another can of worms):
https://github.com/openwrt/openwrt/blob/main/target/linux/armsr/base-files/lib/upgrade/platform.sh
>>
>> Thanks
>>
>>>
>>> This is all done on a fresh openwrt checkout, I added your selinux
>>> updates and build the image with this config:
>>>
>>> CONFIG_TARGET_armsr=y
>>> CONFIG_TARGET_armsr_armv8=y
>>> CONFIG_TARGET_armsr_armv8_DEVICE_generic=y
>>> CONFIG_PACKAGE_qemu-ga=y
>>> CONFIG_SELINUX=y
>>>
>>> I can send you the compressed image file, if you want to try it
>>> yourself with qemu/virt-manager.
>>
>> No thanks. All the events you pasted above are either normal rough edges
>> or issues that I am aware of but that are only documented in my
>> policy/repository. Eventually I am going to write a wiki page that
>> summarizes all the "gotches".
>>
>> Thanks!
>>
>>>
>>> Regards,
>>> Stefan Hellermann
>>>
>>>
>>> Am 13.01.25 um 18:52 schrieb Dominick Grift:
>>>> Dominick Grift <dominick.grift at defensec.nl> writes:
>>>>
>>>>> Dominick Grift <dominick.grift at defensec.nl> writes:
>>>>>
>>>>>> Hi, Thank you for feedback. Comments inline below:
>>>>>>
>>>>>> Stefan Hellermann <stefan at the2masters.de> writes:
>>>>>>
>>>>> <snip>
>>>>>
>>>>>>> audit(1736704702.290:4): avc: denied { associate } for pid=1010
>>>>>>> comm="mv" name="sysupgrade.tgz" scontext=sys.id:sys.role:dos.fs
>>>>>>> tcontext=sys.id:sys.role:xattr.fs tclass=filesystem permissive=1
>>>>>> This is caused by mv'ing the file from a fat filesystem (fat does not
>>>>>> support extended attributes) to an extended attribute file system. When
>>>>>> you mv a file you also mv its associated context with it.
>>>>>>
>>>>>> This should not be allowed. Instead you should use cp. mv does not make
>>>>>> much sense anyway cross filesystem.
>>>>>>
>>>>> This bothered me so I would like to explain why I object to this.
>>>>>
>>>>> mv and cp are more complicated than some think. I see this all the time
>>>>> where people for example use `cp -a` without realizing the consequences.
>>>>>
>>>>> But regardless of this, coreutils has extensive support for SELinux and
>>>>> `mv -Z` would have addressed the above challenge. The issue is that
>>>>> busybox' `mv` does not support -Z and so eventually I will have to draw
>>>>> the line somewhere anyway. This seems like a good place to start.
>>>>>
>>>>>>> Sun Jan 12 17:58:25 2025 user.warn kernel: urandom-seed: Seed file not
>>>>>>> found (/etc/urandom.seed)
>>>>>>> Sun Jan 12 17:58:25 2025 user.info kernel: procd: - early -
>>>>>>> Sun Jan 12 17:58:25 2025 kern.notice kernel: audit: type=1400
>>>>>>> audit(1736704702.590:5): avc: denied { write } for pid=1166
>>>>>>> comm="mkdir" name="/" dev="tmpfs" ino=1
>>>>>>> scontext=sys.id:sys.role:hotplug.call.subj
>>>>>>> tcontext=sys.id:sys.role:tmp.fs tclass=dir permissive=1
>>>>>>> Sun Jan 12 17:58:25 2025 kern.notice kernel: audit: type=1400
>>>>>>> audit(1736704702.590:6): avc: denied { add_name } for pid=1166
>>>>>>> comm="mkdir" name="virtio-ports"
>>>>>>> scontext=sys.id:sys.role:hotplug.call.subj
>>>>>>> tcontext=sys.id:sys.role:tmp.fs tclass=dir permissive=1
>>>>>>> Sun Jan 12 17:58:25 2025 kern.notice kernel: audit: type=1400
>>>>>>> audit(1736704702.590:7): avc: denied { create } for pid=1166
>>>>>>> comm="mkdir" name="virtio-ports"
>>>>>>> scontext=sys.id:sys.role:hotplug.call.subj
>>>>>>> tcontext=sys.id:sys.role:tmp.fs tclass=dir permissive=1
>>>>>>> Sun Jan 12 17:58:25 2025 kern.notice kernel: audit: type=1400
>>>>>>> audit(1736704702.590:8): avc: denied { create } for pid=1167
>>>>>>> comm="ln" name="org.qemu.guest_agent.0"
>>>>>>> scontext=sys.id:sys.role:hotplug.call.subj
>>>>>>> tcontext=sys.id:sys.role:tmp.fs tclass=lnk_file permissive=1
>>>>>>> Sun Jan 12 17:58:25 2025 user.info kernel: procd: - ubus -
>>>>>>> Sun Jan 12 17:58:25 2025 user.info kernel: procd: - init -
>>>> I added support for this. We'll see where this leads. I might end up
>>>> reverting it later.
>>>>
>>>> https://git.defensec.nl/?p=selinux-policy.git;a=commitdiff;h=32c0cc897f679b6d2b204bc2935d9de3b7006944
>>>>
>>>>>> This seems like an 'exotic hotplug script'. I have an accomodation for
>>>>>> this. see if this comment helps:
>>>>>> https://git.defensec.nl/?p=selinux-policy.git;a=blob;f=src/agent/sysagent/hotplugsysagent.cil;h=3987b8540ae537d174a74cceb2c89ce26ef3c813;hb=HEAD#l115
>>>>> We'll have to see how this will work out practically. I am open to
>>>>> suggestions for alternative approaches but this seems like a fair
>>>>> approach.
>>>>>
>>>>> There are also challenges here. For example in the above event, the
>>>>> script is trying to create a dir and symlink in /dev. In OpenWrt there
>>>>> is no (easy) way to make a distinction between devtmpfs and and a common
>>>>> tmpfs. If I we're to allow this then that would later potentially
>>>>> present challenges when another script wants to create a dir or symlink in /tmp.
>>>>>
>>>>> Again, eventually I would have to draw the line somewhere as to what
>>>>> should be allowed by default and what is to be considered exotic. This
>>>>> looks like a good place.
>>>>>
>>>>> Just trying to explain some of the rationale because I am open to better
>>>>> alternatives. I just don't see any.
>>>
--
gpg --locate-keys dominick.grift at defensec.nl (wkd)
Key fingerprint = FCD2 3660 5D6B 9D27 7FC6 E0FF DA7E 521F 10F6 4098
Dominick Grift
Mastodon: @kcinimod at defensec.nl
More information about the openwrt-devel
mailing list