Find the answer to your Linux question:
Page 1 of 2 1 2 LastLast
Results 1 to 10 of 16
Hi, I get error 13 (EACCES - Permission denied) when I try to open a serial port with - open("/dev/ttyS0", O_RDWR | ...); What permissions do I need (and how ...
  1. #1
    Just Joined!
    Join Date
    Dec 2008
    Posts
    10

    Error while opening port as user

    Hi,

    I get error 13 (EACCES - Permission denied) when I try to
    open a serial port with -
    open("/dev/ttyS0", O_RDWR | ...);

    What permissions do I need (and how do I acquire them) to open
    a port as a user? I do NOT get the above error when I run the
    program as a super user and can communicate on that port.
    Should something be added to the program so that anybody
    can run it and communicate on the serial port (I don't mean
    file permissions, paths etc. for the executable.)?

    Thank you.

    lu

  2. #2
    Linux Enthusiast gerard4143's Avatar
    Join Date
    Dec 2007
    Location
    Canada, Prince Edward Island
    Posts
    714
    Try running the program as the root user...Hope this helps Gerard4143

    Welcome to the forums

  3. #3
    Just Joined!
    Join Date
    Dec 2008
    Posts
    10
    Executing the program as a root/superuser is not an option. I already know I can do it as a superuser. But the application is to be made available to ordinary users without root/superuser access. I faintly recall that there is a way to run an application with the privileges of the owner of the file/executable (I have done something similar in another POSIX compliant OS some years ago) but my memory fails me... The user does not need to have root/superuser access and the privileges hold only within the context of the application.

    Thank you.

    lu

  4. #4
    Linux Enthusiast gerard4143's Avatar
    Join Date
    Dec 2007
    Location
    Canada, Prince Edward Island
    Posts
    714
    O.K. try investigating setuid()/seteuid() functions

  5. #5
    Just Joined!
    Join Date
    Dec 2008
    Posts
    10
    Tried already.
    Also setgid(), setegid(), setreuid(), setregid() etc.
    with chmod ug+s for the executable.

    Nothing makes a difference. Same error on open().
    Thank you.

    lu

  6. #6
    Linux Enthusiast gerard4143's Avatar
    Join Date
    Dec 2007
    Location
    Canada, Prince Edward Island
    Posts
    714
    Check this web site for an example:

    Hope this Helps

    GNU C Library (libc) Programming Guide - Setuid Program Example

    Note: you should compile the program while logged in as the root user for setuid/seteuid to work

    Also: I wrote a Gnome panel applet that accesses the CPU temp using seteuid() so it does work...I found the above example helped alot

  7. #7
    Linux Enthusiast gerard4143's Avatar
    Join Date
    Dec 2007
    Location
    Canada, Prince Edward Island
    Posts
    714
    Also I chmod 4755 the executable

  8. #8
    Just Joined!
    Join Date
    Dec 2008
    Posts
    10
    I came across the same example on the GNU site and already tried it. It did not work.

    In my test prog. (myapp), I copied that code and tried to open the serial port at various points in main() by calling the following functions in different order, several times, etc.
    - open(/dev/ttyS0,..)
    - do_setuid()
    - undo_setuid()

    The port could not be opened when myapp was run as user.

    With the following broad steps,
    uid_t ruid = getuid();
    uid_t euid = geteuid();

    1). print ruid, euid
    2). change ruid, euid with do/undo_setuid()
    3). re-evaluate and print ruid, euid
    4). try open() at various points



    When I am superuser and run myapp,
    (-rwxr-xr-x ... superuser superuser ... myapp),
    I see -
    1). prints 1000 for both values
    3). prints 1000 for both values
    4). port is opened, no error seen any time


    When I am user and run myapp,
    (-rwxr-xr-x ... superuser superuser ... myapp),
    I see -
    1). prints 1001 for both values
    3). prints 1001 for both values
    4). port is not opened, errno 13 seen every time



    Then as superuser, I do "chmod ug+s myapp", then

    when I am superuser and run myapp
    (-rwsr-sr-x ... superuser superuser ... myapp),
    I see -

    1). prints 1000 for both values
    3). prints 1000 for both values
    4). port is opened, no error seen any time


    when I am user and run myapp
    (-rwsr-sr-x ... superuser superuser ... myapp),
    I see -

    1). prints 1001 for ruid and 1000 for euid
    3). prints 1001 or 1000 based on what I set to what in 2)
    (I tried many combos, including the order in the example)
    4). port is not opened, errno 13 seen every time

    I don't see how the user ever gets the id of the superuser in the example code, so how are the privileges of the user elevated to that of the superuser? I tried changing the uid of the user to be the same as the euid (which is the uid of the superuser) after doing chmod but that did not work either for opening the port (it actually allowed me to change the uid!! when executing as a user).

    I hope that I have explained in sufficient detail and not messed up anything during the cut and paste.

    Thank you.

    lu

  9. #9
    Linux Enthusiast gerard4143's Avatar
    Join Date
    Dec 2007
    Location
    Canada, Prince Edward Island
    Posts
    714
    Here's my CPU temp panel applet code and make file...well a stripped down version i.e. no gnome panel code...its just a console app but it still calls the CPU temp which is privileged...

    Note: this will only work on a 64 bit machine(the assembler routine is 64 bit) and when you compile this program make sure your logged in as the root user...

    Also: This works I just tried it on my machine...Good luck hope this helps...Gerard4143

    makefile

    Code:
    test: asmcode.o test.c
    	gcc -o test test.c asmcode.o
    	chmod 4755 test
    
    asmcode.o: asmcode.s
    	as asmcode.s -o asmcode.o
    asmcode.s

    Code:
    ///will only work on a 64 bit machine
    
    .section .data
    
    .section .bss
    	.lcomm mytemp, 1
    
    .section .text
    	.global myfunc
    	.global mytemp
    myfunc:
    			pushq	%rbp
    			movq	%rsp, %rbp
    
    			movb	$0x0029, %al
    			movw	$0x0295, %dx
    			out	%al, %dx
    			
    
    			movw	$0x0296, %dx
    			inb	%dx, %al
    			movb	%al, mytemp
    
    			movq	%rbp, %rsp
    			popq	%rbp
    			ret
    test.c

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <unistd.h>
    #include <sys/io.h>
    #include <sys/types.h>
    #include <string.h>
    #include <fcntl.h>
    
    extern void myfunc();
    extern unsigned char mytemp;
    
    static uid_t euid, ruid;
         
    /*---------chmod 4755 test------- for this to work!!!!!!*\
    
    /* Restore the effective UID to its original value. */
         
    static void do_setuid (void)
    {
    	int status;
         
    	#ifdef _POSIX_SAVED_IDS
    		status = seteuid (euid);
    	#else
    		status = setreuid (ruid, euid);
    	#endif
    
    	if (status < 0) 
    	{
    		fprintf (stderr, "Couldn't set uid.\n");
    		exit (status);
             }
         }
         
         
    /* Set the effective UID to the real UID. */
         
    static void undo_setuid (void)
    {
    	int status;
         
    	#ifdef _POSIX_SAVED_IDS
    		status = seteuid (ruid);
    	#else
    		status = setreuid (euid, ruid);
    	#endif
           
    	if (status < 0) 
    	{
    		fprintf (stderr, "Couldn't set uid.\n");
    		exit (status);
    	}
         }
    
    
    static void try_it()
    {
    	ruid = getuid ();
    	euid = geteuid ();
    	
    	do_setuid();
    
    	ioperm(0x0295, 2, true);
    	myfunc();
    	
    	char temp[18];
    	char cpu[4];
    	char degree[5];
    
    	cpu[0] = 'C';
    	cpu[1] = 'P';
    	cpu[2] = 'U';
    	cpu[3] = ' ';
    	
    
    	degree[0] = ' ';
    	degree[1] = 0xc2;//the degree symbol
    	degree[2] = 0xb0;//the degree symbol
    	degree[3] = 'C';
    	degree[4] = '\0';
    
    	sprintf(temp, "%s%d%s", cpu, mytemp, degree);
    	fprintf(stdout, "temp->%s\n", temp);
    
    	undo_setuid ();
    }
    
    int main(int argc, char**argv)
    {
    	try_it();
    	exit(EXIT_SUCCESS);
    }

  10. #10
    Just Joined!
    Join Date
    Dec 2008
    Posts
    10
    I am on a 32-bit CPU.

    I copied your test.c into lutest.c and modified try_it() as shown.

    Does not work!!!

    lutest.c is copied verbatim here. Please tell me what you see. The details of what I see are at the top of the file:


    ==================

    /*
    * File: lutest.c
    *
    * executed as follows:
    * (log in as suser in a shell)
    * suser$ gcc -o lutest lutest.c
    * suser$ chmod 4755 lutest
    * suser$ lutest
    * Closing port
    * suser$
    *
    *
    * executed again as follows:
    * (log in as user in another shell)
    * user$ ~suser/lutest
    * Error 13 in open()
    * user$
    */

    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <unistd.h>
    #include <sys/io.h>
    #include <sys/types.h>
    #include <string.h>
    #include <fcntl.h>

    #if 0
    extern void myfunc();
    extern unsigned char mytemp;
    #endif


    static uid_t euid, ruid;

    /*---------chmod 4755 test------- for this to work!!!!!!*\

    /* Restore the effective UID to its original value. */

    static void do_setuid (void)
    {
    int status; #else
    status = setreuid (ruid, euid);
    #endif

    if (status < 0)
    {
    fprintf (stderr, "Couldn't set uid.\n");
    exit (status);
    }
    }


    /* Set the effective UID to the real UID. */

    static void undo_setuid (void)
    {
    int status;

    #ifdef _POSIX_SAVED_IDS
    status = seteuid (ruid);
    #else
    status = setreuid (euid, ruid);
    #endif

    if (status < 0)
    {
    fprintf (stderr, "Couldn't set uid.\n");
    exit (status);
    }
    }


    static void try_it()
    {
    ruid = getuid ();
    euid = geteuid ();

    do_setuid();

    #if 0
    ioperm(0x0295, 2, true);
    myfunc();

    char temp[18];
    char cpu[4];
    char degree[5];

    cpu[0] = 'C';
    cpu[1] = 'P';
    cpu[2] = 'U';
    cpu[3] = ' ';


    degree[0] = ' ';
    degree[1] = 0xc2;//the degree symbol
    degree[2] = 0xb0;//the degree symbol
    degree[3] = 'C';
    degree[4] = '\0';

    sprintf(temp, "%s%d%s", cpu, mytemp, degree);
    fprintf(stdout, "temp->%s\n", temp);
    #else
    int fd = open("/dev/ttyS0", (O_RDWR | O_NOCTTY | O_NONBLOCK));
    if (fd == -1)
    {
    printf("Error %d in open()\n", errno);
    }
    else
    {
    printf("Closing port\n");
    close(fd);
    }

    #endif

    undo_setuid ();
    }

    int main(int argc, char**argv)
    {
    try_it();
    exit(EXIT_SUCCESS);
    }

Page 1 of 2 1 2 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...