Closed Bug 403023 Opened 17 years ago Closed 12 years ago

Extract NSIS (windows) installers and MAR files when virus scanning

Categories

(Infrastructure & Operations :: Infrastructure: Other, task, P3)

task

Tracking

(Not tracked)

RESOLVED DUPLICATE of bug 72410

People

(Reporter: nthomas, Assigned: justdave)

References

Details

(Whiteboard: [automation][releases][simple])

Attachments

(5 files, 12 obsolete files)

1.14 KB, patch
rail
: review+
Details | Diff | Splinter Review
18.95 KB, patch
catlee
: review+
Details | Diff | Splinter Review
113 bytes, patch
bhearsum
: review+
Details | Diff | Splinter Review
766 bytes, patch
catlee
: review+
Details | Diff | Splinter Review
1.04 KB, patch
catlee
: review+
Details | Diff | Splinter Review
clamav apparently doesn't know how to un-7-zip our windows installers, if you scan for viruses on non-windows platforms. Please add scripting to do this so that we improve our coverage on the most virus prone platform.
Any idea how?
Can clamav be given a location to scan ? If so

# get files with something like: find <layer> -type f -name '*.exe'
for each <file>
 <make tmpdir>
 7z x -o<tmpdir> <file>
 <call clamav with tmpdir>
done

You can also use -so to send the output to stdout.

Hopefully old school SeaMonkey installers will also be extracted by 7z.
"old-school" seamonkey installers are not 7-zip. They're a Netscape-custom self-extractor based on zip.  Call those with "sm-install.exe -u" to extract in-place without running the installer. The resulting files will be a few executables/libraries and zip-format .xpi files which the scanner should already be able to handle.
Assignee: server-ops → justdave
ok, so basically, we have to wrap the scanning script in something that pre-extracts the files, and remembers where they came from, so if one of those files is found to be infected, we move the correct file from the tree into quarantine...  and the extracted versions have to be put somewhere outside of the tree so they don't accidently get posted in extracted form after they pass.

(In reply to comment #3)
> "old-school" seamonkey installers are not 7-zip. They're a Netscape-custom
> self-extractor based on zip.  Call those with "sm-install.exe -u" to extract
> in-place without running the installer.

So you're saying in order to extract them I have to run the code we're scanning.  Yeah, that's safe. :)
It's our own custom self-extractor, I'm sure the tool could be adapted fairly easily. The contained archives are zip-compressed and stored as individual windows "resources". Look at the EnumResourceNames() call in nsztool.c and the ExtractFilesProc callback function.

Same code appears in mozilla/xpinstall/wizard/windows/nsinstall/nsinstall.cpp, if they're not identical I'm not sure which version would be more up-to-date.
Priority: -- → P2
So I'm not generally a C programmer...  can someone write me a utility that unpacks our self-extracting installer archives? or explain how to script it if it's doable with existing linux utilities? I'm not going to trust uploaded files to actually run them.
Reassign this back to me when you get a volunteer for comment 6.
Assignee: justdave → nobody
Component: Server Operations → Server Operations: Projects
Nick says build can make sure someone gets this utility written
Component: Server Operations: Projects → Build & Release
QA Contact: justin → build
Blocks: 419978
No longer blocks: 394069
(In reply to comment #8)
> Nick says build can make sure someone gets this utility written

Hmm, I don't recall saying that. The original intent here was to handle NSIS/7zip installers, so I've filed bug 421159 for the netscape ones. Also bug 421158 for mar files.
Component: Build & Release → Release Engineering: Projects
Priority: P2 → P3
QA Contact: build → release
Assignee: nobody → server-ops
Component: Release Engineering: Projects → Server Operations
QA Contact: release → justin
Ah, yes, 7zip there's a utility for already.  No reason to wait on the Netscape stuff to do that one.
Assignee: server-ops → justdave
Blocks: 394069
Component: Server Operations → Server Operations: Projects
Changing QA Contact.
QA Contact: justin → mrz
Moving to RE in order to get the script written.
Assignee: justdave → nobody
Component: Server Operations: Projects → Release Engineering
Priority: P3 → --
QA Contact: mrz → release
Does this even matter until we have virus scanning on stage?
Component: Release Engineering → Release Engineering: Future
Clamav claims they support 7zip now: http://oss.netfarm.it/clamav/
Status: NEW → RESOLVED
Closed: 15 years ago
Resolution: --- → WONTFIX
we just picked up 0.95.1 this last week, so we should indeed have this now.
(In reply to comment #14)
> Clamav claims they support 7zip now: http://oss.netfarm.it/clamav/

Only on Windows it turns out.  The Linux version doesn't support it yet.
Status: RESOLVED → REOPENED
Resolution: WONTFIX → ---
Mass move of bugs from Release Engineering:Future -> Release Engineering. See
http://coop.deadsquid.com/2010/02/kiss-the-future-goodbye/ for more details.
Component: Release Engineering: Future → Release Engineering
Priority: -- → P3
Whiteboard: [goodfirstbug]
Whiteboard: [goodfirstbug] → [simple]
https://wwws.clamav.net/bugzilla/show_bug.cgi?id=1222 and http://www.clamav.net/about/roadmap/ say that 7-zip archives will be scannable in the ClamAV 0.96 release. A RC for that is due March 10.
Dave: have we tried the RC yet to see whether it works? Looks like they're on rc2 now:

http://sourceforge.net/projects/clamav/files/clamav/0.96rc2/clamav-0.96rc2.tar.gz/download
(In reply to comment #18)
> https://wwws.clamav.net/bugzilla/show_bug.cgi?id=1222 and
> http://www.clamav.net/about/roadmap/ say that 7-zip archives will be scannable
> in the ClamAV 0.96 release. A RC for that is due March 10.

Is this ClamAV 0.96 available, and does it scan 7-zip archives as expected?
Assignee: nobody → server-ops
Component: Release Engineering → Server Operations
QA Contact: release → mrz
Pushing this over to Chris.  He has ideas on which scanners we should be using or moving to so I'll let him comment on this.
Assignee: server-ops → clyon
Component: Server Operations → Server Operations: Security
QA Contact: mrz → clyon
(In reply to comment #21)
> Pushing this over to Chris.  He has ideas on which scanners we should be using
> or moving to so I'll let him comment on this.

So besides ClamAV, the other Linux based scanners that we have are McAfee and AVG. These are both acceptable for scanning but not sure if it is going to solve the root of this problem. Would need to do further research on that. The other one which we should be getting a copy of soon is Kapersky.
I no longer know what this bug is asking IT/infrasec to do.  Help?
closing this out since it doesn't seem there is any real direction. reopen and comment if somebody disagrees.
Status: REOPENED → RESOLVED
Closed: 15 years ago13 years ago
Resolution: --- → WONTFIX
We need to be able to scan inside our windows installers before releases get pushed out in case one of our build machines gets infected and corrupts one of our releases. It's that simple.
Status: RESOLVED → REOPENED
Resolution: WONTFIX → ---
(In reply to comment #25)
> We need to be able to scan inside our windows installers before releases get
> pushed out in case one of our build machines gets infected and corrupts one of
> our releases. It's that simple.

At what point are we going to do these scans? RegEng has stated they will not hold a release pending a scan before it goes public. Their stance is it will be done after the fact and this is already in place on f.m.o. 

FWIW, I don't agree with that and I think they need to scan before stuff goes public and the more scanners the better. I can't tell you off the top of my head which scanners vs 7z are better or worse but we probably shouldn't just use one of them.
Assignee: clyon → nobody
Component: Server Operations: Security → Release Engineering
QA Contact: clyon → release
btw, moving to releng as this is a process issue that needs to be discussed further and they need to agree upon where to scan in the process.
Whiteboard: [simple] → [simple][triage]
Virus scanning is currently an automated part of our release automation which happens automatically after updates are generated, and manually before pushing to mirrors, and we do block pushing builds to mirrors based on the virus scan results.

Looks like we're currently running 0.97 on stage, does that do what we want for scanning?
Assignee: nobody → server-ops
Component: Release Engineering → Server Operations: Security
QA Contact: release → clyon
I don't think clamav knows how to extract 7zip self-installer packages, I think that was the point of this bug.
(In reply to comment #29)
> I don't think clamav knows how to extract 7zip self-installer packages, I think
> that was the point of this bug.

Ok, so using clamav 0.97 on my machine confirms this. As far as I can tell it's not unpacking the setup.exe file and looking inside of it.

Back over to RelEng.
Assignee: server-ops → nobody
Component: Server Operations: Security → Release Engineering
QA Contact: clyon → release
Assignee: nobody → bhearsum
Whiteboard: [simple][triage] → [automation][releases][simple]
Catlee, what do you think of this approach? I've only done a mild local test, but it seems to work.
Attachment #517738 - Flags: feedback?(catlee)
Comment on attachment 517738 [details]
bash script which runs a command on a list of files, while extracting 7z archives

Looks good.  Be sure to sign the installer as a whole as well though!
Attachment #517738 - Flags: feedback?(catlee) → feedback+
I realized that we don't look inside of MAR files either, updating summary to include that.
Summary: Extract NSIS (windows) installers with 7z when virus scanning → Extract NSIS (windows) installers and MAR files when virus scanning
Can someone from IT tell me how the normal virus scanning is done? What invokes it, and how?
Per mrz, moving to Server Ops to get comment on this:

(In reply to comment #34)
> Can someone from IT tell me how the normal virus scanning is done? What invokes
> it, and how?
Assignee: bhearsum → server-ops
Component: Release Engineering → Server Operations
QA Contact: release → mrz
I've been testing this on surf in the release-scenario, where we trigger a scan. Invocation looks like:
./extract-and-run-command clamdscan -m --no-summary -- /pub/mozilla.org/firefox/nightly/4.0rc1-candidates/build1/

This seems to work well, but has a couple of drawbacks:
- We only scan a single file per invocation
- "-m" is now useless, because of the above
I think these are OK, because of how early we run the virus scan these days. Even in a chemspill, I suspect update verify and QA will still be the long pole. I'm doing a re-run of the 4.0rc1 virus scan right now to get an idea of how long this is going to take.

If it's an issue, I can try to build some sort of batching in...but that may get hairy due to the temp dirs.

I've dropped -v and added --no-summary because the level of verboseness we currently use doesn't make sense here, because we only scan a single file per invocation. New output looks like:
/pub/mozilla.org/firefox/nightly/4.0rc1-candidates/build1/linux-i686/fa/firefox-4.0rc1.tar.bz2.asc: OK
/pub/mozilla.org/firefox/nightly/4.0rc1-candidates/build1/linux-i686/fi/firefox-4.0rc1.checksums: OK
/pub/mozilla.org/firefox/nightly/4.0rc1-candidates/build1/linux-i686/fi/firefox-4.0rc1.tar.bz2: OK
/pub/mozilla.org/firefox/nightly/4.0rc1-candidates/build1/linux-i686/fi/firefox-4.0rc1.tar.bz2.asc: OK
...
/tmp/tmp.elNPO27899/core/plugin-container.exe: OK
/tmp/tmp.elNPO27899/core/README.txt: OK
/tmp/tmp.elNPO27899/core/removed-files: OK
/tmp/tmp.elNPO27899/core/searchplugins/eBay.xml: OK
/tmp/tmp.elNPO27899/core/searchplugins/eki-ee.xml: OK
/tmp/tmp.elNPO27899/core/searchplugins/google.xml: OK
/tmp/tmp.elNPO27899/core/searchplugins/neti-ee.xml: OK
/tmp/tmp.elNPO27899/core/searchplugins/osta-ee.xml: OK


Still waiting to hear from IT about how the normal virus scans are run, to ensure this can be integrated there.
Attachment #517738 - Attachment is obsolete: true
Attachment #517866 - Flags: review?(catlee)
Comment on attachment 517866 [details] [diff] [review]
patch, including mar tool and updated script that handles MARs and EXEs

Can we print out which file we fail on if we do fail? Printing out which file we failed on will be very useful when debugging I imagine!

How long does this take to run now?  Does it preclude running it on release day?  If so, do we need to verify that nothing has changed before pushing to mirrors?  we should probably be doing that anyway...
Attachment #517866 - Flags: review?(catlee) → review+
(In reply to comment #37)
> Comment on attachment 517866 [details] [diff] [review]
> patch, including mar tool and updated script that handles MARs and EXEs
> 
> Can we print out which file we fail on if we do fail? Printing out which file
> we failed on will be very useful when debugging I imagine!

The output already shows each file and pass/fail for it, are you looking to have these summarized at the end? Do you want just the high level files to be highlighted, or even files that were scanned from an unpacked EXE or MAR? Those come out as "/tmp/tmp.whatever/blah/blah", and are fairly noisy. Would grepping out the "PASS" messages from the existing output be good enough?

> How long does this take to run now?

Not sure..I forgot to start this in screen last night, so my first try never finished :(.

> Does it preclude running it on release
> day?

It certainly precludes doing a scan after we get a "push to mirrors" mail, but if we preempt it by enough, we could do it.

> If so, do we need to verify that nothing has changed before pushing to
> mirrors?  we should probably be doing that anyway...

We definitely should be doing that, I'll file a follow-up on it. I don't think that should block this, because we already do releases in which we scan a week ahead of going to mirrors, and never rescan.
(In reply to comment #38)
> (In reply to comment #37)
> > Comment on attachment 517866 [details] [diff] [review]
> > patch, including mar tool and updated script that handles MARs and EXEs
> > 
> > Can we print out which file we fail on if we do fail? Printing out which file
> > we failed on will be very useful when debugging I imagine!
> 
> The output already shows each file and pass/fail for it, are you looking to
> have these summarized at the end? Do you want just the high level files to be
> highlighted, or even files that were scanned from an unpacked EXE or MAR? Those
> come out as "/tmp/tmp.whatever/blah/blah", and are fairly noisy. Would grepping
> out the "PASS" messages from the existing output be good enough?

I just want to make sure if we detect a virus, that we know exactly which file it's in, including the container (setup.exe, .mar) if applicable
(In reply to comment #35)
> Per mrz, moving to Server Ops to get comment on this:
> 
> (In reply to comment #34)
> > Can someone from IT tell me how the normal virus scanning is done? What invokes
> > it, and how?

ping
Heh, I started to answer this the other day, and then in doing my fact checking, discovered it was all broken, and got distracted trying to fix it (we broke it all when we changed the firefox ftp mounts around, which I knew at the time and was intending to fix within a couple days after that, and promptly forgot :|  )

We have it set up according to the "Ongoing Scanning" section on https://intranet.mozilla.org/Security/Virus_Scanning

We have a scheduler and queue runners on various scan engines that run the scan jobs.  The dashboard is at http://im-virusscan01.mozilla.org/cgi-bin/listqueue.cgi for now (VPN required, URL will probably change eventually)

It should be fairly easy to get this integrated into the queue runners to handle files of these types when they're hit.
Thanks for your reply, Dave. Just to spell it out explicitly, this is the current interface to the extractor:
extract_and_run_command.py -j4 [command that causes files to be scanned] -- [files to be scanned]

Will the ongoing scanning system be able to integrate that?
(In reply to comment #42)
> Thanks for your reply, Dave. Just to spell it out explicitly, this is the
> current interface to the extractor:
> extract_and_run_command.py -j4 [command that causes files to be scanned] --
> [files to be scanned]
> 
> Will the ongoing scanning system be able to integrate that?

Justdave confirmed that this should be fine on IRC. I'm going to take this bug back to finish up the RelEng parts. I'll throw it back again once it's all landed and ready to be used.
Assignee: server-ops → nobody
Component: Server Operations → Release Engineering
QA Contact: mrz → release
Attached patch python version (obsolete) — Splinter Review
I ran this version on stage with -j4 and -j12. -j4 took 90min, -j12 took 77min. I kept on an eye on running jobs at the time, and neither seemed to hammer the system hard enough to cause any failures. Load shot up pretty high, but I suspect that's normal when you're working this much.

For the on-demand scans, we're going to want to change our invocation to something like:
extract_and_run_command.py -jN clamdscan -m --no-summary -- /pub/mozilla.org/firefox/nightly/4.0rc1-candidates/build1

I'm not sure what -j should end up being yet, maybe we'll stick with 4 for now?

KeyboardInterrupt still doesn't seem to be working right, despite what the comments say it only seems to be killing a single thread. Any idea how to fix that? Should I just rip it out and make it clear that you need to use 'kill' to terminate mid-run?
Attachment #517866 - Attachment is obsolete: true
Attachment #518462 - Flags: review?(catlee)
After a few more attempts I still couldn't get KeyboardInterrupt handling to work properly, so I ripped it out entirely and added a big warning about killing it.

This patch is 100% done now, as far as I know.
Attachment #518462 - Attachment is obsolete: true
Attachment #518488 - Flags: review?(catlee)
Attachment #518462 - Flags: review?(catlee)
Small updates here:
- Fix sys.path appending to account for symlinks, because that's how we'll be using it.
- Fix bug in push-to-mirrors.py patch

This has been running fine in staging, albeit really slowly. We may have to move staging-stage to a better disk/ESX host for this to actually work.
Attachment #518495 - Attachment is obsolete: true
Attachment #518734 - Flags: review?(rail)
Attachment #518734 - Flags: review?(catlee)
We need p7zip to extract installers, and I changed the fake clamdscan to improve the output a bit.
Attachment #518488 - Attachment is obsolete: true
Attachment #518496 - Attachment is obsolete: true
Attachment #518735 - Flags: review?(rail)
Attachment #518488 - Flags: review?(catlee)
Depends on: 640990
Assignee: nobody → bhearsum
Attachment #518735 - Attachment is obsolete: true
Attachment #518735 - Flags: review?(rail)
Comment on attachment 518734 [details] [diff] [review]
fix sys.path addition, push-to-mirrors.py

r+ with the following 2 nits:
1. mar.py: use "#/usr/bin/env python" shebang
2. extract_and_run_command.py: use os.path.splitext instead of filename.split('.')[-1]

Otherwise looks good.
Attachment #518734 - Flags: review?(rail) → review+
BTW, dmg files could be also extracted by mounting them:

bzcat file.dmg > file.hfs
sudo mount -t hfsplus -o loop file.hfs /mnt/dmg_dir

what requires sudo or a special fstab entry :/
Uses the EL4 RPM, also has extract_and_run_command.py / updated clmadscan. I tested the $@ on a Linux staging slave, and it worked fine.
Attachment #518747 - Attachment is obsolete: true
Attachment #519159 - Flags: review?(rail)
Attachment #519159 - Flags: review?(rail) → review+
(In reply to comment #52)
> BTW, dmg files could be also extracted by mounting them:
> 
> bzcat file.dmg > file.hfs
> sudo mount -t hfsplus -o loop file.hfs /mnt/dmg_dir
> 
> what requires sudo or a special fstab entry :/

Don't think we'll be getting that on stage, and I'm going to resist further scope-creep here and explicitly defer it :).
This version fixes the potential deadlock caused by using proc.wait() without sending stdout somewhere.
Attachment #518734 - Attachment is obsolete: true
Attachment #519643 - Flags: review?(catlee)
Attachment #518734 - Flags: review?(catlee)
Attachment #519643 - Flags: review?(catlee) → review+
Attachment #519643 - Flags: checked-in+
Attachment #519159 - Flags: checked-in+
Dave, the Releng side of this is done now. Can you:
- Add a symlink from /usr/local/bin/extract_and_run_command.py -> /home/ffxbld/bin/extract_and_run_command.py
- Adjust the continuous virus scan to use the following command:
/usr/local/bin/extract_and_run_command.py -j4 [your normal clamd invocation] -- [files to scan]

Let me know if you have any questions!
Assignee: bhearsum → server-ops
Component: Release Engineering → Server Operations
Flags: checked-in+
QA Contact: release → mrz
extract_and_run_command.py should be chmoded 755
Attachment #520162 - Flags: review?(bhearsum)
Attachment #520162 - Flags: review?(bhearsum) → review+
Any chance that the symlink part of this can be done today, so that the 4.0rc2 virus scan works correctly?
Severity: normal → critical
Assignee: server-ops → justdave
Comment on attachment 520162 [details] [diff] [review]
chmod extract_and_run_command.py

Pushed http://hg.mozilla.org/build/tools/rev/e28488b561ea

[~ffxbld/checkouts/hg-build-tools@stage.m.o]
hg pull -u
symlink is in place on surf.  Working on initial checkout/setup on one of the virus scan machines to test there.
justdave found a bug in extract_and_run_command.py: it doesn't handle files, only dirs. This patch fixes it:
[] bhearsum@voot:~/Mozilla/checkouts/tools/stage$ python extract_and_run_command.py -j4 echo -- ~/tmp/abcd/setup.exe
START 10:28:56: /home/bhearsum/tmp/abcd/setup.exe
/home/bhearsum/tmp/abcd/setup.exe
END 10:28:56 (0 seconds elapsed): /home/bhearsum/tmp/abcd/setup.exe
Attachment #520192 - Flags: review?(catlee)
Attachment #520192 - Flags: review?(catlee) → review+
Attached patch append dirname to tempdir (obsolete) — Splinter Review
Justdave says that this will make the output much easier to parse/understand.
Attachment #520205 - Flags: review?(catlee)
Comment on attachment 520205 [details] [diff] [review]
append dirname to tempdir

Should include a directory named after the file being unpacked, too.
i.e. if you're unpacking /pub/mozilla.org/foo.exe then the tempdir should be
 {tempdir}/pub/mozilla.org/foo.exe/{unpacked files}
not
 {tempdir}/pub/mozilla.org/{unpacked files}
Attached patch v2 (obsolete) — Splinter Review
good catch!
Attachment #520205 - Attachment is obsolete: true
Attachment #520207 - Flags: review?(catlee)
Attachment #520205 - Flags: review?(catlee)
Attached patch v3 (obsolete) — Splinter Review
Better way of appending the filename, also fixes relative paths to work better, by using abspath() in find_files().
Attachment #520207 - Attachment is obsolete: true
Attachment #520210 - Flags: review?(catlee)
Attachment #520207 - Flags: review?(catlee)
Comment on attachment 520210 [details] [diff] [review]
v3

This version doesn't clean up very well....going to fix that.
Attachment #520210 - Attachment is obsolete: true
Attachment #520210 - Flags: review?(catlee)
Attachment #520217 - Flags: review?(catlee)
Attachment #520217 - Flags: review?(catlee) → review+
Dave, I'm all done here, anything else you need to do?
Assignee: justdave → dparsons
Assignee: dparsons → server-ops-infra
Component: Server Operations → Server Operations: Infrastructure
QA Contact: mrz → jdow
Assignee: server-ops-infra → justdave
Apparently we are running scan-uploaded-files.sh somewhere (this file lives at, eg, upload1.dmz.scl3:/usr/local/bin/) because there is an up-to-date timestamps in /data/. That scripts calls out to scanfile, which is just doing a clamdscan. It could be calling extract_and_run_command.py to handle this. For example, our explicit scanning of release files does this:
 extract_and_run_command.py -j2 clamdscan -m --no-summary -- /pub/mozilla.org/thunderbird/nightly/13.0-candidates/build1/
Status: REOPENED → RESOLVED
Closed: 13 years ago12 years ago
Resolution: --- → DUPLICATE
Component: Server Operations: Infrastructure → Infrastructure: Other
Product: mozilla.org → Infrastructure & Operations
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: