udev- scanning usb drive with clamscan

Hello,

my intention is to scan every usb drive that is plugged into my computer by clamscan. To achieve this I made an udev rules that contains the following line

/etc/udev/rules.d/99-scan-UsbStorage.rules:


KERNEL=="sd*",RUN+="~/-udevscripts/clamscan.sh" 

~/-udevscripts/clamscan.sh:


#!/bin/sh

file="~/.udevscripts/clamscan.log"

zenity --info --width=180 --title="ClamAV" --text="Bitte warten, es wird kurz auf Viren überprüft" --display=:0.0 &

if  -f $file ]; then
        rm -f $file
fi

/usr/bin/clamscan -r -i /run/media > ~/.udevscripts/clamscan.log
        
zenity --text-info --title="ClamAV" --filename="/home/saschawork/.udevscripts/clamscan.log" --display=:0.0 &

exit 0


But somehow it doesn’t work. When I manually run the script it runs pretty smooth. I want to make the usb drive describtion as general as possible to cover even partitioned drives from sdb1 to sdd8.

I based the udev-description of the drive on the following information

“sudo udevadm info -a -p /sys/block/sdb/sdb1”:


(...)

looking at device '/block/sdb/sdb1':
    KERNEL=="sdb1"
    SUBSYSTEM=="block"
    DRIVER==""
    ATTR{ro}=="0"
    ATTR{size}=="31504384"
    ATTR{stat}=="     405    15465    18830     1600       47        2       49     1070        0     1079     2670"
    ATTR{partition}=="1"
    ATTR{start}=="2048"
    ATTR{discard_alignment}=="0"
    ATTR{alignment_offset}=="0"
    ATTR{inflight}=="       0        0"

(...)

When I want to test the sdb1 action with root, I get the following lines

“sudo udevadm test /sys/block/sdb/sdb1”:

calling: test
version 210
This program is for debugging only, it does not run any program
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.

load module index
timestamp of '/usr/lib/systemd/network' changed
Parsed configuration file /usr/lib/systemd/network/99-default.link
Created link configuration context.
timestamp of '/etc/udev/rules.d' changed
read rules file: /usr/lib/udev/rules.d/10-dm.rules
read rules file: /usr/lib/udev/rules.d/11-dm-lvm.rules
read rules file: /usr/lib/udev/rules.d/11-dm-mpath.rules
read rules file: /usr/lib/udev/rules.d/13-dm-disk.rules
read rules file: /usr/lib/udev/rules.d/40-libgphoto2.rules
read rules file: /usr/lib/udev/rules.d/40-usb-media-players.rules
read rules file: /usr/lib/udev/rules.d/40-usb_modeswitch.rules
read rules file: /usr/lib/udev/rules.d/42-hd-audio-pm.rules
read rules file: /usr/lib/udev/rules.d/42-usb-hid-pm.rules
read rules file: /usr/lib/udev/rules.d/50-udev-default.rules
read rules file: /usr/lib/udev/rules.d/51-android.rules
read rules file: /usr/lib/udev/rules.d/51-lirc.rules
read rules file: /etc/udev/rules.d/55-libsane.rules
read rules file: /usr/lib/udev/rules.d/55-scsi-sg3_id.rules
read rules file: /usr/lib/udev/rules.d/56-idedma.rules
read rules file: /usr/lib/udev/rules.d/56-multipath.rules
read rules file: /etc/udev/rules.d/56-sane-backends-autoconfig.rules
read rules file: /usr/lib/udev/rules.d/58-scsi-sg3_symlink.rules
read rules file: /usr/lib/udev/rules.d/60-cdrom_id.rules
read rules file: /usr/lib/udev/rules.d/60-drm.rules
read rules file: /usr/lib/udev/rules.d/60-keyboard.rules
read rules file: /usr/lib/udev/rules.d/60-pcmcia.rules
read rules file: /usr/lib/udev/rules.d/60-persistent-alsa.rules
read rules file: /usr/lib/udev/rules.d/60-persistent-input.rules
read rules file: /usr/lib/udev/rules.d/60-persistent-serial.rules
read rules file: /usr/lib/udev/rules.d/60-persistent-storage-tape.rules
read rules file: /usr/lib/udev/rules.d/60-persistent-storage.rules
read rules file: /usr/lib/udev/rules.d/60-persistent-v4l.rules
read rules file: /usr/lib/udev/rules.d/60-ssd-scheduler.rules
read rules file: /etc/udev/rules.d/60-vboxdrv.rules
read rules file: /usr/lib/udev/rules.d/60-vboxguest.rules
read rules file: /usr/lib/udev/rules.d/61-accelerometer.rules
read rules file: /usr/lib/udev/rules.d/63-md-raid-arrays.rules
read rules file: /usr/lib/udev/rules.d/64-btrfs.rules
read rules file: /usr/lib/udev/rules.d/64-md-raid-assembly.rules
read rules file: /usr/lib/udev/rules.d/65-wacom.rules
read rules file: /usr/lib/udev/rules.d/66-kpartx.rules
read rules file: /usr/lib/udev/rules.d/67-kpartx-compat.rules
read rules file: /usr/lib/udev/rules.d/69-dm-lvm-metad.rules
read rules file: /usr/lib/udev/rules.d/69-libmtp.rules
read rules file: /usr/lib/udev/rules.d/69-xorg-vmmouse.rules
skip empty file: /etc/udev/rules.d/70-persistent-net.rules
read rules file: /usr/lib/udev/rules.d/70-power-switch.rules
read rules file: /usr/lib/udev/rules.d/70-printers.rules
read rules file: /usr/lib/udev/rules.d/70-uaccess.rules
read rules file: /usr/lib/udev/rules.d/71-seat.rules
read rules file: /usr/lib/udev/rules.d/73-seat-late.rules
read rules file: /usr/lib/udev/rules.d/73-seat-numlock.rules
read rules file: /usr/lib/udev/rules.d/75-net-description.rules
read rules file: /usr/lib/udev/rules.d/75-persistent-net-generator.rules
read rules file: /usr/lib/udev/rules.d/75-probe_mtd.rules
read rules file: /usr/lib/udev/rules.d/75-tty-description.rules
read rules file: /usr/lib/udev/rules.d/76-net-sriov-names.rules
read rules file: /usr/lib/udev/rules.d/77-mm-ericsson-mbm.rules
read rules file: /usr/lib/udev/rules.d/77-mm-huawei-net-port-types.rules
read rules file: /usr/lib/udev/rules.d/77-mm-longcheer-port-types.rules
read rules file: /usr/lib/udev/rules.d/77-mm-nokia-port-types.rules
read rules file: /usr/lib/udev/rules.d/77-mm-pcmcia-device-blacklist.rules
read rules file: /usr/lib/udev/rules.d/77-mm-platform-serial-whitelist.rules
read rules file: /usr/lib/udev/rules.d/77-mm-simtech-port-types.rules
read rules file: /usr/lib/udev/rules.d/77-mm-usb-device-blacklist.rules
read rules file: /usr/lib/udev/rules.d/77-mm-usb-serial-adapters-greylist.rules
read rules file: /usr/lib/udev/rules.d/77-mm-x22x-port-types.rules
read rules file: /usr/lib/udev/rules.d/77-mm-zte-port-types.rules
read rules file: /usr/lib/udev/rules.d/77-nm-olpc-mesh.rules
read rules file: /usr/lib/udev/rules.d/78-sound-card.rules
read rules file: /usr/lib/udev/rules.d/80-drivers.rules
read rules file: /usr/lib/udev/rules.d/80-hotplug-cpu-mem.rules
read rules file: /usr/lib/udev/rules.d/80-mm-candidate.rules
read rules file: /usr/lib/udev/rules.d/80-net-setup-link.rules
read rules file: /usr/lib/udev/rules.d/80-udisks2.rules
read rules file: /usr/lib/udev/rules.d/85-regulatory.rules
read rules file: /usr/lib/udev/rules.d/90-alsa-restore.rules
read rules file: /usr/lib/udev/rules.d/90-haveged.rules
read rules file: /usr/lib/udev/rules.d/90-libgpod.rules
read rules file: /usr/lib/udev/rules.d/90-mcelog.rules
read rules file: /usr/lib/udev/rules.d/90-pulseaudio.rules
read rules file: /usr/lib/udev/rules.d/90-vconsole.rules
read rules file: /usr/lib/udev/rules.d/95-dm-notify.rules
read rules file: /usr/lib/udev/rules.d/95-udev-late.rules
read rules file: /usr/lib/udev/rules.d/95-upower-csr.rules
read rules file: /usr/lib/udev/rules.d/95-upower-hid.rules
read rules file: /usr/lib/udev/rules.d/95-upower-wup.rules
read rules file: /usr/lib/udev/rules.d/97-hid2hci.rules
read rules file: /usr/lib/udev/rules.d/99-iwlwifi-led.rules
read rules file: /etc/udev/rules.d/99-scan-UsbStorage.rules
read rules file: /usr/lib/udev/rules.d/99-systemd.rules
rules contain 393216 bytes tokens (32768 * 12 bytes), 38164 bytes strings
25073 strings (213127 bytes), 21735 de-duplicated (178302 bytes), 3339 trie nodes used
GROUP 6 /usr/lib/udev/rules.d/50-udev-default.rules:48
IMPORT '/usr/bin/sg_inq --export /dev/sdb' /usr/lib/udev/rules.d/55-scsi-sg3_id.rules:10
starting '/usr/bin/sg_inq --export /dev/sdb'
'/usr/bin/sg_inq --export /dev/sdb'(out) 'SCSI_TPGS=3'
'/usr/bin/sg_inq --export /dev/sdb'(out) 'SCSI_TYPE=disk'
'/usr/bin/sg_inq --export /dev/sdb'(out) 'SCSI_VENDOR=Verbatim'
'/usr/bin/sg_inq --export /dev/sdb'(out) 'SCSI_VENDOR_ENC=Verbatim'
'/usr/bin/sg_inq --export /dev/sdb'(out) 'SCSI_MODEL=STORE_N_GO'
'/usr/bin/sg_inq --export /dev/sdb'(out) 'SCSI_MODEL_ENC=STORE\x20N\x20GO\x20\x20\x20\x20\x20\x20'
'/usr/bin/sg_inq --export /dev/sdb'(out) 'SCSI_REVISION=1100'
'/usr/bin/sg_inq --export /dev/sdb' [11164] exit with return code 0
IMPORT '/usr/bin/sg_inq --export --page=sn /dev/sdb' /usr/lib/udev/rules.d/55-scsi-sg3_id.rules:19
starting '/usr/bin/sg_inq --export --page=sn /dev/sdb'
'/usr/bin/sg_inq --export --page=sn /dev/sdb'(out) 'SCSI_IDENT_SERIAL=12250000001425A2'
'/usr/bin/sg_inq --export --page=sn /dev/sdb' [11165] exit with return code 0
IMPORT '/usr/bin/sg_inq --export --page=di /dev/sdb' /usr/lib/udev/rules.d/55-scsi-sg3_id.rules:21
starting '/usr/bin/sg_inq --export --page=di /dev/sdb'
'/usr/bin/sg_inq --export --page=di /dev/sdb'(out) 'SCSI_IDENT_LUN_EUI64=0001020000060804'
'/usr/bin/sg_inq --export --page=di /dev/sdb'(out) 'SCSI_IDENT_LUN_NAA=2020030102060804'
'/usr/bin/sg_inq --export --page=di /dev/sdb' [11167] exit with return code 0
PROGRAM '/sbin/multipath -i -u sdb' /usr/lib/udev/rules.d/56-multipath.rules:12
starting '/sbin/multipath -i -u sdb'
'/sbin/multipath -i -u sdb'(out) 'Oct 21 12:53:14 | DM multipath kernel driver not loaded'
'/sbin/multipath -i -u sdb' [11168] exit with return code 1
LINK 'disk/by-id/scsi-SVerbatim_STORE_N_GO_12250000001425A2' /usr/lib/udev/rules.d/58-scsi-sg3_symlink.rules:12
LINK 'disk/by-id/scsi-32020030102060804' /usr/lib/udev/rules.d/58-scsi-sg3_symlink.rules:15
LINK 'disk/by-id/scsi-20001020000060804' /usr/lib/udev/rules.d/58-scsi-sg3_symlink.rules:18
LINK 'disk/by-id/scsi-32020030102060804' /usr/lib/udev/rules.d/60-persistent-storage.rules:42
IMPORT builtin 'path_id' /usr/lib/udev/rules.d/60-persistent-storage.rules:63
LINK 'disk/by-path/pci-0000:00:1d.0-usb-0:1.2:1.0-scsi-0:0:0:0' /usr/lib/udev/rules.d/60-persistent-storage.rules:64
IMPORT builtin 'blkid' /usr/lib/udev/rules.d/60-persistent-storage.rules:81
probe /dev/sdb raid offset=0
LINK 'disk/by-uuid/2014-10-27-15-28-42-00' /usr/lib/udev/rules.d/60-persistent-storage.rules:87
LINK 'disk/by-label/openSUSE\x2013.2\x20KDE\x20Live' /usr/lib/udev/rules.d/60-persistent-storage.rules:88
LINK 'disk/by-id/wwn-0x2020030102060804' /usr/lib/udev/rules.d/60-persistent-storage.rules:91
RUN '#!/bin/sh ~/-udevscripts/clamscan.sh' /etc/udev/rules.d/99-scan-UsbStorage.rules:1
handling device node '/dev/sdb', devnum=b8:16, mode=0660, uid=0, gid=6
preserve permissions /dev/sdb, 060660, uid=0, gid=6
preserve already existing symlink '/dev/block/8:16' to '../sdb'
found 'b8:16' claiming '/run/udev/links/\x2fdisk\x2fby-id\x2fscsi-20001020000060804'
creating link '/dev/disk/by-id/scsi-20001020000060804' to '/dev/sdb'
preserve already existing symlink '/dev/disk/by-id/scsi-20001020000060804' to '../../sdb'
found 'b8:16' claiming '/run/udev/links/\x2fdisk\x2fby-id\x2fscsi-32020030102060804'
creating link '/dev/disk/by-id/scsi-32020030102060804' to '/dev/sdb'
preserve already existing symlink '/dev/disk/by-id/scsi-32020030102060804' to '../../sdb'
found 'b8:16' claiming '/run/udev/links/\x2fdisk\x2fby-id\x2fscsi-SVerbatim_STORE_N_GO_12250000001425A2'
creating link '/dev/disk/by-id/scsi-SVerbatim_STORE_N_GO_12250000001425A2' to '/dev/sdb'
preserve already existing symlink '/dev/disk/by-id/scsi-SVerbatim_STORE_N_GO_12250000001425A2' to '../../sdb'
found 'b8:16' claiming '/run/udev/links/\x2fdisk\x2fby-id\x2fwwn-0x2020030102060804'
creating link '/dev/disk/by-id/wwn-0x2020030102060804' to '/dev/sdb'
preserve already existing symlink '/dev/disk/by-id/wwn-0x2020030102060804' to '../../sdb'
found 'b8:16' claiming '/run/udev/links/\x2fdisk\x2fby-label\x2fopenSUSE\x5cx2013.2\x5cx20KDE\x5cx20Live'
creating link '/dev/disk/by-label/openSUSE\x2013.2\x20KDE\x20Live' to '/dev/sdb'
preserve already existing symlink '/dev/disk/by-label/openSUSE\x2013.2\x20KDE\x20Live' to '../../sdb'
found 'b8:16' claiming '/run/udev/links/\x2fdisk\x2fby-path\x2fpci-0000:00:1d.0-usb-0:1.2:1.0-scsi-0:0:0:0'
creating link '/dev/disk/by-path/pci-0000:00:1d.0-usb-0:1.2:1.0-scsi-0:0:0:0' to '/dev/sdb'
preserve already existing symlink '/dev/disk/by-path/pci-0000:00:1d.0-usb-0:1.2:1.0-scsi-0:0:0:0' to '../../sdb'
found 'b8:16' claiming '/run/udev/links/\x2fdisk\x2fby-uuid\x2f2014-10-27-15-28-42-00'
creating link '/dev/disk/by-uuid/2014-10-27-15-28-42-00' to '/dev/sdb'
preserve already existing symlink '/dev/disk/by-uuid/2014-10-27-15-28-42-00' to '../../sdb'
ACTION=add
DEVLINKS=/dev/disk/by-id/scsi-20001020000060804 /dev/disk/by-id/scsi-32020030102060804 /dev/disk/by-id/scsi-SVerbatim_STORE_N_GO_12250000001425A2 /dev/disk/by-id/wwn-0x2020030102060804 /dev/disk/by-label/openSUSE\x2013.2\x20KDE\x20Live /dev/disk/by-path/pci-0000:00:1d.0-usb-0:1.2:1.0-scsi-0:0:0:0 /dev/disk/by-uuid/2014-10-27-15-28-42-00
DEVNAME=/dev/sdb
DEVPATH=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host6/target6:0:0/6:0:0:0/block/sdb
DEVTYPE=disk
ID_BUS=scsi
ID_FS_APPLICATION_ID=0xe28d2fda
ID_FS_BOOT_SYSTEM_ID=EL\x20TORITO\x20SPECIFICATION
ID_FS_LABEL=openSUSE_13.2_KDE_Live
ID_FS_LABEL_ENC=openSUSE\x2013.2\x20KDE\x20Live
ID_FS_PUBLISHER_ID=SUSE\x20LINUX\x20GmbH
ID_FS_SYSTEM_ID=LINUX
ID_FS_TYPE=udf
ID_FS_USAGE=filesystem
ID_FS_UUID=2014-10-27-15-28-42-00
ID_FS_UUID_ENC=2014-10-27-15-28-42-00
ID_FS_VERSION=Joliet Extension
ID_MODEL=STORE_N_GO
ID_MODEL_ENC=STORE\x20N\x20GO\x20\x20\x20\x20\x20\x20
ID_PART_TABLE_TYPE=dos
ID_PART_TABLE_UUID=e28d2fda
ID_PATH=pci-0000:00:1d.0-usb-0:1.2:1.0-scsi-0:0:0:0
ID_PATH_TAG=pci-0000_00_1d_0-usb-0_1_2_1_0-scsi-0_0_0_0
ID_REVISION=1100
ID_SCSI=1
ID_SERIAL=32020030102060804
ID_SERIAL_SHORT=2020030102060804
ID_TYPE=disk
ID_VENDOR=Verbatim
ID_VENDOR_ENC=Verbatim
ID_WWN=0x2020030102060804
ID_WWN_WITH_EXTENSION=0x2020030102060804
MAJOR=8
MINOR=16
MPATH_SBIN_PATH=/sbin
SCSI_IDENT_LUN_EUI64=0001020000060804
SCSI_IDENT_LUN_NAA=2020030102060804
SCSI_IDENT_SERIAL=12250000001425A2
SCSI_MODEL=STORE_N_GO
SCSI_MODEL_ENC=STORE\x20N\x20GO\x20\x20\x20\x20\x20\x20
SCSI_REVISION=1100
SCSI_TPGS=3
SCSI_TYPE=disk
SCSI_VENDOR=Verbatim
SCSI_VENDOR_ENC=Verbatim
SUBSYSTEM=block
TAGS=:systemd:
USEC_INITIALIZED=28101423
run: '#!/bin/sh ~/-udevscripts/clamscan.sh'
unload module index
Unloaded link configuration context.

running udevadm test without root causes the output to claim not being able to have permission for sdb1 (“error opening file: /dev/sdb: Permission denied’”).

Do you have any idea what I could improve? I am thankful for any help.

These lines were inspired from the following sites:
http://www.linuxquestions.org/questions/linux-security-4/run-clamav-on-mount-of-flashdrive-797286/
http://reactivated.net/writing_udev_rules.html

if  -f $file ]; then
        rm -f $file
fi

/usr/bin/clamscan -r -i /run/media > ~/.udevscripts/clamscan.log

Sorry, this has nothing to do with your posted problem, but

  • in the last line you should replace the last word with: $file imho
  • the first three lines here are superfluous as the > redirection does create the file new regardless of it’s previous existance.

And the following may have something to do with your problem.

I am not that good with udev rules, but I assume they are run by “the system” (probably the process owner being root). Thus the ~ you use in some pathes here is probably not what you think it might be. In these sorts of scripts (same with cron) better specyfy the complete pathes and not ~ or $HOME, etc.

Sorry, it goes with small steps.

I went for some shopping, but your case came back to my mind. And I now assume that you do not quite understand who is/should be the process owner.

E.g. when you configure this

KERNEL=="sd*",RUN+="~/-udevscripts/clamscan.sh"

what you think the ~ expansion will evolve in?

The udevd that interpretes this is NOT run by any loged in user. Thus there is no $HOME defined in it’s environment, Not even the home directory of root (which is the user running udevd) is defined in $HOME. Thus ~ expansion will lead into nothing.

I have no idea which user’s home dirctory you thought it would expand into, but while this is run as root, the script should NOT be in a place not owned by root. And it should not be writeble by the world. Else huge security vulnerabilities will be present.

Thus for a place to put such a script, you could e.g. take

/root/bin

which is in root’s home directory. Another choice could be

/usr/local/bin

And the permissions of the script should be

-rwxr--r--  1 root root  146 Jan 18  2014 <thescript>j*

at the most. But you could remove the others read permission (and even the group read permission) when wanted.

Please try to understand that you are designing some system action that has nothing to do with any of “normal” users on your system.

Hello,

thank you for your answers. Indeed it was as simple as substituting “~/” with “/home/USERNAME” to make it run. I am aware that I am a Linux Newbie, but that’s how it works. Starting something, screwing things up, learn, trying.
Your security concerns are logical to me and this actually explains why in the first of my sources it was placed in the /etc/udev folder. But since I am not good at shell scripting I didn’t want to write the whole script again, when I upgrade to openSUSE Leap. That’s why I saved it in the home directory.

So I ended up with

/etc/udev/rules.d/99-scan-UsbStorage.rules:


KERNEL=="sd*[1-5]",ACTION=="add",RUN+="sudo /etc/udev/scripts/clamscan.sh" 

since it started the script several times, when adding an usb stick. The script now ended up being

/etc/udev/scripts/clamscan.sh:


#!/bin/sh

zenity --info --width=180 --title="ClamAV" --text="Bitte warten, es wird kurz auf Viren überprüft" --display=:0.0 &

/usr/bin/clamscan -r -i /run/media > "/tmp/clamscan.log"
        
zenity --text-info --title="ClamAV" --filename="/tmp/clamscan.log" --display=:0.0 &

exit 0

Now I got the problem, that the udev rule starts the script but the first zenity window is not displayed and it somehow scans merely 2 directories and not one of the 2000 files being on my usb stick. Again starting the script manually make it run properly.

Thanks again!

I think you are missing a few more points and I do not realy know where to start.

The sudo in the udev rule is nonsense. That sudo will change to root, but the processes there are already run by root.

I have a lot to guess here, because this seems to be an old problem of asking questions: you ask for help with a step, but you fail to explain the goal. What do you want? Maybe the step you ask now help for is not even a step on the path you should walk to reach your goal.

I do not realy know what that clamscan is doing, but what I understand from what I see is that when the system signals an USB mass-storage device being connected, it starts the script, which in turn runs that program clamscan with the directory /run/media as a parameter. Now this directory hasn’t anything to do with the device just connected, thus I do not see the logic behind this.

I also do not know the program zenity, but it seems that it should open a window on display localhost:0.0 (the default display). But this assumes:

  1. that there is a user loged in on that that display, but you do not test that;
  2. that the user of the xsession on that display (if there is one) opened the display for others (at least localhost root) to allow a window opened (from outside the session). Did you inform those potential users about that (with xhost + or the like)?

I have a strong idea that you do not understand all the consequences of using a multi-user operating system.

BTW, putting the scipt in /etc/udev/scripts/ is wholy your idea. It is none of the places I recommended.

Yes the “sudo” in my udev rule is complete nonsense, actually this was an artefact from one of my many desperate tryings. I tried every of your suggestions where to put the clamscan.sh script. But every option resulted in the same problems. It it now in /root/bin and that’s where it stays as you suggested.

Actually I explained my intentions in the first sentence of the opening post of this thread. There I said:

Hello,

my intention is to scan every usb drive that is plugged into my computer by clamscan. To achieve this I made an udev rule (…)

Since I said “clamscan” instead of “Clam Anti VIrus” this might have been confusing.
ClamAV is an anti virus program that scans files by the command “sudo clamscan -option /directory” and since it is the only one I know for Linux is assumed that it would be commonly known. I am sorry for that.

Clam AntiVirus (ClamAV) is a free and open-source, cross-platform antivirus software tool-kit able to detect many types of malicious software, including viruses. One of its main uses is on mail servers as a server-side email virus scanner. The application was developed for Unix and has third party versions available for AIX, BSD, HP-UX, Linux, OS X, OpenVMS, OSF (Tru64) and Solaris. As of version 0.97.5, ClamAV builds and runs on Microsoft Windows.[1]](ClamAV - Wikipedia)[2]](ClamAV - Wikipedia) Both ClamAV and its updates are made available free of charge.

(Source: ClamAV - Wikipedia)

/run/media is the mount point of my usb drives. Adding the option “-r” to “clamscan” makes clamscan scan this directory recursively, meaning every subfolder in it. The option “-i” makes it print only infected files. So the command “sudo clamscan -r -i /run/media” makes it scan every folder and file of my usb drives printing infected files it found.

Then zenity is a GUI for shell scripts, it opens windows to display messages and it can receive strings. I myself am logged on display localhost:0.0. That’s at least what I suggest since running the script manually brings up all the zenity windows I expect. Because the script in the udev rule is executed by root it could be possible that root is not allowed to open a display on my session. But that sounds unusual because I thought root has rights for everything. And why only the second window and not the first?

I understand the principles of multi user operating systems and I know that these actions are very serious interventions in the running system.

So, I assume that you assume that there are files with mails on those USB mass-storage devices. And that you want those mails scanned for known Microsoft Windows virusses.
Bit strange, but when that is what you want.

In any case, you also assume that there is a file system on the device (or on or more partitions on the device) and you assume that this/these file system(s) are mounted on mount point(s) inside /run/media. That might be the case when the user “in the seat” has acted on the popup that is shown in his/her desktop, but that is certainly NOT the case when udev is creating the device files (sdX).
In that phase, nothing of the device is mounted. Thus the files on it are unaccesable.

I assume that the test needs read-access, thus the file system(s), if present, must be mounted first, then tested, then unmouned and after that the normal steps (like signaling e.g. KDE, etc.) must resume.
Does not seem an easy thing to me. But interesting.

BTW, imo this should have been in Programming/Scripting and not in Applications.

BTW, imo this should have been in Programming/Scripting and not in Applications.

I was actually looking for such a corner here but I didn’t find one. Additionally the search tool revealed that this is de first udev thread here. Feel free to move this thread to where it belongs.

So, I assume that you assume that there are files with mails on those USB mass-storage devices. And that you want those mails scanned for known Microsoft Windows virusses.
Bit strange, but when that is what you want.

ClamAV doesn’t only work with mails, it works with every kind of file. The reason why I do this is that I work at an scientific institution with an isolated intranet run with windows. When I want to move my analysis files from the intranet to my privat notebook I have to use usb sticks. I want to make sure that I don’t distribute viruses when I use my usb stick on the intranet which is build on windows or from the intranet to privat computers (in case that somebody else was careless). And no our intranet is not checked by any antivirus software.

In any case, you also assume that there is a file system on the device (or on or more partitions on the device) and you assume that this/these file system(s) are mounted on mount point(s) inside /run/media. That might be the case when the user “in the seat” has acted on the popup that is shown in his/her desktop, but that is certainly NOT the case when udev is creating the device files (sdX).
In that phase, nothing of the device is mounted. Thus the files on it are unaccesable.

I assume that the test needs read-access, thus the file system(s), if present, must be mounted first, then tested, then unmouned and after that the normal steps (like signaling e.g. KDE, etc.) must resume.
Does not seem an easy thing to me. But interesting.

I would be totally content if the script would run after the usb drive is mounted since I think that windows (C++ ?) viruses are not able to run their code on unix systems. I could plug in my usb drive, get informed by ClamAV that I have viruses von my usb drive, desinfect it (manually) and then proceed with my work.
I agree with you that it looks like the script would be run before the file system is mounted. I ran “udevadm monitor” and plugged in a usb drive with one partition. The result was the following:


monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[2186.039153] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
KERNEL[2186.039332] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
KERNEL[2186.039624] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7 (scsi)
KERNEL[2186.039726] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/scsi_host/host7 (scsi_host)
UDEV  [2186.063923] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
UDEV  [2186.066938] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
UDEV  [2186.067592] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7 (scsi)
UDEV  [2186.068214] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/scsi_host/host7 (scsi_host)
KERNEL[2187.456581] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0 (scsi)
KERNEL[2187.456610] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0 (scsi)
KERNEL[2187.456654] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0 (scsi_disk)
KERNEL[2187.456710] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0/scsi_device/7:0:0:0 (scsi_device)
KERNEL[2187.456804] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0/scsi_generic/sg1 (scsi_generic)
KERNEL[2187.456887] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0/bsg/7:0:0:0 (bsg)
UDEV  [2187.457198] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0 (scsi)
UDEV  [2187.458153] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0 (scsi)
UDEV  [2187.458918] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0/scsi_device/7:0:0:0 (scsi_device)
UDEV  [2187.459027] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0 (scsi_disk)
UDEV  [2187.459117] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0/scsi_generic/sg1 (scsi_generic)
KERNEL[2187.459455] add      /devices/virtual/bdi/8:16 (bdi)
UDEV  [2187.459479] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0/bsg/7:0:0:0 (bsg)
UDEV  [2187.459800] add      /devices/virtual/bdi/8:16 (bdi)
KERNEL[2187.464281] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0/block/sdb (block)
KERNEL[2187.464324] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1 (block)
UDEV  [2187.544378] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0/block/sdb (block)
UDEV  [2199.621764] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1 (block)

Right now it looks like the script is run after the following line:


UDEV  [2075.412442] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host6/target6:0:0/6:0:0:0/block/sdb (block)

Maybe I should specify the rule to be run after


UDEV  [2199.621764] add       /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1  (block)

But how?

Prhrammimg and Scripting is a sub-forum of Develoment.

Aren’t you developing something :wink:

This is CLOSED for the moment and will be moved.

Moved from Hardware and open again.

We are now, slowly, getting at your goal. Because your earlier post (#6) came down to: my goal is running clamscan as I posted in my first post here. You goal is of cource NOT runnnig clamscan, clamscan it is the tool you try to use to reach our goal.

And I am fully aware that clamscan will test all files. Clamscan will probably not even know if a file is a mail. But scanning virusses on mails going to Windows system is about the only usefull thing it can do on a LInux system (and you can read that also fom the quote in your post #6 above). And even then it is only a service to the Windows system getting those mails eventualy. And those virusses are not created on your system. Thus it is completley a service to the poor Windows systems. Something that, as said, maybe the owner of a Linux mail server (or you in your paricular case) will provide to it’s poor Windows customers. (My personal idea is: let those Windows systems care for themselves).

As said, as long as you start from udev, you will always be before the file system(s) is/are mounted. udev does NOT mount anything. It s NOT where it is designed for. udev is designed to create the device files in /dev.

I see two theoretical possibilities:

  1. starting a script from udev (as you are trying), but that script then should involve first mounting, then scanning, then unmounting. And all that follows (signaling udisk > the desktop > the user > the user answer that probably leads to mounting for the user) must wait for this to complete.
  2. some action from the desktop that will include the normal “desktop mounting” to start with. This last solution (when makable) will also take account of uncertainties as: how many users (0,1, 2 or more) are loged in?

As said: not trivial, but a nice project.

udev will intentionally kill any long-running process started as part of event handling (where “long running” is in order of 1-2 minutes), so this is likely not an option here.

Hey guys,

sorry I’m not answering at the moment. There is a lot to do at work at the moment. But I tried the first suggestion of hcvv and added some lines to the /bin/root/clamscan.sh:


#!/bin/sh

zenity --info --title="ClamAV" --text="Bitte warten, es wird kurz auf Viren überprüft" --display=:0.0 &

mount -t vfat /dev/sdb1 /run/media/ClamAV
/usr/bin/clamscan -r -i /run/media/ClamAV > "/tmp/clamscan.log"
umount -t vfat /dev/sdb1 /run/media/ClamAV
        
zenity --text-info --title="ClamAV" --filename="/tmp/clamscan.log" --display=:0.0 &

exit 0

And this works with my personal usb drive. The only thing I don’t get is why it doesn’t display the first zenity window oO.
The next step is the hard step where I have to generalise my usb’s properties. The idea is something like this:


#!/bin/sh
FILESYSTEM_SDB1= Some shell command from which I get the usb file system

zenity --info --title="ClamAV" --text="Bitte warten, es wird kurz auf Viren überprüft" --display=:0.0 &

mount -t $FILESYSTEM_SDB1 /dev/sdb1 /run/media/ClamAV
/usr/bin/clamscan -r -i /run/media/ClamAV > "/tmp/clamscan.log"
umount -t $FILESYSTEM_SDB1 /dev/sdb1 /run/media/ClamAV
        
zenity --text-info --title="ClamAV" --filename="/tmp/clamscan.log" --display=:0.0 &

exit 0

And then continuing with /dev/sdc1. Also a if loop will be nessecary to avoid that the script scan every usb drive after plugging in a new one. But for this I need to dig a bit deeper into shell scripting.
Does anybody have a suggestion from which command I can get the file systems of the drives?

You indeed first have to find out which device file(s) are the new ones. You better do this correct, because I foresee problems:

  • not only when you add a second device while the first one still being checked, but also you will not be able to add any mass-storage device to your system in the future without changing your script (which you,l at that moment in time, will most probably forget);
  • it is not garanteed that there is a partition table on the device (whole disk), nor that there is only one partition (the device files created will mirror this);
  • the contents of the whole disk or of any partitition may be anything, it may even be a file system, but that is not garanteed;
  • And when there is/are one or more file systems, it is not obvious which type it is (as you already thought).

And never forget that this is a script that runs as root in the background. In other words, when it is not flawless it may easy harm your system and you will even not see it happen.

I do like people tackling these sort of problems and trying to find good solutions for them. So partitaly I do not want to discourage you. But OTH I am a bit pessimistic about this solution because it is very much beside the design goal of udev. And because of the many uncertainties you have to solve.

My pessimistic view may be nurtured by the fact that I see no reason at all to detect Windows virusses on a Linux system (unless maybe when I will be paid a resonable sum of money for delivering such a service). Let those Windows addicts care for themselves. :wink:

From a Design and Architecture perspective,

The way I look at what you’re trying to do should be broken up into discrete parts…

  • Detect when a USB device is plugged in, <if> you want to create something that might work automatically.
    I would recommend you take a look at whatever notifications are generated when a USB device is physically plugged in.

  • Mounting the USB device.
    This can get complicated because there are <many> different ways that USB devices are mounted… eg I’ll just list a few I know of

  • fstab

  • Desktop code

  • systemd mount (and nowadays there seems to be many mount services instead of only one originally)

And, there are USB storage profiles… Which try and typically do an awful job trying to apply settings and policy based on whether the USB device is internal or external storage.

The above is not trivial because <how> the USB storage is mounted will also likely determine the path and device to access the file system on the device. If you want to try to mount the device only a particular way, you may have to intercept auto mounting all the other ways.

Bottom line,
IMO this gets very complex and deep, perhaps more than a casual Developer will likely want to invest time and energy.
You may have better luck perhaps selecting one automated process, eg a specific Desktop which reliably discovers and mounts USB storage (like KDE) and then write an app specific for that Desktop.

Otherwise, you might consider writing a universal tool which someone with some technical knowledge could use by manually executing with custom parameters… This more or less is similar to how ClamAV requires the User to know how to prepare and present the target system to ClamAV.

IMO,
TSU