Recent

Author Topic: self elevation in linux  (Read 3300 times)

jw

  • Full Member
  • ***
  • Posts: 126
self elevation in linux
« on: December 01, 2020, 04:19:36 am »
I'm accessing serial ports in linux, which means the program needs to run as root, or I gotta know if the user has rights to use tty, else synaser will try, but the program won't crash or anything, it just won't communicate...

As such, with gksudo now gone etc,  here's my code to self elevate, which doesn't work and I don't know why....  I have found that it's extremely hard to visualize what the command line is going to look like in order to figure out why things fail in both linux and windows.  I wish it was as easy as it looks in the memo.

Code: Pascal  [Select][+][-]
  1. if FpGetuid <> 0 then
  2.      begin
  3.  
  4.           password := PasswordBox('Attention', 'Access to serial ports requires the right permissions.' + #10#13 + 'With the wrong permissions the program looks like it''s working, but actually does nothing.' + #10#13 + 'If you are sure you have tty permissions then leave the password blank.' + #10#13 + 'Else enter the root password.');
  5.           if password <> '' then
  6.           begin
  7.           // memo1.append('echo ' + password + ' | sudo -S "' + paramstr(0) + '"');
  8.  
  9.           AProcess := TProcess.Create(nil);
  10.           //AProcess.Executable:= 'echo';
  11.           //AProcess.Parameters.Add(' ' + password + ' | sudo -S "' + paramstr(0) + '"');
  12.  
  13.           AProcess.CommandLine:= 'echo ' + password + ' | sudo -S "' + paramstr(0) + '"';
  14.           AProcess.Options := AProcess.Options + [poWaitOnExit];
  15.           AProcess.Execute;
  16.           AProcess.Free;
  17.           halt(1);
  18.  
  19.           end;
  20.  
  21.      end;          
  22.  
  23.  
  24.  

BlueIcaro

  • Hero Member
  • *****
  • Posts: 792
    • Blog personal
Re: self elevation in linux
« Reply #1 on: December 01, 2020, 07:59:18 am »
I'm accessing serial ports in linux, which means the program needs to run as root, or I gotta know if the user has rights to use tty, else synaser will try, but the program won't crash or anything, it just won't communicate...

As such, with gksudo now gone etc,  here's my code to self elevate, which doesn't work and I don't know why....  I have found that it's extremely hard to visualize what the command line is going to look like in order to figure out why things fail in both linux and windows.  I wish it was as easy as it looks in the memo.

Code: Pascal  [Select][+][-]
  1. if FpGetuid <> 0 then
  2.      begin
  3.  
  4.           password := PasswordBox('Attention', 'Access to serial ports requires the right permissions.' + #10#13 + 'With the wrong permissions the program looks like it''s working, but actually does nothing.' + #10#13 + 'If you are sure you have tty permissions then leave the password blank.' + #10#13 + 'Else enter the root password.');
  5.           if password <> '' then
  6.           begin
  7.           // memo1.append('echo ' + password + ' | sudo -S "' + paramstr(0) + '"');
  8.  
  9.           AProcess := TProcess.Create(nil);
  10.           //AProcess.Executable:= 'echo';
  11.           //AProcess.Parameters.Add(' ' + password + ' | sudo -S "' + paramstr(0) + '"');
  12.  
  13.           AProcess.CommandLine:= 'echo ' + password + ' | sudo -S "' + paramstr(0) + '"';
  14.           AProcess.Options := AProcess.Options + [poWaitOnExit];
  15.           AProcess.Execute;
  16.           AProcess.Free;
  17.           halt(1);
  18.  
  19.           end;
  20.  
  21.      end;          
  22.  
  23.  
  24.  
I think you can give permision to your user, to user serial port.

Quote
sudo chown username  /dev/ttyACM0

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: self elevation in linux
« Reply #2 on: December 01, 2020, 08:37:34 am »
As for your code, it doesn't work because:
  • echo is a shell command, not a program you can run; and
  • it's the shell who allows redirections (e.g. using the "pipe");
which means your command-line goes to never-never land :)

Instead, try:
Code: Pascal  [Select][+][-]
  1. AProcess.CommandLine:= 'bash echo ' + password + ' | sudo -S "' + paramstr(0) + '"';
though note that CommandLine is deprecated; instead you should be using the properties Executable and Parameters.

HTH!
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: self elevation in linux
« Reply #3 on: December 01, 2020, 10:13:12 am »
I'm accessing serial ports in linux, which means the program needs to run as root

It most certainly does not. It means that you need to identify whether the serial port is owned by a specific group such as (on Debian) dialout, and make sure that the user as which you are running is a member of that group.

If a hotplugged serial port is not owned by dialout, then fix your udev rules.

For anything more than that, you use POSIX capabilities.

You might have problems debugging a program using POSIX capabilities from the IDE, in which case you run it as root using gdbserver... there's one or two odd issues that give problems relating to e.g. stuff in the /sys tree but nothing that would affect ordinary programs.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: self elevation in linux
« Reply #4 on: December 01, 2020, 10:15:15 am »
  • echo is a shell command, not a program you can run; and

Careful there. It's one of a number of commands which exist as both shell intrinsics and binaries on disc, so can be confusing.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: self elevation in linux
« Reply #5 on: December 01, 2020, 02:10:29 pm »
Careful there. It's one of a number of commands which exist as both shell intrinsics and binaries on disc, so can be confusing.

Yes, you're right, but the shell one (if it exists) usually supersedes the independent one, more so for simple:
Code: Pascal  [Select][+][-]
  1. echo something
lines, without options.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: self elevation in linux
« Reply #6 on: December 01, 2020, 09:30:13 pm »
Careful there. It's one of a number of commands which exist as both shell intrinsics and binaries on disc, so can be confusing.

Yes, you're right, but the shell one (if it exists) usually supersedes the independent one, more so for simple:
Code: Pascal  [Select][+][-]
  1. echo something
lines, without options.

Yes, but the risk is that somebody might do man echo or man time and then puzzle over why reality doesn't conform.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: self elevation in linux
« Reply #7 on: December 02, 2020, 12:11:22 am »
Well, yes ... though reality conforms more times than not since for calling an internal command with unknown (by the shell) options makes it (most of the times) look for an external one.

It's a little confusing at first but thus is the "zen" of *nix :D

Anyway (and yes, I know you know; just to clarify for future generations and get back to on-topic ;)) the OP's "CommandLine" clearly needs the shell (or some more complex thing) because how sudo -S (in his command) works.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

jw

  • Full Member
  • ***
  • Posts: 126
Re: self elevation in linux
« Reply #8 on: December 02, 2020, 03:09:15 am »
Yip, after I posted and retired to bed I realized that bash was doing the piping so I leaned/dreamed very heavily towards exactly what Lucamar posted....

Code: Pascal  [Select][+][-]
  1. AProcess.CommandLine:= 'bash echo ' + password + ' | sudo -S "' + paramstr(0) + '"';
  2.  

Unfortunately that still fails with no a clue as to why?  It's Linux Mint 19.3 Tricia and bash is the default shell, yet perhaps the path is not there?  How would I know?   

Even this still fails silently!
Code: Pascal  [Select][+][-]
  1. AProcess.CommandLine:= '/bin/bash echo ' + password + ' | sudo -S "' + paramstr(0) + '"';

As I said, it's very hard to understand what goes wrong with tprocess without it telling me something like, "Hey you, I couldn't find that bash thing you were looking for."  Though I should probably just start piping the shelled data back to the tmemo to try to find out what may be happening.

Yes I should be using the properties Executable and Parameters, but as per the commented memo.append line, the tprocess.commandline resembles that tmemo.append syntax exactly, thus eliminating a stray space, or some such anomaly, that has ruined many of my past shell attempts.  Thus, with a quick cut and past from a visual text representation of tmemo that works when cut and pasted into a bash prompt it's an easy thing to do.  So again how does bash echo ' + password + ' | sudo -S "' + paramstr(0) + '" not work???

As far as the philosophy of linux and it's permissions, there's no point in arguing any of that especially when folks find it necessary to criticize an entire premise based on a single portion of an extreamly mal-constructed sentence designed to convey the exact nature of the Linux beast..   And so, as MarkMLI explained and explained and explained, thereby again proving why such a user unfriendly beast should be tamed by a fool such as I for the sake of the world;  the facts are this: Linux and it various flavors have throwbacks to that of electronic typewriters tty's.  When a user sits down at a linux box they are usually allowed to surf the web, yet they're not allowed to access to an antiquated serial interface!!  To to fix that programmatically without administrating every box that my software my hit root is required or the user themselves must be savvy enough on their own, which is quite plainy found written in my message to the user via the password box....

Cyrax

  • Hero Member
  • *****
  • Posts: 836
Re: self elevation in linux
« Reply #9 on: December 02, 2020, 03:39:12 am »
You should learn how polkit works. https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html

I use this script code snippet in my bash script to launch all my GUI or terminal programs at root privileges.
Code: Bash  [Select][+][-]
  1. eval pkexec env DISPLAY=$DISPLAY PATH=$PATH dbus-launch "${1}" "${@:2}"

Yip, after I posted and retired to bed I realized that bash was doing the piping so I leaned/dreamed very heavily towards exactly what Lucamar posted....

Code: Pascal  [Select][+][-]
  1. AProcess.CommandLine:= 'bash echo ' + password + ' | sudo -S "' + paramstr(0) + '"';
  2.  

Unfortunately that still fails with no a clue as to why?  It's Linux Mint 19.3 Tricia and bash is the default shell, yet perhaps the path is not there?  How would I know?   

Even this still fails silently!
Code: Pascal  [Select][+][-]
  1. AProcess.CommandLine:= '/bin/bash echo ' + password + ' | sudo -S "' + paramstr(0) + '"';

As I said, it's very hard to understand what goes wrong with tprocess without it telling me something like, "Hey you, I couldn't find that bash thing you were looking for."  Though I should probably just start piping the shelled data back to the tmemo to try to find out what may be happening.

Yes I should be using the properties Executable and Parameters, but as per the commented memo.append line, the tprocess.commandline resembles that tmemo.append syntax exactly, thus eliminating a stray space, or some such anomaly, that has ruined many of my past shell attempts.  Thus, with a quick cut and past from a visual text representation of tmemo that works when cut and pasted into a bash prompt it's an easy thing to do.  So again how does bash echo ' + password + ' | sudo -S "' + paramstr(0) + '" not work???

As far as the philosophy of linux and it's permissions, there's no point in arguing any of that especially when folks find it necessary to criticize an entire premise based on a single portion of an extreamly mal-constructed sentence designed to convey the exact nature of the Linux beast..   And so, as MarkMLI explained and explained and explained, thereby again proving why such a user unfriendly beast should be tamed by a fool such as I for the sake of the world;  the facts are this: Linux and it various flavors have throwbacks to that of electronic typewriters tty's.  When a user sits down at a linux box they are usually allowed to surf the web, yet they're not allowed to access to an antiquated serial interface!!  To to fix that programmatically without administrating every box that my software my hit root is required or the user themselves must be savvy enough on their own, which is quite plainy found written in my message to the user via the password box....


You need to feed -c option to bash and make sure that there is no quotation included when passing the program name to sudo -S command.
Code: Pascal  [Select][+][-]
  1. AProcess.CommandLine:= '/bin/bash -c "echo ' + password + ' | sudo -S ' + paramstr(0) + '"';

dbannon

  • Hero Member
  • *****
  • Posts: 2786
    • tomboy-ng, a rewrite of the classic Tomboy
Re: self elevation in linux
« Reply #10 on: December 02, 2020, 04:05:21 am »
Yip, after I posted and retired to bed I realized that bash was doing the piping so I leaned/dreamed very heavily towards exactly what Lucamar posted....

While Lucamar is correct in what he says, there are some policy issues that take (IMHO) precedence.  Firstly, the model of an application asking the user for the root password has some issues-
* Giving an application the root password allows it to do anything. I imagine your app wont run off the rails but can you guarantee that ?  What about if your app is somehow hacked ?  In the *nix world, we have very clear borders between user space and system space to minimize that risk, by running your app, even part of it, in root space, you bypass all those safe guards.
* Because of the above, most experienced *nix users will get very nervous when asked for the root password. There are some apps we know will make that request and we know their history, my guess is you app will not yet be so trusted.  Even if your app is completely safe, we do not want apps 'training' end users to supply root password when asked.
* The user may not even know the root password.

Mark's model is vastly better and its the standard way to do things in the *nix world. You add the (ordinary) user who will run the app to the group that can use the serial port. Just like, its all you need to do. If your app runs amok or is replaced by some malicious one, all it can do is use the serial port. Thats quite a modest risk.

Importantly, thats the tried and tested way to achieve what you are trying to do. I believe you would need a very good reason to look for another way ....

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: self elevation in linux
« Reply #11 on: December 02, 2020, 09:43:37 am »
As far as the philosophy of linux and it's permissions, there's no point in arguing any of that especially when folks find it necessary to criticize an entire premise based on a single portion of an extreamly mal-constructed sentence designed to convey the exact nature of the Linux beast..   And so, as MarkMLI explained and explained and explained, thereby again proving why such a user unfriendly beast should be tamed by a fool such as I for the sake of the world;  the facts are this: Linux and it various flavors have throwbacks to that of electronic typewriters tty's.  When a user sits down at a linux box they are usually allowed to surf the web, yet they're not allowed to access to an antiquated serial interface!!  To to fix that programmatically without administrating every box that my software my hit root is required or the user themselves must be savvy enough on their own, which is quite plainy found written in my message to the user via the password box....

<Shrug> You're doing it wrong. Read the Linux documentation, read the documentation which came with the development board you're using. Most of this was fixed about 20 years ago, when serial ports were moved onto /dev/ttyXXX rather than the older /dev/cuaXXX inherited from UUCP.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: self elevation in linux
« Reply #12 on: December 02, 2020, 03:03:09 pm »
First to your problem, try '/bin/bash -c "echo ... | sudo ..."

But, do you really want to execute your whole program as root? this get's really messy, if all you need is a single stream you could use something like this:
Code: Pascal  [Select][+][-]
  1. AProcess.CommandLine := 'sudo tail -f ' + Filename;
  2. AProcess.Options := AProcess.Options + [poUsePipes];
  3. AProcess.Execute;
  4. // sudo asks for a passwort, so let's supply it with one
  5. AProcess.Input.Write(Password[1], Length(Password));
  6. AProcess.Input.WriteByte(#10); // Newline
  7. AProcess.CloseInput; // tail does not require stdin, if the passwort is wrong, sudo will now terminate with an error code
  8. // TODO: sudo error checking
  9. // From this point onwards use AProcess.Output provides a stream to read from that file
This technique can also be used to read real files not only pseudo files that require root (by using cat instead of tail -f)

If you need a real filedescriptor in the filesystem, then you can use named pipes (fifos), by executing the following:
Code: Pascal  [Select][+][-]
  1. fpMkFifo('temporary.fifo', &600); // from unit BaseUnix
  2. AProcess.CommandLine := 'bash -c "sudo tail -f ' + Filename + ' > temporary.fifo"'
  3. ...
Now you can read from temporary.fifo as if it is the real file, but with the difference that you own the file and tail does the reading as admin.

You of course need to delete the fifo afterwards, using fpUnlink from BaseUnix (probably DeleteFile also works)

This can also all be combined into one command:
Code: Pascal  [Select][+][-]
  1. AProcess.CommandLine := 'bash -c "mkfifo temporary.fifo && sudo tail -f ' + Filename + ' > temporary.fifo; unlink temporary.fifo"'

PS: you probably don't want to use poWaitOnExit in either scenario

PPS: if you don't expect the user to have root rights all the time, providing your own programm that calls tail on the correct file and set the setuid bit on this file as root. This needs to be done only once (on installation of your program) and then this program always runs with root previliges regardless which user calls it

PPPS: sudo might not be installed on all linux systems, just keep that in mind
« Last Edit: December 02, 2020, 03:19:06 pm by Warfley »

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: self elevation in linux
« Reply #13 on: December 02, 2020, 03:19:06 pm »
But, do you really want to execute your whole program as root?

That's one of the key things. Unix doctrine is to give a program as few rights as possible, and the capabilities mechanism was specifically added to make this fine-grained. If the requirements of the program /demand/ that access to a device be granted by a password, then it would be far better to organise it so that this granted a single extra capability (which is removed as soon as the device has been opened) rather than making the whole thing root which /will/ eventually cause problems.

And I'd expect sudo in this context to have -k so that the password isn't cached longer than necessary.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2020
  • Former Delphi 1-7, 10.2 user
Re: self elevation in linux
« Reply #14 on: December 02, 2020, 10:42:30 pm »
But, do you really want to execute your whole program as root?

That's one of the key things. Unix doctrine is to give a program as few rights as possible, and the capabilities mechanism was specifically added to make this fine-grained. If the requirements of the program /demand/ that access to a device be granted by a password, then it would be far better to organise it so that this granted a single extra capability (which is removed as soon as the device has been opened) rather than making the whole thing root which /will/ eventually cause problems.

Spot on. This is also why daemons which need to bind to low ports start as root but then switch to a non-privileged user after accomplishing that. Anything else introduces a serious security issue. Expecting any user to run a user application as root is just so wrong on so many levels, quite apart from the assumption that a normal user has root access.

 

TinyPortal © 2005-2018