On 11.10.2013 19:30, Schaufler, Casey wrote:

Dominique and I discussed the underlying problem in some detail
and believe that we have a cleaner solution.

Nobody has yet explained why launcher needs to be somehow privileged and why it's not just a service part of a normal user session?

I'm not advocating for SO_PEERCRED & /proc/PID usage, but it can be made fairly proper. I have made a small demo client/server pair (attached) that should be quite OK for dealing with this combination for whatever use.

I think I will also attempt to fix kernel regarding the "feature" I found (as commented in the sources).


        - Jussi

/* small test/example client for SO_PEERCRED use
 * author: Jussi Laako <[email protected]>
 */


#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>


int main (int argc, char *argv[])
{
        int nw = 0;
        int fd;
        struct sockaddr_un sun;
        char msg[8];
        
        if (argc > 1)
                nw = 1;

        fd = socket(AF_LOCAL, SOCK_STREAM, 0);
        if (fd < 0)
                return 1;
        sun.sun_family = AF_LOCAL;
        strcpy(sun.sun_path, "/tmp/peercred-test");
        if (connect(fd, (struct sockaddr *) &sun, sizeof(sun)) < 0)
                return 1;
        strcpy(msg, "YooHoo");
        puts(msg);
        if (send(fd, msg, sizeof(msg), 0) <= 0)
                return 2;
        if (nw)
        {
                close(fd);
                return 0;
        }
        if (recv(fd, msg, sizeof(msg), MSG_WAITALL) <= 0)
                return 2;
        msg[7] = '\0';
        puts(msg);
        close(fd);

        return 0;
}

/* small test/example server for SO_PEERCRED use
 * author: Jussi Laako <[email protected]>
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>


int main (int argc, char *argv[])
{
        int lfd, cfd;
        struct sockaddr_un sun;
        char msg[8];
        struct ucred crd;
        socklen_t optsz = sizeof(crd);
        char pidf[_POSIX_PATH_MAX + 1];
        char lnkf[_POSIX_PATH_MAX + 1];

        /* we get same info in other way */
        signal(SIGPIPE, SIG_IGN);

        lfd = socket(AF_LOCAL, SOCK_STREAM, 0);
        if (lfd < 0)
                return 1;
        sun.sun_family = AF_LOCAL;
        strcpy(sun.sun_path, "/tmp/peercred-test");
        unlink(sun.sun_path);
        if (bind(lfd, (struct sockaddr *) &sun, sizeof(sun)) < 0)
                return 1;
        if (listen(lfd, 2) < 0)
                return 1;
        while ((cfd = accept(lfd, NULL, NULL)) >= 0)
        {
                while (recv(cfd, msg, sizeof(msg), MSG_WAITALL) > 0)
                {
                        if (getsockopt(cfd, SOL_SOCKET, SO_PEERCRED,
                                &crd, &optsz))
                                break;
                        printf("pid=%d uid=%d gid=%d\n",
                                crd.pid, crd.uid, crd.gid);
                        /* give other end chance to exit */
                        sleep(1);
                        /* dereference peer binary */
                        snprintf(pidf, _POSIX_PATH_MAX,
                                "/proc/%d/exe", crd.pid);
                        memset(lnkf, 0x00, sizeof(lnkf));
                        if (readlink(pidf, lnkf, _POSIX_PATH_MAX) <= 0)
                                break;
                        printf("\texe=%s\n", lnkf);
                        /* this should probably fail if the peer doesn't
                         * exist anymore, however it doesn't */
                        /*if (getsockopt(cfd, SOL_SOCKET, SO_PEERCRED,
                                &crd, &optsz))
                                break;
                        printf("\tpid=%d uid=%d gid=%d\n",
                                crd.pid, crd.uid, crd.gid);*/
                        /* probe if the peer is still there */
                        if (send(cfd, NULL, 0, 0) < 0)
                        {
                                if (errno == EPIPE)
                                        puts("\tpeer has gone away");
                                else
                                        printf("\terror: %s\n",
                                                strerror(errno));
                        }
                        /* send reply */
                        strcpy(msg, "2U2");
                        if (send(cfd, msg, sizeof(msg), 0) < 0)
                                break;
                }
                close(cfd);
        }
        close(lfd);
        unlink(sun.sun_path);

        return 0;
}

_______________________________________________
Dev mailing list
[email protected]
https://lists.tizen.org/listinfo/dev

Reply via email to