[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

zero-trust methods, trusted store method



To expand my idea from IRC to a wider audience:

Currently, we have some sort of implicit trust in _apt methods
because we trust them doing hashes correctly, which caused the
last CVE.

We can re-read the file and reverify the hashes of course, but
it still leaves us vulnerable: Since partial/ is owned by _apt,
_apt could be replacing the file while we are reverifying it.

In order to make the sandboxing complete, there is one solution:
We introduce a trusted method that runs as root and can write files
to a directory that is owned by root. It then copies the files from
partial/ to root, and verifies them.

We also need to compress some indexes, and we use the store method
for that. Now, we cannot verify the result of the compression in a
meaningful way.

My suggestion is thus to make store run as root, and run decompression
and compression algorithms in a forked subprocess that runs as nobody
- this also protects those processes from other _apt processes trying
to influence them.

We essentially build a simple flow of data:

<partial/> -> [untrusted decompressor]
              |
              \-> [trusted hasher]
                  |
                  \-> [untrusted compressor]
                      |
                      \-> [trusted writer] -> <verified/>

A (Go like) pseudo code for this could look like this:
	// Untrusted helper process
	if (fork() == 0) {
		drop privileges to nobody

		select {
			case compressedData available:
				dataToHash <- decompress(compressedData)
			case hashedData available:
				dataToWrite <- compress(hashedData)
		}
	}
        // Trusted verification and writing code (running as root)
	select {
		case dataToHash available:
			hashes = updateHashes(dataToHash, hashes)
			hashedData <- dataToHash
		case dataToWrite available:
			outputFile <- dataToWrite
	}
        unlink(partial file)


This model has some interesting properties:

(0) partial/ becomes completely untrusted
(1) We can thus keep existing methods as they are, and let them do
    whatever they want to in partial/
(2) methods writing to partial/ cannot interfere with the store method
    that writes to verified/, as they run using different users (_apt vs {root, nobody}).

There are some drawbacks:

(1) It takes more space to keep the extra copies around. For uncompressed
    files on btrfs or recent xfs, we could work around that by just performing
    reflinks instead of copying, and then only hash the data instead of copying it.
(2) It takes extra time because we hash/copy everything one more time.
(3) it does not work for the file:/ method - maybe it is time to remove it and force
    people to use copy:/ instead.

-- 
debian developer - deb.li/jak | jak-linux.org - free software dev
ubuntu core developer                              i speak de, en


Reply to: