public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: "Michal Prívozník" <mprivozn@redhat.com>
To: Stefano Brivio <sbrivio@redhat.com>
Cc: libvir-list@redhat.com, passt-dev@passt.top
Subject: Re: [PATCH 4/4] qemu_passt: Don't let passt fork off
Date: Tue, 14 Feb 2023 16:30:17 +0100	[thread overview]
Message-ID: <56000087-8df0-294c-6f42-57983e15d383@redhat.com> (raw)
In-Reply-To: <20230214140253.49bbc13a@elisabeth>

On 2/14/23 14:02, Stefano Brivio wrote:
> On Tue, 14 Feb 2023 12:51:22 +0100
> Michal Privoznik <mprivozn@redhat.com> wrote:
> 
>> When passt starts it tries to do some security measures to
>> restrict itself. For instance, it creates its own namespaces,
>> umounts basically everything, drops capabilities, forks off to
>> further restrict itself (the child is where all interesting work
>> takes place now). This is sound, except it's causing two
>> problems:
>>
>> 1) the PID file FD, which we leak into the passt process, gets
>>    closed (and thus our virPidFile*() helpers see unlocked PID
>>    file, which makes them think the process is gone),
> 
> I didn't realise this was the case, but giving passt write (unless I'm
> missing something) access to a file created by libvirtd doesn't look
> desirable to me.

That's not what's happening here. In fact, the opposite. We let libvirt
create the file, lock and write it. Then the file's FD is leaked into
passt process. This way, we can learn whether the PID file is still
valid: if we just try to lock it and:

a) fail, then the file is still locked, i.e. passt is still running,
b) succeed, then the file is no longer locket by passt, i.e. it's no
longer running.

Thing is, passt doesn't even know about the FD (unless it starts closing
FDs "randomly", e.g. via closefrom(3) or an alternative). This is the
reason we can't use passt's --pid, because it writes the PID file
without any locking dance. Therefore, libvirt can't know whether the PID
file is still valid. If it did just read the file and killed PID from
there it might kill a random process that was unfortunate to be assigned
the same PID.

BTW, there are two other issues with PID files in passt:
1) no locking means, that the file is very easily overwritten:

 $ passt --pid /tmp/passt.pid 2>/dev/null & \
   passt --pid /tmp/passt.pid 2>/dev/null; \
   pgrep passt ; cat /tmp/passt.pid
[1] 21029
[1]+  Done                    passt --pid /tmp/passt.pid 2> /dev/null
21034
21035
21035

2) with --daemonize, only the PID of the parent process is written which
is pretty much useless, as the parent quits shortly after clone().

Now, libvirt's virPidFile* machinery (src/util/virpidfile.c) ensures
that case 1) won't happen (yes, we have internal APIs that read pid
files unlocked, but those are not used from this code we're talking about).

And this patch tries to fix the case 2) by instructing passt to not
clone(). If it means that it can't use PID namespace, then so be it.
It's better to not let processes behind.

> 
>> 2) the PID file no longer reflects true PID of the process.
>>
>> Worse, the child calls setsid() so we can't even kill the whole
>> process group. I mean, we can but it won't be any good.
>>
>> Fortunately, passt has '--foreground' argument, which causes it
>> to undergo the same security measures but without forking off the
>> child.
> 
> They're not the same -- unfortunately they can't be, because, on Linux,
> you can't change the PID of an existing process, so there's no way to
> enter a new PID namespace without clone().
> 
> If passt remains in the same PID namespace, it's still able to see PIDs
> of other processes, which is not desirable from a security perspective.

I understand that, but it's already confined in plenty other ways. It's
way worse to leave a process running than being able to see other PIDs.

> 
> Again from a security perspective, this is probably a small impact, so
> I guess it's fine if there's no other way around it. But I see a lot of
> ways around it...
> 

Is there? If we have a helper process that fork()-s then the only way we
can 'track' its PIDs (and kill them) is by placing them into a CGroup.
Until we do that we have to trust helper processes to behave properly.
But that's something I'd like to avoid.

Michal


  reply	other threads:[~2023-02-14 15:30 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-14 11:51 [PATCH 0/4] qemu_passt: Don't let passt fork off Michal Privoznik
2023-02-14 11:51 ` [PATCH 1/4] Revert "qemu: allow passt to self-daemonize" Michal Privoznik
2023-02-15  7:06   ` Laine Stump
2023-02-14 11:51 ` [PATCH 2/4] qemu_extdevice: Make qemuExtDevicesHasDevice() check def->nets Michal Privoznik
2023-02-15  7:22   ` Laine Stump
2023-02-15 15:23     ` Michal Prívozník
2023-02-14 11:51 ` [PATCH 3/4] qemu_passt: Report error when getting passt PID failed Michal Privoznik
2023-02-15  7:24   ` Laine Stump
2023-02-14 11:51 ` [PATCH 4/4] qemu_passt: Don't let passt fork off Michal Privoznik
2023-02-14 13:02   ` Stefano Brivio
2023-02-14 15:30     ` Michal Prívozník [this message]
2023-02-14 16:22       ` Stefano Brivio
2023-02-15  7:50     ` Laine Stump
2023-02-15 17:04       ` Michal Prívozník
2023-02-15 18:22         ` Laine Stump
2023-02-15 18:30         ` Stefano Brivio
2023-02-16  8:52           ` Michal Prívozník
2023-02-16  9:07             ` Peter Krempa
2023-02-16  9:15             ` Stefano Brivio

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56000087-8df0-294c-6f42-57983e15d383@redhat.com \
    --to=mprivozn@redhat.com \
    --cc=libvir-list@redhat.com \
    --cc=passt-dev@passt.top \
    --cc=sbrivio@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).