Hi,
On 2/8/21 11:41, aitor wrote:
> On 2/8/21 0:44, aitor wrote:
>> Better said, the suid binary can check whether or not the gui has
>> handled the signal as expected because
>> the default behavior of SIGUSR1 (User defined signal 1) is to
>> terminate the process. See the table at the
>> end of the link:
>>
>> https://en.wikipedia.org/wiki/Signal_(IPC)#POSIX_signals
>> <https://en.wikipedia.org/wiki/Signal_(IPC)#POSIX_signals>
>>
>> I.e., when such a intruder is acting the
>> PSTAT_BINARY="SOMEWHERE_DEFINED_NAME" with process ID="PID"
>> no longer exists.
>
> Here you are the code:
>
> https://www.gnuinos.org/suid/ <https://www.gnuinos.org/suid/>
>
>
> ** HOWTO: **
>
> 1) Install Jude Nelson's libpstat:
>
> $ git clone https://github.com/jcnelson/libpstat.git
> $ cd libpstat
> $ make OS=LINUX
> $ sudo make install PREFIX=/ INCLUDE_PREFIX=/usr
>
>
> 2) Open an empty directory and download the files:
>
> $ wget https://www.gnuinos.org/suid/Makefile
> $ wget https://www.gnuinos.org/suid/gui.c
> $ wget https://www.gnuinos.org/suid/suid.c
> $ wget https://www.gnuinos.org/suid/intruder.c
>
>
> 3) Install libgtk-3-dev:
>
> $ sudo apt-get install libgtk-3-dev
>
>
> 4) Build the files:
>
> $ make
>
>
> 5) Run the GUI in the command line and click on the button several times:
>
> $ ./gui
>
> You'll get:
>
> From GUI: Received a 10 (SIGUSR1) signal sent from the suid
> From SUID: Ok, go on!
>
>
> 6) Open a new tab in the command line and run the intruder (the GUI
> remains running):
>
> $ ./intruder
>
> You'll get:
>
> Foreign PID to use: 4301
> From SUID: Stop, you're an intruder!
>
> If you have a look at the code of both programs, they're trying to do
> the same (using the intruder a foreign pid).
> Keep in mind that, for our testing purposes, all the binaries must be
> located in the same directory, since
> we're using:
>
> key_t key = ftok(".", 's');
>
> to access the same shared memory segment.
>
> Cheers,
>
> Aitor.
>
There is a better way to do all this because it's possible to enquery
the sender of the socket thanks to getsockopt(),
doing something like this:
pid_t pid;
socklen_t pid_size = sizeof(pid);
rc = getsockopt( df, SOCK_STREAM, SO_PEERCRED, &pid, &pid_size );
if (rc == -1) {
perror("getsockopt");
return -1;
}
printf("client pid=%d\n", pid);
where fd is the file descriptor tied to the unix socket.
Once we know the pid of the process, libpstat will give us the fullpath
to the binary runin the process,
checking afterwards whether or not it's included in the *white* list of
allowed applications.
On the other hand, as simple-netaid is actually daemonized, it's
possible to run all the stuff requiring root
permissions though the service, so i decided to remove the suid binary
providing to the shared library
the CAP_KILL linux capability instead [*], which will allow us to send
signals to the daemon without the requirement of
root permissions. Yes, to the shared library! Because doing this way, we
don't need to give capabilities to each
application depending on it... [**]But i'll explain shortly this point
in another thread headlined: "Hopman,
Simple-netaid and Linux capabilities".
Cheers,
Aitor.
_Note 1_: giving suid permissions to an executable shared library
doesn't take effect (and it wouldn't be recommended),
but it's possible to provide them linux capabilites.
_Note 2_: keep in mind that the shared library sends the signal to the
daemon, and then the daemon communicates with
the running process though the socket filtering possible intruders in
the client side (the shared library cannot make use
of libpstat beforesending the signal to the daemon because it would
require root permissions).
_Note 3_: the daemon uses select() waiting for netlink events, and it's
possible to add more and more file descriptors
to the poll via FD_SET(), keeping this way the daemon looking forward
client sockets to communicate with, but i prefer to
do things the otherway around: the running process sends a signal to the
daemon thanks the capability of the shared
library sendingafterwards therequired arguments though the server
socket, and waiting to be listened by the client.
To finish with, at this point i must admit that i've never have had
clear which is the server and which the client
(because i've seen everything!), but i hope you understand me :)
_Note 4_: i've done a lot of improvements in the daemon (snetaid), but i
still didn't push them to gitea. I'll let you know.
[*] Look at the line nº 82 in the Makefile.am:
https://gitea.devuan.dev/aitor_czr/libnetaid/src/branch/master/src/Makefile.am
<
https://gitea.devuan.dev/aitor_czr/libnetaid/src/branch/master/src/Makefile.am>
[**] Now the shared library is executable:
https://gitea.devuan.dev/aitor_czr/libnetaid/src/branch/master/src/entry.c
<
https://gitea.devuan.dev/aitor_czr/libnetaid/src/branch/master/src/entry.c>