4

I am working on a rather complex C++ code which performs the following operation as standard user

fd = open("/dev/port",O_WRONLY);
...
lseek(fd, 0x2E,SEEK_SET);
...
write(fd,&buf,1);

I get a 'Operation not permitted' error on opening the file, despite having chmodded the file.

crwxrwxrwx 1 root kmem 1, 4 Sep 12 14:32 /dev/port

I know of security issues with chmodding /dev/port, but as far as we're concerned the system will run on a closed LAN.


To make it easier, this:

using namespace std;
int main(int argc, char *argv[])
{
  int fd=-1;

  //  fd1=open("/dev/port",O_RDWR|O_NDELAY);
  vector<string> fnames;
  fnames.push_back("/dev/port");
  fnames.push_back("/dev/tty0");

  string fname;


  for(int i=0;i<fnames.size();i++)
    {
      fname = fnames[i];
      fd=open(fname.c_str(),O_RDWR | O_NDELAY);
      if(fd<0)
    {
      cout << fname << " "  << fd << endl;
      cout << fname << " "  << strerror(errno) << endl;
    }
      else
    {
      cout << "Open ok: " << fname << endl;
    }
    }


  return 0;
}

returns this:

me@myPC:~/test$ ./main 
/dev/port -1
/dev/port Operation not permitted
Open ok: /dev/tty0

with these permission rights

me@myPC:~/test$ ll /dev/tty /dev/port 
crw-rw-rw- 1 root kmem 1, 4 Sep 12 14:32 /dev/port
crw-rw-rw- 1 root tty  5, 0 Sep 12 15:51 /dev/tty
malber
  • 1,053
  • 4
  • 16
  • 24
  • 1
    Did you have a question? – mah Sep 12 '12 at 12:57
  • Have you tried to run the program as root user? – ott-- Sep 12 '12 at 13:01
  • 1
    The question is in the title: how could I execute the code as a simple user? I can execute the code as root with no problems, but the rest of the code must be run as a non-root user (file read/write). – malber Sep 12 '12 at 13:02
  • Ok, I should have written "does it work when running as root", followed by setting it to suid or using sudo. – ott-- Sep 12 '12 at 16:17
  • 1
    @malber: Please don't [abuse the question title](http://meta.stackexchange.com/q/145019/163768). The title is for the summary page, but once someone has opened the question, they should not need to work hard to discover what you're asking. Write a self-contained body instead. – Kerrek SB Sep 13 '12 at 14:44
  • Plus, the title isn't actually a question. –  Oct 03 '12 at 10:48

1 Answers1

2

To open /dev/port you need the capability CAP_SYS_RAWIO, in addition to permission to open the file.

drivers/char/mem.c:730

static int open_port(struct inode * inode, struct file * filp)
{
    return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
}

You can either gain this by being root or by setting it for a single executable (similar to set-uid) using setcap.

http://linux.die.net/man/8/setcap

jleahy
  • 16,149
  • 6
  • 47
  • 66
  • It worked. By doing `sudo setcap cap_sys_rawio=ep EXECUTABLE_NAME` I was able to access /dev/port. Would it be possible to extend such privilege to a user rather than to a single executable? – malber Sep 12 '12 at 14:12
  • You can do this by using pam_cap.so, a pam module to grant capabilities for a single user. Check out the last link in my edited answer. I'm checking to see if you can do this without using setcap at all. – jleahy Sep 12 '12 at 14:26
  • No easy solution at the horizon for user-specific capabilities on rawIO, as far as I understood. – malber Sep 12 '12 at 15:00
  • Looks that way. It seems the other thing you could do is set =ei, then use pam_cap.so, but if you're doing that you might as well just set =ep. – jleahy Sep 12 '12 at 15:15
  • Thanks again for the reply, in the end I fixed with the `sudo setcap` and some other calls in an init.d script. Stackoverflow policy prevents me to upvote you (I have less than 15 reputation). I'll fix that as soon as I am wont' be a noob anymore :) – malber Sep 13 '12 at 06:33