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
Re: /dev/mem user access
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
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
Re: /dev/mem user access
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!
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!
Re: /dev/mem user access
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
I agree that it seems strange that you have to be root to access GPIO.
Will
Re: /dev/mem user access
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.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.
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.)
-
- Posts: 1
- Joined: Wed Jan 08, 2014 5:18 pm
Re: /dev/mem user access
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;
}
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;
}
Re: /dev/mem user access
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:
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:
You can drop privileges immediately after the open. You should also close /dev/mem as soon as you have mmaped the registers you need.
Code: Select all
setcap cap_sys_rawio+ep BINARY
Code: Select all
if (setuid(getuid()) < 0) _exit(1);