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 ...
- 01-22-2009 #1Just 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
- 01-22-2009 #2
Try running the program as the root user...Hope this helps Gerard4143
Welcome to the forums
- 01-22-2009 #3Just 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
- 01-22-2009 #4
O.K. try investigating setuid()/seteuid() functions
- 01-22-2009 #5Just 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
- 01-22-2009 #6
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
- 01-22-2009 #7
Also I chmod 4755 the executable
- 01-23-2009 #8Just 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
- 01-23-2009 #9
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
asmcode.sCode: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
test.cCode:///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
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); }
- 01-23-2009 #10Just 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);
}


Reply With Quote