Repository: mesonbuild/meson
Issue category: Security Vulnerability

Issue:
'ninja install' attempts to gain elevated privileges
It is disturbing for 'ninja install' to prompt for a sudo password with polkit.

This breaks user expectations, and introduces a security risk.

This has evidently been meson's behavior for a very long time, but it's distressing, and it's surprising because meson is usually so keen on simplicity; the last thing I expect when invoking a build tool is for it to take over the screen and request a password.

(It would be equally distressing for 'sudo ninja install' to clutter the local directory with root-owned files.)
pkexec logic is a bad idea
This is a bit related to https://github.com/mesonbuild/meson/issues/4758

Basically, what you're doing with polkit doesn't make sense.  You're allowing to execute arbitrary code (in the Meson build logic) as root; the permission isn't actually limited in any way.  So rather than having meson contain logic to run `pkexec` it's just much saner to tell people to do `sudo meson install` (or `pkexec meson install`) etc.

IOW you should just delete the polkit rules and print an error message telling people how to use `sudo/pkexec` (this is quite commonly documented for other build systems of course).
'ninja install' attempts to gain elevated privileges
It is disturbing for 'ninja install' to prompt for a sudo password with polkit.

This breaks user expectations, and introduces a security risk.

This has evidently been meson's behavior for a very long time, but it's distressing, and it's surprising because meson is usually so keen on simplicity; the last thing I expect when invoking a build tool is for it to take over the screen and request a password.

(It would be equally distressing for 'sudo ninja install' to clutter the local directory with root-owned files.)
pkexec logic is a bad idea
This is a bit related to https://github.com/mesonbuild/meson/issues/4758

Basically, what you're doing with polkit doesn't make sense.  You're allowing to execute arbitrary code (in the Meson build logic) as root; the permission isn't actually limited in any way.  So rather than having meson contain logic to run `pkexec` it's just much saner to tell people to do `sudo meson install` (or `pkexec meson install`) etc.

IOW you should just delete the polkit rules and print an error message telling people how to use `sudo/pkexec` (this is quite commonly documented for other build systems of course).


Hints:
What system are you using? Asking because it helps use determine how to fix this. Also would help to say what version of Meson and Ninja you’re using.
This is on Linux (ubuntu 20.04), and using meson from either the system or up-to-date git.

It's not a bug; it's a feature.  It just happens to be a feature that gives me the shivers.

Here's an example meson.build to reproduce with:
```
project('blah', 'c')
configure_file(
   input: 'foo.h.in',
   output: 'foo.h',
   configuration : {},
   install_dir: 'include',
   install: true)
```
Create a foo.h.in with anything in it, then do
```
$ meson . btmp
$ cd btmp
$ ninja install
```

This will trigger the prompt for a sudo password.



The `sudo` command is used to temporarily give members of the sudo group privileges similar to the one root users have. When setting up Ubuntu you are asked to provide a password to proceed with installation. That is the password needed here.

Note it won't be seen on the terminal when typing as this prevents any one around from looking over your shoulder and seeing it.

That is the password that will be asked of you whenever you want to carry out any tasks that required elevated user privileges, like in this particular case.

It’s possible to disable sudo but I don’t recommend doing it.
That is all true, and I knew that already.

The bug I am reporting is a design bug; build utilities have traditionally never attempted to gain elevated privileges, and it is highly surprising that meson does so.
@michaelbadcrumble This issue was opened with the rationale "asking for sudo is a disturbing design and security violation because build tools should not ask for elevated privileges". It's very out of place to try explaining that sudo is a tool to gain elevated privileges, because that was never in doubt...

...

This was added in #3567 with the rationale:
- No more accidentally touching a file before running `sudo ninja install`, causing the outputs to become owned by root.
Yes, it solves a real problem (sudo ninja install accidentally touching files in build directory).  

But  alternate solutions (e.g. abort rather than build if something needs building during install, or dropping privs while building) are possible.
We should probably just print what we need elevated privileges for. Then the user can make a decision about whether to provide it or not.
> We should probably just print what we need elevated privileges for.

Why not just let to fall back to "Permission denied" when it fails to install files without a the right permissions? Anyone that knows how to use meson should be able to figure out what that means.
It's hard to come up with something both secure and convenient...
There is a simple solution to this. Don't elevate privileges. If the user wants root, tell them to use "sudo meson …". This is very easy to implement and it's what every other build system does.

EDIT: Workaround for all of this: `export PKEXEC_UID=99999`. Meson will now raise a permission error instead of trying to grab elevated privileges.
I recently helped debug someone's distro build script using meson install. By accident, DESTDIR was not set. Instead of either visibly trying pkexec or failing with normal permission errors, meson simply crashed because LD_PRELOAD was automatically exported by fakeroot, which the entire distro build script runs under, and hence pkexec could not be executed at all.

That was a pretty annoying and silly thing to debug. It would have been a whole lot clearer to just get a permission error. :p
Similar problem here. On my machine, `sudo` does not ask for a password if its executed from my user account.
I was certainly surprised when it printed `Installing *.so to /usr/local/lib`. 

Good things the libraries have a timestamp, so that I can see which one was just installed and delete them.

If there were some libraries in this project that are called the same like an existing library, I would have accidentally broken my machine.

IMHO, an explicit `--try-to-grab-root-rights` flag would be ok, but `meson install` just taking root rights is very unexpected.
 `meson` is not taking any root rights without user's permission but user, through pkexec, is, when the user let meson manage the DESTDIR, `/usr/local`. 

pkexec's popup allows you to cancel the privilege grant anytime but sudo is keeping on until a timeout where you can execute root command without entering the password again.

For me the pkexec is safer and give more control to the user including newbies.
polkit is an issue in a non X env such as a docker image setup with a user
This ticket is not discussing whether polkit or sudo is more secure or user friendly than the other.

It is discussing whether "automatically try a privilege elevation command of any sort" is a good/bad idea.
To answer your question I think it's a good idea to grant pivilege but using polkit limits to a graphical environment.
I think it is very unexpected too. I haven't looked at the code (and I didn't see this behavior mentioned int he documentation, but I didn't go looking for it) but how does meson decide whether it needs elevated privileges? I can imagine situations where the current user is not root yet it can write to the destination directory just fine.
IMHO an install command is supposed to be started with privileges appropriate for installing to DESTDIR, not try to grab them itself. This is how most if not all other equivalents of "make install" work; the Principle of Least Surprise should apply to meson too.

> I can imagine situations where the current user is not root yet it can write to the destination directory just fine.

Exactly. Worse, the way some home directories and/or test environments are set up I can easily imagine an install to fail *because* it's done by root.
The pkexec is used **only** if a permission error is detected by meson (if DESTDIR is a safe user place, no pkexec). In any case the sudoer's password is requested. 

This solution avoids `ninja install` to build missing dependency (file modified and ninja install called to fast the process) as a sudoers and create `root` files in the build folder.

We could use  `sudo -k` which is always requesting the sudoer password and is console compatible.

> In any case the sudoer's password is requested.

If sudo is configured to work without password, there is no password request, even with the -k option 
> If sudo is configured to work without password

Don't do that. And if you do, I don't see how it's meson problem's if you shoot yourself in the feet...

> polkit is an issue in a non X env such as a docker image setup with a user
> To answer your question I think it's a good idea to grant pivilege but using polkit limits to a graphical environment.

Why is it a problem? It will just fail, but I guess meson would raise a backtrace instead of printing a nice error message.
```
pkexec true
Error getting authority: Error initializing authority: Could not connect: No such file or directory
```

> I can easily imagine an install to fail _because_ it's done by root.

Actually no, because the pkexec case is run ONLY in a case it would have failed anyway. If you expected the install to work without priviledge and that prompt popup, just cancel it and fix your setup.

> I can imagine situations where the current user is not root yet it can write to the destination directory just fine.

I'm doing that all the time, meson won't use pkexec in that case.

> The bug I am reporting is a design bug; build utilities have traditionally never attempted to gain elevated privileges, and it is highly surprising that meson does so.

I would not take traditional build utilities as example, they all sucks, that's why we have meson in the first place... It is surprising only because it's a new thing to lots of people, but it's not unique neither. systemctl command line does it too, I think more and more CLI does it because it's a nicer user experience. The more CLI does it, the less surprising it will become.
> I recently helped debug someone's distro build script using meson install. By accident, DESTDIR was not set. Instead of either visibly trying pkexec or failing with normal permission errors, meson simply crashed because LD_PRELOAD was automatically exported by fakeroot, which the entire distro build script runs under, and hence pkexec could not be executed at all.
> 
> That was a pretty annoying and silly thing to debug. It would have been a whole lot clearer to just get a permission error. :p
"it's a nice user experience, the more CLI tools do it the more people will expect it".

That was never really my argument.

No, it's a bad user experience, I don't want meson to emulate other build tools because other build tools don't do it -- I want meson to not do it, because it's a bad thing to do, and "just for the record everyone else realized it's a bad idea, too".
> "it's a nice user experience, the more CLI tools do it the more people will expect it".
> 
> No, it's a bad user experience, I don't want meson to emulate other build tools because other build tools don't do it -- I want meson to not do it, because it's a bad thing to do, and "just for the record everyone else realized it's a bad idea, too".

Could you please elaborate a bit more about `because it's a bad thing to do` ?

> > I recently helped debug someone's distro build script using meson install. By accident, DESTDIR was not set. Instead of either visibly trying pkexec or failing with normal permission errors, meson simply crashed because LD_PRELOAD was automatically exported by fakeroot, which the entire distro build script runs under, and hence pkexec could not be executed at all.
> > That was a pretty annoying and silly thing to debug. It would have been a whole lot clearer to just get a permission error. :p

That seems a very specific case and easy to fix. We can detect if we are in fakeroot and not use pkexec: https://stackoverflow.com/questions/33446353/bash-check-if-user-is-root
You have taken my objection "this is a fragile pile of 💩 and fails in surprising ways whenever you step out of the narrow-minded box of the polkit developers" and extracted from that, that "hey, we can make this a special case, everything will be fine". :p

The essential problem here is that under a number of circumstances meson decides it needs root permission, and it's wrong because I actually wanted meson to error out with permission errors and I absolutely under no circumstances want it to be successful, I'd rather fix meson.build or the configure options. And meson gives no insight into why it's automatically doing this nonsense.
Also polkit was a horrible choice if anything should be done :p it pops up a GUI window when running cli commands. I'm extremely annoyed at systemctl for the same reason, I assure you.
The current situation might not be perfect, but most people will then just call `doas/sudo ninja install` which is really bad because you can easily end up with files owned by root in your build directory. In this case, there is not much Meson can do (dropping privileges, etc.) because `ninja` is in charge of compiling at this point.

So, the solution here is to use the least privilege principle. The easiest way of achieving this is to only elevate privileges when needed.

Whether polkit is the right tool (I am also not a fan of GUI popups in my CLI), stability, bugs, etc. is a different question.
I think that `ninja install` requiring to create files in the build directory is a bug in Meson or a deficiency of the build definition. Fixing this may be harder than wrapping the "real" install part of `ninja install` into a wrapper that elevates privileges, but IMHO is the correct solution.
> Whether polkit is the right tool (I am also not a fan of GUI popups in my CLI), stability, bugs, etc. is a different question.

Indeed, and that's why I think polkit prompts ***don't solve the problem***.

The current state of affairs:
- meson is broken

The previous state of affairs:
- meson is broken in a completely unrelated way

The "solution" merged doesn't solve anything, it merely shifts the brokenness one step over to the left. And people building stuff on the command line are statistically speaking more likely than *any* other linux users to simply... not have polkit installed at all (but they probably do have sudo or doas).

These people are still getting root owned files.

I guess in the year 2018 I'd object fiercely to #3567 being merged on the grounds "this solves nothing". I still believe it should be reverted, but I do understand it is harder to convince other people to move back from one brokenness to the original brokenness because ***I*** think the original brokenness is less bad.

Inertia, "let's just do nothing if we cannot solve it properly", cuts both ways.
> The current state of affairs:
> 
>     * meson is broken

What's broken? If it's just the fakeroot case, it's easy to fix without throwing the baby with the bathwater.
> And people building stuff on the command line are statistically speaking more likely than _any_ other linux users to simply... not have polkit installed at all

[citation needed]

Not sure who does not have pkexec installed, is there any distro not having it by default? And if you don't have it then it's all good for you, it will just not use it and you'll get your permission denied error.


> >  If sudo is configured to work without password

> Don't do that. And if you do, I don't see how it's meson problem's if you shoot yourself in the feet...

Why shouldn't I do that? The password prompt is just security theater, if a malicious program has user rights it can just run 

```
echo "alias sudo=keyloggedsudo" >> ~/.bashrc 
```
> There is a simple solution to this. Don't elevate privileges. If the user wants root, tell them to use "sudo meson …". This is very easy to implement and it's what every other build system does.
> 
> EDIT: Workaround for all of this: `export PKEXEC_UID=99999`. Meson will now raise a permission error instead of trying to grab elevated privileges.

This was a good work around for me as I was building with meson on an NFS
Just here to chime in that this is wrong and should be removed. The proper way to do this is not prompting for privilege elevation (that's **always wrong** and trains users to get phished) nor `sudo ninja install` (which as noted can give root-owned files in build directory) but performing an unprivileged install into a `DESTDIR` then manually elevating privileges to copy the contents of the staged install to the main filesystem *after confirming it's not writing places you don't want it to*.

> and trains users to get phished

A program with user privileges can run
```
echo "alias sudo=keyloggedsudo" >> ~/.bashrc 
```
So that argument is invalid.
You're missing the point which is about the kind of reaction it trains, not the particular privilege domains involved here. It's training the pattern "something asks for credentials and presents a prompt" as valid, which is how phishing works.

Yeah ok. 
To be fair, phishing is usually browser based and not console based.
> You're missing the point which is about the kind of reaction it trains, not the particular privilege domains involved here. It's training the pattern "something asks for credentials and presents a prompt" as valid, which is how phishing works.

IMHO it's user's problem. If It asks for privilege,  we should respect people's intelligence to be responsible of putting their credentials.
There are better mechanisms (cf. DESTDIR) than asking for privileges in the first place.

Respecting people's intelligence is not the point. You can train perfectly intelligent people to habitually ack away any and all auth-request dialog windows if you annoy them enough with them.

The point is motor memory, unexpected interactions, and anti-patterns (e.g. an install method that behaves differently when started non-interactively).


The point here is to install by default your software (no DESTDIR) on most linux distro dest dir, /usr/local which is a system restricted area. 

So user  needs to grant privilege to install his library (he chose to do it). Train him to use `sudo ninja install` sounds a bit the same as training him to enter the password in pkexec. 

And it avoids to generate files which will be root owned by a rebuild of a modified source file.
@Volker-Weissmann I would also argue that if you have a malicious user program with access to your home directory that you have *far* bigger problems to worry about (like it encrypting or uploading everything it has access to, keylogging your *entire* desktop https://github.com/anko/xkbcat).
> @Volker-Weissmann I would also argue that if you have a malicious user program with access to your home directory that you have _far_ bigger problems to worry about (like it encrypting or uploading everything it has access to, keylogging your _entire_ desktop https://github.com/anko/xkbcat).

Yes, of course, but keylogging everything doesn't mean you could not also keylog sudo.
Even if your data is only readible/writable as root, that won't save you.
> It's training the pattern "something asks for credentials and presents a prompt" as valid, which is how phishing works.

Right, we should stop training people to prepend "sudo" to all commands. Better only request elevated permission only if needed.
I agree, but this concern is already raised in #7345 (without however mentioning the keyword "pkexec", only "polkit").
Workaround: `export PKEXEC_UID=99999`.
What system are you using? Asking because it helps use determine how to fix this. Also would help to say what version of Meson and Ninja you’re using.
This is on Linux (ubuntu 20.04), and using meson from either the system or up-to-date git.

It's not a bug; it's a feature.  It just happens to be a feature that gives me the shivers.

Here's an example meson.build to reproduce with:
```
project('blah', 'c')
configure_file(
   input: 'foo.h.in',
   output: 'foo.h',
   configuration : {},
   install_dir: 'include',
   install: true)
```
Create a foo.h.in with anything in it, then do
```
$ meson . btmp
$ cd btmp
$ ninja install
```

This will trigger the prompt for a sudo password.



The `sudo` command is used to temporarily give members of the sudo group privileges similar to the one root users have. When setting up Ubuntu you are asked to provide a password to proceed with installation. That is the password needed here.

Note it won't be seen on the terminal when typing as this prevents any one around from looking over your shoulder and seeing it.

That is the password that will be asked of you whenever you want to carry out any tasks that required elevated user privileges, like in this particular case.

It’s possible to disable sudo but I don’t recommend doing it.
That is all true, and I knew that already.

The bug I am reporting is a design bug; build utilities have traditionally never attempted to gain elevated privileges, and it is highly surprising that meson does so.
@michaelbadcrumble This issue was opened with the rationale "asking for sudo is a disturbing design and security violation because build tools should not ask for elevated privileges". It's very out of place to try explaining that sudo is a tool to gain elevated privileges, because that was never in doubt...

...

This was added in #3567 with the rationale:
- No more accidentally touching a file before running `sudo ninja install`, causing the outputs to become owned by root.
Yes, it solves a real problem (sudo ninja install accidentally touching files in build directory).  

But  alternate solutions (e.g. abort rather than build if something needs building during install, or dropping privs while building) are possible.
We should probably just print what we need elevated privileges for. Then the user can make a decision about whether to provide it or not.
> We should probably just print what we need elevated privileges for.

Why not just let to fall back to "Permission denied" when it fails to install files without a the right permissions? Anyone that knows how to use meson should be able to figure out what that means.
It's hard to come up with something both secure and convenient...
There is a simple solution to this. Don't elevate privileges. If the user wants root, tell them to use "sudo meson …". This is very easy to implement and it's what every other build system does.

EDIT: Workaround for all of this: `export PKEXEC_UID=99999`. Meson will now raise a permission error instead of trying to grab elevated privileges.
I recently helped debug someone's distro build script using meson install. By accident, DESTDIR was not set. Instead of either visibly trying pkexec or failing with normal permission errors, meson simply crashed because LD_PRELOAD was automatically exported by fakeroot, which the entire distro build script runs under, and hence pkexec could not be executed at all.

That was a pretty annoying and silly thing to debug. It would have been a whole lot clearer to just get a permission error. :p
Similar problem here. On my machine, `sudo` does not ask for a password if its executed from my user account.
I was certainly surprised when it printed `Installing *.so to /usr/local/lib`. 

Good things the libraries have a timestamp, so that I can see which one was just installed and delete them.

If there were some libraries in this project that are called the same like an existing library, I would have accidentally broken my machine.

IMHO, an explicit `--try-to-grab-root-rights` flag would be ok, but `meson install` just taking root rights is very unexpected.
 `meson` is not taking any root rights without user's permission but user, through pkexec, is, when the user let meson manage the DESTDIR, `/usr/local`. 

pkexec's popup allows you to cancel the privilege grant anytime but sudo is keeping on until a timeout where you can execute root command without entering the password again.

For me the pkexec is safer and give more control to the user including newbies.
polkit is an issue in a non X env such as a docker image setup with a user
This ticket is not discussing whether polkit or sudo is more secure or user friendly than the other.

It is discussing whether "automatically try a privilege elevation command of any sort" is a good/bad idea.
To answer your question I think it's a good idea to grant pivilege but using polkit limits to a graphical environment.
I think it is very unexpected too. I haven't looked at the code (and I didn't see this behavior mentioned int he documentation, but I didn't go looking for it) but how does meson decide whether it needs elevated privileges? I can imagine situations where the current user is not root yet it can write to the destination directory just fine.
IMHO an install command is supposed to be started with privileges appropriate for installing to DESTDIR, not try to grab them itself. This is how most if not all other equivalents of "make install" work; the Principle of Least Surprise should apply to meson too.

> I can imagine situations where the current user is not root yet it can write to the destination directory just fine.

Exactly. Worse, the way some home directories and/or test environments are set up I can easily imagine an install to fail *because* it's done by root.
The pkexec is used **only** if a permission error is detected by meson (if DESTDIR is a safe user place, no pkexec). In any case the sudoer's password is requested. 

This solution avoids `ninja install` to build missing dependency (file modified and ninja install called to fast the process) as a sudoers and create `root` files in the build folder.

We could use  `sudo -k` which is always requesting the sudoer password and is console compatible.

> In any case the sudoer's password is requested.

If sudo is configured to work without password, there is no password request, even with the -k option 
> If sudo is configured to work without password

Don't do that. And if you do, I don't see how it's meson problem's if you shoot yourself in the feet...

> polkit is an issue in a non X env such as a docker image setup with a user
> To answer your question I think it's a good idea to grant pivilege but using polkit limits to a graphical environment.

Why is it a problem? It will just fail, but I guess meson would raise a backtrace instead of printing a nice error message.
```
pkexec true
Error getting authority: Error initializing authority: Could not connect: No such file or directory
```

> I can easily imagine an install to fail _because_ it's done by root.

Actually no, because the pkexec case is run ONLY in a case it would have failed anyway. If you expected the install to work without priviledge and that prompt popup, just cancel it and fix your setup.

> I can imagine situations where the current user is not root yet it can write to the destination directory just fine.

I'm doing that all the time, meson won't use pkexec in that case.

> The bug I am reporting is a design bug; build utilities have traditionally never attempted to gain elevated privileges, and it is highly surprising that meson does so.

I would not take traditional build utilities as example, they all sucks, that's why we have meson in the first place... It is surprising only because it's a new thing to lots of people, but it's not unique neither. systemctl command line does it too, I think more and more CLI does it because it's a nicer user experience. The more CLI does it, the less surprising it will become.
> I recently helped debug someone's distro build script using meson install. By accident, DESTDIR was not set. Instead of either visibly trying pkexec or failing with normal permission errors, meson simply crashed because LD_PRELOAD was automatically exported by fakeroot, which the entire distro build script runs under, and hence pkexec could not be executed at all.
> 
> That was a pretty annoying and silly thing to debug. It would have been a whole lot clearer to just get a permission error. :p
"it's a nice user experience, the more CLI tools do it the more people will expect it".

That was never really my argument.

No, it's a bad user experience, I don't want meson to emulate other build tools because other build tools don't do it -- I want meson to not do it, because it's a bad thing to do, and "just for the record everyone else realized it's a bad idea, too".
> "it's a nice user experience, the more CLI tools do it the more people will expect it".
> 
> No, it's a bad user experience, I don't want meson to emulate other build tools because other build tools don't do it -- I want meson to not do it, because it's a bad thing to do, and "just for the record everyone else realized it's a bad idea, too".

Could you please elaborate a bit more about `because it's a bad thing to do` ?

> > I recently helped debug someone's distro build script using meson install. By accident, DESTDIR was not set. Instead of either visibly trying pkexec or failing with normal permission errors, meson simply crashed because LD_PRELOAD was automatically exported by fakeroot, which the entire distro build script runs under, and hence pkexec could not be executed at all.
> > That was a pretty annoying and silly thing to debug. It would have been a whole lot clearer to just get a permission error. :p

That seems a very specific case and easy to fix. We can detect if we are in fakeroot and not use pkexec: https://stackoverflow.com/questions/33446353/bash-check-if-user-is-root
You have taken my objection "this is a fragile pile of 💩 and fails in surprising ways whenever you step out of the narrow-minded box of the polkit developers" and extracted from that, that "hey, we can make this a special case, everything will be fine". :p

The essential problem here is that under a number of circumstances meson decides it needs root permission, and it's wrong because I actually wanted meson to error out with permission errors and I absolutely under no circumstances want it to be successful, I'd rather fix meson.build or the configure options. And meson gives no insight into why it's automatically doing this nonsense.
Also polkit was a horrible choice if anything should be done :p it pops up a GUI window when running cli commands. I'm extremely annoyed at systemctl for the same reason, I assure you.
The current situation might not be perfect, but most people will then just call `doas/sudo ninja install` which is really bad because you can easily end up with files owned by root in your build directory. In this case, there is not much Meson can do (dropping privileges, etc.) because `ninja` is in charge of compiling at this point.

So, the solution here is to use the least privilege principle. The easiest way of achieving this is to only elevate privileges when needed.

Whether polkit is the right tool (I am also not a fan of GUI popups in my CLI), stability, bugs, etc. is a different question.
I think that `ninja install` requiring to create files in the build directory is a bug in Meson or a deficiency of the build definition. Fixing this may be harder than wrapping the "real" install part of `ninja install` into a wrapper that elevates privileges, but IMHO is the correct solution.
> Whether polkit is the right tool (I am also not a fan of GUI popups in my CLI), stability, bugs, etc. is a different question.

Indeed, and that's why I think polkit prompts ***don't solve the problem***.

The current state of affairs:
- meson is broken

The previous state of affairs:
- meson is broken in a completely unrelated way

The "solution" merged doesn't solve anything, it merely shifts the brokenness one step over to the left. And people building stuff on the command line are statistically speaking more likely than *any* other linux users to simply... not have polkit installed at all (but they probably do have sudo or doas).

These people are still getting root owned files.

I guess in the year 2018 I'd object fiercely to #3567 being merged on the grounds "this solves nothing". I still believe it should be reverted, but I do understand it is harder to convince other people to move back from one brokenness to the original brokenness because ***I*** think the original brokenness is less bad.

Inertia, "let's just do nothing if we cannot solve it properly", cuts both ways.
> The current state of affairs:
> 
>     * meson is broken

What's broken? If it's just the fakeroot case, it's easy to fix without throwing the baby with the bathwater.
> And people building stuff on the command line are statistically speaking more likely than _any_ other linux users to simply... not have polkit installed at all

[citation needed]

Not sure who does not have pkexec installed, is there any distro not having it by default? And if you don't have it then it's all good for you, it will just not use it and you'll get your permission denied error.


> >  If sudo is configured to work without password

> Don't do that. And if you do, I don't see how it's meson problem's if you shoot yourself in the feet...

Why shouldn't I do that? The password prompt is just security theater, if a malicious program has user rights it can just run 

```
echo "alias sudo=keyloggedsudo" >> ~/.bashrc 
```
> There is a simple solution to this. Don't elevate privileges. If the user wants root, tell them to use "sudo meson …". This is very easy to implement and it's what every other build system does.
> 
> EDIT: Workaround for all of this: `export PKEXEC_UID=99999`. Meson will now raise a permission error instead of trying to grab elevated privileges.

This was a good work around for me as I was building with meson on an NFS
Just here to chime in that this is wrong and should be removed. The proper way to do this is not prompting for privilege elevation (that's **always wrong** and trains users to get phished) nor `sudo ninja install` (which as noted can give root-owned files in build directory) but performing an unprivileged install into a `DESTDIR` then manually elevating privileges to copy the contents of the staged install to the main filesystem *after confirming it's not writing places you don't want it to*.

> and trains users to get phished

A program with user privileges can run
```
echo "alias sudo=keyloggedsudo" >> ~/.bashrc 
```
So that argument is invalid.
You're missing the point which is about the kind of reaction it trains, not the particular privilege domains involved here. It's training the pattern "something asks for credentials and presents a prompt" as valid, which is how phishing works.

Yeah ok. 
To be fair, phishing is usually browser based and not console based.
> You're missing the point which is about the kind of reaction it trains, not the particular privilege domains involved here. It's training the pattern "something asks for credentials and presents a prompt" as valid, which is how phishing works.

IMHO it's user's problem. If It asks for privilege,  we should respect people's intelligence to be responsible of putting their credentials.
There are better mechanisms (cf. DESTDIR) than asking for privileges in the first place.

Respecting people's intelligence is not the point. You can train perfectly intelligent people to habitually ack away any and all auth-request dialog windows if you annoy them enough with them.

The point is motor memory, unexpected interactions, and anti-patterns (e.g. an install method that behaves differently when started non-interactively).


The point here is to install by default your software (no DESTDIR) on most linux distro dest dir, /usr/local which is a system restricted area. 

So user  needs to grant privilege to install his library (he chose to do it). Train him to use `sudo ninja install` sounds a bit the same as training him to enter the password in pkexec. 

And it avoids to generate files which will be root owned by a rebuild of a modified source file.
@Volker-Weissmann I would also argue that if you have a malicious user program with access to your home directory that you have *far* bigger problems to worry about (like it encrypting or uploading everything it has access to, keylogging your *entire* desktop https://github.com/anko/xkbcat).
> @Volker-Weissmann I would also argue that if you have a malicious user program with access to your home directory that you have _far_ bigger problems to worry about (like it encrypting or uploading everything it has access to, keylogging your _entire_ desktop https://github.com/anko/xkbcat).

Yes, of course, but keylogging everything doesn't mean you could not also keylog sudo.
Even if your data is only readible/writable as root, that won't save you.
> It's training the pattern "something asks for credentials and presents a prompt" as valid, which is how phishing works.

Right, we should stop training people to prepend "sudo" to all commands. Better only request elevated permission only if needed.
I agree, but this concern is already raised in #7345 (without however mentioning the keyword "pkexec", only "polkit").
Workaround: `export PKEXEC_UID=99999`.

Patch:
diff --git a/docs/markdown/Installing.md b/docs/markdown/Installing.md
index a692afe7deea..2d18c178fccd 100644
--- a/docs/markdown/Installing.md
+++ b/docs/markdown/Installing.md
@@ -102,6 +102,22 @@ Telling Meson to run this script at install time is a one-liner.
 The argument is the name of the script file relative to the current
 subdirectory.
 
+## Installing as the superuser
+
+When building as a non-root user, but installing to root-owned locations via
+e.g. `sudo ninja install`, ninja will attempt to rebuild any out of date
+targets as root. This results in various bad behaviors due to build outputs and
+ninja internal files being owned by root.
+
+Running `meson install` is preferred for several reasons. It can rebuild out of
+date targets and then re-invoke itself as root. *(since 1.1.0)* Additionally,
+running `sudo meson install` will drop permissions and rebuild out of date
+targets as the original user, not as root.
+
+*(since 1.1.0)* Re-invoking as root will try to guess the user's preferred method for
+re-running commands as root. The order of precedence is: sudo, doas, pkexec
+(polkit). An elevation tool can be forced by setting `$MESON_ROOT_CMD`.
+
 ## DESTDIR support
 
 Sometimes you need to install to a different directory than the
diff --git a/docs/markdown/snippets/meson_install_drop_privs.md b/docs/markdown/snippets/meson_install_drop_privs.md
new file mode 100644
index 000000000000..e08dfc000535
--- /dev/null
+++ b/docs/markdown/snippets/meson_install_drop_privs.md
@@ -0,0 +1,16 @@
+## `sudo meson install` now drops privileges when rebuilding targets
+
+It is common to install projects using sudo, which should not affect build
+outputs but simply install the results. Unfortunately, since the ninja backend
+updates a state file when run, it's not safe to run ninja as root at all.
+
+It has always been possible to carefully build with:
+
+```
+ninja && sudo meson install --no-rebuild
+```
+
+Meson now tries to be extra safe as a general solution. `sudo meson install`
+will attempt to rebuild, but has learned to run `ninja` as the original
+(pre-sudo or pre-doas) user, ensuring that build outputs are generated/compiled
+as non-root.
diff --git a/docs/markdown/snippets/meson_install_elevate.md b/docs/markdown/snippets/meson_install_elevate.md
new file mode 100644
index 000000000000..2ba92e631a83
--- /dev/null
+++ b/docs/markdown/snippets/meson_install_elevate.md
@@ -0,0 +1,9 @@
+## `meson install` now supports user-preferred root elevation tools
+
+Previously, when installing a project, if any files could not be installed due
+to insufficient permissions the install process was automatically re-run using
+polkit. Now it prompts to ask whether that is desirable, and checks for
+CLI-based tools such as sudo or opendoas or `$MESON_ROOT_CMD`, first.
+
+Meson will no longer attempt privilege elevation at all, when not running
+interactively.
diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py
index 40c2d2d418e3..077823cb7929 100644
--- a/mesonbuild/minstall.py
+++ b/mesonbuild/minstall.py
@@ -18,6 +18,7 @@
 import argparse
 import errno
 import os
+import selectors
 import shlex
 import shutil
 import subprocess
@@ -42,7 +43,7 @@
             ExecutableSerialisation, InstallDataBase, InstallEmptyDir,
             InstallSymlinkData, TargetInstallData
     )
-    from .mesonlib import FileMode
+    from .mesonlib import FileMode, EnvironOrDict
 
     try:
         from typing import Protocol
@@ -556,13 +557,36 @@ def do_install(self, datafilename: str) -> None:
                     self.log('Preserved {} unchanged files, see {} for the full list'
                              .format(self.preserved_file_count, os.path.normpath(self.lf.name)))
         except PermissionError:
-            if shutil.which('pkexec') is not None and 'PKEXEC_UID' not in os.environ and destdir == '':
-                print('Installation failed due to insufficient permissions.')
-                print('Attempting to use polkit to gain elevated privileges...')
-                os.execlp('pkexec', 'pkexec', sys.executable, main_file, *sys.argv[1:],
-                          '-C', os.getcwd())
-            else:
+            if is_windows() or destdir != '' or not os.isatty(sys.stdout.fileno()) or not os.isatty(sys.stderr.fileno()):
+                # can't elevate to root except in an interactive unix environment *and* when not doing a destdir install
                 raise
+            rootcmd = os.environ.get('MESON_ROOT_CMD') or shutil.which('sudo') or shutil.which('doas')
+            pkexec = shutil.which('pkexec')
+            if rootcmd is None and pkexec is not None and 'PKEXEC_UID' not in os.environ:
+                rootcmd = pkexec
+
+            if rootcmd is not None:
+                print('Installation failed due to insufficient permissions.')
+                s = selectors.DefaultSelector()
+                s.register(sys.stdin, selectors.EVENT_READ)
+                ans = None
+                for attempt in range(5):
+                    print(f'Attempt to use {rootcmd} to gain elevated privileges? [y/n] ', end='', flush=True)
+                    if s.select(30):
+                        # we waited on sys.stdin *only*
+                        ans = sys.stdin.readline().rstrip('\n')
+                    else:
+                        print()
+                        break
+                    if ans in {'y', 'n'}:
+                        break
+                else:
+                    if ans is not None:
+                        raise MesonException('Answer not one of [y/n]')
+                if ans == 'y':
+                    os.execlp(rootcmd, rootcmd, sys.executable, main_file, *sys.argv[1:],
+                              '-C', os.getcwd(), '--no-rebuild')
+            raise
 
     def do_strip(self, strip_bin: T.List[str], fname: str, outname: str) -> None:
         self.log(f'Stripping target {fname!r}.')
@@ -743,7 +767,41 @@ def rebuild_all(wd: str) -> bool:
         print("Can't find ninja, can't rebuild test.")
         return False
 
-    ret = subprocess.run(ninja + ['-C', wd]).returncode
+    def drop_privileges() -> T.Tuple[T.Optional[EnvironOrDict], T.Optional[T.Callable[[], None]]]:
+        if not is_windows() and os.geteuid() == 0:
+            import pwd
+            env = os.environ.copy()
+
+            if os.environ.get('SUDO_USER') is not None:
+                orig_user = env.pop('SUDO_USER')
+                orig_uid = env.pop('SUDO_UID', 0)
+                orig_gid = env.pop('SUDO_GID', 0)
+                homedir = pwd.getpwuid(int(orig_uid)).pw_dir
+            elif os.environ.get('DOAS_USER') is not None:
+                orig_user = env.pop('DOAS_USER')
+                pwdata = pwd.getpwnam(orig_user)
+                orig_uid = pwdata.pw_uid
+                orig_gid = pwdata.pw_gid
+                homedir = pwdata.pw_dir
+            else:
+                return None, None
+
+            env['USER'] = orig_user
+            env['HOME'] = homedir
+
+            def wrapped() -> None:
+                print(f'Dropping privileges to {orig_user!r} before running ninja...')
+                if orig_gid is not None:
+                    os.setgid(int(orig_gid))
+                if orig_uid is not None:
+                    os.setuid(int(orig_uid))
+
+            return env, wrapped
+        else:
+            return None, None
+
+    env, preexec_fn = drop_privileges()
+    ret = subprocess.run(ninja + ['-C', wd], env=env, preexec_fn=preexec_fn).returncode
     if ret != 0:
         print(f'Could not rebuild {wd}')
         return False


Test patch: