Folks,
Thanks for your help with this.
I have figured out the problem, though I can't say I completely
understand it.
My EPICS application was not actually directly calling iopl(3) because
iopl(3) requires root priv, and I don't want to run the IOC
application itself as root. Rather I have a separate little program
which is installed with root priv, and that program does iopl(3), then
lowers its priv, then does execv() of the IOC application.
I tried running this root program to execv Till’s test program but
with the call to iopl(3) removed.
On one of my Linux systems this works fine. On another it does not work.
Here is the program that is installed with root priv.
**************************************
[epics@baja ~]$ more startWithIopl3.c
/*
* Open window to all I/O ports and run
* application as non-privileged user.
*
* Install this executable setuid-root.
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/io.h>
int main (int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "Usage: %s executable [args ...]\n", argv[0]);
return 1;
}
/* Open the I/O ports */
if (iopl(3) != 0) {
fprintf(stderr, "Can't open access to I/O ports: %s\n", strerror(errno));
return 2;
}
/* Relinquish super-user status */
setuid(getuid());
/* Execute the application */
argv++;
execv(argv[0], argv);
fprintf(stderr, "Can't execute %s: %s\n", argv[0], strerror(errno));
return 3;
}
**************************************
Here is a version of Till's test program with the call to iopl(3) removed.
**************************************
[epics@baja ~]$ more test_io.c
#include <stdio.h>
#include <sys/io.h>
int main(int argc, char **argv)
{
unsigned char v;
unsigned short p;
if ( argc < 2 || 1 != sscanf(argv[1],"%hi",&p) ) {
fprintf(stderr,"Usage: %s <port>\n",argv[0]);
return 1;
}
// if ( iopl(3) ) {
// perror("iopl");
// return 1;
// }
v = inb(p);
printf("0x%02x\n",v);
return 0;
}
**************************************
Here is the information on a Linux system for which this works:
corvette:~/scratch>more /proc/version
Linux version 2.6.27.21-78.2.41.fc9.i686 (mockbuild@) (gcc version
4.3.0 20080428 (Red Hat 4.3.0-8) (GCC) ) #1 SMP Mon Mar 23 23:45:58
EDT 2009
Here is the info on the file with root privs
corvette:~/scratch>ls -l startWithIopl3
-rwsrwsr-x 1 root epics 5782 Jul 10 10:00 startWithIopl3
Here is what happens when I run the program:
corvette:~/scratch>./startWithIopl3 ./test_io 0x378
0xff
So it works fine.
Here is the information on a Linux system for which the identical
program and setup fails:
[epics@baja ~]$ more /proc/version
Linux version 2.6.26.8-57.fc8 ([email protected])
(gcc version 4.1.2 20070925 (Red Hat 4.1.2-33)) #1 SMP Thu Dec 18
18:59:49 EST
2008
Here is the information on the file:
[epics@baja ~]$ ls -l ./startWithIopl3
-rwsrwsr-x 1 root epics 7826 2009-07-10 09:58 ./startWithIopl3
Here is what happens when I try to run the program:
[epics@baja ~]$ ./startWithIopl3 ./test_io 0x378
Segmentation fault (core dumped)
So it fails. The seg fault happens because the I/O is being done
without first calling iopl(3). If I modify the test_io.c program to
implement the call to iopl(3) then it works if I run it as root.
So on some systems executing iopl(3) and then calling execv() allows
I/O port access in the exec'd task, but on some systems it does not.
Any ideas why?
Thanks,
Mark
-----Original Message-----
From: [email protected]
[mailto:[email protected]] On Behalf Of
Mark Rivers
Sent: Thursday, July 09, 2009 3:42 PM
To: Till Straumann
Cc: [email protected]; tech-talk
Subject: Re: [APS Beamline_controls] Access to IO registers from
user-spacein recent Linux versions
Till,
Your program works on my system accessing the EPP port (0x378).
So it must not be a security problem, it must be a problem with my code.
Thanks very much for sending the code.
Mark
-----Original Message-----
From: Till Straumann [mailto:[email protected]]
Sent: Thursday, July 09, 2009 2:06 PM
To: Mark Rivers
Cc: tech-talk; [email protected]
Subject: Re: Access to IO registers from user-space in recent Linux
versions
The iopl(3) followed by 'in' works fine for me (both, when compiled -m32
or without)
till@tillbook:~/tmp$ uname -a
Linux tillbook 2.6.28-13-generic #45-Ubuntu SMP Tue Jun 30 22:12:12 UTC
2009 x86_64 GNU/Linux
#include <stdio.h>
#include <sys/io.h>
int main(int argc, char **argv)
{
unsigned char v;
unsigned short p;
if ( argc < 2 || 1 != sscanf(argv[1],"%hi",&p) ) {
fprintf(stderr,"Usage: %s <port>\n",argv[0]);
return 1;
}
if ( iopl(3) ) {
perror("iopl");
return 1;
}
asm volatile ( "inb %1,%0" : "=a" (v) : "d"(p));
printf("0x%02x\n",v);
return 0;
}
-- Till
Mark Rivers wrote:
>
> Folks,
>
>
>
> I have an EPICS application that directly accesses the parallel port
> (EPP) registers from user space on Linux. This is to communicate with
> an XIA Saturn spectroscopy module.
>
>
>
> In order versions of Linux this worked fine if I ran the application
> as root, or by calling iopl(3) as root before exec-ing the EPICS
> application.
>
>
>
> I am now trying to run this under a recent Linux (Redhat Fedora)
version
>
>
>
> baja:~>more /proc/version
>
> Linux version 2.6.26.8-57.fc8 ([email protected])
>
> (gcc version 4.1.2 20070925 (Red Hat 4.1.2-33))
>
> #1 SMP Thu Dec 18 18:59:49 EST 2008
>
>
>
> The EPICS IOC now crashes with a segmentation fault when trying to
> access the EPP port, even when running as root, and the following
> entry appears in /var/log/messages
>
>
>
> Jul 9 11:43:44 baja kernel: dxpApp[27837] general protection
> ip:80a90a6 sp:ff8ea8ac error:0 in dxpApp[8048000+1f7000]
>
>
>
> Does anyone know what one needs to do in recent Linux versions to get
> access to the IO registers from user-space?
>
>
>
> Thanks,
>
> Mark
>
>
>
>
>
_______________________________________________
APS Beamline_controls mailing list
post: [email protected]
request: [email protected]
http://www.aps.anl.gov/mailman/listinfo/beamline_controls