/dev/mem user access


7 posts
by Scratch » Fri Nov 09, 2012 5:48 pm
Hi all,

I have a project that requires access to /dev/mem in order to change GPIOs, at the moment I have been using root to do this but this is far from ideal. I have tried changing the permissions for /dev/mem to rw- for the kmem group and then adding my user to that group, not only does this not work, I have read that this is bad practice as, if it were to succeed, this effectively gives the user root access.

My question is; how would this be done properly, enabling me to mmap a section of /dev/mem (as in the first example here: http://elinux.org/RPi_Low-level_peripherals) as a user.

Thanks in advance,

S
Posts: 13
Joined: Sun Oct 07, 2012 2:40 am
by nroff-man » Fri Nov 09, 2012 6:46 pm
hi

you can make your binary setuid root else use sudo.

if you use the former then you may do it like this:

chown 0:0 mybin
chmod u+s mybin

after you open /dev/mem you may then setuid(getuid())
to continue running as the user.

if you prefer sudo, then you could create a shell alias
Eg. alias mybin='sudo /usr/local/bin/mybin'

bye
User avatar
Posts: 23
Joined: Mon Jul 30, 2012 7:31 pm
Location: /usr/bin
by Scratch » Fri Nov 09, 2012 7:05 pm
thanks very much,

The setuid option seems appealing, its odd (and annoying) how there doesn't seem to be any way of controlling the GPIOs as a user...

thanks again!
Posts: 13
Joined: Sun Oct 07, 2012 2:40 am
by Wisar » Sat Nov 17, 2012 6:03 am
Is there a third option of granting needed rights to /dev/mem or is this not possible? I have tried and not succeeded but suspect that I am doing something wrong.

I agree that it seems strange that you have to be root to access GPIO.

Will
Posts: 58
Joined: Tue Sep 25, 2012 6:33 am
Location: Temple near Marlow, England
by jojopi » Sat Nov 17, 2012 10:10 am
Wisar wrote:Is there a third option of granting needed rights to /dev/mem or is this not possible? I have tried and not succeeded but suspect that I am doing something wrong.
To open /dev/mem you need both regular access permissions on the device file and the security capability CAP_SYS_RAWIO, or to be root. There is no getting around this, because full access to memory allows a lot more than just GPIO. It has huge security implications.

The best approach is to start setuid (or setcap) and then drop privileges after initial setup, as suggested above. If you drop privileges, mmap only the GPIO registers you need, and close /dev/mem, then you will not be able to reopen or mmap more later, so the security risks are minimized.

(If you are happy to use the /sys/class/gpio kernel interface then it is possible to change the permissions on those files so that they are accessible to non-root users.)
User avatar
Posts: 2929
Joined: Tue Oct 11, 2011 8:38 pm
by govind_atcall » Wed Jan 08, 2014 5:28 pm
I tried explicitly setting CAP_SYS_RAWIO before calling opening dev/mem.
For me setcap is failing due to permission.Any suggestion?

int android_set_aid_and_cap()
{
struct __user_cap_header_struct header = {0};
struct __user_cap_data_struct cap = {0};

ALOGD("%s: pid %d uid %d gid %d", __func__, getpid(), getuid(), getgid());

header.version = _LINUX_CAPABILITY_VERSION;
header.pid = getpid();
if (capget(&header, &cap) < 0)
ALOGE("%s: capget(): %s", __func__, strerror(errno));




ALOGD("%s: Cap data 0x%x, 0x%x, 0x%x\n", __func__, cap.effective,
cap.permitted, cap.inheritable);

prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);

header.version = _LINUX_CAPABILITY_VERSION;
header.pid = 0;

cap.effective = cap.permitted = cap.inheritable =
1 << CAP_NET_RAW |
1 << CAP_NET_ADMIN |
1 << CAP_NET_BIND_SERVICE |
1 << CAP_SYS_RAWIO |
1 << CAP_SYS_NICE |
1 << CAP_SETGID;

if (capset(&header, &cap)) {
ALOGE("%s: capset(): %s", __func__, strerror(errno));
return 0;
}

ALOGD("%s: capset(): Success", __func__);
return 1;
}
Posts: 1
Joined: Wed Jan 08, 2014 5:18 pm
by jojopi » Wed Jan 08, 2014 11:46 pm
You can only manipulate or drop capabilities you already have, or reinstate those that are still in your permitted set. Most non-root programs start with no capabilities permitted. To permit and effect a capability for a binary, install package "libcap2-bin", then run:
Code: Select all
setcap cap_sys_rawio+ep BINARY
Now the program starts with the capability enabled; you can open /dev/mem (subject to access permissions), and then drop the capability. However, in this case where we need very powerful capabilities, but only for a single system call, I think it makes more sense to make the binary setuid root as nroff-man suggested above. The code to drop root privileges is a lot simpler than the code to drop capabilities:
Code: Select all
  if (setuid(getuid()) < 0) _exit(1);
You can drop privileges immediately after the open. You should also close /dev/mem as soon as you have mmaped the registers you need.
User avatar
Posts: 2929
Joined: Tue Oct 11, 2011 8:38 pm